1// 2// Copyright 2014 Ettus Research LLC 3// Copyright 2018 Ettus Research, a National Instruments Company 4// 5// SPDX-License-Identifier: LGPL-3.0-or-later 6// 7// 8// Ultra fast critical path FIFO. 9// Only 2 entrys but no combinatorial feed through paths 10// 11 12 13module axi_fast_extract_tlast 14 #(parameter WIDTH=64) 15 ( 16 input clk, 17 input reset, 18 input clear, 19 // 20 input [WIDTH-1:0] i_tdata, 21 input i_tvalid, 22 output reg i_tready, 23 // 24 output [WIDTH-1:0] o_tdata, 25 output o_tlast, 26 output reg o_tvalid, 27 input o_tready 28 ); 29 30 reg [WIDTH:0] data_reg1, data_reg2; 31 32 reg [1:0] fifo_state; 33 34 localparam EMPTY = 0; 35 localparam HALF = 1; 36 localparam FULL = 2; 37 38 reg [1:0] extract_state; 39 40 localparam IDLE = 0; 41 localparam EXTRACT1 = 1; 42 localparam EXTRACT2 = 2; 43 localparam EXTRACT3 = 3; 44 45 46 always @(posedge clk) 47 if (reset | clear) begin 48 fifo_state <= EMPTY; 49 end else begin 50 case (fifo_state) 51 // Nothing in either register. 52 // Upstream can always push data to us. 53 // Downstream has nothing to take from us. 54 EMPTY: begin 55 if ((extract_state == IDLE) && (i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid) begin 56 // Embeded escpae code received. 57 extract_state <= EXTRACT1; 58 i_tready <= 1'b1; 59 o_tvalid <= 1'b0; 60 fifo_state <= EMPTY; 61 end else if ((extract_state == EXTRACT1) && i_tvalid) begin 62 // Now work out if its a genuine embeded tlast or emulation. 63 i_tready <= 1'b1; 64 o_tvalid <= 1'b0; 65 fifo_state <= EMPTY; 66 if (i_tdata[31:0] == 'h1) begin 67 extract_state <= EXTRACT2; 68 end else begin 69 extract_state <= EXTRACT3; 70 end 71 end else if ((extract_state == EXTRACT2) && i_tvalid) begin 72 // Extract tlast. 73 data_reg1 <= {1'b1,i_tdata}; 74 i_tready <= 1'b1; 75 o_tvalid <= 1'b1; 76 fifo_state <= HALF; 77 extract_state <= IDLE; 78 end else if (i_tvalid) begin 79 // Get here both for normal data and for EXTRACT3 emulation data. 80 data_reg1 <= {1'b0,i_tdata}; 81 fifo_state <= HALF; 82 extract_state <= IDLE; 83 i_tready <= 1'b1; 84 o_tvalid <= 1'b1; 85 end else begin 86 // Nothing to do. 87 fifo_state <= EMPTY; 88 i_tready <= 1'b1; 89 o_tvalid <= 1'b0; 90 end 91 end 92 // First Register Full. 93 // Upstream can always push data to us. 94 // Downstream can always read from us. 95 HALF: begin 96 if ((extract_state == IDLE) && (i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid) begin 97 // Embeded escpae code received. 98 extract_state <= EXTRACT1; 99 if (o_tready) begin 100 // If meanwhile we get read then go empty... 101 i_tready <= 1'b1; 102 o_tvalid <= 1'b0; 103 fifo_state <= EMPTY; 104 end else begin 105 // ...else stay half full. 106 fifo_state <= HALF; 107 i_tready <= 1'b1; 108 o_tvalid <= 1'b1; 109 end 110 end else if ((extract_state == EXTRACT1) && i_tvalid) begin 111 // Now work out if its a genuine embeded tlast or emulation. 112 if (i_tdata[31:0] == 'h1) begin 113 extract_state <= EXTRACT2; 114 end else begin 115 extract_state <= EXTRACT3; 116 end 117 if (o_tready) begin 118 // If meanwhile we get read then go empty... 119 i_tready <= 1'b1; 120 o_tvalid <= 1'b0; 121 fifo_state <= EMPTY; 122 end else begin 123 // ...else stay half full. 124 fifo_state <= HALF; 125 i_tready <= 1'b1; 126 o_tvalid <= 1'b1; 127 end 128 end else if ((extract_state == EXTRACT2) && i_tvalid) begin 129 // Extract tlast. 130 data_reg1 <= {1'b1,i_tdata}; 131 extract_state <= IDLE; 132 if (o_tready) begin 133 // We get read and writen same cycle... 134 i_tready <= 1'b1; 135 o_tvalid <= 1'b1; 136 fifo_state <= HALF; 137 end else begin 138 // ...or we get written and go full. 139 data_reg2 <= data_reg1; 140 i_tready <= 1'b0; 141 o_tvalid <= 1'b1; 142 fifo_state <= FULL; 143 end 144 end else if (i_tvalid) begin 145 // Get here both for normal data and for EXTRACT3 emulation data. 146 data_reg1 <= {1'b0,i_tdata}; 147 extract_state <= IDLE; 148 if (o_tready) begin 149 // We get read and writen same cycle... 150 fifo_state <= HALF; 151 i_tready <= 1'b1; 152 o_tvalid <= 1'b1; 153 end else begin 154 // ...or we get written and go full. 155 data_reg2 <= data_reg1; 156 i_tready <= 1'b0; 157 o_tvalid <= 1'b1; 158 fifo_state <= FULL; 159 end 160 end else if (o_tready) begin // if (i_tvalid) 161 // Only getting read this cycle so go empty 162 fifo_state <= EMPTY; 163 i_tready <= 1'b1; 164 o_tvalid <= 1'b0; 165 end else begin 166 // Absolutley nothing happens, everything stays the same. 167 fifo_state <= HALF; 168 i_tready <= 1'b1; 169 o_tvalid <= 1'b1; 170 end 171 end // case: HALF 172 // Both Registers Full. 173 // Upstream can not push to us in this fifo_state. 174 // Downstream can always read from us. 175 FULL: begin 176 if (o_tready) begin 177 fifo_state <= HALF; 178 i_tready <= 1'b1; 179 o_tvalid <= 1'b1; 180 end 181 else begin 182 fifo_state <= FULL; 183 i_tready <= 1'b0; 184 o_tvalid <= 1'b1; 185 end 186 end 187 endcase // case(fifo_state) 188 end // else: !if(reset | clear) 189 190 assign {o_tlast,o_tdata} = (fifo_state == FULL) ? data_reg2 : data_reg1; 191 192 193endmodule // axi_fast_extract_tlast 194