1 |
32 |
redbear |
# (C) 2001-2017 Intel Corporation. All rights reserved.
|
2 |
|
|
# Your use of Intel Corporation's design tools, logic functions and other
|
3 |
|
|
# software and tools, and its AMPP partner logic functions, and any output
|
4 |
40 |
redbear |
# files from any of the foregoing (including device programming or simulation
|
5 |
32 |
redbear |
# files), and any associated documentation or information are expressly subject
|
6 |
|
|
# to the terms and conditions of the Intel Program License Subscription
|
7 |
40 |
redbear |
# Agreement, Intel FPGA IP License Agreement, or other applicable
|
8 |
32 |
redbear |
# license agreement, including, without limitation, that your use is for the
|
9 |
|
|
# sole purpose of programming logic devices manufactured by Intel and sold by
|
10 |
|
|
# Intel or its authorized distributors. Please refer to the applicable
|
11 |
|
|
# agreement for further details.
|
12 |
|
|
|
13 |
|
|
|
14 |
|
|
#####################################################################
|
15 |
|
|
#
|
16 |
|
|
# THIS IS AN AUTO-GENERATED FILE!
|
17 |
|
|
# -------------------------------
|
18 |
|
|
# If you modify this files, all your changes will be lost if you
|
19 |
|
|
# regenerate the core!
|
20 |
|
|
#
|
21 |
|
|
# FILE DESCRIPTION
|
22 |
|
|
# ----------------
|
23 |
|
|
# This file contains the timing constraints for the UniPHY memory
|
24 |
|
|
# interface.
|
25 |
|
|
# * The timing parameters used by this file are assigned
|
26 |
|
|
# in the hps_sdram_p0_timing.tcl script.
|
27 |
|
|
# * The helper routines are defined in hps_sdram_p0_pin_map.tcl
|
28 |
|
|
#
|
29 |
|
|
# NOTE
|
30 |
|
|
# ----
|
31 |
|
|
|
32 |
|
|
set script_dir [file dirname [info script]]
|
33 |
|
|
|
34 |
|
|
source "$script_dir/hps_sdram_p0_parameters.tcl"
|
35 |
|
|
source "$script_dir/hps_sdram_p0_timing.tcl"
|
36 |
|
|
source "$script_dir/hps_sdram_p0_pin_map.tcl"
|
37 |
|
|
|
38 |
|
|
load_package ddr_timing_model
|
39 |
|
|
|
40 |
|
|
set synthesis_flow 0
|
41 |
|
|
set sta_flow 0
|
42 |
|
|
set fit_flow 0
|
43 |
|
|
if { $::TimeQuestInfo(nameofexecutable) == "quartus_map" } {
|
44 |
|
|
set synthesis_flow 1
|
45 |
|
|
} elseif { $::TimeQuestInfo(nameofexecutable) == "quartus_sta" } {
|
46 |
|
|
set sta_flow 1
|
47 |
|
|
} elseif { $::TimeQuestInfo(nameofexecutable) == "quartus_fit" } {
|
48 |
|
|
set fit_flow 1
|
49 |
|
|
}
|
50 |
|
|
|
51 |
|
|
####################
|
52 |
|
|
# #
|
53 |
|
|
# GENERAL SETTINGS #
|
54 |
|
|
# #
|
55 |
|
|
####################
|
56 |
|
|
|
57 |
|
|
# This is a global setting and will apply to the whole design.
|
58 |
|
|
# This setting is required for the memory interface to be
|
59 |
|
|
# properly constrained.
|
60 |
|
|
derive_clock_uncertainty
|
61 |
|
|
|
62 |
|
|
# Debug switch. Change to 1 to get more run-time debug information
|
63 |
|
|
set debug 0
|
64 |
|
|
|
65 |
|
|
# All timing requirements will be represented in nanoseconds with up to 3 decimal places of precision
|
66 |
|
|
set_time_format -unit ns -decimal_places 3
|
67 |
|
|
|
68 |
|
|
# Determine if entity names are on
|
69 |
|
|
set entity_names_on [ hps_sdram_p0_are_entity_names_on ]
|
70 |
|
|
|
71 |
|
|
##################
|
72 |
|
|
# #
|
73 |
|
|
# QUERIED TIMING #
|
74 |
|
|
# #
|
75 |
|
|
##################
|
76 |
|
|
|
77 |
|
|
set io_standard "DIFFERENTIAL 1.5-V SSTL CLASS I"
|
78 |
|
|
|
79 |
|
|
# This is the peak-to-peak jitter on the whole read capture path
|
80 |
|
|
set DQSpathjitter [expr [get_micro_node_delay -micro DQDQS_JITTER -parameters [list IO] -in_fitter]/1000.0]
|
81 |
|
|
|
82 |
|
|
# This is the proportion of the DQ-DQS read capture path jitter that applies to setup
|
83 |
|
|
set DQSpathjitter_setup_prop [expr [get_micro_node_delay -micro DQDQS_JITTER_DIVISION -parameters [list IO] -in_fitter]/100.0]
|
84 |
|
|
|
85 |
|
|
# This is the peak-to-peak jitter, of which half is considered to be tJITper
|
86 |
|
|
set tJITper [expr [get_micro_node_delay -micro MEM_CK_PERIOD_JITTER -parameters [list IO PHY_SHORT] -in_fitter -period $t(CK)]/2000.0 + $SSN(pullin_o)]
|
87 |
|
|
|
88 |
|
|
##################
|
89 |
|
|
# #
|
90 |
|
|
# DERIVED TIMING #
|
91 |
|
|
# #
|
92 |
|
|
##################
|
93 |
|
|
|
94 |
|
|
# These parameters are used to make constraints more readeable
|
95 |
|
|
|
96 |
|
|
# Half of memory clock cycle
|
97 |
|
|
set half_period [ hps_sdram_p0_round_3dp [ expr $t(CK) / 2.0 ] ]
|
98 |
|
|
|
99 |
|
|
# Half of reference clock
|
100 |
|
|
set ref_half_period [ hps_sdram_p0_round_3dp [ expr $t(refCK) / 2.0 ] ]
|
101 |
|
|
|
102 |
|
|
# Minimum delay on data output pins
|
103 |
|
|
set t(wru_output_min_delay_external) [expr $t(DH) + $board(intra_DQS_group_skew) + $ISI(DQ)/2 + $ISI(DQS)/2 - $board(DQ_DQS_skew)]
|
104 |
|
|
set t(wru_output_min_delay_internal) [expr $t(WL_DCD) + $t(WL_JITTER)*(1.0-$t(WL_JITTER_DIVISION)) + $SSN(rel_pullin_o)]
|
105 |
|
|
set data_output_min_delay [ hps_sdram_p0_round_3dp [ expr - $t(wru_output_min_delay_external) - $t(wru_output_min_delay_internal)]]
|
106 |
|
|
|
107 |
|
|
# Maximum delay on data output pins
|
108 |
|
|
set t(wru_output_max_delay_external) [expr $t(DS) + $board(intra_DQS_group_skew) + $ISI(DQ)/2 + $ISI(DQS)/2 + $board(DQ_DQS_skew)]
|
109 |
|
|
set t(wru_output_max_delay_internal) [expr $t(WL_DCD) + $t(WL_JITTER)*$t(WL_JITTER_DIVISION) + $SSN(rel_pushout_o)]
|
110 |
|
|
set data_output_max_delay [ hps_sdram_p0_round_3dp [ expr $t(wru_output_max_delay_external) + $t(wru_output_max_delay_internal)]]
|
111 |
|
|
|
112 |
|
|
# Maximum delay on data input pins
|
113 |
|
|
set t(rdu_input_max_delay_external) [expr $t(DQSQ) + $board(intra_DQS_group_skew) + $board(DQ_DQS_skew) + $ISI(READ_DQ)/2 + $ISI(READ_DQS)/2]
|
114 |
|
|
set t(rdu_input_max_delay_internal) [expr $DQSpathjitter*$DQSpathjitter_setup_prop + $SSN(rel_pushout_i)]
|
115 |
|
|
set data_input_max_delay [ hps_sdram_p0_round_3dp [ expr $t(rdu_input_max_delay_external) + $t(rdu_input_max_delay_internal) ]]
|
116 |
|
|
|
117 |
|
|
# Minimum delay on data input pins
|
118 |
|
|
set t(rdu_input_min_delay_external) [expr $board(intra_DQS_group_skew) - $board(DQ_DQS_skew) + $ISI(READ_DQ)/2 + $ISI(READ_DQS)/2]
|
119 |
|
|
set t(rdu_input_min_delay_internal) [expr $t(DCD) + $DQSpathjitter*(1.0-$DQSpathjitter_setup_prop) + $SSN(rel_pullin_i)]
|
120 |
|
|
set data_input_min_delay [ hps_sdram_p0_round_3dp [ expr - $t(rdu_input_min_delay_external) - $t(rdu_input_min_delay_internal) ]]
|
121 |
|
|
|
122 |
|
|
# Minimum delay on address and command paths
|
123 |
|
|
set ac_min_delay [ hps_sdram_p0_round_3dp [ expr - $t(IH) -$fpga(tPLL_JITTER) - $fpga(tPLL_PSERR) - $board(intra_addr_ctrl_skew) + $board(addresscmd_CK_skew) - $ISI(addresscmd_hold) ]]
|
124 |
|
|
|
125 |
|
|
# Maximum delay on address and command paths
|
126 |
|
|
set ac_max_delay [ hps_sdram_p0_round_3dp [ expr $t(IS) +$fpga(tPLL_JITTER) + $fpga(tPLL_PSERR) + $board(intra_addr_ctrl_skew) + $board(addresscmd_CK_skew) + $ISI(addresscmd_setup) ]]
|
127 |
|
|
|
128 |
|
|
if { $debug } {
|
129 |
|
|
post_message -type info "SDC: Computed Parameters:"
|
130 |
|
|
post_message -type info "SDC: --------------------"
|
131 |
|
|
post_message -type info "SDC: half_period: $half_period"
|
132 |
|
|
post_message -type info "SDC: data_output_min_delay: $data_output_min_delay"
|
133 |
|
|
post_message -type info "SDC: data_output_max_delay: $data_output_max_delay"
|
134 |
|
|
post_message -type info "SDC: data_input_min_delay: $data_input_min_delay"
|
135 |
|
|
post_message -type info "SDC: data_input_max_delay: $data_input_max_delay"
|
136 |
|
|
post_message -type info "SDC: ac_min_delay: $ac_min_delay"
|
137 |
|
|
post_message -type info "SDC: ac_max_delay: $ac_max_delay"
|
138 |
|
|
post_message -type info "SDC: Using Timing Models: Micro"
|
139 |
|
|
}
|
140 |
|
|
|
141 |
|
|
# This is the main call to the netlist traversal routines
|
142 |
|
|
# that will automatically find all pins and registers required
|
143 |
|
|
# to apply timing constraints.
|
144 |
|
|
# During the fitter, the routines will be called only once
|
145 |
|
|
# and cached data will be used in all subsequent calls.
|
146 |
|
|
if { ! [ info exists hps_sdram_p0_sdc_cache ] } {
|
147 |
|
|
set hps_sdram_p0_sdc_cache 1
|
148 |
|
|
hps_sdram_p0_initialize_ddr_db hps_sdram_p0_ddr_db
|
149 |
|
|
} else {
|
150 |
|
|
if { $debug } {
|
151 |
|
|
post_message -type info "SDC: reusing cached DDR DB"
|
152 |
|
|
}
|
153 |
|
|
}
|
154 |
|
|
|
155 |
|
|
# If multiple instances of this core are present in the
|
156 |
|
|
# design they will all be constrained through the
|
157 |
|
|
# following loop
|
158 |
|
|
set instances [ array names hps_sdram_p0_ddr_db ]
|
159 |
|
|
foreach { inst } $instances {
|
160 |
|
|
if { [ info exists pins ] } {
|
161 |
|
|
# Clean-up stale content
|
162 |
|
|
unset pins
|
163 |
|
|
}
|
164 |
|
|
array set pins $hps_sdram_p0_ddr_db($inst)
|
165 |
|
|
|
166 |
|
|
set prefix $inst
|
167 |
|
|
if { $entity_names_on } {
|
168 |
|
|
set prefix [ string map "| |*:" $inst ]
|
169 |
|
|
set prefix "*:$prefix"
|
170 |
|
|
}
|
171 |
|
|
|
172 |
|
|
#####################################################
|
173 |
|
|
# #
|
174 |
|
|
# Transfer the pin names to more readable variables #
|
175 |
|
|
# #
|
176 |
|
|
#####################################################
|
177 |
|
|
|
178 |
|
|
set dqs_pins $pins(dqs_pins)
|
179 |
|
|
set dqsn_pins $pins(dqsn_pins)
|
180 |
|
|
set q_groups [ list ]
|
181 |
|
|
foreach { q_group } $pins(q_groups) {
|
182 |
|
|
set q_group $q_group
|
183 |
|
|
lappend q_groups $q_group
|
184 |
|
|
}
|
185 |
|
|
set all_dq_pins [ join [ join $q_groups ] ]
|
186 |
|
|
|
187 |
|
|
set ck_pins $pins(ck_pins)
|
188 |
|
|
set ckn_pins $pins(ckn_pins)
|
189 |
|
|
set add_pins $pins(add_pins)
|
190 |
|
|
set ba_pins $pins(ba_pins)
|
191 |
|
|
set cmd_pins $pins(cmd_pins)
|
192 |
|
|
set reset_pins $pins(reset_pins)
|
193 |
|
|
set ac_pins [ concat $add_pins $ba_pins $cmd_pins ]
|
194 |
|
|
set dm_pins $pins(dm_pins)
|
195 |
|
|
set all_dq_dm_pins [ concat $all_dq_pins $dm_pins ]
|
196 |
|
|
|
197 |
|
|
set pll_ref_clock "pll_ref_clock"
|
198 |
|
|
set pll_dq_write_clock $pins(pll_dq_write_clock)
|
199 |
|
|
set pll_ck_clock $pins(pll_ck_clock)
|
200 |
|
|
set pll_write_clock $pins(pll_write_clock)
|
201 |
|
|
set pll_driver_core_clock $pins(pll_driver_core_clock)
|
202 |
|
|
|
203 |
|
|
set dqs_in_clocks $pins(dqs_in_clocks)
|
204 |
|
|
set dqs_out_clocks $pins(dqs_out_clocks)
|
205 |
|
|
set dqsn_out_clocks $pins(dqsn_out_clocks)
|
206 |
|
|
|
207 |
|
|
set afi_reset_reg $pins(afi_reset_reg)
|
208 |
|
|
set sync_reg $pins(sync_reg)
|
209 |
|
|
set read_capture_ddio $pins(read_capture_ddio)
|
210 |
|
|
set fifo_wraddress_reg $pins(fifo_wraddress_reg)
|
211 |
|
|
set fifo_rdaddress_reg $pins(fifo_rdaddress_reg)
|
212 |
|
|
set fifo_wrdata_reg $pins(fifo_wrdata_reg)
|
213 |
|
|
set fifo_rddata_reg $pins(fifo_rddata_reg)
|
214 |
|
|
|
215 |
|
|
##################
|
216 |
|
|
# #
|
217 |
|
|
# QUERIED TIMING #
|
218 |
|
|
# #
|
219 |
|
|
##################
|
220 |
|
|
|
221 |
|
|
# Phase Jitter on DQS paths. This parameter is queried at run time
|
222 |
|
|
set fpga(tDQS_PHASE_JITTER) [ expr [ get_integer_node_delay -integer $::GLOBAL_hps_sdram_p0_dqs_delay_chain_length -parameters {IO MAX HIGH} -src DQS_PHASE_JITTER -in_fitter ] / 1000.0 ]
|
223 |
|
|
|
224 |
|
|
# Phase Error on DQS paths. This parameter is queried at run time
|
225 |
|
|
set fpga(tDQS_PSERR) [ expr [ get_integer_node_delay -integer $::GLOBAL_hps_sdram_p0_dqs_delay_chain_length -parameters {IO MAX HIGH} -src DQS_PSERR -in_fitter ] / 1000.0 ]
|
226 |
|
|
|
227 |
|
|
# Correct input min/max delay for queried parameters
|
228 |
|
|
set t(rdu_input_min_delay_external) [expr $t(rdu_input_min_delay_external) + ($t(CK)/2.0 - $t(QH_time))]
|
229 |
|
|
set t(rdu_input_min_delay_internal) [expr $t(rdu_input_min_delay_internal) + $fpga(tDQS_PSERR) + $tJITper]
|
230 |
|
|
set t(rdu_input_max_delay_external) [expr $t(rdu_input_max_delay_external)]
|
231 |
|
|
set t(rdu_input_max_delay_internal) [expr $t(rdu_input_max_delay_internal) + $fpga(tDQS_PSERR)]
|
232 |
|
|
|
233 |
|
|
set final_data_input_max_delay [ hps_sdram_p0_round_3dp [ expr $data_input_max_delay + $fpga(tDQS_PSERR) ]]
|
234 |
|
|
set final_data_input_min_delay [ hps_sdram_p0_round_3dp [ expr $data_input_min_delay - $t(CK) / 2.0 + $t(QH_time) - $fpga(tDQS_PSERR) - $tJITper]]
|
235 |
|
|
|
236 |
|
|
if { $debug } {
|
237 |
|
|
post_message -type info "SDC: Jitter Parameters"
|
238 |
|
|
post_message -type info "SDC: -----------------"
|
239 |
|
|
post_message -type info "SDC: DQS Phase: $::GLOBAL_hps_sdram_p0_dqs_delay_chain_length"
|
240 |
|
|
post_message -type info "SDC: fpga(tDQS_PHASE_JITTER): $fpga(tDQS_PHASE_JITTER)"
|
241 |
|
|
post_message -type info "SDC: fpga(tDQS_PSERR): $fpga(tDQS_PSERR)"
|
242 |
|
|
post_message -type info "SDC: t(QH_time): $t(QH_time)"
|
243 |
|
|
post_message -type info "SDC:"
|
244 |
|
|
post_message -type info "SDC: Derived Parameters:"
|
245 |
|
|
post_message -type info "SDC: -----------------"
|
246 |
|
|
post_message -type info "SDC: Corrected data_input_max_delay: $final_data_input_max_delay"
|
247 |
|
|
post_message -type info "SDC: Corrected data_input_min_delay: $final_data_input_min_delay"
|
248 |
|
|
post_message -type info "SDC: -----------------"
|
249 |
|
|
}
|
250 |
|
|
|
251 |
|
|
# ----------------------- #
|
252 |
|
|
# - - #
|
253 |
|
|
# --- REFERENCE CLOCK --- #
|
254 |
|
|
# - - #
|
255 |
|
|
# ----------------------- #
|
256 |
|
|
|
257 |
|
|
# This is the reference clock used by the PLL to derive any other clock in the core
|
258 |
|
|
if { [get_collection_size [get_clocks -nowarn $pll_ref_clock]] > 0 } { remove_clock $pll_ref_clock }
|
259 |
|
|
|
260 |
|
|
# ------------------ #
|
261 |
|
|
# - - #
|
262 |
|
|
# --- PLL CLOCKS --- #
|
263 |
|
|
# - - #
|
264 |
|
|
# ------------------ #
|
265 |
|
|
|
266 |
|
|
|
267 |
|
|
|
268 |
|
|
|
269 |
|
|
# DQ write clock
|
270 |
|
|
set local_pll_dq_write_clk [ hps_sdram_p0_get_or_add_clock_vseries_from_virtual_refclk \
|
271 |
|
|
-target $pll_dq_write_clock \
|
272 |
|
|
-suffix "dq_write_clk" \
|
273 |
|
|
-period $t(CK) \
|
274 |
|
|
-phase $::GLOBAL_hps_sdram_p0_pll_phase(PLL_WRITE_CLK) ]
|
275 |
|
|
|
276 |
|
|
# DQS write clock
|
277 |
|
|
set local_pll_write_clk [ hps_sdram_p0_get_or_add_clock_vseries_from_virtual_refclk \
|
278 |
|
|
-target $pll_write_clock \
|
279 |
|
|
-suffix "write_clk" \
|
280 |
|
|
-period $t(CK) \
|
281 |
|
|
-phase $::GLOBAL_hps_sdram_p0_pll_phase(PLL_MEM_CLK) ]
|
282 |
|
|
|
283 |
|
|
|
284 |
|
|
|
285 |
|
|
|
286 |
|
|
|
287 |
|
|
|
288 |
|
|
|
289 |
|
|
# Pulse-generator used by DQS tracking
|
290 |
|
|
set local_sampling_clock "${inst}|hps_sdram_p0_sampling_clock"
|
291 |
|
|
|
292 |
|
|
if {[get_collection_size [get_registers -nowarn $pins(dqs_enable_regs_pins)]] > 0} {
|
293 |
|
|
create_generated_clock \
|
294 |
|
|
-add \
|
295 |
|
|
-name $local_sampling_clock \
|
296 |
|
|
-source $pll_write_clock \
|
297 |
|
|
-multiply_by 1 \
|
298 |
|
|
-divide_by 1 \
|
299 |
|
|
-phase 0 \
|
300 |
|
|
$pins(dqs_enable_regs_pins)
|
301 |
|
|
}
|
302 |
|
|
|
303 |
|
|
# If this is the example design, then we need to find the PLL output which is used in the core by the driver and MPFE ports.
|
304 |
|
|
# The node name is known; check to see if it exists (implying the example design) before creating the clock.
|
305 |
|
|
if {[string compare -nocase $pll_driver_core_clock "_UNDEFINED_PIN_"] != 0} {
|
306 |
|
|
set local_pll_driver_core_clk [ hps_sdram_p0_get_or_add_clock_vseries \
|
307 |
|
|
-target $pll_driver_core_clock \
|
308 |
|
|
-suffix "driver_core_clk" \
|
309 |
|
|
-source $pll_ref_clock \
|
310 |
|
|
-multiply_by 1 \
|
311 |
|
|
-divide_by 1 \
|
312 |
|
|
-phase 0 ]
|
313 |
|
|
}
|
314 |
|
|
|
315 |
|
|
|
316 |
|
|
# -------------------- #
|
317 |
|
|
# - - #
|
318 |
|
|
# --- SYSTEM CLOCK --- #
|
319 |
|
|
# - - #
|
320 |
|
|
# -------------------- #
|
321 |
|
|
|
322 |
|
|
# This is the CK clock
|
323 |
|
|
foreach { ck_pin } $ck_pins {
|
324 |
|
|
create_generated_clock -multiply_by 1 -source $pll_write_clock -master_clock "$local_pll_write_clk" $ck_pin -name $ck_pin
|
325 |
|
|
set_clock_uncertainty -to [ get_clocks $ck_pin ] $t(WL_JITTER)
|
326 |
|
|
}
|
327 |
|
|
|
328 |
|
|
# This is the CK#clock
|
329 |
|
|
foreach { ckn_pin } $ckn_pins {
|
330 |
|
|
create_generated_clock -multiply_by 1 -invert -source $pll_write_clock -master_clock "$local_pll_write_clk" $ckn_pin -name $ckn_pin
|
331 |
|
|
set_clock_uncertainty -to [ get_clocks $ckn_pin ] $t(WL_JITTER)
|
332 |
|
|
}
|
333 |
|
|
|
334 |
|
|
# ------------------- #
|
335 |
|
|
# - - #
|
336 |
|
|
# --- READ CLOCKS --- #
|
337 |
|
|
# - - #
|
338 |
|
|
# ------------------- #
|
339 |
|
|
|
340 |
|
|
foreach dqs_in_clock_struct $dqs_in_clocks {
|
341 |
|
|
array set dqs_in_clock $dqs_in_clock_struct
|
342 |
|
|
# This is the DQS clock for Read Capture analysis (micro model)
|
343 |
|
|
create_clock -period $t(CK) -waveform [ list 0 $half_period ] $dqs_in_clock(dqs_pin) -name $dqs_in_clock(dqs_pin)_IN -add
|
344 |
|
|
|
345 |
|
|
# Clock Uncertainty is accounted for by the ...pathjitter parameters
|
346 |
|
|
set_clock_uncertainty -from [ get_clocks $dqs_in_clock(dqs_pin)_IN ] 0
|
347 |
|
|
}
|
348 |
|
|
|
349 |
|
|
# -------------------- #
|
350 |
|
|
# - - #
|
351 |
|
|
# --- WRITE CLOCKS --- #
|
352 |
|
|
# - - #
|
353 |
|
|
# -------------------- #
|
354 |
|
|
|
355 |
|
|
# This is the DQS clock for Data Write analysis (micro model)
|
356 |
|
|
foreach dqs_out_clock_struct $dqs_out_clocks {
|
357 |
|
|
array set dqs_out_clock $dqs_out_clock_struct
|
358 |
|
|
create_generated_clock -multiply_by 1 -master_clock [get_clocks $local_pll_write_clk] -source $pll_write_clock $dqs_out_clock(dst) -name $dqs_out_clock(dst)_OUT -add
|
359 |
|
|
|
360 |
|
|
# Clock Uncertainty is accounted for by the ...pathjitter parameters
|
361 |
|
|
set_clock_uncertainty -to [ get_clocks $dqs_out_clock(dst)_OUT ] 0
|
362 |
|
|
}
|
363 |
|
|
|
364 |
|
|
# This is the DQS#clock for Data Write analysis (micro model)
|
365 |
|
|
foreach dqsn_out_clock_struct $dqsn_out_clocks {
|
366 |
|
|
array set dqsn_out_clock $dqsn_out_clock_struct
|
367 |
|
|
create_generated_clock -multiply_by 1 -master_clock [get_clocks $local_pll_write_clk] -source $pll_write_clock $dqsn_out_clock(dst) -name $dqsn_out_clock(dst)_OUT -add
|
368 |
|
|
|
369 |
|
|
# Clock Uncertainty is accounted for by the ...pathjitter parameters
|
370 |
|
|
set_clock_uncertainty -to [ get_clocks $dqsn_out_clock(dst)_OUT ] 0
|
371 |
|
|
}
|
372 |
|
|
|
373 |
|
|
##################
|
374 |
|
|
# #
|
375 |
|
|
# READ DATA PATH #
|
376 |
|
|
# #
|
377 |
|
|
##################
|
378 |
|
|
|
379 |
|
|
foreach { dqs_pin } $dqs_pins { dq_pins } $q_groups {
|
380 |
|
|
foreach { dq_pin } $dq_pins {
|
381 |
|
|
if {[get_collection_size [get_registers -nowarn $read_capture_ddio]] > 0} {
|
382 |
|
|
set_max_delay -from [get_ports $dq_pin] -to $read_capture_ddio 0
|
383 |
|
|
set_min_delay -from [get_ports $dq_pin] -to $read_capture_ddio [expr 0-$half_period]
|
384 |
|
|
}
|
385 |
|
|
|
386 |
|
|
# Specifies the maximum delay difference between the DQ pin and the DQS pin:
|
387 |
|
|
set_input_delay -max $final_data_input_max_delay -clock [get_clocks ${dqs_pin}_IN ] [get_ports $dq_pin] -add_delay
|
388 |
|
|
|
389 |
|
|
# Specifies the minimum delay difference between the DQ pin and the DQS pin:
|
390 |
|
|
set_input_delay -min $final_data_input_min_delay -clock [get_clocks ${dqs_pin}_IN ] [get_ports $dq_pin] -add_delay
|
391 |
|
|
}
|
392 |
|
|
}
|
393 |
|
|
|
394 |
|
|
###################
|
395 |
|
|
# #
|
396 |
|
|
# WRITE DATA PATH #
|
397 |
|
|
# #
|
398 |
|
|
###################
|
399 |
|
|
|
400 |
|
|
foreach { dqs_pin } $dqs_pins { dq_pins } $q_groups {
|
401 |
|
|
foreach { dq_pin } $dq_pins {
|
402 |
|
|
# Specifies the minimum delay difference between the DQS pin and the DQ pins:
|
403 |
|
|
set_output_delay -min $data_output_min_delay -clock [get_clocks ${dqs_pin}_OUT ] [get_ports $dq_pin] -add_delay
|
404 |
|
|
|
405 |
|
|
# Specifies the maximum delay difference between the DQS pin and the DQ pins:
|
406 |
|
|
set_output_delay -max $data_output_max_delay -clock [get_clocks ${dqs_pin}_OUT ] [get_ports $dq_pin] -add_delay
|
407 |
|
|
}
|
408 |
|
|
}
|
409 |
|
|
|
410 |
|
|
foreach { dqsn_pin } $dqsn_pins { dq_pins } $q_groups {
|
411 |
|
|
foreach { dq_pin } $dq_pins {
|
412 |
|
|
# Specifies the minimum delay difference between the DQS#pin and the DQ pins:
|
413 |
|
|
set_output_delay -min $data_output_min_delay -clock [get_clocks ${dqsn_pin}_OUT ] [get_ports $dq_pin] -add_delay
|
414 |
|
|
|
415 |
|
|
# Specifies the maximum delay difference between the DQS#pin and the DQ pins:
|
416 |
|
|
set_output_delay -max $data_output_max_delay -clock [get_clocks ${dqsn_pin}_OUT ] [get_ports $dq_pin] -add_delay
|
417 |
|
|
}
|
418 |
|
|
}
|
419 |
|
|
|
420 |
|
|
foreach dqs_out_clock_struct $dqs_out_clocks {
|
421 |
|
|
array set dqs_out_clock $dqs_out_clock_struct
|
422 |
|
|
|
423 |
|
|
if { [string length $dqs_out_clock(dm_pin)] > 0 } {
|
424 |
|
|
# Specifies the minimum delay difference between the DQS and the DM pins:
|
425 |
|
|
set_output_delay -min $data_output_min_delay -clock [get_clocks $dqs_out_clock(dst)_OUT ] [get_ports $dqs_out_clock(dm_pin)] -add_delay
|
426 |
|
|
|
427 |
|
|
# Specifies the maximum delay difference between the DQS and the DM pins:
|
428 |
|
|
set_output_delay -max $data_output_max_delay -clock [get_clocks $dqs_out_clock(dst)_OUT ] [get_ports $dqs_out_clock(dm_pin)] -add_delay
|
429 |
|
|
}
|
430 |
|
|
}
|
431 |
|
|
|
432 |
|
|
foreach dqsn_out_clock_struct $dqsn_out_clocks {
|
433 |
|
|
array set dqsn_out_clock $dqsn_out_clock_struct
|
434 |
|
|
|
435 |
|
|
if { [string length $dqsn_out_clock(dm_pin)] > 0 } {
|
436 |
|
|
# Specifies the minimum delay difference between the DQS and the DM pins:
|
437 |
|
|
set_output_delay -min $data_output_min_delay -clock [get_clocks $dqsn_out_clock(dst)_OUT ] [get_ports $dqsn_out_clock(dm_pin)] -add_delay
|
438 |
|
|
|
439 |
|
|
# Specifies the maximum delay difference between the DQS and the DM pins:
|
440 |
|
|
set_output_delay -max $data_output_max_delay -clock [get_clocks $dqsn_out_clock(dst)_OUT ] [get_ports $dqsn_out_clock(dm_pin)] -add_delay
|
441 |
|
|
}
|
442 |
|
|
}
|
443 |
|
|
|
444 |
|
|
##################
|
445 |
|
|
# #
|
446 |
|
|
# DQS vs CK PATH #
|
447 |
|
|
# #
|
448 |
|
|
##################
|
449 |
|
|
|
450 |
|
|
foreach { ck_pin } $ck_pins {
|
451 |
|
|
set_output_delay -add_delay -clock [get_clocks $ck_pin] -max [hps_sdram_p0_round_3dp [expr $t(CK) - $t(DQSS)*$t(CK) - $board(minCK_DQS_skew) ]] $dqs_pins
|
452 |
|
|
set_output_delay -add_delay -clock [get_clocks $ck_pin] -min [hps_sdram_p0_round_3dp [expr $t(DQSS)*$t(CK) - $board(maxCK_DQS_skew) ]] $dqs_pins
|
453 |
|
|
set_false_path -to [get_clocks $ck_pin] -fall_from [get_clocks $local_pll_write_clk ]
|
454 |
|
|
}
|
455 |
|
|
|
456 |
|
|
############
|
457 |
|
|
# #
|
458 |
|
|
# A/C PATH #
|
459 |
|
|
# #
|
460 |
|
|
############
|
461 |
|
|
|
462 |
|
|
foreach { ck_pin } $ck_pins {
|
463 |
|
|
# ac_pins can contain input ports such as mem_err_out_n
|
464 |
|
|
# Loop through each ac pin to make sure we only apply set_output_delay to output ports
|
465 |
|
|
foreach { ac_pin } $ac_pins {
|
466 |
|
|
set ac_port [ get_ports $ac_pin ]
|
467 |
|
|
if {[get_collection_size $ac_port] > 0} {
|
468 |
|
|
if [ get_port_info -is_output_port $ac_port ] {
|
469 |
|
|
# Specifies the minimum delay difference between the DQS pin and the address/control pins:
|
470 |
|
|
set_output_delay -min [hps_sdram_p0_round_3dp [expr {$ac_min_delay + $t(CK)/2}]] -clock [get_clocks $ck_pin] $ac_port -add_delay
|
471 |
|
|
|
472 |
|
|
# Specifies the maximum delay difference between the DQS pin and the address/control pins:
|
473 |
|
|
set_output_delay -max [hps_sdram_p0_round_3dp [expr {$ac_max_delay + $t(CK)/2}]] -clock [get_clocks $ck_pin] $ac_port -add_delay
|
474 |
|
|
}
|
475 |
|
|
}
|
476 |
|
|
}
|
477 |
|
|
}
|
478 |
|
|
|
479 |
|
|
# Only the rising edge-launched control data needs to be timing analyzed in full rate
|
480 |
|
|
set_false_path -fall_from [ get_clocks ${local_pll_write_clk} ] -to [ get_ports $ac_pins ]
|
481 |
|
|
|
482 |
|
|
##########################
|
483 |
|
|
# #
|
484 |
|
|
# MULTICYCLE CONSTRAINTS #
|
485 |
|
|
# #
|
486 |
|
|
##########################
|
487 |
|
|
|
488 |
|
|
|
489 |
|
|
# If powerdown feature is enabled, multicycle path from core logic to the CK generator.
|
490 |
|
|
# The PHY must be idle several cycles before entering and after exiting powerdown mode.
|
491 |
|
|
if { [get_collection_size [get_registers -nowarn ${prefix}|*p0|*umemphy|*uio_pads|*uaddr_cmd_pads|*clock_gen[*].umem_ck_pad|*]] > 0 } {
|
492 |
|
|
set_multicycle_path -to [get_registers ${prefix}|*p0|*umemphy|*uio_pads|*uaddr_cmd_pads|*clock_gen[*].umem_ck_pad|*] -end -setup 4
|
493 |
|
|
set_multicycle_path -to [get_registers ${prefix}|*p0|*umemphy|*uio_pads|*uaddr_cmd_pads|*clock_gen[*].umem_ck_pad|*] -end -hold 4
|
494 |
|
|
}
|
495 |
|
|
|
496 |
|
|
|
497 |
|
|
|
498 |
|
|
|
499 |
|
|
|
500 |
|
|
|
501 |
|
|
set read_fifo_read_dff ${prefix}|*p0|*altdq_dqs2_inst|*read_fifo~OUTPUT_DFF_*
|
502 |
|
|
set read_fifo_write_address_dff ${prefix}|*p0|*altdq_dqs2_inst|*read_fifo~WRITE_ADDRESS_DFF
|
503 |
|
|
set read_fifo_read_address_dff ${prefix}|*p0|*altdq_dqs2_inst|*read_fifo~READ_ADDRESS_DFF
|
504 |
|
|
set lfifo_in_read_en_dff ${prefix}|*p0|*lfifo~LFIFO_IN_READ_EN_DFF
|
505 |
|
|
set lfifo_in_read_en_full_dff ${prefix}|*p0|*lfifo~LFIFO_IN_READ_EN_FULL_DFF
|
506 |
|
|
set lfifo_dff_reg ${prefix}|*p0|*lfifo~LFIFO_OUT_OCT_LFIFO_DFF
|
507 |
|
|
set lfifo_out_rden_dff ${prefix}|*p0|*lfifo~LFIFO_OUT_RDEN_DFF
|
508 |
|
|
set lfifo_out_rdata_valid_dff ${prefix}|*p0|*lfifo~LFIFO_OUT_RDATA_VALID_DFF
|
509 |
|
|
set os_oct_ddio_oe_reg ${prefix}|*p0|*os_oct_ddio_oe~DFF
|
510 |
|
|
set lfifo_rd_latency_dff ${prefix}|*p0|*lfifo~RD_LATENCY_DFF*
|
511 |
|
|
set vfifo_qvld_in_dff ${prefix}|*p0|*altdq_dqs2_inst|vfifo~QVLD_IN_DFF
|
512 |
|
|
set vfifo_inc_wr_ptr_dff ${prefix}|*p0|*vfifo~INC_WR_PTR_DFF
|
513 |
|
|
set phase_align_dff ${prefix}|*p0|*altdq_dqs2_inst|phase_align_os~DFF*
|
514 |
|
|
set os_oe_reg ${prefix}|*p0|*os_oe_reg
|
515 |
|
|
set phase_align_dff ${prefix}|*p0|*phase_align_os~DFF*
|
516 |
|
|
set hphy_ff ${prefix}|*p0|*umemphy|hphy_inst~FF_*
|
517 |
|
|
set hmc_ff ${prefix}|*c0|hmc_inst~FF_*
|
518 |
|
|
set phy_read_latency_counter $hphy_ff
|
519 |
|
|
set read_fifo_reset $hphy_ff
|
520 |
|
|
set phy_reset_mem_stable $hphy_ff
|
521 |
|
|
|
522 |
|
|
set after_u2b 0
|
523 |
|
|
if {[get_collection_size [get_registers -nowarn $read_fifo_write_address_dff]] > 0} {
|
524 |
|
|
set after_u2b 1
|
525 |
|
|
}
|
526 |
|
|
|
527 |
|
|
if {$after_u2b} {
|
528 |
|
|
|
529 |
|
|
set_multicycle_path -from $hphy_ff -to $lfifo_in_read_en_full_dff -end -setup 2
|
530 |
|
|
set_multicycle_path -from $hphy_ff -to $lfifo_in_read_en_full_dff -end -hold 1
|
531 |
|
|
|
532 |
|
|
set_multicycle_path -from $read_fifo_reset -to $read_fifo_read_address_dff -end -setup 2
|
533 |
|
|
set_multicycle_path -from $read_fifo_reset -to $read_fifo_read_address_dff -end -hold 1
|
534 |
|
|
|
535 |
|
|
|
536 |
|
|
set_false_path -from $hmc_ff -to ${prefix}|*p0|*umemphy|*uio_pads|*uaddr_cmd_pads|*ddio_out*
|
537 |
|
|
set_false_path -from $hphy_ff -to $lfifo_in_read_en_dff
|
538 |
|
|
set_false_path -from $hmc_ff -to $lfifo_in_read_en_dff
|
539 |
|
|
set_false_path -from $hphy_ff -to $vfifo_inc_wr_ptr_dff
|
540 |
|
|
set_false_path -from $hmc_ff -to $vfifo_qvld_in_dff
|
541 |
|
|
set_false_path -from $lfifo_out_rdata_valid_dff -to $hphy_ff
|
542 |
|
|
set_false_path -from $phy_reset_mem_stable -to $vfifo_qvld_in_dff
|
543 |
|
|
set_false_path -from $phy_read_latency_counter -to $lfifo_rd_latency_dff
|
544 |
|
|
set_false_path -from $hphy_ff -to ${prefix}|*p0|*umemphy|*uio_pads|*uaddr_cmd_pads|*ddio_out*
|
545 |
|
|
set_false_path -from $hphy_ff -to ${prefix}|*p0|*umemphy|*altdq_dqs2_inst|*output_path_gen[*].ddio_out*
|
546 |
|
|
set_false_path -from $hphy_ff -to ${prefix}|*p0|*umemphy|*altdq_dqs2_inst|extra_output_pad_gen[*].ddio_out*
|
547 |
|
|
set_false_path -from $hphy_ff -to $hphy_ff
|
548 |
|
|
set_false_path -from $hmc_ff -to $hphy_ff
|
549 |
|
|
set_false_path -from $hphy_ff -to $hmc_ff
|
550 |
|
|
set_false_path -from $hphy_ff -to $phase_align_dff
|
551 |
|
|
set_false_path -from ${prefix}|*s0|* -to [get_clocks $local_pll_write_clk]
|
552 |
|
|
set_false_path -from [get_clocks $local_pll_write_clk] -to ${prefix}|*s0|*hphy_bridge_s0_translator|av_readdata_pre[*]
|
553 |
|
|
|
554 |
|
|
set_false_path -from $read_fifo_read_dff -to $hphy_ff
|
555 |
|
|
|
556 |
|
|
}
|
557 |
|
|
|
558 |
|
|
# Sampling register to AVL clock is multicycled because of topology of the PHY
|
559 |
|
|
if {[get_collection_size [get_registers -nowarn $pins(dqs_enable_regs_pins)]] > 0} {
|
560 |
|
|
set_multicycle_path -from [get_clocks $local_sampling_clock] -setup 2
|
561 |
|
|
set_multicycle_path -from [get_clocks $local_sampling_clock] -hold 2
|
562 |
|
|
}
|
563 |
|
|
|
564 |
|
|
|
565 |
|
|
##########################
|
566 |
|
|
# #
|
567 |
|
|
# FALSE PATH CONSTRAINTS #
|
568 |
|
|
# #
|
569 |
|
|
##########################
|
570 |
|
|
|
571 |
|
|
# Cut paths for memory clocks / async resets to avoid unconstrained warnings
|
572 |
|
|
foreach { pin } [concat $dqsn_pins $ck_pins $ckn_pins $reset_pins] {
|
573 |
|
|
set_false_path -to [get_ports $pin]
|
574 |
|
|
}
|
575 |
|
|
|
576 |
|
|
if { ! $synthesis_flow } {
|
577 |
|
|
foreach dqs_in_clock_struct $dqs_in_clocks dqsn_out_clock_struct $dqsn_out_clocks {
|
578 |
|
|
array set dqs_in_clock $dqs_in_clock_struct
|
579 |
|
|
array set dqsn_out_clock $dqsn_out_clock_struct
|
580 |
|
|
|
581 |
|
|
set_clock_groups -physically_exclusive -group "$dqs_in_clock(dqs_pin)_IN" -group "$dqs_in_clock(dqs_pin)_OUT $dqsn_out_clock(dst)_OUT"
|
582 |
|
|
|
583 |
|
|
|
584 |
|
|
}
|
585 |
|
|
}
|
586 |
|
|
|
587 |
|
|
foreach dqs_out_clock_struct $dqs_out_clocks {
|
588 |
|
|
array set dqs_out_clock $dqs_out_clock_struct
|
589 |
|
|
set_false_path -from $read_fifo_reset -to [ get_clocks $dqs_out_clock(dst)_OUT ]
|
590 |
|
|
}
|
591 |
|
|
|
592 |
|
|
# The paths between DQS_ENA_CLK and DQS_IN are calibrated, so they must not be analyzed
|
593 |
|
|
set_false_path -from [get_clocks $local_pll_write_clk] -to [get_clocks {*_IN}]
|
594 |
|
|
|
595 |
|
|
|
596 |
|
|
|
597 |
|
|
# The following registers serve as anchors for the pin_map.tcl
|
598 |
|
|
# script and are not used by the IP during memory operation
|
599 |
|
|
|
600 |
|
|
# Cut internal calibrated paths
|
601 |
|
|
set dqs_delay_chain_pst_dff ${prefix}|*p0|*altdq_dqs2_inst|dqs_delay_chain~POSTAMBLE_DFF
|
602 |
|
|
if {$after_u2b} {
|
603 |
|
|
set_false_path -from ${prefix}|*p0|*altdq_dqs2_inst|dqs_enable_ctrl~* -to $dqs_delay_chain_pst_dff
|
604 |
|
|
}
|
605 |
|
|
|
606 |
|
|
# Cut path to sampling register, calibrated by the PHY
|
607 |
|
|
if {[get_collection_size [get_registers -nowarn $pins(dqs_enable_regs_pins)]] > 0} {
|
608 |
|
|
set_false_path -to [get_clocks $local_sampling_clock]
|
609 |
|
|
}
|
610 |
|
|
|
611 |
|
|
# ------------------------------ #
|
612 |
|
|
# - - #
|
613 |
|
|
# --- FITTER OVERCONSTRAINTS --- #
|
614 |
|
|
# - - #
|
615 |
|
|
# ------------------------------ #
|
616 |
|
|
if {$fit_flow} {
|
617 |
|
|
|
618 |
|
|
|
619 |
|
|
|
620 |
|
|
}
|
621 |
|
|
|
622 |
|
|
# -------------------------------- #
|
623 |
|
|
# - - #
|
624 |
|
|
# --- TIMING MODEL ADJUSTMENTS --- #
|
625 |
|
|
# - - #
|
626 |
|
|
# -------------------------------- #
|
627 |
|
|
|
628 |
|
|
}
|
629 |
|
|
|
630 |
|
|
if {(($::quartus(nameofexecutable) ne "quartus_fit") && ($::quartus(nameofexecutable) ne "quartus_map"))} {
|
631 |
|
|
set dqs_clocks [hps_sdram_p0_get_all_instances_dqs_pins hps_sdram_p0_ddr_db]
|
632 |
|
|
# Leave clocks active when in debug mode
|
633 |
|
|
if {[llength $dqs_clocks] > 0 && !$debug} {
|
634 |
|
|
post_sdc_message info "Setting DQS clocks as inactive; use Report DDR to timing analyze DQS clocks"
|
635 |
|
|
set_active_clocks [remove_from_collection [get_active_clocks] [get_clocks $dqs_clocks]]
|
636 |
|
|
}
|
637 |
|
|
}
|
638 |
|
|
|
639 |
|
|
######################
|
640 |
|
|
# #
|
641 |
|
|
# REPORT DDR COMMAND #
|
642 |
|
|
# #
|
643 |
|
|
######################
|
644 |
|
|
|
645 |
|
|
add_ddr_report_command "source [list [file join [file dirname [info script]] ${::GLOBAL_hps_sdram_p0_corename}_report_timing.tcl]]"
|
646 |
|
|
|