JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

The Clock Network: Skew, Clock Tree Synthesis and Useful Skew

Until now we treated the clock as a perfect metronome that taps every flip-flop at the exact same instant. It isn't. The clock has to travel through millions of microns of wire and hundreds of buffers, and it arrives at different flops at slightly different times — that mismatch is **clock skew**, and it can quietly steal your margin or, used wisely, hand some back. This guide follows the clock from the pin to the registers, shows why skew helps setup but hurts hold, and ends with the deliberate art of **useful skew**.

The metronome that lies

Picture an orchestra of a billion musicians. The conductor raises the baton, and on the downbeat every player is supposed to strike at once. In a synchronous chip the clock is that baton, and the flip-flops are the players. In rung 3 we computed slack assuming the launch flop and the capture flop both felt the downbeat at the very same picosecond. That assumption was a convenient lie.

The downbeat does not teleport. It leaves the clock pin as an edge, charges and discharges wire after wire, and passes through a long chain of buffers before it reaches any given flop. A flop tucked in the corner of a 20 mm² die might see the rising edge 80–150 ps later than a flop near the clock source. The difference in arrival time of the *same* clock edge at two different flops is clock skew.

clk pin ──▶[buf]──▶[buf]──▶[buf]──┬──▶ FF_A  (launch)   edge @ t = 110 ps
                                  │
                                  └──▶[buf]──▶ FF_B  (capture)  edge @ t = 165 ps

   skew(A→B) = T_capture_clk − T_launch_clk = 165 − 110 = +55 ps
   (capture clock arrives LATER than launch clock  →  positive skew)
Skew is always defined for a *pair* of flops on a path: capture-arrival minus launch-arrival.

Positive skew helps setup, hurts hold

Here is the beautiful asymmetry that makes the whole topic worth a guide. When the capture clock arrives *later* than the launch clock — positive skew — the data has been given extra time to arrive before it gets sampled. Positive skew literally pushes the deadline back. That is pure gift to a setup check.

SETUP  (must arrive BEFORE the next capture edge):

  slack_setup = T_clk + skew − T_cq − T_logic − T_setup
                        ^^^^
              positive skew ADDS to the budget  ✓ easier

HOLD  (must NOT change too soon after the SAME capture edge):

  slack_hold  = T_cq + T_logic − T_hold − skew
                                          ^^^^
              positive skew SUBTRACTS from the budget  ✗ harder
One sign flip is everything: positive skew adds to setup slack but subtracts from hold slack.

Why does hold swing the other way? Hold asks a different question. It isn't about the *next* edge; it's about the *same* edge. New data launched on edge N must not race through the logic and corrupt what the capture flop is trying to grab on that very same edge N. If the capture clock is late (positive skew), the capture flop's window stays open *longer* into the future — and the freshly launched data has more time to sneak in and clobber it. So the exact thing that rescues setup is what wrecks hold.

Clock tree synthesis: building the baton

If skew is the enemy of hold and an unreliable friend of setup, the obvious instinct is: make skew zero everywhere. Deliver the edge to all million flops at the same instant. The step that attempts this is clock tree synthesis, or CTS, run during physical implementation right after placement.

You cannot drive a million flops from one buffer — the load capacitance would crush the slew and the edge would arrive as a mushy ramp. So CTS grows a *tree*: the clock root fans out to a few buffers, each of those to a few more, branching down through perhaps 10–18 levels until the leaves are the flop clock pins. The art is to make every root-to-leaf path take the *same* delay, so all leaves see the edge together.

                       ┌─[buf]─┬─▶ FF
            ┌─[buf]──┤         └─▶ FF
            │         └─[buf]─┬─▶ FF
clk root ─[buf]                └─▶ FF
            │         ┌─[buf]─┬─▶ FF
            └─[buf]──┤         └─▶ FF
                       └─[buf]─┴─▶ FF

  Goal: every root→leaf path = equal delay  →  skew ≈ 0
  Knobs: balanced fanout, matched wire length, buffer sizing,
         shielding, sometimes an H-tree or clock mesh for the spine
A balanced clock tree: insertion delay is large, but the *difference* (skew) between leaves is driven toward zero.
  1. Cluster the flops geographically so nearby leaves share a branch.
  2. Build the tree, inserting and sizing clock buffers to balance path delays.
  3. Balance — tune wire detours and buffer strengths so all leaves land within a tight skew target.
  4. Optimize for power and signal integrity: clocks toggle every cycle, so the tree is often 30–40% of total dynamic power; shield it against crosstalk and watch its slew.

Clock uncertainty: the margin you hold in reserve

Even after a beautiful CTS run, you cannot promise the skew you measured in the tool is exactly what silicon will deliver. Buffers vary with process, voltage and temperature. The clock source itself wobbles. Crosstalk nudges edges. So STA refuses to bet the whole budget on a nominal number — it sets aside a deliberate pad called clock uncertainty.

set_clock_uncertainty -setup 0.12   [get_clocks clk]   # ps reserved for setup
set_clock_uncertainty -hold  0.04   [get_clocks clk]   # ps reserved for hold

# what it folds in:
#   • clock JITTER from the PLL / source        (cycle-to-cycle wander)
#   • estimated SKEW before the tree is built   (pre-CTS guess)
#   • a safety pad for OCV / crosstalk / margin

# effect on the check:
#   slack_setup = (T_clk − uncertainty_setup) + skew − T_cq − T_logic − T_setup
Uncertainty is subtracted from the available period — a pessimism you buy on purpose so silicon doesn't surprise you.

Notice that setup and hold get *different* uncertainty values, and that's not an accident. Setup uncertainty bundles in jitter (which only matters across a full clock period) plus margin; hold uncertainty is usually much smaller because hold checks happen within a single edge where period jitter mostly cancels. Early in the flow, before the tree exists, uncertainty also carries a *guess* at the skew the tree will eventually have — and once CTS gives you a real propagated tree, you shrink the uncertainty to leave only jitter and true margin.

Useful skew: turning the bug into a tool

Now for the twist that separates a tool operator from an engineer. We spent this whole guide fighting to make skew *zero*. But remember the asymmetry: positive skew *helps* setup. What if one stubborn path is failing setup by 30 ps while the very next path it feeds has 200 ps of slack to spare? Instead of flattening the tree, you could deliberately delay the shared flop's clock — handing the failing path more time, paid for out of the rich neighbor's surplus. That deliberate, surgical skew is useful skew.

Before useful skew (zero-skew tree):

   FFa ──[ tight logic ]──▶ FFb ──[ loose logic ]──▶ FFc
          setup slack:           setup slack:
             −30 ps  ✗              +200 ps  ✓✓

Apply +40 ps of useful skew to FFb's clock (delay it):

   • path FFa→FFb : capture clock (FFb) now LATER  → setup slack  −30 +40 = +10 ps ✓
   • path FFb→FFc : launch  clock (FFb) now LATER  → setup slack +200 −40 = +160 ps ✓
   • borrow 40 ps from the loose stage to rescue the tight one — net win
Useful skew shifts one flop's clock to move slack from a rich path to a poor one — a per-register version of time borrowing.

Modern timing tools fold this into CTS automatically. The optimizer treats each flop's insertion delay as a *variable*, not a fixed target, and solves for the set of small skews that maximizes the worst negative slack across the whole design — a clock-tree-wide useful-skew budgeting problem. Done well, it can buy you tens of picoseconds and shave a whole timing corner without touching the logic.

Putting it together: a closing picture

Step back and the clock network tells a coherent story. The clock is not an ideal baton but a physical tree with delay and mismatch. Skew is the mismatch — it gives to setup and takes from hold. CTS builds and balances the tree to keep skew small and slew sharp. Clock uncertainty is the honest margin we reserve for the wobble we can't predict. And useful skew is the moment we stop treating skew as pure error and start spending it on purpose, moving slack to where it's needed most.

When you next read a timing report and see `clock network delay (propagated)` and a per-path `clock skew` column, you'll know exactly what they mean and which way each one tips your slack. In rung 5 we leave the nominal world entirely: real chips don't run at one voltage, one temperature, or one process — we'll meet on-chip variation and the multi-corner, multi-mode sign-off that decides whether the part actually ships.