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.
| Category | What the report shows | Where to look |
|---|---|---|
| Setup | A reg2reg path shows negative slack, endpoint deep in a combinational cloud | Count logic levels and fanout on the failing path; check which PVT corner produced the number and whether clock uncertainty is realistic |
| Setup | Same failing path keeps reappearing after a placement-only ECO | A real fix needs sizing, buffering, or restructuring/pipelining — check whether slack actually improved or the path just moved |
| Hold | Hold violation appears only at the best-case (fast) corner | Classic launch/capture skew or a too-fast min-delay path — confirm which corner is reported, it's rarely the same one setup fails at |
| Hold | New hold violations appear right after a setup fix on the same path | The setup fix (buffer/upsize) shortened the path just enough to break hold at the fast corner — re-check hold after every setup ECO |
| Clock definition | Two clocks are analyzed as synchronous but you expected them asynchronous, or the reverse | Missing or wrong set_clock_groups / generated-clock ratio — verify the SDC clock relationships explicitly, don't assume a default |
| Exceptions | A path you know is functionally safe still shows a huge violation | Needs an explicit false_path or multicycle_path exception — or already has one that's stale and no longer applying |
| Exceptions | A multicycle setup exception is applied, and hold now fails on that same path | Missing the matching -hold multicycle exception — the default hold multiplier is not the same as the setup one |
| Report reading | A path you expect to see is simply missing from the report | It's likely unconstrained, not passing — check coverage (every register pair should be reachable by some clock/constraint) before trusting a clean report |
| Recovery/removal | Async reset release flagged as a recovery violation | Reset de-assertion is landing too close to a clock edge — needs a synchronized release, same root cause as a reset-domain-crossing bug |
| Corners | Design is clean at the typical corner, fails at a PVT extreme | Only 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.
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.
| Cause | Fix |
|---|---|
| Long combinational path / too many logic levels between registers | Restructure 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 path | Buffer 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 constraints | Correct set_clock_uncertainty using real PLL jitter numbers instead of a placeholder default |
| Setup checked before clock-tree synthesis, using ideal/estimated clock latency | Expect 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 placement | Check 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.
| Cause | Fix |
|---|---|
| Very fast (few-gate) data path with little or no clock skew to help it | Insert deliberate delay buffers on the data path — the standard, well-understood hold fix |
| Useful skew applied to fix a setup violation, shrinking hold margin elsewhere | Re-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 them | Common in register files and shift registers — treat hold as the primary risk there, not setup |
| Hold checked only at the setup-critical corner | Hold 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 exception | Add 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 hold | Hold'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.
| Issue | What happens | Fix |
|---|---|---|
| Missing or wrong set_clock_groups | Two 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_clock | Every downstream check on that clock is meaningless, in either direction | Verify -divide_by / -multiply_by (and edge alignment) matches the actual RTL divider logic exactly |
| Missing set_case_analysis for mode-select pins | Mutually exclusive paths (scan vs. functional, test vs. mission mode) get timed together as if both could be active at once | Apply 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 mode | Disable arcs that are structurally guaranteed off, instead of leaving them to show up as false violations |
| Only one PVT corner analyzed | Whichever corner is actually worst for setup or hold on a given path never gets checked | Full multi-corner signoff — every setup-critical corner and every hold-critical corner, not just typical |
| Flat/global OCV derate instead of AOCV or POCV | Margin is either too pessimistic (over-designing, missing real performance) or too optimistic (missing a real risk), especially at advanced nodes | Use stage-count-aware AOCV or path-based POCV derating instead of one global percentage everywhere |
| Over-broad false_path or multicycle_path exception | A genuinely timing-critical path gets silently excluded from the report and nobody notices until it fails in silicon | Scope 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 field | What it tells you |
|---|---|
| Startpoint / endpoint | The launch register (or input port) and capture register (or output port) that define this path |
| Path group / clock names | Which 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 time | Built 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 time | Built 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 |
| Slack | Required 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 columns | Each 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.
| Trend | New timing exposure |
|---|---|
| Multi-corner multi-mode (MCMM) signoff | Advanced 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 nodes | Below 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 domains | Level 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 clocks | At 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
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.