Migrate hardware platform from XC7A50T to XC7A200T-2FBG484I

Production FPGA: Artix-7 XC7A200T-2FBG484I (33,650 slices, 740 DSP48E1,
365 BRAM, -2 speed grade). Pin-mapped across 6 banks with proper VCCO
assignment (3.3V/2.5V/1.8V).

RTL timing primitives added for clean timing closure:
- ad9484_interface_400m.v: BUFIO for IDDR capture at 400MHz DDR,
  BUFG for fabric logic, reset synchronizer (P1-7)
- dac_interface_single.v: ODDR for dac_clk forwarding + dac_data[7:0]
  output registration, eliminates clock-forwarding insertion delay
- usb_data_interface.v: ODDR for ft601_clk_out forwarding, FSM runs
  on ft601_clk_in domain with CDC synchronizers

Constraints:
- New production XDC (xc7a200t_fbg484.xdc): 182 pins, generated clocks
  for ODDR outputs, BUFIO/DDR input delays, fixed false_path strategy
  (from reset source, not to CLR pins), IOB packing on cells not ports
- Preserved upstream XDC as xc7a50t_ftg256.xdc for reference
- Updated cntrt.xdc with DRC fixes (I/O standards, missing constraints)
This commit is contained in:
Jason
2026-03-16 22:24:22 +02:00
parent fd6094ee9e
commit 1acedf494c
7 changed files with 1431 additions and 276 deletions
+55 -8
View File
@@ -44,8 +44,24 @@ IBUFDS #(
.IB(adc_dco_n) .IB(adc_dco_n)
); );
// Global clock buffer for DCO — used as 400MHz clock throughout receiver // ============================================================================
wire adc_dco_buffered; // Clock buffering strategy for source-synchronous ADC interface:
//
// BUFIO: Near-zero insertion delay, can only drive IOB primitives (IDDR).
// Used for IDDR clocking to match the data path delay through IBUFDS.
// This eliminates the hold violation caused by BUFG insertion delay.
//
// BUFG: Global clock buffer for fabric logic (downstream processing).
// Has ~4 ns insertion delay but that's fine for fabric-to-fabric paths.
// ============================================================================
wire adc_dco_bufio; // Near-zero delay — drives IDDR only
wire adc_dco_buffered; // BUFG output — drives fabric logic
BUFIO bufio_dco (
.I(adc_dco),
.O(adc_dco_bufio)
);
BUFG bufg_dco ( BUFG bufg_dco (
.I(adc_dco), .I(adc_dco),
.O(adc_dco_buffered) .O(adc_dco_buffered)
@@ -53,8 +69,8 @@ BUFG bufg_dco (
assign adc_dco_bufg = adc_dco_buffered; assign adc_dco_bufg = adc_dco_buffered;
// IDDR for capturing DDR data // IDDR for capturing DDR data
wire [7:0] adc_data_rise; // Data on rising edge wire [7:0] adc_data_rise; // Data on rising edge (BUFIO domain)
wire [7:0] adc_data_fall; // Data on falling edge wire [7:0] adc_data_fall; // Data on falling edge (BUFIO domain)
genvar j; genvar j;
generate generate
@@ -67,7 +83,7 @@ generate
) iddr_inst ( ) iddr_inst (
.Q1(adc_data_rise[j]), // Rising edge data .Q1(adc_data_rise[j]), // Rising edge data
.Q2(adc_data_fall[j]), // Falling edge data .Q2(adc_data_fall[j]), // Falling edge data
.C(adc_dco_buffered), // 400MHz DCO (buffered) .C(adc_dco_bufio), // BUFIO clock (near-zero insertion delay)
.CE(1'b1), .CE(1'b1),
.D(adc_data[j]), .D(adc_data[j]),
.R(1'b0), .R(1'b0),
@@ -76,13 +92,44 @@ generate
end end
endgenerate endgenerate
// ============================================================================
// Re-register IDDR outputs into BUFG domain
// IDDR with SAME_EDGE_PIPELINED produces outputs stable for a full clock cycle.
// BUFIO and BUFG are derived from the same source (adc_dco), so they are
// frequency-matched. This single register stage transfers from IOB (BUFIO)
// to fabric (BUFG) with guaranteed timing.
// ============================================================================
reg [7:0] adc_data_rise_bufg;
reg [7:0] adc_data_fall_bufg;
always @(posedge adc_dco_buffered) begin
adc_data_rise_bufg <= adc_data_rise;
adc_data_fall_bufg <= adc_data_fall;
end
// Combine rising and falling edge data to get 400MSPS stream // Combine rising and falling edge data to get 400MSPS stream
reg [7:0] adc_data_400m_reg; reg [7:0] adc_data_400m_reg;
reg adc_data_valid_400m_reg; reg adc_data_valid_400m_reg;
reg dco_phase; reg dco_phase;
// Reset synchronizer
// reset_n comes from the 100 MHz sys_clk domain. Assertion (going low)
// is asynchronous and safe the FFs enter reset instantly. De-assertion
// (going high) must be synchronised to adc_dco_buffered to avoid
// metastability. This is the classic "async assert, sync de-assert" pattern.
(* ASYNC_REG = "TRUE" *) reg [1:0] reset_sync_400m;
wire reset_n_400m;
always @(posedge adc_dco_buffered or negedge reset_n) begin always @(posedge adc_dco_buffered or negedge reset_n) begin
if (!reset_n) begin if (!reset_n)
reset_sync_400m <= 2'b00; // async assert
else
reset_sync_400m <= {reset_sync_400m[0], 1'b1}; // sync de-assert
end
assign reset_n_400m = reset_sync_400m[1];
always @(posedge adc_dco_buffered or negedge reset_n_400m) begin
if (!reset_n_400m) begin
adc_data_400m_reg <= 8'b0; adc_data_400m_reg <= 8'b0;
adc_data_valid_400m_reg <= 1'b0; adc_data_valid_400m_reg <= 1'b0;
dco_phase <= 1'b0; dco_phase <= 1'b0;
@@ -91,10 +138,10 @@ always @(posedge adc_dco_buffered or negedge reset_n) begin
if (dco_phase) begin if (dco_phase) begin
// Output falling edge data (completes the 400MSPS stream) // Output falling edge data (completes the 400MSPS stream)
adc_data_400m_reg <= adc_data_fall; adc_data_400m_reg <= adc_data_fall_bufg;
end else begin end else begin
// Output rising edge data // Output rising edge data
adc_data_400m_reg <= adc_data_rise; adc_data_400m_reg <= adc_data_rise_bufg;
end end
adc_data_valid_400m_reg <= 1'b1; // Always valid when ADC is running adc_data_valid_400m_reg <= 1'b1; // Always valid when ADC is running
+207 -253
View File
@@ -1,307 +1,260 @@
# ============================================================================ # ============================================================================
# RADAR SYSTEM FPGA CONSTRAINTS # RADAR SYSTEM FPGA CONSTRAINTS
# ============================================================================ # ============================================================================
# Device: [XC7A100T] # Device: XC7A50T-2FTG256I (FTG256 package)
# Created: [DATE] # Board: AERIS-10 Phased Array Radar — Main Board
# Description: Main constraints file for radar system with FT601 USB 3.0 # Source: Pin assignments extracted from Eagle schematic (RADAR_Main_Board.sch)
# FPGA = U42
#
# NOTE: The README and prior version of this file incorrectly referenced
# XC7A100TCSG324-1. The physical board uses XC7A50T in a 256-ball BGA
# (FTG256). All PACKAGE_PIN values below are FTG256 ball locations.
#
# I/O Bank Voltage Summary:
# Bank 0: VCCO = 3.3V (JTAG, flash CS)
# Bank 14: VCCO = 3.3V (ADC LVDS data, SPI flash)
# Bank 15: VCCO = 3.3V (DAC, clocks, STM32 SPI 3.3V side, DIG bus, mixer)
# Bank 34: VCCO = 1.8V (ADAR1000 beamformer control, SPI 1.8V side)
# Bank 35: VCCO = 3.3V (unused — no signal connections)
# ============================================================================ # ============================================================================
# ============================================================================ # ============================================================================
# CLOCK CONSTRAINTS # CLOCK CONSTRAINTS
# ============================================================================ # ============================================================================
# 100MHz System Clock # 100MHz System Clock (AD9523 OUT6 → FPGA_SYS_CLOCK → Bank 15 MRCC pin E12)
set_property PACKAGE_PIN E12 [get_ports {clk_100m}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_100m}]
create_clock -name clk_100m -period 10.0 [get_ports {clk_100m}] create_clock -name clk_100m -period 10.0 [get_ports {clk_100m}]
set_input_jitter [get_clocks clk_100m] 0.1 set_input_jitter [get_clocks clk_100m] 0.1
# 120MHz DAC Clock # 120MHz DAC Clock (AD9523 OUT11 → FPGA_DAC_CLOCK → Bank 15 MRCC pin C13)
# NOTE: The physical DAC (U3, AD9708) receives its clock directly from the
# AD9523 via a separate net (DAC_CLOCK), NOT from the FPGA. The FPGA
# uses this clock input for internal DAC data timing only. The RTL port
# `dac_clk` is an output that assigns clk_120m directly — it has no
# separate physical pin on this board and should be removed from the
# RTL or left unconnected.
set_property PACKAGE_PIN C13 [get_ports {clk_120m_dac}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_120m_dac}]
create_clock -name clk_120m_dac -period 8.333 [get_ports {clk_120m_dac}] create_clock -name clk_120m_dac -period 8.333 [get_ports {clk_120m_dac}]
set_input_jitter [get_clocks clk_120m_dac] 0.1 set_input_jitter [get_clocks clk_120m_dac] 0.1
# FT601 Clock (100MHz from FT601) # ADC DCO Clock (400MHz LVDS — AD9523 OUT5 → AD9484 → FPGA, Bank 14 MRCC)
create_clock -name ft601_clk_in -period 10.0 [get_ports {ft601_clk_in}] set_property PACKAGE_PIN N14 [get_ports {adc_dco_p}]
set_input_jitter [get_clocks ft601_clk_in] 0.1 set_property PACKAGE_PIN P14 [get_ports {adc_dco_n}]
set_property IOSTANDARD LVDS_33 [get_ports {adc_dco_p}]
# ADC DCO Clock (400MHz LVDS) set_property IOSTANDARD LVDS_33 [get_ports {adc_dco_n}]
set_property DIFF_TERM TRUE [get_ports {adc_dco_p}]
create_clock -name adc_dco_p -period 2.5 [get_ports {adc_dco_p}] create_clock -name adc_dco_p -period 2.5 [get_ports {adc_dco_p}]
set_input_jitter [get_clocks adc_dco_p] 0.05 set_input_jitter [get_clocks adc_dco_p] 0.05
# ============================================================================ # --------------------------------------------------------------------------
# RESET CONSTRAINTS # FT601 Clock — COMMENTED OUT: FT601 (U6) is placed in schematic but has
# ============================================================================ # zero net connections. No physical clock pin exists on this board.
# --------------------------------------------------------------------------
# create_clock -name ft601_clk_in -period 10.0 [get_ports {ft601_clk_in}]
# set_input_jitter [get_clocks ft601_clk_in] 0.1
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {reset_n}] # ============================================================================
# RESET (Active-Low)
# ============================================================================
# DIG_4 (STM32 PD12 → FPGA Bank 15 pin E15)
# STM32 firmware uses HAL_GPIO_WritePin to assert/deassert FPGA reset.
set_property PACKAGE_PIN E15 [get_ports {reset_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {reset_n}] set_property IOSTANDARD LVCMOS33 [get_ports {reset_n}]
set_property PULLUP true [get_ports {reset_n}] set_property PULLUP true [get_ports {reset_n}]
# ============================================================================ # ============================================================================
# TRANSMITTER INTERFACE (DAC) # TRANSMITTER INTERFACE (DAC — Bank 15, VCCO=3.3V)
# ============================================================================ # ============================================================================
# DAC Data Bus (8-bit) # DAC Data Bus (8-bit) — AD9708 data inputs via schematic nets DAC_0..DAC_7
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_data[0]}] set_property PACKAGE_PIN A14 [get_ports {dac_data[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_data[1]}] set_property PACKAGE_PIN A13 [get_ports {dac_data[1]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_data[2]}] set_property PACKAGE_PIN A12 [get_ports {dac_data[2]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_data[3]}] set_property PACKAGE_PIN B11 [get_ports {dac_data[3]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_data[4]}] set_property PACKAGE_PIN B10 [get_ports {dac_data[4]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_data[5]}] set_property PACKAGE_PIN A10 [get_ports {dac_data[5]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_data[6]}] set_property PACKAGE_PIN A9 [get_ports {dac_data[6]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_data[7]}] set_property PACKAGE_PIN A8 [get_ports {dac_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[*]}] set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[*]}]
set_property SLEW FAST [get_ports {dac_data[*]}] set_property SLEW FAST [get_ports {dac_data[*]}]
set_property DRIVE 8 [get_ports {dac_data[*]}] set_property DRIVE 8 [get_ports {dac_data[*]}]
# DAC Control # DAC Clock Output — NOT DIRECTLY WIRED TO DAC IN SCHEMATIC
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_clk}] # The DAC chip (U3) receives its clock from AD9523 via a separate net
set_property IOSTANDARD LVCMOS33 [get_ports {dac_clk}] # (DAC_CLOCK), not from the FPGA. The RTL `dac_clk` output has no
set_property SLEW FAST [get_ports {dac_clk}] # physical pin. Comment out or remove from RTL.
# set_property PACKAGE_PIN ??? [get_ports {dac_clk}]
# set_property IOSTANDARD LVCMOS33 [get_ports {dac_clk}]
# set_property SLEW FAST [get_ports {dac_clk}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dac_sleep}] # DAC Sleep Control — DAC_SLEEP net
set_property PACKAGE_PIN A15 [get_ports {dac_sleep}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_sleep}] set_property IOSTANDARD LVCMOS33 [get_ports {dac_sleep}]
# RF Switch Control # RF Switch Control — M3S_VCTRL net
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {fpga_rf_switch}] set_property PACKAGE_PIN G15 [get_ports {fpga_rf_switch}]
set_property IOSTANDARD LVCMOS33 [get_ports {fpga_rf_switch}] set_property IOSTANDARD LVCMOS33 [get_ports {fpga_rf_switch}]
# Mixer Enables # Mixer Enables — MIX_RX_EN, MIX_TX_EN nets
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {rx_mixer_en}] set_property PACKAGE_PIN D11 [get_ports {rx_mixer_en}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {tx_mixer_en}] set_property PACKAGE_PIN C11 [get_ports {tx_mixer_en}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_mixer_en}] set_property IOSTANDARD LVCMOS33 [get_ports {rx_mixer_en}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_mixer_en}] set_property IOSTANDARD LVCMOS33 [get_ports {tx_mixer_en}]
# ============================================================================ # ============================================================================
# ADAR1000 BEAMFORMER CONTROL # ADAR1000 BEAMFORMER CONTROL (Bank 34, VCCO=1.8V)
# ============================================================================ # ============================================================================
# ADAR1000 Load/Control Pins (Channel 1-4) # ADAR1000 TX Load Pins (via level shifters, active-high pulse)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_tx_load_1}] set_property PACKAGE_PIN P3 [get_ports {adar_tx_load_1}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_rx_load_1}] set_property PACKAGE_PIN T4 [get_ports {adar_tx_load_2}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_tx_load_2}] set_property PACKAGE_PIN R3 [get_ports {adar_tx_load_3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_rx_load_2}] set_property PACKAGE_PIN R2 [get_ports {adar_tx_load_4}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_tx_load_3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_rx_load_3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_tx_load_4}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_rx_load_4}]
set_property IOSTANDARD LVCMOS33 [get_ports {adar_*_load_*}]
# ADAR1000 TR Pins # ADAR1000 RX Load Pins
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_tr_1}] set_property PACKAGE_PIN M5 [get_ports {adar_rx_load_1}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_tr_2}] set_property PACKAGE_PIN T2 [get_ports {adar_rx_load_2}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_tr_3}] set_property PACKAGE_PIN R1 [get_ports {adar_rx_load_3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adar_tr_4}] set_property PACKAGE_PIN N4 [get_ports {adar_rx_load_4}]
set_property IOSTANDARD LVCMOS33 [get_ports {adar_tr_*}]
# Bank 34 VCCO = 1.8V → must use LVCMOS18 (not LVCMOS33)
set_property IOSTANDARD LVCMOS18 [get_ports {adar_*_load_*}]
# ADAR1000 TR (Transmit/Receive) Pins
set_property PACKAGE_PIN N2 [get_ports {adar_tr_1}]
set_property PACKAGE_PIN N1 [get_ports {adar_tr_2}]
set_property PACKAGE_PIN P1 [get_ports {adar_tr_3}]
set_property PACKAGE_PIN P4 [get_ports {adar_tr_4}]
set_property IOSTANDARD LVCMOS18 [get_ports {adar_tr_*}]
# ============================================================================ # ============================================================================
# LEVEL SHIFTER SPI INTERFACE (STM32 to ADAR1000) # LEVEL SHIFTER SPI INTERFACE (STM32 ADAR1000)
# ============================================================================ # ============================================================================
# 3.3V Side (from STM32) # 3.3V Side (from STM32, Bank 15, VCCO=3.3V)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_sclk_3v3}] set_property PACKAGE_PIN J16 [get_ports {stm32_sclk_3v3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_mosi_3v3}] set_property PACKAGE_PIN H13 [get_ports {stm32_mosi_3v3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_miso_3v3}] set_property PACKAGE_PIN G14 [get_ports {stm32_miso_3v3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_cs_adar1_3v3}] set_property PACKAGE_PIN F14 [get_ports {stm32_cs_adar1_3v3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_cs_adar2_3v3}] set_property PACKAGE_PIN H16 [get_ports {stm32_cs_adar2_3v3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_cs_adar3_3v3}] set_property PACKAGE_PIN G16 [get_ports {stm32_cs_adar3_3v3}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_cs_adar4_3v3}] set_property PACKAGE_PIN J15 [get_ports {stm32_cs_adar4_3v3}]
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_*_3v3}] set_property IOSTANDARD LVCMOS33 [get_ports {stm32_*_3v3}]
# 1.8V Side (to ADAR1000) # 1.8V Side (to ADAR1000, Bank 34, VCCO=1.8V)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_sclk_1v8}] set_property PACKAGE_PIN P5 [get_ports {stm32_sclk_1v8}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_mosi_1v8}] set_property PACKAGE_PIN M1 [get_ports {stm32_mosi_1v8}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_miso_1v8}] set_property PACKAGE_PIN N3 [get_ports {stm32_miso_1v8}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_cs_adar1_1v8}] set_property PACKAGE_PIN L5 [get_ports {stm32_cs_adar1_1v8}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_cs_adar2_1v8}] set_property PACKAGE_PIN L4 [get_ports {stm32_cs_adar2_1v8}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_cs_adar3_1v8}] set_property PACKAGE_PIN M4 [get_ports {stm32_cs_adar3_1v8}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_cs_adar4_1v8}] set_property PACKAGE_PIN M2 [get_ports {stm32_cs_adar4_1v8}]
set_property IOSTANDARD LVCMOS18 [get_ports {stm32_*_1v8}] set_property IOSTANDARD LVCMOS18 [get_ports {stm32_*_1v8}]
# ============================================================================ # ============================================================================
# STM32 CONTROL INTERFACE # STM32 CONTROL INTERFACE (DIG bus, Bank 15, VCCO=3.3V)
# ============================================================================ # ============================================================================
# DIG_0..DIG_4 are STM32 outputs (PD8-PD12) → FPGA inputs
# DIG_5..DIG_7 are STM32 inputs (PD13-PD15) ← FPGA outputs (unused in RTL)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_new_chirp}] set_property PACKAGE_PIN F13 [get_ports {stm32_new_chirp}] ;# DIG_0 (PD8)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_new_elevation}] set_property PACKAGE_PIN E16 [get_ports {stm32_new_elevation}] ;# DIG_1 (PD9)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_new_azimuth}] set_property PACKAGE_PIN D16 [get_ports {stm32_new_azimuth}] ;# DIG_2 (PD10)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {stm32_mixers_enable}] set_property PACKAGE_PIN F15 [get_ports {stm32_mixers_enable}] ;# DIG_3 (PD11)
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_new_*}] set_property IOSTANDARD LVCMOS33 [get_ports {stm32_new_*}]
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_mixers_enable}] set_property IOSTANDARD LVCMOS33 [get_ports {stm32_mixers_enable}]
# reset_n is DIG_4 (PD12) — constrained above in the RESET section
# DIG_5 = H11, DIG_6 = G12, DIG_7 = H12 — available for FPGA→STM32 status
# Currently unused in RTL. Could be connected to status outputs if needed.
# ============================================================================ # ============================================================================
# ADC INTERFACE (LVDS - 400MHz) # ADC INTERFACE (LVDS — Bank 14, VCCO=3.3V)
# ============================================================================ # ============================================================================
# ADC Data (LVDS pairs) # ADC Data (8-bit LVDS pairs from AD9484)
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_d_p[0]}] set_property PACKAGE_PIN P15 [get_ports {adc_d_p[0]}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_d_n[0]}] set_property PACKAGE_PIN P16 [get_ports {adc_d_n[0]}]
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_d_p[1]}] set_property PACKAGE_PIN R15 [get_ports {adc_d_p[1]}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_d_n[1]}] set_property PACKAGE_PIN R16 [get_ports {adc_d_n[1]}]
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_d_p[2]}] set_property PACKAGE_PIN T14 [get_ports {adc_d_p[2]}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_d_n[2]}] set_property PACKAGE_PIN T15 [get_ports {adc_d_n[2]}]
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_d_p[3]}] set_property PACKAGE_PIN R13 [get_ports {adc_d_p[3]}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_d_n[3]}] set_property PACKAGE_PIN T13 [get_ports {adc_d_n[3]}]
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_d_p[4]}] set_property PACKAGE_PIN R10 [get_ports {adc_d_p[4]}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_d_n[4]}] set_property PACKAGE_PIN R11 [get_ports {adc_d_n[4]}]
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_d_p[5]}] set_property PACKAGE_PIN T9 [get_ports {adc_d_p[5]}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_d_n[5]}] set_property PACKAGE_PIN T10 [get_ports {adc_d_n[5]}]
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_d_p[6]}] set_property PACKAGE_PIN T7 [get_ports {adc_d_p[6]}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_d_n[6]}] set_property PACKAGE_PIN T8 [get_ports {adc_d_n[6]}]
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_d_p[7]}] set_property PACKAGE_PIN R6 [get_ports {adc_d_p[7]}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_d_n[7]}] set_property PACKAGE_PIN R7 [get_ports {adc_d_n[7]}]
# ADC DCO Clock (LVDS) # ADC DCO Clock (LVDS) — already constrained above in CLOCK section
set_property PACKAGE_PIN [PIN_NUMBER_P] [get_ports {adc_dco_p}]
set_property PACKAGE_PIN [PIN_NUMBER_N] [get_ports {adc_dco_n}]
# ADC Power Down # ADC Power Down — ADC_PWRD net (single-ended, Bank 14)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {adc_pwdn}] set_property PACKAGE_PIN T5 [get_ports {adc_pwdn}]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_pwdn}] set_property IOSTANDARD LVCMOS33 [get_ports {adc_pwdn}]
# LVDS Constraints # LVDS I/O Standard — Bank 14 VCCO = 3.3V → use LVDS_33 (not LVDS_25)
set_property IOSTANDARD LVDS_25 [get_ports {adc_d_p[*]}] set_property IOSTANDARD LVDS_33 [get_ports {adc_d_p[*]}]
set_property IOSTANDARD LVDS_25 [get_ports {adc_d_n[*]}] set_property IOSTANDARD LVDS_33 [get_ports {adc_d_n[*]}]
set_property IOSTANDARD LVDS_25 [get_ports {adc_dco_p}]
set_property IOSTANDARD LVDS_25 [get_ports {adc_dco_n}]
# Differential pair constraints # Differential termination
set_property DIFF_TERM TRUE [get_ports {adc_d_p[*]}] set_property DIFF_TERM TRUE [get_ports {adc_d_p[*]}]
set_property DIFF_TERM TRUE [get_ports {adc_dco_p}]
# Input delay for ADC data (adjust based on PCB trace length) # Input delay for ADC data relative to DCO (adjust based on PCB trace length)
set_input_delay -clock [get_clocks adc_dco_p] -max 1.0 [get_ports {adc_d_p[*]}] set_input_delay -clock [get_clocks adc_dco_p] -max 1.0 [get_ports {adc_d_p[*]}]
set_input_delay -clock [get_clocks adc_dco_p] -min 0.2 [get_ports {adc_d_p[*]}] set_input_delay -clock [get_clocks adc_dco_p] -min 0.2 [get_ports {adc_d_p[*]}]
# ============================================================================ # ============================================================================
# FT601 USB 3.0 INTERFACE # FT601 USB 3.0 INTERFACE — ACTIVE: NO PHYSICAL CONNECTIONS
# ============================================================================
# The FT601 chip (U6, FT601Q-B-T) is placed in the Eagle schematic but has
# ZERO net connections — no signals are routed between it and the FPGA.
# Bank 35 (which would logically host FT601 signals) has no signal pins
# connected, only VCCO_35 power.
#
# ALL FT601 constraints are commented out. The RTL module usb_data_interface.v
# instantiates the FT601 interface, but it cannot function without physical
# pin assignments. To use USB, the schematic must be updated to wire the
# FT601 to FPGA Bank 35 pins, and then these constraints can be populated.
#
# Ports affected (from radar_system_top.v):
# ft601_data[31:0], ft601_be[1:0], ft601_txe_n, ft601_rxf_n, ft601_txe,
# ft601_rxf, ft601_wr_n, ft601_rd_n, ft601_oe_n, ft601_siwu_n,
# ft601_srb[1:0], ft601_swb[1:0], ft601_clk_out, ft601_clk_in
#
# TODO: Wire FT601 in schematic, then assign pins here.
# ============================================================================ # ============================================================================
# FT601 Data Bus (32-bit bidirectional)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[1]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[2]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[3]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[4]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[5]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[6]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[7]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[8]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[9]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[10]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[11]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[12]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[13]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[14]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[15]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[16]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[17]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[18]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[19]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[20]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[21]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[22]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[23]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[24]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[25]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[26]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[27]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[28]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[29]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[30]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_data[31]}]
# Byte enables
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_be[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_be[1]}]
# Control signals
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_txe_n}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_rxf_n}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_txe}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_rxf}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_wr_n}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_rd_n}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_oe_n}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_siwu_n}]
# FIFO flags
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_srb[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_srb[1]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_swb[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_swb[1]}]
# Clock out (optional)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {ft601_clk_out}]
# FT601 I/O Standards (3.3V for FT601)
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_data[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_be[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_rxf_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_rxf}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_wr_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_rd_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_oe_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_siwu_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_srb[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_swb[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_clk_out}]
# FT601 timing constraints
set_output_delay -clock [get_clocks ft601_clk_in] -max 2.0 [get_ports {ft601_data[*]}]
set_output_delay -clock [get_clocks ft601_clk_in] -min 0.5 [get_ports {ft601_data[*]}]
set_output_delay -clock [get_clocks ft601_clk_in] -max 2.0 [get_ports {ft601_be[*]}]
set_output_delay -clock [get_clocks ft601_clk_in] -min 0.5 [get_ports {ft601_be[*]}]
# ============================================================================ # ============================================================================
# STATUS OUTPUTS # STATUS / DEBUG OUTPUTS — NO PHYSICAL CONNECTIONS
# ============================================================================
# The following RTL output ports have no corresponding FPGA pins in the
# schematic. The only FPGA→STM32 outputs available are DIG_5 (H11),
# DIG_6 (G12), and DIG_7 (H12) — only 3 pins for potentially 60+ signals.
#
# These constraints are commented out. If status readback is needed, either:
# (a) Multiplex selected status bits onto DIG_5/6/7, or
# (b) Send status data over the SPI interface, or
# (c) Route through USB once FT601 is wired.
#
# Ports affected:
# current_elevation[5:0], current_azimuth[5:0], current_chirp[5:0],
# new_chirp_frame, dbg_doppler_data[31:0], dbg_doppler_valid,
# dbg_doppler_bin[4:0], dbg_range_bin[5:0], system_status[3:0]
# ============================================================================ # ============================================================================
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_elevation[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_elevation[1]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_elevation[2]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_elevation[3]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_elevation[4]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_elevation[5]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_azimuth[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_azimuth[1]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_azimuth[2]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_azimuth[3]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_azimuth[4]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_azimuth[5]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_chirp[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_chirp[1]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_chirp[2]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_chirp[3]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_chirp[4]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {current_chirp[5]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {new_chirp_frame}]
set_property IOSTANDARD LVCMOS33 [get_ports {new_chirp_frame}]
# Debug outputs
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dbg_doppler_data[0]}]
# ... (continue for all 32 bits)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dbg_doppler_data[31]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dbg_doppler_valid}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dbg_doppler_bin[0]}]
# ... (continue for all 5 bits)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dbg_doppler_bin[4]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dbg_range_bin[0]}]
# ... (continue for all 6 bits)
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {dbg_range_bin[5]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {system_status[0]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {system_status[1]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {system_status[2]}]
set_property PACKAGE_PIN [PIN_NUMBER] [get_ports {system_status[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dbg_*}]
set_property IOSTANDARD LVCMOS33 [get_ports {system_status[*]}]
# ============================================================================ # ============================================================================
# TIMING EXCEPTIONS # TIMING EXCEPTIONS
# ============================================================================ # ============================================================================
# False paths for asynchronous signals # False paths for asynchronous STM32 control signals (active-edge toggle interface)
set_false_path -from [get_ports {stm32_new_*}] set_false_path -from [get_ports {stm32_new_*}]
set_false_path -from [get_ports {stm32_mixers_enable}] set_false_path -from [get_ports {stm32_mixers_enable}]
@@ -315,26 +268,14 @@ set_false_path -from [get_ports {stm32_mixers_enable}]
# - Route delay alone exceeds the clock period (18+ ns for 10ns period) # - Route delay alone exceeds the clock period (18+ ns for 10ns period)
# - Reset deassertion order is not functionally critical — all registers # - Reset deassertion order is not functionally critical — all registers
# come out of reset within a few cycles of each other # come out of reset within a few cycles of each other
#
# This covers:
# - async_default path group (clk_100m intra-clock, WNS = -11.025ns)
# - clk_100m → clk_120m_dac CDC reset paths (WNS = -3.200ns)
# - clk_100m → ft601_clk_in CDC reset paths (WNS = -3.188ns)
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
set_false_path -from [get_cells reset_sync_reg[*]] -to [get_pins -filter {REF_PIN_NAME == CLR} -of_objects [get_cells -hierarchical -filter {PRIMITIVE_TYPE =~ REGISTER.*.*}]] set_false_path -from [get_cells reset_sync_reg[*]] -to [get_pins -filter {REF_PIN_NAME == CLR} -of_objects [get_cells -hierarchical -filter {PRIMITIVE_TYPE =~ REGISTER.*.*}]]
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Clock Domain Crossing false paths # Clock Domain Crossing false paths
#
# These clock domains are asynchronous to each other. Data crossing between
# them uses proper CDC synchronizers (2-stage or 3-stage) with ASYNC_REG
# attributes. The timing tool should not attempt to time these paths as
# single-cycle transfers.
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# clk_100m ↔ adc_dco_p (400 MHz): DDC reset synchronizer handles this # clk_100m ↔ adc_dco_p (400 MHz): DDC has internal CDC synchronizers
# The DDC has an internal 2-stage reset synchronizer for the 400 MHz domain.
# Any remaining CDC paths between these domains use proper synchronizers.
set_false_path -from [get_clocks clk_100m] -to [get_clocks adc_dco_p] set_false_path -from [get_clocks clk_100m] -to [get_clocks adc_dco_p]
set_false_path -from [get_clocks adc_dco_p] -to [get_clocks clk_100m] set_false_path -from [get_clocks adc_dco_p] -to [get_clocks clk_100m]
@@ -342,27 +283,40 @@ set_false_path -from [get_clocks adc_dco_p] -to [get_clocks clk_100m]
set_false_path -from [get_clocks clk_100m] -to [get_clocks clk_120m_dac] set_false_path -from [get_clocks clk_100m] -to [get_clocks clk_120m_dac]
set_false_path -from [get_clocks clk_120m_dac] -to [get_clocks clk_100m] set_false_path -from [get_clocks clk_120m_dac] -to [get_clocks clk_100m]
# clk_100m ↔ ft601_clk_in: CDC via synchronizers in usb_data_interface # FT601 CDC paths removed — no ft601_clk_in clock defined (chip unwired)
set_false_path -from [get_clocks clk_100m] -to [get_clocks ft601_clk_in]
set_false_path -from [get_clocks ft601_clk_in] -to [get_clocks clk_100m]
# Multicycle paths for slow signals (kept from original constraints)
# NOTE: The false_path above supersedes this for clk_100m→ft601_clk_in,
# but keeping it for documentation of the original design intent.
# set_multicycle_path -setup 2 -from [get_clocks clk_100m] -to [get_clocks ft601_clk_in]
# set_multicycle_path -hold 1 -from [get_clocks clk_100m] -to [get_clocks ft601_clk_in]
# ============================================================================ # ============================================================================
# PHYSICAL CONSTRAINTS # PHYSICAL CONSTRAINTS
# ============================================================================ # ============================================================================
# Group related pins into banks # Pull up unused pins to prevent floating inputs
set_property BITSTREAM.CONFIG.UNUSEDPIN Pullup [current_design] set_property BITSTREAM.CONFIG.UNUSEDPIN Pullup [current_design]
# Place high-speed interfaces in same bank # ============================================================================
set_property PACKAGE_PIN_BANK [BANK_NUMBER] [get_ports {ft601_data[*]}] # ADDITIONAL NOTES
set_property PACKAGE_PIN_BANK [BANK_NUMBER] [get_ports {ft601_*_n}] # ============================================================================
#
# 1. ADC Sampling Clock: FPGA_ADC_CLOCK_P/N (N11/N12) is the 400 MHz LVDS
# clock from AD9523 OUT5 that drives the AD9484. It connects to FPGA MRCC
# pins but is not used as an FPGA clock input — the ADC returns data with
# its own DCO (adc_dco_p/n on N14/P14).
#
# 2. Clock Test: FPGA_CLOCK_TEST (H14) is a 20 MHz LVCMOS output from the
# FPGA, configured by AD9523 OUT7. Not currently used in RTL.
#
# 3. SPI Flash: FPGA_FLASH_CS (E8), FPGA_FLASH_CLK (J13),
# FPGA_FLASH_D0 (J14), D1 (K15), D2 (K16), D3 (L12), unnamed (L13).
# These are typically handled by Vivado bitstream configuration and do
# not need explicit XDC constraints for user logic.
#
# 4. JTAG: FPGA_TCK (L7), FPGA_TDI (N7), FPGA_TDO (N8), FPGA_TMS (M7).
# Dedicated pins — no XDC constraints needed.
#
# 5. dac_clk port: The RTL top module declares `dac_clk` as an output, but
# the physical board wires the DAC clock (AD9708 CLOCK pin) directly from
# the AD9523, not from the FPGA. This port should be removed from the RTL
# or left unconnected. It currently just assigns clk_120m_dac passthrough.
#
# ============================================================================ # ============================================================================
# END OF CONSTRAINTS # END OF CONSTRAINTS
# ============================================================================ # ============================================================================
+78
View File
@@ -0,0 +1,78 @@
# AERIS-10 FPGA Constraint Files
## Two Targets
| File | Device | Package | Purpose |
|------|--------|---------|---------|
| `xc7a50t_ftg256.xdc` | XC7A50T-2FTG256I | FTG256 (256-ball BGA) | Upstream author's board (copy of `cntrt.xdc`) |
| `xc7a200t_fbg484.xdc` | XC7A200T-2FBG484I | FBG484 (484-ball BGA) | Production board (new PCB design) |
## Why Two Files
The upstream prototype uses a smaller XC7A50T in an FTG256 package. The production
AERIS-10 radar migrates to the XC7A200T for more logic, BRAM, and DSP resources.
The two devices have completely different packages and pin names, so each needs its
own constraint file. Both files constrain the same RTL top module (`radar_system_top.v`).
## Bank Voltage Assignments
### XC7A50T-FTG256 (Upstream)
| Bank | VCCO | Signals |
|------|------|---------|
| 0 | 3.3V | JTAG, flash CS |
| 14 | 3.3V | ADC LVDS (LVDS_33), SPI flash |
| 15 | 3.3V | DAC, clocks, STM32 3.3V SPI, DIG bus |
| 34 | 1.8V | ADAR1000 control, SPI 1.8V side |
| 35 | 3.3V | Unused (no signal connections) |
### XC7A200T-FBG484 (Production)
| Bank | VCCO | Used/Avail | Signals |
|------|------|------------|---------|
| 13 | 3.3V | 17/35 | Debug overflow (doppler bins, range bins, status) |
| 14 | 2.5V | 19/50 | ADC LVDS_25 + DIFF_TERM, ADC power-down |
| 15 | 3.3V | 27/50 | System clocks (100M, 120M), DAC, RF, STM32 3.3V SPI, DIG bus |
| 16 | 3.3V | 50/50 | FT601 USB 3.0 (32-bit data + byte enable + control) |
| 34 | 1.8V | 19/50 | ADAR1000 beamformer control, SPI 1.8V side |
| 35 | 3.3V | 50/50 | Status outputs (beam position, chirp, doppler data bus) |
## Signal Differences Between Targets
| Signal | Upstream (FTG256) | Production (FBG484) |
|--------|-------------------|---------------------|
| FT601 USB | Unwired (chip placed, no nets) | Fully wired, Bank 16 |
| `dac_clk` | Not connected (DAC clocked by AD9523 directly) | Routed, FPGA drives DAC |
| `ft601_be` width | `[1:0]` in RTL | `[3:0]` needed (RTL update required) |
| ADC LVDS standard | LVDS_33 (3.3V bank) | LVDS_25 (2.5V bank, better quality) |
| Status/debug outputs | No physical pins (commented out) | All routed to Banks 35 + 13 |
## How to Select in Vivado
In the Vivado project, only one XDC should be active at a time:
1. Add both files to the project: `File > Add Sources > Add Constraints`
2. In the Sources panel, right-click the XDC you do NOT want and select
`Set File Properties > Enabled = false` (or remove it from the active
constraint set)
3. Alternatively, use two separate constraint sets and switch between them
For TCL-based flows:
```tcl
# For production target:
read_xdc constraints/xc7a200t_fbg484.xdc
# For upstream target:
read_xdc constraints/xc7a50t_ftg256.xdc
```
## Notes
- The production XDC pin assignments are **recommended** for the new PCB.
The PCB designer should follow this allocation.
- Bank 16 (FT601) is fully utilized at 50/50 pins. No room for expansion
on that bank.
- Bank 35 (status/debug) is also at capacity (50/50). Additional debug
signals should use Bank 13 spare pins (18 remaining).
- Clock inputs are placed on MRCC (Multi-Region Clock Capable) pins to
ensure proper clock tree access.
@@ -0,0 +1,673 @@
# ============================================================================
# AERIS-10 PHASED ARRAY RADAR — PRODUCTION FPGA CONSTRAINTS
# ============================================================================
# Device: XC7A200T-2FBG484I (FBG484 package)
# Target: Production PCB (NEW design — pin assignments are RECOMMENDED,
# PCB designer should follow this allocation)
#
# Revision History:
# v1.0 2026-03-16 Initial pin plan from Vivado FBG484 package CSV export.
# Migrated from XC7A50T-FTG256 (upstream cntrt.xdc).
# FT601 USB 3.0 fully wired (32-bit data bus).
# dac_clk output wired (FPGA drives DAC clock).
#
# I/O Bank Voltage Plan:
# Bank 13: VCCO = 3.3V — Debug outputs overflow (doppler debug, range bins)
# Bank 14: VCCO = 2.5V — ADC LVDS (LVDS_25 + DIFF_TERM), ADC control
# Bank 15: VCCO = 3.3V — System clocks (100M MRCC, 120M MRCC), DAC,
# RF control, STM32 3.3V SPI, STM32 DIG bus, reset
# Bank 16: VCCO = 3.3V — FT601 USB 3.0 (32-bit data + 4-bit byte enable +
# control, clock on MRCC)
# Bank 34: VCCO = 1.8V — ADAR1000 beamformer control, SPI 1.8V side
# Bank 35: VCCO = 3.3V — Status outputs (beam position, chirp, doppler
# data bus, system status)
#
# Pin Count Summary:
# Bank 13: 17 used / 35 available (18 spare)
# Bank 14: 19 used / 50 available (31 spare)
# Bank 15: 27 used / 50 available (23 spare)
# Bank 16: 50 used / 50 available (0 spare)
# Bank 34: 19 used / 50 available (31 spare)
# Bank 35: 50 used / 50 available (0 spare)
# TOTAL: 182 used / 285 available
#
# Key Differences from Upstream (XC7A50T-FTG256):
# 1. ADC uses LVDS_25 (2.5V VCCO) instead of LVDS_33 (better signal quality)
# 2. FT601 USB 3.0 is fully wired (Bank 16) — unwired on upstream board
# 3. dac_clk output is routed — unconnected on upstream board
# 4. ft601_be is 4 bits wide for 32-bit FT601 mode (upstream RTL has [1:0])
# 5. All status/debug outputs have physical pins (Banks 35 + 13)
# ============================================================================
# ============================================================================
# CONFIGURATION
# ============================================================================
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.CONFIG.UNUSEDPIN Pullup [current_design]
# ============================================================================
# CLOCK CONSTRAINTS
# ============================================================================
# --------------------------------------------------------------------------
# 100 MHz System Clock — AD9523 OUT6 → FPGA Bank 15 MRCC
# Pin: J19 = IO_L12P_T1_MRCC_15
# --------------------------------------------------------------------------
set_property PACKAGE_PIN J19 [get_ports {clk_100m}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_100m}]
create_clock -name clk_100m -period 10.000 [get_ports {clk_100m}]
set_input_jitter [get_clocks clk_100m] 0.100
# --------------------------------------------------------------------------
# 120 MHz DAC Clock — AD9523 OUT11 → FPGA Bank 15 MRCC
# Pin: K18 = IO_L13P_T2_MRCC_15
# --------------------------------------------------------------------------
set_property PACKAGE_PIN K18 [get_ports {clk_120m_dac}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_120m_dac}]
create_clock -name clk_120m_dac -period 8.333 [get_ports {clk_120m_dac}]
set_input_jitter [get_clocks clk_120m_dac] 0.100
# --------------------------------------------------------------------------
# FT601 Clock Input — 100 MHz from FT601 chip, Bank 16 MRCC
# Pin: D17 = IO_L12P_T1_MRCC_16
# --------------------------------------------------------------------------
set_property PACKAGE_PIN D17 [get_ports {ft601_clk_in}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_clk_in}]
create_clock -name ft601_clk_in -period 10.000 [get_ports {ft601_clk_in}]
set_input_jitter [get_clocks ft601_clk_in] 0.100
# --------------------------------------------------------------------------
# ADC DCO Clock — 400 MHz LVDS from AD9484, Bank 14 MRCC
# Pins: W19/W20 = IO_L12P_T1_MRCC_14 / IO_L12N_T1_MRCC_14
# --------------------------------------------------------------------------
set_property PACKAGE_PIN W19 [get_ports {adc_dco_p}]
set_property PACKAGE_PIN W20 [get_ports {adc_dco_n}]
set_property IOSTANDARD LVDS_25 [get_ports {adc_dco_p}]
set_property IOSTANDARD LVDS_25 [get_ports {adc_dco_n}]
set_property DIFF_TERM TRUE [get_ports {adc_dco_p}]
create_clock -name adc_dco_p -period 2.500 [get_ports {adc_dco_p}]
set_input_jitter [get_clocks adc_dco_p] 0.050
# ============================================================================
# RESET (Active-Low) — Bank 15, VCCO = 3.3V
# ============================================================================
# Pin: J16 = IO_0_15 (standalone, not part of a diff pair)
set_property PACKAGE_PIN J16 [get_ports {reset_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {reset_n}]
set_property PULLUP true [get_ports {reset_n}]
# ============================================================================
# ADC INTERFACE — Bank 14, VCCO = 2.5V, LVDS_25 with DIFF_TERM
# ============================================================================
# AD9484 8-bit LVDS data pairs. Each pair uses matched P/N pins in Bank 14.
# LVDS_25 with internal differential termination provides better signal
# integrity than LVDS_33 used on the upstream board.
# adc_d[0]: IO_L1P/L1N_T0_D00/D01_14
set_property PACKAGE_PIN P22 [get_ports {adc_d_p[0]}]
set_property PACKAGE_PIN R22 [get_ports {adc_d_n[0]}]
# adc_d[1]: IO_L2P/L2N_T0_D02/D03_14
set_property PACKAGE_PIN P21 [get_ports {adc_d_p[1]}]
set_property PACKAGE_PIN R21 [get_ports {adc_d_n[1]}]
# adc_d[2]: IO_L3P/L3N_T0_DQS_14
set_property PACKAGE_PIN U22 [get_ports {adc_d_p[2]}]
set_property PACKAGE_PIN V22 [get_ports {adc_d_n[2]}]
# adc_d[3]: IO_L4P/L4N_T0_D04/D05_14
set_property PACKAGE_PIN T21 [get_ports {adc_d_p[3]}]
set_property PACKAGE_PIN U21 [get_ports {adc_d_n[3]}]
# adc_d[4]: IO_L5P/L5N_T0_D06/D07_14
set_property PACKAGE_PIN P19 [get_ports {adc_d_p[4]}]
set_property PACKAGE_PIN R19 [get_ports {adc_d_n[4]}]
# adc_d[5]: IO_L7P/L7N_T1_D09/D10_14
set_property PACKAGE_PIN W21 [get_ports {adc_d_p[5]}]
set_property PACKAGE_PIN W22 [get_ports {adc_d_n[5]}]
# adc_d[6]: IO_L8P/L8N_T1_D11/D12_14
set_property PACKAGE_PIN AA20 [get_ports {adc_d_p[6]}]
set_property PACKAGE_PIN AA21 [get_ports {adc_d_n[6]}]
# adc_d[7]: IO_L9P/L9N_T1_DQS_D13_14
set_property PACKAGE_PIN Y21 [get_ports {adc_d_p[7]}]
set_property PACKAGE_PIN Y22 [get_ports {adc_d_n[7]}]
# LVDS I/O standard and differential termination
set_property IOSTANDARD LVDS_25 [get_ports {adc_d_p[*]}]
set_property IOSTANDARD LVDS_25 [get_ports {adc_d_n[*]}]
set_property DIFF_TERM TRUE [get_ports {adc_d_p[*]}]
# ADC Power Down — single-ended, Bank 14 (LVCMOS25 matches bank VCCO)
# Pin: P20 = IO_0_14
set_property PACKAGE_PIN P20 [get_ports {adc_pwdn}]
set_property IOSTANDARD LVCMOS25 [get_ports {adc_pwdn}]
# ============================================================================
# TRANSMITTER INTERFACE — DAC (Bank 15, VCCO = 3.3V)
# ============================================================================
# DAC Data Bus (8-bit) — AD9708 data inputs
# Using Bank 15 L1..L6 pins (single-ended from diff pairs)
set_property PACKAGE_PIN H13 [get_ports {dac_data[0]}]
set_property PACKAGE_PIN G13 [get_ports {dac_data[1]}]
set_property PACKAGE_PIN G15 [get_ports {dac_data[2]}]
set_property PACKAGE_PIN G16 [get_ports {dac_data[3]}]
set_property PACKAGE_PIN G17 [get_ports {dac_data[4]}]
set_property PACKAGE_PIN G18 [get_ports {dac_data[5]}]
set_property PACKAGE_PIN J15 [get_ports {dac_data[6]}]
set_property PACKAGE_PIN H15 [get_ports {dac_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[*]}]
set_property SLEW FAST [get_ports {dac_data[*]}]
set_property DRIVE 8 [get_ports {dac_data[*]}]
# DAC Clock Output — FPGA drives DAC clock on production board
# (On upstream board, DAC clock came from AD9523 directly; not routed to FPGA)
# Pin: H17 = IO_L6P_T0_15
set_property PACKAGE_PIN H17 [get_ports {dac_clk}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_clk}]
set_property SLEW FAST [get_ports {dac_clk}]
set_property DRIVE 8 [get_ports {dac_clk}]
# DAC Sleep Control
# Pin: H18 = IO_L6N_T0_VREF_15
set_property PACKAGE_PIN H18 [get_ports {dac_sleep}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_sleep}]
# ============================================================================
# RF SWITCH & MIXER CONTROL (Bank 15, VCCO = 3.3V)
# ============================================================================
# Pin: J22 = IO_L7P_T1_AD2P_15
set_property PACKAGE_PIN J22 [get_ports {fpga_rf_switch}]
set_property IOSTANDARD LVCMOS33 [get_ports {fpga_rf_switch}]
# Pin: H22 = IO_L7N_T1_AD2N_15
set_property PACKAGE_PIN H22 [get_ports {rx_mixer_en}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_mixer_en}]
# Pin: H20 = IO_L8P_T1_AD10P_15
set_property PACKAGE_PIN H20 [get_ports {tx_mixer_en}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_mixer_en}]
# ============================================================================
# LEVEL SHIFTER SPI — 3.3V side from STM32 (Bank 15, VCCO = 3.3V)
# ============================================================================
# Pin: K21 = IO_L9P_T1_DQS_AD3P_15
set_property PACKAGE_PIN K21 [get_ports {stm32_sclk_3v3}]
# Pin: K22 = IO_L9N_T1_DQS_AD3N_15
set_property PACKAGE_PIN K22 [get_ports {stm32_mosi_3v3}]
# Pin: M21 = IO_L10P_T1_AD11P_15
set_property PACKAGE_PIN M21 [get_ports {stm32_miso_3v3}]
# Pin: L21 = IO_L10N_T1_AD11N_15
set_property PACKAGE_PIN L21 [get_ports {stm32_cs_adar1_3v3}]
# Pin: N22 = IO_L15P_T2_DQS_15
set_property PACKAGE_PIN N22 [get_ports {stm32_cs_adar2_3v3}]
# Pin: M22 = IO_L15N_T2_DQS_ADV_B_15
set_property PACKAGE_PIN M22 [get_ports {stm32_cs_adar3_3v3}]
# Pin: M18 = IO_L16P_T2_A28_15
set_property PACKAGE_PIN M18 [get_ports {stm32_cs_adar4_3v3}]
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_*_3v3}]
# ============================================================================
# STM32 DIG BUS — Control signals (Bank 15, VCCO = 3.3V)
# ============================================================================
# Pin: L18 = IO_L16N_T2_A27_15
set_property PACKAGE_PIN L18 [get_ports {stm32_new_chirp}]
# Pin: N18 = IO_L17P_T2_A26_15
set_property PACKAGE_PIN N18 [get_ports {stm32_new_elevation}]
# Pin: N19 = IO_L17N_T2_A25_15
set_property PACKAGE_PIN N19 [get_ports {stm32_new_azimuth}]
# Pin: N20 = IO_L18P_T2_A24_15
set_property PACKAGE_PIN N20 [get_ports {stm32_mixers_enable}]
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_new_*}]
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_mixers_enable}]
# ============================================================================
# ADAR1000 BEAMFORMER CONTROL (Bank 34, VCCO = 1.8V)
# ============================================================================
# TX Load Pins — active-high pulse via level shifters
# Pin: T1 = IO_L1P_T0_34
set_property PACKAGE_PIN T1 [get_ports {adar_tx_load_1}]
# Pin: U1 = IO_L1N_T0_34
set_property PACKAGE_PIN U1 [get_ports {adar_tx_load_2}]
# Pin: U2 = IO_L2P_T0_34
set_property PACKAGE_PIN U2 [get_ports {adar_tx_load_3}]
# Pin: V2 = IO_L2N_T0_34
set_property PACKAGE_PIN V2 [get_ports {adar_tx_load_4}]
# RX Load Pins
# Pin: W2 = IO_L4P_T0_34
set_property PACKAGE_PIN W2 [get_ports {adar_rx_load_1}]
# Pin: Y2 = IO_L4N_T0_34
set_property PACKAGE_PIN Y2 [get_ports {adar_rx_load_2}]
# Pin: W1 = IO_L5P_T0_34
set_property PACKAGE_PIN W1 [get_ports {adar_rx_load_3}]
# Pin: Y1 = IO_L5N_T0_34
set_property PACKAGE_PIN Y1 [get_ports {adar_rx_load_4}]
set_property IOSTANDARD LVCMOS18 [get_ports {adar_*_load_*}]
# TR (Transmit/Receive) Pins
# Pin: AA1 = IO_L7P_T1_34
set_property PACKAGE_PIN AA1 [get_ports {adar_tr_1}]
# Pin: AB1 = IO_L7N_T1_34
set_property PACKAGE_PIN AB1 [get_ports {adar_tr_2}]
# Pin: AB3 = IO_L8P_T1_34
set_property PACKAGE_PIN AB3 [get_ports {adar_tr_3}]
# Pin: AB2 = IO_L8N_T1_34
set_property PACKAGE_PIN AB2 [get_ports {adar_tr_4}]
set_property IOSTANDARD LVCMOS18 [get_ports {adar_tr_*}]
# ============================================================================
# LEVEL SHIFTER SPI — 1.8V side to ADAR1000 (Bank 34, VCCO = 1.8V)
# ============================================================================
# Pin: Y3 = IO_L9P_T1_DQS_34
set_property PACKAGE_PIN Y3 [get_ports {stm32_sclk_1v8}]
# Pin: AA3 = IO_L9N_T1_DQS_34
set_property PACKAGE_PIN AA3 [get_ports {stm32_mosi_1v8}]
# Pin: AA5 = IO_L10P_T1_34
set_property PACKAGE_PIN AA5 [get_ports {stm32_miso_1v8}]
# Pin: AB5 = IO_L10N_T1_34
set_property PACKAGE_PIN AB5 [get_ports {stm32_cs_adar1_1v8}]
# Pin: W6 = IO_L15P_T2_DQS_34
set_property PACKAGE_PIN W6 [get_ports {stm32_cs_adar2_1v8}]
# Pin: W5 = IO_L15N_T2_DQS_34
set_property PACKAGE_PIN W5 [get_ports {stm32_cs_adar3_1v8}]
# Pin: U6 = IO_L16P_T2_34
set_property PACKAGE_PIN U6 [get_ports {stm32_cs_adar4_1v8}]
set_property IOSTANDARD LVCMOS18 [get_ports {stm32_*_1v8}]
# ============================================================================
# FT601 USB 3.0 INTERFACE (Bank 16, VCCO = 3.3V)
# ============================================================================
# FT601 is fully wired on the production board.
# 32-bit data bus + 4-bit byte enable + control signals.
#
# NOTE: Current RTL declares ft601_be[1:0]. Production board requires
# ft601_be[3:0] for 32-bit FT601 mode. RTL update needed.
# --- ft601_clk_in on MRCC (D17) constrained above in CLOCK section ---
# FT601 Clock Output (forwarded clock to FT601)
# Pin: C17 = IO_L12N_T1_MRCC_16 (paired with clk_in on L12P)
set_property PACKAGE_PIN C17 [get_ports {ft601_clk_out}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_clk_out}]
set_property SLEW FAST [get_ports {ft601_clk_out}]
set_property DRIVE 8 [get_ports {ft601_clk_out}]
# FT601 Data Bus [31:0] — bidirectional, 3.3V LVCMOS
set_property PACKAGE_PIN F13 [get_ports {ft601_data[0]}]
set_property PACKAGE_PIN F14 [get_ports {ft601_data[1]}]
set_property PACKAGE_PIN F16 [get_ports {ft601_data[2]}]
set_property PACKAGE_PIN E17 [get_ports {ft601_data[3]}]
set_property PACKAGE_PIN C14 [get_ports {ft601_data[4]}]
set_property PACKAGE_PIN C15 [get_ports {ft601_data[5]}]
set_property PACKAGE_PIN E13 [get_ports {ft601_data[6]}]
set_property PACKAGE_PIN E14 [get_ports {ft601_data[7]}]
set_property PACKAGE_PIN E16 [get_ports {ft601_data[8]}]
set_property PACKAGE_PIN D16 [get_ports {ft601_data[9]}]
set_property PACKAGE_PIN D14 [get_ports {ft601_data[10]}]
set_property PACKAGE_PIN D15 [get_ports {ft601_data[11]}]
set_property PACKAGE_PIN B15 [get_ports {ft601_data[12]}]
set_property PACKAGE_PIN B16 [get_ports {ft601_data[13]}]
set_property PACKAGE_PIN C13 [get_ports {ft601_data[14]}]
set_property PACKAGE_PIN B13 [get_ports {ft601_data[15]}]
set_property PACKAGE_PIN A15 [get_ports {ft601_data[16]}]
set_property PACKAGE_PIN A16 [get_ports {ft601_data[17]}]
set_property PACKAGE_PIN A13 [get_ports {ft601_data[18]}]
set_property PACKAGE_PIN A14 [get_ports {ft601_data[19]}]
set_property PACKAGE_PIN B17 [get_ports {ft601_data[20]}]
set_property PACKAGE_PIN B18 [get_ports {ft601_data[21]}]
set_property PACKAGE_PIN F18 [get_ports {ft601_data[22]}]
set_property PACKAGE_PIN E18 [get_ports {ft601_data[23]}]
set_property PACKAGE_PIN B20 [get_ports {ft601_data[24]}]
set_property PACKAGE_PIN A20 [get_ports {ft601_data[25]}]
set_property PACKAGE_PIN A18 [get_ports {ft601_data[26]}]
set_property PACKAGE_PIN A19 [get_ports {ft601_data[27]}]
set_property PACKAGE_PIN F19 [get_ports {ft601_data[28]}]
set_property PACKAGE_PIN F20 [get_ports {ft601_data[29]}]
set_property PACKAGE_PIN D20 [get_ports {ft601_data[30]}]
set_property PACKAGE_PIN C20 [get_ports {ft601_data[31]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_data[*]}]
set_property SLEW FAST [get_ports {ft601_data[*]}]
set_property DRIVE 8 [get_ports {ft601_data[*]}]
# FT601 Byte Enable [3:0]
set_property PACKAGE_PIN C22 [get_ports {ft601_be[0]}]
set_property PACKAGE_PIN B22 [get_ports {ft601_be[1]}]
set_property PACKAGE_PIN B21 [get_ports {ft601_be[2]}]
set_property PACKAGE_PIN A21 [get_ports {ft601_be[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_be[*]}]
set_property SLEW FAST [get_ports {ft601_be[*]}]
set_property DRIVE 8 [get_ports {ft601_be[*]}]
# FT601 Control Signals — active-low strobes
set_property PACKAGE_PIN E22 [get_ports {ft601_wr_n}]
set_property PACKAGE_PIN D22 [get_ports {ft601_rd_n}]
set_property PACKAGE_PIN E21 [get_ports {ft601_oe_n}]
set_property PACKAGE_PIN D21 [get_ports {ft601_siwu_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_wr_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_rd_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_oe_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_siwu_n}]
set_property SLEW FAST [get_ports {ft601_wr_n}]
set_property SLEW FAST [get_ports {ft601_rd_n}]
set_property SLEW FAST [get_ports {ft601_oe_n}]
set_property DRIVE 8 [get_ports {ft601_wr_n}]
set_property DRIVE 8 [get_ports {ft601_rd_n}]
set_property DRIVE 8 [get_ports {ft601_oe_n}]
# FT601 active-low enable outputs (directly from FPGA to FT601)
set_property PACKAGE_PIN G21 [get_ports {ft601_txe_n}]
set_property PACKAGE_PIN G22 [get_ports {ft601_rxf_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_rxf_n}]
# FT601 status inputs (active-high from FT601 to FPGA)
set_property PACKAGE_PIN F21 [get_ports {ft601_txe}]
set_property PACKAGE_PIN F15 [get_ports {ft601_rxf}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_rxf}]
# FT601 FIFO buffer select inputs
set_property PACKAGE_PIN C18 [get_ports {ft601_srb[0]}]
set_property PACKAGE_PIN C19 [get_ports {ft601_srb[1]}]
set_property PACKAGE_PIN E19 [get_ports {ft601_swb[0]}]
set_property PACKAGE_PIN D19 [get_ports {ft601_swb[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_srb[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ft601_swb[*]}]
# ============================================================================
# STATUS OUTPUTS — Beam Position & System Status (Bank 35, VCCO = 3.3V)
# ============================================================================
# current_elevation[5:0]
set_property PACKAGE_PIN B1 [get_ports {current_elevation[0]}]
set_property PACKAGE_PIN A1 [get_ports {current_elevation[1]}]
set_property PACKAGE_PIN C2 [get_ports {current_elevation[2]}]
set_property PACKAGE_PIN B2 [get_ports {current_elevation[3]}]
set_property PACKAGE_PIN E1 [get_ports {current_elevation[4]}]
set_property PACKAGE_PIN D1 [get_ports {current_elevation[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {current_elevation[*]}]
# current_azimuth[5:0]
set_property PACKAGE_PIN E2 [get_ports {current_azimuth[0]}]
set_property PACKAGE_PIN D2 [get_ports {current_azimuth[1]}]
set_property PACKAGE_PIN G1 [get_ports {current_azimuth[2]}]
set_property PACKAGE_PIN F1 [get_ports {current_azimuth[3]}]
set_property PACKAGE_PIN F3 [get_ports {current_azimuth[4]}]
set_property PACKAGE_PIN E3 [get_ports {current_azimuth[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {current_azimuth[*]}]
# current_chirp[5:0]
set_property PACKAGE_PIN K1 [get_ports {current_chirp[0]}]
set_property PACKAGE_PIN J1 [get_ports {current_chirp[1]}]
set_property PACKAGE_PIN H2 [get_ports {current_chirp[2]}]
set_property PACKAGE_PIN G2 [get_ports {current_chirp[3]}]
set_property PACKAGE_PIN K2 [get_ports {current_chirp[4]}]
set_property PACKAGE_PIN J2 [get_ports {current_chirp[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {current_chirp[*]}]
# new_chirp_frame
set_property PACKAGE_PIN J5 [get_ports {new_chirp_frame}]
set_property IOSTANDARD LVCMOS33 [get_ports {new_chirp_frame}]
# system_status[3:0]
set_property PACKAGE_PIN H5 [get_ports {system_status[0]}]
set_property PACKAGE_PIN H3 [get_ports {system_status[1]}]
set_property PACKAGE_PIN G3 [get_ports {system_status[2]}]
set_property PACKAGE_PIN H4 [get_ports {system_status[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {system_status[*]}]
# ============================================================================
# DEBUG OUTPUTS — Doppler Data (Bank 35, VCCO = 3.3V)
# ============================================================================
# dbg_doppler_data[26:0] on Bank 35, dbg_doppler_data[31:27] on Bank 13
# dbg_doppler_data[26:0] — Bank 35
set_property PACKAGE_PIN G4 [get_ports {dbg_doppler_data[0]}]
set_property PACKAGE_PIN K4 [get_ports {dbg_doppler_data[1]}]
set_property PACKAGE_PIN J4 [get_ports {dbg_doppler_data[2]}]
set_property PACKAGE_PIN L3 [get_ports {dbg_doppler_data[3]}]
set_property PACKAGE_PIN K3 [get_ports {dbg_doppler_data[4]}]
set_property PACKAGE_PIN M1 [get_ports {dbg_doppler_data[5]}]
set_property PACKAGE_PIN L1 [get_ports {dbg_doppler_data[6]}]
set_property PACKAGE_PIN M3 [get_ports {dbg_doppler_data[7]}]
set_property PACKAGE_PIN M2 [get_ports {dbg_doppler_data[8]}]
set_property PACKAGE_PIN K6 [get_ports {dbg_doppler_data[9]}]
set_property PACKAGE_PIN J6 [get_ports {dbg_doppler_data[10]}]
set_property PACKAGE_PIN L5 [get_ports {dbg_doppler_data[11]}]
set_property PACKAGE_PIN L4 [get_ports {dbg_doppler_data[12]}]
set_property PACKAGE_PIN N4 [get_ports {dbg_doppler_data[13]}]
set_property PACKAGE_PIN N3 [get_ports {dbg_doppler_data[14]}]
set_property PACKAGE_PIN R1 [get_ports {dbg_doppler_data[15]}]
set_property PACKAGE_PIN P1 [get_ports {dbg_doppler_data[16]}]
set_property PACKAGE_PIN P5 [get_ports {dbg_doppler_data[17]}]
set_property PACKAGE_PIN P4 [get_ports {dbg_doppler_data[18]}]
set_property PACKAGE_PIN P2 [get_ports {dbg_doppler_data[19]}]
set_property PACKAGE_PIN N2 [get_ports {dbg_doppler_data[20]}]
set_property PACKAGE_PIN M6 [get_ports {dbg_doppler_data[21]}]
set_property PACKAGE_PIN M5 [get_ports {dbg_doppler_data[22]}]
set_property PACKAGE_PIN P6 [get_ports {dbg_doppler_data[23]}]
set_property PACKAGE_PIN N5 [get_ports {dbg_doppler_data[24]}]
set_property PACKAGE_PIN L6 [get_ports {dbg_doppler_data[25]}]
set_property PACKAGE_PIN F4 [get_ports {dbg_doppler_data[26]}]
# dbg_doppler_data[31:27] — Bank 13 (overflow)
set_property PACKAGE_PIN Y17 [get_ports {dbg_doppler_data[27]}]
set_property PACKAGE_PIN Y16 [get_ports {dbg_doppler_data[28]}]
set_property PACKAGE_PIN AA16 [get_ports {dbg_doppler_data[29]}]
set_property PACKAGE_PIN AB16 [get_ports {dbg_doppler_data[30]}]
set_property PACKAGE_PIN AB17 [get_ports {dbg_doppler_data[31]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dbg_doppler_data[*]}]
# ============================================================================
# DEBUG OUTPUTS — Doppler Valid & Bins (Bank 13, VCCO = 3.3V)
# ============================================================================
set_property PACKAGE_PIN AA13 [get_ports {dbg_doppler_valid}]
set_property IOSTANDARD LVCMOS33 [get_ports {dbg_doppler_valid}]
# dbg_doppler_bin[4:0]
set_property PACKAGE_PIN AB13 [get_ports {dbg_doppler_bin[0]}]
set_property PACKAGE_PIN AA15 [get_ports {dbg_doppler_bin[1]}]
set_property PACKAGE_PIN AB15 [get_ports {dbg_doppler_bin[2]}]
set_property PACKAGE_PIN Y13 [get_ports {dbg_doppler_bin[3]}]
set_property PACKAGE_PIN AA14 [get_ports {dbg_doppler_bin[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dbg_doppler_bin[*]}]
# dbg_range_bin[5:0]
set_property PACKAGE_PIN W14 [get_ports {dbg_range_bin[0]}]
set_property PACKAGE_PIN Y14 [get_ports {dbg_range_bin[1]}]
set_property PACKAGE_PIN AB11 [get_ports {dbg_range_bin[2]}]
set_property PACKAGE_PIN AB12 [get_ports {dbg_range_bin[3]}]
set_property PACKAGE_PIN AA9 [get_ports {dbg_range_bin[4]}]
set_property PACKAGE_PIN AB10 [get_ports {dbg_range_bin[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dbg_range_bin[*]}]
# ============================================================================
# INPUT DELAY CONSTRAINTS
# ============================================================================
# ADC data relative to DCO (source-synchronous, center-aligned)
# NOTE: Rising-edge input delay constraints are here; falling-edge + BUFIO
# adjustments are in the "ADC SOURCE-SYNCHRONOUS INPUT CONSTRAINTS" section below.
# DDR at 400 MHz → 2.5 ns period, data valid window ±0.625 ns
# These are overridden by the more complete constraints below (with -add_delay
# for clock_fall), but kept for documentation of the original intent.
# set_input_delay -clock [get_clocks adc_dco_p] -max 1.000 [get_ports {adc_d_p[*]}]
# set_input_delay -clock [get_clocks adc_dco_p] -min 0.200 [get_ports {adc_d_p[*]}]
# FT601 input delays (relative to ft601_clk_in, 100 MHz)
# FT601 datasheet: Tco max = 7.0 ns, Tco min = 1.0 ns
set_input_delay -clock [get_clocks ft601_clk_in] -max 7.000 [get_ports {ft601_data[*]}]
set_input_delay -clock [get_clocks ft601_clk_in] -min 1.000 [get_ports {ft601_data[*]}]
set_input_delay -clock [get_clocks ft601_clk_in] -max 7.000 [get_ports {ft601_txe}]
set_input_delay -clock [get_clocks ft601_clk_in] -min 1.000 [get_ports {ft601_txe}]
set_input_delay -clock [get_clocks ft601_clk_in] -max 7.000 [get_ports {ft601_rxf}]
set_input_delay -clock [get_clocks ft601_clk_in] -min 1.000 [get_ports {ft601_rxf}]
set_input_delay -clock [get_clocks ft601_clk_in] -max 7.000 [get_ports {ft601_srb[*]}]
set_input_delay -clock [get_clocks ft601_clk_in] -min 1.000 [get_ports {ft601_srb[*]}]
set_input_delay -clock [get_clocks ft601_clk_in] -max 7.000 [get_ports {ft601_swb[*]}]
set_input_delay -clock [get_clocks ft601_clk_in] -min 1.000 [get_ports {ft601_swb[*]}]
# ============================================================================
# OUTPUT DELAY CONSTRAINTS
# ============================================================================
# --------------------------------------------------------------------------
# DAC output delay relative to ODDR-forwarded clock
# --------------------------------------------------------------------------
# dac_clk is now forwarded via ODDR from clk_120m_dac BUFG output.
# Create a generated clock on the dac_clk output pin representing the
# ODDR-forwarded clock. Output delays are then set relative to THIS
# generated clock, not the source port clock. Since both data ODDRs and
# clock ODDR are driven by the same BUFG, insertion delays cancel.
#
# AD9708 specs at the DAC pin: Tsu = 2.0 ns, Th = 1.5 ns
# Board trace skew budget: ~0.5 ns (conservative)
# output_delay_max = Tsu + trace_skew = 2.0 + 0.5 = 2.5 ns
# output_delay_min = -(Th - trace_skew) = -(1.5 - 0.5) = -1.0 ns
create_generated_clock -name dac_clk_fwd \
-source [get_pins -hierarchical -filter {NAME =~ *oddr_dac_clk/C}] \
-divide_by 1 \
[get_ports {dac_clk}]
set_output_delay -clock [get_clocks dac_clk_fwd] -max 2.500 [get_ports {dac_data[*]}]
set_output_delay -clock [get_clocks dac_clk_fwd] -min -1.000 [get_ports {dac_data[*]}]
# dac_clk itself has no meaningful output delay (it IS the clock reference)
# but we remove the old constraint that was relative to the source port clock.
# --------------------------------------------------------------------------
# FT601 output delay relative to ODDR-forwarded clock
# --------------------------------------------------------------------------
# ft601_clk_out is now forwarded via ODDR from ft601_clk_in BUFG output.
# Since both data FFs and clock ODDR are driven by the same BUFG, insertion
# delays cancel. Output delay only needs to cover FT601 Tsu/Th + trace skew.
#
# FT601 specs: Tsu = 3.0 ns, Th = 0.5 ns
# Board trace skew budget: ~0.5 ns
# output_delay_max = Tsu + trace_skew = 3.0 + 0.5 = 3.5 ns
# output_delay_min = -(Th - trace_skew) = -(0.5 - 0.5) = 0.0 ns
create_generated_clock -name ft601_clk_fwd \
-source [get_pins -hierarchical -filter {NAME =~ *oddr_ft601_clk/C}] \
-divide_by 1 \
[get_ports {ft601_clk_out}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -max 3.500 [get_ports {ft601_data[*]}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -min 0.000 [get_ports {ft601_data[*]}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -max 3.500 [get_ports {ft601_be[*]}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -min 0.000 [get_ports {ft601_be[*]}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -max 3.500 [get_ports {ft601_wr_n}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -min 0.000 [get_ports {ft601_wr_n}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -max 3.500 [get_ports {ft601_rd_n}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -min 0.000 [get_ports {ft601_rd_n}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -max 3.500 [get_ports {ft601_oe_n}]
set_output_delay -clock [get_clocks ft601_clk_fwd] -min 0.000 [get_ports {ft601_oe_n}]
# ============================================================================
# TIMING EXCEPTIONS — FALSE PATHS
# ============================================================================
# Asynchronous STM32 control signals (toggle interface, double-synced in RTL)
set_false_path -from [get_ports {stm32_new_*}]
set_false_path -from [get_ports {stm32_mixers_enable}]
# Async reset false paths
# reset_n is held asserted for many clock cycles. All paths originating from
# the reset port or reset synchronizer registers are false paths — this covers
# both data paths (setup/hold) and asynchronous control paths (recovery/removal).
#
# NOTE: Using -from only (no -to filter). Vivado does not accept CLR/PRE pins
# as valid endpoints for set_false_path -to. Waiving all paths FROM these
# sources is the correct and standard approach.
set_false_path -from [get_ports {reset_n}]
set_false_path -from [get_cells -hierarchical -filter {NAME =~ *reset_sync*}]
# ============================================================================
# TIMING EXCEPTIONS — CLOCK DOMAIN CROSSINGS
# ============================================================================
# clk_100m ↔ adc_dco_p (400 MHz): DDC has internal CDC synchronizers
set_false_path -from [get_clocks clk_100m] -to [get_clocks adc_dco_p]
set_false_path -from [get_clocks adc_dco_p] -to [get_clocks clk_100m]
# clk_100m ↔ clk_120m_dac: CDC via synchronizers in radar_system_top
set_false_path -from [get_clocks clk_100m] -to [get_clocks clk_120m_dac]
set_false_path -from [get_clocks clk_120m_dac] -to [get_clocks clk_100m]
# clk_100m ↔ ft601_clk_in: USB data interface has CDC synchronizers
set_false_path -from [get_clocks clk_100m] -to [get_clocks ft601_clk_in]
set_false_path -from [get_clocks ft601_clk_in] -to [get_clocks clk_100m]
# clk_120m_dac ↔ ft601_clk_in: no direct data path expected
set_false_path -from [get_clocks clk_120m_dac] -to [get_clocks ft601_clk_in]
set_false_path -from [get_clocks ft601_clk_in] -to [get_clocks clk_120m_dac]
# adc_dco_p ↔ ft601_clk_in: no direct data path expected
set_false_path -from [get_clocks adc_dco_p] -to [get_clocks ft601_clk_in]
set_false_path -from [get_clocks ft601_clk_in] -to [get_clocks adc_dco_p]
# Generated clock cross-domain paths:
# dac_clk_fwd and ft601_clk_fwd are generated from their respective source
# clocks. Vivado automatically inherits the source clock false paths for
# generated clocks, but be explicit for clarity:
set_false_path -from [get_clocks clk_100m] -to [get_clocks dac_clk_fwd]
set_false_path -from [get_clocks dac_clk_fwd] -to [get_clocks clk_100m]
set_false_path -from [get_clocks ft601_clk_fwd] -to [get_clocks clk_120m_dac]
set_false_path -from [get_clocks clk_120m_dac] -to [get_clocks ft601_clk_fwd]
# ============================================================================
# ADC SOURCE-SYNCHRONOUS INPUT CONSTRAINTS
# ============================================================================
# With BUFIO clocking the IDDR (near-zero insertion delay), the input delay
# constraints need updating. The IDDR sees data and clock with similar
# propagation delays (both through IOB primitives).
#
# AD9484 source-synchronous interface:
# - DDR at 400 MHz → 1.25 ns half-period (data valid window)
# - Data is center-aligned to DCO by the ADC
# - Tco_max (data after clock edge) = 1.0 ns, Tco_min = 0.2 ns
#
# With BUFIO, the clock insertion delay at IDDR is ~0.3 ns (vs 4.4 ns BUFG).
# Input delay values are board-level delays only.
set_input_delay -clock [get_clocks adc_dco_p] -max 1.000 [get_ports {adc_d_p[*]}]
set_input_delay -clock [get_clocks adc_dco_p] -min 0.200 [get_ports {adc_d_p[*]}]
# DDR falling edge captures
set_input_delay -clock [get_clocks adc_dco_p] -max 1.000 -clock_fall [get_ports {adc_d_p[*]}] -add_delay
set_input_delay -clock [get_clocks adc_dco_p] -min 0.200 -clock_fall [get_ports {adc_d_p[*]}] -add_delay
# ============================================================================
# IOB PACKING
# ============================================================================
# Force DAC data and clock ODDR outputs into IOBs
set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *oddr_dac_clk*}]
set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *oddr_dac_data*}]
# Force FT601 clock ODDR into IOB
set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *oddr_ft601_clk*}]
# FT601 data/control output FFs: packed into IOBs where possible
# NOTE: IOB packing requires the register to be the ONLY driver of the output
# and have no other fanout. The FT601 FSM may prevent this for some signals.
# Vivado will warn if it cannot pack — that's OK, timing is still met via
# the generated clock (insertion delay cancellation).
set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_data_out_reg*}]
set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_be_reg*}]
set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_wr_n_reg*}]
set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_rd_n_reg*}]
set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_oe_n_reg*}]
# ============================================================================
# TIMING EXCEPTIONS — CIC DECIMATOR MULTICYCLE PATHS
# ============================================================================
# CIC integrator stages operate at input rate but only produce valid output
# at the decimated rate (every N cycles). The wide combinational paths have
# multiple clock cycles to settle.
set_multicycle_path 2 -setup \
-from [get_cells -hierarchical -filter {NAME =~ *cic_decimator*/integrator_reg*}] \
-to [get_cells -hierarchical -filter {NAME =~ *cic_decimator*/integrator_reg*}]
set_multicycle_path 1 -hold \
-from [get_cells -hierarchical -filter {NAME =~ *cic_decimator*/integrator_reg*}] \
-to [get_cells -hierarchical -filter {NAME =~ *cic_decimator*/integrator_reg*}]
# ============================================================================
# END OF CONSTRAINTS
# ============================================================================
@@ -0,0 +1,322 @@
# ============================================================================
# RADAR SYSTEM FPGA CONSTRAINTS
# ============================================================================
# Device: XC7A50T-2FTG256I (FTG256 package)
# Board: AERIS-10 Phased Array Radar — Main Board
# Source: Pin assignments extracted from Eagle schematic (RADAR_Main_Board.sch)
# FPGA = U42
#
# NOTE: The README and prior version of this file incorrectly referenced
# XC7A100TCSG324-1. The physical board uses XC7A50T in a 256-ball BGA
# (FTG256). All PACKAGE_PIN values below are FTG256 ball locations.
#
# I/O Bank Voltage Summary:
# Bank 0: VCCO = 3.3V (JTAG, flash CS)
# Bank 14: VCCO = 3.3V (ADC LVDS data, SPI flash)
# Bank 15: VCCO = 3.3V (DAC, clocks, STM32 SPI 3.3V side, DIG bus, mixer)
# Bank 34: VCCO = 1.8V (ADAR1000 beamformer control, SPI 1.8V side)
# Bank 35: VCCO = 3.3V (unused — no signal connections)
# ============================================================================
# ============================================================================
# CLOCK CONSTRAINTS
# ============================================================================
# 100MHz System Clock (AD9523 OUT6 → FPGA_SYS_CLOCK → Bank 15 MRCC pin E12)
set_property PACKAGE_PIN E12 [get_ports {clk_100m}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_100m}]
create_clock -name clk_100m -period 10.0 [get_ports {clk_100m}]
set_input_jitter [get_clocks clk_100m] 0.1
# 120MHz DAC Clock (AD9523 OUT11 → FPGA_DAC_CLOCK → Bank 15 MRCC pin C13)
# NOTE: The physical DAC (U3, AD9708) receives its clock directly from the
# AD9523 via a separate net (DAC_CLOCK), NOT from the FPGA. The FPGA
# uses this clock input for internal DAC data timing only. The RTL port
# `dac_clk` is an output that assigns clk_120m directly — it has no
# separate physical pin on this board and should be removed from the
# RTL or left unconnected.
set_property PACKAGE_PIN C13 [get_ports {clk_120m_dac}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_120m_dac}]
create_clock -name clk_120m_dac -period 8.333 [get_ports {clk_120m_dac}]
set_input_jitter [get_clocks clk_120m_dac] 0.1
# ADC DCO Clock (400MHz LVDS — AD9523 OUT5 → AD9484 → FPGA, Bank 14 MRCC)
set_property PACKAGE_PIN N14 [get_ports {adc_dco_p}]
set_property PACKAGE_PIN P14 [get_ports {adc_dco_n}]
set_property IOSTANDARD LVDS_33 [get_ports {adc_dco_p}]
set_property IOSTANDARD LVDS_33 [get_ports {adc_dco_n}]
set_property DIFF_TERM TRUE [get_ports {adc_dco_p}]
create_clock -name adc_dco_p -period 2.5 [get_ports {adc_dco_p}]
set_input_jitter [get_clocks adc_dco_p] 0.05
# --------------------------------------------------------------------------
# FT601 Clock — COMMENTED OUT: FT601 (U6) is placed in schematic but has
# zero net connections. No physical clock pin exists on this board.
# --------------------------------------------------------------------------
# create_clock -name ft601_clk_in -period 10.0 [get_ports {ft601_clk_in}]
# set_input_jitter [get_clocks ft601_clk_in] 0.1
# ============================================================================
# RESET (Active-Low)
# ============================================================================
# DIG_4 (STM32 PD12 → FPGA Bank 15 pin E15)
# STM32 firmware uses HAL_GPIO_WritePin to assert/deassert FPGA reset.
set_property PACKAGE_PIN E15 [get_ports {reset_n}]
set_property IOSTANDARD LVCMOS33 [get_ports {reset_n}]
set_property PULLUP true [get_ports {reset_n}]
# ============================================================================
# TRANSMITTER INTERFACE (DAC — Bank 15, VCCO=3.3V)
# ============================================================================
# DAC Data Bus (8-bit) — AD9708 data inputs via schematic nets DAC_0..DAC_7
set_property PACKAGE_PIN A14 [get_ports {dac_data[0]}]
set_property PACKAGE_PIN A13 [get_ports {dac_data[1]}]
set_property PACKAGE_PIN A12 [get_ports {dac_data[2]}]
set_property PACKAGE_PIN B11 [get_ports {dac_data[3]}]
set_property PACKAGE_PIN B10 [get_ports {dac_data[4]}]
set_property PACKAGE_PIN A10 [get_ports {dac_data[5]}]
set_property PACKAGE_PIN A9 [get_ports {dac_data[6]}]
set_property PACKAGE_PIN A8 [get_ports {dac_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_data[*]}]
set_property SLEW FAST [get_ports {dac_data[*]}]
set_property DRIVE 8 [get_ports {dac_data[*]}]
# DAC Clock Output — NOT DIRECTLY WIRED TO DAC IN SCHEMATIC
# The DAC chip (U3) receives its clock from AD9523 via a separate net
# (DAC_CLOCK), not from the FPGA. The RTL `dac_clk` output has no
# physical pin. Comment out or remove from RTL.
# set_property PACKAGE_PIN ??? [get_ports {dac_clk}]
# set_property IOSTANDARD LVCMOS33 [get_ports {dac_clk}]
# set_property SLEW FAST [get_ports {dac_clk}]
# DAC Sleep Control — DAC_SLEEP net
set_property PACKAGE_PIN A15 [get_ports {dac_sleep}]
set_property IOSTANDARD LVCMOS33 [get_ports {dac_sleep}]
# RF Switch Control — M3S_VCTRL net
set_property PACKAGE_PIN G15 [get_ports {fpga_rf_switch}]
set_property IOSTANDARD LVCMOS33 [get_ports {fpga_rf_switch}]
# Mixer Enables — MIX_RX_EN, MIX_TX_EN nets
set_property PACKAGE_PIN D11 [get_ports {rx_mixer_en}]
set_property PACKAGE_PIN C11 [get_ports {tx_mixer_en}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_mixer_en}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_mixer_en}]
# ============================================================================
# ADAR1000 BEAMFORMER CONTROL (Bank 34, VCCO=1.8V)
# ============================================================================
# ADAR1000 TX Load Pins (via level shifters, active-high pulse)
set_property PACKAGE_PIN P3 [get_ports {adar_tx_load_1}]
set_property PACKAGE_PIN T4 [get_ports {adar_tx_load_2}]
set_property PACKAGE_PIN R3 [get_ports {adar_tx_load_3}]
set_property PACKAGE_PIN R2 [get_ports {adar_tx_load_4}]
# ADAR1000 RX Load Pins
set_property PACKAGE_PIN M5 [get_ports {adar_rx_load_1}]
set_property PACKAGE_PIN T2 [get_ports {adar_rx_load_2}]
set_property PACKAGE_PIN R1 [get_ports {adar_rx_load_3}]
set_property PACKAGE_PIN N4 [get_ports {adar_rx_load_4}]
# Bank 34 VCCO = 1.8V → must use LVCMOS18 (not LVCMOS33)
set_property IOSTANDARD LVCMOS18 [get_ports {adar_*_load_*}]
# ADAR1000 TR (Transmit/Receive) Pins
set_property PACKAGE_PIN N2 [get_ports {adar_tr_1}]
set_property PACKAGE_PIN N1 [get_ports {adar_tr_2}]
set_property PACKAGE_PIN P1 [get_ports {adar_tr_3}]
set_property PACKAGE_PIN P4 [get_ports {adar_tr_4}]
set_property IOSTANDARD LVCMOS18 [get_ports {adar_tr_*}]
# ============================================================================
# LEVEL SHIFTER SPI INTERFACE (STM32 ↔ ADAR1000)
# ============================================================================
# 3.3V Side (from STM32, Bank 15, VCCO=3.3V)
set_property PACKAGE_PIN J16 [get_ports {stm32_sclk_3v3}]
set_property PACKAGE_PIN H13 [get_ports {stm32_mosi_3v3}]
set_property PACKAGE_PIN G14 [get_ports {stm32_miso_3v3}]
set_property PACKAGE_PIN F14 [get_ports {stm32_cs_adar1_3v3}]
set_property PACKAGE_PIN H16 [get_ports {stm32_cs_adar2_3v3}]
set_property PACKAGE_PIN G16 [get_ports {stm32_cs_adar3_3v3}]
set_property PACKAGE_PIN J15 [get_ports {stm32_cs_adar4_3v3}]
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_*_3v3}]
# 1.8V Side (to ADAR1000, Bank 34, VCCO=1.8V)
set_property PACKAGE_PIN P5 [get_ports {stm32_sclk_1v8}]
set_property PACKAGE_PIN M1 [get_ports {stm32_mosi_1v8}]
set_property PACKAGE_PIN N3 [get_ports {stm32_miso_1v8}]
set_property PACKAGE_PIN L5 [get_ports {stm32_cs_adar1_1v8}]
set_property PACKAGE_PIN L4 [get_ports {stm32_cs_adar2_1v8}]
set_property PACKAGE_PIN M4 [get_ports {stm32_cs_adar3_1v8}]
set_property PACKAGE_PIN M2 [get_ports {stm32_cs_adar4_1v8}]
set_property IOSTANDARD LVCMOS18 [get_ports {stm32_*_1v8}]
# ============================================================================
# STM32 CONTROL INTERFACE (DIG bus, Bank 15, VCCO=3.3V)
# ============================================================================
# DIG_0..DIG_4 are STM32 outputs (PD8-PD12) → FPGA inputs
# DIG_5..DIG_7 are STM32 inputs (PD13-PD15) ← FPGA outputs (unused in RTL)
set_property PACKAGE_PIN F13 [get_ports {stm32_new_chirp}] ;# DIG_0 (PD8)
set_property PACKAGE_PIN E16 [get_ports {stm32_new_elevation}] ;# DIG_1 (PD9)
set_property PACKAGE_PIN D16 [get_ports {stm32_new_azimuth}] ;# DIG_2 (PD10)
set_property PACKAGE_PIN F15 [get_ports {stm32_mixers_enable}] ;# DIG_3 (PD11)
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_new_*}]
set_property IOSTANDARD LVCMOS33 [get_ports {stm32_mixers_enable}]
# reset_n is DIG_4 (PD12) — constrained above in the RESET section
# DIG_5 = H11, DIG_6 = G12, DIG_7 = H12 — available for FPGA→STM32 status
# Currently unused in RTL. Could be connected to status outputs if needed.
# ============================================================================
# ADC INTERFACE (LVDS — Bank 14, VCCO=3.3V)
# ============================================================================
# ADC Data (8-bit LVDS pairs from AD9484)
set_property PACKAGE_PIN P15 [get_ports {adc_d_p[0]}]
set_property PACKAGE_PIN P16 [get_ports {adc_d_n[0]}]
set_property PACKAGE_PIN R15 [get_ports {adc_d_p[1]}]
set_property PACKAGE_PIN R16 [get_ports {adc_d_n[1]}]
set_property PACKAGE_PIN T14 [get_ports {adc_d_p[2]}]
set_property PACKAGE_PIN T15 [get_ports {adc_d_n[2]}]
set_property PACKAGE_PIN R13 [get_ports {adc_d_p[3]}]
set_property PACKAGE_PIN T13 [get_ports {adc_d_n[3]}]
set_property PACKAGE_PIN R10 [get_ports {adc_d_p[4]}]
set_property PACKAGE_PIN R11 [get_ports {adc_d_n[4]}]
set_property PACKAGE_PIN T9 [get_ports {adc_d_p[5]}]
set_property PACKAGE_PIN T10 [get_ports {adc_d_n[5]}]
set_property PACKAGE_PIN T7 [get_ports {adc_d_p[6]}]
set_property PACKAGE_PIN T8 [get_ports {adc_d_n[6]}]
set_property PACKAGE_PIN R6 [get_ports {adc_d_p[7]}]
set_property PACKAGE_PIN R7 [get_ports {adc_d_n[7]}]
# ADC DCO Clock (LVDS) — already constrained above in CLOCK section
# ADC Power Down — ADC_PWRD net (single-ended, Bank 14)
set_property PACKAGE_PIN T5 [get_ports {adc_pwdn}]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_pwdn}]
# LVDS I/O Standard — Bank 14 VCCO = 3.3V → use LVDS_33 (not LVDS_25)
set_property IOSTANDARD LVDS_33 [get_ports {adc_d_p[*]}]
set_property IOSTANDARD LVDS_33 [get_ports {adc_d_n[*]}]
# Differential termination
set_property DIFF_TERM TRUE [get_ports {adc_d_p[*]}]
# Input delay for ADC data relative to DCO (adjust based on PCB trace length)
set_input_delay -clock [get_clocks adc_dco_p] -max 1.0 [get_ports {adc_d_p[*]}]
set_input_delay -clock [get_clocks adc_dco_p] -min 0.2 [get_ports {adc_d_p[*]}]
# ============================================================================
# FT601 USB 3.0 INTERFACE — ACTIVE: NO PHYSICAL CONNECTIONS
# ============================================================================
# The FT601 chip (U6, FT601Q-B-T) is placed in the Eagle schematic but has
# ZERO net connections — no signals are routed between it and the FPGA.
# Bank 35 (which would logically host FT601 signals) has no signal pins
# connected, only VCCO_35 power.
#
# ALL FT601 constraints are commented out. The RTL module usb_data_interface.v
# instantiates the FT601 interface, but it cannot function without physical
# pin assignments. To use USB, the schematic must be updated to wire the
# FT601 to FPGA Bank 35 pins, and then these constraints can be populated.
#
# Ports affected (from radar_system_top.v):
# ft601_data[31:0], ft601_be[1:0], ft601_txe_n, ft601_rxf_n, ft601_txe,
# ft601_rxf, ft601_wr_n, ft601_rd_n, ft601_oe_n, ft601_siwu_n,
# ft601_srb[1:0], ft601_swb[1:0], ft601_clk_out, ft601_clk_in
#
# TODO: Wire FT601 in schematic, then assign pins here.
# ============================================================================
# ============================================================================
# STATUS / DEBUG OUTPUTS — NO PHYSICAL CONNECTIONS
# ============================================================================
# The following RTL output ports have no corresponding FPGA pins in the
# schematic. The only FPGA→STM32 outputs available are DIG_5 (H11),
# DIG_6 (G12), and DIG_7 (H12) — only 3 pins for potentially 60+ signals.
#
# These constraints are commented out. If status readback is needed, either:
# (a) Multiplex selected status bits onto DIG_5/6/7, or
# (b) Send status data over the SPI interface, or
# (c) Route through USB once FT601 is wired.
#
# Ports affected:
# current_elevation[5:0], current_azimuth[5:0], current_chirp[5:0],
# new_chirp_frame, dbg_doppler_data[31:0], dbg_doppler_valid,
# dbg_doppler_bin[4:0], dbg_range_bin[5:0], system_status[3:0]
# ============================================================================
# ============================================================================
# TIMING EXCEPTIONS
# ============================================================================
# False paths for asynchronous STM32 control signals (active-edge toggle interface)
set_false_path -from [get_ports {stm32_new_*}]
set_false_path -from [get_ports {stm32_mixers_enable}]
# --------------------------------------------------------------------------
# Async reset recovery/removal false paths
#
# The async reset (reset_n) is held asserted for multiple clock cycles during
# power-on and system reset. The recovery/removal timing checks on CLR pins
# are over-constrained for this use case:
# - reset_sync_reg[1] fans out to 1000+ registers across the FPGA
# - Route delay alone exceeds the clock period (18+ ns for 10ns period)
# - Reset deassertion order is not functionally critical — all registers
# come out of reset within a few cycles of each other
# --------------------------------------------------------------------------
set_false_path -from [get_cells reset_sync_reg[*]] -to [get_pins -filter {REF_PIN_NAME == CLR} -of_objects [get_cells -hierarchical -filter {PRIMITIVE_TYPE =~ REGISTER.*.*}]]
# --------------------------------------------------------------------------
# Clock Domain Crossing false paths
# --------------------------------------------------------------------------
# clk_100m ↔ adc_dco_p (400 MHz): DDC has internal CDC synchronizers
set_false_path -from [get_clocks clk_100m] -to [get_clocks adc_dco_p]
set_false_path -from [get_clocks adc_dco_p] -to [get_clocks clk_100m]
# clk_100m ↔ clk_120m_dac: CDC via synchronizers in radar_system_top
set_false_path -from [get_clocks clk_100m] -to [get_clocks clk_120m_dac]
set_false_path -from [get_clocks clk_120m_dac] -to [get_clocks clk_100m]
# FT601 CDC paths removed — no ft601_clk_in clock defined (chip unwired)
# ============================================================================
# PHYSICAL CONSTRAINTS
# ============================================================================
# Pull up unused pins to prevent floating inputs
set_property BITSTREAM.CONFIG.UNUSEDPIN Pullup [current_design]
# ============================================================================
# ADDITIONAL NOTES
# ============================================================================
#
# 1. ADC Sampling Clock: FPGA_ADC_CLOCK_P/N (N11/N12) is the 400 MHz LVDS
# clock from AD9523 OUT5 that drives the AD9484. It connects to FPGA MRCC
# pins but is not used as an FPGA clock input — the ADC returns data with
# its own DCO (adc_dco_p/n on N14/P14).
#
# 2. Clock Test: FPGA_CLOCK_TEST (H14) is a 20 MHz LVCMOS output from the
# FPGA, configured by AD9523 OUT7. Not currently used in RTL.
#
# 3. SPI Flash: FPGA_FLASH_CS (E8), FPGA_FLASH_CLK (J13),
# FPGA_FLASH_D0 (J14), D1 (K15), D2 (K16), D3 (L12), unnamed (L13).
# These are typically handled by Vivado bitstream configuration and do
# not need explicit XDC constraints for user logic.
#
# 4. JTAG: FPGA_TCK (L7), FPGA_TDI (N7), FPGA_TDO (N8), FPGA_TMS (M7).
# Dedicated pins — no XDC constraints needed.
#
# 5. dac_clk port: The RTL top module declares `dac_clk` as an output, but
# the physical board wires the DAC clock (AD9708 CLOCK pin) directly from
# the AD9523, not from the FPGA. This port should be removed from the RTL
# or left unconnected. It currently just assigns clk_120m_dac passthrough.
#
# ============================================================================
# END OF CONSTRAINTS
# ============================================================================
+61 -6
View File
@@ -3,24 +3,79 @@ module dac_interface_enhanced (
input wire reset_n, input wire reset_n,
input wire [7:0] chirp_data, input wire [7:0] chirp_data,
input wire chirp_valid, input wire chirp_valid,
output reg [7:0] dac_data, output wire [7:0] dac_data,
output wire dac_clk, output wire dac_clk,
output wire dac_sleep output wire dac_sleep
); );
// Register DAC data to meet timing // ============================================================================
// DAC data register (fabric FF — feeds ODDR D1/D2 inputs)
// ============================================================================
reg [7:0] dac_data_reg;
always @(posedge clk_120m or negedge reset_n) begin always @(posedge clk_120m or negedge reset_n) begin
if (!reset_n) begin if (!reset_n) begin
dac_data <= 8'd128; // Center value dac_data_reg <= 8'd128; // Center value
end else if (chirp_valid) begin end else if (chirp_valid) begin
dac_data <= chirp_data; dac_data_reg <= chirp_data;
end else begin end else begin
dac_data <= 8'd128; // Default to center when no chirp dac_data_reg <= 8'd128; // Default to center when no chirp
end end
end end
// DAC clock is same as input clock (120MHz) `ifndef SIMULATION
// ============================================================================
// ODDR for dac_clk forwarding (Xilinx 7-series)
// D1=1, D2=0 produces a clock replica aligned to clk_120m rising edge.
// The ODDR is placed in the IOB, giving near-zero skew between the
// forwarded clock and ODDR data outputs in the same bank.
// ============================================================================
ODDR #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"),
.INIT(1'b0),
.SRTYPE("SYNC")
) oddr_dac_clk (
.Q(dac_clk),
.C(clk_120m),
.CE(1'b1),
.D1(1'b1),
.D2(1'b0),
.R(1'b0),
.S(1'b0)
);
// ============================================================================
// ODDR for dac_data[7:0] packs output FFs into IOBs
// D1=D2=same value SDR behavior through ODDR, but placed in IOB.
// This eliminates fabric routing delay to the output pad.
// ============================================================================
genvar i;
generate
for (i = 0; i < 8; i = i + 1) begin : oddr_dac_data_gen
ODDR #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"),
.INIT(1'b0),
.SRTYPE("SYNC")
) oddr_dac_data (
.Q(dac_data[i]),
.C(clk_120m),
.CE(1'b1),
.D1(dac_data_reg[i]),
.D2(dac_data_reg[i]),
.R(1'b0),
.S(1'b0)
);
end
endgenerate
`else
// ============================================================================
// Simulation behavioral equivalent
// ============================================================================
assign dac_clk = clk_120m; assign dac_clk = clk_120m;
assign dac_data = dac_data_reg;
`endif
assign dac_sleep = 1'b0; assign dac_sleep = 1'b0;
endmodule endmodule
+34 -8
View File
@@ -31,7 +31,7 @@ module usb_data_interface (
input wire [1:0] ft601_swb, // Selected write buffer input wire [1:0] ft601_swb, // Selected write buffer
// Clock // Clock
output reg ft601_clk_out, // Output clock to FT601 (optional) output wire ft601_clk_out, // Output clock to FT601 (forwarded via ODDR)
input wire ft601_clk_in // Clock from FT601 (60/100MHz) input wire ft601_clk_in // Clock from FT601 (60/100MHz)
); );
@@ -223,13 +223,39 @@ always @(posedge ft601_clk_in or negedge reset_n) begin
end end
end end
// Generate clock for FT601 if needed (optional) // ============================================================================
always @(posedge clk or negedge reset_n) begin // FT601 clock output forwarding
if (!reset_n) begin // ============================================================================
ft601_clk_out <= 0; // Forward ft601_clk_in back out via ODDR so that the forwarded clock at the
end else begin // pin has the same insertion delay as the data outputs (both go through the
ft601_clk_out <= ~ft601_clk_out; // Divide by 2 from main clock // same BUFG). This makes the output delay analysis relative to the generated
end // clock at the pin, where insertion delays cancel.
`ifndef SIMULATION
ODDR #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"),
.INIT(1'b0),
.SRTYPE("SYNC")
) oddr_ft601_clk (
.Q(ft601_clk_out),
.C(ft601_clk_in),
.CE(1'b1),
.D1(1'b1),
.D2(1'b0),
.R(1'b0),
.S(1'b0)
);
`else
// Simulation: behavioral clock forwarding
reg ft601_clk_out_sim;
always @(posedge ft601_clk_in or negedge reset_n) begin
if (!reset_n)
ft601_clk_out_sim <= 1'b0;
else
ft601_clk_out_sim <= 1'b1;
end end
// In simulation, just pass the clock through
assign ft601_clk_out = ft601_clk_in;
`endif
endmodule endmodule