Hardware Engineering · FPGAs
Static Timing Analysis: Slack, Corners, and Uncertainty
How a timing graph is built from the netlist, what setup and hold slack mean at the two ends of a path, and why the report is only as trustworthy as its corner and derate assumptions.
Timing closure in an FPGA is an accounting exercise repeated over every path in the design. The tool builds a graph from the registers and the combinational logic between them, assigns a delay to every element, and checks that no path takes longer than its clock period allows or shorter than the register’s hold requirement permits. The output is a single number per path, slack, and the entire discipline of meeting timing reduces to making that number non-negative everywhere, at every operating condition the device is specified for.
Building the graph
The graph’s vertices are the timing points: register outputs, register data inputs, primary inputs and outputs, and the pins of memory and arithmetic blocks. Its edges are the combinational elements: lookup tables, carry chains, the routing between them, and the dedicated paths inside hardened blocks. Each edge carries a delay, and the delay depends on which corner the analysis is running at.
A path starts at a launching register’s clock-to-out and ends at a capturing register’s setup or hold requirement. Between them sits the sum of edge delays. The clock reaches both registers through the clock network, with its own insertion delay to each, and the difference is skew. The available time is the clock period, minus the setup requirement, minus the clock-to-out, minus uncertainty, plus or minus skew.
Two path classes are checked. Setup, or maximum delay, asks whether the data arrives before the capturing clock edge. Hold, or minimum delay, asks whether the data does not arrive so early that it overwrites the value the capturing register should have kept. The second is the one that surprises people, because it gets worse when a path gets faster, and because it cannot be fixed by slowing the clock down.
Why there are corners
Delay in silicon is not a single number. It varies with process variation across the die, with supply voltage, and with temperature. A path built from fast transistors at high voltage and low temperature is fast; the same path at low voltage and high temperature is slow, though at advanced nodes with low supply voltage the temperature term can invert, so which corner is worst is a property of the device family. The spread is large enough that a design verified at one condition says nothing about another.
Static timing analysis handles this with corners: combinations of process, voltage, and temperature at which the delays are characterized. The slow corner is used for setup checks, because a slow path against a fixed clock period is the worst case for arriving too late. The fast corner is used for hold checks, because a fast path is the worst case for arriving too early. Some tools add a low-voltage corner and a high-temperature corner separately, and the on-chip supply may itself be a corner, since the core voltage regulator’s output is specified with tolerance.
The consequence for the designer is that a slack number is meaningless without its corner. A report that says the worst setup slack is positive at the slow corner, and the worst hold slack is positive at the fast corner, is the statement that matters. A report at a nominal corner is a midpoint, not a guarantee.
Process variation across a single die is handled by derating: on-chip variation (OCV) applies a margin to delays depending on path depth, so that a launching path is assumed slower and a capturing path faster, or vice versa, depending on which combination is pessimistic. Advanced nodes add statistical treatment and path-based derating, but the principle is the same: the analysis deliberately assumes the worst combination that the silicon could produce, and the resulting pessimism is removed only where it can be shown to be impossible.
Slack arithmetic on a real path
Consider a path from register A to register B at 200 MHz, so the period is 5 ns. Register A has a clock-to-out of 0.4 ns. The combinational logic and routing between them sum to 3.1 ns. Register B needs 0.2 ns of setup time before its clock edge. The clock reaches B 0.05 ns later than it reaches A, so the skew helps setup by 0.05 ns. The clock constraint carries 0.15 ns of uncertainty.
The available time is $5 - 0.2 + 0.05 - 0.15 = 4.7$ ns. The required time at the end of the data path is that value; the arrival time is $0.4 + 3.1 = 3.5$ ns. Slack is $4.7 - 3.5 = 1.2$ ns, so the path meets with room to spare. At 400 MHz, the period halves to 2.5 ns and the available time becomes 2.2 ns, so slack turns negative by 1.3 ns. Nothing about the logic changed; the budget did.
This is why frequency is the wrong variable to optimize first. Moving from 200 to 400 MHz does not require halving every delay; it requires removing 1.3 ns from the worst path, and the same 1.3 ns from every path that was between 2.2 and 3.5 ns. Paths with large positive slack are irrelevant, and the design’s achievable frequency is set by the small set of paths with the least margin.
Reading the report
The summary section of a timing report lists the worst paths per clock group, with a breakdown per path: logic delay, route delay, the percentage that is routing, and the number of logic levels. The percentages are the diagnostic. A path that is 80 percent routing is a placement problem; a path with many logic levels is an RTL problem; a path that is mostly one long net is a floorplanning problem. The remedy differs in each case, and applying the wrong one wastes a build cycle.
Two report details are commonly misread. The first is the difference between estimated and actual delay. Before place and route, the tool estimates routing delay from fanout and congestion statistics. Those estimates can be optimistic, particularly on long nets and high-fanout signals, and the gap between synthesis estimates and post-route results is the reason a design that “met timing” after synthesis can fail after implementation. The only report that reflects the hardware is the post-route one.
The second is the treatment of unconstrained paths. A path with no timing requirement is not reported as failing; it is reported as unconstrained, or ignored. A design with an incomplete constraint set can therefore produce a clean report while containing paths that will fail at speed. The count of unconstrained endpoints is the number to check, and it belongs to the constraint discipline described in timing constraints and clock definitions.
Hold, and why it fails late
Hold violations are rare in a design that meets setup, because a path long enough to meet setup at a given frequency is usually long enough not to violate hold. They appear in specific circumstances: a very short path between two registers, a path through a hardened block with a small delay, a clock with large skew between two regions, or a design that has been aggressively retimed.
# Worst hold (minimum-delay) paths, one report per endpoint.
report_timing -delay_type min -max_paths 20 -sort_by slack -input_pins
Hold is also where the tool’s pessimism has the largest effect. The capturing register’s clock is assumed to arrive as early as possible and the launching register’s as late as possible, which maximizes the apparent earliness of the data. On a design with substantial clock skew, hold checks can fail on paths with almost no logic, and the fix is not to add delay but to change the clocking or the placement.
Because hold gets worse at the fast corner and setup at the slow, a design must be checked at both, and a fix for one can hurt the other. Adding delay to a short path to fix hold increases its setup delay, which matters only if the path was near the setup limit. Since hold-failing paths are by definition short, the two rarely conflict, but the interaction is why timing closure is iterative rather than a single pass.
Where static analysis stops
Static timing analysis proves that the graph’s delays satisfy the constraints. It does not prove that the constraints describe the intended behaviour. A path constrained as a false path, excluded because the logic makes it impossible, is not analysed at all, and if the exclusion is wrong the design fails in hardware while the report stays clean. Every exception in the constraint file is a claim about the design’s behaviour, and it is the claim, not the arithmetic, that carries the risk.
The analysis also assumes a single clock edge relationship per path. Asynchronous crossings have no meaningful setup requirement, and multicycle paths have a requirement that is a multiple of the period, and both must be declared. The construction and verification of those declarations is the subject of clock domain crossing. What remains after all the declarations is the part of the design that static analysis can actually speak about, and that part is smaller than the total path count suggests.
References
- Algorithms for VLSI Design Automation — Sabih H. Gerez, Wiley, 1999
- Vivado Design Suite User Guide: Using Constraints (UG903) — Xilinx / AMD
- Static Timing Analysis for Nanometer Designs: A Practical Approach — J. Bhasker and Rakesh Chadha, Springer, 2009