Manual RTL review catches maybe 40% of clock domain crossing bugs. On a million-gate SoC with dozens of asynchronous interfaces, the other 60% silently ship to silicon and explode in the field. Commercial CDC tools close that gap: they parse the entire RTL, extract every clock domain, and identify every unsynchronized crossing in minutes. This day covers the three industry-standard tools — Synopsys SpyGlass CDC, Cadence JasperGold CDC App, and Mentor Questa CDC — plus open-source alternatives, common violation codes, and where each tool fits in the design flow.
A modern SoC might have 8–16 independent clock domains: a CPU cluster at 3 GHz, a display engine at 148.5 MHz, a USB PHY at 480 MHz, an LPDDR controller at 800 MHz, dozens of APB peripherals at 100 MHz, and more. Each domain boundary is a potential metastability injection point.
Manual review fails for three reasons:
CDC tools perform structural analysis — they do not simulate. They read RTL, build a connectivity graph, tag every register with its clock domain, and walk every net to find domain crossings. A complete run on a 10-million-gate design takes 30–60 minutes versus weeks of manual review.
Studies from Synopsys and academic CDC surveys consistently show that static CDC tools catch 60–80% of real CDC bugs at RTL, before any simulation. The remaining 20–40% are caught by formal CDC (JasperGold) and dynamic CDC (Questa CDC simulation). Manual review alone finds roughly 30–40%.
SpyGlass CDC is the industry standard for RTL CDC checking. It is used by virtually every major semiconductor company for CDC signoff. SpyGlass performs static structural analysis — it never runs simulation.
The typical SpyGlass CDC run follows five steps: read RTL, define clocks, run the CDC goal, review violations, waive false positives, and export a closure report.
# --- Step 1: Read RTL ------------------------------------------------
read_file -type verilog {
rtl/clk_a_domain.v
rtl/clk_b_domain.v
rtl/cdc_synchronizer.v
rtl/top.v
}
# Read constraints (SDC)
read_file -type sdc constraints/top.sdc
# --- Step 2: Set clock definitions -----------------------------------
# (Usually already in SDC, but can be set manually)
define_clock -name clk_a -period 4.0 [get_ports clk_a]
define_clock -name clk_b -period 6.67 [get_ports clk_b]
define_clock -name clk_c -period 10.0 [get_ports clk_c]
# Mark async clock pairs (no phase relationship)
set_clock_groups -asynchronous \
-group {clk_a} \
-group {clk_b} \
-group {clk_c}
# --- Step 3: Set CDC goal and run ------------------------------------
current_goal CDC/lint -top top
# Enable reconvergence checks (off by default in older versions)
set_option enableReconvergenceCheck true
# Run CDC analysis
run
# --- Step 4: Review violations ---------------------------------------
# Get all violations
set viols [get_violations -goal CDC/lint]
foreach v $viols {
puts "VIOLATION: [get_attribute $v violation_name] \
SEVERITY: [get_attribute $v severity] \
LOCATION: [get_attribute $v location]"
}
# --- Step 5: Waive false positives -----------------------------------
# Waive a known-safe path with justification
waive -rule Ac_unsync01 \
-regexp {req_sync/d_in} \
-comment "Handled by 2-FF synchronizer in cdc_synchronizer.v line 42"
# Waive reconvergence where data is gray-coded (safe)
waive -rule Ac_conv01 \
-regexp {gray_counter/q\[} \
-comment "Gray-coded bus: only 1 bit changes per cycle, reconvergence is safe"
# --- Step 6: Re-run and export closure report -----------------------
run
report -type cdc -output reports/cdc_closure.rpt
# Export waiver log for review board
report_waivers -output reports/cdc_waivers.rpt
JasperGold CDC is Cadence's formal CDC verification tool. Rather than structural analysis, it uses model checking — a mathematical technique that exhaustively explores all possible input sequences to prove properties about the design.
This makes JasperGold fundamentally different from SpyGlass:
JasperGold is significantly slower than SpyGlass (hours versus minutes for large designs) but eliminates false positives and can automatically generate waivers for paths it proves safe. It also provides coverage metrics: which CDC paths were exercised by simulation, and which were only proven safe by formal.
# --- JasperGold CDC App invocation ----------------------------------
# Run from: jg -cdc -allow_unsupported_OS
# Load design
analyze -sv09 {
rtl/clk_a_domain.sv
rtl/clk_b_domain.sv
rtl/cdc_synchronizer.sv
rtl/top.sv
}
elaborate -top top -work worklib
# --- Clock and reset specification ----------------------------------
clock clk_a -period 4
clock clk_b -period 6
reset -expression {!rst_n}
# --- CDC App: prove synchronizer correctness ------------------------
# Enable CDC property generation
cdc_app -enable
# Set synchronizer depth to check
cdc_app -sync_depth 2
# Run formal proof
prove -all
# --- Review CDC results ---------------------------------------------
# Proven-safe crossings (auto-waivable)
report -type cdc_proven -out reports/jg_cdc_proven.rpt
# Crossings with counter-examples (real bugs)
report -type cdc_violated -out reports/jg_cdc_violated.rpt
# Coverage: which CDC paths exercised by simulation
report -type cdc_coverage -out reports/jg_cdc_coverage.rpt
# Generate automatic waivers for proven-safe paths
cdc_generate_waivers -proven -output waivers/auto_cdc_waivers.svwf
Xcelium is Cadence's primary RTL simulator. It includes a built-in runtime CDC checker that instruments the design during simulation and reports CDC violations as they actually occur — catching dynamic violations that static analysis cannot find.
The key advantage: Xcelium CDC can detect protocol violations that depend on simulation stimulus. A handshake protocol that is structurally correct but violates timing under specific traffic patterns will only be caught at runtime. Xcelium CDC also integrates with Cadence CCOV to show which CDC crossings were exercised during simulation, helping teams understand their CDC coverage gap.
# Compile with CDC instrumentation enabled
xmvlog -sv -64bit \
-define CDC_ENABLE \
rtl/top.sv rtl/cdc_synchronizer.sv
# Elaborate with CDC runtime checks
xmelab -64bit \
-access +r \
-cdc_enable \
-cdc_report reports/xm_cdc_runtime.rpt \
worklib.top
# Run simulation -- CDC checker fires on violations
xmsim -64bit \
-cdc_enable \
-cdc_max_violations 1000 \
worklib.top
# After simulation: review CDC runtime report
# Violations appear as:
# CDC_VIOLATION at time X ns in module Y
# port Z crossing from domain A to domain B without synchronizer
Questa CDC (now under Siemens EDA) combines static CDC analysis with tight integration into the Questa simulation environment. Its key strength is mixed static + dynamic verification: it performs an initial structural analysis pass, then instruments the RTL for runtime checking during simulation.
Questa CDC produces a CDC coverage report after simulation that shows which crossings were exercised during the sim run, which were clean, and which produced violations. This makes it very powerful for directed CDC regression testing — you can write testbench scenarios specifically targeting CDC paths and verify every crossing was exercised.
# --- Step 1: Static CDC analysis ------------------------------------
qvl_compile -f filelist.f -top top
# Run static CDC check
cdc check -d top \
-clock {clk_a 4ns} \
-clock {clk_b 6.67ns} \
-reset {rst_n -low} \
-report reports/questa_static_cdc.rpt
# --- Step 2: Instrument RTL for dynamic CDC -------------------------
# Generate an instrumented netlist for simulation
cdc instrument -d top \
-out_file work/top_cdc_inst.sv
# --- Step 3: Simulate instrumented design ---------------------------
vlog -sv work/top_cdc_inst.sv
vsim -t 1ps top_tb
# Run test
run -all
# --- Step 4: CDC coverage report ------------------------------------
cdc report -db questa_cdc.db \
-type coverage \
-output reports/questa_cdc_coverage.rpt
# CDC coverage shows:
# EXERCISED -- crossing was sampled in simulation
# CLEAN -- no violation observed
# VIOLATED -- runtime CDC violation detected
# UNREACHED -- crossing never exercised (coverage gap)
# --- Step 5: Waiver management -------------------------------------
cdc waiver -rule CDC_ASYNC_RESET \
-scope {top.u_core.u_rst_sync} \
-comment "Asynchronous reset synchronizer -- by design"
| Feature | Synopsys SpyGlass CDC | Cadence JasperGold CDC | Siemens Questa CDC |
|---|---|---|---|
| Analysis type | Static structural | Formal (model checking) | Static + dynamic hybrid |
| Speed (10M gates) | 30–60 min | 2–8 hours | 1–2 hr static; sim runtime varies |
| False positives | Moderate (needs waivers) | Low (proven paths auto-waived) | Low-moderate |
| False negatives | Moderate (misses dynamic bugs) | Low for covered properties | Low (dynamic catches runtime) |
| Simulation integration | None (pure static) | Can import sim traces (CCOV) | Tight — same tool as simulator |
| Formal proof | No | Yes — proves sync correctness | No |
| CDC coverage metrics | Structural coverage only | Formal + simulation coverage | Dynamic coverage per crossing |
| Reconvergence detection | Yes (Ac_conv01) | Yes (proven) | Yes (static + dynamic) |
| Learning curve | Medium | High (formal background needed) | Low for Questa users |
| Industry adoption | Very high — de facto standard | High in formal-centric teams | High in simulation-centric flows |
| Waiver format | AWF (Atrenta Waiver Format) | SVWF / auto-generated | Built-in waiver DB |
Commercial tools are expensive. For smaller teams, open-source alternatives provide partial CDC coverage:
Open-source tools do not perform automatic synchronizer structure recognition, reconvergence analysis, or full multi-clock domain extraction at the level of commercial tools. For tapeout-bound designs, commercial tools are mandatory. Open-source is appropriate for educational projects, pre-RTL exploration, or as a fast CI gate before commercial tool runs.
SpyGlass CDC uses standardized violation codes. These codes appear in all major CDC tools in similar forms. Understanding them is essential for triaging a CDC signoff report.
| Violation Code | Meaning | Fix |
|---|---|---|
| Ac_unsync01 | Unsynchronized crossing — a signal crosses clock domains with no synchronizer on the path | Add a 2-FF synchronizer (single-bit) or handshake / FIFO (multi-bit bus) |
| Ac_conv01 | Reconvergence — two paths from the same domain crossing re-join in the destination domain, creating a functional hazard | Use gray coding on buses; ensure only one bit changes per cycle; or use a FIFO |
| Ac_glitch01 | Combinational glitch — a combinational path drives a crossing, creating glitch pulses that could be latched in the destination domain | Register the output before the crossing; never pass raw combinational logic across a domain boundary |
| Ac_sync_set_reset | Set/reset signals to a synchronizer flip-flop are driven from a different clock domain without synchronization | Ensure set/reset paths are either tied to a static value or properly synchronized before reaching the synchronizer |
| Ac_cdc_coherency | Multi-bit bus crossing where individual bits can arrive at different times — coherency violation | Use gray-encoded counter, handshake protocol, or dual-clock FIFO |
| Ac_recon02 | Advanced reconvergence — more than two paths from different crossing points converge in the destination, multiplying hazard potential | Redesign the crossing to use a single synchronized control signal; separate data paths explicitly |
# --- GOOD waiver: documented, scoped, justified ---------------------
waive -rule Ac_unsync01 \
-regexp {u_gray_counter\.q\[} \
-comment "SAFE: Gray counter output -- only 1 bit changes per \
clock cycle. Analyzed by CDC lead 2026-06-20. \
Jira: CDC-142."
# --- BAD waiver: blanket waive without justification ----------------
# NEVER do this -- it masks real bugs
# waive -rule Ac_unsync01 -regexp {.*} ;# DO NOT USE
# --- Reconvergence waiver with evidence ----------------------------
waive -rule Ac_conv01 \
-regexp {u_arb\.req_sync} \
-comment "Reconvergence on arbitration request. Both paths \
converge at u_arb.grant_r which is qualified by \
u_arb.lock -- lock prevents simultaneous assertion. \
Design review signoff: DR-2026-031."
CDC tools are not run once and forgotten. They belong at multiple stages of the design flow, and the output of each run feeds into the next:
| Design Stage | Tool | Goal | Pass Criteria |
|---|---|---|---|
| RTL design | SpyGlass CDC | Catch structural crossing errors early while fix cost is low | Zero Ac_unsync01 violations without waiver |
| RTL freeze / CDC signoff | SpyGlass + JasperGold | Full CDC closure: prove synchronizer correctness, generate waiver file | All violations waived with justification; JasperGold proves sync stages |
| Block-level simulation | Questa CDC / Xcelium CDC | Catch dynamic violations under directed CDC test scenarios | All CDC crossings reached in simulation; zero runtime violations |
| Gate-level simulation | Questa CDC (gate) | Verify synthesis did not introduce new CDC violations (gate-to-RTL CDC delta) | CDC report matches RTL signoff; no new violations |
| Post-route | SpyGlass CDC (netlist) | Verify placement/routing did not violate synchronizer timing requirements | Synchronizer max_delay constraints met; no new timing-CDC violations |
| Silicon bringup | Logic analyzer + CDC-aware debug | Correlate silicon failures with CDC signoff database | Any CDC-region failure triggers re-examination of waiver justifications |
Rule of thumb: If a CDC violation appears at gate level that was not in the RTL CDC report, it means synthesis restructured logic across a domain boundary — usually by inlining or moving registers. Always run a gate-level CDC check and compare the delta to the RTL baseline.
Synopsys SpyGlass CDC is an industry-standard static analysis tool for identifying clock domain crossing violations in RTL. It extracts clock domains, identifies unsynchronized crossings, checks synchronizer structures, detects reconvergence, and produces a closure report signed off before tapeout.
SpyGlass CDC is static analysis — it reads RTL and identifies structural violations without simulation. JasperGold CDC App uses formal methods (model checking) to mathematically prove whether synchronizers are correct and whether CDC paths are provably safe, providing coverage metrics and automatic waivers for proven-safe paths.
Ac_unsync01 is SpyGlass's violation code for an unsynchronized clock domain crossing — a signal crossing from one clock domain to another without any synchronizer on the path. This is the most critical CDC violation and must be fixed or explicitly waived with documented justification before signoff.