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
    • Interrupt Controller Integration
    • Interrupt Routing and Latency
    • DMA Integration
    • Peripheral Subsystem
      • UART Integration
      • SPI and GPIO Integration
      • Bridges, Clocks and Bring-Up Order
    • Pad Muxing and GPIO
  • 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
Loading lesson

←Peripheral Subsystem
  1. Topics
  2. SoC Design
  3. Interrupts, DMA and Peripherals
  4. Peripheral Subsystem
  5. Bridges, Clocks and Bring-Up Order
On this page

    Part 7 of 14, lesson 12 of 15Part 7 of 14/Interrupts, DMA and Peripherals/Lesson 12 of 15All levels

    Bridges, Clocks and Bring-Up Order

    The two APB segments, what each peripheral access costs, and the order software brings the subsystem up.

    Why it matters

    This lesson has one job: price the plumbing and order the boot. The UART, SPI and GPIO do not hang off the fast fabric: they sit on a 24 MHz APB segment behind a clock-domain crossing, and two peripheral siblings, the DMA and the stream bridge, sit on a 96 MHz APB segment in front of it. Every register touch in this section pays the bridge toll, every peripheral shares one reset, and the bring-up order is forced by dependencies: clocks before release, controller before DMA self-test, UART before the banner, SPI before the image. Write the order down once and every later section reuses it.

    The core idea

    The AXI-to-APB bridge plus the slot decoder translate each fabric access into APB: one bridge-accept cycle, three APB clocks on the fast segment for the DMA and bridge registers, then bridge-respond and fabric return. Behind the APB clock bridge the five slow peripherals each take two 24 MHz clocks per APB access plus the request and response synchronisation, which total 208.33 ns for the whole slow-segment access path, APB beats included. The blocking, one-access-at-a-time totals are 125 ns for a DMA or bridge register read from the CPU and 281.25 ns for a UART, SPI, GPIO, controller or reset-controller register read. Nothing here is pipelined or posted from software's view: each access completes before the next starts, which is why the boot table can simply add them.

    Resets are shared per segment, not per block: rst_per_n releases the UART, SPI, GPIO, controller, reset controller and the slow side of the crossing together, 2 clk_per cycles after the oscillator is ready. The DMA and bridge release with rst_sys_n much later, after the PLL locks and the gates open. Bring-up order follows the hardware: release, read the reset-cause register first so the cause is never lost, enable the UART and print the banner as the first signs of life, run the DMA self-test while the fabric is idle, then load the image over SPI and check it. A secure note belongs here: the reset controller is secure-only, so non-secure software cannot issue the software reset or gate clocks; the boot ROM runs secure and owns those registers throughout.

    Worked example: the peripheral bring-up bill

    The script below adds the peripheral-side accesses from the boot flow: three UART configuration writes, the 16-character banner, the DMA self-test register traffic, and the SPI image load, confirming the NanoSoC boot total of 12.581 ms and showing where each microsecond goes.

    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
    T_CPU = 1 / 192e6
    per_access = 281.25e-9   # one clk_per peripheral register access
    dma_access = 125e-9      # one DMA/SBR register access from the CPU
    uart_cfg = 3 * per_access
    assert abs(uart_cfg - 843.75e-9) < 1e-12
    banner = 16 * 10 / (24e6 / (16 * 13))
    assert abs(banner - 1386.667e-6) < 1e-9
    T_SYS = 1 / 96e6
    dma_selftest = 5 * dma_access + 7 * dma_access + 72 * T_SYS + 135.4e-9 + 6000e-9
    print(f"UART config: {uart_cfg * 1e9:.2f} ns")
    print(f"banner: {banner * 1e6:.1f} us")
    print(f"DMA self-test: {dma_selftest * 1e6:.3f} us")
    assert abs(dma_selftest - 8.385e-6) < 0.05e-6
    spi_load = (8192 + 4) * 8 / 6e6
    total = 53.948e-6 + 125e-9 + 10.667e-6 + 281.25e-9 + uart_cfg + banner
    total += dma_selftest + spi_load + 192e-6
    print(f"reset + clear + cause + UART + banner + DMA + SPI + checksum:")
    print(f"  total {total * 1e3:.3f} ms")
    assert abs(total - 12.581e-3) < 0.002e-3
    share = spi_load / total
    print(f"SPI share: {share * 100:.1f}%")
    assert share > 0.86
    print("PASS: boot totals 12.581 ms; SPI load is 86.9%")

    What the review looks for

    • Every peripheral access in every boot-time claim uses 281.25 ns for slow registers and 125 ns for fast ones, never a guessed round number.

    • The bring-up order is written as a numbered list with the dependency for each step: cause before config, UART before banner, self-test before image.

    • The reset-cause register is read before any write to any peripheral, and the secure-only registers have an owner that runs secure.

    Verify and debug

    Time the banner on the bench: 1,386.7 us at the reset divider is the cheapest oscilloscope check that the crystal, the divider and the peripheral clock are all correct. If one peripheral answers and the others do not, the APB slot decoder is the suspect, not the blocks: confirm the slot number in address bits 15 down to 12. If no slow peripheral answers but DMA registers do, the APB clock bridge is held in reset or its clocks are gated; if nothing answers, check rst_sys_n, rst_per_n and the PLL lock first, then the bridge; the reset-cause register is itself an APB register behind that bridge, so it cannot answer either. Once any register answers, RST_CAUSE tells you which reset fired.

    APB bridge ignores PREADY or PSLVERR: the bridge assumes zero-wait access or drops the error, so a slow peripheral returns stale data and errors vanish silently. The NanoSoC bridge honours both by construction; the test that proves it randomises wait states and injects an error per slave. The partial sibling is the address-offset bug: word addresses wired to the DMA's byte-offset port, so STATUS, LEN and KEY answer PSLVERR, a COUNT read silently returns STATUS, and only CTRL is right.

    If asked what a peripheral register read costs, answer 281.25 ns with the stage breakdown, and 125 ns on the fast segment. The follow-up is why the UART init costs under a microsecond while the banner costs a millisecond: registers are nanoseconds, wire bits at 115 kilobaud are microseconds.

    Check yourself Non-secure application code tries to gate the DMA clock through CLK_EN and the access faults. Correct behaviour or bug?

    Correct behaviour: the reset controller slot is secure-only, so the interconnect returns SLVERR to the non-secure access. Clock policy belongs to secure firmware; the application asks through a call, never through the register.

    Related topics

    • SPI and GPIO Integration

    • Next: Pad Muxing and GPIO

    • Protocol First Principles: Bridges and Protocol Conversion

    Previous

    147 / 289

    Next: Pad Muxing and GPIO

    Up next

    Up nextPad Muxing and GPIO

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • UART Integration