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
|
//
// Copyright 2015 Ettus Research LLC
//
// Single cycle latency, depth of 2 "Flip flop" with no end to end combinatorial paths on
// AXI control signals (such as i_tready depends on o_tready). Breaking the combinatorial
// paths requires an additional register stage.
//
// Note: Once i_tvalid is asserted, it cannot be deasserted without i_tready having asserted
// indicating i_tdata has been read. This is an AXI stream requirement.
module axi_fifo_flop #(
parameter WIDTH = 32)
(
input clk,
input reset,
input clear,
input [WIDTH-1:0] i_tdata,
input i_tvalid,
output i_tready,
output [WIDTH-1:0] o_tdata,
output o_tvalid,
input o_tready,
output [1:0] space,
output [1:0] occupied);
reg [WIDTH-1:0] i_tdata_pipe, i_tdata_reg;
reg i_tvalid_pipe, i_tvalid_reg;
// Steady state data flow is typically: i_tdata -> i_tdata_reg -> o_tdata
// but can change to: i_tdata -> i_tdata_reg -> i_tdata_pipe -> o_tdata
// depending on i_tvalid / o_tready combinations
always @(posedge clk) begin
if (reset | clear) begin
i_tvalid_reg <= 1'b0;
i_tvalid_pipe <= 1'b0;
i_tdata_reg <= {WIDTH{1'b0}};
i_tdata_pipe <= {WIDTH{1'b0}};
end else begin
// Always accept new data if there is space in the pipeline
if (i_tready) begin
i_tdata_reg <= i_tdata;
i_tvalid_reg <= i_tvalid;
end
if (o_tready) begin
if (i_tready) begin
// Only useful when data flow is i_tdata -> i_tdata_reg -> i_tdata_pipe -> o_tdata
i_tdata_pipe <= i_tdata_reg;
if (i_tvalid_pipe) begin
// Switch from: i_tdata -> i_tdata_reg -> i_tdata_pipe -> o_tdata
// to: i_tdata -> i_tdata_reg -> o_tdata
// will occur if i_tvalid_reg = 0
i_tvalid_pipe <= i_tvalid_reg;
end
// Input is throttled
end else begin
i_tdata_pipe <= i_tdata_reg;
i_tvalid_pipe <= i_tvalid_reg;
i_tvalid_reg <= 1'b0; // Since i_tready = 0, we know we will not get new data this cycle
end
// Output is throttled
end else begin
// Space available in i_tdata_pipe to store i_tdata_reg.
// This is the case where data flow will change
// from: i_tdata -> i_tdata_reg -> o_tdata
// to: i_tdata -> i_tdata_reg -> i_tdata_pipe -> o_tdata
// if i_tvalid_reg = 1
if (~i_tvalid_pipe) begin
i_tvalid_pipe <= i_tvalid_reg;
i_tdata_pipe <= i_tdata_reg;
end
end
end
end
assign i_tready = ~(i_tvalid_reg & i_tvalid_pipe);
assign o_tvalid = i_tvalid_pipe ? 1'b1 : i_tvalid_reg;
assign o_tdata = i_tvalid_pipe ? i_tdata_pipe : i_tdata_reg;
assign occupied = i_tvalid_reg + i_tvalid_pipe;
assign space = 2'd2 - occupied;
endmodule
|