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
    • Clock Sources and PLLs
      • Crystal, PLL and Dividers
      • PLL Wrapper and the Lock Handshake
      • PLL Settings Calculator
    • Dividers, Muxes and Glitch-Free Switching
    • Clock Gating Architecture
    • Clock Domain Planning
    • Top-Level Crossings
    • Always-On Domain, Wake Policy and a Timer Extension
    • Reset Sources and Reset Tree
    • Reset Sequencing and Release
  • 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
Loading lesson

←Clock Sources and PLLs
  1. Topics
  2. SoC Design
  3. Clock and Reset Architecture
  4. Clock Sources and PLLs
  5. PLL Wrapper and the Lock Handshake
On this page

    Part 5 of 14, lesson 2 of 24Part 5 of 14/Clock and Reset Architecture/Lesson 2 of 24All levels

    PLL Wrapper and the Lock Handshake

    Integrating the PLL macro: enable, lock counter, synchronised lock, and what holds the chip until lock.

    Why it matters

    The PLL is an analog macro in a digital tree, and the boundary between the two is where start-up bugs live. Software writes one enable bit, the macro answers with one lock bit, and between them sit a start-up delay, a 256-cycle lock counter and a synchroniser. This lesson owns that boundary: who drives what, how long each step takes, and which gates stay shut until lock is real. Its one job is the wrapper and the handshake; the frequency arithmetic belongs to the previous lesson.

    The core idea

    The wrapper lives in nano_rstpwr on clk_per, because the controller that sequences lock must itself run on a clock that does not need the PLL. Software enables the macro through RSTPWR PLL_CTRL bit EN, which resets to 1 so the cold-boot sequence starts locking without firmware. The macro answers with a lock flag that is asynchronous to every digital clock, so it crosses through a two-flop synchroniser (crossing X7) before anything acts on it. Between enable and lock the controller counts: 4 clk_per cycles of start-up, then 256 clk_per cycles of lock qualification. The lock counter alone is 256 cycles, 10.667 us; with the start-up the total is 260 cycles, 10.833 us. The gates open 2 clk_per after that, so the enable-to-gates time is 262 cycles, 10.917 us. Only then do the clk_sys and clk_cpu gates open, and the resets release later still, in the release-order lesson.

    Two states must never disagree: the enable the controller holds and the bypass the tree assumes. If firmware clears EN to save power in sleep, the tree must already be on the crystal path for every domain that still runs, and the wake sequence must re-lock before reopening the fast gates. The bypass inconsistency, running fast logic on a clock assumed PLL-clean while the PLL is off, is the subtler half of the classic PLL failure.

    Lock timing

    The counter values are NanoSoC teaching values from the NanoSoC specification, and the script recomputes them in slow-clock cycles and microseconds so the release-order lesson can reuse the total:

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    T_PER_NS = 1e9 / 24e6  # 41.6667 ns slow-clock period
    STARTUP = 4      # NanoSoC teaching value: macro start-up
    LOCK = 256       # NanoSoC teaching value: lock counter
    R3 = STARTUP + LOCK
    
    lock_us = LOCK * T_PER_NS / 1000
    r3_us = R3 * T_PER_NS / 1000
    assert abs(lock_us - 10.6667) < 0.001, lock_us
    assert abs(r3_us - 10.8333) < 0.001, r3_us
    # The gates open 2 clk_per later (step R4): enable to gates is 262 cycles.
    sync_ns = 2 * T_PER_NS
    assert abs(sync_ns - 83.333) < 0.01, sync_ns
    gates_us = (R3 + 2) * T_PER_NS / 1000
    assert abs(gates_us - 10.9167) < 0.001, gates_us
    # A counter that skipped the start-up would open the gates 4 cycles early.
    assert (LOCK + 2) * T_PER_NS / 1000 < gates_us
    print("PASS: lock 256 cycles = 10.667 us; enable-to-lock-qualified 260 = 10.833 us; to gates 262 = 10.917 us")

    What the review looks for

    • The wrapper diagram names the driver of EN, the synchroniser on lock, and every gate qualified by the synchronised lock.

    • The lock counter value appears once, in the controller, and every quoted wait derives from it.

    • The sleep path clears EN only after the tree is on bypass, and the wake path re-locks before reopening fast gates.

    Verify and debug

    Simulate the sequence with a lock model that deasserts for a bounded time, then asserts and stays: the gates must not open one cycle early, and a lock dropout mid-run must re-qualify through the full counter rather than resuming it. On silicon, a start-up that fails only sometimes, and only cold, points at lock timing before it points at reset: read back PLL_STATUS LOCK and the PWR_IRQ lock event before touching the reset tree.

    PLL not locked when released. Symptom: random start-up failure with the frequency out of range. Caught by sequencing simulations with a lock model and by emulation. Fixed with a lock-qualified clock enable plus a wait with margin, exactly the counter above.

    If asked how you know the PLL is locked, refuse the single-bit answer: the macro flag, qualified by a counter with margin, synchronised into the using domain, with a dropout path that restarts the count. Then quote 256 cycles.

    Check yourself Firmware clears PLL_CTRL EN during sleep and sets it on wake. What must the wake code wait for before reopening the fast gates?

    The full lock sequence again: 4 start-up plus 256 lock cycles on clk_per, about 10.833 us, seen through the synchronised LOCK flag. Reopening on the raw macro flag skips the sync latency and risks acting on a metastable lock.

    Related topics

    • Crystal, PLL and Dividers

    • Next: PLL Settings Calculator

    • Release Order and Timing

    Previous

    86 / 289

    Next: PLL Settings Calculator

    Up next

    Up nextPLL Settings Calculator

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error