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
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
    • Capstone Brief
      • Requirements, Deliverables and Data
      • Planted Bugs and Grading
    • Stage 1: Memory Map and Interconnect
    • Stage 2: Clocks, Resets, Power
    • Stage 3: Interrupts and Boot
    • Stage 4: Verification and Signoff
Loading lesson

←Capstone Brief
  1. Topics
  2. SoC Design
  3. Capstone: Integrate NanoSoC
  4. Capstone Brief
  5. Planted Bugs and Grading
On this page

    Part 14 of 14, lesson 2 of 14Part 14 of 14/Capstone: Integrate NanoSoC/Lesson 2 of 14All levels

    Planted Bugs and Grading

    The ten planted integration bugs with symptom, root cause and fix, plus the grading rubric.

    Why it matters

    A lab without known bugs teaches touring, not integrating. Ten real integration mistakes are injected into the clean lab data, one at a time, each one made possible by a genuine NanoSoC sharp edge: a narrow DMA port behind a wide decoder, a faster sync beating a slower fabric, a reset-safe register default that is not access-safe. Your grade is the fraction you catch with checkers, not with eyes.

    Goal, inputs and steps

    • Goal: memorise the ten bugs as symptom, root cause and fix, and the rubric weights.

    • Inputs: the table below; the behaviour of the DMA and SBR registers that each bug abuses.

    • Steps: for each bug write which stage catches it before reading the stage; after the lab, diff your prediction against the test matrix.

    Bug

    Symptom

    Root cause

    Fix

    Stage

    1 Address overlap

    SBR CTRL write flips DMA data bit 0

    DMA slot decoded as 8 KB, slots 0 and 1 overlap

    Decode addr[15:12] per 4 KB slot

    1

    2 Reset release order

    CPU stalls at 0x0000_0000, no RVALID

    rst_cpu_n released with rst_sys_n; first fetch lost

    CPU last: 8 clk_sys + 2 clk_cpu later

    2

    3 Mis-wired interrupt

    DMA irq high, INTC RAW bit 1 is 0, bit 6 is 1

    irq_dma tied to spare input 6

    Connect to input 1; per-IRQ test

    3

    4 Width and addressing

    Only CTRL reads right; STATUS, LEN, KEY take PSLVERR and a COUNT read silently returns STATUS

    paddr fed word addresses, DMA decodes byte offsets: 0x10 shifted right by 2 is 0x04

    Connect apb_paddr[7:0]

    1

    5 Unsynchronised crossing

    Missed interrupt once in thousands of jobs

    irq_dma into clk_per with no 2-flop sync

    2-flop synchroniser on every INTC input

    2

    6 Missing isolation

    Spurious irq_cpu in SLEEP; sleep/wake loop

    112 of 114 clamps; interrupts missed

    Clamp-0 on all 114 nets before power off

    2

    7 Secure attribute

    SBR STATUS.ERR on first beat from SRAM1

    SBR CTRL.NS resets to 1, SRAM1 secure-only

    Secure software clears CTRL.NS

    3

    8 Stream length mismatch

    ERR with COUNT 32, or SBR stuck BUSY

    SBR LEN and DMA LEN disagree

    One n_words written to both LENs

    3

    9 Contract traps

    Stale KEY; irq never drops; IRQ_EN cleared

    Ignored writes while BUSY; sticky ERR; CTRL rewrites IRQ_EN

    Wait BUSY=0; clear DONE and ERR; write 0x3

    3

    10 Gated clock hang

    After CLK_EN = 0 the first access to the idle DMA hangs the bus; only reset recovers

    clk_dma stopped, so no PREADY, and the bridge has no timeout

    256-cycle bridge watchdog completes it with PSLVERR

    2

    Two related traps are not numbered bugs. Placing the SBR source and destination in the same SRAM bank halves the stream rate (stage 1). And the SBR register slot is non-secure, so non-secure software can clear CTRL.NS and reach SRAM1 through the SBR: the secure partition is not closed in NanoSoC v1 (stage 3 and the readiness review).

    The checker

    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    MAP = [
        ("BOOTROM", 0x00000000, 0x4000),
        ("SRAM0", 0x20000000, 0x10000),
        ("SRAM1", 0x20010000, 0x10000),
        ("DMA", 0x40000000, 0x1000),
        ("SBR", 0x40001000, 0x1000),
        ("UART", 0x40002000, 0x1000),
        ("SPI", 0x40003000, 0x1000),
        ("GPIO", 0x40004000, 0x1000),
        ("INTC", 0x40005000, 0x1000),
        ("RSTPWR", 0x40006000, 0x1000),
    ]
    SECURE_ONLY = {"SRAM1", "RSTPWR"}
    SLOTS = ["DMA", "SBR", "UART", "SPI", "GPIO", "INTC", "RSTPWR"]
    T_CPU, T_SYS, T_PER = 1e9 / 192e6, 1e9 / 96e6, 1e9 / 24e6
    def end_of(base, size):
        return base + size - 1
    def overlaps(entries=MAP):
        bad = []
        xs = sorted(entries, key=lambda e: e[1])
        for a, b in zip(xs, xs[1:]):
            if b[1] < a[1] + a[2]:
                bad.append((a[0], b[0]))
        return bad
    def misaligned(entries=MAP):
        return [n for n, b, s in entries if b % s != 0]
    def decode(addr, slots=SLOTS):
        if addr >> 14 == 0:
            return "BOOTROM"
        if addr >> 16 == 0x2000:
            return "SRAM0"
        if addr >> 16 == 0x2001:
            return "SRAM1"
        if addr >> 16 == 0x4000:
            slot = (addr >> 12) & 0xF
            return slots[slot] if slot < 7 else "H3"
        if addr < 0x20000000:
            return "H1"
        if addr < 0x40000000:
            return "H2"
        return "H4"
    def response(addr, secure, slots=SLOTS):
        t = decode(addr, slots)
        if t in ("H1", "H2", "H4"):
            return "DECERR"
        if t == "H3":
            return "SLVERR"
        if t in SECURE_ONLY and not secure:
            return "SLVERR"
        return "OK"
    def sustained(peak, beats):
        return peak * beats / (beats + 1)
    
    # ---- this lesson starts here ----
    
    bugs = {1: "stage1", 2: "stage2", 3: "stage3", 4: "stage1", 5: "stage2",
            6: "stage2", 7: "stage3", 8: "stage3", 9: "stage3", 10: "stage2"}
    def covered(b):
        return {s: sum(1 for v in b.values() if v == s) for s in ["stage1", "stage2", "stage3"]}
    EXPECT = {"stage1": 2, "stage2": 4, "stage3": 4}
    assert sorted(bugs) == list(range(1, 11)) and covered(bugs) == EXPECT
    assert covered({**bugs, 4: "stage2"}) != EXPECT   # a mis-filed bug is visible
    assert decode(0x40000000) == "DMA" and decode(0x40001000) == "SBR"
    print("PASS: 10 planted bugs filed: stage1 2, stage2 4, stage3 4; stage 4 proves all ten")

    Expected output

    One PASS line with the per-stage catch counts. Stage 4 files no bug of its own: it runs the matrix that proves stages 1 to 3 caught all ten.

    What each failure means

    A count failure means a bug was filed under the wrong stage; the table above is the oracle. A decode failure means the engine's map disagrees with your bug-1 notes: slots 0 and 1 are the DMA and SBR windows, and both must decode clean.

    Hint ladder

    Hint 1: group the bugs by signal family, address, reset/clock/power, interrupt/DMA/contract, and the stage names itself. Hint 2: bugs 1 and 4 share the APB decode; bugs 8 and 9 share the LEN and CTRL registers. Hint 3: bug 10 looks like software but is a hardware timeout that is missing. Answer: stage 1 catches 1 and 4, stage 2 catches 2, 5, 6 and 10, stage 3 catches 3, 7, 8 and 9, stage 4 proves all ten.

    Grading rubric (illustrative NanoSoC teaching values): 40 percent for checkers that catch their bugs on both good and injected-bad data, 25 percent for correct root-cause statements quoting the exact register or cycle count, 20 percent for the final manifest check passing, 10 percent for the waiver-ageing review with every waiver evidenced, 5 percent for the readiness statement and its stated leftovers. A stage scores only when its checker prints PASS on the clean data and flags the injected fault.

    Fixing the symptom in software and calling the bug caught. Polling around a mis-wired interrupt hides bug 3 without fixing the wiring; the rubric pays only for the connectivity test that forces each source and checks its RAW bit.

    Pick any two bugs and contrast their evidence: bug 1 is deterministic on the first SBR write, bug 5 needs thousands of jobs. An interviewer who hears that distinction knows you have debugged both kinds.

    Check yourself Bug 6 says 112 of 114 clamps. Which two are missing, and why those two?

    The two interrupt lines irq_dma and irq_sbr: they look like control, not data, so the clamp audit that counts bus widths walks past them.

    Related topics

    • Back: Requirements, Deliverables and Data

    • Stage 1: Memory Map and Interconnect

    • Hardware Debug: The Cost of a Bug by Stage

    Previous

    267 / 289

    Next: Stage 1: Memory Map and Interconnect

    Up next

    Up nextStage 1: Memory Map and Interconnect

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error