util_axis_fifo: Add room and level outputs

Add a room output on the input side that reports how many free entries the
FIFO has and a level output on the output side that reports how many valid
entries are in the FIFO.

Note that the level output is only accurate if the output of the FIFO is not
registered, otherwise it might be off by one.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
main
Lars-Peter Clausen 2015-04-09 14:32:44 +02:00
parent ae4e7a0c37
commit 762fa3290b
4 changed files with 36 additions and 12 deletions

View File

@ -42,13 +42,15 @@ module fifo_address_gray (
input m_axis_ready, input m_axis_ready,
output reg m_axis_valid, output reg m_axis_valid,
output [C_ADDRESS_WIDTH-1:0] m_axis_raddr_next, output [C_ADDRESS_WIDTH-1:0] m_axis_raddr_next,
output reg [C_ADDRESS_WIDTH:0] m_axis_level,
input s_axis_aclk, input s_axis_aclk,
input s_axis_aresetn, input s_axis_aresetn,
output reg s_axis_ready, output reg s_axis_ready,
input s_axis_valid, input s_axis_valid,
output reg s_axis_empty, output reg s_axis_empty,
output [C_ADDRESS_WIDTH-1:0] s_axis_waddr output [C_ADDRESS_WIDTH-1:0] s_axis_waddr,
output reg [C_ADDRESS_WIDTH:0] s_axis_room
); );
parameter C_ADDRESS_WIDTH = 4; parameter C_ADDRESS_WIDTH = 4;

View File

@ -43,13 +43,15 @@ module fifo_address_gray_pipelined (
output reg m_axis_valid, output reg m_axis_valid,
output [C_ADDRESS_WIDTH-1:0] m_axis_raddr_next, output [C_ADDRESS_WIDTH-1:0] m_axis_raddr_next,
output [C_ADDRESS_WIDTH-1:0] m_axis_raddr, output [C_ADDRESS_WIDTH-1:0] m_axis_raddr,
output reg [C_ADDRESS_WIDTH:0] m_axis_level,
input s_axis_aclk, input s_axis_aclk,
input s_axis_aresetn, input s_axis_aresetn,
output reg s_axis_ready, output reg s_axis_ready,
input s_axis_valid, input s_axis_valid,
output reg s_axis_empty, output reg s_axis_empty,
output [C_ADDRESS_WIDTH-1:0] s_axis_waddr output [C_ADDRESS_WIDTH-1:0] s_axis_waddr,
output reg [C_ADDRESS_WIDTH:0] s_axis_room
); );
parameter C_ADDRESS_WIDTH = 4; parameter C_ADDRESS_WIDTH = 4;
@ -127,19 +129,23 @@ begin
if (s_axis_aresetn == 1'b0) begin if (s_axis_aresetn == 1'b0) begin
s_axis_ready <= 1'b1; s_axis_ready <= 1'b1;
s_axis_empty <= 1'b1; s_axis_empty <= 1'b1;
s_axis_room <= 2**C_ADDRESS_WIDTH;
end else begin end else begin
s_axis_ready <= (_s_axis_raddr[C_ADDRESS_WIDTH] == _s_axis_waddr_next[C_ADDRESS_WIDTH] || s_axis_ready <= (_s_axis_raddr[C_ADDRESS_WIDTH] == _s_axis_waddr_next[C_ADDRESS_WIDTH] ||
_s_axis_raddr[C_ADDRESS_WIDTH-1:0] != _s_axis_waddr_next[C_ADDRESS_WIDTH-1:0]); _s_axis_raddr[C_ADDRESS_WIDTH-1:0] != _s_axis_waddr_next[C_ADDRESS_WIDTH-1:0]);
s_axis_empty <= _s_axis_raddr == _s_axis_waddr_next; s_axis_empty <= _s_axis_raddr == _s_axis_waddr_next;
s_axis_room <= _s_axis_raddr - _s_axis_waddr_next + 2**C_ADDRESS_WIDTH;
end end
end end
always @(posedge m_axis_aclk) always @(posedge m_axis_aclk)
begin begin
if (s_axis_aresetn == 1'b0) if (s_axis_aresetn == 1'b0) begin
m_axis_valid <= 1'b0; m_axis_valid <= 1'b0;
else begin m_axis_level <= 'h00;
end else begin
m_axis_valid <= _m_axis_waddr != _m_axis_raddr_next; m_axis_valid <= _m_axis_waddr != _m_axis_raddr_next;
m_axis_level <= _m_axis_waddr - _m_axis_raddr_next;
end end
end end

View File

@ -44,18 +44,24 @@ module fifo_address_sync (
output reg m_axis_valid, output reg m_axis_valid,
output reg [C_ADDRESS_WIDTH-1:0] m_axis_raddr, output reg [C_ADDRESS_WIDTH-1:0] m_axis_raddr,
output reg [C_ADDRESS_WIDTH-1:0] m_axis_raddr_next, output reg [C_ADDRESS_WIDTH-1:0] m_axis_raddr_next,
output [C_ADDRESS_WIDTH:0] m_axis_level,
output reg s_axis_ready, output reg s_axis_ready,
input s_axis_valid, input s_axis_valid,
output reg s_axis_empty, output reg s_axis_empty,
output reg [C_ADDRESS_WIDTH-1:0] s_axis_waddr output reg [C_ADDRESS_WIDTH-1:0] s_axis_waddr,
output [C_ADDRESS_WIDTH:0] s_axis_room
); );
parameter C_ADDRESS_WIDTH = 4; parameter C_ADDRESS_WIDTH = 4;
reg [C_ADDRESS_WIDTH:0] level; reg [C_ADDRESS_WIDTH:0] room = 2**C_ADDRESS_WIDTH;
reg [C_ADDRESS_WIDTH:0] level = 'h00;
reg [C_ADDRESS_WIDTH:0] level_next; reg [C_ADDRESS_WIDTH:0] level_next;
assign s_axis_room = room;
assign m_axis_level = level;
wire read = m_axis_ready & m_axis_valid; wire read = m_axis_ready & m_axis_valid;
wire write = s_axis_ready & s_axis_valid; wire write = s_axis_ready & s_axis_valid;
@ -94,8 +100,12 @@ begin
if (resetn == 1'b0) begin if (resetn == 1'b0) begin
m_axis_valid <= 1'b0; m_axis_valid <= 1'b0;
s_axis_ready <= 1'b0; s_axis_ready <= 1'b0;
level <= 'h00;
room <= 2**C_ADDRESS_WIDTH;
s_axis_empty <= 'h00;
end else begin end else begin
level <= level_next; level <= level_next;
room <= 2**C_ADDRESS_WIDTH - level_next;
m_axis_valid <= level_next != 0; m_axis_valid <= level_next != 0;
s_axis_ready <= level_next != 2**C_ADDRESS_WIDTH; s_axis_ready <= level_next != 2**C_ADDRESS_WIDTH;
s_axis_empty <= level_next == 0; s_axis_empty <= level_next == 0;

View File

@ -42,13 +42,15 @@ module util_axis_fifo (
input m_axis_ready, input m_axis_ready,
output m_axis_valid, output m_axis_valid,
output [C_DATA_WIDTH-1:0] m_axis_data, output [C_DATA_WIDTH-1:0] m_axis_data,
output [C_ADDRESS_WIDTH:0] m_axis_level,
input s_axis_aclk, input s_axis_aclk,
input s_axis_aresetn, input s_axis_aresetn,
output s_axis_ready, output s_axis_ready,
input s_axis_valid, input s_axis_valid,
input [C_DATA_WIDTH-1:0] s_axis_data, input [C_DATA_WIDTH-1:0] s_axis_data,
output s_axis_empty output s_axis_empty,
output [C_ADDRESS_WIDTH:0] s_axis_room
); );
parameter C_DATA_WIDTH = 64; parameter C_DATA_WIDTH = 64;
@ -86,8 +88,10 @@ sync_bits #(
); );
assign m_axis_valid = m_axis_raddr != m_axis_waddr; assign m_axis_valid = m_axis_raddr != m_axis_waddr;
assign m_axis_level = m_axis_valid;
assign s_axis_ready = s_axis_raddr == s_axis_waddr; assign s_axis_ready = s_axis_raddr == s_axis_waddr;
assign s_axis_empty = s_axis_raddr == s_axis_waddr; assign s_axis_empty = s_axis_ready;
assign s_axis_room = s_axis_ready;
always @(posedge s_axis_aclk) begin always @(posedge s_axis_aclk) begin
if (s_axis_ready) if (s_axis_ready)
@ -131,17 +135,18 @@ fifo_address_gray_pipelined #(
) i_address_gray ( ) i_address_gray (
.m_axis_aclk(m_axis_aclk), .m_axis_aclk(m_axis_aclk),
.m_axis_aresetn(m_axis_aresetn), .m_axis_aresetn(m_axis_aresetn),
.m_axis_ready(_m_axis_ready), .m_axis_ready(_m_axis_ready),
.m_axis_valid(_m_axis_valid), .m_axis_valid(_m_axis_valid),
.m_axis_raddr(m_axis_raddr), .m_axis_raddr(m_axis_raddr),
.m_axis_level(m_axis_level),
.s_axis_aclk(s_axis_aclk), .s_axis_aclk(s_axis_aclk),
.s_axis_aresetn(s_axis_aresetn), .s_axis_aresetn(s_axis_aresetn),
.s_axis_ready(s_axis_ready), .s_axis_ready(s_axis_ready),
.s_axis_valid(s_axis_valid), .s_axis_valid(s_axis_valid),
.s_axis_empty(s_axis_empty), .s_axis_empty(s_axis_empty),
.s_axis_waddr(s_axis_waddr) .s_axis_waddr(s_axis_waddr),
.s_axis_room(s_axis_room)
); );
end else begin end else begin
@ -151,15 +156,16 @@ fifo_address_sync #(
) i_address_sync ( ) i_address_sync (
.clk(m_axis_aclk), .clk(m_axis_aclk),
.resetn(m_axis_aresetn), .resetn(m_axis_aresetn),
.m_axis_ready(_m_axis_ready), .m_axis_ready(_m_axis_ready),
.m_axis_valid(_m_axis_valid), .m_axis_valid(_m_axis_valid),
.m_axis_raddr(m_axis_raddr), .m_axis_raddr(m_axis_raddr),
.m_axis_level(m_axis_level),
.s_axis_ready(s_axis_ready), .s_axis_ready(s_axis_ready),
.s_axis_valid(s_axis_valid), .s_axis_valid(s_axis_valid),
.s_axis_empty(s_axis_empty), .s_axis_empty(s_axis_empty),
.s_axis_waddr(s_axis_waddr) .s_axis_waddr(s_axis_waddr),
.s_axis_room(s_axis_room)
); );
end end