Point-to-Point & Combinational Delays
Point-to-Point & Combinational Delays (Deep)
Most timing checks come from clocks. Data launches on one edge and must arrive by another. But sometimes you want to bound a delay directly, without a clock telling the story. You want to say "this path must take no more than X" or "no less than Y." Point-to-point delay constraints do exactly that. This chapter goes deep on how they work and where they fit. We keep the format generic. We call it SDC. We never name a tool or product. We say "the timing tool" for the engine that checks paths.
Bounding a Delay Directly
The command set_max_delay sets a ceiling on the delay along a path. The command
set_min_delay sets a floor. They speak in absolute time, not in clock cycles. You pick the endpoints
and you pick the number. This is different from a normal flop-to-flop check. A normal check derives its requirement from the clock period and the flop timing. A point-to-point constraint ignores all that and states the limit outright. It is a direct, manual bound. When is this useful? When the path has no natural clock requirement, or when the clock-derived requirement is not the one you want. Combinational paths that run from an input pin straight to an
output pin are a classic case. There is no flop to anchor a normal check, so you bound the delay by hand.

Combinational and Pin-to-Pin Paths
A combinational path has no flop in the middle. Signal flows through gates only. From input pin to output pin, with logic in between, is the purest example. Such a path has no launch edge and no capture edge, so the clock-based machinery has nothing to grip. The point-to-point commands fill the gap. You name a start and an end with -from and -to , optionally a midpoint with -through , and give a time. The tool then checks that the delay between those points stays within your bound.
# standard SDC — portable across compliant tools
# Bound a pure combinational path from input to output.
set_max_delay 3.27 -from [get_ports cfg_in] -to [get_ports decode_out]
set_min_delay 0.49 -from [get_ports cfg_in] -to [get_ports decode_out]
| Command | Sets | Used for |
|---|---|---|
| set_max_delay | A ceiling on path delay | Setup-like bound, slowest allowed |
| set_min_delay | A floor on path delay | Hold-like bound, fastest allowed |
A worked feel. A combinational decode path runs from cfg_in to decode_out . You set a max delay of 3.27 ns. The tool computes the actual delay at 2.91 ns. Slack is 3.27 minus 2.91, which is +0.36 ns. The path passes. Set a min delay of 0.49 ns and the same path easily clears the floor, since 2.91 is well above 0.49.
Interaction with Clock-Derived Requirements
Point-to-point constraints can also land on paths that already have a clock-derived requirement. Then two requirements exist on one path: the natural clock check and your manual bound. The tool honors the tighter one.
This is a powerful override but a sharp one. If your set_max_delay is tighter than the clock-derived setup requirement, your bound wins and the path is held to your stricter limit. If your bound is looser, the clock requirement still rules. So a point-to-point constraint can only make a clocked path stricter, not looser, unless you also remove the clock relationship.
| Situation | Binding requirement |
|---|---|
| Manual bound tighter than clock check | Manual bound |
| Manual bound looser than clock check | Clock check |
| No clock relationship on the path | Manual bound only |
Because of this, point-to-point delays are often used to add an extra, custom ceiling on a path that matters more than the clock period suggests. They are also used on paths the clock machinery cannot reach at all, like input-to-output combinational routes.
# standard SDC — portable across compliant tools
# A tighter custom ceiling on an otherwise clocked path.
set_max_delay 1.88 -from [get_cells crit_src_reg] -to [get_cells crit_dst_reg]
Removing Clock Latency from the Picture
A clocked path's requirement includes clock latency. Clock latency is the time the clock signal itself takes to reach the flop. When you bound a delay by hand, you sometimes want to measure only the data path and exclude that clock travel time. The option -ignore_clock_latency does this. It tells the tool to leave clock latency out of the calculation for that bound. The result is a cleaner measure of the pure data delay, which is often what you mean when you state an absolute number.

A worked feel. A path's data delay is 2.44 ns. The capture clock latency adds 0.37 ns to the effective requirement. Without ignoring it, the tool folds that 0.37 ns into the math. With -
ignore_clock_latency , the tool compares your bound against the pure 2.44 ns data delay only. If you meant your number to describe data travel alone, this option makes the check match your intent.
# standard SDC — portable across compliant tools
# Bound only the data delay, excluding clock travel time.
set_max_delay 2.60 -ignore_clock_latency \
-from [get_cells pipe_a_reg] -to [get_cells pipe_b_reg]
Use on Asynchronous Datapaths
Asynchronous datapaths are a natural home for point-to-point delays. An asynchronous datapath carries data between two domains whose clocks are unrelated. The normal clock-to-clock check is meaningless there, so you often disable it. But disabling it leaves the path with no bound at all, and an unbounded path can grow huge in synthesis. The fix is to declare the clock relationship false or asynchronous, then add a set_max_delay to keep the physical delay reasonable. This way the tool stops doing the meaningless clock comparison but still caps the raw propagation delay. It is a common pattern for synchronizer inputs and other crossings where you want the data to settle quickly even though no clock relationship governs it.
# standard SDC — portable across compliant tools
# Async crossing: drop the clock relationship, then cap raw delay.
set_clock_groups -asynchronous \
-group [get_clocks clk_a] -group [get_clocks clk_b]
set_max_delay 1.53 -from [get_cells a_launch_reg] -to [get_cells b_sync_reg]
| Step | Purpose |
|---|---|
| Declare clocks asynchronous | Stop the meaningless clock-to-clock check |
| Add set_max_delay | Keep the raw propagation delay bounded |
| Optionally set_min_delay | Prevent the path from collapsing too short |
A worked illustration. Two unrelated clocks feed a crossing. After declaring them asynchronous, the clock comparison is gone, but the route could otherwise wander to several nanoseconds. A
set_max_delay of 1.53 ns caps it. The tool reports this path against the 1.53 ns ceiling alone, so the
crossing stays short and the metastability window for the downstream synchronizer stays small. The clock machinery never touches it again.
Interview Q&A
absolute time bound directly, in nanoseconds, rather than deriving a requirement from the clock period
and flop timing. set_max_delay is a ceiling and set_min_delay is a floor, both set by hand on chosen endpoints.
has no flop in the middle, so there is no launch or capture edge for the clock machinery to grip. The point-to-point commands supply the bound the path otherwise lacks, checking the delay between the named pins directly.
requirements then coexist, and the tool honors the tighter one. If your manual bound is stricter than the clock-derived requirement, it wins; if it is looser, the clock requirement still rules. A manual bound can tighten a clocked path but not loosen it.
the bound's calculation, leaving a pure measure of the data path delay. You use it when your absolute number is meant to describe data travel alone, so the check matches that intent.
asynchronous stops the meaningless clock-to-clock check, but it leaves the path unbounded, free to grow large. Adding a max delay caps the raw propagation delay so the crossing stays short, which keeps the downstream synchronizer's window small.
always applies the tighter of the manual bound and the clock check, so a looser manual bound is ignored. To truly loosen the path you must remove the clock relationship, for example by declaring it false or asynchronous.
Key Takeaways
- Point-to-point delays bound time directly.
set_max_delayandset_min_delaystate absolute ceilings and floors, not clock-derived requirements. - Combinational paths need them. Input-to-output routes have no flop, so the clock machinery cannot check them and a manual bound steps in.
- Manual bounds only tighten clocked paths. The tool keeps the stricter of the manual bound and the clock check, never the looser one.
-ignore_clock_latencyisolates data delay. It strips clock travel time so the bound matches a pure data-path number.- Async crossings need a cap. Declaring clocks asynchronous removes the check but leaves the path unbounded, so pair it with a max delay.
ChipBuddy
← Home
Comments
Leave a Reply