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
|
//
// Copyright 2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
//
// Ultra fast critical path FIFO.
// Only 2 entrys but no combinatorial feed through paths
//
module axi_fast_fifo
#(parameter WIDTH=64)
(
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_tvalid,
input o_tready
);
reg [WIDTH-1:0] data_reg1, data_reg2;
reg [1:0] state;
localparam EMPTY = 0;
localparam HALF = 1;
localparam FULL = 2;
always @(posedge clk)
if (reset | clear) begin
state <= EMPTY;
data_reg1 <= 0;
data_reg2 <= 0;
o_tvalid <= 1'b0;
i_tready <= 1'b0;
end else begin
case (state)
// Nothing in either register.
// Upstream can always push data to us.
// Downstream has nothing to take from us.
EMPTY: begin
if (i_tvalid) begin
data_reg1 <= i_tdata;
state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end else begin
state <= EMPTY;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
end
end
// First Register Full.
// Upstream can always push data to us.
// Downstream can always read from us.
HALF: begin
if (i_tvalid && o_tready) begin
data_reg1 <= i_tdata;
state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end else if (i_tvalid) begin
data_reg1 <= i_tdata;
data_reg2 <= data_reg1;
state <= FULL;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
end else if (o_tready) begin
state <= EMPTY;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
end else begin
state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
end // case: HALF
// Both Registers Full.
// Upstream can not push to us in this state.
// Downstream can always read from us.
FULL: begin
if (o_tready) begin
state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
else begin
state <= FULL;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
end
end
endcase // case(state)
end // else: !if(reset | clear)
assign o_tdata = (state == FULL) ? data_reg2 : data_reg1;
endmodule // axi_fast_fifo
|