DigiFlop

HomeDebug Guides › STA Debug Guide
RTL Debug · Static Timing Analysis
Debugging STA Violations: Setup, Hold, and What the Report Doesn't Tell You
A negative slack number is not automatically a bug — telling a real violation from a constraint problem is most of the job.
A functional simulation can pass every test you throw at it and the chip can still fail in silicon over a setup or hold violation nowhere in that simulation. Static timing analysis checks every register-to-register path against every corner exhaustively, without simulating a single vector — which means its report reads nothing like a simulation failure. This guide walks through what an STA report is actually telling you: which numbers point at a real timing problem in the design, which point at a broken or missing constraint in the STA setup itself, and how to read a report_timing dump like the story it actually is instead of a wall of numbers. No specific STA tool is assumed — command names follow the industry-standard SDC format, and report formatting varies by vendor, but the underlying checks don't.

Quick Cheat Sheet

What an STA report line usually means, sorted by how often it actually shows up on a real signoff run. Skim this before triaging a fresh report.

CategoryWhat the report showsWhere to look
SetupA reg2reg path shows negative slack, endpoint deep in a combinational cloudCount logic levels and fanout on the failing path; check which PVT corner produced the number and whether clock uncertainty is realistic
SetupSame failing path keeps reappearing after a placement-only ECOA real fix needs sizing, buffering, or restructuring/pipelining — check whether slack actually improved or the path just moved
HoldHold violation appears only at the best-case (fast) cornerClassic launch/capture skew or a too-fast min-delay path — confirm which corner is reported, it's rarely the same one setup fails at
HoldNew hold violations appear right after a setup fix on the same pathThe setup fix (buffer/upsize) shortened the path just enough to break hold at the fast corner — re-check hold after every setup ECO
Clock definitionTwo clocks are analyzed as synchronous but you expected them asynchronous, or the reverseMissing or wrong set_clock_groups / generated-clock ratio — verify the SDC clock relationships explicitly, don't assume a default
ExceptionsA path you know is functionally safe still shows a huge violationNeeds an explicit false_path or multicycle_path exception — or already has one that's stale and no longer applying
ExceptionsA multicycle setup exception is applied, and hold now fails on that same pathMissing the matching -hold multicycle exception — the default hold multiplier is not the same as the setup one
Report readingA path you expect to see is simply missing from the reportIt's likely unconstrained, not passing — check coverage (every register pair should be reachable by some clock/constraint) before trusting a clean report
Recovery/removalAsync reset release flagged as a recovery violationReset de-assertion is landing too close to a clock edge — needs a synchronized release, same root cause as a reset-domain-crossing bug
CornersDesign is clean at the typical corner, fails at a PVT extremeOnly one corner was signed off — setup and hold each need their own worst-case corner, and they're usually not the same one

Setup and Hold: Two Opposite Failure Modes on the Same Path

Setup and hold checks look at the exact same launch-capture register pair and the exact same data path between them — but they ask opposite questions, and confusing which one you're looking at wastes debug time fast.

Setup asks: did the data launched on this clock edge arrive at the capture register before the next capturing edge, with enough margin? A setup violation means the data path was too slow relative to the clock period.

Hold asks: did the data launched on this clock edge stay stable at the capture register long enough after the current edge, so the flop didn't accidentally latch the wrong value? A hold violation means the data path was too fast — the new value arrived and changed before the old one was safely captured.

Setup violations are frequency-dependent; hold violations are not. Slow the clock down and a setup violation can disappear, because you gave the data path more time to arrive before the next edge. A hold violation exists at any clock frequency, including a clock that never toggles again, because both the launch and capture edge are the same edge — it's a race condition on that one edge, not a period problem. This is why "just run it slower" fixes setup and does absolutely nothing for hold.

edge N edge N+1 LAUNCH FF COMBINATIONAL LOGIC Tcomb (data path delay) CAPTURE FF SETUP CHECK Tcq + Tcomb must finish before edge N+1, minus setup margin HOLD CHECK data must not change until safely after edge N Same data path, same registers — setup checks the far edge, hold checks the near one

Setup Violations: What the Report Is Telling You

A setup violation means the data path — clock-to-out of the launch register plus every gate and net delay to the capture register — didn't finish in time for the next capturing edge, after subtracting the library's required setup margin and any clock uncertainty. It's almost always about the data path being too slow, or the report's assumptions about the clock being wrong.

CauseFix
Long combinational path / too many logic levels between registersRestructure or reduce logic depth; consider retiming or adding a pipeline stage if the path is fundamentally too deep for one cycle
High-fanout net sitting on the critical pathBuffer or upsize the driving cell; reduce fanout by duplicating the driving logic if the load can be split
Optimistic clock uncertainty or jitter margin in the constraintsCorrect set_clock_uncertainty using real PLL jitter numbers instead of a placeholder default
Setup checked before clock-tree synthesis, using ideal/estimated clock latencyExpect setup slack to move once CTS is in and real clock-tree delay and skew are modeled — don't over-fix pre-CTS numbers as final
Missing or too-generous input/output delay constraint (set_input_delay / set_output_delay)Verify these against the real board or interface timing budget, not a placeholder value copied from another block
Register physically far from its fanin/fanout after placementCheck how much of the delay is routing versus logic; may need placement or floorplan guidance rather than a logic change
Reported worst path shouldn't be timed at all (missing exception)Confirm the path is real and exercised before spending an ECO on it — it may need a false_path or multicycle_path instead

Hold Violations: The Check Most Teams Under-Debug

Hold violations get less attention than setup because they don't show up in every simulation-minded engineer's mental model of "the clock is too fast." But an unfixed hold violation is arguably worse: it's a functional bug in silicon at any speed, and it can't be worked around by simply operating the chip slower.

CauseFix
Very fast (few-gate) data path with little or no clock skew to help itInsert deliberate delay buffers on the data path — the standard, well-understood hold fix
Useful skew applied to fix a setup violation, shrinking hold margin elsewhereRe-check hold on every register pair touched by a useful-skew or clock-tree change, not just the path that motivated it
Same-edge launch and capture registers physically adjacent with almost no logic between themCommon in register files and shift registers — treat hold as the primary risk there, not setup
Hold checked only at the setup-critical cornerHold is typically worst at the fast/low-temperature/high-voltage corner — a different corner than setup — make sure it's actually being run
Multicycle setup exception applied without the matching hold exceptionAdd the -hold version of the multicycle_path exception (usually one cycle less than the setup multiplier), or hold fails immediately at the default
On-chip variation (OCV) derate applied in the wrong direction for holdHold's pessimistic derate direction is the opposite of setup's — verify the STA setup applies OCV per-check-type correctly, not one flat derate everywhere

Constraints & Corners: When the Report Itself Is Wrong

A meaningful share of a first STA report isn't describing real timing problems at all — it's describing gaps or mistakes in how the design was constrained or which corners were run. Getting this right is what turns a report you can't trust into one with a short, real list of violations.

IssueWhat happensFix
Missing or wrong set_clock_groupsTwo clocks that are actually unrelated get analyzed as synchronous (masking a real crossing risk) or two related clocks get treated as asynchronous (flooding the report with meaningless violations)Declare every clock pair's true relationship explicitly — don't inherit a default from an unrelated block
Generated clock ratio wrong in create_generated_clockEvery downstream check on that clock is meaningless, in either directionVerify -divide_by / -multiply_by (and edge alignment) matches the actual RTL divider logic exactly
Missing set_case_analysis for mode-select pinsMutually exclusive paths (scan vs. functional, test vs. mission mode) get timed together as if both could be active at onceApply set_case_analysis per mode and sign off each mode's report separately
Un-modeled disabled timing arc (set_disable_timing)The tool reports a path through logic that can never actually toggle that way in any valid modeDisable arcs that are structurally guaranteed off, instead of leaving them to show up as false violations
Only one PVT corner analyzedWhichever corner is actually worst for setup or hold on a given path never gets checkedFull multi-corner signoff — every setup-critical corner and every hold-critical corner, not just typical
Flat/global OCV derate instead of AOCV or POCVMargin is either too pessimistic (over-designing, missing real performance) or too optimistic (missing a real risk), especially at advanced nodesUse stage-count-aware AOCV or path-based POCV derating instead of one global percentage everywhere
Over-broad false_path or multicycle_path exceptionA genuinely timing-critical path gets silently excluded from the report and nobody notices until it fails in siliconScope every exception to the narrowest possible startpoint/endpoint pair, and re-review exceptions at every RTL change

Reading a Timing Report Line by Line

A report_timing (or report_checks) dump looks intimidating mostly because it's unfamiliar, not because it's actually complicated. Every setup or hold report is built from the same two numbers compared against each other.

Report fieldWhat it tells you
Startpoint / endpointThe launch register (or input port) and capture register (or output port) that define this path
Path group / clock namesWhich clock launches the data and which clock captures it — for a setup check, the launch edge and the next capture edge; for hold, the same edge
Data arrival timeBuilt up from: clock source latency + clock network latency to the launch register + that register's clock-to-out (Tcq) + every cell and net delay through the combinational logic to the endpoint
Data required timeBuilt up from: the capture clock's edge time (period, for setup) + clock latency to the capture register − the library's setup (or + hold) requirement − clock uncertainty, adjusted for any useful skew
SlackRequired time minus arrival time for setup, or arrival minus required for hold. Negative slack is a violation; the magnitude tells you roughly how much delay needs to come out (or margin needs to be added)
Point / incr / path columnsEach stage's own delay (incr) and the running total (path) as the signal moves through the netlist — the biggest single incr jump is usually exactly which cell or net is dominating the path

Separate clock-path lines from data-path lines before proposing a fix. If the arrival or required time is dominated by clock source/network latency, the fix is a clock-tree or SDC change (useful skew, clock uncertainty, CTS rework) — not a data-path buffer. If it's dominated by cell/net delay through logic, it's the reverse. Fixing the wrong side of that split is one of the most common wasted ECO cycles in STA debug.

When Design Complexity Raises the Stakes

A few trends in current chip design make timing signoff meaningfully harder than the classic single-corner, single-voltage picture above, and are worth checking for explicitly.

TrendNew timing exposure
Multi-corner multi-mode (MCMM) signoffAdvanced designs can have dozens to hundreds of corner × mode combinations to sign off, not two or three — a clean report in one combination says nothing about the others
On-chip variation at advanced nodesBelow roughly 16nm, cell-to-cell variation is large enough that a single flat derate is actively wrong in both directions — needs AOCV or statistical (POCV) timing to stay accurate
Multi-voltage / DVFS domainsLevel shifters add their own timing checks at domain boundaries, and a domain's own timing view changes as its voltage scales — the same logical path can have a different worst corner depending on which voltage state it's in
High-speed SerDes / PLL-generated clocksAt multi-GHz interfaces, jitter, duty-cycle distortion, and clock-to-clock skew margins dominate over ordinary logic setup/hold, and typically need their own signoff methodology layered on top of standard STA

Triage Tactics: Working a Timing Report Without Losing a Week

  1. Split real timing violations from constraint problems before touching any RTL or running any ECO. A violation caused by a missing clock-group declaration needs an SDC fix, not a buffer — fixing it in RTL wastes the ECO and leaves the actual constraint bug in place.
  2. Check both setup and hold after every single ECO, on every relevant corner. A setup fix routinely creates a new hold violation nearby, and a hold fix can just as easily reopen setup — verify both, not just the one you were chasing.
  3. Read clock-path lines separately from data-path lines. Clock latency or skew problems need a clock-tree or SDC fix; data-path problems need a logic, sizing, or placement fix. Treating one as the other is one of the most common wasted debug cycles.
  4. Verify every timing exception is actually applying, not just written. A stale false_path or multicycle_path that no longer matches the current RTL hierarchy can silently stop applying and reintroduce a "surprise" violation with no code change nearby to blame.
  5. Don't over-fix pre-CTS setup numbers. Ideal or estimated clock latency before clock-tree synthesis routinely shifts once real clock-tree delay and skew are in the picture — treat early numbers as directional, not final.
  6. Confirm which PVT corner produced the worst number before proposing a fix. A fix that helps at the reported corner can make a different, unreported corner worse — check the full corner set, not just the one in front of you.
  7. Treat recovery/removal (asynchronous reset) violations as seriously as data setup/hold. An unsynchronized reset release is a real functional bug in silicon, not a report artifact to waive away.

Command names (create_clock, set_false_path, set_multicycle_path, report_timing) follow the industry-standard Synopsys Design Constraints (SDC) format used across static timing signoff tools; exact report formatting and flags vary between vendors — the underlying timing concepts described here are common across the industry's STA signoff practice.

Read the Setup & Hold Timing concept guide → CDC debug guide → STA interview questions → ← All Debug Guides