1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
//
// Copyright 2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
module periodic_framer #(
parameter SR_FRAME_LEN = 0,
parameter SR_GAP_LEN = 1,
parameter SR_OFFSET = 2,
parameter SR_NUMBER_SYMBOLS_MAX = 3,
parameter SR_NUMBER_SYMBOLS_SHORT = 4,
// Skip a set number of gaps at the beginning. Use 1 to properly frame 802.11 long preamble.
parameter SKIP_GAPS = 1,
parameter WIDTH = 32)
(
input clk, input reset, input clear,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
input [WIDTH-1:0] stream_i_tdata, input stream_i_tlast, input stream_i_tvalid, output stream_i_tready,
output [WIDTH-1:0] stream_o_tdata, output stream_o_tlast, output stream_o_tvalid, input stream_o_tready,
output reg sof, output reg eof);
wire [15:0] frame_len;
wire [15:0] gap_len;
wire [15:0] offset;
wire [15:0] numsymbols_max, numsymbols_thisburst, numsymbols_short;
wire [15:0] burst_len;
wire set_numsymbols;
wire consume;
reg [15:0] counter;
reg [$clog2(SKIP_GAPS):0] skip_cnt;
reg [15:0] numsymbols;
setting_reg #(.my_addr(SR_FRAME_LEN), .width(16)) reg_frame_len (
.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
.out(frame_len), .changed());
setting_reg #(.my_addr(SR_GAP_LEN), .width(16)) reg_gap_len (
.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
.out(gap_len), .changed());
setting_reg #(.my_addr(SR_OFFSET), .width(16)) reg_offset (
.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
.out(offset), .changed());
setting_reg #(.my_addr(SR_NUMBER_SYMBOLS_MAX), .width(16)) reg_max_symbols (
.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
.out(numsymbols_max), .changed());
setting_reg #(.my_addr(SR_NUMBER_SYMBOLS_SHORT), .width(16)) reg_symbols_short (
.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
.out(numsymbols_short), .changed(set_numsymbols));
reg [1:0] state;
localparam ST_WAIT_FOR_TRIG = 2'd0;
localparam ST_DO_OFFSET = 2'd1;
localparam ST_FRAME = 2'd2;
localparam ST_GAP = 2'd3;
reg shorten_burst;
always @(posedge clk) begin
if (reset | clear) begin
shorten_burst <= 1'b0;
end else if (set_numsymbols) begin
shorten_burst <= 1'b1;
end else if(state == ST_WAIT_FOR_TRIG) begin
shorten_burst <= 1'b0;
end
end
assign numsymbols_thisburst = shorten_burst ? numsymbols_short : numsymbols_max;
always @(posedge clk) begin
if (reset | clear) begin
eof <= 1'b0;
sof <= 1'b0;
counter <= 1;
skip_cnt <= 0;
numsymbols <= 16'd1;
state <= ST_WAIT_FOR_TRIG;
end else begin
if (consume) begin
case(state)
ST_WAIT_FOR_TRIG : begin
eof <= 1'b0;
skip_cnt <= 0;
if (stream_i_tlast) begin
counter <= 16'b1;
if (offset == 0) begin
state <= ST_FRAME;
end else begin
state <= ST_DO_OFFSET;
end
end
end
ST_DO_OFFSET : begin
if (counter >= offset) begin
sof <= 1'b1;
counter <= 16'b1;
numsymbols <= 16'd1;
state <= ST_FRAME;
end else begin
counter <= counter + 16'd1;
end
end
ST_FRAME : begin
if (counter >= frame_len) begin
sof <= 1'b0;
counter <= 1;
numsymbols <= numsymbols + 1;
if (numsymbols >= numsymbols_thisburst) begin
eof <= 1'b1;
state <= ST_WAIT_FOR_TRIG;
end else begin
if (skip_cnt < SKIP_GAPS) begin
skip_cnt <= skip_cnt + 1;
state <= ST_FRAME;
end else begin
state <= ST_GAP;
end
end
end else begin
counter <= counter + 16'd1;
end
end
ST_GAP : begin
if (counter >= gap_len) begin
state <= ST_FRAME;
counter <= 1;
end else begin
counter <= counter + 16'd1;
end
end
endcase
end
end
end
assign stream_o_tdata = stream_i_tdata;
assign stream_o_tlast = (state == ST_FRAME) & (counter >= frame_len);
assign stream_o_tvalid = stream_i_tvalid & (state == ST_FRAME);
assign stream_i_tready = consume;
assign consume = stream_i_tvalid & ((state != ST_FRAME) | stream_o_tready);
endmodule // periodic_framer
|