diff --git a/lib/fifo/fifo_2clk_xpm_core.v b/lib/fifo/fifo_2clk_xpm_core.v new file mode 100644 index 0000000..82194bf --- /dev/null +++ b/lib/fifo/fifo_2clk_xpm_core.v @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Vivado/XPM replacement for the legacy Ettus FIFO Generator building blocks +// used by axi_fifo_2clk.v on Xilinx 7-series devices. +// +// This core deliberately provides the old native FIFO interface while using +// xpm_fifo_async internally. The external reset may be asynchronous, as it +// was for the FIFO Generator instances. XPM's rst input, however, must be +// synchronous to wr_clk, so reset assertion is captured asynchronously and +// then presented to XPM through a wr_clk synchronizer. Read/write requests +// and external flags are held inactive/conservative until XPM reset-busy has +// cleared. + +`timescale 1ns/1ps +`default_nettype none + +module fifo_2clk_xpm_core #( + parameter integer FIFO_DEPTH = 32, + parameter integer COUNT_WIDTH = 6, + parameter integer CDC_SYNC_STAGES = 3, + parameter MEMORY_TYPE = "distributed" +)( + input wire rst, + input wire wr_clk, + input wire [71:0] din, + input wire wr_en, + output wire full, + output wire [COUNT_WIDTH-1:0] wr_data_count, + input wire rd_clk, + output wire [71:0] dout, + input wire rd_en, + output wire empty, + output wire [COUNT_WIDTH-1:0] rd_data_count +); + + // ------------------------------------------------------------------------ + // Reset adaptation + // ------------------------------------------------------------------------ + // Legacy FIFO Generator accepted an asynchronous reset. XPM_FIFO_ASYNC + // requires rst to be synchronous to wr_clk. rst_capture catches even a + // short asynchronous assertion; xpm_rst_sync then converts it into a reset + // signal that changes only on wr_clk edges. + reg rst_capture = 1'b1; + always @(posedge wr_clk or posedge rst) begin + if (rst) + rst_capture <= 1'b1; + else + rst_capture <= 1'b0; + end + + (* ASYNC_REG = "TRUE", SHREG_EXTRACT = "NO" *) + reg [1:0] xpm_rst_sync = 2'b11; + always @(posedge wr_clk) begin + xpm_rst_sync[0] <= rst_capture; + xpm_rst_sync[1] <= xpm_rst_sync[0]; + end + + wire xpm_rst = xpm_rst_sync[1]; + + wire xpm_full; + wire xpm_empty; + wire xpm_wr_rst_busy; + wire xpm_rd_rst_busy; + wire [71:0] xpm_dout; + wire [COUNT_WIDTH-1:0] xpm_wr_data_count; + wire [COUNT_WIDTH-1:0] xpm_rd_data_count; + + // Keep the read-side legacy interface quiescent from the instant the old + // asynchronous reset is asserted until both XPM reset propagation and the + // read-domain reset-busy interval have completed. Assertion is asynchronous; + // release is synchronized to rd_clk. + wire rd_hold_req = rst | xpm_rst | xpm_rd_rst_busy; + (* ASYNC_REG = "TRUE", SHREG_EXTRACT = "NO" *) + reg [1:0] rd_hold_sync = 2'b11; + always @(posedge rd_clk or posedge rd_hold_req) begin + if (rd_hold_req) + rd_hold_sync <= 2'b11; + else begin + rd_hold_sync[0] <= 1'b0; + rd_hold_sync[1] <= rd_hold_sync[0]; + end + end + + wire rd_hold = rd_hold_sync[1]; + wire wr_hold = rst | xpm_rst | xpm_wr_rst_busy; + + // XPM requires wr_en/rd_en low while reset or the corresponding reset-busy + // flag is active. Gating with full/empty also suppresses overflow/underflow + // requests from legacy call sites that leave an enable asserted continuously. + wire xpm_wr_en = wr_en & ~wr_hold & ~xpm_full; + wire xpm_rd_en = rd_en & ~rd_hold & ~xpm_empty; + + // Match the conservative reset behavior of the Ettus FIFO Generator IP: + // full is asserted during reset and empty is asserted until read-side reset + // recovery is complete. + assign full = wr_hold | xpm_full; + assign empty = rd_hold | xpm_empty; + assign dout = rd_hold ? 72'b0 : xpm_dout; + assign wr_data_count = wr_hold ? {COUNT_WIDTH{1'b0}} : xpm_wr_data_count; + assign rd_data_count = rd_hold ? {COUNT_WIDTH{1'b0}} : xpm_rd_data_count; + + // USE_ADV_FEATURES="0404" enables only wr_data_count (bit 2) and + // rd_data_count (bit 10), preserving the legacy ports without enabling the + // other optional status logic. + xpm_fifo_async #( + .CDC_SYNC_STAGES (CDC_SYNC_STAGES), + .DOUT_RESET_VALUE ("0"), + .ECC_MODE ("no_ecc"), + .FIFO_MEMORY_TYPE (MEMORY_TYPE), + .FIFO_READ_LATENCY (0), + .FIFO_WRITE_DEPTH (FIFO_DEPTH), + .FULL_RESET_VALUE (1), + .PROG_EMPTY_THRESH (10), + .PROG_FULL_THRESH (10), + .RD_DATA_COUNT_WIDTH(COUNT_WIDTH), + .READ_DATA_WIDTH (72), + .READ_MODE ("fwft"), + .RELATED_CLOCKS (0), + .SIM_ASSERT_CHK (1), + .USE_ADV_FEATURES ("0404"), + .WAKEUP_TIME (0), + .WRITE_DATA_WIDTH (72), + .WR_DATA_COUNT_WIDTH(COUNT_WIDTH) + ) xpm_fifo_async_i ( + .almost_empty (), + .almost_full (), + .data_valid (), + .dbiterr (), + .dout (xpm_dout), + .empty (xpm_empty), + .full (xpm_full), + .overflow (), + .prog_empty (), + .prog_full (), + .rd_data_count(xpm_rd_data_count), + .rd_rst_busy (xpm_rd_rst_busy), + .sbiterr (), + .underflow (), + .wr_ack (), + .wr_data_count(xpm_wr_data_count), + .wr_rst_busy (xpm_wr_rst_busy), + .din (din), + .injectdbiterr(1'b0), + .injectsbiterr(1'b0), + .rd_clk (rd_clk), + .rd_en (xpm_rd_en), + .rst (xpm_rst), + .sleep (1'b0), + .wr_clk (wr_clk), + .wr_en (xpm_wr_en) + ); + +endmodule + +`default_nettype wire diff --git a/lib/fifo/fifo_4k_2clk.v b/lib/fifo/fifo_4k_2clk.v new file mode 100644 index 0000000..cff6c54 --- /dev/null +++ b/lib/fifo/fifo_4k_2clk.v @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Drop-in replacement for Ettus/X300 fifo_4k_2clk FIFO Generator IP. +// X300 configuration: 72 bits x 512 words (36 Kibit), independent clocks, +// block RAM, FWFT, 2 CDC synchronization stages. + +`timescale 1ns/1ps +`default_nettype none + +module fifo_4k_2clk ( + input wire rst, + input wire wr_clk, + input wire [71:0] din, + input wire wr_en, + output wire full, + output wire [9:0] wr_data_count, + input wire rd_clk, + output wire [71:0] dout, + input wire rd_en, + output wire empty, + output wire [9:0] rd_data_count +); + + fifo_2clk_xpm_core #( + .FIFO_DEPTH (512), + .COUNT_WIDTH (10), + .CDC_SYNC_STAGES (2), + .MEMORY_TYPE ("block") + ) impl_i ( + .rst (rst), + .wr_clk (wr_clk), + .din (din), + .wr_en (wr_en), + .full (full), + .wr_data_count(wr_data_count), + .rd_clk (rd_clk), + .dout (dout), + .rd_en (rd_en), + .empty (empty), + .rd_data_count(rd_data_count) + ); + +endmodule + +`default_nettype wire diff --git a/lib/fifo/fifo_short_2clk.v b/lib/fifo/fifo_short_2clk.v new file mode 100644 index 0000000..63119a1 --- /dev/null +++ b/lib/fifo/fifo_short_2clk.v @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Drop-in replacement for Ettus/X300 fifo_short_2clk FIFO Generator IP. +// X300 configuration: 72 bits x 32 words, independent clocks, +// distributed RAM, FWFT, 3 CDC synchronization stages. + +`timescale 1ns/1ps +`default_nettype none + +module fifo_short_2clk ( + input wire rst, + input wire wr_clk, + input wire [71:0] din, + input wire wr_en, + output wire full, + output wire [5:0] wr_data_count, + input wire rd_clk, + output wire [71:0] dout, + input wire rd_en, + output wire empty, + output wire [5:0] rd_data_count +); + + fifo_2clk_xpm_core #( + .FIFO_DEPTH (32), + .COUNT_WIDTH (6), + .CDC_SYNC_STAGES (3), + .MEMORY_TYPE ("distributed") + ) impl_i ( + .rst (rst), + .wr_clk (wr_clk), + .din (din), + .wr_en (wr_en), + .full (full), + .wr_data_count(wr_data_count), + .rd_clk (rd_clk), + .dout (dout), + .rd_en (rd_en), + .empty (empty), + .rd_data_count(rd_data_count) + ); + +endmodule + +`default_nettype wire diff --git a/vivado/b210_k7/sources.tcl b/vivado/b210_k7/sources.tcl index f77d302..6514f91 100644 --- a/vivado/b210_k7/sources.tcl +++ b/vivado/b210_k7/sources.tcl @@ -2,12 +2,6 @@ # # Exact source manifest for the reconstructed Kintex-7 B210 clone. # -# IMPORTANT: This initial manifest intentionally reproduces the original -# Vivado 2024.1 project, including its use of lib/sim/fifo/axi_fifo_2clk_sim.v -# for synthesis. A later Git commit should replace that entry with the real -# hardware FIFO hierarchy and XPM wrappers. Keeping the historical mistake in -# this baseline makes the Git history accurately describe the repair. -# # Paths are repository-relative and are deliberately explicit. Do not replace # these lists with recursive globs; doing so can accidentally pull simulation # sources into synthesis. @@ -31,7 +25,10 @@ set B210_HDL_SOURCES { lib/fifo/axi_fifo.v lib/fifo/axi_fifo32_to_fifo64.v lib/fifo/axi_fifo64_to_fifo32.v - lib/sim/fifo/axi_fifo_2clk_sim.v + lib/fifo/axi_fifo_2clk.v + lib/fifo/fifo_short_2clk.v + lib/fifo/fifo_4k_2clk.v + lib/fifo/fifo_2clk_xpm_core.v lib/fifo/axi_fifo_bram.v lib/fifo/axi_fifo_flop.v lib/fifo/axi_fifo_flop2.v