Formal Verification in Digital Design
Clearing Lint, CDC, X-Prop, and RDC the Right Way
Formal Verification in Digital Design
Clearing Lint, CDC, X-Prop, and RDC the Right Way
Why formal verification matters
Formal verification is one of the fastest ways to catch deep design bugs before silicon. Formal flows help you prove that a design obeys a property, or show a counterexample when it does not. In real SoC projects, the same static signoff mindset is often extended across lint, CDC, RDC, and X-propagation checks because these issues can survive traditional simulation and appear later in silicon.
The most common setback is not the tool itself, but unclear intent in RTL or constraints. A violation can be real, a false positive, or a design issue that needs an architectural change, so the first job is to classify it correctly. Another common problem is trying to “fix the report” instead of fixing the root cause, which often leads to new violations elsewhere.
What is a Lint violation
Lint finds structural and coding issues such as unintended latches, unconnected signals, simulation-synthesis mismatches, FSM problems, and bad clock/reset usage. A clean lint flow usually starts with reviewing coding style, then checking whether the warning is truly a design bug or just a waiver-worthy style choice.
How to clear lint step by step
- Read the message carefully and identify whether it is style, synthesis, or functional risk.
- Check if the issue comes from missing assignments, incomplete sensitivity lists, or bad
alwaysblock usage. - Fix the RTL if the behavior is unintended, especially for latches, combinational loops, and undriven nets.
- If the behavior is intentional, document the reason and apply a controlled waiver only after review.
- Re-run lint and confirm that the fix did not create new warnings in nearby logic.
For example: unintended latch
A typical lint warning appears when a combinational always block does not assign every output in every branch. For example, an if statement without an else may infer a latch, even though the designer intended pure combinational logic.
How to fix it:
- Identify the missing assignment path.
- Add a default assignment at the top of the block.
- Or complete every
ifandcasebranch. - Re-run lint to confirm the latch warning is gone.
CDC violations
CDC analysis flags signals that cross between asynchronous clock domains without proper synchronization. The most common root causes are missing synchronizers, unsafe multi-bit transfers, reconvergence problems, and incorrect assumptions about pulse width or data stability.
How to clear CDC step by step
- Identify the crossing type: single-bit control, pulse, multi-bit data, FIFO, handshake, or reset-related crossing.
- For single-bit control signals, use a proper two-flop or equivalent synchronizer.
- For multi-bit data, use Gray coding, handshake protocols, or asynchronous FIFO structures instead of independent bit synchronization.
- Mark the clocks correctly in the CDC tool and distinguish real crossings from false paths or intentionally synchronized paths.
- If the tool reports a questionable path, validate the intent with assertions or a small formal model before waiving it.
- Re-run CDC after the RTL fix and check for reconvergence, fanout, and reset interaction issues.
For example: unsynchronized pulse crossing
A common CDC violation happens when a one-cycle pulse from clk_a is directly sampled by logic in clk_b. The pulse may be missed entirely if it is shorter than the destination clock period, or it may create metastability if it is sampled near an edge.
How to fix it:
- Classify the crossing as a pulse, not a level signal.
- Convert the pulse to a toggle-based handshake or stretch it.
- Pass the signal through a proper two-flop synchronizer if it is single-bit.
- Re-check for fanout or reconvergence problems.
Example 2: asynchronous FIFO pointer issue
In an asynchronous FIFO, if the write pointer is transferred without Gray coding, multiple bits can change at once and the destination domain may sample an invalid value. That can break full/empty detection and cause overflow or underflow.
How to fix it:
- Keep pointers in binary locally for memory addressing.
- Convert pointers to Gray code before crossing domains.
- Synchronize the Gray-coded pointer with two flip-flops.
- Verify full/empty logic against the synchronized pointer only
X-prop violations
X-propagation issues happen when unknown values spread through the design and hide reset, initialization, or control-flow problems. Formal X-check flows are useful because they can trace X sources and show how unknowns reach critical logic.
How to clear X-prop step by step
- Find the first X source, usually an unreset flop, incomplete case statement, or gated control signal.
- Check reset behavior and confirm that all state-holding elements reach a known value after reset.
- Look for optimism and pessimism mismatches between RTL and gate-level behavior.
- Add safe default assignments, full-case handling, or reset logic where the design truly needs a known startup state.
- Re-run formal X-prop checks to make sure the fix removes the source rather than masking the symptom.
Example: reset not initialized
A common X-propagation issue occurs when a state register is never reset, so simulation starts with X and the unknown value spreads into compare logic or FSM outputs. This often shows up as a “works in RTL, fails in gate-level” problem.
How to fix it:
- Find the first register that can power up unknown.
- Add a proper reset or initialization path.
- Check whether the FSM has a safe default state.
- Re-run X-prop analysis to make sure the source is removed, not just masked.
RDC violations
RDC checks focus on reset signals crossing between reset domains, where one flop may leave reset before another. These are easy to miss because they often look harmless in RTL but can create silicon failures during power-up or reset sequencing.
How to clear RDC step by step
- Identify the reset source, destination, and whether the reset is synchronous or asynchronous.
- Check whether the reset release order is guaranteed for both launch and capture flops.
- If the reset crosses domains, synchronize the deassertion or redesign the reset scheme so both sides come out of reset safely.
- Avoid using reset as a data path or combining unrelated resets without explicit control logic.
- Re-run RDC and confirm that the reset tree connectivity is correct and no hidden reset paths remain.
Example: reset deasserted unsafely
A reset-domain crossing issue appears when a reset is released asynchronously into a destination clock domain and different flops come out of reset at different times. This can leave part of the logic active while the rest is still reset, creating an illegal intermediate state.
How to fix it:
- Identify the reset source and destination domain.
- Use a reset synchronizer so deassertion happens synchronously.
- Avoid multiple independent synchronizations of the same reset unless the architecture explicitly supports it.
- Apply the proper false-path or async clock constraints to the reset path.
WHAT TO DO WHEN GOT STUCK AT THIS STAGE
Start by understanding the intent of the path, then decide whether the violation is a real bug, a missing constraint, or a tool limitation. The best teams also keep a tight feedback loop between RTL, verification, and physical signoff so that the same bug does not reappear in another form.
메타데이터
- post_id
- aaf562d4f138
- slug
- formal-verification-in-digital-design-aaf562d4f138
- url
- https://medium.com/@siliconscript/formal-verification-in-digital-design-aaf562d4f138
- canonical_url
- https://medium.com/@siliconscript/formal-verification-in-digital-design-aaf562d4f138
- author_url
- https://medium.com/@siliconscript
- status
- ok
- fetched_at
- 2026-06-24 04:09:36