103 lines
2.0 KiB
Verilog
103 lines
2.0 KiB
Verilog
//
|
|
// 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
|