@@ -13,62 +13,131 @@ set_clock_groups -asynchronous -group {fmc_clk_pin fmc_virt_clk} -group {clk_125
1313# FMC Interface
1414# #######################
1515
16+ # SP output a continuous clock here.
17+ # The FMC interface is clocked at 66.67MHz, which is a 15ns period.
1618# FPGA's input delays have to be low enough that they don't run into the uncertainty region due to any possible skew.
17- # skew_bre is the shortests trace delay vs the clock, and skew_are is the longest trace delay vs the clock.
18- # On grapefruit, clock trace is 61.195mm. shortest trace is FMC_SP_TO_FPGA_BL1_L at 60.504mm, longest is FMC_SP_TO_FPGA_BL0_L at 65.116mm
19- # 6.8ns per m so 61.195-60.504 = 0.691mm * 6.8ns/m = 0.0047ns skew_bre
20- # 65.116-61.195 = 3.921mm * 6.8ns/m = 0.0266ns skew_are
21-
22- # Also note that the SP changes outputs only on the *falling* edge of the fmc clock, which means there's a phase-shift
23-
24- # in delay max = tco_ext to max delay ext to fpga
25- # in delay min = minTco_ext to min delay ext to fpga
26- # chipsel example:
27- # Since data comes out on the falling edge, but we didn't shift the clock,
28- # we need to add an additional 1/2 period to the TCO_exts so
29- # max= 7.5ns (1/2 period) + 1ns (maxreal tco) + 0.0266ns max skew
30- # min= 7.5ns (1/2 period) + 0ns (min real tco) + 0.0047 min skew
31- set_input_delay -clock fmc_virt_clk -max 8.527 [get_ports fmc_sp_to_fpga1_cs_l]
32- set_input_delay -clock fmc_virt_clk -min 7.505 [get_ports fmc_sp_to_fpga1_cs_l]
33- set_input_delay -clock fmc_virt_clk -max 8.527 [get_ports fmc_sp_to_fpga1_we_l]
34- set_input_delay -clock fmc_virt_clk -min 7.505 [get_ports fmc_sp_to_fpga1_we_l]
35- set_input_delay -clock fmc_virt_clk -max 8.527 [get_ports fmc_sp_to_fpga1_oe_l]
36- set_input_delay -clock fmc_virt_clk -min 7.505 [get_ports fmc_sp_to_fpga1_oe_l]
37- set_input_delay -clock fmc_virt_clk -max 8.527 [get_ports fmc_sp_to_fpga1_adv_l]
38- set_input_delay -clock fmc_virt_clk -min 7.505 [get_ports fmc_sp_to_fpga1_adv_l]
39- set_input_delay -clock fmc_virt_clk -max 8.527 [get_ports fmc_sp_to_fpga1_bl_l]
40- set_input_delay -clock fmc_virt_clk -min 7.005 [get_ports fmc_sp_to_fpga1_bl_l]
41- # Address has diff relationship
42- # max= 7.5ns (1/2 period) + 2.5ns (maxreal tco) + 0.0266ns max skew
43- # min= 7.5ns (1/2 period) + 0ns (min real tco) + 0.0047ns max skew
44- set_input_delay -clock fmc_virt_clk -max 10.027 [get_ports fmc_sp_to_fpga1_a[*]]
45- set_input_delay -clock fmc_virt_clk -min 7.505 [get_ports fmc_sp_to_fpga1_a[*]]
46- # Data in has diff relationship
47- # max= 7.5ns (1/2 period) + 3ns (maxreal tco) + 0.0266ns max skew
48- # min= 7.5ns (1/2 period) + 0ns (min real tco) + 0.0047ns max skew
49- set_input_delay -clock fmc_virt_clk -max 10.527 [get_ports fmc_sp_to_fpga1_da[*]]
50- set_input_delay -clock fmc_virt_clk -min 7.505 [get_ports fmc_sp_to_fpga1_da[*]]
51-
52- # out delay max = ext setup + max delay fpga to external
53- # out delay min = ext hold + min delay fpga to external
54-
55- # max = 3ns (SP's needed setup time) + return delay (60.797mm)
56- # max = 3ns (SP's needed setup time) + 0.414 ns
57- # min = 1 ns (SP's needed hold time) + 0.414 ns
58- set_output_delay -clock fmc_virt_clk -max 3.414 [get_ports fmc_sp_to_fpga1_wait_l]
59- set_output_delay -clock fmc_virt_clk -min 1.414 [get_ports fmc_sp_to_fpga1_wait_l]
60-
61- # max = 3ns (SP's needed setup time) + clock delay to FPGA (61.195mm) + return delay (63.985mm)
62- # max = 3ns (SP's needed setup time) + 0.851 ns
63- # min = 0 ns (SP's needed hold time) + 0.851 ns
64- set_output_delay -clock fmc_virt_clk -max 3.851 [get_ports fmc_sp_to_fpga1_da[*]]
65- set_output_delay -clock fmc_virt_clk -min 0.830 [get_ports fmc_sp_to_fpga1_da[*]]
66-
19+ # skew_bre is the shortest trace delay vs the clock, and skew_are is the longest trace delay vs the clock.
20+ # On cosmo, clock trace is 60.787 rev1, 53.026mm rev2 .
21+ # shortest trace rev1 is FMC_SP_TO_FPGA1_A22 at 58.956, rev2 is FMC_SP_TO_FPGA1_DA14 at 52.54
22+ # longest trace rev1 (ignoring BL) is FMC_SP_TO_FPGA1_DA5 at 61.565, rev2 is FMC_SP_TO_FPGA1_A20 at 54.473
23+
24+ # Max clock delay to FPGA: 60.787mm * 6.8ns/m = 0.4134 ns (rev1 longest)
25+ set max_clock_delay 0.4134
26+ # Min clock delay to FPGA: 53.026mm * 6.8ns/m = 0.3602 ns (rev2 shortest)
27+ set min_clock_delay 0.3602
28+ # Max data delay between SP and FPGA: 61.565mm * 6.8ns/m = 0.4186 ns (rev1 longest)
29+ set max_data_delay 0.4186
30+ # Min data delay between SP and FPGA: 52.54mm * 6.8ns/m = 0.3573 ns (rev2 shortest)
31+ set min_data_delay 0.3573
32+ # Max wait delay between SP and FPGA: 60.787*6.8ns/m = 0.4134 ns (rev1 longest)
33+ set max_wait_delay 0.4134
34+ # Min wait delay between SP and FPGA: 53.467*6.8ns/m = 0.3635 ns (rev1 longest)
35+ set min_wait_delay 0.3635
36+
37+ # #################
38+ # Input constraints.
39+ # Effectively longest data delay, fastest clock arrival at FPGA.
40+ # input_max = clk_ext_delay_max + extTco_max + board_delay_max - fpga_clk_delay_min
41+ # Effectively shortest data delay, slowest clock arrival at FPGA.
42+ # input_min = clk_ext_delay_min + extTco_min + board_delay_min - fpga_clk_delay_max
43+
44+ # For the inputs data valid before rising edge can be calculated based on the SP's datasheet timings and trace delays.
45+ # td(CLKL-NExL) clock to out is max 1ns
46+ # td(CLKH_NExH) is min
47+ # td(CLKL-AV) 2.5ns
48+ # td(CLKH-AIV) 8ns?
49+ # td(CLKL-NOEL) 1.5ns
50+ # td(CLKH-NOEH) 7.5ns
51+ # td(CLKL-ADV) 3 ns
52+ # td(CLKL-ADIV) 0 ns
53+ # tsu(ADV-CLKH) 3 ns
54+ # th(CLKH-ADV) 0
55+ # tsu(NWAIT-CLKH) 3 ns (worst read timing)
56+ # th(CLKH-NWAIT) 2 ns (worst write timing)
57+
58+ # Source sync so external_clk_delay is 0.
59+ # Setup time is 1ns, and we include the 1/2 period due to SP shifting the data out on the falling edge.
60+ set sp_output_half_period 7.5
61+ set sp_0_hold 0
62+ set sp_clk_delay 0
63+
64+ # We have our 1/2 period of 7.5 ns due to SP outputting on falling edges, plus the td in the datasheet
65+ set td_clkl_nehl 1
66+ set nl_output_delay [expr {sp_output_half_period + td_clkl_nehl}]
67+ set max_nl expr [expr {$sp_clk_delay + $nl_output_delay + $max_data_delay - $min_clock_delay }]
68+ # latest clock, earliest data. We assume a hold time of 0 for the SP.
69+ # min external: fastest data, slowest clock
70+ set min_nl expr [expr {$sp_clk_delay + $sp_0_hold + $min_data_delay - $max_clock_delay }]\
71+
72+ # Apply to all of these pins with similar or better timing relationships.
73+ set_input_delay -clock fmc_virt_clk -max $max_nl [get_ports fmc_sp_to_fpga1_cs_l]
74+ set_input_delay -clock fmc_virt_clk -min $min_nl [get_ports fmc_sp_to_fpga1_cs_l]
75+ set_input_delay -clock fmc_virt_clk -max $max_nl [get_ports fmc_sp_to_fpga1_we_l]
76+ set_input_delay -clock fmc_virt_clk -min $min_nl [get_ports fmc_sp_to_fpga1_we_l]
77+ set_input_delay -clock fmc_virt_clk -max $max_nl [get_ports fmc_sp_to_fpga1_oe_l]
78+ set_input_delay -clock fmc_virt_clk -min $min_nl [get_ports fmc_sp_to_fpga1_oe_l]
79+ set_input_delay -clock fmc_virt_clk -max $max_nl [get_ports fmc_sp_to_fpga1_adv_l]
80+ set_input_delay -clock fmc_virt_clk -min $min_nl [get_ports fmc_sp_to_fpga1_adv_l]
81+ set_input_delay -clock fmc_virt_clk -max $max_nl [get_ports fmc_sp_to_fpga1_bl_l]
82+ set_input_delay -clock fmc_virt_clk -min $min_nl [get_ports fmc_sp_to_fpga1_bl_l]
83+
84+ # Address has diff relationship 2.5ns (max tco)
85+ set td_clkl_av 2.5
86+ set a_output_delay [expr {sp_output_half_period + td_clkl_av}]
87+ set max_a expr [expr {$sp_clk_delay + $a_output_delay + $max_data_delay - $min_clock_delay }]
88+ # Still 0 hold on these pins.
89+ set min_a expr [expr {$sp_clk_delay + $sp_0_hold + $min_data_delay - $max_clock_delay }]
90+ set_input_delay -clock fmc_virt_clk -max $max_a [get_ports fmc_sp_to_fpga1_a[*]]
91+ set_input_delay -clock fmc_virt_clk -min $min_a [get_ports fmc_sp_to_fpga1_a[*]]
92+
93+ # Data in has diff relationship 3ns (max tco)
94+ set td_clkl_adv 3
95+ set ad_output_delay [expr {sp_output_half_period + td_clkl_adv}]
96+ set max_ad expr [expr {$sp_clk_delay + $ad_output_delay + $max_data_delay - $min_clock_delay }]
97+ # Still 0 hold on these pins.
98+ set min_ad expr [expr {$sp_clk_delay + $sp_0_hold + $min_data_delay - $max_clock_delay }]
99+ set_input_delay -clock fmc_virt_clk -max $max_ad [get_ports fmc_sp_to_fpga1_da[*]]
100+ set_input_delay -clock fmc_virt_clk -min $min_ad [get_ports fmc_sp_to_fpga1_da[*]]
101+
102+ # ### END Of inputs
103+
104+ # #################
105+ # Output constraints.
106+ # Effectively need to meet setup time with longest FPGA data delay and fastest clock arrival at other device.
107+ # output_max = fpga_clk_delay_max + board_delay_max + extTsu - ext_clk_delay_min
108+ # Effectively need to meet hold time with shortest FPGA data delay and slowest clock arrival at other device.
109+ # input_min = fpga_clk_delay_min + board_delay_min - extTh - ext_clk_delay_max
110+
111+ # Ext setup time is 3ns
112+ set tsu_nwait_clkh 3
113+ # SP rising edge samples so 0 clock delay at external device.
114+ set max_wait expr [expr {$tsu_nwait_clkh + $max_wait_delay + $max_clock_delay - $sp_clk_delay }]
115+ # Ext hold time is 2ns, still 0 clock delay at external device.
116+ set th_clkh_nwait 2
117+ set min_wait expr [expr {$min_clock_delay + $min_wait_delay - $th_clkh_nwait - $sp_clk_delay }]
118+ set_output_delay -clock fmc_virt_clk -max max_wait [get_ports fmc_sp_to_fpga1_wait_l]
119+ set_output_delay -clock fmc_virt_clk -min min_wait [get_ports fmc_sp_to_fpga1_wait_l]
120+
121+ # Ext setup time is 3ns
122+ set tsu_adv_clkh 3
123+ # Ext hold time is 0ns
124+ set th_clkh_adv 0
125+ # Still 0 clk delay at external device
126+ set max_da expr [expr {$tsu_adv_clkh + $max_data_delay + $max_clock_delay - $sp_clk_delay }]
127+ set min_da expr [expr {$min_data_delay - $th_clkh_adv + $min_clock_delay - $sp_clk_delay }]
128+ set_output_delay -clock fmc_virt_clk -max $max_da [get_ports fmc_sp_to_fpga1_da[*]]
129+ set_output_delay -clock fmc_virt_clk -min $min_da [get_ports fmc_sp_to_fpga1_da[*]]
130+
131+
132+ # assuming wait_l works, we have multiple cycles to get the data out. This is likely needed due to the tri-state stuff here
133+ # and it has trouble meeting timing without the additional cycles. The fpga design compensates for this with wait_l.
67134set_multicycle_path -from [get_pins {stm32h7_fmc_target_inst/data_out*/C}] -to [get_ports {fmc_sp_to_fpga1_da[*]}] -setup 2
68135set_multicycle_path -from [get_pins {stm32h7_fmc_target_inst/data_out*/C}] -to [get_ports {fmc_sp_to_fpga1_da[*]}] -hold 1
69136set_multicycle_path -from [get_pins {stm32h7_fmc_target_inst/data_out_en_reg*/C}] -to [get_ports {fmc_sp_to_fpga1_da[*]}] -setup 2
70137set_multicycle_path -from [get_pins {stm32h7_fmc_target_inst/data_out_en_reg*/C}] -to [get_ports {fmc_sp_to_fpga1_da[*]}] -hold 1
71138
139+ # End FMC
140+
72141set_false_path -from [get_nets *] -to [get_ports {fpga1_spare_v3p3*}]
73142set_false_path -from [get_nets *] -to [get_ports {fpga1_spare_v1p8[*]}]
74143
0 commit comments