diff --git a/fpga/usrp3/lib/fifo/axi_packet_gate.v b/fpga/usrp3/lib/fifo/axi_packet_gate.v index c0037e80f..dacf8bc00 100644 --- a/fpga/usrp3/lib/fifo/axi_packet_gate.v +++ b/fpga/usrp3/lib/fifo/axi_packet_gate.v @@ -5,7 +5,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // // Description: -// Holds packets in a FIFO until they are complete. This allows buffering +// Holds packets in a FIFO until they are complete. This allows buffering // slowly-built packets so they don't clog up downstream logic. If o_tready // is held high, this module guarantees that o_tvalid will not be deasserted // until a full packet is transferred. This module can also optionally drop @@ -14,12 +14,12 @@ // NOTE: // - The maximum size of a packet that can pass through this module is // 2^SIZE lines. If a larger packet is sent, this module will lock up. -// - Assuming that upstream is valid and downstream is ready, the maximum -// in to out latency per packet is (2^SIZE + 2) clock cycles. +// - Assuming that upstream is valid and downstream is ready, the maximum +// in to out latency per packet is (2^SIZE + 2) clock cycles. // 2^SIZE because this module gates a packet, 1 cycle for the RAM read and // 1 more cycle for the output register. This is not guaranteed behavior though. // - The USE_AS_BUFF parameter can be used to treat this packet gate as -// a multi-packet buffer. When USE_AS_BUFF=0, the max number of packets +// a multi-packet buffer. When USE_AS_BUFF=0, the max number of packets // (regardless of size) that the module can store is 2. When USE_AS_BUFF=1, // the entire storage of this module can be used to buffer packets but at // the cost of some additional RAM. Beware the sequence of (big packet, @@ -32,8 +32,8 @@ module axi_packet_gate #( parameter USE_AS_BUFF = 0, // Allow the packet gate to be used as a buffer (uses more RAM) parameter MIN_PKT_SIZE= 0 // log2 of minimum valid packet size (rounded down, used to reduce addr fifo size) ) ( - input wire clk, - input wire reset, + input wire clk, + input wire reset, input wire clear, input wire [WIDTH-1:0] i_tdata, input wire i_tlast, @@ -65,7 +65,7 @@ module axi_packet_gate #( ram_2port #( .DWIDTH (WIDTH+1), .AWIDTH(SIZE), .RW_MODE("NO-CHANGE"), .OUT_REG(0), - .RAM_TYPE(SIZE <= LUTRAM_THRESH ? "LUTRAM" : "AUTOMATIC") + .RAM_TYPE(SIZE <= LUTRAM_THRESH ? "LUTRAM" : "BRAM") ) ram_i ( .clka (clk), .ena(1'b1), .wea(wr_en), .addra(wr_addr), .dia(wr_data), .doa(), @@ -116,7 +116,7 @@ module axi_packet_gate #( // ------------------------------------------- // The address FIFO will hold the write address // for the last line in a non-errant packet - + wire [SIZE-1:0] afifo_i_tdata, afifo_o_tdata, afifo_p_tdata; wire afifo_i_tvalid, afifo_i_tready; wire afifo_o_tvalid, afifo_o_tready; diff --git a/fpga/usrp3/lib/rfnoc/transport_adapters/rfnoc_ta_x4xx_eth/x4xx_qsfp_wrapper.sv b/fpga/usrp3/lib/rfnoc/transport_adapters/rfnoc_ta_x4xx_eth/x4xx_qsfp_wrapper.sv index 3ea8b64d9..35f98ba11 100644 --- a/fpga/usrp3/lib/rfnoc/transport_adapters/rfnoc_ta_x4xx_eth/x4xx_qsfp_wrapper.sv +++ b/fpga/usrp3/lib/rfnoc/transport_adapters/rfnoc_ta_x4xx_eth/x4xx_qsfp_wrapper.sv @@ -504,7 +504,7 @@ module x4xx_qsfp_wrapper #( axi_hp_dma[lane].bready = 1'b0; axi_hp_dma[lane].rready = 1'b0; - mgt_pause_req = 0'b0; + mgt_pause_req = 1'b0; eth_rx_irq[lane] = 1'b0; eth_tx_irq[lane] = 1'b0; diff --git a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter_wrapper.sv b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter_wrapper.sv index b79f4274b..6509f23ec 100644 --- a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter_wrapper.sv +++ b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter_wrapper.sv @@ -133,7 +133,7 @@ module eth_ipv4_chdr_adapter_wrapper #( // Interface //--------------------------------------------------------------------------- - AxiStreamIf #(.DATA_WIDTH(ENET_W), .USER_WIDTH(ENET_USER_W), .TKEEP(0)) + AxiStreamIf #(.DATA_WIDTH(ENET_W), .USER_WIDTH(ENET_USER_W), .TKEEP(1)) eth_tx (eth_clk, eth_rst); AxiStreamIf #(.DATA_WIDTH(ENET_W), .USER_WIDTH(ENET_USER_W), .TKEEP(0)) eth_rx (eth_clk, eth_rst); diff --git a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv index 52ddc1eb1..8ea5b2ca5 100644 --- a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv +++ b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv @@ -292,7 +292,7 @@ module eth_ipv4_internal #( localparam CPU_USER_W = $clog2(CPU_W/8)+1; // SOF + trailing bytes // Host DMA interfaces - AxiStreamIf #(.DATA_WIDTH(CPU_W), .USER_WIDTH(CPU_USER_W), .TUSER(1), .TKEEP(0)) + AxiStreamIf #(.DATA_WIDTH(CPU_W), .USER_WIDTH(CPU_USER_W), .TUSER(1), .TKEEP(1)) e2h_chdr(bus_clk, bus_rst); AxiStreamIf #(.DATA_WIDTH(CPU_W), .USER_WIDTH(CPU_USER_W), .TUSER(1), .TKEEP(0)) h2e_chdr(bus_clk, bus_rst); diff --git a/fpga/usrp3/top/e320/build_e320.tcl b/fpga/usrp3/top/e320/build_e320.tcl index 47ad70534..8a2c0e7f8 100644 --- a/fpga/usrp3/top/e320/build_e320.tcl +++ b/fpga/usrp3/top/e320/build_e320.tcl @@ -28,7 +28,7 @@ dict set e3xx_strategy "post_place_phys_opt_design.directive" "Default" dict set e3xx_strategy "route_design.directive" "Default" dict set e3xx_strategy "route_design.more_options" "-tns_cleanup" dict set e3xx_strategy "post_route_phys_opt_design.is_enabled" 1 -dict set e3xx_strategy "post_route_phys_opt_design.directive" "Default" +dict set e3xx_strategy "post_route_phys_opt_design.directive" "ExploreWithAggressiveHoldFix" vivado_strategies::implement_design $e3xx_strategy # STEP#4: Generate reports diff --git a/fpga/usrp3/top/n3xx/build_n3xx.tcl b/fpga/usrp3/top/n3xx/build_n3xx.tcl index 80195e8dc..36e23775f 100644 --- a/fpga/usrp3/top/n3xx/build_n3xx.tcl +++ b/fpga/usrp3/top/n3xx/build_n3xx.tcl @@ -21,14 +21,14 @@ dict set n3xx_strategy "implementation.incremental" 0 dict set n3xx_strategy "opt_design.is_enabled" 1 dict set n3xx_strategy "opt_design.directive" "NoBramPowerOpt" dict set n3xx_strategy "post_opt_power_opt_design.is_enabled" 0 -dict set n3xx_strategy "place_design.directive" "ExtraNetDelay_high" +dict set n3xx_strategy "place_design.directive" "Explore" dict set n3xx_strategy "post_place_power_opt_design.is_enabled" 0 dict set n3xx_strategy "post_place_phys_opt_design.is_enabled" 1 dict set n3xx_strategy "post_place_phys_opt_design.directive" "AggressiveExplore" dict set n3xx_strategy "route_design.directive" "Explore" dict set n3xx_strategy "route_design.more_options" "-tns_cleanup" dict set n3xx_strategy "post_route_phys_opt_design.is_enabled" 1 -dict set n3xx_strategy "post_route_phys_opt_design.directive" "Explore" +dict set n3xx_strategy "post_route_phys_opt_design.directive" "ExploreWithAggressiveHoldFix" vivado_strategies::implement_design $n3xx_strategy # STEP#4: Generate reports diff --git a/fpga/usrp3/top/x300/ip/ten_gig_eth_pcs_pma/ten_gige_phy_clk_gen.v b/fpga/usrp3/top/x300/ip/ten_gig_eth_pcs_pma/ten_gige_phy_clk_gen.v index 27655571a..bdd061ff2 100644 --- a/fpga/usrp3/top/x300/ip/ten_gig_eth_pcs_pma/ten_gige_phy_clk_gen.v +++ b/fpga/usrp3/top/x300/ip/ten_gig_eth_pcs_pma/ten_gige_phy_clk_gen.v @@ -2,7 +2,7 @@ // Copyright 2008-2013 Ettus Research LLC // -module ten_gige_phy_clk_gen +module ten_gige_phy_clk_gen ( input areset, input refclk_p, @@ -16,7 +16,9 @@ module ten_gige_phy_clk_gen wire clk156_buf; wire dclk_buf; wire clkfbout; - + wire clkfb; + wire refclk_buf; + IBUFDS_GTE2 ibufds_inst ( .O (refclk), .ODIV2 (), @@ -25,21 +27,50 @@ module ten_gige_phy_clk_gen .IB (refclk_n) ); - BUFG clk156_bufg_inst ( + // required buffer to get differential refclock from clock region without PLL instance to another + // one + BUFG refclk_bufg_inst ( .I (refclk), - .O (clk156) + .O (refclk_buf) ); - // Divding independent clock by 2 as source for DRP clock - BUFR # ( - .BUFR_DIVIDE ("2") - ) dclk_divide_by_2_buf ( - .I (clk156), - .O (dclk_buf), - .CE (1'b1), - .CLR (1'b0) + // Clock cleanup required with Vivado 2025.2 to remove hold timing violations downstream + PLLE2_BASE #( + .BANDWIDTH("HIGH"), + .CLKFBOUT_MULT(10), + .CLKFBOUT_PHASE(0.0), + .CLKIN1_PERIOD(6.4), + .CLKOUT0_DIVIDE(10), + .CLKOUT1_DIVIDE(20), + .DIVCLK_DIVIDE(1), + .REF_JITTER1(0.010), + .STARTUP_WAIT("FALSE") + ) pll_clk156_inst ( + .CLKOUT0(clk156_buf), + .CLKOUT1(dclk_buf), + .CLKOUT2(), + .CLKOUT3(), + .CLKOUT4(), + .CLKOUT5(), + .CLKFBOUT(clkfbout), + .LOCKED(), + .CLKIN1(refclk_buf), + .PWRDWN(1'b0), + .RST(areset), + .CLKFBIN(clkfb) ); + // PLL feedback clock buffer + BUFG clkfb_bufg_inst ( + .I (clkfbout), + .O (clkfb) + ); + + // buffer for generated clocks + BUFG clk156_bufg_inst ( + .I (clk156_buf), + .O (clk156) + ); BUFG dclk_bufg_i ( .I (dclk_buf), .O (dclk) diff --git a/fpga/usrp3/top/x300/x300_10ge.xdc b/fpga/usrp3/top/x300/x300_10ge.xdc index fef9e1fa6..0e71606a4 100644 --- a/fpga/usrp3/top/x300/x300_10ge.xdc +++ b/fpga/usrp3/top/x300/x300_10ge.xdc @@ -10,10 +10,10 @@ set_property PACKAGE_PIN R7 [get_ports XG_CLK_n] create_clock -name XG_CLK -period 6.400 -waveform {0.000 3.200} [get_ports XG_CLK_p] -set_clock_groups -asynchronous -group [get_clocks bus_clk] -group [get_clocks XG_CLK] -set_clock_groups -asynchronous -group [get_clocks bus_clk_div2] -group [get_clocks XG_CLK] -set_clock_groups -asynchronous -group [get_clocks -filter {NAME =~ *sfpp_io_*/ten_gige_phy_i/ten_gig_eth_pcs_pma_i/*/gtxe2_i/RXOUTCLK}] -group [get_clocks XG_CLK] -set_clock_groups -asynchronous -group [get_clocks -filter {NAME =~ *sfpp_io_*/ten_gige_phy_i/ten_gig_eth_pcs_pma_i/*/gtxe2_i/TXOUTCLK}] -group [get_clocks XG_CLK] +set_clock_groups -asynchronous -group [get_clocks bus_clk] -group [get_clocks XG_CLK -include_generated_clocks] +set_clock_groups -asynchronous -group [get_clocks bus_clk_div2] -group [get_clocks XG_CLK -include_generated_clocks] +set_clock_groups -asynchronous -group [get_clocks -filter {NAME =~ *sfpp_io_*/ten_gige_phy_i/ten_gig_eth_pcs_pma_i/*/gtxe2_i/RXOUTCLK}] -group [get_clocks XG_CLK -include_generated_clocks] +set_clock_groups -asynchronous -group [get_clocks -filter {NAME =~ *sfpp_io_*/ten_gige_phy_i/ten_gig_eth_pcs_pma_i/*/gtxe2_i/TXOUTCLK}] -group [get_clocks XG_CLK -include_generated_clocks] set_false_path -to [get_pins -of_objects [get_cells -hier -filter {NAME =~ *sfpp_io_*/ten_gige_phy_i/*sync1_r_reg*}] -filter {NAME =~ *PRE}] set_false_path -to [get_pins -of_objects [get_cells -hier -filter {NAME =~ *sfpp_io_*/ten_gige_phy_i/*sync1_r_reg*}] -filter {NAME =~ *CLR}] diff --git a/fpga/usrp3/top/x400/Makefile b/fpga/usrp3/top/x400/Makefile index c40b1e69c..a1a7f40e5 100644 --- a/fpga/usrp3/top/x400/Makefile +++ b/fpga/usrp3/top/x400/Makefile @@ -145,7 +145,7 @@ X420_IP: ##Build X420 IP only. Use the -j option to build multiple IP block +$(call vivado_ip,X420,$(DEFS) X420=1) X440_IP: ##Build X440 IP only. Use the -j option to build multiple IP blocks simultaneously. - +$(call vivado_ip,X440,$(DEFS) X440=1) + +$(call vivado_ip,X440,$(DEFS) X440=1) BUILD_ALL_X440_RFDC=1 $(BUILD_DIR)/x410-version-info.dtsi: regmap/x410/versioning_regs_regmap_utils.vh tools/parse_versions_for_dts.py \ diff --git a/fpga/usrp3/top/x400/Makefile.x4xx.inc b/fpga/usrp3/top/x400/Makefile.x4xx.inc index ea094c076..70056034e 100644 --- a/fpga/usrp3/top/x400/Makefile.x4xx.inc +++ b/fpga/usrp3/top/x400/Makefile.x4xx.inc @@ -20,9 +20,6 @@ BASE_DIR = $(abspath ..) IP_DIR = $(abspath ./ip) include $(BASE_DIR)/../tools/make/viv_design_builder.mak -# Include IP directory -include $(IP_DIR)/Makefile.inc - # Include any LIB dependencies include coregen_dsp/Makefile.srcs include $(LIB_DIR)/control/Makefile.srcs @@ -51,6 +48,9 @@ ifdef BUILD_DIR include $(BUILD_DIR)/Makefile.inc endif +# Include IP directory +include $(IP_DIR)/Makefile.inc + ################################################## # Sources ################################################## diff --git a/fpga/usrp3/top/x400/build_x4xx.tcl b/fpga/usrp3/top/x400/build_x4xx.tcl index 8fb5a74e4..babe79120 100644 --- a/fpga/usrp3/top/x400/build_x4xx.tcl +++ b/fpga/usrp3/top/x400/build_x4xx.tcl @@ -10,10 +10,6 @@ source $::env(VIV_TOOLS_DIR)/scripts/viv_strategies.tcl # STEP#1: Create project, add sources, refresh IP vivado_utils::initialize_project -# STEP#1.5: Modify block diagram if needed -set script_dir [file dirname [info script]] -source [file join $script_dir x4xx_bd_modification.tcl] - # STEP#2: Run synthesis vivado_utils::synthesize_design vivado_utils::generate_post_synth_reports @@ -23,12 +19,8 @@ vivado_utils::exit_if_synth_only set strategy [vivado_strategies::get_impl_preset "Performance_ExplorePostRoutePhysOpt"] # Enable incremental build dict set strategy "implementation.incremental" $::env(VIV_INCR_BUILD) -# Turn up uncertainty on 100Gb clocks(-quiet so if it fails because the clocks don't exist, it won't error) -set_clock_uncertainty 0.5 -quiet -setup [get_clocks txoutclk_out*] # Vivado has been underestimating routing delays. dict set strategy "place_design.directive" "ExtraNetDelay_high" -# Turn down uncertainty on 100Gb clocks -dict set strategy "route_design.pre_hook" {set_clock_uncertainty 0.0 -quiet -setup [get_clocks txoutclk_out*]} vivado_strategies::implement_design $strategy # STEP#4: Generate reports diff --git a/fpga/usrp3/top/x400/ip/Makefile.inc b/fpga/usrp3/top/x400/ip/Makefile.inc index 8057b170e..dab949639 100644 --- a/fpga/usrp3/top/x400/ip/Makefile.inc +++ b/fpga/usrp3/top/x400/ip/Makefile.inc @@ -43,12 +43,12 @@ include $(IP_DIR)/adc_100m_bd/Makefile.inc include $(IP_DIR)/dac_100m_bd/Makefile.inc include $(IP_DIR)/ddr4_64bits_x440/Makefile.inc include $(IP_DIR)/x4xx_ps_rfdc_bd/x440_ps_rfdc_bd/Makefile.inc +include $(IP_DIR)/x4xx_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/Makefile.inc include $(IP_DIR)/fir_dec3_2spc/Makefile.inc include $(IP_DIR)/fir_inp3_1spc/Makefile.inc endif BD_SRCS = \ -$(IP_X4XX_PS_RFDC_BD_SRCS) \ $(IP_X4XX_PS_RFDC_HDL_SRCS) \ $(IP_AXI_INTERCONNECT_APP_BD_SRCS) \ $(IP_AXI_INTERCONNECT_ETH_BD_SRCS) \ @@ -81,11 +81,25 @@ $(IP_DAC_400M_HDL_SRCS) endif ifdef X440 + # Both X440 RFDC block-diagram Makefiles assign the same source and output + # variables. For a binary target, select only the RFDC variant required by + # the image core so the shared variables identify the correct sources. For + # the IP target, BUILD_ALL_X440_RFDC selects both variants so all generated + # IP is available. + ifeq ($(BUILD_ALL_X440_RFDC),1) + BD_SRCS += $(IP_X4XX_PS_RFDC_BD_SRCS) $(IP_X4XX_2SPC_PS_RFDC_BD_SRCS) + else ifneq (,$(findstring X440_2SPC_PS_RFDC_BD=1,$(RFNOC_IMAGE_CORE_DEFS))) + BD_SRCS += $(IP_X4XX_2SPC_PS_RFDC_BD_SRCS) + else + BD_SRCS += $(IP_X4XX_PS_RFDC_BD_SRCS) + endif BD_SRCS += \ $(IP_ADC_100M_BD_SRCS) \ $(IP_ADC_100M_HDL_SRCS) \ $(IP_DAC_100M_BD_SRCS) \ $(IP_DAC_100M_HDL_SRCS) +else # default case for non-X440 devices + BD_SRCS += $(IP_X4XX_PS_RFDC_BD_SRCS) endif IP_XCI_SRCS = \ @@ -114,7 +128,6 @@ $(IP_FIR_INP3_1SPC_SRCS) endif BD_OUTPUTS = \ -$(BD_X4XX_PS_RFDC_BD_OUTS) \ $(BD_AXI_INTERCONNECT_APP_BD_OUTS) \ $(BD_AXI_INTERCONNECT_ETH_BD_OUTS) \ $(BD_AXI_INTERCONNECT_DMA_BD_OUTS) \ @@ -129,6 +142,15 @@ $(BD_AXI_INTER_2X512_512_BD_OUTS) \ $(BD_100G_BD_OUTS) \ $(BD_AXI_ETH_DMA_BD_OUTS) +# See the X440 BD_SRCS selection above for why these RFDC outputs are selected. +ifeq ($(BUILD_ALL_X440_RFDC),1) + BD_OUTPUTS += $(BD_X4XX_PS_RFDC_BD_OUTS) $(BD_X4XX_2SPC_PS_RFDC_BD_OUTS) +else ifneq (,$(findstring X440_2SPC_PS_RFDC_BD=1,$(RFNOC_IMAGE_CORE_DEFS))) + BD_OUTPUTS += $(BD_X4XX_2SPC_PS_RFDC_BD_OUTS) +else + BD_OUTPUTS += $(BD_X4XX_PS_RFDC_BD_OUTS) +endif + ifdef X410 BD_OUTPUTS += \ $(BD_ADC_100M_BD_OUTS) \ diff --git a/fpga/usrp3/top/x400/ip/x4xx_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/Makefile.inc b/fpga/usrp3/top/x400/ip/x4xx_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/Makefile.inc new file mode 100644 index 000000000..ef8e0e426 --- /dev/null +++ b/fpga/usrp3/top/x400/ip/x4xx_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/Makefile.inc @@ -0,0 +1,37 @@ +# +# Copyright 2026 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# + +IP_X4XX_2SPC_PS_RFDC_ORIG_SRCS = \ +$(IP_BUILD_DIR)/x440_2spc_ps_rfdc_bd_base/x440_2spc_ps_rfdc_bd_base.tcl \ +$(IP_DIR)/x4xx_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/x440_2spc_ps_rfdc_bd.tcl + +IP_X4XX_2SPC_PS_RFDC_BDTCL_SRCS = $(addprefix $(IP_BUILD_DIR)/x440_2spc_ps_rfdc_bd/, \ +x440_2spc_ps_rfdc_bd.tcl \ +) + +IP_X4XX_2SPC_PS_RFDC_BD_SRCS = $(addprefix $(IP_BUILD_DIR)/x440_2spc_ps_rfdc_bd/, \ +x440_2spc_ps_rfdc_bd/x440_2spc_ps_rfdc_bd.bd \ +) + +BD_X4XX_2SPC_PS_RFDC_BD_OUTS = $(addprefix $(IP_BUILD_DIR)/x440_2spc_ps_rfdc_bd/, \ +x440_2spc_ps_rfdc_bd.bd.out \ +x440_2spc_ps_rfdc_bd/x440_2spc_ps_rfdc_bd_ooc.xdc \ +x440_2spc_ps_rfdc_bd/synth/x440_2spc_ps_rfdc_bd.v \ +) + +.INTERMEDIATE: IP_X4XX_2SPC_PS_RFDC_BD_TRGT +$(IP_X4XX_2SPC_PS_RFDC_BD_SRCS) $(BD_X4XX_2SPC_PS_RFDC_BD_OUTS) $(IP_X4XX_2SPC_PS_RFDC_BDTCL_SRCS): IP_X4XX_2SPC_PS_RFDC_BD_TRGT + @: + +IP_X4XX_2SPC_PS_RFDC_BD_TRGT: $(IP_X4XX_2SPC_PS_RFDC_ORIG_SRCS) + $(call BUILD_VIVADO_BDTCL,x440_2spc_ps_rfdc_bd,$(ARCH),$(PART_ID),$(IP_DIR)/x4xx_ps_rfdc_bd,$(IP_BUILD_DIR),$(LIB_DIR)/vivado_ipi,$(IP_X4XX_PS_RFDC_HDL_SRCS)) + +# derive the base diagram by adding "2spc" to all strings +# This ensures that generated clock domain naming like "x440_2spc_ps_rfdc_bd_pll_ref_clk_in" still +# works fine after renaming. +$(IP_BUILD_DIR)/x440_2spc_ps_rfdc_bd_base/x440_2spc_ps_rfdc_bd_base.tcl: $(IP_DIR)/x4xx_ps_rfdc_bd/x440_ps_rfdc_bd/x440_ps_rfdc_bd.tcl + mkdir -p $(dir $@) + sed 's/x440_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/g' $< > $@ diff --git a/fpga/usrp3/top/x400/ip/x4xx_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/x440_2spc_ps_rfdc_bd.tcl b/fpga/usrp3/top/x400/ip/x4xx_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/x440_2spc_ps_rfdc_bd.tcl new file mode 100644 index 000000000..72d80121f --- /dev/null +++ b/fpga/usrp3/top/x400/ip/x4xx_ps_rfdc_bd/x440_2spc_ps_rfdc_bd/x440_2spc_ps_rfdc_bd.tcl @@ -0,0 +1,76 @@ +# +# Copyright 2026 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# +# Module: x440_2spc_ps_rfdc_bd +# +# Description: +# +# Manual X440 RFDC block-design wrapper for the 2-samples-per-cycle +# configuration. The base block-design Tcl is generated from the original +# X440 design with its design and clock-domain names adapted for this +# variant. This script applies the RFDC data-width and interface-width +# changes required by the 2-SPC datapath, then validates and saves the +# resulting block design. +# + +# Reuse the original x440 block diagram after renaming. +source ../x440_2spc_ps_rfdc_bd_base/x440_2spc_ps_rfdc_bd_base.tcl + +# Change the RFDC data path to 2 samples / cycle. +# This requires the decimation and interpolation modes to be set to 8. +# As the original configuration is 8 samples / cycle at using 2 times +# resampling the clock rates stay the same. +set_property -dict [list \ + CONFIG.ADC0_Multi_Tile_Sync {true} \ + CONFIG.ADC_Decimation_Mode00 {8} \ + CONFIG.ADC_Data_Width00 {2} \ + CONFIG.ADC_Decimation_Mode01 {8} \ + CONFIG.ADC_Data_Width01 {2} \ + CONFIG.ADC_Data_Width02 {2} \ + CONFIG.ADC_Data_Width03 {2} \ + CONFIG.ADC1_Multi_Tile_Sync {true} \ + CONFIG.ADC_Data_Width10 {2} \ + CONFIG.ADC_Data_Width11 {2} \ + CONFIG.ADC_Data_Width12 {2} \ + CONFIG.ADC_Data_Width13 {2} \ + CONFIG.ADC2_Multi_Tile_Sync {true} \ + CONFIG.ADC_Data_Width20 {2} \ + CONFIG.ADC_Data_Width21 {2} \ + CONFIG.ADC_Data_Width22 {2} \ + CONFIG.ADC_Data_Width23 {2} \ + CONFIG.ADC3_Multi_Tile_Sync {true} \ + CONFIG.ADC_Data_Width30 {2} \ + CONFIG.ADC_Data_Width31 {2} \ + CONFIG.ADC_Data_Width32 {2} \ + CONFIG.ADC_Data_Width33 {2} \ + CONFIG.DAC0_Multi_Tile_Sync {true} \ + CONFIG.DAC_Data_Width00 {4} \ + CONFIG.DAC_Data_Width01 {4} \ + CONFIG.DAC_Data_Width02 {4} \ + CONFIG.DAC_Data_Width03 {4} \ + CONFIG.DAC1_Multi_Tile_Sync {true} \ + CONFIG.DAC_Data_Width10 {4} \ + CONFIG.DAC_Data_Width11 {4} \ + CONFIG.DAC_Data_Width12 {4} \ + CONFIG.DAC_Data_Width13 {4} \ + ] [get_bd_cells rfdc/rf_data_converter] + + +# The changed RFDC interfaces have to be reflected in the upstream AXI +# interfaces. A change to 2 samples/cycle is required for the calibration +# muxes. +set_property -dict [list CONFIG.kAxiWidth {64}] [get_bd_cells rfdc/calibration_muxes/gpio_to_axis_mux_0] +set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile228_ch0_din] +set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile228_ch1_din] +set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile228_ch2_din] +set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile228_ch3_din] +set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile229_ch0_din] +set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile229_ch1_din] +set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile229_ch2_din] +set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile229_ch3_din] + +# revalidate and save the block design +validate_bd_design +save_bd_design diff --git a/fpga/usrp3/top/x400/x4xx.sv b/fpga/usrp3/top/x400/x4xx.sv index 481b2aa31..7906db898 100644 --- a/fpga/usrp3/top/x400/x4xx.sv +++ b/fpga/usrp3/top/x400/x4xx.sv @@ -570,7 +570,7 @@ module x4xx ( // Input Clock Freq (MHz) Input Jitter (UI) //---------------------------------------------------------------------------- // __primary_____________200____________0.010 - + wire fast_ce_gen_clkfbout; wire fast_ce_gen_clkout0; wire fast_ce_clk; @@ -1886,7 +1886,11 @@ module x4xx ( .clk_adc0 () ); `elsif X440 + `ifdef X440_2SPC_PS_RFDC_BD + x440_2spc_ps_rfdc_bd x440_ps_rfdc_bd_i ( + `else x440_ps_rfdc_bd x440_ps_rfdc_bd_i ( + `endif .adc_enable_data_r0clk (adc_enable_data_rclk[0]), .adc_enable_data_r1clk (adc_enable_data_rclk[1]), .adc_reset_pulse_r0clk (adc_reset_pulse[0]), diff --git a/fpga/usrp3/top/x400/x4xx_bd_modification.tcl b/fpga/usrp3/top/x400/x4xx_bd_modification.tcl deleted file mode 100644 index 21e1d1842..000000000 --- a/fpga/usrp3/top/x400/x4xx_bd_modification.tcl +++ /dev/null @@ -1,83 +0,0 @@ - -# Extract the Verilog defines from the environment (optional variable) -set viv_defs "" -if { [info exists ::env(VIV_VERILOG_DEFS)] } { - set viv_defs $::env(VIV_VERILOG_DEFS) -} - -# Only apply these modifications for X440 with 200M RF bandwidth image -if {[regexp {X440=1} $viv_defs] && [regexp {RF_BW=200} $viv_defs] && [regexp {USE_FABRIC_RESAMPLERS=1} $viv_defs]} { - - # print a message to indicate that the modifications are being applied - puts "Applying X440 200M RF modifications to block design" - - # Load the custom HDL sources required by the block design IP before opening it. - set script_dir [file dirname [file normalize [info script]]] - source [file join $script_dir ip x4xx_ps_rfdc_bd x440_ps_rfdc_bd hdl_sources.tcl] - - # open the existing block design - open_bd_design [get_files x440_ps_rfdc_bd.bd] - - # Change the RFDC data path to 2 samples / cycle. - # This requires the decimation and interpolation modes to be set to 8. - # As the original configuration is 8 samples / cycle at using 2 times - # resampling the clock rates stay the same. - set_property -dict [list \ - CONFIG.ADC0_Multi_Tile_Sync {true} \ - CONFIG.ADC_Decimation_Mode00 {8} \ - CONFIG.ADC_Data_Width00 {2} \ - CONFIG.ADC_Decimation_Mode01 {8} \ - CONFIG.ADC_Data_Width01 {2} \ - CONFIG.ADC_Data_Width02 {2} \ - CONFIG.ADC_Data_Width03 {2} \ - CONFIG.ADC1_Multi_Tile_Sync {true} \ - CONFIG.ADC_Data_Width10 {2} \ - CONFIG.ADC_Data_Width11 {2} \ - CONFIG.ADC_Data_Width12 {2} \ - CONFIG.ADC_Data_Width13 {2} \ - CONFIG.ADC2_Multi_Tile_Sync {true} \ - CONFIG.ADC_Data_Width20 {2} \ - CONFIG.ADC_Data_Width21 {2} \ - CONFIG.ADC_Data_Width22 {2} \ - CONFIG.ADC_Data_Width23 {2} \ - CONFIG.ADC3_Multi_Tile_Sync {true} \ - CONFIG.ADC_Data_Width30 {2} \ - CONFIG.ADC_Data_Width31 {2} \ - CONFIG.ADC_Data_Width32 {2} \ - CONFIG.ADC_Data_Width33 {2} \ - CONFIG.DAC0_Multi_Tile_Sync {true} \ - CONFIG.DAC_Data_Width00 {4} \ - CONFIG.DAC_Data_Width01 {4} \ - CONFIG.DAC_Data_Width02 {4} \ - CONFIG.DAC_Data_Width03 {4} \ - CONFIG.DAC1_Multi_Tile_Sync {true} \ - CONFIG.DAC_Data_Width10 {4} \ - CONFIG.DAC_Data_Width11 {4} \ - CONFIG.DAC_Data_Width12 {4} \ - CONFIG.DAC_Data_Width13 {4} \ - ] [get_bd_cells rfdc/rf_data_converter] - - - # The changed RFDC interfaces have to be reflected in the upstream AXI - # interfaces. A change to 2 samples/cycle is required for the calibration - # muxes. - set_property -dict [list CONFIG.kAxiWidth {64}] [get_bd_cells rfdc/calibration_muxes/gpio_to_axis_mux_0] - set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile228_ch0_din] - set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile228_ch1_din] - set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile228_ch2_din] - set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile228_ch3_din] - set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile229_ch0_din] - set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile229_ch1_din] - set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile229_ch2_din] - set_property -dict [list CONFIG.TDATA_NUM_BYTES {8}] [get_bd_intf_ports dac_tile229_ch3_din] - - # revalidate and save the block design - validate_bd_design - save_bd_design - - # regenerate the output products to avoid any stale intermediate files - generate_target all [get_files x440_ps_rfdc_bd.bd] - - # close the block design after applying all changes - close_bd_design [current_bd_design] -} diff --git a/host/include/uhd/rfnoc/core/x440_bsp.yml b/host/include/uhd/rfnoc/core/x440_bsp.yml index f281a7209..4ee67a49b 100644 --- a/host/include/uhd/rfnoc/core/x440_bsp.yml +++ b/host/include/uhd/rfnoc/core/x440_bsp.yml @@ -74,7 +74,7 @@ make_defs: - DRAM_BANKS=${0 if not parameters['ENABLE_DRAM'] else parameters['NUM_DRAM_BANKS']} - DRAM_CH=${0 if not parameters['ENABLE_DRAM'] else parameters['NUM_DRAM_CHANS']} - DRAM_W=${parameters['DRAM_WIDTH']} - - USE_FABRIC_RESAMPLERS=${1 if parameters['USE_FABRIC_RESAMPLERS'] else 0} + - ${"X440_2SPC_PS_RFDC_BD=1" if parameters['USE_FABRIC_RESAMPLERS'] else ""} - DISABLE_TX=${1 if parameters['DISABLE_TX'] else 0} - ENABLE_CLOCK_WD=${1 if parameters['ENABLE_CLOCK_WD'] else 0}