aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/axi/axi_add_preamble.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/axi/axi_add_preamble.v')
-rw-r--r--fpga/usrp3/lib/axi/axi_add_preamble.v157
1 files changed, 157 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/axi/axi_add_preamble.v b/fpga/usrp3/lib/axi/axi_add_preamble.v
new file mode 100644
index 000000000..a66b4229d
--- /dev/null
+++ b/fpga/usrp3/lib/axi/axi_add_preamble.v
@@ -0,0 +1,157 @@
+//
+// Copyright 2016 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Adds preamble, EOP, and CRC/num_words check
+// <preamble> <packet> <EOP> [control_chksum,word_count,payload_chksum]
+// <preamble> = 64'h9E6774129E677412
+// <EOP> = 64'h2A1D632F2A1D632F
+
+module axi_add_preamble #(
+ parameter WIDTH=64
+) (
+ input clk,
+ input reset,
+ input clear,
+ //
+ input [WIDTH-1:0] i_tdata,
+ input i_tlast,
+ input i_tvalid,
+ output i_tready,
+ //
+ output reg [WIDTH-1:0] o_tdata,
+ output o_tvalid,
+ input o_tready
+);
+
+ function [0:0] cvita_get_has_time;
+ input [63:0] header;
+ cvita_get_has_time = header[61];
+ endfunction
+
+ //States
+ localparam IDLE = 0;
+ localparam PREAMBLE = 1;
+ localparam PASS = 3;
+ localparam EOP = 4;
+ localparam CRC = 5;
+
+ localparam PAYLOAD_WORDCOUNT_WIDTH = 16;
+ localparam PAYLOAD_CHKSUM_WIDTH = 32;
+ localparam CONTROL_CHKSUM_WIDTH = 16;
+
+ reg [2:0] state, next_state;
+
+ reg [PAYLOAD_WORDCOUNT_WIDTH-1:0] word_count;
+ reg [PAYLOAD_WORDCOUNT_WIDTH-1:0] cntrl_length = 16'd2;
+ wire [PAYLOAD_CHKSUM_WIDTH-1:0] payload_chksum;
+ wire [CONTROL_CHKSUM_WIDTH-1:0] control_chksum;
+
+ // Payload LFSR
+ crc_xnor #(.INPUT_WIDTH(WIDTH), .OUTPUT_WIDTH(PAYLOAD_CHKSUM_WIDTH)) payload_chksum_gen (
+ .clk(clk), .rst(word_count<=cntrl_length), .hold(~(i_tready && i_tvalid)),
+ .input_data(i_tdata), .crc_out(payload_chksum)
+ );
+
+ // Control LFSR
+ crc_xnor #(.INPUT_WIDTH(WIDTH), .OUTPUT_WIDTH(CONTROL_CHKSUM_WIDTH)) control_chksum_gen (
+ .clk(clk), .rst(word_count=='d0), .hold(~(i_tready && i_tvalid) || word_count>=cntrl_length),
+ .input_data(i_tdata), .crc_out(control_chksum)
+ );
+
+ //Update control length so control checksum is correct
+ always @(posedge clk) begin
+ if (state == IDLE && i_tvalid)
+ cntrl_length <= cvita_get_has_time(i_tdata) ? 16'd2 : 16'd1;
+ end
+
+ //Note that word_count includes EOP
+ always @(posedge clk) begin
+ if (state == IDLE) begin
+ word_count <= 0;
+ end else if (i_tready && i_tvalid || (o_tready && state == EOP)) begin
+ word_count <= word_count+1;
+ end
+ end
+
+ always @(posedge clk)
+ if (reset | clear) begin
+ state <= IDLE;
+ end else begin
+ state <= next_state;
+ end
+
+ always @(*) begin
+ case(state)
+ IDLE: begin
+ if (i_tvalid) begin
+ next_state = PREAMBLE;
+ end else begin
+ next_state = IDLE;
+ end
+ end
+
+ PREAMBLE: begin
+ if(o_tready) begin
+ next_state = PASS;
+ end else begin
+ next_state = PREAMBLE;
+ end
+ end
+
+ PASS: begin
+ if(i_tready && i_tvalid && i_tlast) begin
+ next_state = EOP;
+ end else begin
+ next_state = PASS;
+ end
+ end
+
+ EOP: begin
+ if(o_tready) begin
+ next_state = CRC;
+ end else begin
+ next_state = EOP;
+ end
+ end
+
+ CRC: begin
+ if(o_tready) begin
+ next_state = IDLE;
+ end else begin
+ next_state = CRC;
+ end
+ end
+
+ default: begin
+ next_state = IDLE;
+ end
+
+ endcase
+ end
+
+ //
+ // Muxes
+ //
+ always @*
+ begin
+ case(state)
+ IDLE: o_tdata = 0;
+ PASS: o_tdata = i_tdata;
+ PREAMBLE: o_tdata = 64'h9E6774129E677412;
+ EOP: o_tdata = 64'h2A1D632F2A1D632F;
+ CRC: o_tdata = {control_chksum,word_count,payload_chksum};
+ default: o_tdata = 0;
+
+ endcase
+ end
+
+ assign o_tvalid = (state == PASS) ? i_tvalid : (state != IDLE);
+ assign i_tready = (state == PASS) ? o_tready : 1'b0;
+
+endmodule
+
+
+