Skip to content

Clock Tree Synthesis

Richard Huang edited this page Aug 3, 2026 · 2 revisions

Clock Tree Synthesis

Clock Tree Synthesis (CTS) builds the physical network that delivers the clock from its source to every sequential element on the die. Until CTS runs, the clock is ideal — the tools pretend it arrives everywhere at the same instant. CTS replaces that fiction with real buffers, real wires, and real delay.

It runs after Placement and before Routing, and it is where a lot of optimistic pre-CTS timing goes to die.


Objectives

  • Low skew — the clock should arrive at related flops at nearly the same time
  • Low insertion delay — shorter total latency means less variation and less jitter accumulation
  • Low power — the clock network is often 20–40% of total dynamic power
  • Robustness — tolerate on-chip variation (OCV) across process, voltage, and temperature
  • Signal integrity — the clock is the highest-activity net on the chip and a major aggressor

Where It Fits

flowchart LR
    A[Placement<br/>ideal clocks] --> B[CTS]
    B --> C[Post-CTS opt<br/>propagated clocks]
    C --> D[Routing]
    style B fill:#2d6a9f,color:#fff
Loading

The important change at CTS is that timing analysis switches from ideal to propagated clocks. Setup slack usually gets worse; hold violations appear in large numbers. Both are expected.


Core Vocabulary

Term Definition Why it matters
Insertion delay (latency) Source to sink delay Longer trees accumulate more variation
Skew Arrival-time difference between two sinks Directly eats setup and hold margin
Local skew Skew between flops that actually talk to each other The one that matters
Global skew Max minus min arrival across all sinks Easy to report, often misleading
Jitter Cycle-to-cycle source variation Comes from the PLL, not the tree; budget it in uncertainty
Transition Clock edge rate at a sink Slow edges worsen variation and setup/hold accuracy

Why Skew Costs You Timing

Setup and hold with real skew:

Setup:  T_clk  ≥  t_cq + t_logic + t_setup − t_skew
Hold:   t_cq + t_logic  ≥  t_hold + t_skew

Read those together and the tension is obvious: positive skew helps setup and hurts hold. You can't just minimize one.

That's also the insight behind useful skew — deliberately delaying a capture clock to give a slow path more time, borrowed from the next stage which has slack to spare. Modern tools (Cadence CCOpt) do this automatically as part of CTS rather than targeting zero skew.

Why insertion delay matters even when skew is fine: two paths through a long tree share fewer common buffers, so on-chip variation affects them more independently. Less shared path means more effective skew after derating. This is the common path pessimism effect, and CPPR (common path pessimism removal) credits it back during Timing Closure.


Tree Topologies

Topology Structure Use when
Buffer tree Balanced fanout tree of clock buffers Default for most blocks
H-tree Geometrically symmetric recursive H Regular arrays where sinks are uniformly distributed
Clock mesh / grid Buffers drive a shorted metal grid Very low skew needed; high power cost
Multi-source CTS Several drivers into a mesh or spine Large dies, high-performance designs

Meshes short all sinks together, so skew is very low almost by construction — but the grid switches enormous capacitance every cycle. Apple and NVIDIA use mesh or hybrid structures on high-performance clock domains and plain trees elsewhere. Pick per domain, not per chip.


Clock Gating

Clock gating shuts off the clock to idle logic. It is the single largest clock power lever.

  • Integrated clock gating (ICG) cells are inserted by synthesis and preserved through CTS
  • CTS must balance through the ICG, since it sits in the clock path
  • Gating high in the tree saves more power; gating low gives finer control
  • Over-gating creates a deep tree with more variation

For an inference accelerator this matters a lot: Verification activity traces will show large idle fractions in the compute array during memory-bound phases, and that's free power savings.


Cadence Innovus Flow

Innovus uses CCOpt (Clock Concurrent Optimization), which builds the tree and optimizes datapath timing together rather than sequentially.

# 1. Constrain the tree
create_clock_tree_spec                 ;# auto-generate a starting spec
set_db cts_target_skew 0.05            ;# ns
set_db cts_target_max_transition 0.10  ;# ns
set_db cts_buffer_cells {CLKBUF_X4 CLKBUF_X8 CLKBUF_X16}
set_db cts_inverter_cells {CLKINV_X8 CLKINV_X16}

# 2. Build + optimize concurrently
ccopt_design

# 3. Switch analysis to real clocks
set_interactive_constraint_mode {propagated}
update_io_latency -adjust_source_latency

# 4. Post-CTS optimization
opt_design -post_cts               ;# setup
opt_design -post_cts -hold         ;# hold fixing

# 5. Reports
report_clock_trees -summary
report_skew
report_timing -path_group reg2reg
report_timing -early -path_group reg2reg   ;# hold paths

What matters here:

  • cts_target_skew — the skew you're asking for; tighter costs buffers and power
  • cts_buffer_cells — restrict to real clock buffers (balanced rise/fall), never ordinary logic buffers
  • ccopt_design — builds the tree while optimizing datapath, which is why it beats classic build-then-fix CTS
  • -post_cts -hold — hold fixing is a separate pass and inserts delay buffers, often thousands of them

Non-default routing

Clock nets are usually routed with wider wires and extra spacing to cut resistance and crosstalk:

create_route_rule -name clk_rule -spacing_multiplier 2 -width_multiplier 2
set_db cts_route_type_leaf clk_rule
set_db cts_route_type_trunk clk_rule

Metrics

Metric Typical target How to improve
Global skew < 5–10% of clock period Better sink clustering; balanced tree
Local skew As low as possible on real paths This is the one to actually optimize
Insertion delay Minimize; a few hundred ps typical Fewer levels, stronger buffers
Clock power 20–40% of dynamic total More clock gating, smaller mesh, fewer buffers
Max transition Within library limit Add buffers, widen routing
Clock buffer count Design-dependent Excess means sinks are too dispersed
Hold violations post-CTS Thousands is normal Fixed by opt_design -post_cts -hold

Common Problems

Problem Root cause Fix
Skew blows up Sinks physically dispersed Cluster related flops in Placement; revisit Floorplanning
Huge insertion delay Deep tree, weak buffers Stronger buffers, fewer levels, multi-source CTS
Thousands of hold violations Expected — skew is now real opt_design -post_cts -hold; budget the area for delay cells
Setup got much worse post-CTS Pre-CTS ideal-clock optimism Use realistic uncertainty pre-CTS in Design Constraints
Clock power too high Too many buffers / mesh too dense More gating; relax skew target; check for over-constraint
Crosstalk on clock Aggressors adjacent to clock routes Non-default rules with extra spacing; shielding
Skew fine, timing still fails Global skew reported, local skew bad Report skew per clock group, on real paths
CTS ignores a domain Clock not defined in SDC Every clock must be declared — see Design Constraints

Best Practices

  • Cluster sinks in placement. CTS quality is mostly determined before CTS runs. Flops that share a clock should be physically near each other.
  • Optimize local skew, not global. Global skew is a headline number; local skew is what fails silicon.
  • Let CCOpt use useful skew. Forcing zero skew throws away free timing margin.
  • Expect hold violations and budget for them. Hold fixing adds real area and power.
  • Use dedicated clock buffers only — balanced rise/fall matters for duty cycle.
  • Handle clock domain crossings explicitly. Group asynchronous clocks with set_clock_groups -asynchronous or CTS will try to balance unrelated trees.
  • Check transition times everywhere. A slow clock edge quietly degrades every timing check that depends on it.
  • Keep the tree shallow. Fewer levels means less variation and less power.

See also: Placement · Routing · Timing Closure · Design Constraints · Physical Design

Clone this wiki locally