Timing, Hazards & Metastability
What breaks when logic meets a clock: setup and hold windows, propagation delay and clock skew, static and dynamic hazards, metastability and the synchroniser chain, switch debouncing, and arbitration between requesters that can collide.
Setup, Hold and the Timing Equations That Decide the Clock
A synchronous design works because every flip-flop sees stable data at every clock edge. Two inequalities guarantee that. The setup equation says the longest path between two registers must fit inside one clock period, which sets the maximum frequency. The hold equation says the shortest path must be long enough that new data does not arrive before the old is captured, and it contains no clock period at all - which is why a hold violation cannot be fixed by slowing down.
How it is built
- Setup: clock-to-Q plus the longest combinational delay plus the setup time must be no more than the clock period plus whatever skew helps. Everything on the left is fixed by the design; the period is what you solve for.
- Hold: clock-to-Q plus the shortest combinational delay must be at least the hold time plus any skew that hurts. The period is absent, which is the whole reason hold is a different kind of problem.
- Clock skew is the difference in arrival time of the same edge at two registers. Skew in the direction of data flow relaxes setup and tightens hold; against it, the reverse. It is not simply bad.
- Jitter is cycle-to-cycle variation in the edge, and unlike skew it always costs you - it must be subtracted from the available period regardless of direction.
- Slack is the margin: positive means the path passes, negative means it fails by that amount. Static timing analysis reports slack for every path, which is how a design is signed off without simulating.
- The critical path is the one with the least setup slack. Improving anything else changes nothing, which makes timing closure a matter of repeatedly finding and fixing one path.
Design procedure
- Establish the target period, then compute the setup budget: subtract clock-to-Q, setup time and jitter, and what remains is the logic budget.
- Count levels of logic on the longest path and multiply by the per-level delay to see whether the budget is plausible before synthesis.
- Fix setup failures by shortening the path: fewer logic levels, a faster structure such as carry-lookahead, or pipelining to split it across two cycles.
- Fix hold failures by adding delay to the short path - buffers - or by adjusting the clock tree. Never by changing the frequency.
- Check skew between related registers, particularly across a large die or a board, and treat clock distribution as a design task rather than a wire.
- Re-run analysis at both temperature and voltage extremes: setup is worst when slow and hold is worst when fast, so the two corners are different.
Key terms
- Setup time
- Data stable before the edge. Violation caps the frequency.
- Hold time
- Data stable after the edge. Violation is a race, independent of frequency.
- Clock-to-Q
- Delay from edge to output valid. Consumed from every period.
- Skew
- Arrival difference of one edge at two registers. Helps setup or hold, hurts the other.
- Jitter
- Cycle-to-cycle edge variation. Always costs margin.
- Slack
- Margin on a path. Negative means it fails by that amount.
- Critical path
- Least setup slack. The only path whose improvement raises the frequency.
- Timing corner
- A process, voltage and temperature combination. Setup fails slow, hold fails fast.
Worked example
A 100 MHz design has a 10 ns period. Clock-to-Q is 0.4 ns, setup is 0.3 ns and jitter is 0.2 ns, leaving 9.1 ns for logic. At 0.2 ns per level that allows about 45 levels, which is generous - so the design closes easily. Raise the target to 500 MHz and the period is 2 ns, the logic budget is 1.1 ns, and only five levels fit. Nothing about the logic changed; the same adder that was comfortable is now the critical path, and the fix is pipelining rather than a faster cell.Common pitfalls
Arbiters: Deciding Who Gets the Shared Resource
When several requesters want one resource, something must choose between them, and that something is an arbiter. The choice looks trivial and is not: the arbitration policy determines whether every requester eventually gets service, whether a burst from one starves the others, and what the worst-case wait is. Those are the properties a system-level timing argument rests on, and they follow from the policy rather than from the implementation.
How it is built
- Fixed priority always grants the highest-priority requester. It is the smallest and fastest arbiter and it can starve low-priority requesters indefinitely if a high-priority one is persistent.
- Round-robin grants in rotation, so every requester is served within one full rotation. That bounded wait is what makes it fair, and it costs a pointer register and a rotation of the priority.
- Least-recently-used grants to whoever has waited longest. It is fairer still and needs state proportional to the number of requesters, which is why it appears in caches more than in bus arbiters.
- Weighted schemes give some requesters more turns than others, which is how quality of service is implemented - a display controller that must not underrun gets more slots than a background DMA.
- A grant must be mutually exclusive by construction: exactly one at a time, guaranteed by the logic rather than by convention. Two grants at once is a bus contention, not a fairness problem.
- The arbiter's own delay sits in every transaction's latency, so a complex policy on a fast bus becomes the bottleneck it was meant to manage.
Design procedure
- State the requirement first: is the need fairness, bounded latency, or throughput? Those lead to different policies and the choice is not interchangeable.
- Use fixed priority only where starvation is genuinely acceptable, or where a low-priority requester provably cannot be blocked for long.
- Use round-robin as the default. Its worst-case wait is one rotation, which is a number that can be stated and checked.
- Compute the worst-case wait for each requester under the chosen policy, and compare it against what that requester can tolerate before it underruns or overflows.
- Verify mutual exclusion structurally rather than by testing - exactly one grant must be possible at a time by construction.
- Check the arbiter's own delay against the transaction rate, since it is added to every access.
Key terms
- Fixed priority
- Highest requester always wins. Smallest, and can starve.
- Round-robin
- Rotation. Worst-case wait is one full rotation.
- Starvation
- A requester never served. The failure fixed priority permits.
- Fairness
- Every requester served within a bounded time.
- Weighted arbitration
- Unequal shares, which is how quality of service is built.
- Mutual exclusion
- Exactly one grant at a time, guaranteed structurally.
- Arbitration latency
- The arbiter's own delay, added to every transaction.
Worked example
A memory controller serves a CPU, a display controller and a DMA engine. Under fixed priority with the CPU highest, a tight CPU loop can hold the bus indefinitely and the display underruns - which appears on screen as tearing, and looks like a display problem. Round-robin bounds every requester's wait to two other transactions, so the display is guaranteed service. The display actually needs more than an equal share, so the practical answer is weighted: the display gets a guaranteed slot every N cycles and the CPU and DMA share the rest.Common pitfalls
Debouncing: Making a Mechanical Contact Look Digital
A mechanical switch does not close cleanly. The contacts strike, separate and strike again for a few milliseconds, so a single press produces tens of transitions. Digital logic is fast enough to see every one of them, so a counter increments twenty times per press and an interrupt fires repeatedly. Debouncing is imposing the assumption that the input is stable - either by waiting for it to settle, or by filtering, or by making the switch itself unambiguous.
How it is built
- Bounce duration is a mechanical property, typically 1 to 20 ms depending on the switch. It is not noise and does not diminish with a better power supply; the contacts are genuinely opening and closing.
- A counter-based debouncer requires the input to hold a new value for N consecutive samples before accepting it. It is the standard digital approach and its latency is exactly N sample periods.
- An RC filter plus a Schmitt trigger does it in analog: the capacitor slows the transition and the hysteresis converts the slow edge back into a clean one. Without the Schmitt trigger a slow edge through an ordinary input oscillates.
- A single-pole double-throw switch with an SR latch debounces perfectly, because the latch sets on the first contact with one throw and cannot change until the other throw is touched. Bounce on either contact is ignored after the first.
- Latency and robustness trade directly. A longer window rejects more bounce and delays the response, and above about 50 ms the delay becomes perceptible to a person.
- Release usually bounces differently from press, and some designs debounce them with different windows - fast press for responsiveness, slower release to reject a momentary opening.
Design procedure
- Measure the actual bounce with a scope or a logic analyser rather than assuming. Switches differ by an order of magnitude and the datasheet figure is often optimistic.
- Choose the debounce window as several times the observed bounce, and check the resulting latency is acceptable to whatever is watching.
- Sample at a fixed rate from a timer rather than in a busy loop, so the window is a defined time rather than a function of how busy the processor is.
- Never attach an interrupt directly to an undebounced switch. The bounce produces a burst of interrupts, and at the wrong moment that can overflow a queue.
- For a rotary encoder, debounce both signals and decode the quadrature afterwards - debouncing after decoding loses counts.
- Test by pressing slowly and partially, which produces the worst bounce, rather than with clean deliberate presses.
Key terms
- Bounce
- Repeated make and break as contacts settle. Typically 1-20 ms.
- Debounce window
- How long the input must be stable before it is believed.
- Schmitt trigger
- Input with hysteresis. Converts a slow edge into a clean one.
- Hysteresis
- Different thresholds for rising and falling. What prevents oscillation.
- SPDT + SR latch
- Perfect debounce in hardware, using the switch's second throw.
- Sample period
- The debouncer's tick. Window latency is N times this.
- Quadrature
- Two phase-shifted signals giving direction. Debounce before decoding.
Worked example
A pushbutton on a GPIO with a falling-edge interrupt fires eleven times on one press. The counter it increments jumps by eleven, which reads as a software bug in the counter. Adding a 20 ms counter-based debouncer - the input must read the same value for twenty consecutive 1 ms samples - reduces it to exactly one event, at the cost of 20 ms of latency that no user can perceive. The scope trace shows the eleven transitions plainly, and no amount of reading the firmware would have.Common pitfalls
Hazards and Glitches: When Correct Logic Still Misbehaves
A hazard is a momentary incorrect output during an input transition, in a circuit whose logic is correct at every stable input. It happens because real gates have delays that differ, so during a change one path is briefly ahead of another. A static hazard is a pulse where the output should have held steady; a dynamic hazard is multiple transitions where there should have been one. Neither is a logic error, which is what makes them hard to find by reasoning about the equations.
How it is built
- A static-1 hazard occurs where two adjacent input combinations both give an output of 1, but are covered by different product terms. As the input moves between them, one AND gate turns off before the other turns on and the OR's output dips.
- On a Karnaugh map the condition is visible: two adjacent 1s in different groups with no group containing both. Wherever a cover hands over between terms, there is a potential hazard.
- The fix is the consensus term - a redundant product covering both cells. It is logically unnecessary and physically essential, because it holds the output high throughout the handover.
- A minimal cover therefore is not always the right cover. Karnaugh minimisation optimises gate count and has no model of delay, so the smallest circuit is sometimes the one that glitches.
- A dynamic hazard is multiple output changes when one was expected, and requires three or more paths of differing delay. It cannot occur in a two-level circuit, which is one argument for keeping logic shallow.
- Whether a hazard matters depends entirely on what reads the output. Registered into a flip-flop, a glitch that settles before setup time is invisible. Feeding a clock, an asynchronous reset, or an edge-sensitive input, it causes a real fault.
Design procedure
- Identify where the output feeds. A glitch into combinational logic that is subsequently registered is harmless; into a clock or asynchronous input it is not, and only then is a hazard worth fixing.
- On the Karnaugh map, look for adjacent 1s in different groups with no group covering both - that adjacency is the hazard condition.
- Add the consensus term to bridge each such handover. It costs one gate and is the standard fix.
- Prefer synchronous design generally: registering combinational outputs makes the whole class of problem irrelevant, which is why hazards matter far less than they once did.
- Never generate a clock from combinational logic. A gated or decoded clock carries every hazard on its inputs directly into the clock tree.
- Simulate with delays rather than at zero delay. A zero-delay functional simulation cannot show a hazard at all, which is why they survive to hardware.
Key terms
- Static-1 hazard
- A momentary 0 where the output should have stayed 1.
- Static-0 hazard
- The dual: a momentary 1 in a steady 0.
- Dynamic hazard
- Several transitions where one was expected. Needs three or more paths.
- Consensus term
- A redundant product bridging two groups. The standard fix.
- Cover handover
- Where responsibility passes between product terms. Where hazards live.
- Zero-delay simulation
- Cannot show hazards, because it has no delay model.
- Gated clock
- A clock through combinational logic. Carries every glitch into the clock tree.
Worked example
F = A'C + AB, with B and C both high, and A changing from 0 to 1. Before the change A'C holds the output high; after it AB does. In between, the inverter feeding A'C has not yet propagated while AB's AND has already seen A rise - or the reverse - and for the difference in those delays neither term is asserting. The output dips, briefly, in a circuit that is correct at both endpoints. Adding BC, which is high throughout because both are high, holds the output up during the handover. One extra AND gate, and the glitch is gone.Common pitfalls
Setup, hold, and what a timing budget actually contains
A flip-flop needs its input stable for a window around the clock edge: setup time before, hold time after. Every synchronous design is the claim that both are satisfied on every path, and static timing analysis is the process of proving it. The two constraints fail in opposite directions - setup is violated by a path that is too slow, hold by one that is too fast - which is why a slower clock fixes one and can never fix the other.
How it is built
- Setup: data must arrive at least t_su before the capturing edge. The available time is the clock period minus the launch delay, the logic delay and the setup requirement.
- Hold: data must remain stable at least t_h after the edge, so the path must be slow enough not to overwrite the value being captured.
- Clock skew is the difference in clock arrival time between two flip-flops; it adds to the setup budget in one direction and subtracts from hold in the other.
- Clock jitter is cycle-to-cycle variation in the edge position and is deducted from the setup budget as pure loss.
- Slack is the margin: positive means the constraint is met, negative is by how much it failed.
Design procedure
- Compute setup slack as period minus (clock-to-Q + logic delay + setup) plus skew, and require it positive at the slow corner.
- Compute hold slack as (clock-to-Q + logic delay) minus (hold + skew), and check it at the fast corner - the opposite corner from setup.
- Fix setup failures by shortening logic, adding pipeline stages, or lowering the clock frequency.
- Fix hold failures by adding delay to the data path; lowering the clock does nothing, because hold has no period term.
- Analyse both corners, since a design that passes setup at the slow corner can fail hold at the fast one.
Key terms
- Setup time
- How long data must be stable before the clock edge.
- Hold time
- How long data must remain stable after the clock edge.
- Clock-to-Q
- The delay from the clock edge to the flip-flop's output changing.
- Skew
- Difference in clock arrival between two flip-flops. Helps one constraint and hurts the other.
- Slack
- Margin against a constraint. Negative slack is a failure and its magnitude is the shortfall.
Worked example
The two budgets, and why they need different corners:
SETUP T >= t_cq + t_logic + t_su - t_skew
T = 10 ns, t_cq = 0.4, t_logic = 8.2, t_su = 0.3, skew = 0.2
slack = 10 - (0.4 + 8.2 + 0.3) + 0.2 = +1.3 ns PASS
HOLD t_cq + t_logic >= t_h + t_skew
same path, t_h = 0.15
0.4 + 8.2 = 8.6 >= 0.15 + 0.2 = 0.35 PASS easily
Now a short path, t_logic = 0.05 ns:
0.4 + 0.05 = 0.45 >= 0.35 PASS, barely
at the fast corner t_cq drops to 0.2 and skew rises to 0.3:
0.2 + 0.05 = 0.25 >= 0.15 + 0.3 = 0.45 FAIL
Note there is no T in the hold equation. Halving the clock speed
changes nothing, which is why a hold violation cannot be fixed by
running slower and must be fixed by adding delay.Common pitfalls
Hazards and glitches: correct logic with a wrong output
A hazard is a momentary incorrect output produced by a combinational circuit whose steady-state behaviour is entirely correct. It happens because signals take different paths of different lengths to the same gate, so during a transition the gate briefly sees a combination that the settled inputs never produce. In a fully synchronous design the glitch settles before the next clock edge and does no harm; anywhere it reaches an asynchronous input, it is a real fault.
How it is built
- A static-1 hazard is a momentary 0 on an output that should stay 1 throughout the transition; static-0 is the reverse.
- A dynamic hazard is an output that changes more than once when it should change exactly once, and needs three or more paths of differing delay.
- The cause is unequal path delays, so a hazard is a property of the implementation rather than of the function.
- A static hazard in a sum-of-products expression is removed by adding the consensus term covering the transition, at the cost of the gate that minimisation removed.
- Synchronous design is the general answer: sample only at clock edges, and require settling within the period.
Design procedure
- Assume any combinational output can glitch, and design so that nothing samples it except a clock edge.
- Where a combinational output must drive an asynchronous input - a reset, an enable, a clock - register it first.
- Where a glitch-free combinational output is genuinely required, add the consensus terms and accept the larger circuit.
- Never gate a clock with combinational logic; use a clock enable on the flip-flop instead.
- Look for hazards on the Karnaugh map: a transition between two adjacent groups with no group covering both is where one lives.
Key terms
- Static-1 hazard
- A brief 0 on an output that should remain 1 across an input change.
- Dynamic hazard
- Multiple transitions where one was expected. Requires three or more unequal paths.
- Consensus term
- The redundant product that covers the transition between two adjacent groups, removing the hazard.
- Glitch
- The observable pulse a hazard produces.
- Clock gating
- Gating a clock with logic. A classic source of glitches on the clock itself; use a clock enable instead.
Worked example
The hazard, and the term that removes it:
Y = AB + A'C
With B = C = 1, changing A from 1 to 0:
A=1: Y = 1·1 + 0·1 = 1
A=0: Y = 0·1 + 1·1 = 1 steady state 1 both sides
But the inverter that produces A' has delay. Momentarily A is 0
AND A' is still 0:
Y = 0·1 + 0·1 = 0 a static-1 hazard
Adding the consensus term BC:
Y = AB + A'C + BC
With B = C = 1 the BC term holds the output at 1 throughout the
transition, regardless of what A and A' are doing.
The minimiser removed BC because it is logically redundant. It is redundant to
the function and necessary to the implementation, which is the whole reason a
synthesis tool has a separate hazard-free mode.Common pitfalls
Metastability and the synchroniser
When a flip-flop's setup or hold window is violated - which is guaranteed to happen eventually for any signal not derived from the same clock - it can enter a metastable state where its output sits between valid logic levels for an unbounded time. It cannot be prevented, only made improbable, and the entire discipline of clock domain crossing exists to make its probability small enough that it will not happen in the product's lifetime.
How it is built
- A metastable flip-flop resolves eventually, but the resolution time is a random variable with an exponential tail and no hard bound.
- A two-flip-flop synchroniser gives the first stage most of a clock period to settle before the second samples it.
- Mean time between failures grows exponentially with the settling time allowed, which is why one extra stage buys orders of magnitude.
- A synchroniser only works for a single bit. Multiple bits synchronised independently can be captured from different cycles, giving a value that never existed.
- Multi-bit crossings therefore need Gray coding, a handshake, or an asynchronous FIFO - not a wider synchroniser.
Design procedure
- Put a two-flip-flop synchroniser on every asynchronous single-bit input, without exception.
- Never synchronise a multi-bit bus bit by bit; use Gray coding if it is a counter, or a handshake or FIFO otherwise.
- Compute the MTBF from the clock frequency, the data rate and the library's metastability constants, and check it against the product's lifetime.
- Add a third stage where the MTBF calculation demands it, typically at high clock rates or high crossing rates.
- Mark synchroniser paths as false paths for timing analysis, since the first stage's setup violation is expected by design.
Key terms
- Metastability
- A flip-flop output resting between valid levels for an unbounded time after a timing violation.
- Resolution time
- How long the flip-flop takes to settle. Random, exponentially distributed, unbounded.
- MTBF
- Mean time between synchronisation failures. Grows exponentially with settling time allowed.
- CDC
- Clock domain crossing: any path between two unrelated clocks.
- False path
- A path deliberately excluded from timing analysis, because the violation is expected and handled.
Worked example
Why one flip-flop is not enough, and why two bits are worse than one:
ONE STAGE
async input violates setup -> Q is metastable
downstream gates sample an undecided level and may DISAGREE
about whether it is 0 or 1, so the design forks internally
TWO STAGES
stage 1 goes metastable, has a full clock period to settle
stage 2 samples a settled value
MTBF goes from seconds to millions of years for the same part
TWO BITS, EACH SYNCHRONISED SEPARATELY
bus changes 01 -> 10, both bits crossing
bit 0 resolves this cycle, bit 1 resolves next cycle
the receiver sees 00 or 11 - values the transmitter never sent
This is the failure a wider synchroniser cannot fix, because each
bit is individually correct. Gray coding removes it by ensuring
only one bit ever changes; a handshake removes it by ensuring the
bus is stable before it is sampled.Common pitfalls
Debouncing and arbitration
Two practical problems that both come down to imposing order on inputs that have none. A mechanical switch does not make a clean transition; it bounces for several milliseconds, and a fast digital input will count every bounce as a separate event. Arbitration is the same problem between requesters: several may assert at once, and something must choose one and guarantee the others are eventually served.
How it is built
- Switch bounce typically lasts 1 to 20 ms and produces tens of transitions; the exact figure is a property of the switch and changes as it wears.
- A counter-based debouncer accepts a new level only after it has been stable for a defined number of samples, which is the standard digital approach.
- An RC filter plus a Schmitt trigger debounces in hardware, with hysteresis providing the noise immunity the sharp threshold lacks.
- Fixed-priority arbitration always grants the highest-priority requester, which is simple and can starve the lowest indefinitely.
- Round-robin arbitration rotates the priority after each grant, which bounds the wait for every requester at the cost of more state.
Design procedure
- Sample the switch at a fixed rate and require N consecutive identical samples before accepting a change; N times the sample period must exceed the worst-case bounce.
- Debounce press and release separately if their bounce characteristics differ, which they often do.
- Choose fixed priority only where starvation is genuinely acceptable, and document that decision.
- Choose round-robin where fairness matters, and verify the grant is held for exactly the transaction and no longer.
- Synchronise every asynchronous request into the arbiter's clock domain before arbitrating, or the arbiter itself can go metastable.
Key terms
- Bounce
- Rapid make-break transitions as a mechanical contact settles. Milliseconds, dozens of edges.
- Schmitt trigger
- An input with hysteresis: different thresholds for rising and falling, so a noisy edge produces one clean transition.
- Fixed priority
- Always grant the highest-priority requester. Simple, can starve the lowest.
- Round robin
- Rotate priority after each grant, bounding every requester's wait.
- Starvation
- A requester never granted because higher-priority ones keep asserting.
Worked example
The counter debouncer, and the number that sizes it:
sample every 1 ms, require 10 stable samples
-> a change is accepted only after 10 ms of stability
-> bounce up to 10 ms is rejected
-> the cost is 10 ms of added latency, which is imperceptible
for a button and unacceptable for an encoder
if (raw == stable) {
count = 0;
} else if (++count >= 10) {
stable = raw;
count = 0;
}
And the fairness difference, four requesters all asserting continuously:
FIXED PRIORITY grant sequence: 0 0 0 0 0 0 0 0 ...
requesters 1-3 are never served
ROUND ROBIN grant sequence: 0 1 2 3 0 1 2 3 ...
every requester waits at most 3 grants
Fixed priority is not wrong - an emergency stop should preempt everything. It
is wrong when it is chosen by default rather than deliberately.Common pitfalls
More in Digital Electronics
- Combinational BlocksEvery combinational building block in one place: multiplexers and demultiplexers, encoders and priority encoders, decoders and address decoding, and the arithmetic circuits from half adder through carry-lookahead. Each with a live explorer and the propagation-delay cost that decides which one you use.
- Sequential DesignStorage and state: latches against flip-flops, the D/T/JK families and how they convert, counters and clock dividers, shift registers and serial conversion, and the Moore/Mealy state machine encodings, with a live stepper for each.
- Boolean Algebra & GatesBoolean algebra, the gate set it maps onto, and Karnaugh-map minimisation: the identities that let an expression be rewritten, why NAND and NOR are functionally complete, how a truth table becomes a minimal sum of products, and where don't-care terms come from in real designs.
- Logic Levels & InterfacingThe electrical contract under the logic: threshold voltages and noise margins across TTL, CMOS and LVCMOS families, level shifting and open-drain interfacing, fan-out and drive strength, and where dynamic and static power actually goes.
- Digital ElectronicsGates, Boolean algebra, K-maps, muxes, encoders, decoders, flip-flops, arithmetic circuits, counters and debouncing.