aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/rfnoc/periodic_framer.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/periodic_framer.v')
-rw-r--r--fpga/usrp3/lib/rfnoc/periodic_framer.v151
1 files changed, 151 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/periodic_framer.v b/fpga/usrp3/lib/rfnoc/periodic_framer.v
new file mode 100644
index 000000000..3e83bcf8d
--- /dev/null
+++ b/fpga/usrp3/lib/rfnoc/periodic_framer.v
@@ -0,0 +1,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