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

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
    • Low-Power RTL Hub
    • DFT and Scan Hub
    • Physical Awareness Hub
    • Waveform Debug Hub
    • STA and ECO Hub
    • RTL-to-Implementation Closure
    • DFT-Ready RTL
    • Capstone: Resilient Streaming Peripheral
    • Principal Design Review
    • Senior RTL Interview Questions & Model Answers
      • Interview: Combinational and Arithmetic
      • Interview: Sequential and Pipelines
      • Interview: FSM and Control
      • Interview: Timing and STA
      • Interview: CDC and Reset
        • A CDC review: what to check
        • Reset assertion vs release
        • Why an async FIFO uses Gray pointers
        • Pulse synchronizers and reset-domain crossings
      • Interview: Memories and Buses
      • Interview: Low-Power Design
      • Interview: Debug and ECO
      • Interview: Coding and Whiteboard
  • Glossary and Notation
Loading lesson

‹Interview: CDC and Reset
  1. Topics
  2. RTL Design
  3. Senior & Interview
  4. Senior RTL Interview Questions & Model Answers
  5. Interview: CDC and Reset
  6. Pulse synchronizers and reset-domain crossings

Part 9 · Senior · Senior

Pulse synchronizers and reset-domain crossings

A toggle pulse synchroniser with spacing rules, one-sided reset hazards, and a reset-mid-test testbench.

On this page

    Why this matters

    A one-cycle pulse can fall between two slower destination edges and vanish, and a reset hitting one side mid-transfer can duplicate or invent a word. Both are classic follow-ups after a plain synchroniser answer.

    After this lesson you can: build a toggle pulse synchroniser, say how far apart pulses must be, and list the three reset-domain crossing hazards with their fixes.

    The question

    “Pass a one-cycle pulse across clocks.” Then: “What if one side resets mid-transfer?” One lesson holds both questions: events first, reset-domain crossings second.

    The short answer for the pulse: a toggle or a request and acknowledge handshake, never a blind stretch. The reset half follows the course reset-domain lessons.

    Pulse synchroniser

    A short pulse can fall between two destination edges, so it is first turned into a level: each pulse toggles a source flop. A two-flop synchroniser carries the level, and an XOR of the output with its previous value remakes one destination pulse per toggle (pulse lesson).

    Each slot is half a destination clock cycle, so clk_d reads high then low across each pair of slots. The source pulse is one fast cycle wide: narrower than one destination cycle.

    • Slot 2: pulse_s is high for this one slot only, and toggle_s flips to 1 in the same slot. The pulse is shorter than one destination cycle, so it can fall between two destination edges; without the toggle the destination could miss it entirely.

    • Slots 3 to 5: the new level crosses the two-flop chain (the first stage is internal and not shown), while q2 still reads 0.

    • Slots 6 to 7: q2 turns 1 and pulse_d is high. Those two slots are one full destination cycle: exactly one output pulse for one input pulse.

    • Slots 8 to 11: the level holds steady at 1, so no second pulse appears.

    Spacing rule: each toggle level must survive long enough for destination sampling and edge detection across clock modes, phase and margin. A conservative open-loop contract spans at least three clean destination sampling edges per level; two destination periods is not a universal lossless bound. Stoppable or unbounded clocks need an acknowledged event protocol, a counter or a FIFO.

    Check yourself Why is the destination pulse exactly one cycle wide?

    The synchronised level changes at one destination edge and the previous-value flop copies it at the next. The XOR is high only between those two edges.

    Check yourself How is the spacing rule enforced in a real block?

    With a busy or ready flag: the source may not raise another pulse until the handshake or hold counter clears. A producer that ignores it overwrites events.

    Reset-domain crossings

    Reset-domain crossing starts where CDC stops: a reset hits one side mid-protocol. Three hazards follow.

    Hazard

    What goes wrong

    Fix

    Cleared source data

    Source data cleared while a request is visible is captured as a real word.

    Retain data through completion or authorised cancellation, and qualify destination acceptance during recovery. Leaving data unreset alone is not enough.

    Cleared destination history

    History cleared while a request or toggle is retained duplicates a transfer or creates a phantom event.

    Block acceptance and establish a fresh baseline or epoch. Acknowledging a stale request is cancellation, not delivery.

    Release order

    The producer starts while the consumer is still in reset.

    Ordered release, or a ready flag the sender waits for (quiescence, isolation).

    All three have one cure: a planned recovery sequence run by logic that stays alive, the always-on recovery controller.

    Seven steps top to bottom: close acceptance at the source; fresh flush acknowledgement; reset the destination with init_d holding delivery off; release through the local reset synchroniser; history settles to the source toggle level; drop init_d so ready_d rises; reopen source traffic.
    Recovery order for a destination reset on a pulse crossing: close, flush, reset, release, rebuild history, then reopen.

    Read the chart top to bottom; traffic is closed from the first box until the last.

    • Box 2 is the cure for hazard 1: no word is in flight when the reset lands.

    • Box 5 is the cure for hazard 2: the XOR has a fresh baseline before any pulse can count.

    • Boxes 4 and 6 are the cure for hazard 3: release is synchronised and the source waits for ready.

    Recovery and removal close the timing side: every asynchronous release passes a reset synchroniser in its own domain (recovery). A timeout in box 5 keeps the link closed; it does not return ownership of an accepted event. Account accepted = delivered + cancelled + pending per epoch.

    Warning

    Limits: this flow is for a planned reset. An unexpected reset is detected with some latency, so it also needs a containment and cancellation policy. A fixed timer, or the absence of an event in flight, is not enough.

    Check yourself A watchdog resets the consumer domain only, mid-transfer. What breaks?

    The consumer loses protocol state and may duplicate the word in flight, while the producer waits for an acknowledge. The crossing needs the isolation and tolerance rules above, plus a randomised reset test.

    Common wrong answers

    Common pitfall

    Blind pulse stretching is unsafe, but bounded open-loop stretching is a valid alternative when clock limits are known. Guarantee high and low widths long enough for destination capture, including setup/hold and margin over all allowed clock modes; a conservative contract keeps each level across three destination sampling edges. Synchronise the stretched level and edge-detect it locally so multiple high samples become one event. Enforce event spacing and coordinated reset. If the destination can stop or the bounds cannot be guaranteed, use a handshake or FIFO instead.

    Check yourself A stretched level is sampled high on three destination cycles. Must it create three events?

    No. A destination rising-edge detector on the synchronised level emits one pulse. It must also observe a sufficiently long low interval before the next event; stretching without width and spacing guarantees is not a complete CDC protocol.

    • “A plain 2FF catches a one-cycle pulse if the destination is faster.” Only if the pulse is guaranteed to span enough destination edges (about three) in every clock mode; with unknown or changing clock ratios, or a fast source, use a toggle or handshake.

    • “One reset wire to both domains is enough.” The wire reaches each domain through its own synchroniser, so the domains still release in different cycles. Protocol tolerance or sequencing is still needed.

    Solution and testbench

    The toggle synchroniser with an init_d gate, and a bench that resets the destination at the start and between bursts of events. The comments at the top of the bench say what each phase checks.

    pulse_sync.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // Pulse crossing by toggling: each source pulse flips a level, a 2FF carries it,
    // and the destination turns each flip back into a one-cycle pulse.
    module pulse_sync (
      input  logic clk_s, rst_s_n, pulse_s,
      input  logic clk_d, rst_d_n, init_d,
      output logic pulse_d, ready_d, raw_pulse_d
    );
      logic toggle_s, q1, q2, q2_prev;
      always_ff @(posedge clk_s or negedge rst_s_n)
        if (!rst_s_n) toggle_s <= 1'b0;
        else if (pulse_s) toggle_s <= ~toggle_s;   // one flip per pulse
      always_ff @(posedge clk_d or negedge rst_d_n)
        if (!rst_d_n) begin
          q1 <= 1'b0; q2 <= 1'b0; q2_prev <= 1'b0; ready_d <= 1'b0;
        end else begin
          q1 <= toggle_s; q2 <= q1; q2_prev <= q2;
          ready_d <= !init_d;
        end
      // Controller holds source traffic closed throughout init and baseline capture.
      // Deassert init only after stable source history has traversed q1/q2/q2_prev.
      assign raw_pulse_d = q2 ^ q2_prev;            // diagnostic: unsafe without initialization
      assign pulse_d = ready_d && !init_d && raw_pulse_d;
    endmodule
    

    Remember

    • Turn the pulse into a level with a toggle, cross it, and XOR with the previous value to rebuild one pulse.

    • Each toggle level must last long enough for the destination to sample it, about three clean edges for open-loop use.

    • Reset crossings fail by cleared data, cleared history or release order. Block acceptance and establish a fresh baseline.

    Rule of thumb: never stretch a pulse blindly: toggle it or handshake it, and treat a mid-transfer reset as part of the protocol.

    How this was checked

    Bench Run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It delivers 61 events and resets destination history at both idle polarities. After 40 events the toggle is 0; after one more it is 1. It models the external controller and does not implement the full always-on barrier or unexpected-fault containment. Reset releases are ideal bench stimulus.

    Keep going

    • Practice: Pulse synchroniser across clock domains

    • Practice: A pulse missed in CDC because it was too narrow

    • Code lab: Reset domain crossing

    • Interview: run a mock interview on this topic

    Related topics

    • Pulse synchronisers

    • Reset domain crossing

    Previous

    332 / 350

    Next: Interview: Memories and Buses

    Up next

    Up nextInterview: Memories and Buses

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • A CDC review: what to check
    • Reset assertion vs release
    clk_dpulse_stoggle_sq2pulse_d
    One fast source pulse flips a toggle level that crosses into the slower clock and comes out as a single-cycle destination pulse