Tcl · Module 20
Creating Clocks
Everything else in timing is measured against a clock. Declare it wrong and nothing complains; declare it on a port that does not exist and the report comes back clean and empty.
Intermediate17 min readtcledapart-iisdcclocksconstraints
Part II · Module 20 · Chapter 20.2 · Creating Clocks
A clock declaration says: this signal is a clock, it has this period, and it enters the design here. Every setup check, every hold check and every slack number in the flow is measured against it.
It is the first constraint written and the one with the worst failure mode, because getting it wrong does not produce an error.
1. A primary clock
A primary clock is one that arrives from outside — it is generated elsewhere and enters through a port.
create_clock -name core_clk -period 2.0 [get_ports clk]Three pieces:
-name core_clk— what the clock is called in everything downstream. Reports, exceptions and clock groups all refer to it by this name, not by the port.-period 2.0— the cycle time. The unit comes from the library, commonly nanoseconds; a period of 2.0 ns is 500 MHz.[get_ports clk]— where it enters. A collection, so everything from Module 18 applies, including the way it fails.
2. More than one
Most designs have several, and they are simply several declarations:
create_clock -name core_clk -period 2.0 [get_ports clk]
create_clock -name ref_clk -period 10.0 [get_ports ref_clk] clocks:
core_clk 2.0 on clk (primary)
ref_clk 10.0 on ref_clk (primary)Two independent clocks at different frequencies. Whether paths between them should be analysed is a separate decision, and it is Chapter 20.7.
3. Generated clocks
A clock produced inside the design — by a divider, a gate, or a PLL output — is a generated clock. It is declared differently, and the difference matters:
create_generated_clock -name div2_clk -source ref_clk -divide_by 2 [get_pins -hierarchical u_div/Q] div2_clk div2 of ref_clk on u_div/Q (generated)The essential part is -source. It tells the tool that div2_clk is derived from ref_clk — so the two are phase-related, and the tool can analyse paths between them correctly because it knows how they line up.
Note also that the source is a pin, not a port — the divider's output — which is why the query needs -hierarchical. That is Chapter 18.4 §2's rule, and forgetting it produces an empty collection, which is §5.
4. What the period actually commits you to
The period is not a wish. It is the budget every path in that domain is checked against, and it propagates:
- A path from a flop to a flop in the same domain gets one period to complete.
- The I/O budgets in 20.3 and 20.4 are usually expressed as a fraction of it.
- Multicycle exceptions (20.6) are stated in multiples of it.
Which is why Chapter 20.1 §4 put it in a variable:
set PERIOD 2.0
create_clock -name core_clk -period $PERIOD [get_ports clk]
set_input_delay [expr {$PERIOD * 0.20}] -clock core_clk [get_ports {d_in[*]}]Change $PERIOD and the I/O budgets follow. Write 2.0 and 0.4 separately and one day they disagree.
5. The failure that makes everything else meaningless
puts " create_clock on a typo'd port:"
puts " [catch {create_clock -name core_clk -period 2.0 [get_ports clock]} e] / $e"
puts " and the port that does exist:"
create_clock -name core_clk -period 2.0 [get_ports clk]
puts " defined: [llength $::sdc::clocks] clock(s)" create_clock on a typo'd port:
1 / create_clock -name core_clk source matched nothing
and the port that does exist:
defined: 1 clock(s)6. Checking what you declared
After the clocks are defined, print them. Chapter 19.2 is the full version — comparing clocks defined against clocks arriving — and even the short form is worth having at the top of every run:
foreach c $::sdc::clocks {
lassign $c name period source kind
puts [format " %-10s %-8s on %-14s (%s)" $name $period $source $kind]
}Three things to check by eye the first time, and by script thereafter:
- The count. Fewer clocks than you expected means one failed to apply.
- The periods. Against the specification, not against memory.
- Primary versus generated. A divider output listed as primary is §3's mistake.
7. Exercises
Exercise 1. What three pieces does a primary clock declaration need?
Exercise 2. Why give the clock a different name from the port it arrives on?
Exercise 3. What makes a clock generated rather than primary?
Exercise 4. What does -source tell the tool, and what goes wrong without it?
Exercise 5. Why does a generated clock's source query usually need -hierarchical?
Exercise 6. A real create_clock on a pattern that matches nothing — what happens?
Exercise 7. Why put the period in a variable?
Where this fits
Part of the Tcl curriculum.
