Why does set_multicycle_path without a matching -hold setting shift the hold check?
From PDVerse STA Mentor Guide · pdVerse Mentor Guide
Short Answer
Because every valid hold relationship is defined relative to the setup relationship, changing the setup relationship with set_multicycle_path -setup (SDC) automatically moves the hold check's capture edge along with it - usually to a point that does not match what the design actually needs. The standard fix is to pair it with a second command, set_multicycle_path (N-1) -hold ... (SDC), that moves the hold capture edge back to where it belongs.
Technical Explanation
set_multicycle_path -setup N(SDC) moves which capture edge counts for setup. The Nth capture edge after the launch edge becomes the one setup is checked against, instead of the default first edge.- The hold relationship is derived from the setup relationship, not independent of it. PrimeTime always verifies that data launched for the new setup edge is not also captured by the edge immediately before it, and by default that becomes the new hold check point.
- That default hold point is almost never the one the design actually needs. If the launching register does not need to hold its data all the way out to the edge just before the new setup edge, the implicit hold relationship is overly strict or simply wrong for the real circuit.
- A second, explicit command corrects it.
set_multicycle_path -hold (N-1) -from ... -to ...(SDC), added alongside the-setup Ncommand on the same path, moves the hold check's capture edge backward to line up with what the design intends. - The exact relationship is a small formula, not a guess: hold cycles = (setup value) - 1 - (hold value). With
-setup 2and no-holdcommand, hold cycles default to 2 - 1 - 0 = 1, meaning the hold check still allows one extra cycle of margin versus the single-cycle default; a-hold 1command instead moves it to 2 - 1 - 1 = 0, restoring the original, same-cycle hold point. - Both commands must target the exact same path specification. If the
-setupand-holdcommands use different-from/-to/-throughobjects, they will not necessarily resolve to the same set of paths, and the correction will not land where intended.
Common Mistake
- Writing
set_multicycle_path -setup Nalone and assuming the hold check is unaffected, since the command only mentions setup. - The hold relationship shifts automatically as a side effect, and without a matching
-holdcommand it lands on whatever edge the formula produces by default, not on the edge the actual circuit requires. - Cost: a hold check that is either falsely relaxed (hiding a real hold violation) or falsely tightened (reporting a hold violation on a path that is actually fine), depending on which way the default shift happened to land.
Follow-up Question & Model Response
If a path is set with set_multicycle_path -setup 5 and set_multicycle_path -hold 4 on the same -from/-to pair, what is the resulting hold-cycle count, and what does that tell you about the intended hold behavior?
Candidate Model Response: Using the formula, hold cycles = 5 - 1 - 4 = 0, meaning the hold check is anchored to the same-cycle capture edge as if no multicycle exception existed at all - the setup relationship was stretched to five cycles, but the hold requirement was pulled all the way back to its original, single-cycle position. That tells me the designer wants the extra setup margin without giving up any hold protection at all: the launching register still must not have its data captured any earlier than the very first edge after launch. This is the most common intent behind a paired multicycle setup/hold specification - stretch the timing budget for setup, but hold the hold check exactly where it always was.
Practical Example
A design has a two-cycle path from FF4 to FF5, so the SDC specifies set_multicycle_path -setup 2 -from [get_cells FF4] -to [get_cells FF5] (SDC). Left alone, this implicitly shifts the hold check to hold cycles = 2 - 1 - 0 = 1, meaning FF4's data is now allowed to change one full cycle later than the design actually needs, silently hiding a real hold risk if the data is only meant to be stable for the original single cycle. Adding set_multicycle_path -hold 1 -from [get_cells FF4] -to [get_cells FF5] (SDC) corrects it to hold cycles = 2 - 1 - 1 = 0, restoring the same-cycle hold check the two-cycle setup relationship should have had all along.
Complete STA Handbook
Master Signoff-Ready Static Timing Analysis
Get the complete 10-chapter STA handbook covering setup/hold margins, clock modeling, OCV/POCV, crosstalk noise, and PrimeTime closure.

Continue practising