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
      • Levels and What Only the Chip Can Show
      • The NanoSoC Top-Level Test List
      • Reuse, Regression and Signoff Evidence
    • Integration and Connectivity Tests
    • Firmware Co-Simulation
    • Performance Verification
    • Gate-Level and Power-Aware Simulation
    • Emulation and FPGA Prototyping
    • Bring-Up Readiness
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←SoC Verification Strategy
  1. Topics
  2. SoC Design
  3. Top-Level Verification and Bring-up
  4. SoC Verification Strategy
  5. Levels and What Only the Chip Can Show
On this page

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

    Levels and What Only the Chip Can Show

    Block, subsystem and chip scope; the failures that are invisible below the top; the level rule with NanoSoC examples.

    Why it matters

    Most of the ten planted NanoSoC bugs pass every block test as written, because each block is correct to its own specification and the failure needs the map, a neighbour, the power intent or the driver. Six of them (3, 4, 5, 6, 7, 8) are invisible to any block test; one (9) is correct block behaviour that becomes a bug only through the driver; and three (1, 2, 10) live inside integration blocks (the decoder, the reset sequencer, the bridge), where a block test would catch them only if someone wrote the cross-check. Nobody does, because what is missing is a map table, a release order or a timeout. The DMA bench cannot see that its interrupt reaches controller input 6, the SRAM model cannot see that software put stack and stream in the same bank, and no APB slave test can see that the CPU released from reset before the fabric. A strategy that merely runs more block tests keeps missing them. Its one job is the level rule: what belongs where, and what only the chip can show.

    The core idea

    Three levels, three scopes. Block level proves one block against its specification with its neighbours modelled: the DMA bench proves XOR, LEN handling and the interrupt equation. Subsystem level proves a cluster with real neighbours where interaction matters: the APB segment with its bridge and decoder proves slot decode, wait states and error propagation. Chip level proves the integrated whole with real everything: reset order, the address map as decoded, interrupt wiring end to end, boot to prompt, power modes, and performance against budgets. The level rule follows: run each test at the lowest level that can show its failure, because lower is faster, more controllable and easier to debug; and never assume a higher level repeats a lower one's proof.

    What only the chip can show is the complement of every boundary a lower level models away. On NanoSoC that is: the 8-bit DMA address port behind a 12-bit decoder (alias A1) and the byte-offset wiring into it (planted bug 4), the interrupt input index (planted bug 3), the reset release order (planted bug 2), the missing clamps (planted bug 6), the NS reset default against the secure-only SRAM1 (planted bug 7), the two LEN registers that must agree (planted bug 8), the BUSY-write and sticky-ERR contract (planted bug 9, a driver rule), and the clock gated during an access (planted bug 10). Most of these live in the wiring, the map table, the power intent or the driver, which is why the top-level test list exists. Three are different: the slot overlap (planted bug 1) is a decode error inside the APB decoder, the early CPU release (bug 2) is in the reset sequencer, and the missing timeout (bug 10) is in the bridge. A bench for each of those blocks fails them if it checks the whole slot table, the release order or a slave that never answers; the block benches as written check none of those, which is the point of the chip-level entries.

    Failure

    Visible at block?

    First level that shows it

    DMA XOR data error

    Yes, DMA bench

    Block

    Interrupt to wrong input (bug 3)

    No, bench models the controller

    Chip

    CPU released before the fabric (bug 2)

    No, each block has its own reset

    Chip

    Byte-offset wiring (bug 4)

    No, bench drives paddr directly

    APB subsystem (decoder and bridge real)

    NS default vs secure SRAM1 (bug 7)

    No, attribute lives in the map

    Chip

    SBR/DMA LEN mismatch (bug 8)

    No, two blocks plus software

    Chip with firmware

    Same-bank slowdown 361.4 to 180.7 MB/s

    No, one port per model

    Chip performance

    Slot overlap (bug 1), early CPU release (bug 2), no bridge timeout (bug 10)

    Only if the block bench checks the whole slot table, the release order, or a slave that never answers

    Block, if the cross-check is written; otherwise chip

    Pad pulls, supplies and the simultaneous-switching limit (pad bugs P1 to P3)

    No: no pad cell exists in the RTL

    Board and silicon only

    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
    # The level rule as a checker. Each failure lists the boundaries it needs to be
    # real; the lowest level that instantiates all of them is where it first shows.
    # The requirement sets are ILLUSTRATIVE: a teaching model of the planted bugs,
    # not a measurement. Changing the test changes the set (see the two bug 1 rows).
    LEVELS = ["block", "subsystem", "chip"]
    REAL = {
        "block": {"own-logic"},
        "subsystem": {"own-logic", "apb-decode", "apb-bridge"},
        "chip": {"own-logic", "apb-decode", "apb-bridge", "intc-wiring", "reset-tree",
                 "power-intent", "address-map", "firmware", "shared-sram-port", "clock-gate"},
    }
    FAILURES = {
        "xor data error": {"own-logic"},
        "byte-offset wiring (bug 4)": {"apb-decode", "own-logic"},
        "cpu released early (bug 2)": {"reset-tree"},
        "irq on input 6 (bug 3)": {"intc-wiring"},
        "missing clamps (bug 6)": {"power-intent"},
        "ns default vs sram1 (bug 7)": {"address-map", "firmware"},
        "len mismatch (bug 8)": {"firmware", "own-logic"},
        "same-bank slowdown": {"shared-sram-port", "firmware"},
        # the same bug moves up a level when the test changes: a decoder bench that
        # checks the whole slot table fails at block level; seen only as flipped data
        # it needs the decoder, the SBR write and software together
        "slot overlap, decoder bench checks the slot table (bug 1)": {"own-logic"},
        "slot overlap, seen as flipped data (bug 1)": {"apb-decode", "firmware"},
        "bridge bench with a slave that never answers (bug 10)": {"own-logic"},
        "clock gated during an access (bug 10)": {"clock-gate", "firmware"},
        "pad pull-down on spi_cs_n (pad bug P1)": {"pad-cell"},
    }
    def first_level(needs):
        for level in LEVELS:
            if needs <= REAL[level]:
                return level
        return None
    placed = {name: first_level(needs) for name, needs in FAILURES.items()}
    assert placed["xor data error"] == "block"
    assert placed["byte-offset wiring (bug 4)"] == "subsystem"
    chip_only = sorted(n for n, lvl in placed.items() if lvl == "chip")
    assert len(chip_only) == 8, chip_only
    assert sorted(placed.values(), key=str).count("block") == 3
    # the same bug lands on two levels depending on the test that looks for it
    assert placed["slot overlap, decoder bench checks the slot table (bug 1)"] == "block"
    assert placed["slot overlap, seen as flipped data (bug 1)"] == "chip"
    assert placed["bridge bench with a slave that never answers (bug 10)"] == "block"
    # the checker can fail: no simulated level instantiates a pad cell, so that failure
    # is unplaced and must be handed to the board and silicon plan
    unplaced = sorted(n for n, lvl in placed.items() if lvl is None)
    assert unplaced == ["pad pull-down on spi_cs_n (pad bug P1)"], unplaced
    assert first_level({"analog-supply"}) is None
    print("PASS: 3 block, 1 subsystem, 8 chip-level failures; the pad failure is board-only")

    What the review looks for

    • Every planned test names its level and the failure it shows, with the level rule quoted for any chip-level entry.

    • No failure is assigned below the first level that can show it, and none is left without a level.

    • The plan cross-references the owner-course strategy pages instead of restating them, and teaches only the NanoSoC instance.

    Verify and debug

    Audit the plan against a written list of integration failure modes, not against gut feel: list them, strike the ones with no NanoSoC surface, and confirm each survivor names a test at or above its showing level. A mode with no test is the plan's gap; a test with no mode is the plan's waste. Both get fixed in review, before either consumes simulation.

    End-to-end verification assumed from block results: each block green, the chip never booted. The Hardware Debug cost-of-a-bug lesson prices this escape; the fix is the top-level boot test in the next lesson, running before any performance claim is believed.

    If asked what belongs at chip level, answer with the boundary rule: anything crossing decode, clock, reset, power or software lives at the top. Then offer two NanoSoC proofs: the interrupt index and the two-LEN agreement.

    Check yourself The SBR passes its tests and the DMA passes its bench, yet the stream corrupts. Which level shows it and why?

    Chip with firmware: the corruption is a LEN mismatch between two blocks plus software, and no lower level instantiates all three together.

    Related topics

    • Next: The NanoSoC Top-Level Test List

    • Memory Maps: Memory-Map Verification

    • Verification First Principles: What to Verify Where

    • Verification First Principles: Reuse up the Hierarchy

    • Hardware Debug: The Cost of a Bug by Stage

    Previous

    190 / 289

    Next: The NanoSoC Top-Level Test List

    Up next

    Up nextThe NanoSoC Top-Level Test List

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Reuse, Regression and Signoff Evidence