Clock Tree Synthesis (CTS)
How CTS builds a real, balanced clock network: topologies (H-tree, spine, mesh), skew, latency, useful skew and the hold it exposes.
Your chip has one clock root (usually a PLL output) but hundreds of thousands, even millions, of flip-flops that all need that clock. You cannot run a single wire to all of them: the capacitance would be enormous, the edge would turn into a slow ramp, and flip-flops in different corners of the die would see the edge at wildly different times. Clock tree synthesis (CTS) solves both problems by building a balanced network of clock buffers that fans the clock out level by level, so every flip-flop gets a fast, clean edge at almost the same instant.
What clock tree synthesis does
Before CTS, static timing analysis uses an ideal clock: the tool pretends the clock reaches every flip-flop at exactly the same time with zero delay. That is fine for early analysis, but it is not real silicon. CTS replaces that ideal clock with a physical network of buffers, inverters and wires, and from then on timing is checked with the propagated (real) clock.
CTS runs after placement and before (or interleaved with) routing. It has one job stated two ways: deliver the clock to every sink with a controlled arrival time, and do it with a clean enough edge that setup and hold can be met everywhere. Everything else about CTS is a trade-off around those two goals.
The clock tree: buffers that fan the clock out
A clock tree starts at the clock root and branches outward. Each level of buffers takes the incoming clock and drives a manageable number of loads at the next level, until the last level drives the individual flip-flop clock pins. A real block typically has four to eight levels of buffering. Buffers are what keep the transition (slew) sharp: without them, one net driving tens of thousands of pins would have a rise time measured in nanoseconds and the clock would barely toggle.
Buffer vs inverter, CTS cells come in both flavours. Many tools build the tree from inverters in balanced pairs, because a matched inverter pair keeps rise and fall delays close and cancels duty-cycle drift better than a plain buffer. Whichever is used, the cells are special, well-characterised clock cells, not ordinary logic.
Clock tree topologies
How the tree is shaped is the topology. The tool picks (or you constrain) a topology based on how the sinks are laid out, how tight the skew target is, and how much power and routing you can spend. These are the shapes you will hear named in reviews and interviews.
H-tree
The H-tree is the textbook balanced tree. The clock splits into an H shape, each arm splits into a smaller H, and so on, so that the wire distance from the root to every leaf is identical. Equal length means equal delay, which means skew is near zero by construction rather than by tool effort. The cost is dedicated routing and area, and it works best when sinks are spread out fairly regularly. The X-tree is the same idea rotated onto diagonal segments.
X-tree
An X-tree is an H-tree that routes along diagonals instead of only horizontal and vertical segments. It can shorten total wire length and latency versus a strict H-tree, but diagonal clock routing is awkward on standard preferred-direction metal layers, so it is rare in normal cell-based flows and shows up mostly in custom or full-custom clocking.
Spine / fishbone
A spine (or fishbone) drives one strong central wire and taps ribs off it to reach the sinks. It is compact and cheap in area and power and is a natural fit for regular structures like datapaths and memory arrays. The weakness is balance: sinks near the driver see the clock earlier than sinks at the far end, so skew grows along the spine and has to be watched.
Clock mesh (grid)
A mesh (grid) shorts many drivers onto a single grid of wires that blankets the block. Because dozens of drivers hold the same grid, the arrival time is averaged and skew is extremely low, even under on-chip variation. The price is high power (a large always-switching capacitance) and area, so meshes are reserved for the top-level clock of high-performance CPUs and GPUs where skew matters more than power.
Hybrid trees
Real SoCs almost never use one pure topology. The common pattern is hybrid: a mesh or a balanced H-tree distributes the clock at the top level across the die, and a conventional buffered tree grows locally inside each block from that distribution. You get low top-level skew where it is expensive to fix and cheap local trees everywhere else.
| Topology | Skew control | Power | Area / routing | Typical use |
|---|---|---|---|---|
| H-tree / X-tree | Excellent (balanced by construction) | Moderate | High (dedicated tracks) | Top-level distribution, regular sinks |
| Conventional buffered tree | Good (tool-balanced) | Low to moderate | Low | The default inside standard-cell blocks |
| Spine / fishbone | Moderate (grows along spine) | Low | Low | Datapaths, memory arrays, simple blocks |
| Mesh / grid | Best (drivers averaged) | Very high | High | Top clock of high-performance CPUs/GPUs |
| Hybrid (mesh + local trees) | Excellent | High | High | Large SoCs: mesh at top, trees per block |
The three numbers CTS cares about
Clock skew
Skew is the difference in clock arrival time between two flip-flops. If the launch flop sees the edge at 1.00 ns and the capture flop at 1.04 ns, the skew on that pair is 40 ps. Local skew is measured between related (launch/capture) flops; global skew is the spread across the whole design. Skew is not purely bad: positive skew toward the capture flop relaxes setup but tightens hold, and negative skew does the reverse. A typical post-CTS target keeps global skew under roughly 5% of the clock period.
Insertion delay (latency)
Insertion delay, or clock latency, is the time from the clock source to a flip-flop clock pin through all the buffers and wires. It splits into source latency (before the clock root, e.g. inside the PLL and the top-level route) and network latency (the tree the CTS tool builds). Latency on its own does not break timing; it is the difference in latency between flops, which is skew, that does. Still, lower and more balanced latency means less absolute variation, so tools try to keep the tree shallow.
Clock uncertainty
Uncertainty is the guard-band you subtract from every clock edge in STA. Before CTS it stands in for the skew you have not built yet plus jitter; you set it with set_clock_uncertainty in the SDC. After CTS, the propagated clock carries the real skew directly, so you drop the skew portion and leave only jitter (cycle-to-cycle variation from the PLL, typically tens of picoseconds) and a small modelling margin.
Useful skew, turning skew into margin
Instead of driving skew to zero everywhere, modern CTS deliberately spends it. If a path is tight on setup, delaying the capture clock a little (useful skew) gives that path extra time. The catch is that the capture flop is the launch flop for the next stage, so the borrowed time has to be paid back downstream. Concurrent clock and data optimisation lets the tool push skew onto exactly the launch/capture pairs where it buys the most slack without breaking their neighbours.
Useful skew in one line, zero skew is a starting point, not the goal. The goal is the best worst-slack across the whole design, and a well-placed few picoseconds of skew often beats a perfectly balanced tree.
The CTS flow, step by step
Group flip-flop clock pins by location so physically close sinks share a branch. Good clustering is what makes a shallow, low-skew tree possible.
Grow the network from the clock root, adding balanced buffers or inverter pairs at each level to drive the next fan-out cleanly.
Size and reposition cells so every sink sees the edge at nearly the same time, or hit the target useful-skew schedule instead of pure balance.
Optimise the data paths and the clock together, spending skew where it buys the most margin (ccopt in Innovus, clock_opt in ICC2 / Fusion Compiler).
Commit the clock nets on non-default rules (wider, more spacing, sometimes shielded) so they are low-resistance and immune to neighbour crosstalk.
With real latency in place, re-time the design and add hold buffers on the short paths CTS just exposed.
Clock tree cells, NDR and shielding
The clock network gets special treatment because a picosecond of variation here hits every path. A few things distinguish it from ordinary logic:
- Clock buffers and inverters are dedicated, well-characterised cells; balanced inverter pairs are preferred so rise and fall delays match.
- After the tree is balanced its cells are marked don’t-touch, so later timing optimisation cannot resize them and unbalance the tree.
- Non-default routing rules (NDR) give clock nets extra width and spacing to cut resistance, electromigration and crosstalk-induced skew.
- Shielding runs grounded or power wires alongside sensitive clock nets so neighbouring switching cannot jitter the edge.
- Integrated clock-gating cells (ICG) live inside the tree, so even gated branches stay balanced with the rest of the clock.
Why CTS creates hold violations
Before CTS the clock was ideal, so hold almost always passed. The moment CTS inserts real latency and skew, short paths between physically close flip-flops can fail hold: the data races through the tiny bit of logic and arrives before the previous value is safely captured, and any positive skew toward the capture flop makes it worse.
Hundreds of hold violations right after CTS are normal, not a bug. They are fixed by adding delay (hold or delay buffers) on the short paths, never by speeding the clock up. Watch that the added delay does not eat the setup margin on the same path.
Reading a CTS / clock report
After CTS you check the tree the same way in every tool: skew, insertion delay, transition, buffer count and clock power. A healthy tree hits the skew target with the fewest levels and buffers, and with clean transitions at the leaves.
report_clock_timing -type skew -clock clk
Clock: clk
Rise Skew ............ 0.041 ns
Max Insertion Delay .. 0.312 ns (u_mem/.../CK)
Min Insertion Delay .. 0.271 ns (u_alu/.../CK)
Global Skew .......... 0.041 ns
Sinks ................ 12480
Clock Buffers ........ 214
Tree Levels .......... 6| Metric | What it tells you | Healthy target |
|---|---|---|
| Global skew | Spread of clock arrival across all sinks | Under ~5% of the clock period |
| Max insertion delay | Longest source-to-sink latency | Low, and balanced against min insertion delay |
| Clock transition (slew) | Edge rate at the sink pins | Under ~100 ps (node dependent) |
| Buffer / inverter count | Size and power of the tree | Minimised for the skew target |
| Clock power | Dynamic power of the network | Often 20-40% of chip dynamic power |
| Tree levels | Depth of the tree | Fewer levels means less latency and variation |
Key CTS commands
| Command / property | Tool | Purpose |
|---|---|---|
| ccopt_design | Innovus | Build the tree with concurrent clock + data optimisation |
| set_ccopt_property | Innovus | Set target skew, max latency, buffer/inverter lists, NDR |
| clock_opt | ICC2 / Fusion Compiler | Run clock tree synthesis and optimisation |
| set_clock_tree_options | ICC2 | Configure CTS references, targets and routing rules |
| report_clock_timing -type skew | PrimeTime / Innovus | Report skew between launch and capture sinks |
| report_clock_tree / report_clock_tree_power | Both | Skew, insertion delay, buffer count and clock power |
Recap: CTS turns the ideal clock into a real, buffered network. Pick a topology for your skew and power budget (tree, H-tree, spine or mesh), balance skew or spend it usefully, route the clock on its own rules, then clean up the hold violations that real latency exposes.