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
      • Register Access Sweeps
      • Address-Map and Interrupt Wiring Checks
      • Reset, Clock and Power Sanity
    • 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

←Integration and Connectivity Tests
  1. Topics
  2. SoC Design
  3. Top-Level Verification and Bring-up
  4. Integration and Connectivity Tests
  5. Address-Map and Interrupt Wiring Checks
On this page

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

    Address-Map and Interrupt Wiring Checks

    One access per region and hole, the alias pair, and one forced toggle per interrupt: the wiring proved.

    Why it matters

    Two NanoSoC bugs are wiring or map errors: the DMA interrupt lands on controller input 6 instead of 1, and the SBR slot overlaps the DMA slot through an 8 KB decode. The first passes every block test; the second is a decoder fault that a block test passes unless it checks the whole slot table. Software discovers the first as a handler that never runs and the second as data with bit 0 flipped. A map and wiring sweep discovers both in one short test by touching every region, every hole and every interrupt. Its one job is that sweep: the expected answer per address and the forced toggle per source.

    The core idea

    The map sweep reads one word per region and one per hole. Mapped regions return data: ROM, both SRAMs, all seven peripheral slots; the sweep runs once as a secure master, because SRAM1 and RSTPWR answer a non-secure access with an error. Holes H1, H2 and H4 must answer DECERR within two system clocks; hole H3 inside the APB window must answer PSLVERR, seen as SLVERR on AXI — the different responder is the point, and the sweep asserts the difference. Then the alias pair: read DMA CTRL from 0x4000_0000 and from 0x4000_0100 and require equal values, proving the sixteen images exist and are one register; and write the SBR CTRL START bit and require the DMA KEY unchanged, proving slots 0 and 1 do not overlap, which is planted bug 1 stated as a check.

    Interrupt wiring is proved by force, not by traffic: drive each source high in turn and read INTC RAW, requiring exactly the matching bit. Force irq_dma and require RAW bit 1 with bit 6 low — planted bug 3 fails exactly this line. Tie the reserved inputs 6 and 7 to zero and require RAW bits 6 and 7 low in every other step, so a stray connection has nowhere to hide. The default slave below is the responder the sweep assumes: a DECERR answer, never a hang. It is a sketch of the two-cycle response to one beat only; a denied burst needs the interconnect's burst rules (a read burst returns every R beat with RLAST, a write burst consumes every W beat and returns one B), taught in the default-slave lessons of the map section.

    nano_default_slave.sv
    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
    // NanoSoC teaching values: sketch of the default slave's single-beat response.
    // DECERR after two clk_sys cycles. One beat only: a burst needs one response
    // beat per requested beat (RLAST on reads, one B after the last W beat).
    module nano_default_slave (
      input  logic        clk,
      input  logic        rst_n,
      input  logic        sel,      // this slave selected, address unmapped
      input  logic        write,    // 1 for write, 0 for read (unused here: DECERR on both)
      output logic        ready,    // response valid
      output logic [1:0]  resp      // 2'b11 DECERR
    );
      logic [1:0] count;
    
      always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
          count <= 2'd0;
          ready <= 1'b0;
          resp  <= 2'b00;
        end else if (sel && count == 2'd0) begin
          count <= 2'd1;
          ready <= 1'b0;
          resp  <= 2'b00;
        end else if (sel && count == 2'd1) begin
          count <= 2'd2;
          ready <= 1'b1;
          resp  <= 2'b11; // DECERR
        end else begin
          count <= 2'd0;
          ready <= 1'b0;
          resp  <= 2'b00;
        end
      end
    endmodule
    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
    # Map and interrupt expectations as executable decoders. The expected decode
    # comes from the address map; the sweep runs against a good decoder and
    # against the planted-bug decoders and must fail on those. NanoSoC teaching values.
    def decode(addr, dma_window=0x1000):
        """Returns (target, response) for a secure read."""
        if addr >> 14 == 0: return ("ROM", "OKAY")
        if addr >> 16 == 0x2000: return ("SRAM0", "OKAY")
        if addr >> 16 == 0x2001: return ("SRAM1", "OKAY")
        if addr >> 16 == 0x4000:
            slot = (addr >> 12) & 0xF
            if dma_window == 0x2000 and addr & 0xFFFF < 0x2000: # bug 1: 8 KB DMA window
                return ("DMA", "OKAY")
            names = {0: "DMA", 1: "SBR", 2: "UART", 3: "SPI", 4: "GPIO", 5: "INTC", 6: "RSTPWR"}
            if slot in names: return (names[slot], "OKAY")
            return ("APB-default", "SLVERR") # hole H3: PSLVERR becomes SLVERR
        return ("xbar-default", "DECERR") # holes H1, H2, H4
    def map_sweep(dec):
        bad = []
        for addr, want in [(0x0, "ROM"), (0x2000_0000, "SRAM0"), (0x2001_0000, "SRAM1"),
                           (0x4000_0000, "DMA"), (0x4000_1000, "SBR"), (0x4000_2000, "UART"),
                           (0x4000_6000, "RSTPWR")]:
            if dec(addr)[0] != want: bad.append(hex(addr))
        for addr, want in [(0x4000, "DECERR"), (0x2002_0000, "DECERR"),
                           (0x4000_7000, "SLVERR"), (0x4001_0000, "DECERR")]:
            if dec(addr)[1] != want: bad.append(hex(addr))
        return bad
    assert map_sweep(decode) == []
    bug1 = lambda a: decode(a, dma_window=0x2000)
    assert map_sweep(bug1) == ["0x40001000"] # SBR base now answered by the DMA
    # interrupt wiring: force each source, read the INTC RAW bit
    GOOD = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5} # source irq index -> INTC input
    BUG3 = dict(GOOD); BUG3[1] = 6 # irq_dma lands on spare input 6
    def irq_sweep(wiring):
        bad = []
        for src in range(6):
            raw = 1 << wiring[src]
            if raw != 1 << src: bad.append(f"irq {src} lit RAW bit {wiring[src]}")
        return bad
    assert irq_sweep(GOOD) == []
    assert irq_sweep(BUG3) == ["irq 1 lit RAW bit 6"]
    print("PASS: 11 map probes clean; bug 1 and bug 3 are each caught by name")

    What the review looks for

    • The sweep table names the expected response per hole — DECERR or SLVERR — with the responder named, not just the code.

    • The alias pair and the overlap check are explicit lines: equal reads across images, KEY unchanged by SBR START.

    • Every interrupt force names its RAW bit, and the reserved inputs carry a tied-low assertion in all steps.

    Verify and debug

    A wrong hole response means the decoder changed without the map changing: check which level answered — interconnect default or APB default — and the generation flow that should keep them in step. An alias mismatch means the wrapper drops different bits than the sweep assumes: count the implemented paddr bits at the slave. An interrupt force that lights two RAW bits is a short between sources; one that lights none is an open, or a source pulse shorter than two clk_per cycles (83.3 ns) that the controller missed: sources must be levels held until cleared.

    Interrupt wired to the wrong input, planted bug 3: the source reaches a spare while software waits on the documented line, so polling works and interrupts never fire. Forcing each source against the RAW register catches it; generating the RTL wiring and the software table from one source prevents it.

    If asked how to verify interrupts without running traffic, answer force-and-read: drive each source, read RAW, ENABLE and PENDING, then TOP for priority. Traffic tests prove timing; forces prove wiring, and wiring is what breaks first.

    Check yourself The sweep reads H3 as DECERR instead of SLVERR. Which decoder is suspect?

    The APB slot decoder: H3 must be claimed by the APB default slave and returned as PSLVERR. DECERR means the interconnect default answered, so the access never reached the APB window — the top-level decode is wrong, not the slot table.

    Related topics

    • Register Access Sweeps

    • Next: Reset, Clock and Power Sanity

    • Memory Maps: Planted Bugs and Regression Hooks

    • Memory Maps: Default-Slave Design

    • SystemVerilog: bind, Attaching Verification to RTL

    • Verification First Principles: Formal Apps

    Previous

    197 / 289

    Next: Reset, Clock and Power Sanity

    Up next

    Up nextReset, Clock and Power Sanity

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error