Files
b210-k7-fpga/top/x300/timing.xdc
T
Wade Fife ac0f45bb0e fpga: x300: Update synchronizer constraint
Original-commit: a270c531f07ea3549ec2f3b69a38b2c5298bf47c
2021-09-13 13:20:37 -05:00

604 lines
45 KiB
Tcl

#
# Copyright 2014 Ettus Research LLC
#
#*******************************************************************************
## Primary clock definitions
# Define clocks
create_clock -name FPGA_CLK -period 5.000 -waveform {0.000 2.500} [get_ports FPGA_CLK_p]
create_clock -name FPGA_REFCLK -period 32.563 -waveform {0.000 16.281} [get_ports FPGA_REFCLK_10MHz_p]
create_clock -name FPGA_125MHz_CLK -period 8.000 -waveform {0.000 4.000} [get_ports FPGA_125MHz_CLK]
create_clock -name DB0_ADC_DCLK -period 5.000 -waveform {0.000 2.500} [get_ports DB0_ADC_DCLK_P]
create_clock -name DB1_ADC_DCLK -period 5.000 -waveform {0.000 2.500} [get_ports DB1_ADC_DCLK_P]
create_clock -name IoRxClock -period 4.000 -waveform {0.000 2.000} [get_ports IoRxClock]
# Create virtual clock aligned with FPGA_CLK that is twice the frequency for DAC IO Timing.
create_clock -name VIRT_DAC_CLK -period 2.500 -waveform {0.000 1.250}
# Set clock properties
set_input_jitter [get_clocks FPGA_CLK] 0.05
set var_fpga_clk_delay 1.545 ;# LMK_Delay=0.900ns, LMK->FPGA=0.645ns
set var_fpga_clk_skew 0.100
set_clock_latency -source -early [expr $var_fpga_clk_delay - $var_fpga_clk_skew/2] [get_clocks FPGA_CLK]
set_clock_latency -source -late [expr $var_fpga_clk_delay + $var_fpga_clk_skew/2] [get_clocks FPGA_CLK]
set var_adc_clk_delay 8.440 ;# LMK->ADC=1.04ns, ADC->FPGA=0.750ns, ADC=6.65ns=(0.69*5ns)+5.7-2.5
set var_adc_clk_skew 0.500 ;# The real skew is ~3.5ns with which we will not meet static timing. Ignore skew by temp variations.
set_clock_latency -source -early [expr $var_adc_clk_delay - $var_adc_clk_skew/2] [get_clocks DB0_ADC_DCLK]
set_clock_latency -source -late [expr $var_adc_clk_delay + $var_adc_clk_skew/2] [get_clocks DB0_ADC_DCLK]
set_clock_latency -source -early [expr $var_adc_clk_delay - $var_adc_clk_skew/2] [get_clocks DB1_ADC_DCLK]
set_clock_latency -source -late [expr $var_adc_clk_delay + $var_adc_clk_skew/2] [get_clocks DB1_ADC_DCLK]
# FPGA_CLK_p/n is externally phase shifted to allow for crossing from the ADC clock domain
# to the radio_clk (aka FPGA_CLK_p/n) clock domain. To ensure this timing is consistent,
# lock the locations of the MMCM and BUFG to generate radio_clk.
set_property LOC MMCME2_ADV_X0Y0 [get_cells -hierarchical -filter {NAME =~ "*radio_clk_gen/*mmcm_adv_inst"}]
set_property LOC BUFGCTRL_X0Y8 [get_cells -hierarchical -filter {NAME =~ "*radio_clk_gen/*clkout1_buf"}]
# The PCIe specific 40MHz and 200MHz clocks are only active in clock regious X0Y0 and X1Y0 so we use BUFHs
# to distribute them. To do so, we have to use a PLL because the MMCM in that region is used by radio_clk_gen
# Since that MMCM is LOC constrained, we must LOC constrain this PLL as well.
set_property LOC PLLE2_ADV_X0Y0 [get_cells -hierarchical -filter {NAME =~ "*pcie_clk_gen/*plle2_adv_inst"}]
#*******************************************************************************
## Generated clock definitions
create_generated_clock -name DB0_DAC_DCI -source [get_pins gen_db0/oddr_clk/C] -divide_by 1 [get_ports DB0_DAC_DCI_P]
create_generated_clock -name DB1_DAC_DCI -source [get_pins gen_db1/oddr_clk/C] -divide_by 1 [get_ports DB1_DAC_DCI_P]
create_generated_clock -name IoTxClock -multiply_by 1 \
-source [get_pins -hier -filter {NAME =~ lvfpga_chinch_inst/*/TxClockGenx/TxUseMmcm.TxMmcm/CLKOUT0}] \
[get_ports {IoTxClock}]
#*******************************************************************************
## Aliases for auto-generated clocks
create_generated_clock -name radio_clk [get_pins -hierarchical -filter {NAME =~ "*radio_clk_gen/*/CLKOUT0"}]
create_generated_clock -name radio_clk_2x [get_pins -hierarchical -filter {NAME =~ "*radio_clk_gen/*/CLKOUT1"}]
#create_generated_clock -name dac_dci_clk [get_pins -hierarchical -filter {NAME =~ "*radio_clk_gen/*/CLKOUT2"}]
create_generated_clock -name bus_clk [get_pins -hierarchical -filter {NAME =~ "*bus_clk_gen/*/CLKOUT0"}]
create_generated_clock -name bus_clk_div2 [get_pins -hierarchical -filter {NAME =~ "*bus_clk_gen/*/CLKOUT2"}]
create_generated_clock -name ce_clk [get_pins -hierarchical -filter {NAME =~ "*bus_clk_gen/*/CLKOUT3"}]
create_generated_clock -name ioport2_clk [get_pins -hierarchical -filter {NAME =~ "*bus_clk_gen/*/CLKFBOUT"}]
create_generated_clock -name rio40_clk [get_pins -hierarchical -filter {NAME =~ "*pcie_clk_gen/*/CLKOUT0"}]
create_generated_clock -name ioport2_idelay_ref_clk [get_pins -hierarchical -filter {NAME =~ "*pcie_clk_gen/*/CLKOUT1"}]
#*******************************************************************************
## Asynchronous clock groups
set_clock_groups -asynchronous -group [get_clocks bus_clk] -group [get_clocks ioport2_clk]
set_clock_groups -asynchronous -group [get_clocks ioport2_clk] -group [get_clocks rio40_clk]
set_clock_groups -asynchronous -group [get_clocks bus_clk] -group [get_clocks radio_clk]
set_clock_groups -asynchronous -group [get_clocks bus_clk_div2] -group [get_clocks radio_clk]
set_clock_groups -asynchronous -group [get_clocks ioport2_clk] -group [get_clocks IoPort2Wrapperx/RxLowSpeedClk]
set_clock_groups -asynchronous -group [get_clocks bus_clk] -group [get_clocks FPGA_REFCLK]
set_clock_groups -asynchronous -group [get_clocks ce_clk] -group [get_clocks bus_clk]
set_clock_groups -asynchronous -group [get_clocks ce_clk] -group [get_clocks radio_clk]
#*******************************************************************************
## ADC Interface
# At 200 MHz, static timing cannot be closed so we tune data delays on the capture
# interface from software at device creation time.
# The data is center aligned wrt to the SS Clock when it is launched from the ADC
# So we tune the data IDELAYS to half the range (16) so we have slack in both directions
# In the constraints we capture this by padding the dv_before and dv_after by half the
# tuning range of the IDELAY.
# Using typical values for ADC
set adc_clk_delay_wrt_center 0.000 ;# Possible {-1.340, -0.769, 0, 0.769}
set adc_in_dv_before_clk_edge 0.550 ;# Typical: 0.90ns
set adc_in_dv_after_clk_edge 0.550 ;# Typical: 0.95ns
set idelay_tune_range 2.500 ;# Refclk for IDELAY is 200MHz. Range of idelay is 0.5*period
set adc_in_delay_max [expr 2.500 - $adc_in_dv_before_clk_edge - $idelay_tune_range + $adc_clk_delay_wrt_center]
set adc_in_delay_min [expr $adc_in_dv_after_clk_edge + $idelay_tune_range - $adc_clk_delay_wrt_center]
set_input_delay -clock DB0_ADC_DCLK -max $adc_in_delay_max [get_ports {DB0_ADC_DA*}]
set_input_delay -clock DB0_ADC_DCLK -min $adc_in_delay_min [get_ports {DB0_ADC_DA*}]
set_input_delay -clock DB0_ADC_DCLK -max $adc_in_delay_max -clock_fall -add_delay [get_ports {DB0_ADC_DA*}]
set_input_delay -clock DB0_ADC_DCLK -min $adc_in_delay_min -clock_fall -add_delay [get_ports {DB0_ADC_DA*}]
set_input_delay -clock DB0_ADC_DCLK -max $adc_in_delay_max [get_ports {DB0_ADC_DB*}]
set_input_delay -clock DB0_ADC_DCLK -min $adc_in_delay_min [get_ports {DB0_ADC_DB*}]
set_input_delay -clock DB0_ADC_DCLK -max $adc_in_delay_max -clock_fall -add_delay [get_ports {DB0_ADC_DB*}]
set_input_delay -clock DB0_ADC_DCLK -min $adc_in_delay_min -clock_fall -add_delay [get_ports {DB0_ADC_DB*}]
set_input_delay -clock DB1_ADC_DCLK -max $adc_in_delay_max [get_ports {DB1_ADC_DA*}]
set_input_delay -clock DB1_ADC_DCLK -min $adc_in_delay_min [get_ports {DB1_ADC_DA*}]
set_input_delay -clock DB1_ADC_DCLK -max $adc_in_delay_max -clock_fall -add_delay [get_ports {DB1_ADC_DA*}]
set_input_delay -clock DB1_ADC_DCLK -min $adc_in_delay_min -clock_fall -add_delay [get_ports {DB1_ADC_DA*}]
set_input_delay -clock DB1_ADC_DCLK -max $adc_in_delay_max [get_ports {DB1_ADC_DB*}]
set_input_delay -clock DB1_ADC_DCLK -min $adc_in_delay_min [get_ports {DB1_ADC_DB*}]
set_input_delay -clock DB1_ADC_DCLK -max $adc_in_delay_max -clock_fall -add_delay [get_ports {DB1_ADC_DB*}]
set_input_delay -clock DB1_ADC_DCLK -min $adc_in_delay_min -clock_fall -add_delay [get_ports {DB1_ADC_DB*}]
# We use a simple synchronizer to cross ADC data over from the ADC_CLK domain to the radio_clk domain
# Use max delay constraints to ensure that the transition happens safely
set_min_delay 0.700 -from [get_cells {cap_db0/gen_lvds_pins[*].iddr_i}] \
-to [get_cells {cap_db0/adc_data_rclk_reg*[*]}]
set_min_delay 0.700 -from [get_cells {cap_db1/gen_lvds_pins[*].iddr_i}] \
-to [get_cells {cap_db1/adc_data_rclk_reg*[*]}]
set_max_delay -datapath_only 0.950 -from [get_cells {cap_db0/gen_lvds_pins[*].iddr_i}] \
-to [get_cells {cap_db0/adc_data_rclk_reg*[*]}]
set_max_delay -datapath_only 0.950 -from [get_cells {cap_db1/gen_lvds_pins[*].iddr_i}] \
-to [get_cells {cap_db1/adc_data_rclk_reg*[*]}]
# We also need to location constrain the first flops in the synchronizer to help the tools
# meet timing reliably
# ADC0
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[0]}]
set_property LOC SLICE_X1Y192 [get_cells {cap_db0/adc_data_rclk_reg*[0]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[1]}]
set_property LOC SLICE_X1Y192 [get_cells {cap_db0/adc_data_rclk_reg*[1]}]
set_property BEL AFF [get_cells {cap_db0/adc_data_rclk_reg*[2]}]
set_property LOC SLICE_X1Y190 [get_cells {cap_db0/adc_data_rclk_reg*[2]}]
set_property BEL BFF [get_cells {cap_db0/adc_data_rclk_reg*[3]}]
set_property LOC SLICE_X1Y190 [get_cells {cap_db0/adc_data_rclk_reg*[3]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[4]}]
set_property LOC SLICE_X1Y188 [get_cells {cap_db0/adc_data_rclk_reg*[4]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[5]}]
set_property LOC SLICE_X1Y188 [get_cells {cap_db0/adc_data_rclk_reg*[5]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[6]}]
set_property LOC SLICE_X1Y186 [get_cells {cap_db0/adc_data_rclk_reg*[6]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[7]}]
set_property LOC SLICE_X1Y186 [get_cells {cap_db0/adc_data_rclk_reg*[7]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[8]}]
set_property LOC SLICE_X1Y184 [get_cells {cap_db0/adc_data_rclk_reg*[8]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[9]}]
set_property LOC SLICE_X1Y184 [get_cells {cap_db0/adc_data_rclk_reg*[9]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[10]}]
set_property LOC SLICE_X1Y182 [get_cells {cap_db0/adc_data_rclk_reg*[10]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[11]}]
set_property LOC SLICE_X1Y182 [get_cells {cap_db0/adc_data_rclk_reg*[11]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[12]}]
set_property LOC SLICE_X1Y180 [get_cells {cap_db0/adc_data_rclk_reg*[12]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[13]}]
set_property LOC SLICE_X1Y180 [get_cells {cap_db0/adc_data_rclk_reg*[13]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[14]}]
set_property LOC SLICE_X1Y178 [get_cells {cap_db0/adc_data_rclk_reg*[14]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[15]}]
set_property LOC SLICE_X1Y178 [get_cells {cap_db0/adc_data_rclk_reg*[15]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[16]}]
set_property LOC SLICE_X1Y174 [get_cells {cap_db0/adc_data_rclk_reg*[16]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[17]}]
set_property LOC SLICE_X1Y174 [get_cells {cap_db0/adc_data_rclk_reg*[17]}]
set_property BEL AFF [get_cells {cap_db0/adc_data_rclk_reg*[18]}]
set_property LOC SLICE_X1Y172 [get_cells {cap_db0/adc_data_rclk_reg*[18]}]
set_property BEL BFF [get_cells {cap_db0/adc_data_rclk_reg*[19]}]
set_property LOC SLICE_X1Y172 [get_cells {cap_db0/adc_data_rclk_reg*[19]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[20]}]
set_property LOC SLICE_X1Y218 [get_cells {cap_db0/adc_data_rclk_reg*[20]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[21]}]
set_property LOC SLICE_X1Y218 [get_cells {cap_db0/adc_data_rclk_reg*[21]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[22]}]
set_property LOC SLICE_X1Y198 [get_cells {cap_db0/adc_data_rclk_reg*[22]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[23]}]
set_property LOC SLICE_X1Y198 [get_cells {cap_db0/adc_data_rclk_reg*[23]}]
set_property BEL AFF [get_cells {cap_db0/adc_data_rclk_reg*[24]}]
set_property LOC SLICE_X1Y196 [get_cells {cap_db0/adc_data_rclk_reg*[24]}]
set_property BEL BFF [get_cells {cap_db0/adc_data_rclk_reg*[25]}]
set_property LOC SLICE_X1Y196 [get_cells {cap_db0/adc_data_rclk_reg*[25]}]
set_property BEL A5FF [get_cells {cap_db0/adc_data_rclk_reg*[26]}]
set_property LOC SLICE_X1Y194 [get_cells {cap_db0/adc_data_rclk_reg*[26]}]
set_property BEL B5FF [get_cells {cap_db0/adc_data_rclk_reg*[27]}]
set_property LOC SLICE_X1Y194 [get_cells {cap_db0/adc_data_rclk_reg*[27]}]
# ADC1
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[0]}]
set_property LOC SLICE_X1Y298 [get_cells {cap_db1/adc_data_rclk_reg*[0]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[1]}]
set_property LOC SLICE_X1Y298 [get_cells {cap_db1/adc_data_rclk_reg*[1]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[2]}]
set_property LOC SLICE_X1Y284 [get_cells {cap_db1/adc_data_rclk_reg*[2]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[3]}]
set_property LOC SLICE_X1Y284 [get_cells {cap_db1/adc_data_rclk_reg*[3]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[4]}]
set_property LOC SLICE_X1Y288 [get_cells {cap_db1/adc_data_rclk_reg*[4]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[5]}]
set_property LOC SLICE_X1Y288 [get_cells {cap_db1/adc_data_rclk_reg*[5]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[6]}]
set_property LOC SLICE_X1Y282 [get_cells {cap_db1/adc_data_rclk_reg*[6]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[7]}]
set_property LOC SLICE_X1Y282 [get_cells {cap_db1/adc_data_rclk_reg*[7]}]
set_property BEL AFF [get_cells {cap_db1/adc_data_rclk_reg*[8]}]
set_property LOC SLICE_X1Y296 [get_cells {cap_db1/adc_data_rclk_reg*[8]}]
set_property BEL BFF [get_cells {cap_db1/adc_data_rclk_reg*[9]}]
set_property LOC SLICE_X1Y296 [get_cells {cap_db1/adc_data_rclk_reg*[9]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[10]}]
set_property LOC SLICE_X1Y280 [get_cells {cap_db1/adc_data_rclk_reg*[10]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[11]}]
set_property LOC SLICE_X1Y280 [get_cells {cap_db1/adc_data_rclk_reg*[11]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[12]}]
set_property LOC SLICE_X1Y286 [get_cells {cap_db1/adc_data_rclk_reg*[12]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[13]}]
set_property LOC SLICE_X1Y286 [get_cells {cap_db1/adc_data_rclk_reg*[13]}]
set_property BEL AFF [get_cells {cap_db1/adc_data_rclk_reg*[14]}]
set_property LOC SLICE_X1Y274 [get_cells {cap_db1/adc_data_rclk_reg*[14]}]
set_property BEL BFF [get_cells {cap_db1/adc_data_rclk_reg*[15]}]
set_property LOC SLICE_X1Y274 [get_cells {cap_db1/adc_data_rclk_reg*[15]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[16]}]
set_property LOC SLICE_X1Y272 [get_cells {cap_db1/adc_data_rclk_reg*[16]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[17]}]
set_property LOC SLICE_X1Y272 [get_cells {cap_db1/adc_data_rclk_reg*[17]}]
set_property BEL AFF [get_cells {cap_db1/adc_data_rclk_reg*[18]}]
set_property LOC SLICE_X1Y290 [get_cells {cap_db1/adc_data_rclk_reg*[18]}]
set_property BEL BFF [get_cells {cap_db1/adc_data_rclk_reg*[19]}]
set_property LOC SLICE_X1Y290 [get_cells {cap_db1/adc_data_rclk_reg*[19]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[20]}]
set_property LOC SLICE_X1Y342 [get_cells {cap_db1/adc_data_rclk_reg*[20]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[21]}]
set_property LOC SLICE_X1Y342 [get_cells {cap_db1/adc_data_rclk_reg*[21]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[22]}]
set_property LOC SLICE_X1Y294 [get_cells {cap_db1/adc_data_rclk_reg*[22]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[23]}]
set_property LOC SLICE_X1Y294 [get_cells {cap_db1/adc_data_rclk_reg*[23]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[24]}]
set_property LOC SLICE_X1Y268 [get_cells {cap_db1/adc_data_rclk_reg*[24]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[25]}]
set_property LOC SLICE_X1Y268 [get_cells {cap_db1/adc_data_rclk_reg*[25]}]
set_property BEL A5FF [get_cells {cap_db1/adc_data_rclk_reg*[26]}]
set_property LOC SLICE_X1Y292 [get_cells {cap_db1/adc_data_rclk_reg*[26]}]
set_property BEL B5FF [get_cells {cap_db1/adc_data_rclk_reg*[27]}]
set_property LOC SLICE_X1Y292 [get_cells {cap_db1/adc_data_rclk_reg*[27]}]
# IODELAY constraints
set_property IODELAY_GROUP ADC_CAP_IODELAY_GRP [get_cells adc_cap_idelayctrl_i]
set_property IODELAY_GROUP ADC_CAP_IODELAY_GRP [get_cells {cap_db0/gen_lvds_pins[*].idelay_i}]
set_property IODELAY_GROUP ADC_CAP_IODELAY_GRP [get_cells {cap_db1/gen_lvds_pins[*].idelay_i}]
#*******************************************************************************
## DAC Interface
# DCI System-Sync Timing
# The DCI clock driven to the DACs must obey setup and hold timing with respect to
# the reference clock driven to the DACs (same as the FPGA_CLK, driven by the LMK).
# Define the minimum and maximum clock propagation delays through the FPGA in order to
# meet this system-wide timing.
set dac0_clk_offset_out_max 1.350
set dac0_clk_offset_out_min 0.225
set dac1_clk_offset_out_max 1.350
set dac1_clk_offset_out_min 0.225
# The absolute latest the DCI clock should change is the sum of the maximum delay through
# the FPGA and the latest the sourcing clock (FPGA_CLK) can arrive at the FPGA. This is an
# artifact of the set_clock_latency constraints and doing system-wide timing. Typically,
# these Early/Late delays are automatically compensated for by the analyzer. However this
# is only the case for signals that start and end in the same PRIMARY clock domain. In
# our case, VIRT_DAC_CLK and radio_clk are not the same clock domain and
# therefore we have to manually remove the added Early/Late values from analysis.
set dac0_dci_out_delay_max [expr $dac0_clk_offset_out_max + $var_fpga_clk_delay + $var_fpga_clk_skew/2]
set dac0_dci_out_delay_min [expr $dac0_clk_offset_out_min + $var_fpga_clk_delay - $var_fpga_clk_skew/2]
set dac1_dci_out_delay_max [expr $dac1_clk_offset_out_max + $var_fpga_clk_delay + $var_fpga_clk_skew/2]
set dac1_dci_out_delay_min [expr $dac1_clk_offset_out_min + $var_fpga_clk_delay - $var_fpga_clk_skew/2]
# The min set_output_delay is the earliest the DCI clock should change BEFORE the current
# edge of interest. Here it is inverted (negated) because the earliest the clock should
# change is dac0_dci_out_delay_min AFTER the launch edge of the virtual clock.
set_output_delay -clock VIRT_DAC_CLK -min [expr - $dac0_dci_out_delay_min] [get_ports {DB0_DAC_DCI_*}]
set_output_delay -clock VIRT_DAC_CLK -min [expr - $dac0_dci_out_delay_min] -clock_fall -add_delay [get_ports {DB0_DAC_DCI_*}]
set_output_delay -clock VIRT_DAC_CLK -min [expr - $dac1_dci_out_delay_min] [get_ports {DB1_DAC_DCI_*}]
set_output_delay -clock VIRT_DAC_CLK -min [expr - $dac1_dci_out_delay_min] -clock_fall -add_delay [get_ports {DB1_DAC_DCI_*}]
# The max set_output_delay is the time the data should be stable before the next
# edge of interest. Since we are DDR, this is the falling edge. Hence we subtract
# latest time the data should change, dac0_dci_out_delay_max, from the falling edge
# time, dci_period/2 = 1.25ns.
set_output_delay -clock VIRT_DAC_CLK -max [expr 1.25 - $dac0_dci_out_delay_max] [get_ports {DB0_DAC_DCI_*}]
set_output_delay -clock VIRT_DAC_CLK -max [expr 1.25 - $dac0_dci_out_delay_max] -clock_fall -add_delay [get_ports {DB0_DAC_DCI_*}]
set_output_delay -clock VIRT_DAC_CLK -max [expr 1.25 - $dac1_dci_out_delay_max] [get_ports {DB1_DAC_DCI_*}]
set_output_delay -clock VIRT_DAC_CLK -max [expr 1.25 - $dac1_dci_out_delay_max] -clock_fall -add_delay [get_ports {DB1_DAC_DCI_*}]
# Data to DCI Source-Sync Timing
# The data setup and hold values must be modified in order to pass timing in
# the FPGA. The correct values are 0.270 and 0.090 for setup and hold, respectively.
# The interface fails by around 390 ps in both directions, so we subtract the failing
# amount from the actual amount to get a passing constraint.
# NOTE: Any changes to the adjustment margin below would need to be validated over
# multiple builds, process and temperature. Try not to change it!
set dac_data_setup 0.270
set dac_data_hold 0.090
set dac_setup_adj 0.390
set dac_hold_adj 0.390
# These are real trace delays from the timing spreadsheet. Note that we are assuming
# no variability in our clock delay.
set dac0_data_delay_max 1.036
set dac0_data_delay_min 0.898
set dac0_clk_delay_max 0.974
set dac0_clk_delay_min 0.974
set dac1_data_delay_max 0.941
set dac1_data_delay_min 0.833
set dac1_clk_delay_max 0.930
set dac1_clk_delay_min 0.930
set dac0_out_delay_max [expr $dac0_data_delay_max - $dac0_clk_delay_min + $dac_data_setup - $dac_setup_adj]
set dac0_out_delay_min [expr $dac0_data_delay_min - $dac0_clk_delay_max - $dac_data_hold + $dac_hold_adj]
set dac1_out_delay_max [expr $dac1_data_delay_max - $dac1_clk_delay_min + $dac_data_setup - $dac_setup_adj]
set dac1_out_delay_min [expr $dac1_data_delay_min - $dac1_clk_delay_max - $dac_data_hold + $dac_hold_adj]
set_output_delay -clock [get_clocks DB0_DAC_DCI] -max $dac0_out_delay_max [get_ports -regexp {DB0_DAC_D._. DB0_DAC_FRAME_.}]
set_output_delay -clock [get_clocks DB0_DAC_DCI] -max $dac0_out_delay_max -clock_fall -add_delay [get_ports -regexp {DB0_DAC_D._. DB0_DAC_FRAME_.}]
set_output_delay -clock [get_clocks DB0_DAC_DCI] -min $dac0_out_delay_min [get_ports -regexp {DB0_DAC_D._. DB0_DAC_FRAME_.}]
set_output_delay -clock [get_clocks DB0_DAC_DCI] -min $dac0_out_delay_min -clock_fall -add_delay [get_ports -regexp {DB0_DAC_D._. DB0_DAC_FRAME_.}]
set_output_delay -clock [get_clocks DB1_DAC_DCI] -max $dac1_out_delay_max [get_ports -regexp {DB1_DAC_D._. DB1_DAC_FRAME_.}]
set_output_delay -clock [get_clocks DB1_DAC_DCI] -max $dac1_out_delay_max -clock_fall -add_delay [get_ports -regexp {DB1_DAC_D._. DB1_DAC_FRAME_.}]
set_output_delay -clock [get_clocks DB1_DAC_DCI] -min $dac1_out_delay_min [get_ports -regexp {DB1_DAC_D._. DB1_DAC_FRAME_.}]
set_output_delay -clock [get_clocks DB1_DAC_DCI] -min $dac1_out_delay_min -clock_fall -add_delay [get_ports -regexp {DB1_DAC_D._. DB1_DAC_FRAME_.}]
#*******************************************************************************
## IoPort2
# Constrain the location of the IDELAYCTERL associated with the interface trainer IDELAYs
set_property LOC IDELAYCTRL_X1Y0 [get_cells lvfpga_chinch_inst/IDELAYCTRLx]
# RX Pad Input constraints
set_input_delay -clock [get_clocks IoRxClock] -max 2.580 [get_ports {irIoRx*}]
set_input_delay -clock [get_clocks IoRxClock] -min 2.280 [get_ports {irIoRx*}]
set_input_delay -clock [get_clocks IoRxClock] -max 2.580 -clock_fall -add_delay [get_ports {irIoRx*}]
set_input_delay -clock [get_clocks IoRxClock] -min 2.280 -clock_fall -add_delay [get_ports {irIoRx*}]
# Note: The input clock N-Side ISERDES is not constrained for IO timing since
# adding an input delay does not work as the clock and data are the same.
# Since the architecture requires dedicated routes, the build-to-build
# variablilty will be zero and therefore, no separate timing constraint
# is necessary for the N-Side pin. The RxClock delay is constrained because
# of the input delay constraints on the rest of the bus. This path does, however,
# require a max delay constraint in order to override the default analysis:
set_max_delay -from [get_ports {IoRxClock*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Wrapperx/RxClockGenx/RxClockSerdes*}] \
2.0 -datapath_only
# TX Pad Output constraints
set_output_delay -clock [get_clocks IoTxClock] -max 1.600 [get_ports {itIoTx*}]
set_output_delay -clock [get_clocks IoTxClock] -min 0.400 [get_ports {itIoTx*}]
set_output_delay -clock [get_clocks IoTxClock] -max 1.600 -clock_fall -add_delay [get_ports {itIoTx*}]
set_output_delay -clock [get_clocks IoTxClock] -min 0.400 -clock_fall -add_delay [get_ports {itIoTx*}]
# These signals are all treated as async signals so no stringent timing requirements are needed.
set_max_delay -to [get_ports aIrq*] 10.000
set_max_delay -from [get_ports aIoResetIn_n] 10.000
set_max_delay -from [get_ports aIoReadyIn] 10.000
set_max_delay -to [get_ports aIoReadyOut] 10.000
set_max_delay -to [get_ports aIoPort2Restart] 10.000
set_false_path -from [get_ports aStc3Gpio7]
# Async reset
set_false_path -from [get_cells -hier -filter {NAME =~ lvfpga_chinch_inst/*StartupFsmx/aResetLcl*}]
# Double Sync
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Wrapperx/tIoResetSync/DoubleSyncBasex/iDlySig*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Wrapperx/tIoResetSync/DoubleSyncBasex/DoubleSyncAsyncInBasex/oSig_ms*}] \
6.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Wrapperx/bIoResetAckSync/DoubleSyncBasex/iDlySig*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Wrapperx/bIoResetAckSync/DoubleSyncBasex/DoubleSyncAsyncInBasex/oSig_ms*}] \
6.0 -datapath_only
# Constrains HandshakeSLVx and IClkToPushClkHs in ControlIoDelayClockCross
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/*iLclStoredData*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/*ODataFlop*}] \
8.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/iPushToggle}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/BlkOut.oPushToggle0_ms*}] \
4.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/BlkOut.oPushToggle0_ms*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/BlkOut.oPushToggle1*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/*oPushToggleToReady*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/*iRdyPushToggle_ms*}] \
4.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/*iRdyPushToggle_ms*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/*ControlIoDelayClockCrossx/*/HBx/*iRdyPushToggle*}] \
4.0
# SamplerResultsHandshake and SamplerControlHandshake
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/*iLclStoredData*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/*ODataFlop*}] \
6.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/iPushToggle}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/BlkOut.oPushToggle0_ms*}] \
4.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/BlkOut.oPushToggle0_ms*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/BlkOut.oPushToggle1*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/*oPushToggleToReady*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/*iRdyPushToggle_ms*}] \
4.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/*iRdyPushToggle_ms*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/ClockSamplerBlock.Sampler*Handshake/HBx/*iRdyPushToggle*}] \
4.0
# Constrain PhyResetSync PulseSync
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/TrainerBlock.PhyResetSync/PulseSyncBasex/iHoldSigInx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/TrainerBlock.PhyResetSync/PulseSyncBasex/oHoldSigIn_msx*}] \
4.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/TrainerBlock.PhyResetSync/PulseSyncBasex/oHoldSigIn_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/TrainerBlock.PhyResetSync/PulseSyncBasex/oLocalSigOutCEx*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/TrainerBlock.PhyResetSync/PulseSyncBasex/oLocalSigOutCEx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/TrainerBlock.PhyResetSync/PulseSyncBasex/iSigOut_msx*}] \
4.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/TrainerBlock.PhyResetSync/PulseSyncBasex/iSigOut_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPortClkDelayTrainerx/TrainerBlock.PhyResetSync/PulseSyncBasex/iSigOutx*}] \
4.0
# IoPort2 Core Clock Crossings
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoPort2Receiverx/PacketReceivedDoublesync*iDlySigx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoPort2Receiverx/PacketReceivedDoublesync*DoubleSyncAsyncInBasex*}] \
6.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoPort2Receiverx/PacketReceivedDoublesync*DoubleSyncAsyncInBasex/oSig_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoPort2Receiverx/PacketReceivedDoublesync*DoubleSyncAsyncInBasex/oSigx*}] \
6.0
# Handshake
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/*iLclStoredData*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/*ODataFlop*}] \
10.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/iPushToggle}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/BlkOut.oPushToggle0_ms*}] \
6.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/BlkOut.oPushToggle0_ms*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/BlkOut.oPushToggle1*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/*oPushToggleToReady*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/*iRdyPushToggle_ms*}] \
6.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/*iRdyPushToggle_ms*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/CreditManager*/HBx/*iRdyPushToggle*}] \
4.0
# FIFO Clock Crossings
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/FifoFlags/ieInputCountGrayx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/FifoFlags/oInputCountGray_msx*}] \
5.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/FifoFlags/oInputCountGray_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/FifoFlags/oInputCountGrayx*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/PacketFullyReceived/ieInputCountGrayx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/PacketFullyReceived/oInputCountGray_msx*}] \
5.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/PacketFullyReceived/oInputCountGray_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/ReceiveSide.IoReceiveFifoBasex/PacketFullyReceived/oInputCountGrayx*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.PacketFullyReceived/ieInputCountGrayx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.PacketFullyReceived/oInputCountGray_msx*}] \
5.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.PacketFullyReceived/oInputCountGray_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.PacketFullyReceived/oInputCountGrayx*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.PacketFullyReceived/oeOutputCountGrayx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.PacketFullyReceived/iOutputCountGray_msx*}] \
5.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.PacketFullyReceived/iOutputCountGray_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.PacketFullyReceived/iOutputCountGrayx*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/ieInputCountGrayx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/oInputCountGray_msx*}] \
5.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/oInputCountGray_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/oInputCountGrayx*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/oeOutputCountGrayx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/iOutputCountGray_msx*}] \
5.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/iOutputCountGray_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/iOutputCountGrayx*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo.InputFifo.FifoFlags/oeOutputCountGrayx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/TransmitFifo*DualPortRAMx*oDlyAddr*}] \
5.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/*iLclStoredData*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/*ODataFlop*}] \
10.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/iPushToggle}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/BlkOut.oPushToggle0_ms*}] \
6.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/BlkOut.oPushToggle0_ms*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/BlkOut.oPushToggle1*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/*oPushToggleToReady*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/*iRdyPushToggle_ms*}] \
6.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/*iRdyPushToggle_ms*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/TransmitSide.IoTransmitFifox/CreditManager.HandshakeCredits/HBx/*iRdyPushToggle*}] \
4.0
# Double Sync
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/Startup.DoubleSyncEnableTransmit/iDlySigx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/Startup.DoubleSyncEnableTransmit/*DoubleSyncAsyncInBasex/oSig_msx*}] \
6.0 -datapath_only
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/Startup.DoubleSyncEnableTransmit/*DoubleSyncAsyncInBasex/oSig_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2x/IoPort2Basex/Startup.DoubleSyncEnableTransmit/*DoubleSyncAsyncInBasex/oSigx*}] \
4.0
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/DoubleSyncWidePortMode.DoubleSync*WidePortMode/iDlySigx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/DoubleSyncWidePortMode.DoubleSync*WidePortMode/DoubleSyncAsyncInBasex*}] \
6.0 -datapath_only -quiet
set_max_delay -from [get_cells -hier -filter {NAME =~ *IoPort2Basex/DoubleSyncWidePortMode.DoubleSync*WidePortMode/DoubleSyncAsyncInBasex/oSig_msx*}] \
-to [get_cells -hier -filter {NAME =~ *IoPort2Basex/DoubleSyncWidePortMode.DoubleSync*WidePortMode/DoubleSyncAsyncInBasex/oSigx*}] \
5.0 -quiet
#*******************************************************************************
## PPS Timing
# Constrain delay from PPS input pins to the first stage synchronizer flip-flop
set_max_delay 5.000 -from [get_ports EXT_PPS_IN] \
-to [get_pins -hier -filter {NAME =~ */pps_sync_refclk_inst/synchronizer_constrained/stages[0].value_reg[*]/D}] \
-datapath_only
set_min_delay 2.500 -from [get_ports EXT_PPS_IN] \
-to [get_pins -hier -filter {NAME =~ */pps_sync_refclk_inst/synchronizer_constrained/stages[0].value_reg[*]/D}]
set_max_delay 5.000 -from [get_ports GPS_PPS_OUT] \
-to [get_pins -hier -filter {NAME =~ */pps_sync_refclk_inst/synchronizer_constrained/stages[0].value_reg[*]/D}] \
-datapath_only
set_min_delay 2.500 -from [get_ports GPS_PPS_OUT] \
-to [get_pins -hier -filter {NAME =~ */pps_sync_refclk_inst/synchronizer_constrained/stages[0].value_reg[*]/D}]
# Constrain input-output delay for external PPS
set_max_delay 10.000 -from [get_ports EXT_PPS_IN] -to [get_ports {EXT_PPS_OUT}] -datapath_only
set_min_delay 5.000 -from [get_ports EXT_PPS_IN] -to [get_ports {EXT_PPS_OUT}]
# Constrain delay to the first flop in radio_clk with about 1ns of slack
set_max_delay 6.500 -to [get_pins -hier -filter {NAME =~ */pps_sync_tbclk_inst/synchronizer_constrained/stages[0].value_reg[*]/D}]
set_min_delay 0.500 -to [get_pins -hier -filter {NAME =~ */pps_sync_tbclk_inst/synchronizer_constrained/stages[0].value_reg[*]/D}]
#*******************************************************************************
## Miscellaneous Interfaces
# Dboard and Front-Panel GPIO Interfaces
# We force the registers closest to the PADs into the IOB to achieve lowest skew between individual bits
# in the parallel bus. However, as a sanity check we add the following constraints that will fail if the
# registers don't get placed in the IOB for whatever reason.
set_max_delay 6.000 -to [get_ports * -filter {(DIRECTION == OUT || DIRECTION == INOUT) && NAME =~ "DB*_*X_IO*"}]
set_max_delay 3.000 -from [get_ports * -filter {(DIRECTION == IN || DIRECTION == INOUT) && NAME =~ "DB*_*X_IO*"}]
set_max_delay 6.000 -to [get_ports * -filter {(DIRECTION == OUT || DIRECTION == INOUT) && NAME =~ "FrontPanelGpio[*]"}]
set_max_delay 3.000 -from [get_ports * -filter {(DIRECTION == IN || DIRECTION == INOUT) && NAME =~ "FrontPanelGpio[*]"}]
# SPI Lines
set_max_delay 10.000 -datapath_only \
-from [get_ports {DB*_*X*MISO*}]
set_max_delay 10.000 -to [get_ports {DB*_*SCLK DB*_*SEN DB*_*MOSI}]
set_max_delay 10.000 -to [get_ports {DB_SCL DB_SDA DB0_DAC_ENABLE DB1_DAC_ENABLE DB_ADC_RESET DB_DAC_RESET}]
set_max_delay 10.000 -from [get_ports {DB_SCL DB_SDA DB_DAC_MOSI}]
# Clock distribution chip control
set_max_delay -from [get_ports {LMK_Status[*] LMK_Holdover LMK_Lock LMK_Sync}] 10.000
set_max_delay -to [get_ports {LMK_SEN LMK_MOSI LMK_SCLK}] 10.000
set_max_delay -to [get_ports {ClockRefSelect*}] 10.000
set_max_delay -to [get_ports {TCXO_ENA}] 10.000
# GPS UART
set_max_delay -from [get_ports {GPS_SER_OUT}] 6.000
set_max_delay -to [get_ports {GPS_SER_IN}] 6.000
set_max_delay -from [get_ports {GPS_LOCK_OK}] 25.000
# Reset paths
# All asynchronous resets must be held for at least 20ns
# which is 2+2 radio_clk cycles @200MHz or 2+2 bus_clk cycles @166MHz
set_max_delay -to [get_pins {int_reset_sync/reset_int*/PRE}] 12.000
set_max_delay -to [get_pins {int_div2_reset_sync/reset_int*/PRE}] 12.000
set_max_delay -to [get_pins {ce_reset_sync/reset_int*/PRE}] 12.000
set_max_delay -to [get_pins {radio_reset_sync/reset_int*/PRE}] 10.000
#*******************************************************************************
## Asynchronous paths
set_false_path -to [get_pins -hierarchical -filter {NAME =~ */synchronizer_false_path/stages[0].value_reg[0][*]/D}]
set_false_path -to [get_ports LED_*]
set_false_path -to [get_ports {SFPP*_RS0 SFPP*_RS1 SFPP*_SCL SFPP*_SDA SFPP*_TxDisable}]
set_false_path -from [get_ports {SFPP*_ModAbs SFPP*_RxLOS SFPP*_SCL SFPP*_SDA SFPP*_TxFault}]
set_false_path -to [get_ports GPSDO_PWR_ENA]