SDC Constraints, Complete
Every check in this course was driven by a constraint: a clock, an input delay, an exception. Those constraints live in one file, written in SDC, and a timing tool believes every word of it. This volume gathers the whole language in one place, command by command, and ends with the part most often skipped: checking that the file says what you meant.
- How to define clocks and generated clocks, including -edges
- Which clock properties to set, and when each one changes
- How to describe inputs and outputs completely, including drive and load
- Every exception, and which one wins when two apply
- What design rules are, and how to check that nothing is left untimed
- Volumes 06 to 10, where each of these constraints was first used
13.1 Defining clocks
Every timing check starts from a clock, and a tool only knows the clocks you declare. Primary clocks are created on the pins where they enter; every clock made inside the design is declared as generated from one of them.
SDC is the constraint language nearly every timing tool reads. It is Tcl: one command per line, read from top to bottom. This volume collects every command the course has used, in the order a constraint file usually follows.
Primary clocks
# a 100 MHz clock arriving on port clk, rising at 0 and falling at 5
create_clock -name clk -period 10 -waveform {0 5} [get_ports clk]
# a clock for another chip, with no pin in this design (Volume 10)
create_clock -name vclk -period 10 -waveform {2 7}
Generated clocks
A generated clock names a master and says how its edges come from the master's. The -edges option numbers the master's edges from the first rising one: 1 rises, 2 falls, 3 rises, and so on. It gives three numbers - the new clock's rise, fall and next rise.
| From a 10 ns master | Period | Rises | Falls | Duty |
|---|---|---|---|---|
| -divide_by 2, the same as -edges {1 3 5} | 20.00 ns | 0.00 | 10.00 | 50% |
| -edges {1 4 7}: divide by 3 | 30.00 ns | 0.00 | 15.00 | 50% |
| -edges {1 5 7}: divide by 3 | 30.00 ns | 0.00 | 20.00 | 67% |
| -edges {2 4 6}: inverted, divide by 2 | 20.00 ns | 5.00 | 15.00 | 50% |
create_generated_clock -name clk_div2 -source [get_ports clk] -divide_by 2 [get_pins u_div2/Q]
create_generated_clock -name clk_div3 -source [get_ports clk] -edges {1 4 7} [get_pins u_div3/Q]
Declaring a divided clock with create_clock. Volume 07 showed the price: the tool loses the divider's latency and, often, the phase relationship to the master - one direction of crossing then looks better than it is.
From an 8 ns master, what does create_generated_clock -edges {1 4 7} produce?
Show the answer
Answer: C. Master edges 1 and 7 are rising edges at 0 and 24 ns, so the period is 24 ns. Edge 4 is the second falling edge, at 12 ns, so the new clock is high for exactly half its period.
13.2 Clock properties
A clock also carries properties: how long it takes to arrive, how much it wobbles, and how sharp its edges are. Most of them change once the clock tree is built.
# where the clock comes from (Volume 06): off-chip PLL to our clock pin
set_clock_latency -source 0.50 [get_clocks clk]
# before the clock tree exists: an estimate of its delay
set_clock_latency 0.40 [get_clocks clk]
# jitter plus margin (setup), margin only (hold) - Volumes 04 and 06
set_clock_uncertainty -setup 0.08 [get_clocks clk]
set_clock_uncertainty -hold 0.03 [get_clocks clk]
# the edge speed at the flip-flops, before the tree is built
set_clock_transition 0.10 [get_clocks clk]
# after clock tree synthesis: measure the real tree instead
set_propagated_clock [all_clocks]
| Property | Before the clock tree | After the clock tree |
|---|---|---|
| Source latency | Set by hand | Set by hand - it is outside the chip |
| Network latency | An estimate | Measured: set_propagated_clock |
| Uncertainty | Jitter + skew estimate + margin | Jitter + margin |
| Clock transition | An estimate | Measured |
Constraint files usually have two versions of this block, one before and one after clock tree synthesis. Using the wrong one is a common source of hold surprises.
Which clock property is still set by hand after the clock tree is built?
Show the answer
Answer: A. Source latency happens outside the chip, before the clock reaches its pin, so the tool can never measure it from the design. Everything inside the tree is measured once the clock is propagated.
13.3 I/O constraints
An input needs more than an input delay: the tool also wants to know how sharp its edge is. An output needs more than an output delay: the tool wants to know how much it drives. Leave either out and the first and last gates of the path are timed with made-up numbers.
# Volume 10: from the other chip's datasheet
set_input_delay -clock clk -max 4.80 [get_ports in_data]
set_input_delay -clock clk -min 1.50 [get_ports in_data]
set_output_delay -clock clk -max 2.70 [get_ports out_data]
set_output_delay -clock clk -min -0.10 [get_ports out_data]
# how the input is driven, and what the output drives
set_input_transition 0.40 [get_ports in_data]
set_load 0.020 [get_ports out_data]
Why they matter, using the NAND2_X1 from Volume 02:
| Constraint | Effect on the gate next to the port |
|---|---|
| Input edge of 50 ps | 29.1 ps through the first NAND2, driving 4 fF |
| Input edge of 400 ps | 139.3 ps through the same gate |
| Output load of 2 fF | 14.2 ps for the output NAND2 |
| Output load of 20 fF | 51.6 ps for the same gate |
set_load takes the load in the library's capacitance unit, often picofarads - so 0.020 is 20 fF. A real design would often use set_driving_cell instead of set_input_transition, naming a library cell whose strength matches the outside driver.
Leaving inputs with no transition and outputs with no load. The tool then assumes a perfect edge and no load at all. So the gates at the edge of the design look far faster than they will be on the board.
An input port has no set_input_transition or set_driving_cell. What does the tool assume?
Show the answer
Answer: D. With nothing said, the tool assumes an ideal driver. The first gate then sees a perfect edge, and its delay comes out at the fast end of its table. Compare 29.1 ps with a 50 ps edge against 139.3 ps with a 400 ps one.
13.4 Exceptions
Exceptions change how particular paths are timed. When two could apply to the same path, a fixed order decides: a false path beats a max or min delay, which beats a multicycle path.
# unrelated clocks: time nothing between them
set_clock_groups -asynchronous -group [get_clocks clk_a] -group [get_clocks clk_b]
# a path that can never happen
set_false_path -through [get_pins u_mux1/I0] -through [get_pins u_mux2/I1]
# three cycles for setup, and the hold check put back
set_multicycle_path 3 -setup -from [get_cells u_src] -to [get_cells u_dst]
set_multicycle_path 2 -hold -from [get_cells u_src] -to [get_cells u_dst]
# a bound on a crossing between unrelated clocks
set_max_delay -datapath_only 3.0 -from [get_cells wptr_gray_reg*] -to [get_cells wptr_sync1_reg*]
# one mode at a time
set_case_analysis 0 [get_ports test_mode]
Which exception wins
| Priority | Exception |
|---|---|
| Highest | set_false_path |
| Then | set_max_delay and set_min_delay |
| Then | set_multicycle_path |
When two exceptions of the same kind cover a path, the more specific one wins. A -from naming a pin beats one naming a cell, and a cell beats a whole clock.
Writing a broad false path "just in case" early in a file. It silently wins over every careful multicycle and max delay written later on the same paths - precedence does not care about the order of lines.
A path is covered by set_multicycle_path 2 and by set_false_path. How is it timed?
Show the answer
Answer: B. A false path has the highest priority of all the exceptions. The path is not timed, and the multicycle constraint has no effect on it.
13.5 Design rules: transition, capacitance, fanout
Design rules are limits on every net, not on paths: how slow an edge may be, how much load a gate may drive, and how many inputs it may feed. They keep gates inside the part of their tables that the library measured.
set_max_transition 0.150 [current_design]
set_max_capacitance 0.025 [current_design]
set_max_fanout 12 [current_design]
Here is the NAND2_X1 from Volume 02, driving a fanout of 16 (29 fF), against those limits:
| Rule | Limit | This net | Result |
|---|---|---|---|
| Max transition | 150 ps | 191.2 ps | Fails by 41.2 ps |
| Max capacitance | 25 fF | 29.0 fF | Fails by 4.0 fF |
| Max fanout | 12 | 16 | Fails by 4 |
There are two fixes, both from Volume 02. Drive the net with a NAND2_X4, whose edge is 47.8 ps. Or split it into two nets of 8 loads, 14.5 fF apiece, whose edges are 95.6 ps each. Either one meets every rule.
A slow edge is a problem even on a path with plenty of slack. It makes every gate it reaches slower, burns power while it crawls through the switching point, and pushes gates outside the range their tables were measured over.
A NAND2_X1 (3 kOhm) drives 22 fF. Using the 2.2 R C estimate, does it meet a 150 ps max transition?
Show the answer
Answer: C. 2.2 x 3 x 22 = 145.0 ps, just inside the 150 ps limit. At 20 fF it would be 131.8 ps. A little more load would push it over.
13.6 Checking your constraints
A timing report only shows problems with paths it could time. A path with a missing constraint is not failing - it is unconstrained, and it is silent. Checking the constraints is its own step.
Go back to the small design of Volume 03, with its seven paths. Suppose the constraint file forgot the input delay on in_b. Two paths now start from a port the tool knows nothing about:
| Path | Timed? |
|---|---|
| in_b -> U2 -> FF3/D | No |
| in_b -> U3 -> out_y | No |
| The other five | Yes |
Here is the trap. FF3/D and out_y still receive other, timed paths - from FF2 and FF3. So neither endpoint looks unconstrained. The report shows no violation, and nothing seems wrong, but two paths in seven are simply not checked.
What to run, and read
- A constraint check (check_timing in many tools): lists unclocked registers, inputs and outputs with no delay, generated clocks with no master, and combinational loops.
- A list of the clocks the tool created, with their periods, waveforms and sources. Compare it with what you meant.
- A list of the exceptions the tool applied, and to how many paths each. An exception that matched nothing is a typo; one that matched thousands of paths deserves a second look.
- A count of unconstrained endpoints and paths. On a finished design it should be zero, or every one explained.
"No violations" is only good news when the constraint check is clean too. Read the warnings first, then the timing report.
Treating constraint warnings as noise because there are hundreds of them. Each class of warning usually has one cause. Fix the cause, and the warnings - and the untimed paths behind them - go away together.
A design has no input delay on one input port, but the flip-flops it reaches are also fed by timed paths. What does the timing report show for those flip-flops?
Show the answer
Answer: A. Each flip-flop still has timed paths into it, so it is not an unconstrained endpoint. The paths from the port simply are not timed. Only a constraint check finds them.
What you learned
- Primary clocks are created on pins; clocks made inside the design are generated from a master.
- -edges counts master edges from the first rise: odd numbers rise, even numbers fall.
- Clock latency, uncertainty and transition are set by hand before the clock tree, and mostly measured after.
- Inputs need a delay and an edge speed; outputs need a delay and a load.
- A false path beats a max or min delay, which beats a multicycle path; the more specific exception wins.
- Design rules limit every net's transition, capacitance and fanout.
- A missing constraint does not fail - it goes silent, so constraints must be checked on their own.
Key words from this volume
Every word below has a plain-English entry in the glossary.
Practice
A clock from an 8 ns master
An 8 ns master clock is divided by two with create_generated_clock -divide_by 2. What is the new clock's period, and when does it first fall?
Show the solution
-divide_by 2 is the same as -edges {1 3 5}. Master edge 1 rises at 0 and edge 5 at 16 ns, so the period is 16 ns. Edge 3, the next rising edge of the master at 8 ns, is where the new clock falls.
Find the silent paths
In the design of sub-module 13.6, the output delay on out_y is removed instead of the input delay on in_b. Which paths go untimed now?
Show the solution
Every path that ends at out_y: in_b -> U3 -> out_y and FF3/CK -> U3 -> out_y. With no output delay, the tool has no requirement at that port.
This time out_y has no timed path left into it, so it does show up as an unconstrained endpoint. Missing output delays are easier to spot than missing input delays - but only if you look.
Interview corner
What goes in an SDC file?
"Walk me through the main sections of an SDC file for a block."
Show the solution
"Clocks first: create_clock on each primary clock port, and create_generated_clock for every divided or muxed clock, with the right source. Then clock properties: source latency, uncertainty for setup and hold, and clock transition or set_propagated_clock after CTS. Then I/O: input and output delays with -max and -min, set_driving_cell or set_input_transition, and set_load. Then exceptions: clock groups, false paths, multicycle pairs, max delays on CDC buses, and case analysis for each mode. Then design rules: max transition, capacitance and fanout. And finally I run the constraint checks, and review the clock and exception reports."
Exception priority
"If a set_max_delay and a set_multicycle_path both cover the same path, which one applies?"
Show the solution
"The max delay. The priority order is false path first, then max and min delay, then multicycle. If both were the same kind of exception, the more specific one would win - a pin-level -from beats a cell, and a cell beats a clock. That is why broad exceptions should be written with care: they can silently override something more careful."
Volume 14 puts everything to work. What do you do when the slack is negative, for setup and for hold, on an FPGA and on an ASIC? It ends with one design closed from its first report to its last.