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
    • The Whiteboard Framework
    • Design a SoC on a Whiteboard
    • Integration Storm and Budget War Scenarios
    • Rapid-Fire Questions by Section
    • Numeric Drills
      • Map, Bandwidth and Latency Drills
      • Reset, Clock, Interrupt and Pad Drills
      • Power, Queue and MTBF Drills
  • Capstone: Integrate NanoSoC14
Loading lesson

←Numeric Drills
  1. Topics
  2. SoC Design
  3. SoC Interview Prep
  4. Numeric Drills
  5. Map, Bandwidth and Latency Drills
On this page

    Part 13 of 14, lesson 14 of 16Part 13 of 14/Interview Prep/Lesson 14 of 16All levels

    Map, Bandwidth and Latency Drills

    Drills 1 to 3: region sizing with overlap checks, link budgets with burst splits, end-to-end latency.

    Why it matters

    Three questions open every design interview: where does it live, how fast does it move, how long does one access take. The answers are three formulas the candidate must own: power-of-two sizing with alignment, bandwidth as width times clock times efficiency, latency as the sum of stage delays. This lesson drills all three on NanoSoC numbers with checkers that prove each result.

    Drill 1: memory map sizing

    Formula: size = 2^ceil(log2(need)), base a multiple of size, waste = size minus need, select bits = 32 minus log2(size). Worked: the ROM needs 16 KB and takes a 16 KB window with zero waste, select bits [31:14]; each SRAM needs 64 KB and takes 64 KB with zero waste, select [31:16]. The seven peripheral slots need 7 x 4 KB = 28 KB, which would round up to 32 KB (4 KB waste) as one window; NanoSoC instead decodes a 64 KB APB window with select [31:16] and then 4 KB slots by address bits [15:12], so slots 7 to 15 form a 36 KB hole that answers with an error. The checker proves alignment and no overlap, and fails on a misaligned base or an overlap.

    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
    import math
    def window(need):
        return 1 << math.ceil(math.log2(need))  # next power of two
    def check(windows):
        spans = sorted((b, b + s) for _, b, s in windows)
        for name, b, s in windows:
            if s & (s - 1) or b % s:
                return f"{name}: base {hex(b)} not aligned to size {s}"
        for (a0, a1), (b0, b1) in zip(spans, spans[1:]):
            if b0 < a1:
                return f"overlap at {hex(b0)}"
        return "ok"
    needs = [("ROM", 0x0000_0000, 16 * 1024), ("SRAM0", 0x2000_0000, 64 * 1024),
             ("SRAM1", 0x2001_0000, 64 * 1024), ("APB", 0x4000_0000, 7 * 4096)]
    windows = []
    for name, base, need in needs:
        size = window(need)
        waste = size - need
        sel = 32 - int(math.log2(size))
        print(f"{name}: need {need // 1024} KB -> window {size // 1024} KB, waste {waste // 1024} KB, select [31:{sel}]")
        windows.append((name, base, size))
    assert check(windows) == "ok"
    # The peripheral need (28 KB) rounds up to 32 KB, but NanoSoC decodes a 64 KB window then 4 KB slots.
    assert window(7 * 4096) == 32 * 1024
    windows[3] = ("APB", 0x4000_0000, 64 * 1024)
    assert check(windows) == "ok" and 7 * 4096 <= 64 * 1024
    # The checker must be able to fail: a misaligned base and an overlap.
    assert "not aligned" in check([("X", 0x2000_8000, 64 * 1024)])
    assert "overlap" in check([("A", 0x2000_0000, 64 * 1024), ("B", 0x2000_8000, 32 * 1024)])
    print("PASS: bases aligned, no overlap, checker rejects a misaligned base and an overlap")

    Variation: add an eighth 4 KB peripheral slot (slot 7). The last mapped address moves from 0x4000_6FFF to 0x4000_7FFF, still inside the same 64 KB APB window, the slot decoder gains select value 7, and the unmapped hole shrinks from 36 KB to 32 KB. Predict the new end address before running, then add the slot to the checker.

    Drill 2: bandwidth with burst splits

    Formula: sustained = width x f x L/(L+1), plus splits at every 4 KB boundary the transfer crosses. Worked: one fabric link at 4 bytes and 96 MHz with 16-beat bursts gives 384 x 16/17 = 361.4 MB/s. The 8 KB boot image at 0x2000_0000 is 4 KB-aligned, spans exactly two pages, crosses one boundary, and needs 128 bursts of 64 bytes. Same-bank sharing halves each stream to 180.7 MB/s, which is why placement is a bandwidth decision.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    peak = 4 * 96e6 / 1e6
    for length in (1, 4, 8, 16):
        sustained = peak * length / (length + 1)
        print(f"L={length:2d}: {sustained:6.1f} MB/s")
        assert abs(sustained - {1: 192.0, 4: 307.2, 8: 341.3, 16: 361.4}[length]) < 0.15
    def segments(start, length, page=4096):
        out = []
        while length > 0:
            n = min(length, page - start % page)  # bytes left in this 4 KB page
            out.append(n)
            start, length = start + n, length - n
        return out
    def crosses(addr, nbytes, page=4096):
        return addr // page != (addr + nbytes - 1) // page
    segs = segments(0x2000_0000, 8192)
    bursts = sum(-(-seg // 64) for seg in segs)
    assert segs == [4096, 4096] and bursts == 128, (segs, bursts)
    assert crosses(0x2000_0FF0, 64) and not crosses(0x2000_0FC0, 64), "boundary rule"
    assert segments(0x2000_0800, 8192) == [2048, 4096, 2048]
    bursts48 = sum(-(-seg // 48) for seg in segments(0x2000_0800, 8192))
    print(f"aligned image: {len(segs) - 1} boundary, {bursts} bursts of 64 B; shifted image with 48 B bursts: {bursts48}")
    print("PASS: 361.4 MB/s at L=16; 1 split, 128 bursts for the image")

    Variation: start the same 8 KB image at 0x2000_0800. It now crosses two boundaries (0x2000_1000 and 0x2000_2000) and splits into 2 KB, 4 KB and 2 KB segments; the checker prints the split so you can predict the burst count for 64-byte and for 48-byte bursts before running.

    Drill 3: latency

    Formula: total = sum of stage cycles per domain converted to ns, plus 2 to 3 destination cycles per crossing, plus slave access. Worked: CPU word read 7 system plus 4 CPU clocks = 93.75 ns; slow-peripheral register read 9 system, 4 peripheral and 4 CPU clocks = 281.25 ns; the request and acknowledge bridge alone (2 + 2 peripheral clocks plus 2 + 2 system clocks) 208.33 ns; a 64-word DMA job of 72 system clocks = 750 ns. The checker re-derives all four from the periods.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    t_cpu, t_sys, t_per = 1 / 192e6, 1 / 96e6, 1 / 24e6
    word = 7 * t_sys + 4 * t_cpu
    slow = 9 * t_sys + 4 * t_per + 4 * t_cpu
    bridge = 2 * t_per + 2 * t_per + 2 * t_sys + 2 * t_sys  # request sync, access, response sync, respond
    dma64 = (64 + 8) * t_sys  # N words plus 8 clocks of pipeline fill and drain
    for name, got, want in [("word", word, 93.75), ("slow-periph", slow, 281.25),
                            ("bridge-alone", bridge, 208.33), ("dma64", dma64, 750.0)]:
        ns = got * 1e9
        assert abs(ns - want) < 0.02, (name, ns)
        print(f"{name:12s} {ns:8.2f} ns")
    # Variation: one extra system clock each way inside the bridge.
    slow2 = slow + 2 * t_sys
    assert abs(slow2 * 1e9 - 302.08) < 0.02
    print("PASS: 93.75, 281.25, 208.33 ns and 750 ns re-derived; variation 302.08 ns")

    Variation: add one extra system clock each way inside the request and acknowledge bridge (2 system clocks, 20.83 ns). Predict the new slow-peripheral total (281.25 + 20.83 = 302.08 ns) before running.

    What the review looks for

    • Each drill states the formula before the numbers, so a wrong input still shows a right method.

    • Every derived number carries its assert: alignment, efficiency, boundary count, nanosecond total.

    • Waste, splits and tails are quoted, not just the headline rate.

    Verify and debug

    Run each checker, then break one input deliberately: a misaligned base, a burst length of 3, a missing synchroniser term. The assert that fires names the rule you violated; if no assert fires, the checker is missing a rule and you just found the gap. Time yourself: all three drills plus variations inside thirty minutes.

    Burst crossing a 4 KB boundary: a DMA or converter that ignores the rule issues illegal bursts and corrupts the next page. Drill 2's split count is the whiteboard version of the protocol checker's boundary assertion.

    For bandwidth questions, always quote the triple: peak, efficiency, sustained. 384, 16 over 17, 361.4. The triple proves you know what eats the difference.

    Check yourself The interviewer changes the burst length to 8. Which numbers change and which do not.

    Efficiency falls to 8 over 9 and sustained to 341.3; peak 384 does not change, and the 128-burst image count doubles to 256 bursts of 32 bytes only if the burst size changes with it. State both halves.

    Related topics

    • Next: Reset, Clock, Interrupt and Pad Drills

    • SoC: Sizes, Alignment and Power-of-Two Windows

    • SoC: The 4KB Rule and Burst Splitting

    Previous

    263 / 289

    Next: Reset, Clock, Interrupt and Pad Drills

    Up next

    Up nextReset, Clock, Interrupt and Pad Drills

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Power, Queue and MTBF Drills