mirror of
https://github.com/alexforencich/verilog-ethernet.git
synced 2025-01-14 06:43:18 +08:00
Add option for output FIFO to improve pipelining and RAM inference for large FIFOs
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
parent
d4cf84ccf0
commit
9c3409f9d7
@ -60,6 +60,9 @@ module axis_async_fifo #
|
||||
parameter USER_WIDTH = 1,
|
||||
// number of RAM pipeline registers
|
||||
parameter RAM_PIPELINE = 1,
|
||||
// use output FIFO
|
||||
// When set, the RAM read enable and pipeline clock enables are removed
|
||||
parameter OUTPUT_FIFO_ENABLE = 0,
|
||||
// Frame FIFO mode - operate on frames instead of cycles
|
||||
// When set, m_axis_tvalid will not be deasserted within a frame
|
||||
// Requires LAST_ENABLE set
|
||||
@ -121,6 +124,8 @@ module axis_async_fifo #
|
||||
|
||||
parameter ADDR_WIDTH = (KEEP_ENABLE && KEEP_WIDTH > 1) ? $clog2(DEPTH/KEEP_WIDTH) : $clog2(DEPTH);
|
||||
|
||||
parameter OUTPUT_FIFO_ADDR_WIDTH = RAM_PIPELINE < 2 ? 3 : $clog2(RAM_PIPELINE*2+7);
|
||||
|
||||
// check configuration
|
||||
initial begin
|
||||
if (FRAME_FIFO && !LAST_ENABLE) begin
|
||||
@ -207,6 +212,7 @@ reg [WIDTH-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [WIDTH-1:0] mem_read_data_reg;
|
||||
reg mem_read_data_valid_reg = 1'b0;
|
||||
|
||||
(* shreg_extract = "no" *)
|
||||
reg [WIDTH-1:0] m_axis_pipe_reg[RAM_PIPELINE+1-1:0];
|
||||
reg [RAM_PIPELINE+1-1:0] m_axis_tvalid_pipe_reg = 0;
|
||||
|
||||
@ -273,14 +279,7 @@ wire [ID_WIDTH-1:0] m_axis_tid_pipe = ID_ENABLE ? m_axis[ID_OFFSET +: ID
|
||||
wire [DEST_WIDTH-1:0] m_axis_tdest_pipe = DEST_ENABLE ? m_axis[DEST_OFFSET +: DEST_WIDTH] : {DEST_WIDTH{1'b0}};
|
||||
wire [USER_WIDTH-1:0] m_axis_tuser_pipe = USER_ENABLE ? (m_terminate_frame_reg ? USER_BAD_FRAME_VALUE : m_axis[USER_OFFSET +: USER_WIDTH]) : {USER_WIDTH{1'b0}};
|
||||
|
||||
assign m_axis_tvalid = m_axis_tvalid_pipe;
|
||||
|
||||
assign m_axis_tdata = m_axis_tdata_pipe;
|
||||
assign m_axis_tkeep = m_axis_tkeep_pipe;
|
||||
assign m_axis_tlast = m_axis_tlast_pipe;
|
||||
assign m_axis_tid = m_axis_tid_pipe;
|
||||
assign m_axis_tdest = m_axis_tdest_pipe;
|
||||
assign m_axis_tuser = m_axis_tuser_pipe;
|
||||
wire pipe_ready;
|
||||
|
||||
assign s_status_overflow = overflow_reg;
|
||||
assign s_status_bad_frame = bad_frame_reg;
|
||||
@ -542,14 +541,14 @@ end
|
||||
integer j;
|
||||
|
||||
always @(posedge m_clk) begin
|
||||
if (m_axis_tready) begin
|
||||
if (OUTPUT_FIFO_ENABLE || m_axis_tready) begin
|
||||
// output ready; invalidate stage
|
||||
m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b0;
|
||||
m_terminate_frame_reg <= 1'b0;
|
||||
end
|
||||
|
||||
for (j = RAM_PIPELINE+1-1; j > 0; j = j - 1) begin
|
||||
if (m_axis_tready || ((~m_axis_tvalid_pipe_reg) >> j)) begin
|
||||
if (OUTPUT_FIFO_ENABLE || m_axis_tready || ((~m_axis_tvalid_pipe_reg) >> j)) begin
|
||||
// output ready or bubble in pipeline; transfer down pipeline
|
||||
m_axis_tvalid_pipe_reg[j] <= m_axis_tvalid_pipe_reg[j-1];
|
||||
m_axis_pipe_reg[j] <= j == 1 ? mem_read_data_reg : m_axis_pipe_reg[j-1];
|
||||
@ -557,11 +556,11 @@ always @(posedge m_clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
if (m_axis_tready || ~m_axis_tvalid_pipe_reg) begin
|
||||
if (OUTPUT_FIFO_ENABLE || m_axis_tready || ~m_axis_tvalid_pipe_reg) begin
|
||||
// output ready or bubble in pipeline; read new data from FIFO
|
||||
m_axis_tvalid_pipe_reg[0] <= 1'b0;
|
||||
mem_read_data_reg <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
if (!empty && !m_rst_sync3_reg && !m_drop_frame_reg) begin
|
||||
if (!empty && !m_rst_sync3_reg && !m_drop_frame_reg && pipe_ready) begin
|
||||
// not empty, increment pointer
|
||||
m_axis_tvalid_pipe_reg[0] <= 1'b1;
|
||||
rd_ptr_temp = rd_ptr_reg + 1;
|
||||
@ -572,14 +571,14 @@ always @(posedge m_clk) begin
|
||||
|
||||
if (m_axis_tvalid_pipe && LAST_ENABLE) begin
|
||||
// track output frame status
|
||||
if (m_axis_tlast_pipe && m_axis_tready) begin
|
||||
if (m_axis_tlast_pipe && (OUTPUT_FIFO_ENABLE || m_axis_tready)) begin
|
||||
m_frame_reg <= 1'b0;
|
||||
end else begin
|
||||
m_frame_reg <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if (m_drop_frame_reg && (m_axis_tready || !m_axis_tvalid_pipe) && LAST_ENABLE) begin
|
||||
if (m_drop_frame_reg && (OUTPUT_FIFO_ENABLE ? pipe_ready : m_axis_tready || !m_axis_tvalid_pipe) && LAST_ENABLE) begin
|
||||
// terminate frame
|
||||
// (only for frame transfers interrupted by source reset)
|
||||
m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b1;
|
||||
@ -617,6 +616,99 @@ always @(posedge m_clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
|
||||
if (!OUTPUT_FIFO_ENABLE) begin
|
||||
|
||||
assign pipe_ready = 1'b1;
|
||||
|
||||
assign m_axis_tvalid = m_axis_tvalid_pipe;
|
||||
|
||||
assign m_axis_tdata = m_axis_tdata_pipe;
|
||||
assign m_axis_tkeep = m_axis_tkeep_pipe;
|
||||
assign m_axis_tlast = m_axis_tlast_pipe;
|
||||
assign m_axis_tid = m_axis_tid_pipe;
|
||||
assign m_axis_tdest = m_axis_tdest_pipe;
|
||||
assign m_axis_tuser = m_axis_tuser_pipe;
|
||||
|
||||
end else begin
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg m_axis_tvalid_reg = 1'b0;
|
||||
reg m_axis_tlast_reg = 1'b0;
|
||||
reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}};
|
||||
reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}};
|
||||
|
||||
reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_wr_ptr_reg = 0;
|
||||
reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_rd_ptr_reg = 0;
|
||||
reg out_fifo_half_full_reg = 1'b0;
|
||||
|
||||
wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {OUTPUT_FIFO_ADDR_WIDTH{1'b0}}});
|
||||
wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg;
|
||||
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [DATA_WIDTH-1:0] out_fifo_tdata[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [KEEP_WIDTH-1:0] out_fifo_tkeep[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg out_fifo_tlast[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [ID_WIDTH-1:0] out_fifo_tid[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [DEST_WIDTH-1:0] out_fifo_tdest[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [USER_WIDTH-1:0] out_fifo_tuser[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
|
||||
assign pipe_ready = !out_fifo_half_full_reg;
|
||||
|
||||
assign m_axis_tdata = m_axis_tdata_reg;
|
||||
assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}};
|
||||
assign m_axis_tvalid = m_axis_tvalid_reg;
|
||||
assign m_axis_tlast = LAST_ENABLE ? m_axis_tlast_reg : 1'b1;
|
||||
assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}};
|
||||
assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}};
|
||||
assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}};
|
||||
|
||||
always @(posedge m_clk) begin
|
||||
m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready;
|
||||
|
||||
out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(OUTPUT_FIFO_ADDR_WIDTH-1);
|
||||
|
||||
if (!out_fifo_full && m_axis_tvalid_pipe) begin
|
||||
out_fifo_tdata[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdata_pipe;
|
||||
out_fifo_tkeep[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tkeep_pipe;
|
||||
out_fifo_tlast[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tlast_pipe;
|
||||
out_fifo_tid[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tid_pipe;
|
||||
out_fifo_tdest[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdest_pipe;
|
||||
out_fifo_tuser[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tuser_pipe;
|
||||
out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1;
|
||||
end
|
||||
|
||||
if (!out_fifo_empty && (!m_axis_tvalid_reg || m_axis_tready)) begin
|
||||
m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tvalid_reg <= 1'b1;
|
||||
m_axis_tlast_reg <= out_fifo_tlast[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tid_reg <= out_fifo_tid[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tdest_reg <= out_fifo_tdest[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tuser_reg <= out_fifo_tuser[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1;
|
||||
end
|
||||
|
||||
if (m_rst) begin
|
||||
out_fifo_wr_ptr_reg <= 0;
|
||||
out_fifo_rd_ptr_reg <= 0;
|
||||
m_axis_tvalid_reg <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
|
@ -65,6 +65,9 @@ module axis_async_fifo_adapter #
|
||||
parameter USER_WIDTH = 1,
|
||||
// number of RAM pipeline registers in FIFO
|
||||
parameter RAM_PIPELINE = 1,
|
||||
// use output FIFO
|
||||
// When set, the RAM read enable and pipeline clock enables are removed
|
||||
parameter OUTPUT_FIFO_ENABLE = 0,
|
||||
// Frame FIFO mode - operate on frames instead of cycles
|
||||
// When set, m_axis_tvalid will not be deasserted within a frame
|
||||
// Requires LAST_ENABLE set
|
||||
@ -315,6 +318,7 @@ axis_async_fifo #(
|
||||
.USER_ENABLE(USER_ENABLE),
|
||||
.USER_WIDTH(USER_WIDTH),
|
||||
.RAM_PIPELINE(RAM_PIPELINE),
|
||||
.OUTPUT_FIFO_ENABLE(OUTPUT_FIFO_ENABLE),
|
||||
.FRAME_FIFO(FRAME_FIFO),
|
||||
.USER_BAD_FRAME_VALUE(USER_BAD_FRAME_VALUE),
|
||||
.USER_BAD_FRAME_MASK(USER_BAD_FRAME_MASK),
|
||||
|
116
rtl/axis_fifo.v
116
rtl/axis_fifo.v
@ -60,6 +60,9 @@ module axis_fifo #
|
||||
parameter USER_WIDTH = 1,
|
||||
// number of RAM pipeline registers
|
||||
parameter RAM_PIPELINE = 1,
|
||||
// use output FIFO
|
||||
// When set, the RAM read enable and pipeline clock enables are removed
|
||||
parameter OUTPUT_FIFO_ENABLE = 0,
|
||||
// Frame FIFO mode - operate on frames instead of cycles
|
||||
// When set, m_axis_tvalid will not be deasserted within a frame
|
||||
// Requires LAST_ENABLE set
|
||||
@ -117,6 +120,8 @@ module axis_fifo #
|
||||
|
||||
parameter ADDR_WIDTH = (KEEP_ENABLE && KEEP_WIDTH > 1) ? $clog2(DEPTH/KEEP_WIDTH) : $clog2(DEPTH);
|
||||
|
||||
parameter OUTPUT_FIFO_ADDR_WIDTH = RAM_PIPELINE < 2 ? 3 : $clog2(RAM_PIPELINE*2+7);
|
||||
|
||||
// check configuration
|
||||
initial begin
|
||||
if (FRAME_FIFO && !LAST_ENABLE) begin
|
||||
@ -161,6 +166,7 @@ reg [WIDTH-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [WIDTH-1:0] mem_read_data_reg;
|
||||
reg mem_read_data_valid_reg = 1'b0;
|
||||
|
||||
(* shreg_extract = "no" *)
|
||||
reg [WIDTH-1:0] m_axis_pipe_reg[RAM_PIPELINE+1-1:0];
|
||||
reg [RAM_PIPELINE+1-1:0] m_axis_tvalid_pipe_reg = 0;
|
||||
|
||||
@ -202,14 +208,7 @@ wire [ID_WIDTH-1:0] m_axis_tid_pipe = ID_ENABLE ? m_axis[ID_OFFSET +: ID
|
||||
wire [DEST_WIDTH-1:0] m_axis_tdest_pipe = DEST_ENABLE ? m_axis[DEST_OFFSET +: DEST_WIDTH] : {DEST_WIDTH{1'b0}};
|
||||
wire [USER_WIDTH-1:0] m_axis_tuser_pipe = USER_ENABLE ? m_axis[USER_OFFSET +: USER_WIDTH] : {USER_WIDTH{1'b0}};
|
||||
|
||||
assign m_axis_tvalid = m_axis_tvalid_pipe;
|
||||
|
||||
assign m_axis_tdata = m_axis_tdata_pipe;
|
||||
assign m_axis_tkeep = m_axis_tkeep_pipe;
|
||||
assign m_axis_tlast = m_axis_tlast_pipe;
|
||||
assign m_axis_tid = m_axis_tid_pipe;
|
||||
assign m_axis_tdest = m_axis_tdest_pipe;
|
||||
assign m_axis_tuser = m_axis_tuser_pipe;
|
||||
wire pipe_ready;
|
||||
|
||||
assign status_overflow = overflow_reg;
|
||||
assign status_bad_frame = bad_frame_reg;
|
||||
@ -278,13 +277,13 @@ end
|
||||
integer j;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (m_axis_tready) begin
|
||||
if (OUTPUT_FIFO_ENABLE || m_axis_tready) begin
|
||||
// output ready; invalidate stage
|
||||
m_axis_tvalid_pipe_reg[RAM_PIPELINE+1-1] <= 1'b0;
|
||||
end
|
||||
|
||||
for (j = RAM_PIPELINE+1-1; j > 0; j = j - 1) begin
|
||||
if (m_axis_tready || ((~m_axis_tvalid_pipe_reg) >> j)) begin
|
||||
if (OUTPUT_FIFO_ENABLE || m_axis_tready || ((~m_axis_tvalid_pipe_reg) >> j)) begin
|
||||
// output ready or bubble in pipeline; transfer down pipeline
|
||||
m_axis_tvalid_pipe_reg[j] <= m_axis_tvalid_pipe_reg[j-1];
|
||||
m_axis_pipe_reg[j] <= j == 1 ? mem_read_data_reg : m_axis_pipe_reg[j-1];
|
||||
@ -292,11 +291,11 @@ always @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
if (m_axis_tready || ~m_axis_tvalid_pipe_reg) begin
|
||||
if (OUTPUT_FIFO_ENABLE || m_axis_tready || ~m_axis_tvalid_pipe_reg) begin
|
||||
// output ready or bubble in pipeline; read new data from FIFO
|
||||
m_axis_tvalid_pipe_reg[0] <= 1'b0;
|
||||
mem_read_data_reg <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||
if (!empty) begin
|
||||
if (!empty && pipe_ready) begin
|
||||
// not empty, increment pointer
|
||||
m_axis_tvalid_pipe_reg[0] <= 1'b1;
|
||||
rd_ptr_reg <= rd_ptr_reg + 1;
|
||||
@ -309,6 +308,99 @@ always @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
|
||||
if (!OUTPUT_FIFO_ENABLE) begin
|
||||
|
||||
assign pipe_ready = 1'b1;
|
||||
|
||||
assign m_axis_tvalid = m_axis_tvalid_pipe;
|
||||
|
||||
assign m_axis_tdata = m_axis_tdata_pipe;
|
||||
assign m_axis_tkeep = m_axis_tkeep_pipe;
|
||||
assign m_axis_tlast = m_axis_tlast_pipe;
|
||||
assign m_axis_tid = m_axis_tid_pipe;
|
||||
assign m_axis_tdest = m_axis_tdest_pipe;
|
||||
assign m_axis_tuser = m_axis_tuser_pipe;
|
||||
|
||||
end else begin
|
||||
|
||||
// output datapath logic
|
||||
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
|
||||
reg m_axis_tvalid_reg = 1'b0;
|
||||
reg m_axis_tlast_reg = 1'b0;
|
||||
reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}};
|
||||
reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}};
|
||||
|
||||
reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_wr_ptr_reg = 0;
|
||||
reg [OUTPUT_FIFO_ADDR_WIDTH+1-1:0] out_fifo_rd_ptr_reg = 0;
|
||||
reg out_fifo_half_full_reg = 1'b0;
|
||||
|
||||
wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {OUTPUT_FIFO_ADDR_WIDTH{1'b0}}});
|
||||
wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg;
|
||||
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [DATA_WIDTH-1:0] out_fifo_tdata[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [KEEP_WIDTH-1:0] out_fifo_tkeep[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg out_fifo_tlast[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [ID_WIDTH-1:0] out_fifo_tid[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [DEST_WIDTH-1:0] out_fifo_tdest[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||
reg [USER_WIDTH-1:0] out_fifo_tuser[2**OUTPUT_FIFO_ADDR_WIDTH-1:0];
|
||||
|
||||
assign pipe_ready = !out_fifo_half_full_reg;
|
||||
|
||||
assign m_axis_tdata = m_axis_tdata_reg;
|
||||
assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}};
|
||||
assign m_axis_tvalid = m_axis_tvalid_reg;
|
||||
assign m_axis_tlast = LAST_ENABLE ? m_axis_tlast_reg : 1'b1;
|
||||
assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}};
|
||||
assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}};
|
||||
assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}};
|
||||
|
||||
always @(posedge clk) begin
|
||||
m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready;
|
||||
|
||||
out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(OUTPUT_FIFO_ADDR_WIDTH-1);
|
||||
|
||||
if (!out_fifo_full && m_axis_tvalid_pipe) begin
|
||||
out_fifo_tdata[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdata_pipe;
|
||||
out_fifo_tkeep[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tkeep_pipe;
|
||||
out_fifo_tlast[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tlast_pipe;
|
||||
out_fifo_tid[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tid_pipe;
|
||||
out_fifo_tdest[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdest_pipe;
|
||||
out_fifo_tuser[out_fifo_wr_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]] <= m_axis_tuser_pipe;
|
||||
out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1;
|
||||
end
|
||||
|
||||
if (!out_fifo_empty && (!m_axis_tvalid_reg || m_axis_tready)) begin
|
||||
m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tvalid_reg <= 1'b1;
|
||||
m_axis_tlast_reg <= out_fifo_tlast[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tid_reg <= out_fifo_tid[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tdest_reg <= out_fifo_tdest[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
m_axis_tuser_reg <= out_fifo_tuser[out_fifo_rd_ptr_reg[OUTPUT_FIFO_ADDR_WIDTH-1:0]];
|
||||
out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1;
|
||||
end
|
||||
|
||||
if (rst) begin
|
||||
out_fifo_wr_ptr_reg <= 0;
|
||||
out_fifo_rd_ptr_reg <= 0;
|
||||
m_axis_tvalid_reg <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
|
@ -65,6 +65,9 @@ module axis_fifo_adapter #
|
||||
parameter USER_WIDTH = 1,
|
||||
// number of RAM pipeline registers in FIFO
|
||||
parameter RAM_PIPELINE = 1,
|
||||
// use output FIFO
|
||||
// When set, the RAM read enable and pipeline clock enables are removed
|
||||
parameter OUTPUT_FIFO_ENABLE = 0,
|
||||
// Frame FIFO mode - operate on frames instead of cycles
|
||||
// When set, m_axis_tvalid will not be deasserted within a frame
|
||||
// Requires LAST_ENABLE set
|
||||
@ -310,6 +313,7 @@ axis_fifo #(
|
||||
.USER_ENABLE(USER_ENABLE),
|
||||
.USER_WIDTH(USER_WIDTH),
|
||||
.RAM_PIPELINE(RAM_PIPELINE),
|
||||
.OUTPUT_FIFO_ENABLE(OUTPUT_FIFO_ENABLE),
|
||||
.FRAME_FIFO(FRAME_FIFO),
|
||||
.USER_BAD_FRAME_VALUE(USER_BAD_FRAME_VALUE),
|
||||
.USER_BAD_FRAME_MASK(USER_BAD_FRAME_MASK),
|
||||
|
@ -44,6 +44,7 @@ export PARAM_DEST_WIDTH ?= 8
|
||||
export PARAM_USER_ENABLE ?= 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_RAM_PIPELINE ?= 1
|
||||
export PARAM_OUTPUT_FIFO_ENABLE ?= 0
|
||||
export PARAM_FRAME_FIFO ?= 1
|
||||
export PARAM_USER_BAD_FRAME_VALUE ?= 1
|
||||
export PARAM_USER_BAD_FRAME_MASK ?= 1
|
||||
@ -66,6 +67,7 @@ ifeq ($(SIM), icarus)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_ENABLE=$(PARAM_USER_ENABLE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RAM_PIPELINE=$(PARAM_RAM_PIPELINE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).OUTPUT_FIFO_ENABLE=$(PARAM_OUTPUT_FIFO_ENABLE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).FRAME_FIFO=$(PARAM_FRAME_FIFO)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_BAD_FRAME_VALUE=$(PARAM_USER_BAD_FRAME_VALUE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_BAD_FRAME_MASK=$(PARAM_USER_BAD_FRAME_MASK)
|
||||
@ -92,6 +94,7 @@ else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -GUSER_ENABLE=$(PARAM_USER_ENABLE)
|
||||
COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRAM_PIPELINE=$(PARAM_RAM_PIPELINE)
|
||||
COMPILE_ARGS += -GOUTPUT_FIFO_ENABLE=$(PARAM_OUTPUT_FIFO_ENABLE)
|
||||
COMPILE_ARGS += -GFRAME_FIFO=$(PARAM_FRAME_FIFO)
|
||||
COMPILE_ARGS += -GUSER_BAD_FRAME_VALUE=$(PARAM_USER_BAD_FRAME_VALUE)
|
||||
COMPILE_ARGS += -GUSER_BAD_FRAME_MASK=$(PARAM_USER_BAD_FRAME_MASK)
|
||||
|
@ -229,11 +229,11 @@ async def run_test_init_sink_pause_source_reset(dut):
|
||||
|
||||
tb.sink.pause = True
|
||||
|
||||
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 32))
|
||||
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 512))
|
||||
test_frame = AxiStreamFrame(test_data)
|
||||
await tb.source.send(test_frame)
|
||||
|
||||
for k in range(64):
|
||||
for k in range(1024):
|
||||
await RisingEdge(dut.s_clk)
|
||||
|
||||
await tb.reset_source()
|
||||
@ -522,10 +522,10 @@ rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
@pytest.mark.parametrize(("s_clk", "m_clk"), [(10, 10), (10, 11), (11, 10)])
|
||||
@pytest.mark.parametrize(("frame_fifo", "drop_oversize_frame", "drop_bad_frame", "drop_when_full"),
|
||||
[(0, 0, 0, 0), (1, 0, 0, 0), (1, 1, 0, 0), (1, 1, 1, 0)])
|
||||
@pytest.mark.parametrize(("ram_pipeline"),
|
||||
[0, 1, 4])
|
||||
@pytest.mark.parametrize(("ram_pipeline", "output_fifo"),
|
||||
[(0, 0), (1, 0), (4, 0), (0, 1), (1, 1), (4, 1)])
|
||||
@pytest.mark.parametrize("data_width", [8, 16, 32, 64])
|
||||
def test_axis_async_fifo(request, data_width, ram_pipeline,
|
||||
def test_axis_async_fifo(request, data_width, ram_pipeline, output_fifo,
|
||||
frame_fifo, drop_oversize_frame, drop_bad_frame, drop_when_full, s_clk, m_clk):
|
||||
|
||||
dut = "axis_async_fifo"
|
||||
@ -550,6 +550,7 @@ def test_axis_async_fifo(request, data_width, ram_pipeline,
|
||||
parameters['USER_ENABLE'] = 1
|
||||
parameters['USER_WIDTH'] = 1
|
||||
parameters['RAM_PIPELINE'] = ram_pipeline
|
||||
parameters['OUTPUT_FIFO_ENABLE'] = output_fifo
|
||||
parameters['FRAME_FIFO'] = frame_fifo
|
||||
parameters['USER_BAD_FRAME_VALUE'] = 1
|
||||
parameters['USER_BAD_FRAME_MASK'] = 1
|
||||
|
@ -49,6 +49,7 @@ export PARAM_DEST_WIDTH ?= 8
|
||||
export PARAM_USER_ENABLE ?= 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_RAM_PIPELINE ?= 1
|
||||
export PARAM_OUTPUT_FIFO_ENABLE ?= 0
|
||||
export PARAM_FRAME_FIFO ?= 1
|
||||
export PARAM_USER_BAD_FRAME_VALUE ?= 1
|
||||
export PARAM_USER_BAD_FRAME_MASK ?= 1
|
||||
@ -73,6 +74,7 @@ ifeq ($(SIM), icarus)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_ENABLE=$(PARAM_USER_ENABLE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RAM_PIPELINE=$(PARAM_RAM_PIPELINE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).OUTPUT_FIFO_ENABLE=$(PARAM_OUTPUT_FIFO_ENABLE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).FRAME_FIFO=$(PARAM_FRAME_FIFO)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_BAD_FRAME_VALUE=$(PARAM_USER_BAD_FRAME_VALUE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_BAD_FRAME_MASK=$(PARAM_USER_BAD_FRAME_MASK)
|
||||
@ -101,6 +103,7 @@ else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -GUSER_ENABLE=$(PARAM_USER_ENABLE)
|
||||
COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRAM_PIPELINE=$(PARAM_RAM_PIPELINE)
|
||||
COMPILE_ARGS += -GOUTPUT_FIFO_ENABLE=$(PARAM_OUTPUT_FIFO_ENABLE)
|
||||
COMPILE_ARGS += -GFRAME_FIFO=$(PARAM_FRAME_FIFO)
|
||||
COMPILE_ARGS += -GUSER_BAD_FRAME_VALUE=$(PARAM_USER_BAD_FRAME_VALUE)
|
||||
COMPILE_ARGS += -GUSER_BAD_FRAME_MASK=$(PARAM_USER_BAD_FRAME_MASK)
|
||||
|
@ -547,6 +547,7 @@ def test_axis_async_fifo_adapter(request, s_data_width, m_data_width, frame_fifo
|
||||
parameters['USER_ENABLE'] = 1
|
||||
parameters['USER_WIDTH'] = 1
|
||||
parameters['RAM_PIPELINE'] = 1
|
||||
parameters['OUTPUT_FIFO_ENABLE'] = 0
|
||||
parameters['FRAME_FIFO'] = frame_fifo
|
||||
parameters['USER_BAD_FRAME_VALUE'] = 1
|
||||
parameters['USER_BAD_FRAME_MASK'] = 1
|
||||
|
@ -44,6 +44,7 @@ export PARAM_DEST_WIDTH ?= 8
|
||||
export PARAM_USER_ENABLE ?= 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_RAM_PIPELINE ?= 1
|
||||
export PARAM_OUTPUT_FIFO_ENABLE ?= 0
|
||||
export PARAM_FRAME_FIFO ?= 1
|
||||
export PARAM_USER_BAD_FRAME_VALUE ?= 1
|
||||
export PARAM_USER_BAD_FRAME_MASK ?= 1
|
||||
@ -66,6 +67,7 @@ ifeq ($(SIM), icarus)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_ENABLE=$(PARAM_USER_ENABLE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RAM_PIPELINE=$(PARAM_RAM_PIPELINE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).OUTPUT_FIFO_ENABLE=$(PARAM_OUTPUT_FIFO_ENABLE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).FRAME_FIFO=$(PARAM_FRAME_FIFO)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_BAD_FRAME_VALUE=$(PARAM_USER_BAD_FRAME_VALUE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_BAD_FRAME_MASK=$(PARAM_USER_BAD_FRAME_MASK)
|
||||
@ -92,6 +94,7 @@ else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -GUSER_ENABLE=$(PARAM_USER_ENABLE)
|
||||
COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRAM_PIPELINE=$(PARAM_RAM_PIPELINE)
|
||||
COMPILE_ARGS += -GOUTPUT_FIFO_ENABLE=$(PARAM_OUTPUT_FIFO_ENABLE)
|
||||
COMPILE_ARGS += -GFRAME_FIFO=$(PARAM_FRAME_FIFO)
|
||||
COMPILE_ARGS += -GUSER_BAD_FRAME_VALUE=$(PARAM_USER_BAD_FRAME_VALUE)
|
||||
COMPILE_ARGS += -GUSER_BAD_FRAME_MASK=$(PARAM_USER_BAD_FRAME_MASK)
|
||||
|
@ -314,10 +314,10 @@ rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
|
||||
@pytest.mark.parametrize(("frame_fifo", "drop_oversize_frame", "drop_bad_frame", "drop_when_full"),
|
||||
[(0, 0, 0, 0), (1, 0, 0, 0), (1, 1, 0, 0), (1, 1, 1, 0)])
|
||||
@pytest.mark.parametrize(("ram_pipeline"),
|
||||
[0, 1, 4])
|
||||
@pytest.mark.parametrize(("ram_pipeline", "output_fifo"),
|
||||
[(0, 0), (1, 0), (4, 0), (0, 1), (1, 1), (4, 1)])
|
||||
@pytest.mark.parametrize("data_width", [8, 16, 32, 64])
|
||||
def test_axis_fifo(request, data_width, ram_pipeline,
|
||||
def test_axis_fifo(request, data_width, ram_pipeline, output_fifo,
|
||||
frame_fifo, drop_oversize_frame, drop_bad_frame, drop_when_full):
|
||||
|
||||
dut = "axis_fifo"
|
||||
@ -342,6 +342,7 @@ def test_axis_fifo(request, data_width, ram_pipeline,
|
||||
parameters['USER_ENABLE'] = 1
|
||||
parameters['USER_WIDTH'] = 1
|
||||
parameters['RAM_PIPELINE'] = ram_pipeline
|
||||
parameters['OUTPUT_FIFO_ENABLE'] = output_fifo
|
||||
parameters['FRAME_FIFO'] = frame_fifo
|
||||
parameters['USER_BAD_FRAME_VALUE'] = 1
|
||||
parameters['USER_BAD_FRAME_MASK'] = 1
|
||||
|
@ -49,6 +49,7 @@ export PARAM_DEST_WIDTH ?= 8
|
||||
export PARAM_USER_ENABLE ?= 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_RAM_PIPELINE ?= 1
|
||||
export PARAM_OUTPUT_FIFO_ENABLE ?= 0
|
||||
export PARAM_FRAME_FIFO ?= 1
|
||||
export PARAM_USER_BAD_FRAME_VALUE ?= 1
|
||||
export PARAM_USER_BAD_FRAME_MASK ?= 1
|
||||
@ -73,6 +74,7 @@ ifeq ($(SIM), icarus)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_ENABLE=$(PARAM_USER_ENABLE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RAM_PIPELINE=$(PARAM_RAM_PIPELINE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).OUTPUT_FIFO_ENABLE=$(PARAM_OUTPUT_FIFO_ENABLE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).FRAME_FIFO=$(PARAM_FRAME_FIFO)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_BAD_FRAME_VALUE=$(PARAM_USER_BAD_FRAME_VALUE)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_BAD_FRAME_MASK=$(PARAM_USER_BAD_FRAME_MASK)
|
||||
@ -101,6 +103,7 @@ else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -GUSER_ENABLE=$(PARAM_USER_ENABLE)
|
||||
COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRAM_PIPELINE=$(PARAM_RAM_PIPELINE)
|
||||
COMPILE_ARGS += -GOUTPUT_FIFO_ENABLE=$(PARAM_OUTPUT_FIFO_ENABLE)
|
||||
COMPILE_ARGS += -GFRAME_FIFO=$(PARAM_FRAME_FIFO)
|
||||
COMPILE_ARGS += -GUSER_BAD_FRAME_VALUE=$(PARAM_USER_BAD_FRAME_VALUE)
|
||||
COMPILE_ARGS += -GUSER_BAD_FRAME_MASK=$(PARAM_USER_BAD_FRAME_MASK)
|
||||
|
@ -343,6 +343,7 @@ def test_axis_fifo_adapter(request, s_data_width, m_data_width, frame_fifo, drop
|
||||
parameters['USER_ENABLE'] = 1
|
||||
parameters['USER_WIDTH'] = 1
|
||||
parameters['RAM_PIPELINE'] = 1
|
||||
parameters['OUTPUT_FIFO_ENABLE'] = 0
|
||||
parameters['FRAME_FIFO'] = frame_fifo
|
||||
parameters['USER_BAD_FRAME_VALUE'] = 1
|
||||
parameters['USER_BAD_FRAME_MASK'] = 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user