Files
b210-k7-fpga/lib/axi/axi_fast_extract_tlast.v
T
Ben Hilburn fbbc991a7d Pushing the bulk of UHD-3.7.0 code.
Original-commit: ff1546f8137f7f92bb250f685561b0c34cc0e053
2014-02-14 12:05:07 -08:00

188 lines
4.7 KiB
Verilog

//
// Ultra fast critical path FIFO.
// Only 2 entrys but no combinatorial feed through paths
//
module axi_fast_extract_tlast
#(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 o_tlast,
output reg o_tvalid,
input o_tready
);
reg [WIDTH:0] data_reg1, data_reg2;
reg [1:0] fifo_state;
localparam EMPTY = 0;
localparam HALF = 1;
localparam FULL = 2;
reg [1:0] extract_state;
localparam IDLE = 0;
localparam EXTRACT1 = 1;
localparam EXTRACT2 = 2;
localparam EXTRACT3 = 3;
always @(posedge clk)
if (reset | clear) begin
fifo_state <= EMPTY;
end else begin
case (fifo_state)
// Nothing in either register.
// Upstream can always push data to us.
// Downstream has nothing to take from us.
EMPTY: begin
if ((extract_state == IDLE) && (i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid) begin
// Embeded escpae code received.
extract_state <= EXTRACT1;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
fifo_state <= EMPTY;
end else if ((extract_state == EXTRACT1) && i_tvalid) begin
// Now work out if its a genuine embeded tlast or emulation.
i_tready <= 1'b1;
o_tvalid <= 1'b0;
fifo_state <= EMPTY;
if (i_tdata[31:0] == 'h1) begin
extract_state <= EXTRACT2;
end else begin
extract_state <= EXTRACT3;
end
end else if ((extract_state == EXTRACT2) && i_tvalid) begin
// Extract tlast.
data_reg1 <= {1'b1,i_tdata};
i_tready <= 1'b1;
o_tvalid <= 1'b1;
fifo_state <= HALF;
extract_state <= IDLE;
end else if (i_tvalid) begin
// Get here both for normal data and for EXTRACT3 emulation data.
data_reg1 <= {1'b0,i_tdata};
fifo_state <= HALF;
extract_state <= IDLE;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end else begin
// Nothing to do.
fifo_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 ((extract_state == IDLE) && (i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid) begin
// Embeded escpae code received.
extract_state <= EXTRACT1;
if (o_tready) begin
// If meanwhile we get read then go empty...
i_tready <= 1'b1;
o_tvalid <= 1'b0;
fifo_state <= EMPTY;
end else begin
// ...else stay half full.
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
end else if ((extract_state == EXTRACT1) && i_tvalid) begin
// Now work out if its a genuine embeded tlast or emulation.
if (i_tdata[31:0] == 'h1) begin
extract_state <= EXTRACT2;
end else begin
extract_state <= EXTRACT3;
end
if (o_tready) begin
// If meanwhile we get read then go empty...
i_tready <= 1'b1;
o_tvalid <= 1'b0;
fifo_state <= EMPTY;
end else begin
// ...else stay half full.
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
end else if ((extract_state == EXTRACT2) && i_tvalid) begin
// Extract tlast.
data_reg1 <= {1'b1,i_tdata};
extract_state <= IDLE;
if (o_tready) begin
// We get read and writen same cycle...
i_tready <= 1'b1;
o_tvalid <= 1'b1;
fifo_state <= HALF;
end else begin
// ...or we get written and go full.
data_reg2 <= data_reg1;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
fifo_state <= FULL;
end
end else if (i_tvalid) begin
// Get here both for normal data and for EXTRACT3 emulation data.
data_reg1 <= {1'b0,i_tdata};
extract_state <= IDLE;
if (o_tready) begin
// We get read and writen same cycle...
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end else begin
// ...or we get written and go full.
data_reg2 <= data_reg1;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
fifo_state <= FULL;
end
end else if (o_tready) begin // if (i_tvalid)
// Only getting read this cycle so go empty
fifo_state <= EMPTY;
i_tready <= 1'b1;
o_tvalid <= 1'b0;
end else begin
// Absolutley nothing happens, everything stays the same.
fifo_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 fifo_state.
// Downstream can always read from us.
FULL: begin
if (o_tready) begin
fifo_state <= HALF;
i_tready <= 1'b1;
o_tvalid <= 1'b1;
end
else begin
fifo_state <= FULL;
i_tready <= 1'b0;
o_tvalid <= 1'b1;
end
end
endcase // case(fifo_state)
end // else: !if(reset | clear)
assign {o_tlast,o_tdata} = (fifo_state == FULL) ? data_reg2 : data_reg1;
endmodule // axi_fast_fifo