From 72432c92787786514713625e5db2a62ce87996c2 Mon Sep 17 00:00:00 2001 From: Wade Fife Date: Wed, 12 Feb 2025 10:59:10 -0600 Subject: [PATCH] fpga: lib: Add zero-length option to axi_fifo Original-commit: 6ea4e4808e09e55bb2ba05e787e79ec3c5fe4340 --- lib/fifo/axi_fifo.v | 193 ++++++++++++++++++++++++++++++-------------- 1 file changed, 131 insertions(+), 62 deletions(-) diff --git a/lib/fifo/axi_fifo.v b/lib/fifo/axi_fifo.v index 3a99c4c..0614436 100644 --- a/lib/fifo/axi_fifo.v +++ b/lib/fifo/axi_fifo.v @@ -1,71 +1,140 @@ // -// Copyright 2012-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company +// Copyright 2025 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // +// Module: axi_fifo +// +// Description: +// +// General FIFO block +// +// Parameters: +// +// WIDTH : Width of tdata in bits +// SIZE : Log base 2 of the depth of the FIFO. In other words, the size of +// the FIFO is 2**SIZE elements deep. The implementation changes +// depending on the FIFO size, as described below. +// +// SIZE < 0 : No FIFO (data passes through without any buffer) +// SIZE == 0 : Uses a single stage flop (axi_fifo_flop) +// SIZE == 1 : Uses a two-stage flop (axi_fifo_flop2). Best choice for single +// stage pipelining. Breaks combinatorial paths on the AXI stream +// data / control lines at the cost of additional registers. Maps +// to SLICELs (i.e. does not use distributed RAM). +// SIZE <= 5 : Uses SRL32 to efficient maps a 32 deep FIFO to SLICEMs +// (axi_fifo_short). Not recommended for pipelining as most +// devices have twice as many SLICELs as SLICEMs. +// SIZE > 5 : Uses BRAM FIFO (axi_fifo_bram) +// -// General FIFO block -// Size == 0: Uses a single stage flop (axi_fifo_flop). -// Size == 1: Uses a two stage flop (axi_fifo_flop2). Best choice for single stage pipelining. -// Breaks combinatorial paths on the AXI stream data / control lines at the cost of -// additional registers. Maps to SLICELs (i.e. does not use distributed RAM). -// Size <= 5: Uses SRL32 to efficient maps a 32 deep FIFO to SLICEMs (axi_fifo_short). Not -// recommended for pipelining as most devices have twice as many SLICELs as SLICEMs. -// Size > 5: Uses BRAM fifo (axi_fifo_bram) +`default_nettype none + + +module axi_fifo #( + parameter WIDTH = 32, + parameter SIZE = 5 +) ( + input wire clk, + input wire reset, + input wire clear, + + input wire [WIDTH-1:0] i_tdata, + input wire i_tvalid, + output wire i_tready, + + output wire [WIDTH-1:0] o_tdata, + output wire o_tvalid, + input wire o_tready, + + output wire [ 15:0] space, + output wire [ 15:0] occupied +); -module axi_fifo - #(parameter WIDTH=32, SIZE=5) - (input clk, input reset, input clear, - input [WIDTH-1:0] i_tdata, - input i_tvalid, - output i_tready, - output [WIDTH-1:0] o_tdata, - output o_tvalid, - input o_tready, - - output [15:0] space, - output [15:0] occupied); - generate - if(SIZE==0) - begin - axi_fifo_flop #(.WIDTH(WIDTH)) fifo_flop - (.clk(clk), .reset(reset), .clear(clear), - .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready), - .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready), - .space(space[0]), .occupied(occupied[0])); - assign space[15:1] = 15'd0; - assign occupied[15:1] = 15'd0; - end - else if(SIZE==1) - begin - axi_fifo_flop2 #(.WIDTH(WIDTH)) fifo_flop2 - (.clk(clk), .reset(reset), .clear(clear), - .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready), - .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready), - .space(space[1:0]), .occupied(occupied[1:0])); - assign space[15:2] = 14'd0; - assign occupied[15:2] = 14'd0; - end - else if(SIZE<=5) - begin - axi_fifo_short #(.WIDTH(WIDTH)) fifo_short - (.clk(clk), .reset(reset), .clear(clear), - .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready), - .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready), - .space(space[5:0]), .occupied(occupied[5:0])); - assign space[15:6] = 10'd0; - assign occupied[15:6] = 10'd0; - end - else - begin - axi_fifo_bram #(.WIDTH(WIDTH), .SIZE(SIZE)) fifo_bram - (.clk(clk), .reset(reset), .clear(clear), - .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready), - .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready), - .space(space), .occupied(occupied)); - end + if (SIZE < 0) begin : gen_no_fifo + assign o_tdata = i_tdata; + assign o_tvalid = i_tvalid; + assign i_tready = o_tready; + end + if (SIZE == 0) begin : gen_fifo_flop + axi_fifo_flop #( + .WIDTH(WIDTH) + ) fifo_flop ( + .clk (clk), + .reset (reset), + .clear (clear), + .i_tdata (i_tdata), + .i_tvalid(i_tvalid), + .i_tready(i_tready), + .o_tdata (o_tdata), + .o_tvalid(o_tvalid), + .o_tready(o_tready), + .space (space[0]), + .occupied(occupied[0]) + ); + assign space[15:1] = 15'd0; + assign occupied[15:1] = 15'd0; + end + else if (SIZE == 1) begin : gen_fifo_flop2 + axi_fifo_flop2 #( + .WIDTH(WIDTH) + ) fifo_flop2 ( + .clk (clk), + .reset (reset), + .clear (clear), + .i_tdata (i_tdata), + .i_tvalid(i_tvalid), + .i_tready(i_tready), + .o_tdata (o_tdata), + .o_tvalid(o_tvalid), + .o_tready(o_tready), + .space (space[1:0]), + .occupied(occupied[1:0]) + ); + assign space[15:2] = 14'd0; + assign occupied[15:2] = 14'd0; + end + else if (SIZE <= 5) begin : gen_fifo_short + axi_fifo_short #( + .WIDTH(WIDTH) + ) fifo_short ( + .clk (clk), + .reset (reset), + .clear (clear), + .i_tdata (i_tdata), + .i_tvalid(i_tvalid), + .i_tready(i_tready), + .o_tdata (o_tdata), + .o_tvalid(o_tvalid), + .o_tready(o_tready), + .space (space[5:0]), + .occupied(occupied[5:0]) + ); + assign space[15:6] = 10'd0; + assign occupied[15:6] = 10'd0; + end + else begin : gen_fifo_bram + axi_fifo_bram #( + .WIDTH(WIDTH), + .SIZE (SIZE) + ) fifo_bram ( + .clk (clk), + .reset (reset), + .clear (clear), + .i_tdata (i_tdata), + .i_tvalid(i_tvalid), + .i_tready(i_tready), + .o_tdata (o_tdata), + .o_tvalid(o_tvalid), + .o_tready(o_tready), + .space (space), + .occupied(occupied) + ); + end endgenerate - + endmodule // axi_fifo + + +`default_nettype wire