mirror of
https://github.com/fpganinja/taxi.git
synced 2025-12-09 17:08:38 -08:00
axis: Use reset synchronizer module in AXI stream async FIFO
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
3
rtl/axis/taxi_axis_async_fifo.f
Normal file
3
rtl/axis/taxi_axis_async_fifo.f
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
taxi_axis_async_fifo.sv
|
||||||
|
../sync/taxi_sync_reset.sv
|
||||||
|
taxi_axis_if.sv
|
||||||
@@ -196,18 +196,8 @@ logic wr_ptr_update_ack_sync1_reg = 1'b0;
|
|||||||
(* SHREG_EXTRACT = "NO" *)
|
(* SHREG_EXTRACT = "NO" *)
|
||||||
logic wr_ptr_update_ack_sync2_reg = 1'b0;
|
logic wr_ptr_update_ack_sync2_reg = 1'b0;
|
||||||
|
|
||||||
(* SHREG_EXTRACT = "NO" *)
|
wire s_rst_sync;
|
||||||
logic s_rst_sync1_reg = 1'b1;
|
wire m_rst_sync;
|
||||||
(* SHREG_EXTRACT = "NO" *)
|
|
||||||
logic s_rst_sync2_reg = 1'b1;
|
|
||||||
(* SHREG_EXTRACT = "NO" *)
|
|
||||||
logic s_rst_sync3_reg = 1'b1;
|
|
||||||
(* SHREG_EXTRACT = "NO" *)
|
|
||||||
logic m_rst_sync1_reg = 1'b1;
|
|
||||||
(* SHREG_EXTRACT = "NO" *)
|
|
||||||
logic m_rst_sync2_reg = 1'b1;
|
|
||||||
(* SHREG_EXTRACT = "NO" *)
|
|
||||||
logic m_rst_sync3_reg = 1'b1;
|
|
||||||
|
|
||||||
(* ramstyle = "no_rw_check" *)
|
(* ramstyle = "no_rw_check" *)
|
||||||
logic [WIDTH-1:0] mem[(2**FIFO_AW)-1:0];
|
logic [WIDTH-1:0] mem[(2**FIFO_AW)-1:0];
|
||||||
@@ -261,7 +251,7 @@ logic good_frame_sync2_reg = 1'b0;
|
|||||||
logic good_frame_sync3_reg = 1'b0;
|
logic good_frame_sync3_reg = 1'b0;
|
||||||
logic good_frame_sync4_reg = 1'b0;
|
logic good_frame_sync4_reg = 1'b0;
|
||||||
|
|
||||||
assign s_axis.tready = (FRAME_FIFO ? (!full || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : (!full || MARK_WHEN_FULL)) && !s_rst_sync3_reg;
|
assign s_axis.tready = (FRAME_FIFO ? (!full || (full_wr && DROP_OVERSIZE_FRAME) || DROP_WHEN_FULL) : (!full || MARK_WHEN_FULL)) && !s_rst_sync;
|
||||||
|
|
||||||
wire [WIDTH-1:0] mem_wr_data;
|
wire [WIDTH-1:0] mem_wr_data;
|
||||||
|
|
||||||
@@ -350,31 +340,23 @@ 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_ff @(posedge m_clk or posedge m_rst) begin
|
taxi_sync_reset #(
|
||||||
if (m_rst) begin
|
.N(4)
|
||||||
s_rst_sync1_reg <= 1'b1;
|
)
|
||||||
end else begin
|
s_reset_sync_inst (
|
||||||
s_rst_sync1_reg <= 1'b0;
|
.clk(s_clk),
|
||||||
end
|
.rst(m_rst),
|
||||||
end
|
.out(s_rst_sync)
|
||||||
|
);
|
||||||
|
|
||||||
always_ff @(posedge s_clk) begin
|
taxi_sync_reset #(
|
||||||
s_rst_sync2_reg <= s_rst_sync1_reg;
|
.N(4)
|
||||||
s_rst_sync3_reg <= s_rst_sync2_reg;
|
)
|
||||||
end
|
m_reset_sync_inst (
|
||||||
|
.clk(m_clk),
|
||||||
always_ff @(posedge s_clk or posedge s_rst) begin
|
.rst(s_rst),
|
||||||
if (s_rst) begin
|
.out(m_rst_sync)
|
||||||
m_rst_sync1_reg <= 1'b1;
|
);
|
||||||
end else begin
|
|
||||||
m_rst_sync1_reg <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(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_ff @(posedge s_clk) begin
|
always_ff @(posedge s_clk) begin
|
||||||
@@ -397,7 +379,7 @@ always_ff @(posedge s_clk) begin
|
|||||||
s_frame_reg <= !s_axis.tlast;
|
s_frame_reg <= !s_axis.tlast;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (s_rst_sync3_reg && LAST_EN) begin
|
if (s_rst_sync && LAST_EN) begin
|
||||||
// if sink side is reset during transfer, drop partial frame
|
// if sink side is reset during transfer, drop partial frame
|
||||||
if (s_frame_reg && !(s_axis.tready && s_axis.tvalid && s_axis.tlast)) begin
|
if (s_frame_reg && !(s_axis.tready && s_axis.tvalid && s_axis.tlast)) begin
|
||||||
drop_frame_reg <= 1'b1;
|
drop_frame_reg <= 1'b1;
|
||||||
@@ -525,7 +507,7 @@ always_ff @(posedge s_clk) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (s_rst_sync3_reg) begin
|
if (s_rst_sync) begin
|
||||||
wr_ptr_reg <= '0;
|
wr_ptr_reg <= '0;
|
||||||
wr_ptr_commit_reg <= '0;
|
wr_ptr_commit_reg <= '0;
|
||||||
wr_ptr_gray_reg <= '0;
|
wr_ptr_gray_reg <= '0;
|
||||||
@@ -587,7 +569,7 @@ always_ff @(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 (FRAME_FIFO && m_rst_sync3_reg) begin
|
if (FRAME_FIFO && m_rst_sync) begin
|
||||||
wr_ptr_gray_sync1_reg <= '0;
|
wr_ptr_gray_sync1_reg <= '0;
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -660,7 +642,7 @@ always_ff @(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
|
||||||
mem_rd_valid_pipe_reg[0] <= 1'b0;
|
mem_rd_valid_pipe_reg[0] <= 1'b0;
|
||||||
mem_rd_data_pipe_reg[0] <= mem[rd_ptr_reg[FIFO_AW-1:0]];
|
mem_rd_data_pipe_reg[0] <= mem[rd_ptr_reg[FIFO_AW-1:0]];
|
||||||
if (!empty && !m_rst_sync3_reg && !m_empty_pipe_reg && pipe_ready) begin
|
if (!empty && !m_rst_sync && !m_empty_pipe_reg && pipe_ready) begin
|
||||||
// not empty, increment pointer
|
// not empty, increment pointer
|
||||||
mem_rd_valid_pipe_reg[0] <= 1'b1;
|
mem_rd_valid_pipe_reg[0] <= 1'b1;
|
||||||
rd_ptr_temp = rd_ptr_reg + 1;
|
rd_ptr_temp = rd_ptr_reg + 1;
|
||||||
@@ -688,12 +670,12 @@ always_ff @(posedge m_clk) begin
|
|||||||
m_empty_pipe_reg <= 1'b0;
|
m_empty_pipe_reg <= 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (m_rst_sync3_reg && LAST_EN) begin
|
if (m_rst_sync && LAST_EN) begin
|
||||||
// if source side is reset during transfer, drop partial frame
|
// if source side is reset during transfer, drop partial frame
|
||||||
m_empty_pipe_reg <= 1'b1;
|
m_empty_pipe_reg <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (m_rst_sync3_reg) begin
|
if (m_rst_sync) begin
|
||||||
rd_ptr_reg <= '0;
|
rd_ptr_reg <= '0;
|
||||||
rd_ptr_gray_reg <= '0;
|
rd_ptr_gray_reg <= '0;
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
taxi_axis_async_fifo_adapter.sv
|
taxi_axis_async_fifo_adapter.sv
|
||||||
taxi_axis_async_fifo.sv
|
taxi_axis_async_fifo.f
|
||||||
taxi_axis_adapter.sv
|
taxi_axis_adapter.sv
|
||||||
taxi_axis_if.sv
|
|
||||||
|
|||||||
@@ -20,37 +20,6 @@ foreach fifo_inst [get_cells -hier -filter {(ORIG_REF_NAME == taxi_axis_async_fi
|
|||||||
|
|
||||||
set min_clk_period [expr min($write_clk_period, $read_clk_period)]
|
set min_clk_period [expr min($write_clk_period, $read_clk_period)]
|
||||||
|
|
||||||
# reset synchronization
|
|
||||||
set reset_ffs [get_cells -quiet -hier -regexp ".*/s_rst_sync\[23\]_reg_reg" -filter "PARENT == $fifo_inst"]
|
|
||||||
|
|
||||||
if {[llength $reset_ffs]} {
|
|
||||||
set_property ASYNC_REG TRUE $reset_ffs
|
|
||||||
|
|
||||||
# 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
|
|
||||||
}
|
|
||||||
|
|
||||||
set reset_ffs [get_cells -quiet -hier -regexp ".*/m_rst_sync\[23\]_reg_reg" -filter "PARENT == $fifo_inst"]
|
|
||||||
|
|
||||||
if {[llength $reset_ffs]} {
|
|
||||||
set_property ASYNC_REG TRUE $reset_ffs
|
|
||||||
|
|
||||||
# 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
|
||||||
set sync_ffs [get_cells -quiet -hier -regexp ".*/rd_ptr_gray_sync\[12\]_reg_reg\\\[\\d+\\\]" -filter "PARENT == $fifo_inst"]
|
set sync_ffs [get_cells -quiet -hier -regexp ".*/rd_ptr_gray_sync\[12\]_reg_reg\\\[\\d+\\\]" -filter "PARENT == $fifo_inst"]
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ COCOTB_TOPLEVEL = test_$(DUT)
|
|||||||
MODULE = $(COCOTB_TEST_MODULES)
|
MODULE = $(COCOTB_TEST_MODULES)
|
||||||
TOPLEVEL = $(COCOTB_TOPLEVEL)
|
TOPLEVEL = $(COCOTB_TOPLEVEL)
|
||||||
VERILOG_SOURCES += $(COCOTB_TOPLEVEL).sv
|
VERILOG_SOURCES += $(COCOTB_TOPLEVEL).sv
|
||||||
VERILOG_SOURCES += ../../../rtl/axis/$(DUT).sv
|
VERILOG_SOURCES += ../../../rtl/axis/$(DUT).f
|
||||||
VERILOG_SOURCES += ../../../rtl/axis/taxi_axis_if.sv
|
|
||||||
|
|
||||||
# handle file list files
|
# handle file list files
|
||||||
process_f_file = $(call process_f_files,$(addprefix $(dir $1),$(shell cat $1)))
|
process_f_file = $(call process_f_files,$(addprefix $(dir $1),$(shell cat $1)))
|
||||||
|
|||||||
@@ -682,8 +682,7 @@ def test_taxi_axis_async_fifo(request, data_w, ram_pipeline, output_fifo,
|
|||||||
|
|
||||||
verilog_sources = [
|
verilog_sources = [
|
||||||
os.path.join(tests_dir, f"{toplevel}.sv"),
|
os.path.join(tests_dir, f"{toplevel}.sv"),
|
||||||
os.path.join(rtl_dir, "axis", f"{dut}.sv"),
|
os.path.join(rtl_dir, "axis", f"{dut}.f"),
|
||||||
os.path.join(rtl_dir, "axis", "taxi_axis_if.sv"),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
verilog_sources = process_f_files(verilog_sources)
|
verilog_sources = process_f_files(verilog_sources)
|
||||||
|
|||||||
Reference in New Issue
Block a user