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
  • Power Architecture21
  • Interrupts, DMA and Peripherals15
  • Memories, Boot and Security21
  • IP Integration and Handoff21
  • Top-Level Verification and Bring-up21
    • SoC Verification Strategy
    • Integration and Connectivity Tests
    • Firmware Co-Simulation
    • Performance Verification
    • Gate-Level and Power-Aware Simulation
    • Emulation and FPGA Prototyping
      • When to Leave Simulation
      • What Changes in the Design for Prototyping
      • Speed, Visibility and Hybrid Runs
    • Bring-Up Readiness
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Emulation and FPGA Prototyping
  1. Topics
  2. SoC Design
  3. Top-Level Verification and Bring-up
  4. Emulation and FPGA Prototyping
  5. Speed, Visibility and Hybrid Runs
On this page

    Part 10 of 14, lesson 18 of 21Part 10 of 14/Top-Level Verification and Bring-up/Lesson 18 of 21All levels

    Speed, Visibility and Hybrid Runs

    Sizing a trace window, connecting NanoSoC's pins to host models, and which planted bugs each platform can find.

    Why it matters

    A prototype runs a boot in 100 ms and shows 64 signals; simulation shows all of them and takes minutes. The speed buys long runs and the visibility cost decides whether a failure on them can be explained. Its one job is the trade in numbers: how much of a run a trace buffer can see, how the chip's pins connect to host-side models, and which of the planted bugs a platform can and cannot show.

    The core idea

    A trace buffer is a window: probe width times depth is a fixed memory budget, and the window covers depth samples around a trigger. On an illustrative 64-bit by 8,192-sample buffer sampling clk_sys, one window covers 8,192 of the 1,207,768 cycles of a boot, 0.68 percent, so where the trigger sits is the whole game. A trigger on the symptom shows the silence after the bug; a trigger on an earlier consequence of the hypothesis shows the cause. The Hardware Debug lesson linked below teaches the method of aiming and replaying windows; here the arithmetic fixes how much room there is.

    The chip's pins are connected to host-side models so that the prototype boots like the chip would: the UART transmit pin to a terminal, the SPI pins to a flash model holding the 8,192-byte image (the loader reads 8,196 bytes with its 4-byte command), the GPIO pins to scripted levels, the reset pin to a script that can hold it as long as a lab bench would. In emulation the same models run as transactors beside the design. The models are part of the test: a flash model that answers faster than the real part hides a loader bug.

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    # Trace-window sizing and the platform coverage check. The buffer size is
    # ILLUSTRATIVE; cycle counts and the 72-cycle DMA job come from the boot flow.
    PROBES, DEPTH = 64, 8192 # 64 bits wide, 8,192 samples: a 512 Kbit budget
    BOOT_CYCLES = round(12580.917 * 96)
    coverage = DEPTH / BOOT_CYCLES * 100
    window_us = DEPTH / 12e6 * 1e6 # sampled at the prototype's 12 MHz clk_sys
    print(f"window {DEPTH} samples = {window_us:.0f} us on the prototype; {coverage:.2f}% of one boot")
    assert PROBES * DEPTH == 524_288
    assert abs(coverage - 0.68) < 0.01
    # a window triggered on irq_dma must hold the whole 72-cycle job plus the interrupt path
    JOB, IRQ_PATH_MAX, MARGIN = 72, 35 / 2, 40 # irq: 35 clk_cpu cycles = 17.5 clk_sys
    need = JOB + IRQ_PATH_MAX + MARGIN
    assert need < DEPTH # fits with a large margin
    # Which planted bugs each platform can show, as a small capability model (ILLUSTRATIVE
    # requirement sets): a platform finds a bug if it has every capability of one of the bug's
    # alternatives. The emulator keeps the staged reset only if its wrapper does.
    PLATFORMS = {
        "rtl sim": {"firmware", "staged-reset"},
        "gate+power sim": {"firmware", "staged-reset", "timing-checks", "power-intent"},
        "emulator": {"firmware", "staged-reset"},
        "fpga": {"firmware", "real-flops"}, # a board reset releases everything at once
    }
    NEEDS = { # each bug: alternative capability sets, any one is enough
        1: [{"firmware"}], # overlap: any run that writes SBR CTRL
        2: [{"staged-reset"}], # reset order
        3: [{"firmware"}], 4: [{"firmware"}], # wiring seen by the boot
        5: [{"real-flops"}, {"timing-checks"}], # unsynchronised crossing
        6: [{"power-intent"}], # missing isolation
        7: [{"firmware"}], 8: [{"firmware"}], 9: [{"firmware"}], 10: [{"firmware"}],
    }
    def finds(platform, bug):
        return any(need <= PLATFORMS[platform] for need in NEEDS[bug])
    def found_by(bug, platforms=PLATFORMS):
        return [p for p in platforms if any(n <= platforms[p] for n in NEEDS[bug])]
    assert all(found_by(b) for b in NEEDS) # every planted bug has a platform that can show it
    assert found_by(6) == ["gate+power sim"] # only the power-aware run
    assert found_by(2) == ["rtl sim", "gate+power sim", "emulator"] # the board hides it
    assert not finds("rtl sim", 5) and not finds("emulator", 5) # no real flops, no timing checks
    assert finds("gate+power sim", 5) and finds("fpga", 5) # timing checks can flag it; real flops rarely fail
    # the check can fail: take the power intent away and bug 6 has no platform left
    no_power = {p: caps - {"power-intent"} for p, caps in PLATFORMS.items()}
    assert found_by(6, no_power) == []
    # what the SHIPPED BOOT exercises: it never writes CLK_EN = 0, mismatches a LEN, or writes
    # while BUSY, and the ROM clears NS, so bugs 7 to 10 need directed tests
    TRIGGER = {1: "sbr-start", 2: "reset-release", 3: "irq-wait", 4: "dma-register-read",
               7: "ns-left-default", 8: "len-mismatch", 9: "write-while-busy", 10: "clk-en-zero"}
    BOOT = {"sbr-start", "reset-release", "irq-wait", "dma-register-read"}
    boot_finds = sorted(b for b, t in TRIGGER.items() if t in BOOT)
    assert boot_finds == [1, 2, 3, 4], boot_finds
    assert sorted(b for b, t in TRIGGER.items() if t in BOOT | {"ns-left-default"}) == [1, 2, 3, 4, 7]
    print("PASS: window sized; bug 6 only by the power-aware run, bug 5 by timing checks or real flops, the boot finds 1 to 4")

    Planted bug

    RTL simulation

    Gate-level and power-aware simulation

    Emulator

    FPGA prototype

    1 Address overlap

    Sweep finds it

    Not needed

    Any run that writes SBR CTRL (the boot does)

    Same, slower to diagnose

    2 Reset release order

    Assertion finds it (the boot hangs too)

    Gate-level finds release skew

    Found if the reset staging is kept

    Hidden if the board resets everything at once

    3, 4 Interrupt input, byte-offset wiring

    Sweeps find them; the boot self-test too

    Not needed

    The boot finds them

    The boot finds them, with few probes

    5 Unsynchronised crossing

    Misses it unless the bench randomises clock phase and models a violation as X; structural CDC checking is the guard

    Can flag a timing violation on the path (the library check turns the flop output to X)

    Passes: the model has no metastability

    May fail rarely: real flops, different clocks

    6 Missing isolation

    Passes

    Finds it in one SLEEP entry

    Passes

    Passes: no power domains

    7, 8, 9, 10 NS default, LEN mismatch, BUSY writes, CLK_EN = 0

    Directed tests find them; the shipped boot does not exercise them

    Not needed

    Directed tests, fast

    Directed tests, few probes

    Pad bugs P1 to P3 (pulls, simultaneous switching)

    Not shown: no pad cell in the RTL

    Not shown

    Not shown

    Not shown: an FPGA I/O cell does not reproduce the pad pulls or the SSO limit; board and silicon only

    Two cautions. The shipped boot exercises only bugs 1 to 4: its self-test writes one LEN to both blocks, writes 0x3, clears 0x6 and never writes CLK_EN = 0, and its ROM clears NS, so bugs 7 to 10 are found by the directed tests of the top-level list, not by the boot (bug 7 would appear in the boot only if the ROM forgot to clear NS). And the last row is why the board bring-up topic exists: the pad pulls, the two supply rails and the simultaneous-switching limit are properties of the pad ring and the board, and no pre-silicon platform here shows them.

    What the review looks for

    • Each trace window is sized against the event it must hold, with the trigger and the pre- and post-trigger split written next to it.

    • Every pin model has a stated timing: the flash model runs at the real 6 Mb/s rate (scaled with the clocks), not instantly.

    • The coverage table above exists for the real project (it matches what the boot exercises, not what it could), and a bug with only one platform that can show it carries an owner for that platform.

    Verify and debug

    Check the setup before trusting a failure. Put a known pattern through each pin model and confirm the UART terminal reads the 16-character banner at the scaled baud rate, that the flash model returns the image the checksum expects, and that the trigger fires on the same cycle in two runs. A trigger that moves between runs means the run is not deterministic, which usually means an uncontrolled input or a free-running board clock, and replay-based debugging is impossible until that is fixed.

    The trigger on the symptom: the CPU stalls at PC = 0x0000_0000 with ARVALID high and no RVALID (planted bug 2). A buffer triggered on the stall holds 8,192 identical idle samples. The useful trigger is the cause the hypothesis predicts: rst_cpu_n rising while rst_sys_n is still low, with the window mostly before it. Write what you expect to see in the window before you arm it.

    If asked what you give up on a prototype, answer visibility and power: a few probes in a short window instead of every signal, and no power domains, so isolation and retention cannot be shown. Then name what the prototype is good at, the rare crossing failure that RTL simulation misses, and say that gate-level timing checks and the structural CDC check cover the same bug.

    Check yourself Why can the prototype show the unsynchronised interrupt crossing of planted bug 5 when RTL simulation cannot?

    RTL simulation models flops as ideal, so setup and hold violations never produce metastability and every run passes (gate-level timing checks can still flag the path). Real flops on a real board can go metastable, so a long soak can expose it as a rare failure; but with scaled clocks and different cells the failure rate is not the silicon's, so a clean prototype soak does not prove the crossing safe. The structural CDC check does.

    Related topics

    • What Changes in the Design for Prototyping

    • Package and Pads: I/O Ring and Pad Types

    • Package and Pads: Pad Count and Simultaneous Switching

    • Hardware Debug: Emulation and FPGA Prototyping

    • Verification First Principles: Emulation

    • Verification First Principles: Virtual Platforms and Hybrids

    • Hardware Debug: Counters and Performance Probes

    Previous

    210 / 289

    Next: I/O Ring and Pad Types

    Up next

    Up nextI/O Ring and Pad Types

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • When to Leave Simulation