diff options
Diffstat (limited to 'fpga/usrp3/lib/axi/axi_extract_tlast.v')
-rw-r--r-- | fpga/usrp3/lib/axi/axi_extract_tlast.v | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/axi/axi_extract_tlast.v b/fpga/usrp3/lib/axi/axi_extract_tlast.v new file mode 100644 index 000000000..9afef3c35 --- /dev/null +++ b/fpga/usrp3/lib/axi/axi_extract_tlast.v @@ -0,0 +1,147 @@ +// +// Copyright 2014 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// +// AXI stream neds N+1 bits to transmit packets of N bits so that the LAST bit can be represented. +// LAST occurs relatively infrequently and can be synthesized by using an in-band ESC code to generate +// a multi-word sequence to encode it (and the escape character when it appears as data input). +// +// 0x1234567887654321 with last becomes +// 0xDEADBEEFFEEDCAFE 0x0000000000000001 0x1234567887654321 +// +// 0xDEADBEEFFEEDCAFE with last becomes +// 0xDEADBEEFFEEDCAFE 0x0000000000000001 0xDEADBEEFFEEDCAFE +// +// 0xDEADBEEFFEEDCAFE without last becomes +// 0xDEADBEEFFEEDCAFE 0x0000000000000000 0xDEADBEEFFEEDCAFE +// + +module axi_extract_tlast #( + parameter WIDTH=64, + parameter VALIDATE_CHECKSUM=0 +) ( + input clk, + input reset, + input clear, + // + input [WIDTH-1:0] i_tdata, + input i_tvalid, + output reg i_tready, + // + output [WIDTH-1:0] o_tdata, + output reg o_tlast, + output reg o_tvalid, + input o_tready, + // + output reg checksum_error +); + + reg [1:0] state, next_state; + + localparam IDLE = 0; + localparam EXTRACT1 = 1; + localparam EXTRACT2 = 2; + localparam EXTRACT3 = 3; + + assign o_tdata = i_tdata; + + reg checksum_error_pre; + reg [31:0] checksum, old_checksum; + + always @(posedge clk) + if (reset | clear) begin + checksum <= 0; + old_checksum <= 0; + end else if (VALIDATE_CHECKSUM && o_tready && i_tvalid && o_tlast) begin + checksum <= 0; + old_checksum <= 0; + end else if (VALIDATE_CHECKSUM && i_tready && i_tvalid && (state == IDLE)) begin + checksum <= checksum ^ i_tdata[31:0] ^ i_tdata[63:32]; + old_checksum <= checksum; + end + + always @(posedge clk) + checksum_error <= checksum_error_pre; + + always @(posedge clk) + if (reset | clear) begin + state <= IDLE; + end else begin + state <= next_state; + end + + always @(*) begin + checksum_error_pre = 0; + case(state) + // + // Search for Escape sequence "0xDEADBEEFFEEDCAFE" + // If ESC found don't pass data downstream but transition to next state. + // else pass data downstream. + // + IDLE: begin + o_tlast = 1'b0; + if ((i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid) begin + next_state = EXTRACT1; + o_tvalid = 1'b0; + i_tready = 1'b1; + end else begin + next_state = IDLE; + o_tvalid = i_tvalid; + i_tready = o_tready; + end // else: !if((i_tdata == 'hDEADBEEFFEEDCAFE) && i_tvalid) + end // case: IDLE + // + // Look at next data. If it's a 0x1 then o_tlast should be asserted with next data word. + // if it's 0x0 then it signals emulation of the Escape code in the original data stream + // and we should just pass the next data word through unchanged with no o_tlast indication. + // + EXTRACT1: begin + o_tvalid = 1'b0; + i_tready = 1'b1; + o_tlast = 1'b0; + if (i_tvalid) begin + if (i_tdata[31:0] == 'h1) begin + if (VALIDATE_CHECKSUM && (old_checksum != i_tdata[63:32])) + checksum_error_pre = 1'b1; + next_state = EXTRACT2; + end else begin + // We assume emulation and don't look for illegal codes. + next_state = EXTRACT3; + end // else: !if(i_tdata == 'h1) + end else begin // if (i_tvalid) + next_state = EXTRACT1; + end // else: !if(i_tvalid) + end // case: EXTRACT1 + // + // Assert o_tlast with data word. + // + EXTRACT2: begin + o_tvalid = i_tvalid; + i_tready = o_tready; + o_tlast = 1'b1; + if (i_tvalid & o_tready) + next_state = IDLE; + else + next_state = EXTRACT2; + end + // + // Emulation, don't assert o_tlast with dataword. + // + EXTRACT3: begin + o_tvalid = i_tvalid; + i_tready = o_tready; + o_tlast = 1'b0; + if (i_tvalid & o_tready) + next_state = IDLE; + else + next_state = EXTRACT2; + end + endcase // case(state) + end + +endmodule // axi_extract_tlast + +
\ No newline at end of file |