diff options
Diffstat (limited to 'fpga/usrp3/top/x300/timing.xdc')
-rw-r--r-- | fpga/usrp3/top/x300/timing.xdc | 603 |
1 files changed, 603 insertions, 0 deletions
diff --git a/fpga/usrp3/top/x300/timing.xdc b/fpga/usrp3/top/x300/timing.xdc new file mode 100644 index 000000000..1b913456c --- /dev/null +++ b/fpga/usrp3/top/x300/timing.xdc @@ -0,0 +1,603 @@ +# +# 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 -hier -filter {NAME =~ */synchronizer_false_path/stages[0].value_reg[*]/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] |