From 10da93fec4b6009a5f9544800ef9e216586f4703 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 26 Jul 2023 20:02:43 -0700 Subject: [PATCH] Add depth status outputs to FIFOs Signed-off-by: Alex Forencich --- rtl/axis_async_fifo.v | 52 +++++++++++++++++++++++++++++++---- rtl/axis_async_fifo_adapter.v | 8 ++++++ rtl/axis_fifo.v | 12 ++++++++ rtl/axis_fifo_adapter.v | 4 +++ 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/rtl/axis_async_fifo.v b/rtl/axis_async_fifo.v index 000a80816..b56af5b02 100644 --- a/rtl/axis_async_fifo.v +++ b/rtl/axis_async_fifo.v @@ -114,9 +114,13 @@ module axis_async_fifo # /* * Status */ + output wire [$clog2(DEPTH):0] s_status_depth, + output wire [$clog2(DEPTH):0] s_status_depth_commit, output wire s_status_overflow, output wire s_status_bad_frame, output wire s_status_good_frame, + output wire [$clog2(DEPTH):0] m_status_depth, + output wire [$clog2(DEPTH):0] m_status_depth_commit, output wire m_status_overflow, output wire m_status_bad_frame, output wire m_status_good_frame @@ -161,12 +165,25 @@ localparam DEST_OFFSET = ID_OFFSET + (ID_ENABLE ? ID_WIDTH : 0); localparam USER_OFFSET = DEST_OFFSET + (DEST_ENABLE ? DEST_WIDTH : 0); localparam WIDTH = USER_OFFSET + (USER_ENABLE ? USER_WIDTH : 0); +function [ADDR_WIDTH:0] bin2gray(input [ADDR_WIDTH:0] b); + bin2gray = b ^ (b >> 1); +endfunction + +function [ADDR_WIDTH:0] gray2bin(input [ADDR_WIDTH:0] g); + integer i; + for (i = 0; i <= ADDR_WIDTH; i = i + 1) begin + gray2bin[i] = ^(g >> i); + end +endfunction + reg [ADDR_WIDTH:0] wr_ptr_reg = {ADDR_WIDTH+1{1'b0}}; reg [ADDR_WIDTH:0] wr_ptr_commit_reg = {ADDR_WIDTH+1{1'b0}}; reg [ADDR_WIDTH:0] wr_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}; reg [ADDR_WIDTH:0] wr_ptr_sync_commit_reg = {ADDR_WIDTH+1{1'b0}}; reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}; reg [ADDR_WIDTH:0] rd_ptr_gray_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] wr_ptr_conv_reg = {ADDR_WIDTH+1{1'b0}}; +reg [ADDR_WIDTH:0] rd_ptr_conv_reg = {ADDR_WIDTH+1{1'b0}}; reg [ADDR_WIDTH:0] wr_ptr_temp; reg [ADDR_WIDTH:0] rd_ptr_temp; @@ -241,6 +258,11 @@ reg good_frame_reg = 1'b0; reg m_drop_frame_reg = 1'b0; reg m_terminate_frame_reg = 1'b0; +reg [ADDR_WIDTH:0] s_depth_reg = 0; +reg [ADDR_WIDTH:0] s_depth_commit_reg = 0; +reg [ADDR_WIDTH:0] m_depth_reg = 0; +reg [ADDR_WIDTH:0] m_depth_commit_reg = 0; + reg overflow_sync1_reg = 1'b0; reg overflow_sync2_reg = 1'b0; reg overflow_sync3_reg = 1'b0; @@ -280,10 +302,14 @@ wire [USER_WIDTH-1:0] m_axis_tuser_pipe = USER_ENABLE ? (m_terminate_frame_reg wire pipe_ready; +assign s_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {s_depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : s_depth_reg; +assign s_status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {s_depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : s_depth_commit_reg; assign s_status_overflow = overflow_reg; assign s_status_bad_frame = bad_frame_reg; assign s_status_good_frame = good_frame_reg; +assign m_status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {m_depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : m_depth_reg; +assign m_status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {m_depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : m_depth_commit_reg; assign m_status_overflow = overflow_sync3_reg ^ overflow_sync4_reg; 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; @@ -363,7 +389,7 @@ always @(posedge s_clk) begin wr_ptr_temp = wr_ptr_reg + 1; wr_ptr_reg <= wr_ptr_temp; wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1); + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); end end else if ((full && DROP_WHEN_FULL) || (full_wr && DROP_OVERSIZE_FRAME) || drop_frame_reg) begin // full, packet overflow, or currently dropping frame @@ -373,7 +399,7 @@ always @(posedge s_clk) begin // end of frame, reset write pointer wr_ptr_temp = wr_ptr_commit_reg; wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1); + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); drop_frame_reg <= 1'b0; overflow_reg <= 1'b1; end @@ -381,7 +407,7 @@ always @(posedge s_clk) begin mem[wr_ptr_reg[ADDR_WIDTH-1:0]] <= s_axis; wr_ptr_temp = wr_ptr_reg + 1; wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1); + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); if (s_axis_tlast || (!DROP_OVERSIZE_FRAME && (full_wr || send_frame_reg))) begin // end of frame or send frame send_frame_reg <= !s_axis_tlast; @@ -389,14 +415,14 @@ always @(posedge s_clk) begin // bad packet, reset write pointer wr_ptr_temp = wr_ptr_commit_reg; wr_ptr_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1); + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); bad_frame_reg <= 1'b1; end else begin // good packet or packet overflow, update write pointer wr_ptr_temp = wr_ptr_reg + 1; wr_ptr_reg <= wr_ptr_temp; wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1); + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin // no sync in progress; sync update @@ -419,7 +445,7 @@ always @(posedge s_clk) begin wr_ptr_temp = wr_ptr_reg; wr_ptr_reg <= wr_ptr_temp; wr_ptr_commit_reg <= wr_ptr_temp; - wr_ptr_gray_reg <= wr_ptr_temp ^ (wr_ptr_temp >> 1); + wr_ptr_gray_reg <= bin2gray(wr_ptr_temp); if (wr_ptr_update_reg == wr_ptr_update_ack_sync2_reg) begin // no sync in progress; sync update @@ -461,6 +487,13 @@ always @(posedge s_clk) begin end end +// Write-side status +always @(posedge s_clk) begin + rd_ptr_conv_reg <= gray2bin(rd_ptr_gray_sync2_reg); + s_depth_reg <= wr_ptr_reg - rd_ptr_conv_reg; + s_depth_commit_reg <= wr_ptr_commit_reg - rd_ptr_conv_reg; +end + // pointer synchronization always @(posedge s_clk) begin rd_ptr_gray_sync1_reg <= rd_ptr_gray_reg; @@ -616,6 +649,13 @@ always @(posedge m_clk) begin end end +// Read-side status +always @(posedge m_clk) begin + wr_ptr_conv_reg <= gray2bin(wr_ptr_gray_sync2_reg); + m_depth_reg <= wr_ptr_conv_reg - rd_ptr_reg; + m_depth_commit_reg <= FRAME_FIFO ? wr_ptr_commit_sync_reg - rd_ptr_reg : wr_ptr_conv_reg - rd_ptr_reg; +end + generate if (!OUTPUT_FIFO_ENABLE) begin diff --git a/rtl/axis_async_fifo_adapter.v b/rtl/axis_async_fifo_adapter.v index c8d1692be..8bb69d2bc 100644 --- a/rtl/axis_async_fifo_adapter.v +++ b/rtl/axis_async_fifo_adapter.v @@ -119,9 +119,13 @@ module axis_async_fifo_adapter # /* * Status */ + output wire [$clog2(DEPTH):0] s_status_depth, + output wire [$clog2(DEPTH):0] s_status_depth_commit, output wire s_status_overflow, output wire s_status_bad_frame, output wire s_status_good_frame, + output wire [$clog2(DEPTH):0] m_status_depth, + output wire [$clog2(DEPTH):0] m_status_depth_commit, output wire m_status_overflow, output wire m_status_bad_frame, output wire m_status_good_frame @@ -350,9 +354,13 @@ fifo_inst ( .m_axis_tdest(post_fifo_axis_tdest), .m_axis_tuser(post_fifo_axis_tuser), // Status + .s_status_depth(s_status_depth), + .s_status_depth_commit(s_status_depth_commit), .s_status_overflow(s_status_overflow), .s_status_bad_frame(s_status_bad_frame), .s_status_good_frame(s_status_good_frame), + .m_status_depth(m_status_depth), + .m_status_depth_commit(m_status_depth_commit), .m_status_overflow(m_status_overflow), .m_status_bad_frame(m_status_bad_frame), .m_status_good_frame(m_status_good_frame) diff --git a/rtl/axis_fifo.v b/rtl/axis_fifo.v index 6dba3cd6f..a0f2df395 100644 --- a/rtl/axis_fifo.v +++ b/rtl/axis_fifo.v @@ -113,6 +113,8 @@ module axis_fifo # /* * Status */ + output wire [$clog2(DEPTH):0] status_depth, + output wire [$clog2(DEPTH):0] status_depth_commit, output wire status_overflow, output wire status_bad_frame, output wire status_good_frame @@ -178,6 +180,8 @@ wire full_wr = wr_ptr_reg == (wr_ptr_commit_reg ^ {1'b1, {ADDR_WIDTH{1'b0}}}); reg drop_frame_reg = 1'b0; reg send_frame_reg = 1'b0; +reg [ADDR_WIDTH:0] depth_reg = 0; +reg [ADDR_WIDTH:0] depth_commit_reg = 0; reg overflow_reg = 1'b0; reg bad_frame_reg = 1'b0; reg good_frame_reg = 1'b0; @@ -208,6 +212,8 @@ wire [USER_WIDTH-1:0] m_axis_tuser_pipe = USER_ENABLE ? m_axis[USER_OFFSET +: wire pipe_ready; +assign status_depth = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {depth_reg, {$clog2(KEEP_WIDTH){1'b0}}} : depth_reg; +assign status_depth_commit = (KEEP_ENABLE && KEEP_WIDTH > 1) ? {depth_commit_reg, {$clog2(KEEP_WIDTH){1'b0}}} : depth_commit_reg; assign status_overflow = overflow_reg; assign status_bad_frame = bad_frame_reg; assign status_good_frame = good_frame_reg; @@ -272,6 +278,12 @@ always @(posedge clk) begin end end +// Status +always @(posedge clk) begin + depth_reg <= wr_ptr_reg - rd_ptr_reg; + depth_commit_reg <= wr_ptr_commit_reg - rd_ptr_reg; +end + // Read logic integer j; diff --git a/rtl/axis_fifo_adapter.v b/rtl/axis_fifo_adapter.v index 88d4d9547..4fa6776ae 100644 --- a/rtl/axis_fifo_adapter.v +++ b/rtl/axis_fifo_adapter.v @@ -118,6 +118,8 @@ module axis_fifo_adapter # /* * Status */ + output wire [$clog2(DEPTH):0] status_depth, + output wire [$clog2(DEPTH):0] status_depth_commit, output wire status_overflow, output wire status_bad_frame, output wire status_good_frame @@ -343,6 +345,8 @@ fifo_inst ( .m_axis_tdest(post_fifo_axis_tdest), .m_axis_tuser(post_fifo_axis_tuser), // Status + .status_depth(status_depth), + .status_depth_commit(status_depth_commit), .status_overflow(status_overflow), .status_bad_frame(status_bad_frame), .status_good_frame(status_good_frame)