Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Path
  • CDC/RDC Glossary
  • CDC/RDC Metrics Reference
  • CDC/RDC Interview Prep
  • CDC/RDC Signoff Cheatsheet
  • Clock Domains and Failure Modes8
  • Metastability and Synchronizers16
  • CDC Protocols and Handshakes16
  • Reconvergence and Gray Coding16
    • Gray Code Crossing
    • Reconvergence Analysis
    • Multi-bit Crossing Strategies
    • Reconvergence Debug
      • Reading a Reconvergence Report
      • Worked Reconvergence Example
      • Fix and Recheck
      • Regression Guards
  • Reset Domain Crossing16
  • Architecture and Design Rules16
  • CDC Signoff Methodology24
  • RDC Signoff16
  • Debug and Case Studies11
  • CDC and RDC Interview Prep30
  • Capstone: Sign Off a Multi-clock Peripheral4
Loading lesson

‹Reconvergence Debug
  1. Topics
  2. CDC & RDC
  3. Reconvergence and Gray Coding
  4. Reconvergence Debug
  5. Worked Reconvergence Example

Part 4 · Reconvergence and Gray Coding · All levels

Worked Reconvergence Example

A complete runnable example that shows the failure in a plain-SV model and then the fix, self-checked.

On this page

    This example replays the report excerpt above in miniature: a start pulse and its mode bit change together in the source domain. The bad path synchronises each through its own chain, with one extra destination flop on the mode chain standing in for one cycle of skew between the paths. The good path synchronises only the start pulse and captures the held-stable mode with the recovered pulse (qualified capture). One testbench runs both and checks every transfer.

    The model

    reconv_bad.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    `timescale 1ns/1ps
    
    // BAD path: start and mode each cross through their own chain. The mode chain
    // has one extra destination flop standing in for one cycle of skew between
    // the two synchroniser paths (the same deterministic model as the
    // reconvergence-glitch waveform). The checker samples mode_got with the
    // recovered start pulse.
    module reconv_bad (
      input  logic clk_d, rst_n, start_s, mode_s,
      output logic start_pulse, mode_got
    );
      logic a1, a2, a2_d;             // start chain: two flops
      logic m1, m2, m3;               // mode chain: three flops (the skew model)
      always_ff @(posedge clk_d or negedge rst_n)
        if (!rst_n) begin a1 <= 0; a2 <= 0; a2_d <= 0; m1 <= 0; m2 <= 0; m3 <= 0; end
        else begin
          a1 <= start_s; a2 <= a1; a2_d <= a2;
          m1 <= mode_s; m2 <= m1; m3 <= m2;
        end
      assign start_pulse = a2 & ~a2_d;
      assign mode_got = m3;
    endmodule
    
    // GOOD path: only the start pulse crosses. The mode is held stable by the
    // source around every pulse, so sampling it directly with the recovered pulse
    // is sound (the qualified-capture obligation, proven by the hold times in the
    // stimulus below, not assumed).
    module reconv_good (
      input  logic clk_d, rst_n, start_s, mode_s,
      output logic start_pulse, mode_got
    );
      logic a1, a2, a2_d, mode_q;
      always_ff @(posedge clk_d or negedge rst_n)
        if (!rst_n) begin a1 <= 0; a2 <= 0; a2_d <= 0; mode_q <= 0; end
        else begin
          a1 <= start_s; a2 <= a1; a2_d <= a2;
          if (a2 & ~a2_d) mode_q <= mode_s;
        end
      assign start_pulse = a2 & ~a2_d;
      assign mode_got = mode_q;
    endmodule
    

    Why the test is shaped this way

    • Mode and start change in the same source cycle, like real related logic, and the modes strictly alternate so every stale capture mismatches.

    • The start level holds four source cycles (40 ns) against the 20 ns destination clock, so each transfer yields exactly one pulse on each path; the pulse counts in the PASS line prove no transfer was lost or doubled.

    • The mode is stable for more than 100 ns around every pulse, which is the qualified-capture proof for the good path in miniature.

    • Each side is checked when its result is valid: the bad path exposes a wire, so the stale value is read with the pulse, while the good path exposes a register the pulse loads, so the clean value is read one cycle later after the capture edge.

    Common pitfall

    The good path samples mode_s with a destination clock without a synchroniser. That line is correct only under the stability the stimulus guarantees. Copy the structure without the hold promise and it tears exactly like the bad path. Review the obligation, not just the code.

    Check yourself The bad path shows 6 stale captures out of 6 transfers. Would spacing the transfers further apart fix it?

    No. The skew is structural (one flop of depth difference), so every transfer captures the previous mode no matter the spacing, as long as consecutive modes differ. Spacing fixes overlap, not skew.

    Related topics

    • Reading a report

    • Next: fix and recheck

    Previous

    60 / 179

    Next: Fix and Recheck

    Up next

    Up nextFix and Recheck

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Regression Guards