Timing Exceptions
The one-clock-cycle rule is right for most paths, but not all of them. Some can never carry data that matters. Some are given several cycles on purpose. Some cross between clocks with no relationship. Timing exceptions tell the tool about each case - and each one, written wrongly, hides a real failure. This volume works through every kind with numbers, including the hold check that a multicycle path quietly drags along.
- When a false path is safe, and why a wrong one is dangerous
- How a multicycle path relaxes setup, and the hold trap it sets
- Which clock to count in when a multicycle path crosses between two clocks
- What set_max_delay and set_min_delay do, and where they are used
- How case analysis and disabled arcs remove paths that cannot happen
- Volume 07, for how edges are paired between clocks
8.1 False paths
A false path is a path the tool is told never to time, because it can never carry data that matters. Used correctly it removes violations that do not exist. Used wrongly it hides one that does.
A timing tool times every path it can find, including paths that the design can never actually use. When one of those fails, it fills the report with a violation nobody needs to fix. A timing exception tells the tool the truth about such a path.
A path that cannot happen
Two multiplexers share one select line, S. When S is 0, both pass their first input; when S is 1, both pass their second. At 10 ns, with 0.25 ns clock-to-Q and 0.10 ns setup:
| Path | Logic | Slack | Can it happen? |
|---|---|---|---|
| mux1 in0, then mux2 in0 (S = 0) | 8.90 ns | 0.75 ns | Yes |
| mux1 in1, long operation, mux2 in1 (S = 1) | 9.20 ns | 0.45 ns | Yes |
| mux1 in0, long operation, mux2 in1 | 11.40 ns | -1.75 ns | No - it needs S = 0 and S = 1 at once |
The tool does not know that S cannot be two values at once. So it reports -1.75 ns as the worst path. The real worst path is 0.45 ns, and it passes.
set_false_path -through [get_pins u_mux1/I0] -through [get_pins u_mux2/I1]
A path that does not need timing
A configuration register is written once at power-on, while the logic it controls is idle. Its path through a multiplier takes 12.30 ns on a 10 ns clock, so the tool reports -2.65 ns. But by the time anything reads the result, the register has been steady for thousands of cycles.
That can also be a false path - but only if the design really guarantees it. If software could ever write that register while the logic runs, the path is real, and the violation is a bug.
Declaring a path false because it fails. A false path is a statement about the design, not about the timing report. Every false path in a constraint file should come with a comment saying why the path can never matter, and someone other than its author should check it.
What happens to a real, failing path that is declared false?
Show the answer
Answer: B. A false path is simply not timed. The report looks clean, but the silicon still has a path too slow for its clock. That is why false paths are reviewed so carefully.
8.2 Multicycle paths on one clock
A multicycle path is given more than one clock cycle for setup, because the design only uses its result every few cycles. Relaxing setup drags the hold check along with it, and that must be put back by hand.
Some logic is too slow for one cycle, and the design knows it. A slow calculation is started, and its result is only read three cycles later. An enable signal makes both registers act only every third edge.
Take such a path at 10 ns: clock-to-Q 0.30 ns (0.20 fastest), logic 24.50 ns (1.10 fastest), setup 0.10 ns and hold 0.05 ns.
| Constraint | Setup edges | Setup slack | Hold edges | Hold slack |
|---|---|---|---|---|
| None | 0 then 10 | -14.90 ns | 0 then 0 | 1.25 ns |
| set_multicycle_path 3 -setup | 0 then 30 | 5.10 ns | 0 then 20 | -18.75 ns |
| ...and set_multicycle_path 2 -hold | 0 then 30 | 5.10 ns | 0 then 0 | 1.25 ns |
The hold trap
Look at the middle row. The setup exception moved the capture edge from 10 to 30. The default hold check is always one capture edge before the setup capture - so it moved too, from 0 to 20.
Now hold wants the data to arrive no earlier than 20.05 ns. It arrives at 1.30 ns. The hold check says -18.75 ns: a violation that is pure fiction, and that the tools would try to "fix" with about 19 ns of delay cells.
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]
An N-cycle setup multicycle always needs an (N-1)-cycle hold multicycle. The hold number moves the hold check back N-1 edges, to where it started.
Writing the setup multicycle and forgetting the hold one. The first report shows a huge hold violation; the second, after the tool has filled the path with delay cells, shows a path that is now also too slow. It is the most common constraint mistake there is.
A 17.00 ns path on a 10 ns clock gets set_multicycle_path 2 -setup and nothing else. Setup slack is +2.60 ns. What does the hold check report?
Show the answer
Answer: A. The setup capture moved from 10 to 20 ns, so the default hold check moved from 0 to 10 ns. The data arrives far earlier than that, so hold reports about -9.25 ns. Adding set_multicycle_path 1 -hold puts it back, to +0.75 ns.
8.3 Multicycle paths between two clocks
When a multicycle path crosses between two clocks, you must say whose cycles you are counting. The option -end counts the capture clock and moves the capture edge. The option -start counts the launch clock and moves the launch edge.
Take a path between a 10 ns clock and a 5 ns clock. It has clock-to-Q 0.20 ns and logic 8.20 ns (0.80 fastest), with setup 0.10 ns and hold 0.05 ns. Without an exception, either direction gets one fast period: 5 ns. The design gives it two.
Slow to fast: count the fast capture clock, with -end
| Constraint | Setup edges | Setup slack | Hold edges | Hold slack |
|---|---|---|---|---|
| None | 0 then 5 | -3.50 ns | 0 then 0 | 0.95 ns |
| -setup 2 -end | 0 then 10 | 1.50 ns | 0 then 5 | -4.05 ns |
| ...and -hold 1 -end | 0 then 10 | 1.50 ns | 0 then 0 | 0.95 ns |
Fast to slow: count the fast launch clock, with -start
| Constraint | Setup edges | Setup slack | Hold edges | Hold slack |
|---|---|---|---|---|
| None | 5 then 10 | -3.50 ns | 10 then 10 | 0.95 ns |
| -setup 2 -start | 0 then 10 | 1.50 ns | 5 then 10 | -4.05 ns |
| ...and -hold 1 -start | 0 then 10 | 1.50 ns | 10 then 10 | 0.95 ns |
The pattern is the same as on one clock: an N-cycle setup exception needs an (N-1)-cycle hold exception, counted in the same clock.
set_multicycle_path 2 -setup -start -from [get_clocks fast] -to [get_clocks slow]
set_multicycle_path 1 -hold -start -from [get_clocks fast] -to [get_clocks slow]
Counting the wrong clock
Put -end on the fast-to-slow path by mistake. The tool moves the capture edge by one slow period, from 10 to 20 ns. The path now gets 15 ns instead of 10, and shows 6.50 ns of slack it does not have.
Count the cycles of the faster clock, because that is where the extra cycles really are. For slow-to-fast the faster clock captures, so use -end. For fast-to-slow it launches, so use -start.
Leaving off -start and -end and trusting the default. The default is -end for setup. On a fast-to-slow path that silently gives the path a whole extra slow cycle - an optimistic error the reports will never show.
A path launches on a 4 ns clock and captures on a 12 ns clock. Which option makes set_multicycle_path count the right cycles?
Show the answer
Answer: C. The extra cycles belong to the faster clock, which here launches the data. -start counts launch-clock periods and moves the launch edge. With -end, each extra "cycle" would be a whole 12 ns capture period.
8.4 Max delay and min delay
set_max_delay and set_min_delay replace the clock relationship with a plain number. Their main use is on crossings between unrelated clocks, where there is no clock relationship to use.
Volume 07 put unrelated clocks in separate clock groups, which stops all timing between them. But some crossings still need a bound. The classic one is a Gray-coded pointer in an asynchronous FIFO. Its bits must all arrive within about one destination clock period of each other. Otherwise the synchroniser may see a mixture of old and new bits.
set_max_delay -datapath_only 3.0 -from [get_cells wptr_gray_reg*] -to [get_cells wptr_sync1_reg*]
-datapath_only means: ignore the clocks altogether, and just measure the data path against 3.0 ns.
| Bit | Clock-to-Q + route | Slack against 3.0 ns (setup 0.10) |
|---|---|---|
| bit 0 | 0.20 + 1.10 = 1.30 ns | 1.60 ns |
| bit 1 | 0.20 + 1.85 = 2.05 ns | 0.85 ns |
| bit 2 | 0.20 + 2.60 = 2.80 ns | 0.10 ns |
All three pass, and the spread between the fastest and the slowest bit is 1.50 ns. What the constraint really protects is that spread, so the synchroniser never sees two bits change far apart.
Min delay
set_min_delay is the hold-side partner: the path must take at least this long. A path that can take as little as 0.10 + 0.15 = 0.25 ns, under set_min_delay -datapath_only 0.40, fails by 0.15 ns.
The asynchronous FIFO and its Gray pointers are built in Volume 06 of the Verilog course. That course's Volume 07 explains why a false path on such a crossing is the wrong tool, and FPGA Mastery Volume 03 shows the XDC form of these constraints.
Using set_false_path on a Gray-pointer crossing. It removes the bound entirely. Place-and-route may then route one bit the long way round, and the synchroniser occasionally captures a pointer value that never existed.
Under set_max_delay -datapath_only 2.50, a path has 0.20 ns of clock-to-Q, 2.40 ns of route and a 0.10 ns setup time. What is its slack?
Show the answer
Answer: D. The data takes 0.20 + 2.40 = 2.60 ns. It must be in by 2.50 - 0.10 = 2.40 ns. Slack = 2.40 - 2.60 = -0.20 ns. The clocks play no part: that is what -datapath_only means.
8.5 Case analysis and disabling arcs
Case analysis tells the tool a signal is held constant, so paths that cannot happen in that mode are not timed. Disabling a timing arc removes one arc from every path, which is how a combinational loop is broken.
Many chips have more than one mode. The commonest example is a test mode, where a multiplexer in front of each flip-flop switches from the normal logic to a long test path.
| What the tool times | Worst setup slack at 10 ns |
|---|---|
| Every path, both modes mixed together | -1.55 ns, on a test-only path |
| Functional mode: set_case_analysis 0 on test_mode | 0.75 ns |
| Test mode on its own, with its 20 ns test clock | 8.45 ns on that test path |
# functional mode
set_case_analysis 0 [get_ports test_mode]
# test mode, in a separate run with the test clock
set_case_analysis 1 [get_ports test_mode]
With the mode pin held at 0, the tool knows every test-mode multiplexer passes its functional input. The test paths disappear from the functional run. They are checked in a run of their own, in test mode, against the slower test clock.
Disabling a timing arc
A combinational loop is logic that feeds back on itself with no flip-flop in the way. A timing tool cannot add delays around a circle forever, so it has to cut the loop somewhere. It picks a place, and warns you. Better to choose the place yourself:
set_disable_timing -from A -to Y [get_cells u_loop_nand]
That arc is then left out of every path, everywhere. Use it sparingly, and only on arcs that really cannot carry a timed signal.
Case analysis and disabled arcs both remove paths without saying "false path". They are just as powerful, and just as dangerous when wrong. Every mode the chip can run in needs its own timing run.
Why is it wrong to time a chip once, with the test-mode pin left unconstrained?
Show the answer
Answer: B. With the pin free, the tool times paths that only exist in test mode against the functional clock, and the report is dominated by them. Each mode should be timed on its own, with the pin held by case analysis and the right clocks for that mode.
What you learned
- A false path is never timed; declare one only for paths that can never matter.
- A setup multicycle of N moves the hold check too; it needs an (N-1)-cycle hold multicycle.
- Between two clocks, count cycles of the faster one: -end for slow-to-fast, -start for fast-to-slow.
- set_max_delay -datapath_only bounds a crossing between unrelated clocks, such as a Gray pointer.
- set_min_delay is its hold-side partner.
- Case analysis removes paths that cannot happen in a mode; each mode needs its own run.
- Disabling a timing arc cuts it out of every path, and is how combinational loops are broken.
Key words from this volume
Every word below has a plain-English entry in the glossary.
- False path
- Timing exception
- Multicycle path
- Max delay and min delay
- Case analysis
- Combinational loop
Practice
A four-cycle path
The 24.50 ns path of sub-module 8.2 is given four cycles instead of three. Write the two constraints, and give the setup and hold slack.
Show the solution
set_multicycle_path 4 -setup, and set_multicycle_path 3 -hold.
The capture edge moves to 40 ns, so setup slack is 40.00 - 0.30 - 24.50 - 0.10 = 15.10 ns. The hold check returns to the launch edge, and its slack stays at 1.25 ns.
Spot the optimism
A constraint file contains set_multicycle_path 2 -setup -from [get_clocks fast] -to [get_clocks slow], where fast is 5 ns and slow is 10 ns. There is no -start. What does the tool check, and why is
it wrong?
Show the solution
With no option, setup multicycles count the capture clock. So the capture edge moves by one slow period, and the path is checked from 5 ns to 20 ns: 15 ns allowed. The design only guarantees two fast cycles: 10 ns.
For the path in sub-module 8.3 that shows 6.50 ns of slack instead of the true 1.50 ns. The fix is
-start, and a matching set_multicycle_path 1 -hold -start.
False path or multicycle?
A status register is written by a slow state machine once every 16 cycles. Its value is read by other logic, but only 4 cycles after each write, guaranteed by the design. Which exception fits?
Show the solution
A multicycle path of 4 cycles for setup, with 3 for hold. The path is real and must still be timed, just against a longer requirement.
A false path would also clear the report, but it would put no bound on the path at all. If the logic grew past four cycles, nothing would warn you.
Interview corner
The multicycle hold rule
"You set a 3-cycle multicycle path for setup. What else must you do, and why?"
Show the solution
"Add a 2-cycle multicycle for hold. The default hold check is one capture edge before the setup capture edge. Moving setup from the first edge to the third drags the hold check from edge zero to edge two. The tool would then demand the data take at least two whole cycles. That is almost never true, so it shows a huge false hold violation - and if the tool fixes it with delay cells, it breaks the path. The -hold 2 moves the hold check back to the launch edge."
False path versus max delay on a CDC
"For a bus crossing between two asynchronous clocks, would you use set_false_path or set_max_delay?"
Show the solution
"For a Gray-coded pointer or any multi-bit crossing, set_max_delay -datapath_only, set to about one destination clock period. A false path removes all timing, so place and route may make one bit much slower than the others, and the receiving side could see an inconsistent value. The max delay keeps the bits close together while still ignoring the clock relationship. For a single-bit control signal into a two-flop synchroniser, a false path or clock groups is usually acceptable."
Volume 09 meets a different kind of storage element: the latch, which can borrow time from the next stage when a path runs late.