From 04bb66663eb2da3fa341f6e97d81356bca2224c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20K=C3=B6hler?= Date: Wed, 12 Aug 2026 10:22:55 +0200 Subject: [PATCH] fpga: lib: enable XPM fifo for all Xilinx FPGAs --- fpga/usrp3/lib/fifo/axi_fifo_2clk.v | 76 +++++++++++--------------- fpga/usrp3/lib/fifo/fifo_xpm_2clk.sv | 24 +++++--- fpga/usrp3/tools/scripts/viv_utils.tcl | 3 + 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/fpga/usrp3/lib/fifo/axi_fifo_2clk.v b/fpga/usrp3/lib/fifo/axi_fifo_2clk.v index 0b704ea44..e2b9d6e25 100644 --- a/fpga/usrp3/lib/fifo/axi_fifo_2clk.v +++ b/fpga/usrp3/lib/fifo/axi_fifo_2clk.v @@ -88,18 +88,6 @@ module axi_fifo_2clk #( wire o_ext_tvalid; wire o_ext_tready; - // Derive constants based on device. The XPM-based FIFO is not yet supported - // on some devices. Deriving a local parameter to use for later checks. - `ifdef X300 - localparam USE_LEGACY_FIFO = 1; - `elsif X310 - localparam USE_LEGACY_FIFO = 1; - `elsif B310 - localparam USE_LEGACY_FIFO = 1; - `else - localparam USE_LEGACY_FIFO = 0; - `endif - // First triple of values is for Intel's MAX10 FPGAs. The FIFO generator for // those devices supports embedded memory only (SRL_THRESHOLD = 0). // The later triple has been optimized for Xilinx 7Series FPGAs. They also @@ -123,10 +111,15 @@ module axi_fifo_2clk #( generate // XPM-based FIFO for Xilinx FPGAs, except for the certain devices. - if (DEVICE != "MAX10" && !USE_LEGACY_FIFO) begin: xpm_fifo_section + if (DEVICE != "MAX10") begin: xpm_fifo_section localparam XPM_SIZE = (SIZE < SRL_THRESHOLD) ? SRL_THRESHOLD : SIZE; + localparam TYPE = (SIZE < RAM_THRESHOLD) ? "distributed" : "block"; - fifo_xpm_2clk #(.WIDTH(WIDTH), .DEPTH(1 << XPM_SIZE)) impl_xpm_i ( + fifo_xpm_2clk #( + .WIDTH(WIDTH), + .DEPTH(2**XPM_SIZE), + .TYPE(TYPE) + ) impl_xpm_i ( .rst (i_arst), .wr_clk (i_aclk), .din (i_pipe_tdata), @@ -139,6 +132,9 @@ module axi_fifo_2clk #( .empty (fifo_empty), .rd_data_count() ); + + assign {o_pipe_tdata, o_pipe_tvalid} = {o_ext_tdata, o_ext_tvalid}; + assign o_ext_tready = o_pipe_tready; end else begin: legacy_fifo_section wire [INT_WIDTH-1:0] wr_data, rd_data; wire [NUM_FIFOS-1:0] full, empty; @@ -180,38 +176,28 @@ module axi_fifo_2clk #( ); end end - end - endgenerate - //---------------------------------------------- - // Extension FIFO (for large sizes) - //---------------------------------------------- - - generate - if (SIZE > RAM_THRESHOLD) begin - wire [WIDTH-1:0] ext_pipe_tdata; - wire ext_pipe_tvalid; - wire ext_pipe_tready; - - // Add a register slice between BRAM cascades - axi_fifo_flop2 #(.WIDTH(WIDTH)) ext_fifo_pipe_i ( - .clk(o_aclk), .reset(o_arst), .clear(1'b0), - .i_tdata(o_ext_tdata), .i_tvalid(o_ext_tvalid), .i_tready(o_ext_tready), - .o_tdata(ext_pipe_tdata), .o_tvalid(ext_pipe_tvalid), .o_tready(ext_pipe_tready), - .space(), .occupied() - ); - - // Bolt on an extension FIFO if the requested depth is larger than the BRAM - // 2clk FIFO primitive (IP) - axi_fifo_bram #(.WIDTH(WIDTH), .SIZE(SIZE)) ext_fifo_i ( - .clk(o_aclk), .reset(o_arst), .clear(1'b0), - .i_tdata(ext_pipe_tdata), .i_tvalid(ext_pipe_tvalid), .i_tready(ext_pipe_tready), - .o_tdata(o_pipe_tdata), .o_tvalid(o_pipe_tvalid), .o_tready(o_pipe_tready), - .space(), .occupied() - ); - end else begin - assign {o_pipe_tdata, o_pipe_tvalid} = {o_ext_tdata, o_ext_tvalid}; - assign o_ext_tready = o_pipe_tready; + //---------------------------------------------- + // Extension FIFO (for large sizes) + //---------------------------------------------- + if (SIZE > RAM_THRESHOLD) begin + // Bolt on an extension FIFO if the requested depth is larger than the BRAM + // 2clk FIFO primitive (IP) + axi_fifo_large #( + .WIDTH(WIDTH), + .DEPTH(2**SIZE - 2**RAM_THRESHOLD), + .DEVICE(DEVICE), + .MAX_NUM_URAM_BLOCKS(0) + ) ext_fifo_i ( + .clk(o_aclk), .reset(o_arst), .clear(1'b0), + .i_tdata(o_ext_tdata), .i_tvalid(o_ext_tvalid), .i_tready(o_ext_tready), + .o_tdata(o_pipe_tdata), .o_tvalid(o_pipe_tvalid), .o_tready(o_pipe_tready), + .space(), .occupied() + ); + end else begin + assign {o_pipe_tdata, o_pipe_tvalid} = {o_ext_tdata, o_ext_tvalid}; + assign o_ext_tready = o_pipe_tready; + end end endgenerate diff --git a/fpga/usrp3/lib/fifo/fifo_xpm_2clk.sv b/fpga/usrp3/lib/fifo/fifo_xpm_2clk.sv index e33fcfa15..3a83498a5 100644 --- a/fpga/usrp3/lib/fifo/fifo_xpm_2clk.sv +++ b/fpga/usrp3/lib/fifo/fifo_xpm_2clk.sv @@ -9,18 +9,20 @@ // // Asynchronous dual-clock FIFO implemented with Xilinx XPM FIFO // primitives. The FIFO uses first-word fall-through read mode and -// provides the interface used by fifo_short_2clk. +// provides the dual-clock FIFO interface used by the FPGA projects. // // Parameters: // // WIDTH: Width of the input and output data buses. // DEPTH: Number of entries in the FIFO. Must be a power of two between // 16 and 4194304. +// TYPE: Type of memory to use for the FIFO. Can be "auto", "block", or "distributed". // module fifo_xpm_2clk #( int WIDTH = 72, - int DEPTH = 32 + int DEPTH = 32, + string TYPE = "auto" )( input logic rst, input logic wr_clk, @@ -46,12 +48,20 @@ module fifo_xpm_2clk #( localparam int COUNT_WIDTH = $clog2(DEPTH) + 1; + logic xpm_full; + logic xpm_empty; + logic wr_rst_busy; + logic rd_rst_busy; + + assign full = xpm_full | wr_rst_busy; + assign empty = xpm_empty | rd_rst_busy; + xpm_fifo_async #( .CASCADE_HEIGHT (0), .CDC_SYNC_STAGES (3), .DOUT_RESET_VALUE ("0"), .ECC_MODE ("no_ecc"), - .FIFO_MEMORY_TYPE ("auto"), + .FIFO_MEMORY_TYPE (TYPE), .FIFO_READ_LATENCY (0), .FIFO_WRITE_DEPTH (DEPTH), .FULL_RESET_VALUE (1), @@ -72,18 +82,18 @@ module fifo_xpm_2clk #( .data_valid (), .dbiterr (), .dout (dout), - .empty (empty), - .full (full), + .empty (xpm_empty), + .full (xpm_full), .overflow (), .prog_empty (), .prog_full (), .rd_data_count (rd_data_count), - .rd_rst_busy (), + .rd_rst_busy (rd_rst_busy), .sbiterr (), .underflow (), .wr_ack (), .wr_data_count (wr_data_count), - .wr_rst_busy (), + .wr_rst_busy (wr_rst_busy), .din (din), .injectdbiterr (1'b0), .injectsbiterr (1'b0), diff --git a/fpga/usrp3/tools/scripts/viv_utils.tcl b/fpga/usrp3/tools/scripts/viv_utils.tcl index feeaa86e2..e38deae14 100644 --- a/fpga/usrp3/tools/scripts/viv_utils.tcl +++ b/fpga/usrp3/tools/scripts/viv_utils.tcl @@ -169,6 +169,9 @@ proc ::vivado_utils::synthesize_design {args} { variable g_verilog_defs variable g_include_dirs + # automatically detect xpm libraries and include the respective libraries + auto_detect_xpm + set vdef_args "" foreach vdef $g_verilog_defs { set vdef_args [concat $vdef_args "-verilog_define $vdef"]