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. Crystal, PLL and Dividers
On this page

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

    Crystal, PLL and Dividers

    From 24 MHz to 768 MHz to 192, 96 and 24: the reference, the multiply, the divides and the bypass.

    Why it matters

    On a cold boot the first thing the chip waits for is not software but physics: the crystal must start, and the PLL must lock to it. An integrator who cannot quote that chain cannot budget boot time, cannot say which logic runs during the wait, and cannot answer the first bring-up question, which clocks are alive right now. On NanoSoC the answer fits in one line: 24 MHz in, times 32, divided by 4 and 8, with the slow domain wired straight to the crystal.

    The core idea

    The crystal oscillator produces clk_xtal at 24.000 MHz and runs whenever the supply is on. It is the only timing reference the chip trusts at power-up, and the reset controller counts oscillator-ready cycles on it before anything else happens. The PLL takes that reference with divide R equal to 1 and feedback multiply N equal to 32, so the voltage-controlled oscillator runs at 24 times 32, which is 768 MHz. That sits inside the teaching VCO range of 600 to 1200 MHz with margin on both sides: far enough from the bottom that the loop stays stable, far enough from the top that it never saturates.

    Two post-VCO dividers derive the fast domains: divide by 4 gives clk_cpu at 192 MHz, divide by 8 gives clk_sys at 96 MHz. Integer divides of one VCO keep the two clocks phase-related, which matters for the domain plan later. The third domain, clk_per at 24 MHz, is the crystal itself, bypassing the PLL. The bypass is deliberate, not a shortcut: peripherals, the reset controller and the wake logic must run while the PLL is off, during lock, and in sleep, so they cannot depend on it.

    Clock

    Source

    Frequency

    Period

    Runs when the PLL is off

    clk_cpu

    VCO / 4

    192 MHz

    5.208 ns

    No

    clk_sys

    VCO / 8

    96 MHz

    10.417 ns

    No

    clk_per

    Crystal direct

    24 MHz

    41.667 ns

    Yes

    Diagram
    # not-run: NanoSoC frequency chain, NanoSoC teaching values
    VCO = 24 MHz x 32 / 1 = 768 MHz; range check 600 <= 768 <= 1200 passes
    clk_cpu = 768 / 4 = 192 MHz, period 1 / 192 MHz = 5.208 ns
    clk_sys = 768 / 8 = 96 MHz,  period 1 / 96 MHz = 10.417 ns
    clk_per = 24 MHz direct,      period 1 / 24 MHz = 41.667 ns
    Ratios clk_cpu : clk_sys : clk_per = 8 : 4 : 1

    The calculator

    One short script derives the whole chain and checks it, so no lesson ever quotes a frequency it did not compute. Run it whenever the NanoSoC specification changes; it asserts the VCO range, both divides and the exact 8:4:1 ratios.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    XTAL = 24e6
    R, N = 1, 32
    VCO_LO, VCO_HI = 600e6, 1200e6
    
    vco = XTAL * N / R
    assert VCO_LO <= vco <= VCO_HI, vco
    cpu = vco / 4
    sys = vco / 8
    per = XTAL
    assert cpu == 192e6, cpu
    assert sys == 96e6, sys
    assert per == 24e6, per
    assert (cpu / per, sys / per) == (8.0, 4.0)
    periods = {n: 1e9 / f for n, f in [("cpu", cpu), ("sys", sys), ("per", per)]}
    assert abs(periods["cpu"] - 5.2083) < 0.001, periods
    assert abs(periods["sys"] - 10.4167) < 0.001, periods
    assert abs(periods["per"] - 41.6667) < 0.001, periods
    print("PASS: 24 MHz x32 = 768 MHz VCO; /4 = 192, /8 = 96, bypass = 24")

    What the review looks for

    • Every quoted frequency traces to the crystal through N, R and one divider, with the VCO range check attached.

    • The bypass is drawn as a design decision with its reason, never as an accident: always-on logic must not depend on the PLL.

    • No block takes a clock the table does not list; the domain plan assigns each block one of these three.

    Verify and debug

    On the bench, measure all three frequencies against the crystal before anything else: a wrong divider strap shows up as an exact integer ratio error, and a PLL that never locks leaves the two fast clocks dead while the slow one runs. If only the fast clocks are wrong, suspect the divider programming; if they are absent, suspect lock, which is the next lesson.

    PLL released before lock: reset or clock enables come out while the VCO is still settling, so the first microseconds run at the wrong frequency and start-up fails at random. It is caught by sequencing simulations with a lock model and fixed with a lock-qualified enable, which the next lesson builds.

    If asked why the multiply is 32, answer with the range: 24 times 32 lands mid-range at 768 MHz, and the two divides then land exactly on useful frequencies. Offer to redo it for a different crystal.

    Check yourself A cost-reduced board fits a 20 MHz crystal. Which two numbers must change to keep the fast domain frequencies, and what else moves?

    R and N change together. 768 = 20 x N / R gives N / R = 38.4 = 192 / 5, so R = 5 and N = 192, with the phase detector at 4 MHz (the calculator's N range of 64 would have to grow). Moving the VCO target to 760 or 800 MHz would change the domain frequencies, so it is not an option. The dividers stay and clk_cpu and clk_sys stay at 192 and 96 MHz. But clk_per is the crystal itself and becomes 20 MHz, so everything counted in clk_per cycles changes: the UART and SPI divisors, the 41.667 ns period (50 ns), the 256-cycle lock time (12.8 us instead of 10.667 us) and every boot wait in the release table.

    Related topics

    • Next: PLL Wrapper and the Lock Handshake

    • RTL: PLL Lock and Reset Coordination

    Previous

    85 / 289

    Next: PLL Wrapper and the Lock Handshake

    Up next

    Up nextPLL Wrapper and the Lock Handshake

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • PLL Settings Calculator