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

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • The NanoSoC Tour
  • Reading Path
  • SoC Glossary10
  • SoC Metrics Reference
  • SoC Cheatsheet
  • What SoC Integration Is12
  • Architecture and Budgets21
  • Memory Maps and Address Decode26
  • Interconnect and Bus Fabrics26
  • Clock and Reset Architecture24
    • Clock Sources and PLLs
    • Dividers, Muxes and Glitch-Free Switching
    • Clock Gating Architecture
    • Clock Domain Planning
    • Top-Level Crossings
      • The Ten Crossings
      • Choosing a Mechanism per Crossing
      • Crossing Review Checklist
    • Always-On Domain, Wake Policy and a Timer Extension
    • Reset Sources and Reset Tree
    • Reset Sequencing and Release
  • Power Architecture21
  • Interrupts, DMA and Peripherals15
  • Memories, Boot and Security21
  • IP Integration and Handoff21
  • Top-Level Verification and Bring-up21
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Top-Level Crossings
  1. Topics
  2. SoC Design
  3. Clock and Reset Architecture
  4. Top-Level Crossings
  5. Choosing a Mechanism per Crossing
On this page

    Part 5 of 14, lesson 14 of 24Part 5 of 14/Clock and Reset Architecture/Lesson 14 of 24All levels

    Choosing a Mechanism per Crossing

    FIFO, handshake or two flops: the decision rules, FIFO depth arithmetic, and synchroniser MTBF.

    Why it matters

    A new signal needs to cross and three mechanisms compete. Pick the FIFO for a stream and it idles half empty; pick two flops for a bus and bits arrive on different cycles; pick a handshake for a fast stream and throughput collapses. The choice follows from what the signal is, not from taste, and its size follows from arithmetic. This lesson states the rules and prices both answers. Its one job is the choice and its sizing; the review that checks it is next.

    The core idea

    One bit that is already a level, held long enough, crosses on two flops: resets, enables, lock flags, interrupt lines. One bit that moves as a pulse crosses on a toggle or a handshake, because a pulse shorter than the destination period may never be sampled. Correlated multi-bit data, a bus whose bits must arrive together, crosses on a handshake when traffic is occasional and on an asynchronous FIFO when it streams. Counters cross gray-coded so only one bit moves per step. Anything else, a bus with independent two-flop synchronisers per bit, is the classic multi-bit error: the destination samples bits from different source cycles and reads a value that never existed.

    For the crossing circuits themselves see the CDC course: handshake variants, pulse synchronisers and the synchroniser selection guide. The integrator's arithmetic is twofold. FIFO depth must cover the burst that arrives while the read side drains, plus the synchroniser latency allowance, plus margin. Synchroniser reliability follows the MTBF exponential: each extra stage adds about a clock period to the resolving time, and the formula needs technology constants that the integrator takes as inputs, never invents.

    Worked case: a store burst of 4 beats on the W channel of X1, written on clk_cpu at 192 MHz and read on clk_sys at 96 MHz through the 4-deep FIFO of nano_axi_cdc_m. The formula gives 4 x (1 - 96/192) + 2 + 1 = 5 entries to absorb the burst with no stall, one more than the FIFO has. That is not a defect. The FIFO never overflows because the write side stops on full: the writer backpressures, which costs throughput, not data. A cache line fill goes the other way: it returns on the R channel (X2), written at 96 MHz and read at 192 MHz, so the fast reader drains it as it lands and capacity is no concern. The model below measures the peak before draining, shows that peak 4 means exactly full with zero margin, and shows that without flow control the same FIFO would lose data on a longer burst.

    example.py
    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
    # FIFO depth: burst x (1 - f_read/f_write) + allowance (illustrative: 2 for
    # synchroniser latency, 1 margin). Case: 4-beat store burst on W, X1.
    BURST, F_WRITE, F_READ = 4, 192e6, 96e6
    need = BURST * (1 - F_READ / F_WRITE) + 2 + 1
    assert need == 5.0, need            # more than the 4-deep NanoSoC-specification FIFO
    
    def run(depth, beats, read_start, flow_control):
        # One step per fast (write) cycle; the slow reader pops every 2nd cycle
        # once read_start cycles of synchroniser latency have passed.
        occ = peak = written = lost = stalls = 0
        cycle = 0
        while written + lost < beats:
            if occ == depth:
                if flow_control:
                    stalls += 1          # writer waits: no data lost
                else:
                    lost += 1            # beat written into a full FIFO
                    written += 0
            else:
                occ += 1
                written += 1
            peak = max(peak, occ)        # peak measured BEFORE draining
            if cycle >= read_start and (cycle - read_start) % 2 == 1 and occ > 0:
                occ -= 1
            cycle += 1
        return peak, stalls, lost
    
    # 4-beat burst, reads start after 4 fast cycles of sync latency: peak 4.
    assert run(4, 4, 4, False) == (4, 0, 0)   # exactly full, zero margin
    # A longer burst of 8 beats overflows an 4-deep FIFO without flow control...
    assert run(4, 8, 4, False)[2] > 0
    # ...but with full/empty flow control the writer stalls and nothing is lost.
    peak, stalls, lost = run(4, 8, 4, True)
    assert lost == 0 and stalls > 0, (peak, stalls, lost)
    # A deeper FIFO removes the stalls for the same burst.
    assert run(8, 8, 4, True)[1] == 0
    print("PASS: need 5 vs 4-deep; peak 4 is exactly full; flow control stalls, never loses")
    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # Synchroniser MTBF MTBF = e^(t_res/tau) / (Tw f_c f_d).
    # Tau and Tw are illustrative technology inputs, not NanoSoC measurements.
    import math
    TAU_PS, TW_PS = 20.0, 10.0  # illustrative inputs, labelled as such
    F_CLK, F_DATA = 192e6, 96e6
    T_CLK_PS = 1e12 / F_CLK
    
    def mtbf_years(stages):
        t_res_ps = T_CLK_PS - 100.0 + (stages - 2) * T_CLK_PS  # setup illustrative
        mtbf_s = math.exp(t_res_ps / TAU_PS) / ((TW_PS / 1e12) * F_CLK * F_DATA)
        return mtbf_s / (3600 * 24 * 365)
    
    assert mtbf_years(2) > 1e6, mtbf_years(2)  # two stages: comfortable
    assert mtbf_years(3) > mtbf_years(2)  # each stage multiplies the MTBF
    print("PASS: 2-flop MTBF far above need with illustrative constants; 3 flops higher")

    What the review looks for

    • Every new crossing states its signal class first and its mechanism second; the class decides.

    • FIFO depths show the burst arithmetic with the synchroniser allowance and margin as separate lines.

    • MTBF numbers name their tau and Tw inputs and label them illustrative; no MTBF is quoted without its constants.

    Verify and debug

    Stress each FIFO with continuous bursts at the worst ratio while the read side stalls at random: overflow or underflow convicts the depth. Sweep pulse crossings with ratio and phase sweeps: a pulse caught at one alignment and missed at another needs a toggle, not a faster clock. A depth too small for the burst under the ratio is caught by ratio-sweep simulations.

    Multi-bit bus crossing with independent synchronisers, and the missing synchroniser. Symptoms: occasional corrupt data, rare metastability failures at temperature extremes. Caught by structural CDC checks. Fixed with gray code for counters, handshakes or FIFOs for buses, and two flops for every single bit.

    If asked to size a FIFO, write the formula before the number: burst times one minus the rate ratio, plus synchroniser allowance, plus margin. Then say what you assumed: continuous write during the burst, uniform rates.

    Check yourself A 32-bit status bus crosses with one two-flop synchroniser per bit. The designer says all bits change together so it is safe. Why is it not?

    Together at the source still arrives skewed: each bit resolves through its own synchroniser with independent latency, so the destination can sample some bits from the new value and some from the old. Correlated bits need a handshake or a FIFO.

    Related topics

    • The Ten Crossings

    • Next: Crossing Review Checklist

    • CDC and RDC: Synchronizer Selection Guide

    Previous

    104 / 289

    Next: Crossing Review Checklist

    Up next

    Up nextCrossing Review Checklist

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error