HomeSTA CourseDay 13
DAY 13 · TIMING CLOSURE & SIGN-OFF

Fixing Hold Violations

By EcrioniX · Updated June 2026

Hold violations are frequency-independent, physically guaranteed failures. Unlike setup violations (which can be resolved by reducing the clock frequency), a hold violation means data will overwrite a flip-flop before it has finished capturing its current value — every time, regardless of how slow the clock is. They appear en masse after CTS and must be eliminated — without exception — before tape-out.

1. Why hold violations appear post-CTS

Before CTS, STA uses ideal clocks with zero skew. After CTS, real clock tree buffers introduce local skew — the clock arrives at different times at physically adjacent flip-flops. Consider two flip-flops FF_L (launch) and FF_C (capture) connected by a very short combinational path:

Short paths are the most vulnerable because a very short combinational delay (e.g., a direct connection or a single buffer) means data arrives almost immediately after FF_L launches it. If FF_C’s clock came even 10ps early, a 1-gate path may have a hold violation.

2. The hold check equation

The hold check compares the minimum data arrival time against the minimum required hold time:

Hold slack = Min_data_arrival − (Capture_clock_arrival + Hold_time)

For hold to pass, this must be ≥ 0. Min_data_arrival uses the fastest (best-case) data path; Capture_clock_arrival uses the latest (worst-case) capture clock to maximise pessimism (making the hold window as short as possible); Hold_time is the flip-flop’s hold time from Liberty.

Hold timing report — annotated
Startpoint: ff_launch (rising edge, clocked by clk_core) Endpoint: ff_capture (rising edge, clocked by clk_core) Path Type: min <- hold analysis uses minimum path delay Point Incr Path ──────────────────────────────────────────────── clock clk_core (rise edge) 0.00 0.00 clock network delay (propagated) 0.60 0.60 <- FF_L clock arrival ff_launch/CK (rise) 0.00 0.60 ff_launch/Q (rise) 0.04 0.64 <- fastest Clk-to-Q U_buf/Z (rise) [net1] 0.02 0.66 <- single buffer on path ff_capture/D (rise) [net2] 0.01 0.67 <- data arrives at 0.67 ns data arrival time 0.67 <- MINIMUM arrival clock clk_core (rise edge) 0.00 0.00 clock network delay (propagated) 0.55 0.55 <- FF_C clock arrival (EARLIER!) ff_capture/CK (rise) 0.00 0.55 clock reconvergence pessimism 0.02 0.57 <- CPPR (helps slightly) clock uncertainty -0.05 0.52 library hold time 0.03 0.55 <- FF hold requirement required time 0.55 ──────────────────────────────────────────────── slack (VIOLATED) -0.12 <- 120 ps hold violation!

3. Buffer/delay cell insertion — the primary fix

The primary fix for a hold violation is inserting buffers (delay cells) on the data path to increase the minimum data arrival time. The goal: make Min_data_arrival exceed Capture_clock + Hold_time.

Standard cells provide dedicated delay elements: DLYB1, DLYB2, DLYB4 (increasing delay values), or simply a pair of series inverters. The number of buffers needed depends on the hold violation amount.

Buffer insertion ECO for hold violations
## Step 1: Find worst hold violations report_timing -delay_type min -nworst 20 -slack_lesser_than 0 ## Step 2: For each violation, calculate buffers needed ## Violation = -0.120 ns; DLYB2 adds ~0.070 ns each ## Need 2 x DLYB2 = 0.140 ns -> fixes the 0.120 ns violation with 20 ps margin ## Step 3: Insert delay cells via PT ECO ## In PrimeTime ECO flow: insert_buffer ff_capture/D DLYB2 ; # inserts buffer before D input insert_buffer ff_capture/D DLYB2 ; # second buffer for more delay ## Or using Innovus ECO flow: # eco_opt -hold -slack_threshold 0.0 -eco_route ## Step 4: Verify hold is fixed without setup regression update_timing -full report_timing -delay_type min -from [get_cells ff_launch] -nworst 3 report_timing -delay_type max -from [get_cells ff_launch] -nworst 3 ## Important: check that buffer insertion didn't create a setup violation! ## Each DLYB2 adds delay to min path (+hold) but also to max path (-setup margin) ## Typical buffer adds 0.07 ns to both min and max paths.

Buffer insertion for hold REDUCES setup margin

Every buffer inserted for hold increases both the minimum AND maximum path delay. If setup slack on that path was already tight (say +0.050 ns) and you insert a DLYB2 adding 0.070 ns, you’ve now created a setup violation (-0.020 ns). Always check setup timing after hold ECO. Hold-aware timing closure alternates between hold and setup fixes.

4. HVT cell swapping for hold

Cells on very short paths (single-gate or two-gate paths) may have been previously upsized or swapped to LVT for setup fixing. LVT cells are fast — which is great for setup but makes them the worst cells for hold. Swapping them back to SVT or HVT slows the minimum path.

Cell VtMin path delayHold impactSetup impact
LVTShortest (fastest)Worst for hold (data arrives earliest)Best for setup
SVTNominalStandardStandard
HVTLongest (slowest)Best for hold (data arrives latest)Worst for setup
HVT swap for hold fixing
## Identify cells on short hold-violating paths ## Look for LVT cells (introduced during setup fixes) on hold-critical paths report_timing -delay_type min -nworst 10 -path_type full ## Check Vt of critical cells foreach cell [get_cells u_short_path/*] { puts "[get_object_name $cell]: [get_attribute $cell ref_name]" } ## Swap LVT to SVT on the shortest path cell ## SVT is slower = more hold margin, and leakage is less than LVT size_cell [get_cells u_path/U_buf_lvt] BUFX4 ; # SVT equivalent size_cell [get_cells u_path/U_inv_lvt] INVX2 ; # SVT equivalent ## Or swap to HVT for maximum hold improvement size_cell [get_cells u_path/U_buf_lvt] BUFX4_HVT ## Verify: hold improved, setup not violated update_timing report_timing -delay_type min -from [get_cells ff_A] -nworst 5 report_timing -delay_type max -from [get_cells ff_A] -nworst 5

5. Useful skew for hold

Useful skew can also help hold violations. By making the launch FF’s clock arrive later relative to the capture FF’s clock (increasing the effective data flight time budget), hold margin improves on that specific path pair. However, this means delaying the launch clock, which reduces setup margin on that same path. Useful skew for hold trades setup margin for hold margin — only viable if setup has sufficient margin to spare.

6. ECO buffer insertion flow

In production design flows, hold fixing is an automated ECO step run after CTS and routing:

Automated hold ECO in Innovus / PrimeTime
## ── In Innovus (post-route) ── ## Run hold optimisation (inserts delay buffers automatically) opt_design -post_route -hold # or: eco_opt -hold -slack_threshold 0.0 ## After hold ECO, re-route the new buffers route_eco -fix_drc true ## Re-run STA to verify time_design -post_route report_timing -delay_type min -nworst 20 ## ── In PrimeTime ECO mode ── ## Set up ECO mode set_eco_mode -verbose -eco_all_layers true set_eco_opt_clock false ; # don't touch clock tree set_eco_opt_power false ; # don't power-optimise ## Run hold fixing eco_opt -hold -slack_threshold 0.0 -max_buffer_count 500 ## Write ECO changes back to layout tool write_changes -format icctcl -output hold_eco.tcl # Apply hold_eco.tcl in ICC2 / Innovus

7. Hold-aware CTS

The best time to prevent hold violations is during CTS, not after. A hold-aware CTS strategy actively controls local skew:

Investing effort in hold-aware CTS typically reduces post-route hold ECO buffer count by 50–80%, saving routing resources and reducing congestion from inserted buffers.

Never waive hold violations

Hold violations are physical failures that occur every clock cycle, regardless of clock frequency. They cannot be fixed by running at a lower frequency. A design with unresolved hold violations is non-functional silicon — period. Never approve tape-out with any hold violations, and never apply set_false_path or set_multicycle_path to hide a real hold violation. The only acceptable fixes are physical: more delay on the data path, less skew in the clock tree.

Day 13 Key Takeaways

Frequently Asked Questions

Why do hold violations appear after CTS?

Pre-CTS STA uses ideal clocks with zero local skew. After CTS, real clock buffers create local skew between adjacent flip-flops. If the capture FF’s clock arrives earlier than the launch FF’s clock (positive skew in capture direction), the hold window shrinks. Short data paths can’t sustain even 30–50ps of this skew without violating hold.

What is the primary fix for hold violations?

Buffer (delay cell) insertion on the data path is the primary fix. By adding one or more delay cells between the launch FF’s output and the capture FF’s input, the minimum data arrival time increases. Each delay cell adds approximately 0.05–0.10 ns depending on cell type. The inserted delay must exceed the hold violation amount plus hold margin.

What is HVT swapping for hold fixing?

HVT (High Threshold Voltage) cells switch slower than SVT or LVT cells due to higher Vt. Swapping cells on a short hold-violating path from LVT or SVT to HVT increases the minimum path delay. This is complementary to buffer insertion and is especially useful when LVT cells were previously inserted for setup fixes, inadvertently creating hold vulnerabilities on those paths.

Can you ever waive a hold violation?

No. Hold violations are frequency-independent functional failures — they occur every clock cycle regardless of how slow the clock is. A chip with hold violations will fail in the field, consistently and irrecoverably. Unlike setup violations (which can be mitigated by reducing frequency), hold violations have no operational workaround. They must be fixed physically before tape-out.

What is hold-aware CTS?

Hold-aware CTS controls local skew between adjacent flip-flops during clock tree building. By targeting local skew < 30ps, the CTS tool prevents the worst-case skew conditions that cause post-CTS hold violations. This reduces the amount of ECO buffer insertion needed after routing, saving routing resources and avoiding congestion from hundreds of inserted delay cells.

← Previous
Day 12: Fixing Setup Violations