feat(rtl): add radar_system_top_50t wrapper to solve IO pin overflow
The XC7A50T-FTG256 has only 69 usable IO pins but radar_system_top declares 182 port bits. Previous attempts to remove unconstrained ports via TCL caused opt_design to cascade-remove all driving logic. New approach: radar_system_top_50t.v is a thin wrapper that: - Exposes only the 64 physically-connected ports (ADC, DAC, SPI, clocks) - Instantiates radar_system_top internally with full logic preserved - Ties off unused inputs (FT601 bus, ext trigger) to safe defaults - Leaves unused outputs internally connected (no IOBs created) Updated build_50t_test.tcl to use radar_system_top_50t as top module and removed the now-unnecessary port removal TCL code.
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/**
|
||||
* radar_system_top_50t.v
|
||||
*
|
||||
* 50T Production Wrapper for radar_system_top
|
||||
*
|
||||
* The XC7A50T-FTG256 has only 69 usable IO pins, but radar_system_top
|
||||
* declares 182 port bits (including FT601 USB 3.0, debug outputs, and
|
||||
* status signals that have no physical connections on the 50T board).
|
||||
*
|
||||
* This wrapper exposes only the 64 physically-connected ports and ties
|
||||
* off unused inputs. Unused outputs remain internally connected so the
|
||||
* full radar pipeline is preserved in the netlist.
|
||||
*/
|
||||
|
||||
module radar_system_top_50t (
|
||||
// ===== System Clocks (Bank 15: 3.3V) =====
|
||||
input wire clk_100m,
|
||||
input wire clk_120m_dac,
|
||||
input wire reset_n,
|
||||
|
||||
// ===== DAC Interface (Bank 15: 3.3V) =====
|
||||
output wire [7:0] dac_data,
|
||||
output wire dac_sleep,
|
||||
|
||||
// ===== RF Control (Bank 15: 3.3V) =====
|
||||
output wire fpga_rf_switch,
|
||||
output wire rx_mixer_en,
|
||||
output wire tx_mixer_en,
|
||||
|
||||
// ===== ADAR1000 Beamformer (Bank 34: 1.8V) =====
|
||||
output wire adar_tx_load_1, adar_rx_load_1,
|
||||
output wire adar_tx_load_2, adar_rx_load_2,
|
||||
output wire adar_tx_load_3, adar_rx_load_3,
|
||||
output wire adar_tx_load_4, adar_rx_load_4,
|
||||
output wire adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4,
|
||||
|
||||
// ===== STM32 SPI 3.3V side (Bank 15) =====
|
||||
input wire stm32_sclk_3v3,
|
||||
input wire stm32_mosi_3v3,
|
||||
output wire stm32_miso_3v3,
|
||||
input wire stm32_cs_adar1_3v3, stm32_cs_adar2_3v3,
|
||||
input wire stm32_cs_adar3_3v3, stm32_cs_adar4_3v3,
|
||||
|
||||
// ===== STM32 SPI 1.8V side (Bank 34) =====
|
||||
output wire stm32_sclk_1v8,
|
||||
output wire stm32_mosi_1v8,
|
||||
input wire stm32_miso_1v8,
|
||||
output wire stm32_cs_adar1_1v8, stm32_cs_adar2_1v8,
|
||||
output wire stm32_cs_adar3_1v8, stm32_cs_adar4_1v8,
|
||||
|
||||
// ===== ADC Interface (Bank 14: LVDS_25) =====
|
||||
input wire [7:0] adc_d_p,
|
||||
input wire [7:0] adc_d_n,
|
||||
input wire adc_dco_p,
|
||||
input wire adc_dco_n,
|
||||
output wire adc_pwdn,
|
||||
|
||||
// ===== STM32 Control (Bank 15: 3.3V) =====
|
||||
input wire stm32_new_chirp,
|
||||
input wire stm32_new_elevation,
|
||||
input wire stm32_new_azimuth,
|
||||
input wire stm32_mixers_enable
|
||||
);
|
||||
|
||||
// ===== Tie-off wires for unconstrained inputs =====
|
||||
wire ft601_clk_in_tied = 1'b0;
|
||||
wire ft601_txe_tied = 1'b0;
|
||||
wire ft601_rxf_tied = 1'b0;
|
||||
wire [1:0] ft601_srb_tied = 2'b00;
|
||||
wire [1:0] ft601_swb_tied = 2'b00;
|
||||
|
||||
// ===== FT601 inout bus — tie to high-Z =====
|
||||
wire [31:0] ft601_data_internal;
|
||||
assign ft601_data_internal = 32'hZZZZZZZZ;
|
||||
|
||||
// ===== Unconnected output wires (synthesis preserves driving logic) =====
|
||||
wire dac_clk_nc;
|
||||
wire [3:0] ft601_be_nc;
|
||||
wire ft601_txe_n_nc;
|
||||
wire ft601_rxf_n_nc;
|
||||
wire ft601_wr_n_nc;
|
||||
wire ft601_rd_n_nc;
|
||||
wire ft601_oe_n_nc;
|
||||
wire ft601_siwu_n_nc;
|
||||
wire ft601_clk_out_nc;
|
||||
wire [5:0] current_elevation_nc;
|
||||
wire [5:0] current_azimuth_nc;
|
||||
wire [5:0] current_chirp_nc;
|
||||
wire new_chirp_frame_nc;
|
||||
wire [31:0] dbg_doppler_data_nc;
|
||||
wire dbg_doppler_valid_nc;
|
||||
wire [4:0] dbg_doppler_bin_nc;
|
||||
wire [5:0] dbg_range_bin_nc;
|
||||
wire [3:0] system_status_nc;
|
||||
|
||||
radar_system_top u_core (
|
||||
// ----- Clocks & Reset -----
|
||||
.clk_100m (clk_100m),
|
||||
.clk_120m_dac (clk_120m_dac),
|
||||
.ft601_clk_in (ft601_clk_in_tied),
|
||||
.reset_n (reset_n),
|
||||
|
||||
// ----- DAC -----
|
||||
.dac_data (dac_data),
|
||||
.dac_clk (dac_clk_nc),
|
||||
.dac_sleep (dac_sleep),
|
||||
|
||||
// ----- RF -----
|
||||
.fpga_rf_switch (fpga_rf_switch),
|
||||
.rx_mixer_en (rx_mixer_en),
|
||||
.tx_mixer_en (tx_mixer_en),
|
||||
|
||||
// ----- Beamformer -----
|
||||
.adar_tx_load_1 (adar_tx_load_1),
|
||||
.adar_rx_load_1 (adar_rx_load_1),
|
||||
.adar_tx_load_2 (adar_tx_load_2),
|
||||
.adar_rx_load_2 (adar_rx_load_2),
|
||||
.adar_tx_load_3 (adar_tx_load_3),
|
||||
.adar_rx_load_3 (adar_rx_load_3),
|
||||
.adar_tx_load_4 (adar_tx_load_4),
|
||||
.adar_rx_load_4 (adar_rx_load_4),
|
||||
.adar_tr_1 (adar_tr_1),
|
||||
.adar_tr_2 (adar_tr_2),
|
||||
.adar_tr_3 (adar_tr_3),
|
||||
.adar_tr_4 (adar_tr_4),
|
||||
|
||||
// ----- SPI 3.3V -----
|
||||
.stm32_sclk_3v3 (stm32_sclk_3v3),
|
||||
.stm32_mosi_3v3 (stm32_mosi_3v3),
|
||||
.stm32_miso_3v3 (stm32_miso_3v3),
|
||||
.stm32_cs_adar1_3v3 (stm32_cs_adar1_3v3),
|
||||
.stm32_cs_adar2_3v3 (stm32_cs_adar2_3v3),
|
||||
.stm32_cs_adar3_3v3 (stm32_cs_adar3_3v3),
|
||||
.stm32_cs_adar4_3v3 (stm32_cs_adar4_3v3),
|
||||
|
||||
// ----- SPI 1.8V -----
|
||||
.stm32_sclk_1v8 (stm32_sclk_1v8),
|
||||
.stm32_mosi_1v8 (stm32_mosi_1v8),
|
||||
.stm32_miso_1v8 (stm32_miso_1v8),
|
||||
.stm32_cs_adar1_1v8 (stm32_cs_adar1_1v8),
|
||||
.stm32_cs_adar2_1v8 (stm32_cs_adar2_1v8),
|
||||
.stm32_cs_adar3_1v8 (stm32_cs_adar3_1v8),
|
||||
.stm32_cs_adar4_1v8 (stm32_cs_adar4_1v8),
|
||||
|
||||
// ----- ADC -----
|
||||
.adc_d_p (adc_d_p),
|
||||
.adc_d_n (adc_d_n),
|
||||
.adc_dco_p (adc_dco_p),
|
||||
.adc_dco_n (adc_dco_n),
|
||||
.adc_pwdn (adc_pwdn),
|
||||
|
||||
// ----- STM32 Control -----
|
||||
.stm32_new_chirp (stm32_new_chirp),
|
||||
.stm32_new_elevation (stm32_new_elevation),
|
||||
.stm32_new_azimuth (stm32_new_azimuth),
|
||||
.stm32_mixers_enable (stm32_mixers_enable),
|
||||
|
||||
// ----- FT601 (unwired on 50T) -----
|
||||
.ft601_data (ft601_data_internal),
|
||||
.ft601_be (ft601_be_nc),
|
||||
.ft601_txe_n (ft601_txe_n_nc),
|
||||
.ft601_rxf_n (ft601_rxf_n_nc),
|
||||
.ft601_txe (ft601_txe_tied),
|
||||
.ft601_rxf (ft601_rxf_tied),
|
||||
.ft601_wr_n (ft601_wr_n_nc),
|
||||
.ft601_rd_n (ft601_rd_n_nc),
|
||||
.ft601_oe_n (ft601_oe_n_nc),
|
||||
.ft601_siwu_n (ft601_siwu_n_nc),
|
||||
.ft601_srb (ft601_srb_tied),
|
||||
.ft601_swb (ft601_swb_tied),
|
||||
.ft601_clk_out (ft601_clk_out_nc),
|
||||
|
||||
// ----- Status/Debug (no pins on 50T) -----
|
||||
.current_elevation (current_elevation_nc),
|
||||
.current_azimuth (current_azimuth_nc),
|
||||
.current_chirp (current_chirp_nc),
|
||||
.new_chirp_frame (new_chirp_frame_nc),
|
||||
.dbg_doppler_data (dbg_doppler_data_nc),
|
||||
.dbg_doppler_valid (dbg_doppler_valid_nc),
|
||||
.dbg_doppler_bin (dbg_doppler_bin_nc),
|
||||
.dbg_range_bin (dbg_range_bin_nc),
|
||||
.system_status (system_status_nc)
|
||||
);
|
||||
|
||||
endmodule
|
||||
@@ -9,7 +9,7 @@ set project_root [file normalize [file join $script_dir ".."]]
|
||||
set project_dir [file join $project_root "build_50t"]
|
||||
set rtl_dir $project_root
|
||||
set fpga_part "xc7a50tftg256-2"
|
||||
set top_module "radar_system_top"
|
||||
set top_module "radar_system_top_50t"
|
||||
|
||||
puts "================================================================"
|
||||
puts " AERIS-10 — XC7A50T Production Build"
|
||||
@@ -51,7 +51,12 @@ add_files -fileset constrs_1 -norecurse [file join $project_root "constraints" "
|
||||
# NOTE: DRC severity waivers are set both before synthesis and after open_run
|
||||
# synth_1. Implementation uses direct commands (opt_design, place_design, etc.)
|
||||
# rather than launch_runs/wait_on_run, so all commands share the same Vivado
|
||||
# context. This also allows removing unconstrained ports before placement.
|
||||
# context where the waivers are active.
|
||||
#
|
||||
# The top module is radar_system_top_50t — a thin wrapper that exposes only
|
||||
# the 64 physically-connected ports on the FTG256 board. Unconstrained ports
|
||||
# (FT601, debug, status) are tied off internally, keeping the full radar
|
||||
# pipeline intact while fitting within the 69 available IO pins.
|
||||
#
|
||||
# BIVC-1: Bank 14 VCCO=2.5V (enforced by LVDS_25) with LVCMOS25 adc_pwdn.
|
||||
# This should no longer fire now that adc_pwdn is LVCMOS25, but we keep
|
||||
@@ -86,8 +91,8 @@ report_utilization -file "${report_dir}/01_utilization_post_synth.rpt"
|
||||
|
||||
# ===== IMPLEMENTATION (non-project-mode style) =====
|
||||
# We run implementation steps directly in the parent process instead of
|
||||
# using launch_runs/wait_on_run. This ensures DRC waivers and port removal
|
||||
# commands execute in the same Vivado context as place_design.
|
||||
# using launch_runs/wait_on_run. This ensures DRC waivers are active in
|
||||
# the same Vivado context as place_design.
|
||||
set impl_start [clock seconds]
|
||||
|
||||
# Re-apply DRC waivers in this context (parent process)
|
||||
@@ -95,43 +100,6 @@ set_property SEVERITY {Warning} [get_drc_checks BIVC-1]
|
||||
set_property SEVERITY {Warning} [get_drc_checks NSTD-1]
|
||||
set_property SEVERITY {Warning} [get_drc_checks UCIO-1]
|
||||
|
||||
# ---- Remove unconstrained ports from netlist ----
|
||||
# The 50T board (FTG256, 69 usable IOs) cannot accommodate all 182 port bits.
|
||||
# These ports have no physical connections on the 50T PCB: FT601 USB 3.0
|
||||
# (chip unwired), dac_clk (driven by AD9523, not FPGA), and all
|
||||
# status/debug outputs. Removing them from the netlist avoids [Place 30-58].
|
||||
set unconstrained_ports {
|
||||
ft601_clk_in ft601_data ft601_be ft601_txe_n ft601_rxf_n
|
||||
ft601_txe ft601_rxf ft601_wr_n ft601_rd_n ft601_oe_n
|
||||
ft601_siwu_n ft601_srb ft601_swb ft601_clk_out
|
||||
dac_clk
|
||||
current_elevation current_azimuth current_chirp new_chirp_frame
|
||||
dbg_doppler_data dbg_doppler_valid dbg_doppler_bin dbg_range_bin
|
||||
system_status
|
||||
}
|
||||
set removed_count 0
|
||||
foreach p $unconstrained_ports {
|
||||
# Match scalar port or bus port bits (e.g., "ft601_data" matches ft601_data[*])
|
||||
set port_objs [get_ports -quiet "${p}\[*\]"]
|
||||
if {[llength $port_objs] == 0} {
|
||||
set port_objs [get_ports -quiet $p]
|
||||
}
|
||||
foreach port_obj $port_objs {
|
||||
# Disconnect the net(s) driving/driven by this port first
|
||||
set net_objs [get_nets -quiet -of_objects $port_obj]
|
||||
foreach net_obj $net_objs {
|
||||
catch {disconnect_net -net $net_obj -objects $port_obj}
|
||||
}
|
||||
# Now remove the disconnected port
|
||||
if {[catch {remove_port $port_obj} err]} {
|
||||
puts " WARN: Could not remove port $port_obj: $err"
|
||||
} else {
|
||||
incr removed_count
|
||||
}
|
||||
}
|
||||
}
|
||||
puts " Removed $removed_count unconstrained port(s) from netlist"
|
||||
|
||||
# ---- Run implementation steps ----
|
||||
opt_design -directive Explore
|
||||
place_design -directive Explore
|
||||
|
||||
Reference in New Issue
Block a user