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
    • Firmware Co-Simulation
    • Performance Verification
    • Gate-Level and Power-Aware Simulation
    • Emulation and FPGA Prototyping
      • When to Leave Simulation
      • What Changes in the Design for Prototyping
      • Speed, Visibility and Hybrid Runs
    • Bring-Up Readiness
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Emulation and FPGA Prototyping
  1. Topics
  2. SoC Design
  3. Top-Level Verification and Bring-up
  4. Emulation and FPGA Prototyping
  5. What Changes in the Design for Prototyping
On this page

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

    What Changes in the Design for Prototyping

    What NanoSoC must replace or rewrite to run on a prototype: analog macros, clock gates, memories, power domains and clock scaling.

    Why it matters

    The RTL that goes to silicon does not run unchanged on a prototype: it contains an analog PLL, a power-on-reset cell, latch-based clock gates, power switches, isolation cells and memory macros that the platform does not have. Every replacement changes what the prototype can prove. Its one job is the list: what is replaced, how, and which NanoSoC bug or budget becomes invisible as a result.

    The core idea

    Keep the logic, replace the technology. The prototype build swaps each technology-specific element for a platform equivalent through a wrapper, so the integration RTL above the wrappers stays the same. The rule for the review is that every swap is written down with the behaviour it preserves and the behaviour it loses; the second column is the one that matters.

    NanoSoC element

    On the prototype

    Preserved

    Lost

    PLL (24 MHz in, 768 MHz out)

    The platform's clock generator, with all domain clocks scaled by one factor

    The 8 : 4 : 1 ratios; the wrapper's lock logic

    Real lock time (256 clk_per) and analog behaviour

    Power-on-reset cell

    A board or platform reset input

    RST_CAUSE bits for pad and software reset

    The POR threshold and supply ramp behaviour

    Latch-based clock gates (clk_cpu, clk_dma, clk_sbr)

    Clock enables on one free-running clock, one enable per flop

    Function: a block with CLK_EN cleared holds its state, so the bug 10 hang still happens

    Glitch-freedom, gating-cell timing, clock-tree power

    PD_SW power switches and 114 isolation clamps

    Absent: SLEEP is clock gating and reset only

    The reset and wake software flow

    Isolation (planted bug 6 is invisible), retention, power-up sequencing

    SRAM and ROM macros

    Block memories behind wrappers, ROM initialised with the real image

    Contents, 2-cycle read latency if the wrapper keeps it

    Macro timing; the single-port limit unless the wrapper enforces one access per clock

    Pads, crystal, SPI flash, UART terminal

    Board connectors, a host adapter, a real or modelled flash

    The pin-level protocols

    Pad timing and drive; the pad pulls (a pull-down on the chip-select pad, pad bug P1) and the simultaneous-switching limit (pad bug P2), which an FPGA I/O cell does not reproduce

    Two rows deserve care. The memory wrapper must keep one access per clock: a dual-port block memory would serve the SBR's read and write streams at once and make the same-bank slowdown of 361.4 to 180.7 MB/s disappear, so a performance run on the prototype would pass a trap that silicon fails. And the clock scaling must use one factor for every domain. NanoSoC runs 192, 96 and 24 MHz; dividing all three by 8 gives 24, 12 and 3 MHz with the ratios intact, so every crossing and every cycle-count latency in the boot and latency tables keeps its meaning. Scaling only the fast clocks would change the sys-to-per ratio and test a different chip.

    nano_gate_as_enable.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // Prototype replacement for a gated clock: the flops stay on the free-running
    // clock and the gate becomes an enable on each of them. Function is preserved,
    // the glitch-free gating cell and its timing are not.
    module nano_gate_as_enable (
      input  logic clk_sys,
      input  logic rst_n,
      input  logic clk_en,   // CLK_EN bit for this block
      input  logic d,
      output logic q
    );
      always_ff @(posedge clk_sys or negedge rst_n) begin
        if (!rst_n)      q <= 1'b0;
        else if (clk_en) q <= d;   // clk_en low: the state holds, as with a stopped clock
      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
    # Clock scaling for the prototype: one factor for every domain keeps ratios, cycle
    # counts and the UART and SPI settings meaningful. NanoSoC values from the clock table.
    SCALE = 8
    CPU, SYS, PER = 192e6 / SCALE, 96e6 / SCALE, 24e6 / SCALE
    assert (CPU / PER, SYS / PER) == (8.0, 4.0) # ratios unchanged
    BAUDDIV, CLKDIV = 13, 1
    baud = PER / (16 * BAUDDIV)
    spi_bps = PER / (2 * (CLKDIV + 1))
    silicon_baud = 24e6 / (16 * BAUDDIV)
    err_pct = (baud / 14_400 - 1) * 100
    print(f"UART {baud:.1f} baud ({err_pct:+.2f}% vs 14,400), SPI {spi_bps / 1e3:.0f} kb/s")
    assert abs(err_pct - 0.16) < 0.01 # the same +0.16% error as 115,200 on silicon
    assert abs(silicon_baud / baud - SCALE) < 1e-9
    boot_silicon_ms = 12.580917
    boot_proto_ms = boot_silicon_ms * SCALE # every time-based step stretches by the factor
    assert abs(boot_proto_ms - 100.647) < 0.01
    # the check can fail: scaling only the fast clocks changes the sys : per ratio
    bad_sys = 96e6 / SCALE
    bad_per = 24e6 # peripheral clock left at full speed
    assert bad_sys / bad_per != 4.0
    print(f"boot takes {boot_proto_ms:.1f} ms on the prototype; ratios 8 : 4 : 1 kept")
    print("PASS: scale by 8 keeps the ratios, UART at 14,400 baud, SPI at 750 kb/s")

    What the review looks for

    • A table of every technology swap with a preserved column and a lost column, signed by the person who owns the wrapper.

    • One scale factor for all domains, with the UART divisor, the SPI rate and the host-side settings recomputed from it.

    • The prototype runs the real ROM image and the real boot code, not a shortened copy, so the sequence proved is the one in silicon.

    Verify and debug

    When a prototype run disagrees with simulation, diff the platform changes before the design: confirm the clock enables hold state exactly as the gated clocks did, that the memory wrapper reproduces the read latency and the single port, and that the reset the board applies is released in the same staged order. A prototype that releases every reset at once hides planted bug 2 by construction: the CPU is never early because nothing is staged. Add the reset-order assertion to the prototype's wrapper, not only to simulation.

    Passing on the prototype, failing in silicon: the prototype has no power domains, so the two missing interrupt clamps (planted bug 6) never float, the chip never wakes spuriously, and a full sleep and wake soak passes for days. Only the power-aware simulation of the previous topic shows the bug. A clean prototype run is evidence about function, never about power intent.

    If asked what you change in the design to put it on an FPGA, list the technology elements: clock generator, clock gates to enables, memories behind wrappers, no power domains, board reset. Then say what each hides. The answer that only lists the changes is half an answer.

    Check yourself Why scale every NanoSoC clock by the same factor instead of only slowing the CPU and fabric clocks to fit the platform?

    The peripheral and power logic count cycles of clk_per, and the crossings depend on the 8 : 4 : 1 ratios. Changing one ratio changes the chip under test: the synchroniser latencies, the interrupt window and the APB bridge timing would no longer be those of the design that is taped out.

    Related topics

    • When to Leave Simulation

    • Next: Speed, Visibility and Hybrid Runs

    • Verification First Principles: FPGA Prototyping

    • Hardware Debug: Power-Intent Bugs

    Previous

    209 / 289

    Next: Speed, Visibility and Hybrid Runs

    Up next

    Up nextSpeed, Visibility and Hybrid Runs

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error