Clock-Tree Synthesis (CTS)

The clock reaches every flip-flop on the chip. Learn clock-tree goals (skew, latency, transition, power), H-trees, buffered trees and meshes, skew and its effect on setup and hold, useful skew, clock gating in the tree, non-default routing rules, OCV/CRPR, and how to compute tree depth and timing windows.

Before CTS the clock is 'ideal' — it arrives everywhere at the same instant. CTS builds the real network of buffers and wires that distributes the clock from its source (PLL) to tens of thousands or millions of sinks.

The clock network toggles every cycle and often consumes 30–40% of dynamic power. It must deliver sharp edges with small, controlled differences in arrival time (skew), because skew directly eats setup or hold margin.

An analogy

A clock tree is the water-pipe system of a building that must deliver water to every tap at exactly the same moment: equal-length branches and properly sized pumps (buffers) at each level.

Goals of the clock tree

Reach every sink; keep skew small (typically tens of ps); keep latency reasonable; keep transitions sharp (slow edges add jitter and short-circuit power); and use as little power and area as possible. These goals conflict, so CTS is an optimisation.

Tree structures

Common topologies:

Skew, setup and hold

If the capture flop's clock arrives later than the launch flop's, the data gets more time (setup improves) but the new data may overwrite the old too early at the capture flop (hold worsens). Useful-skew optimisation deliberately delays some clocks to borrow time from fast paths for slow ones.

Variation and clock sign-off

On-chip variation makes clock paths faster or slower in different places; STA models it with derates/AOCV/POCV and removes the pessimism on shared tree segments (CRPR). Clock nets are routed with NDRs (double width/spacing) and shielding to reduce crosstalk and EM. Clock gating cells are placed in the tree; CTS balances through them. Jitter from the PLL adds to uncertainty.

Formulas

Worked example: Tree depth

Given: 10 000 sinks, fan-out 4

Find: Levels and buffers.

Answer: 7 levels, ≈ 5461 buffers (ideal tree)

Worked example: Useful skew

Given: t_cq 50, logic 800, setup 40 ps; skew +30 ps

Find: Minimum period.

Answer: 860 ps (1.163 GHz) vs 890 ps with zero skew

Worked example: Clock power

Given: C_clk = 300 pF, 0.9 V, 1.5 GHz

Find: Clock power.

Answer: ≈ 0.36 W — why clock gating matters

Tree size and the setup/hold effect of skew

import math

sinks = 10000
fanout = 4
levels = math.ceil(math.log(sinks, fanout))
print(f"{sinks} flops with fanout-{fanout} buffers -> {levels} buffer levels, "
      f"{sum(fanout**i for i in range(levels))} buffers (ideal tree)")

tcq, tlogic, tsetup, thold = 50, 800, 40, 30   # ps
for skew in (-30, 0, 30):                      # capture clock later (+) or earlier (-)
    tmin = tcq + tlogic + tsetup - skew
    hold_margin = tcq + 20 - thold - skew      # shortest path = 20 ps of logic
    print(f"skew {skew:+d} ps: min period {tmin} ps ({1e3/tmin:.3f} GHz), hold slack {hold_margin} ps")
# 10000 flops with fanout-4 buffers -> 7 buffer levels, 5461 buffers (ideal tree)
# skew -30 ps: min period 920 ps (1.087 GHz), hold slack 70 ps
# skew +0 ps: min period 890 ps (1.124 GHz), hold slack 40 ps
# skew +30 ps: min period 860 ps (1.163 GHz), hold slack 10 ps

Positive skew (capture clock later) helps setup but hurts hold by the same amount — the basis of 'useful skew'. Too much positive skew on a short path causes hold violations, which cannot be fixed by slowing the clock.

Clock-tree constraints (SDC + OpenROAD style, illustrative)

create_clock -name core_clk -period 1.0 [get_ports clk]
set_clock_uncertainty -setup 0.05 [get_clocks core_clk]   ;# jitter + margin
set_clock_uncertainty -hold  0.02 [get_clocks core_clk]
set_clock_transition 0.08 [get_clocks core_clk]

# CTS with clock buffers/inverters only, wider spaced wires for the clock
clock_tree_synthesis -buf_list {CLKBUF_X4 CLKBUF_X8} -root_buf CLKBUF_X16 \
                     -sink_clustering_enable
set_propagated_clock [all_clocks]                          ;# use real latencies from now on
repair_clock_nets
report_clock_skew

After CTS the clock becomes 'propagated': STA uses real buffer and wire delays instead of ideal timing, and hold fixing starts.

Common mistakes

Applications

Key takeaways

Going further