mirror of
https://github.com/corundum/corundum.git
synced 2025-01-30 08:32:52 +08:00
Split async FIFO resets
This commit is contained in:
parent
e0da1819c4
commit
4f1eabab17
@ -78,15 +78,11 @@ module axis_async_fifo #
|
|||||||
parameter DROP_WHEN_FULL = 0
|
parameter DROP_WHEN_FULL = 0
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
/*
|
|
||||||
* Common asynchronous reset
|
|
||||||
*/
|
|
||||||
input wire async_rst,
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AXI input
|
* AXI input
|
||||||
*/
|
*/
|
||||||
input wire s_clk,
|
input wire s_clk,
|
||||||
|
input wire s_rst,
|
||||||
input wire [DATA_WIDTH-1:0] s_axis_tdata,
|
input wire [DATA_WIDTH-1:0] s_axis_tdata,
|
||||||
input wire [KEEP_WIDTH-1:0] s_axis_tkeep,
|
input wire [KEEP_WIDTH-1:0] s_axis_tkeep,
|
||||||
input wire s_axis_tvalid,
|
input wire s_axis_tvalid,
|
||||||
@ -100,6 +96,7 @@ module axis_async_fifo #
|
|||||||
* AXI output
|
* AXI output
|
||||||
*/
|
*/
|
||||||
input wire m_clk,
|
input wire m_clk,
|
||||||
|
input wire m_rst,
|
||||||
output wire [DATA_WIDTH-1:0] m_axis_tdata,
|
output wire [DATA_WIDTH-1:0] m_axis_tdata,
|
||||||
output wire [KEEP_WIDTH-1:0] m_axis_tkeep,
|
output wire [KEEP_WIDTH-1:0] m_axis_tkeep,
|
||||||
output wire m_axis_tvalid,
|
output wire m_axis_tvalid,
|
||||||
@ -214,9 +211,7 @@ reg mem_read_data_valid_reg = 1'b0;
|
|||||||
|
|
||||||
wire [WIDTH-1:0] s_axis;
|
wire [WIDTH-1:0] s_axis;
|
||||||
|
|
||||||
(* SHREG_EXTRACT = "NO" *)
|
|
||||||
reg [WIDTH-1:0] m_axis_pipe_reg[PIPELINE_OUTPUT-1:0];
|
reg [WIDTH-1:0] m_axis_pipe_reg[PIPELINE_OUTPUT-1:0];
|
||||||
(* SHREG_EXTRACT = "NO" *)
|
|
||||||
reg [PIPELINE_OUTPUT-1:0] m_axis_tvalid_pipe_reg = 1'b0;
|
reg [PIPELINE_OUTPUT-1:0] m_axis_tvalid_pipe_reg = 1'b0;
|
||||||
|
|
||||||
// full when first TWO MSBs do NOT match, but rest matches
|
// full when first TWO MSBs do NOT match, but rest matches
|
||||||
@ -233,12 +228,18 @@ reg write;
|
|||||||
reg read;
|
reg read;
|
||||||
reg store_output;
|
reg store_output;
|
||||||
|
|
||||||
|
reg s_frame_reg = 1'b0;
|
||||||
|
reg m_frame_reg = 1'b0;
|
||||||
|
|
||||||
reg drop_frame_reg = 1'b0;
|
reg drop_frame_reg = 1'b0;
|
||||||
reg send_frame_reg = 1'b0;
|
reg send_frame_reg = 1'b0;
|
||||||
reg overflow_reg = 1'b0;
|
reg overflow_reg = 1'b0;
|
||||||
reg bad_frame_reg = 1'b0;
|
reg bad_frame_reg = 1'b0;
|
||||||
reg good_frame_reg = 1'b0;
|
reg good_frame_reg = 1'b0;
|
||||||
|
|
||||||
|
reg m_drop_frame_reg = 1'b0;
|
||||||
|
reg m_terminate_frame_reg = 1'b0;
|
||||||
|
|
||||||
reg overflow_sync1_reg = 1'b0;
|
reg overflow_sync1_reg = 1'b0;
|
||||||
reg overflow_sync2_reg = 1'b0;
|
reg overflow_sync2_reg = 1'b0;
|
||||||
reg overflow_sync3_reg = 1'b0;
|
reg overflow_sync3_reg = 1'b0;
|
||||||
@ -263,14 +264,23 @@ generate
|
|||||||
if (USER_ENABLE) assign s_axis[USER_OFFSET +: USER_WIDTH] = s_axis_tuser;
|
if (USER_ENABLE) assign s_axis[USER_OFFSET +: USER_WIDTH] = s_axis_tuser;
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
assign m_axis_tvalid = m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT-1];
|
wire m_axis_tvalid_pipe = m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT-1];
|
||||||
|
|
||||||
assign m_axis_tdata = m_axis_pipe_reg[PIPELINE_OUTPUT-1][DATA_WIDTH-1:0];
|
wire [DATA_WIDTH-1:0] m_axis_tdata_pipe = m_axis_pipe_reg[PIPELINE_OUTPUT-1][DATA_WIDTH-1:0];
|
||||||
assign m_axis_tkeep = KEEP_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][KEEP_OFFSET +: KEEP_WIDTH] : {KEEP_WIDTH{1'b1}};
|
wire [KEEP_WIDTH-1:0] m_axis_tkeep_pipe = KEEP_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][KEEP_OFFSET +: KEEP_WIDTH] : {KEEP_WIDTH{1'b1}};
|
||||||
assign m_axis_tlast = LAST_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][LAST_OFFSET] : 1'b1;
|
wire m_axis_tlast_pipe = LAST_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][LAST_OFFSET] : 1'b1;
|
||||||
assign m_axis_tid = ID_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][ID_OFFSET +: ID_WIDTH] : {ID_WIDTH{1'b0}};
|
wire [ID_WIDTH-1:0] m_axis_tid_pipe = ID_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][ID_OFFSET +: ID_WIDTH] : {ID_WIDTH{1'b0}};
|
||||||
assign m_axis_tdest = DEST_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][DEST_OFFSET +: DEST_WIDTH] : {DEST_WIDTH{1'b0}};
|
wire [DEST_WIDTH-1:0] m_axis_tdest_pipe = DEST_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][DEST_OFFSET +: DEST_WIDTH] : {DEST_WIDTH{1'b0}};
|
||||||
assign m_axis_tuser = USER_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][USER_OFFSET +: USER_WIDTH] : {USER_WIDTH{1'b0}};
|
wire [USER_WIDTH-1:0] m_axis_tuser_pipe = USER_ENABLE ? m_axis_pipe_reg[PIPELINE_OUTPUT-1][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_terminate_frame_reg ? 1'b1 : 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_terminate_frame_reg ? USER_BAD_FRAME_VALUE : m_axis_tuser_pipe);
|
||||||
|
|
||||||
assign s_status_overflow = overflow_reg;
|
assign s_status_overflow = overflow_reg;
|
||||||
assign s_status_bad_frame = bad_frame_reg;
|
assign s_status_bad_frame = bad_frame_reg;
|
||||||
@ -281,30 +291,32 @@ assign m_status_bad_frame = bad_frame_sync3_reg ^ bad_frame_sync4_reg;
|
|||||||
assign m_status_good_frame = good_frame_sync3_reg ^ good_frame_sync4_reg;
|
assign m_status_good_frame = good_frame_sync3_reg ^ good_frame_sync4_reg;
|
||||||
|
|
||||||
// reset synchronization
|
// reset synchronization
|
||||||
always @(posedge s_clk or posedge async_rst) begin
|
always @(posedge m_clk or posedge m_rst) begin
|
||||||
if (async_rst) begin
|
if (m_rst) begin
|
||||||
s_rst_sync1_reg <= 1'b1;
|
s_rst_sync1_reg <= 1'b1;
|
||||||
s_rst_sync2_reg <= 1'b1;
|
|
||||||
s_rst_sync3_reg <= 1'b1;
|
|
||||||
end else begin
|
end else begin
|
||||||
s_rst_sync1_reg <= 1'b0;
|
s_rst_sync1_reg <= 1'b0;
|
||||||
s_rst_sync2_reg <= s_rst_sync1_reg || m_rst_sync1_reg;
|
|
||||||
s_rst_sync3_reg <= s_rst_sync2_reg;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge m_clk or posedge async_rst) begin
|
always @(posedge s_clk) begin
|
||||||
if (async_rst) begin
|
s_rst_sync2_reg <= s_rst_sync1_reg;
|
||||||
|
s_rst_sync3_reg <= s_rst_sync2_reg;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge s_clk or posedge s_rst) begin
|
||||||
|
if (s_rst) begin
|
||||||
m_rst_sync1_reg <= 1'b1;
|
m_rst_sync1_reg <= 1'b1;
|
||||||
m_rst_sync2_reg <= 1'b1;
|
|
||||||
m_rst_sync3_reg <= 1'b1;
|
|
||||||
end else begin
|
end else begin
|
||||||
m_rst_sync1_reg <= 1'b0;
|
m_rst_sync1_reg <= 1'b0;
|
||||||
m_rst_sync2_reg <= s_rst_sync1_reg || m_rst_sync1_reg;
|
|
||||||
m_rst_sync3_reg <= m_rst_sync2_reg;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
always @(posedge m_clk) begin
|
||||||
|
m_rst_sync2_reg <= m_rst_sync1_reg;
|
||||||
|
m_rst_sync3_reg <= m_rst_sync2_reg;
|
||||||
|
end
|
||||||
|
|
||||||
// Write logic
|
// Write logic
|
||||||
always @(posedge s_clk) begin
|
always @(posedge s_clk) begin
|
||||||
overflow_reg <= 1'b0;
|
overflow_reg <= 1'b0;
|
||||||
@ -321,14 +333,39 @@ always @(posedge s_clk) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (s_axis_tready && s_axis_tvalid && LAST_ENABLE) begin
|
||||||
|
// track input frame status
|
||||||
|
s_frame_reg <= !s_axis_tlast;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (s_rst_sync3_reg && LAST_ENABLE) begin
|
||||||
|
// if sink side is reset during transfer, drop partial frame
|
||||||
|
if (s_frame_reg && !(s_axis_tready && s_axis_tvalid && s_axis_tlast)) begin
|
||||||
|
drop_frame_reg <= 1'b1;
|
||||||
|
end
|
||||||
|
if (s_axis_tready && s_axis_tvalid && !s_axis_tlast) begin
|
||||||
|
drop_frame_reg <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if (s_axis_tready && s_axis_tvalid) begin
|
if (s_axis_tready && s_axis_tvalid) begin
|
||||||
// transfer in
|
// transfer in
|
||||||
if (!FRAME_FIFO) begin
|
if (!FRAME_FIFO) begin
|
||||||
// normal FIFO mode
|
// normal FIFO mode
|
||||||
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis;
|
mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis;
|
||||||
wr_ptr_temp = wr_ptr_reg + 1;
|
if (drop_frame_reg && LAST_ENABLE) begin
|
||||||
wr_ptr_reg <= wr_ptr_temp;
|
// currently dropping frame
|
||||||
wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
// (only for frame transfers interrupted by sink reset)
|
||||||
|
if (s_axis_tlast) begin
|
||||||
|
// end of frame, clear drop flag
|
||||||
|
drop_frame_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
// update pointers
|
||||||
|
wr_ptr_temp = wr_ptr_reg + 1;
|
||||||
|
wr_ptr_reg <= wr_ptr_temp;
|
||||||
|
wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1);
|
||||||
|
end
|
||||||
end else if ((full_cur && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin
|
end else if ((full_cur && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin
|
||||||
// full, packet overflow, or currently dropping frame
|
// full, packet overflow, or currently dropping frame
|
||||||
// drop frame
|
// drop frame
|
||||||
@ -403,6 +440,19 @@ always @(posedge s_clk) begin
|
|||||||
|
|
||||||
wr_ptr_update_valid_reg <= 1'b0;
|
wr_ptr_update_valid_reg <= 1'b0;
|
||||||
wr_ptr_update_reg <= 1'b0;
|
wr_ptr_update_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (s_rst) begin
|
||||||
|
wr_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
|
wr_ptr_cur_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
|
wr_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
|
wr_ptr_sync_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
|
wr_ptr_cur_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
|
|
||||||
|
wr_ptr_update_valid_reg <= 1'b0;
|
||||||
|
wr_ptr_update_reg <= 1'b0;
|
||||||
|
|
||||||
|
s_frame_reg <= 1'b0;
|
||||||
|
|
||||||
drop_frame_reg <= 1'b0;
|
drop_frame_reg <= 1'b0;
|
||||||
send_frame_reg <= 1'b0;
|
send_frame_reg <= 1'b0;
|
||||||
@ -419,7 +469,7 @@ always @(posedge s_clk) begin
|
|||||||
wr_ptr_update_ack_sync1_reg <= wr_ptr_update_sync3_reg;
|
wr_ptr_update_ack_sync1_reg <= wr_ptr_update_sync3_reg;
|
||||||
wr_ptr_update_ack_sync2_reg <= wr_ptr_update_ack_sync1_reg;
|
wr_ptr_update_ack_sync2_reg <= wr_ptr_update_ack_sync1_reg;
|
||||||
|
|
||||||
if (s_rst_sync3_reg) begin
|
if (s_rst) begin
|
||||||
rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
rd_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
rd_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
wr_ptr_update_ack_sync1_reg <= 1'b0;
|
wr_ptr_update_ack_sync1_reg <= 1'b0;
|
||||||
@ -438,7 +488,7 @@ always @(posedge m_clk) begin
|
|||||||
wr_ptr_update_sync2_reg <= wr_ptr_update_sync1_reg;
|
wr_ptr_update_sync2_reg <= wr_ptr_update_sync1_reg;
|
||||||
wr_ptr_update_sync3_reg <= wr_ptr_update_sync2_reg;
|
wr_ptr_update_sync3_reg <= wr_ptr_update_sync2_reg;
|
||||||
|
|
||||||
if (m_rst_sync3_reg) begin
|
if (m_rst) begin
|
||||||
wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
wr_ptr_gray_sync1_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
wr_ptr_gray_sync2_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
wr_ptr_update_sync1_reg <= 1'b0;
|
wr_ptr_update_sync1_reg <= 1'b0;
|
||||||
@ -453,7 +503,7 @@ always @(posedge s_clk) begin
|
|||||||
bad_frame_sync1_reg <= bad_frame_sync1_reg ^ bad_frame_reg;
|
bad_frame_sync1_reg <= bad_frame_sync1_reg ^ bad_frame_reg;
|
||||||
good_frame_sync1_reg <= good_frame_sync1_reg ^ good_frame_reg;
|
good_frame_sync1_reg <= good_frame_sync1_reg ^ good_frame_reg;
|
||||||
|
|
||||||
if (s_rst_sync3_reg) begin
|
if (s_rst) begin
|
||||||
overflow_sync1_reg <= 1'b0;
|
overflow_sync1_reg <= 1'b0;
|
||||||
bad_frame_sync1_reg <= 1'b0;
|
bad_frame_sync1_reg <= 1'b0;
|
||||||
good_frame_sync1_reg <= 1'b0;
|
good_frame_sync1_reg <= 1'b0;
|
||||||
@ -471,7 +521,7 @@ always @(posedge m_clk) begin
|
|||||||
good_frame_sync3_reg <= good_frame_sync2_reg;
|
good_frame_sync3_reg <= good_frame_sync2_reg;
|
||||||
good_frame_sync4_reg <= good_frame_sync3_reg;
|
good_frame_sync4_reg <= good_frame_sync3_reg;
|
||||||
|
|
||||||
if (m_rst_sync3_reg) begin
|
if (m_rst) begin
|
||||||
overflow_sync2_reg <= 1'b0;
|
overflow_sync2_reg <= 1'b0;
|
||||||
overflow_sync3_reg <= 1'b0;
|
overflow_sync3_reg <= 1'b0;
|
||||||
overflow_sync4_reg <= 1'b0;
|
overflow_sync4_reg <= 1'b0;
|
||||||
@ -491,6 +541,7 @@ always @(posedge m_clk) begin
|
|||||||
if (m_axis_tready) begin
|
if (m_axis_tready) begin
|
||||||
// output ready; invalidate stage
|
// output ready; invalidate stage
|
||||||
m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT-1] <= 1'b0;
|
m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT-1] <= 1'b0;
|
||||||
|
m_terminate_frame_reg <= 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
for (j = PIPELINE_OUTPUT-1; j > 0; j = j - 1) begin
|
for (j = PIPELINE_OUTPUT-1; j > 0; j = j - 1) begin
|
||||||
@ -506,7 +557,7 @@ always @(posedge m_clk) begin
|
|||||||
// output ready or bubble in pipeline; read new data from FIFO
|
// output ready or bubble in pipeline; read new data from FIFO
|
||||||
m_axis_tvalid_pipe_reg[0] <= 1'b0;
|
m_axis_tvalid_pipe_reg[0] <= 1'b0;
|
||||||
m_axis_pipe_reg[0] <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
m_axis_pipe_reg[0] <= mem[rd_ptr_reg[ADDR_WIDTH-1:0]];
|
||||||
if (!empty) begin
|
if (!empty && !m_rst_sync3_reg && !m_drop_frame_reg) begin
|
||||||
// not empty, increment pointer
|
// not empty, increment pointer
|
||||||
m_axis_tvalid_pipe_reg[0] <= 1'b1;
|
m_axis_tvalid_pipe_reg[0] <= 1'b1;
|
||||||
rd_ptr_temp = rd_ptr_reg + 1;
|
rd_ptr_temp = rd_ptr_reg + 1;
|
||||||
@ -515,10 +566,50 @@ always @(posedge m_clk) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (m_axis_tvalid && LAST_ENABLE) begin
|
||||||
|
// track output frame status
|
||||||
|
if (m_axis_tlast && 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
|
||||||
|
// terminate frame
|
||||||
|
// (only for frame transfers interrupted by source reset)
|
||||||
|
m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT-1] <= 1'b1;
|
||||||
|
m_terminate_frame_reg <= 1'b1;
|
||||||
|
m_drop_frame_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (m_rst_sync3_reg && LAST_ENABLE) begin
|
||||||
|
// if source side is reset during transfer, drop partial frame
|
||||||
|
|
||||||
|
// empty output pipeline, except for last stage
|
||||||
|
if (PIPELINE_OUTPUT > 1) begin
|
||||||
|
m_axis_tvalid_pipe_reg[PIPELINE_OUTPUT-2:0] <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (m_frame_reg && (!m_axis_tvalid || (m_axis_tvalid && !m_axis_tlast)) &&
|
||||||
|
!(m_drop_frame_reg || m_terminate_frame_reg)) begin
|
||||||
|
// terminate frame
|
||||||
|
m_drop_frame_reg <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if (m_rst_sync3_reg) begin
|
if (m_rst_sync3_reg) begin
|
||||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
|
end
|
||||||
|
|
||||||
|
if (m_rst) begin
|
||||||
|
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
|
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||||
m_axis_tvalid_pipe_reg <= {PIPELINE_OUTPUT{1'b0}};
|
m_axis_tvalid_pipe_reg <= {PIPELINE_OUTPUT{1'b0}};
|
||||||
|
m_frame_reg <= 1'b0;
|
||||||
|
m_drop_frame_reg <= 1'b0;
|
||||||
|
m_terminate_frame_reg <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -321,10 +321,9 @@ axis_async_fifo #(
|
|||||||
.DROP_WHEN_FULL(DROP_WHEN_FULL)
|
.DROP_WHEN_FULL(DROP_WHEN_FULL)
|
||||||
)
|
)
|
||||||
fifo_inst (
|
fifo_inst (
|
||||||
// Common reset
|
|
||||||
.async_rst(s_rst | m_rst),
|
|
||||||
// AXI input
|
// AXI input
|
||||||
.s_clk(s_clk),
|
.s_clk(s_clk),
|
||||||
|
.s_rst(s_rst),
|
||||||
.s_axis_tdata(pre_fifo_axis_tdata),
|
.s_axis_tdata(pre_fifo_axis_tdata),
|
||||||
.s_axis_tkeep(pre_fifo_axis_tkeep),
|
.s_axis_tkeep(pre_fifo_axis_tkeep),
|
||||||
.s_axis_tvalid(pre_fifo_axis_tvalid),
|
.s_axis_tvalid(pre_fifo_axis_tvalid),
|
||||||
@ -335,6 +334,7 @@ fifo_inst (
|
|||||||
.s_axis_tuser(pre_fifo_axis_tuser),
|
.s_axis_tuser(pre_fifo_axis_tuser),
|
||||||
// AXI output
|
// AXI output
|
||||||
.m_clk(m_clk),
|
.m_clk(m_clk),
|
||||||
|
.m_rst(m_rst),
|
||||||
.m_axis_tdata(post_fifo_axis_tdata),
|
.m_axis_tdata(post_fifo_axis_tdata),
|
||||||
.m_axis_tkeep(post_fifo_axis_tkeep),
|
.m_axis_tkeep(post_fifo_axis_tkeep),
|
||||||
.m_axis_tvalid(post_fifo_axis_tvalid),
|
.m_axis_tvalid(post_fifo_axis_tvalid),
|
||||||
|
@ -26,12 +26,12 @@ proc constrain_axis_async_fifo_inst { inst } {
|
|||||||
# reset synchronization
|
# reset synchronization
|
||||||
set_false_path -from * -to [get_registers "$inst|s_rst_sync*_reg $inst|m_rst_sync*_reg"]
|
set_false_path -from * -to [get_registers "$inst|s_rst_sync*_reg $inst|m_rst_sync*_reg"]
|
||||||
|
|
||||||
if {[get_collection_size [get_registers -nowarn "$inst|s_rst_sync2_reg"]]} {
|
if {[get_collection_size [get_registers -nowarn "$inst|s_rst_sync1_reg"]]} {
|
||||||
set_max_delay -from [get_registers "$inst|s_rst_sync2_reg"] -to [get_registers "$inst|s_rst_sync3_reg"] 8.000
|
set_max_delay -from [get_registers "$inst|s_rst_sync1_reg"] -to [get_registers "$inst|s_rst_sync2_reg"] 8.000
|
||||||
}
|
}
|
||||||
|
|
||||||
if {[get_collection_size [get_registers -nowarn "$inst|m_rst_sync2_reg"]]} {
|
if {[get_collection_size [get_registers -nowarn "$inst|m_rst_sync1_reg"]]} {
|
||||||
set_max_delay -from [get_registers "$inst|m_rst_sync2_reg"] -to [get_registers "$inst|m_rst_sync3_reg"] 8.000
|
set_max_delay -from [get_registers "$inst|m_rst_sync1_reg"] -to [get_registers "$inst|m_rst_sync2_reg"] 8.000
|
||||||
}
|
}
|
||||||
|
|
||||||
# pointer synchronization
|
# pointer synchronization
|
||||||
|
@ -26,12 +26,12 @@ proc constrain_axis_async_fifo_inst { inst } {
|
|||||||
# reset synchronization
|
# reset synchronization
|
||||||
set_false_path -from * -to [get_registers "$inst|s_rst_sync*_reg $inst|m_rst_sync*_reg"]
|
set_false_path -from * -to [get_registers "$inst|s_rst_sync*_reg $inst|m_rst_sync*_reg"]
|
||||||
|
|
||||||
if {[get_collection_size [get_registers -nowarn "$inst|s_rst_sync2_reg"]]} {
|
if {[get_collection_size [get_registers -nowarn "$inst|s_rst_sync1_reg"]]} {
|
||||||
set_data_delay -from [get_registers "$inst|s_rst_sync2_reg"] -to [get_registers "$inst|s_rst_sync3_reg"] -override -get_value_from_clock_period min_clock_period -value_multiplier 0.8
|
set_data_delay -from [get_registers "$inst|s_rst_sync1_reg"] -to [get_registers "$inst|s_rst_sync2_reg"] -override -get_value_from_clock_period min_clock_period -value_multiplier 0.8
|
||||||
}
|
}
|
||||||
|
|
||||||
if {[get_collection_size [get_registers -nowarn "$inst|m_rst_sync2_reg"]]} {
|
if {[get_collection_size [get_registers -nowarn "$inst|m_rst_sync1_reg"]]} {
|
||||||
set_data_delay -from [get_registers "$inst|m_rst_sync2_reg"] -to [get_registers "$inst|m_rst_sync3_reg"] -override -get_value_from_clock_period min_clock_period -value_multiplier 0.8
|
set_data_delay -from [get_registers "$inst|m_rst_sync1_reg"] -to [get_registers "$inst|m_rst_sync2_reg"] -override -get_value_from_clock_period min_clock_period -value_multiplier 0.8
|
||||||
}
|
}
|
||||||
|
|
||||||
# pointer synchronization
|
# pointer synchronization
|
||||||
|
@ -33,21 +33,34 @@ foreach fifo_inst [get_cells -hier -filter {(ORIG_REF_NAME == axis_async_fifo ||
|
|||||||
set min_clk_period [expr $read_clk_period < $write_clk_period ? $read_clk_period : $write_clk_period]
|
set min_clk_period [expr $read_clk_period < $write_clk_period ? $read_clk_period : $write_clk_period]
|
||||||
|
|
||||||
# reset synchronization
|
# reset synchronization
|
||||||
set reset_ffs [get_cells -quiet -hier -regexp ".*/(s|m)_rst_sync\[123\]_reg_reg" -filter "PARENT == $fifo_inst"]
|
set reset_ffs [get_cells -quiet -hier -regexp ".*/s_rst_sync\[123\]_reg_reg" -filter "PARENT == $fifo_inst"]
|
||||||
|
|
||||||
if {[llength $reset_ffs]} {
|
if {[llength $reset_ffs]} {
|
||||||
set_property ASYNC_REG TRUE $reset_ffs
|
set_property ASYNC_REG TRUE $reset_ffs
|
||||||
set_false_path -to [get_pins -of_objects $reset_ffs -filter {IS_PRESET || IS_RESET}]
|
|
||||||
|
# hunt down source
|
||||||
|
set dest [get_cells $fifo_inst/s_rst_sync2_reg_reg]
|
||||||
|
set dest_pins [get_pins -of_objects $dest -filter {REF_PIN_NAME == D}]
|
||||||
|
set net [get_nets -segments -of_objects $dest_pins]
|
||||||
|
set source_pins [get_pins -of_objects $net -filter {IS_LEAF && DIRECTION == OUT}]
|
||||||
|
set source [get_cells -of_objects $source_pins]
|
||||||
|
|
||||||
|
set_max_delay -from $source -to $dest -datapath_only $read_clk_period
|
||||||
}
|
}
|
||||||
|
|
||||||
if {[llength [get_cells -quiet $fifo_inst/s_rst_sync2_reg_reg]]} {
|
set reset_ffs [get_cells -quiet -hier -regexp ".*/m_rst_sync\[123\]_reg_reg" -filter "PARENT == $fifo_inst"]
|
||||||
set_false_path -to [get_pins $fifo_inst/s_rst_sync2_reg_reg/D]
|
|
||||||
set_max_delay -from [get_cells $fifo_inst/s_rst_sync2_reg_reg] -to [get_cells $fifo_inst/s_rst_sync3_reg_reg] $min_clk_period
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[llength [get_cells -quiet $fifo_inst/m_rst_sync2_reg_reg]]} {
|
if {[llength $reset_ffs]} {
|
||||||
set_false_path -to [get_pins $fifo_inst/m_rst_sync2_reg_reg/D]
|
set_property ASYNC_REG TRUE $reset_ffs
|
||||||
set_max_delay -from [get_cells $fifo_inst/m_rst_sync2_reg_reg] -to [get_cells $fifo_inst/m_rst_sync3_reg_reg] $min_clk_period
|
|
||||||
|
# hunt down source
|
||||||
|
set dest [get_cells $fifo_inst/m_rst_sync2_reg_reg]
|
||||||
|
set dest_pins [get_pins -of_objects $dest -filter {REF_PIN_NAME == D}]
|
||||||
|
set net [get_nets -segments -of_objects $dest_pins]
|
||||||
|
set source_pins [get_pins -of_objects $net -filter {IS_LEAF && DIRECTION == OUT}]
|
||||||
|
set source [get_cells -of_objects $source_pins]
|
||||||
|
|
||||||
|
set_max_delay -from $source -to $dest -datapath_only $write_clk_period
|
||||||
}
|
}
|
||||||
|
|
||||||
# pointer synchronization
|
# pointer synchronization
|
||||||
|
@ -52,8 +52,8 @@ class TB(object):
|
|||||||
cocotb.fork(Clock(dut.s_clk, s_clk, units="ns").start())
|
cocotb.fork(Clock(dut.s_clk, s_clk, units="ns").start())
|
||||||
cocotb.fork(Clock(dut.m_clk, m_clk, units="ns").start())
|
cocotb.fork(Clock(dut.m_clk, m_clk, units="ns").start())
|
||||||
|
|
||||||
self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.s_clk, dut.async_rst)
|
self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.s_clk, dut.s_rst)
|
||||||
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.m_clk, dut.async_rst)
|
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.m_clk, dut.m_rst)
|
||||||
|
|
||||||
def set_idle_generator(self, generator=None):
|
def set_idle_generator(self, generator=None):
|
||||||
if generator:
|
if generator:
|
||||||
@ -64,16 +64,41 @@ class TB(object):
|
|||||||
self.sink.set_pause_generator(generator())
|
self.sink.set_pause_generator(generator())
|
||||||
|
|
||||||
async def reset(self):
|
async def reset(self):
|
||||||
self.dut.async_rst.setimmediatevalue(0)
|
self.dut.m_rst.setimmediatevalue(0)
|
||||||
|
self.dut.s_rst.setimmediatevalue(0)
|
||||||
for k in range(10):
|
for k in range(10):
|
||||||
await RisingEdge(self.dut.s_clk)
|
await RisingEdge(self.dut.s_clk)
|
||||||
self.dut.async_rst <= 1
|
self.dut.m_rst <= 1
|
||||||
|
self.dut.s_rst <= 1
|
||||||
for k in range(10):
|
for k in range(10):
|
||||||
await RisingEdge(self.dut.s_clk)
|
await RisingEdge(self.dut.s_clk)
|
||||||
self.dut.async_rst <= 0
|
self.dut.m_rst <= 0
|
||||||
|
self.dut.s_rst <= 0
|
||||||
for k in range(10):
|
for k in range(10):
|
||||||
await RisingEdge(self.dut.s_clk)
|
await RisingEdge(self.dut.s_clk)
|
||||||
|
|
||||||
|
async def reset_source(self):
|
||||||
|
self.dut.s_rst.setimmediatevalue(0)
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.s_clk)
|
||||||
|
self.dut.s_rst <= 1
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.s_clk)
|
||||||
|
self.dut.s_rst <= 0
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.s_clk)
|
||||||
|
|
||||||
|
async def reset_sink(self):
|
||||||
|
self.dut.m_rst.setimmediatevalue(0)
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.m_clk)
|
||||||
|
self.dut.m_rst <= 1
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.m_clk)
|
||||||
|
self.dut.m_rst <= 0
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.m_clk)
|
||||||
|
|
||||||
|
|
||||||
async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None):
|
async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None):
|
||||||
|
|
||||||
@ -190,7 +215,179 @@ async def run_test_init_sink_pause_reset(dut):
|
|||||||
for k in range(64):
|
for k in range(64):
|
||||||
await RisingEdge(dut.s_clk)
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
assert tb.sink.empty()
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_init_sink_pause_source_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
tb.sink.pause = True
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 32))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_source()
|
||||||
|
|
||||||
|
tb.sink.pause = False
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
rx_frame = await tb.sink.recv()
|
||||||
|
|
||||||
|
assert rx_frame.tuser
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_init_sink_pause_sink_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
tb.sink.pause = True
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 32))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_sink()
|
||||||
|
|
||||||
|
tb.sink.pause = False
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_shift_in_source_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 256))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
for k in range(8):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_source()
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
if int(os.getenv("PARAM_FRAME_FIFO")):
|
||||||
|
assert tb.sink.empty()
|
||||||
|
else:
|
||||||
|
rx_frame = await tb.sink.recv()
|
||||||
|
|
||||||
|
assert rx_frame.tuser
|
||||||
|
|
||||||
|
assert tb.sink.empty()
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_shift_in_sink_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 256))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
for k in range(8):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_sink()
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_shift_out_source_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 256))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
await RisingEdge(dut.m_axis_tvalid)
|
||||||
|
|
||||||
|
for k in range(8):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_source()
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
rx_frame = await tb.sink.recv()
|
||||||
|
|
||||||
|
assert rx_frame.tuser
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_shift_out_sink_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 256))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
await RisingEdge(dut.m_axis_tvalid)
|
||||||
|
|
||||||
|
for k in range(8):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_sink()
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
await RisingEdge(dut.s_clk)
|
await RisingEdge(dut.s_clk)
|
||||||
await RisingEdge(dut.s_clk)
|
await RisingEdge(dut.s_clk)
|
||||||
@ -298,6 +495,12 @@ if cocotb.SIM_NAME:
|
|||||||
run_test_tuser_assert,
|
run_test_tuser_assert,
|
||||||
run_test_init_sink_pause,
|
run_test_init_sink_pause,
|
||||||
run_test_init_sink_pause_reset,
|
run_test_init_sink_pause_reset,
|
||||||
|
run_test_init_sink_pause_source_reset,
|
||||||
|
run_test_init_sink_pause_sink_reset,
|
||||||
|
run_test_shift_in_source_reset,
|
||||||
|
run_test_shift_in_sink_reset,
|
||||||
|
run_test_shift_out_source_reset,
|
||||||
|
run_test_shift_out_sink_reset,
|
||||||
run_test_overflow
|
run_test_overflow
|
||||||
]:
|
]:
|
||||||
|
|
||||||
|
@ -74,6 +74,28 @@ class TB(object):
|
|||||||
for k in range(10):
|
for k in range(10):
|
||||||
await RisingEdge(self.dut.s_clk)
|
await RisingEdge(self.dut.s_clk)
|
||||||
|
|
||||||
|
async def reset_source(self):
|
||||||
|
self.dut.s_rst.setimmediatevalue(0)
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.s_clk)
|
||||||
|
self.dut.s_rst <= 1
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.s_clk)
|
||||||
|
self.dut.s_rst <= 0
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.s_clk)
|
||||||
|
|
||||||
|
async def reset_sink(self):
|
||||||
|
self.dut.m_rst.setimmediatevalue(0)
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.m_clk)
|
||||||
|
self.dut.m_rst <= 1
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.m_clk)
|
||||||
|
self.dut.m_rst <= 0
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.m_clk)
|
||||||
|
|
||||||
|
|
||||||
async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None):
|
async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None):
|
||||||
|
|
||||||
@ -190,7 +212,179 @@ async def run_test_init_sink_pause_reset(dut):
|
|||||||
for k in range(64):
|
for k in range(64):
|
||||||
await RisingEdge(dut.s_clk)
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
assert tb.sink.empty()
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_init_sink_pause_source_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
tb.sink.pause = True
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 32))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_source()
|
||||||
|
|
||||||
|
tb.sink.pause = False
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
rx_frame = await tb.sink.recv()
|
||||||
|
|
||||||
|
assert rx_frame.tuser
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_init_sink_pause_sink_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
tb.sink.pause = True
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 32))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_sink()
|
||||||
|
|
||||||
|
tb.sink.pause = False
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_shift_in_source_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 256))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
for k in range(8):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_source()
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
if int(os.getenv("PARAM_FRAME_FIFO")):
|
||||||
|
assert tb.sink.empty()
|
||||||
|
else:
|
||||||
|
rx_frame = await tb.sink.recv()
|
||||||
|
|
||||||
|
assert rx_frame.tuser
|
||||||
|
|
||||||
|
assert tb.sink.empty()
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_shift_in_sink_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 256))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
for k in range(8):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_sink()
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_shift_out_source_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 256))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
await RisingEdge(dut.m_axis_tvalid)
|
||||||
|
|
||||||
|
for k in range(8):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_source()
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
rx_frame = await tb.sink.recv()
|
||||||
|
|
||||||
|
assert rx_frame.tuser
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_shift_out_sink_reset(dut):
|
||||||
|
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
test_data = bytearray(itertools.islice(itertools.cycle(range(256)), 256))
|
||||||
|
test_frame = AxiStreamFrame(test_data)
|
||||||
|
await tb.source.send(test_frame)
|
||||||
|
|
||||||
|
await RisingEdge(dut.m_axis_tvalid)
|
||||||
|
|
||||||
|
for k in range(8):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
await tb.reset_sink()
|
||||||
|
|
||||||
|
for k in range(64):
|
||||||
|
await RisingEdge(dut.s_clk)
|
||||||
|
|
||||||
|
assert tb.sink.idle()
|
||||||
|
|
||||||
await RisingEdge(dut.s_clk)
|
await RisingEdge(dut.s_clk)
|
||||||
await RisingEdge(dut.s_clk)
|
await RisingEdge(dut.s_clk)
|
||||||
@ -298,6 +492,12 @@ if cocotb.SIM_NAME:
|
|||||||
run_test_tuser_assert,
|
run_test_tuser_assert,
|
||||||
run_test_init_sink_pause,
|
run_test_init_sink_pause,
|
||||||
run_test_init_sink_pause_reset,
|
run_test_init_sink_pause_reset,
|
||||||
|
run_test_init_sink_pause_source_reset,
|
||||||
|
run_test_init_sink_pause_sink_reset,
|
||||||
|
run_test_shift_in_source_reset,
|
||||||
|
run_test_shift_in_sink_reset,
|
||||||
|
run_test_shift_out_source_reset,
|
||||||
|
run_test_shift_out_sink_reset,
|
||||||
run_test_overflow
|
run_test_overflow
|
||||||
]:
|
]:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user