β: This English translation is in beta — the Traditional-Chinese original is the authoritative version.
Worked Examples
This page is the hands-on worked-example bank for ISF / phase noise / jitter. The theory pages show where the formulas come from; here you learn to plug in the numbers, compute all the way through, check the units, and verify with one line of Python. All formulas are carried over verbatim from [the AUTHORING_SPEC authoritative formula table]; numbers follow numerical_feeling and the spec Section 8 canonical values ( pC, , GHz, dBc/Hz).
How to use this page: cover the step-by-step solution, work each problem yourself, then check. The core skill of an analog designer is order-of-magnitude estimation at the whiteboard — seeing " dBc/Hz @ 1 MHz, 5 GHz" you should call out "a few hundred fs of jitter" within 30 seconds. The one-line Python at the end of each problem is only for checking, never a substitute for the hand calculation.
Four levels:
- (A) Basic conversions: rad ↔ fs, dBc ↔ linear, phase PSD ↔ . Drill until they become reflexes.
- (B) ISF → phase noise: Eq.(21)/(23)/(24) algebra — turn into dBc/Hz.
- (C) jitter integration: integrate to get ; the high-pass kernel of period jitter.
- (D) design back-calculation: how large a for dBc/Hz; how to choose the ring stage count .
Every problem follows a fixed format: Problem → step-by-step solution (with units) → Result → dimension check → one-line Python verification.
All Python calls real functions from simulations/common/ (see the spec Section 5 API) and runs as-is.
Level A: Basic conversions
This level has only two core relations — memorize them cold:
Example A1: phase → time (how many fs is 1 mrad at 5 GHz?)
Problem: GHz, mrad; find the timing error .
Step-by-step solution
Step 1: write the phase→time conversion (spec formula 17, ). The unit of is rad/s (angular frequency) and is rad; the quotient is seconds:
Step 2: evaluate the denominator: rad/s.
Result: fs.
Dimension check: ✓. Intuition anchor: at 5 GHz, "1 mrad ≈ 32 fs"; conversely "1 rad ≈ 31.8 ps" (the very same digits, offset by ). The period is ps, so 1 mrad is about of a period.
Python verification
from simulations.common.noise_utils import phase_to_time_error
print(phase_to_time_error(1e-3, 5e9) * 1e15, "fs") # -> 31.83 fs
Example A2: dBc/Hz → linear (how much is −100 dBc/Hz?)
Problem: dBc/Hz. Convert to linear (power ratio relative to the carrier, per Hz), then recover the phase PSD .
Step-by-step solution
Step 1: dBc/Hz is the "decibels relative to carrier" unit of ; invert by dividing by 10 and raising 10 to that power:
Step 2: under the small-angle single-tone PM approximation, (spec formula 16 and the Section 10.2 "" derivation), so back out the phase PSD:
Result: /Hz, rad²/Hz.
Dimension check: dBc/Hz is a dimensionless power ratio per Hz; is likewise 1/Hz; after the ×2 it reads as a phase PSD in rad²/Hz (rad² is the unit of phase variance; integrating the variance density over gives rad²) ✓. Mnemonic: every dB = one decade less in linear power; every dB = one decade less in voltage/phase amplitude.
Python verification
import numpy as np
from simulations.common.noise_utils import phase_psd_to_l_dbc_per_hz
s_phi = 2 * 10**(-100/10)
print(s_phi, "rad^2/Hz") # -> 2e-10
print(phase_psd_to_l_dbc_per_hz(s_phi), "dBc/Hz") # -> -100.0 (round trip consistent)
Example A3: injected charge → phase step → time (a 1 fC kick)
Problem (canonical Example A): pC, fC, , GHz. Find the phase step and timing error caused by a single impulse.
Step-by-step solution
Step 1: use the operational ISF definition (spec formula 5, ). is dimensionless and is dimensionless, so is a pure number (rad):
In degrees: .
Step 2: convert to time using the A1 conversion ( GHz):
Result: rad (), fs.
Dimension check: : dimensionless ✓; : ✓. Intuition: 1 fC ≈ 6240 electrons; even at the most sensitive phase it kicks out only ~16 fs. One kick is tiny, but noise kicks continuously and the phase integrator accumulates it (see convolution_derivation).
Python verification
from simulations.common.isf_utils import impulse_to_phase_step
from simulations.common.noise_utils import phase_to_time_error
dphi = impulse_to_phase_step(delta_q=1e-15, gamma_value=0.5, qmax=1e-12)
print(dphi, "rad ->", phase_to_time_error(dphi, 5e9)*1e15, "fs") # 0.0005 rad -> 15.92 fs
Example A4: phase sensitivity varies with injection phase (a taste of LTV)
Problem: an ideal LC oscillator has ISF . With the same fC and pC, inject at the zero crossing (, maximum waveform slope) and at the peak (, waveform top), and find in each case.
Step-by-step solution
Step 1: read off the ISF at both points. Note the phase convention here: with the peak is at and the (falling-edge) zero crossing at ; the ideal LC has :
Step 2: substitute each into ():
Result: injection at the zero crossing → mrad (maximum phase effect); injection at the peak → 0 rad (pure amplitude change, no phase change).
Dimension check: both are rad ✓. This is the essence of LTV (linear time-variant) behavior: the effect of the same impulse depends on which phase of the waveform it kicks. at the peak because the perturbation there is purely radial (amplitude) with no tangential (phase) component, and amplitude is pulled back by the restoring mechanism. See impulse_to_phase_shift.
Python verification
import numpy as np
from simulations.common.isf_utils import gamma_lc_ideal, impulse_to_phase_step
for name, th in [("ZC", np.pi/2), ("peak", 0.0)]:
g = gamma_lc_ideal(th) # = -sin(theta)
print(name, impulse_to_phase_step(1e-15, g, 1e-12), "rad")
# ZC -0.001 rad ; peak 0.0 rad
Level B: ISF → phase noise (algebra)
This level repeatedly uses three signature formulas (all [P1], carried verbatim from spec Section 3):
- White noise 1/f² [P1] Eq.(21), p.185:
- flicker 1/f³ [P1] Eq.(23), p.185: contains the and factors.
- 1/f³ corner [P1] Eq.(24), p.185: .
Reminder: the denominator of Eq.(21) is (SSB bookkeeping convention). A clean time-domain derivation gives ; the factor of 2 is a well-known minor dispute in the literature and does not affect the scaling or the dB/dec slope. See white_noise_to_phase_noise. This page uses the of the original [P1] expression throughout.
Example B1: white noise → L (canonical Example B, computed to the last digit)
Problem: GHz, MHz offset, pC, , white noise A²/Hz. Use Eq.(21) to find .
Step-by-step solution
Step 1: convert the offset frequency to angular frequency: rad/s, .
Step 2: evaluate the bracket of Eq.(21) (separate the dimensionless part from the part carrying units first):
Step 3: multiply (units checked below):
Step 4: take :
Result: dBc/Hz.
Dimension check: the bracket must be dimensionless (argument of a log). ; with ⇒ , , collect . One is still missing — it comes from the per-Hz nature of a PSD: the result is "relative power per Hz", so the argument is really 1/Hz, and after the log it is dBc/Hz ✓. (This is exactly why the units are easy to misread; just remember "the final answer is dBc/Hz".)
Intuition: this is the floor set by a single ideal white-noise source. Real circuits have multiple noise sources, cyclostationarity, and flicker; measurements come in tens of dB higher.
Python verification
import numpy as np
Grms, qmax, Si = 0.5, 1e-12, 1e-24
dw = 2*np.pi*1e6
L = 10*np.log10((Grms**2/qmax**2) * (Si/(4*dw**2)))
print(round(L, 2), "dBc/Hz") # -> -148.0
Example B2: use Parseval to get from , then compute L
Problem: the ideal-LC ISF is purely , i.e. only the first harmonic and all other . (a) Use Parseval (Eq.(20)) to find ; (b) with pC, , MHz, find L.
Step-by-step solution
Step 1 (a): Parseval ([P1] Eq.(20)): . Here , so
(Direct check: , which also gives ✓.)
Step 2 (b): substitute into Eq.(21) with :
Result: ; dBc/Hz.
Dimension check: is dimensionless (the are dimensionless) ✓; L same as Example B1, dBc/Hz ✓. Note is larger than the canonical , so L comes out about dB above B1 ( dB) — consistent.
Python verification
import numpy as np
from simulations.common.isf_utils import gamma_lc_ideal, gamma_rms
theta = np.linspace(0, 2*np.pi, 100000, endpoint=False)
Grms = gamma_rms(theta, gamma_lc_ideal(theta))
print("Grms =", round(Grms, 4)) # -> 0.7071
L = 10*np.log10((Grms**2/(1e-12)**2)*(1e-24/(4*(2*np.pi*1e6)**2)))
print(round(L, 2), "dBc/Hz") # -> -145.0
Example B3: symmetry and 1/f³ (the role of )
Problem: two oscillators with identical white noise and , MHz. A has a fully symmetric waveform (); B is slightly asymmetric (, ). Which one shows close-in 1/f³ upconversion? What is each 1/f³ contribution at kHz?
Step-by-step solution
Step 1: look at Eq.(23) — phase noise in the 1/f³ region is proportional to .
Step 2, for A: the bracket dBc/Hz (no flicker upconversion; the 1/f³ region is fully suppressed). In practice it never truly reaches (other mechanisms take over), but it can sit far below B.
Step 3, for B: , a finite value. Use Eq.(24) to compare the two 1/f³ corners:
For B, , so
That is, B's 1/f³ corner sits at kHz. For A, the corner .
Result: A (symmetric, ) has no 1/f³ upconversion; B () does, with a corner near kHz. Design rule: suppress through waveform symmetry and the 1/f³ corner can be pushed far below the device .
Dimension check: in Eq.(24), is dimensionless; multiplying by (rad/s) gives rad/s ✓.
Python verification
import numpy as np
w_1f = 2*np.pi*1e6
for name, c0, c1 in [("A", 0.0, 1.0), ("B", 0.2, 1.0)]:
Grms2 = 0.5*(c0**2 + c1**2) # Parseval: sum cn^2 = 2 Grms^2
corner = w_1f * c0**2/(2*Grms2)
print(name, "1/f^3 corner =", corner/(2*np.pi)*1e-3, "kHz")
# A 0.0 kHz ; B 38.46 kHz
Example B4: white-noise floor and the −20 dB/dec slope vs offset
Problem: reuse the B1 oscillator ( dBc/Hz, 1/f² region). What is L at MHz? (I.e. push the offset out by 10×.)
Step-by-step solution
Step 1: in Eq.(21), ; after the log this is const, i.e. every 10× in offset drops L by 20 dB ( dB/decade).
Step 2: goes from 1 MHz → 10 MHz (×10):
Result: dBc/Hz.
Dimension check: the argument of is dimensionless (a frequency ratio) ✓; the result is a dB difference, and adding it to dBc/Hz still gives dBc/Hz ✓. Intuition: "20 dB per decade" in the 1/f² region is the most-used visual slope on a phase-noise plot; compare dB/dec in the 1/f³ region.
Python verification
import numpy as np
Grms, qmax, Si = 0.5, 1e-12, 1e-24
def L(df): return 10*np.log10((Grms**2/qmax**2)*(Si/(4*(2*np.pi*df)**2)))
print(round(L(1e6),2), round(L(10e6),2), "dBc/Hz",
"slope =", round(L(10e6)-L(1e6),1), "dB/dec") # -148.0 -168.0 ; -20.0
Level C: jitter integration
Core idea: phase noise is a frequency-domain density, jitter is a time-domain rms; they connect via "integrate + square root + " (spec formulas 18, 19):
Example C1: L(f) → rms jitter (canonical Example C, 1/f² integration)
Problem: dBc/Hz, 1/f² slope, integrate from MHz to MHz, GHz. Find and .
Step-by-step solution
Step 1: convert the datasheet point to a phase PSD (using A2): rad²/Hz, MHz.
Step 2: write the 1/f² shape (anchored at ):
Step 3: integrate ():
So rad mrad.
Step 4: convert to rms jitter ( GHz):
Result: mrad, fs.
Dimension check: : ✓; : ✓. Intuition: the 1/f² integral is dominated by the lower limit () — where you start integrating matters most. With dBc/Hz @ 1 MHz instead (20 dB better = 1/100 the power, 1/10 the amplitude), the jitter shrinks to ~45 fs.

Python verification
import numpy as np
from simulations.common.noise_utils import leeson_one_over_f2, integrate_rms_jitter
f = np.logspace(6, 8, 4000) # 1 MHz -> 100 MHz
L = leeson_one_over_f2(f, L_ref_dbc=-100, f_ref=1e6) # 1/f^2 skirt
sigma_t, sigma_phi = integrate_rms_jitter(f, L, f0=5e9, fmin=1e6, fmax=100e6)
print(round(sigma_phi*1e3,2), "mrad ;", round(sigma_t*1e15,1), "fs") # 14.07 mrad ; 447.9 fs
Example C2: lower-limit dominance — what if the lower limit moves?
Problem: same spectrum as C1 ( dBc/Hz @ 1 MHz, 1/f², GHz), but integrate from kHz to 100 MHz. Estimate and compare with C1.
Step-by-step solution
Step 1: for 1/f², (lower-limit dominated). The lower limit moves from to (10× smaller), so is 10× larger:
Step 2: rad mrad (about × C1).
Step 3: s ps.
Result: ps (C1 was 448 fs). Lowering the limit by 10× → jitter grows by about ×.
Dimension check: same as C1 ✓. Intuition: this is why an "rms jitter" number is only meaningful with its integration band attached; the instrument's lower limit (or the PLL loop bandwidth) determines how much accumulated jitter you get to see.
Python verification
import numpy as np
from simulations.common.noise_utils import leeson_one_over_f2, integrate_rms_jitter
f = np.logspace(5, 8, 6000) # 100 kHz -> 100 MHz
L = leeson_one_over_f2(f, L_ref_dbc=-100, f_ref=1e6)
sigma_t, sigma_phi = integrate_rms_jitter(f, L, f0=5e9, fmin=1e5, fmax=100e6)
print(round(sigma_phi*1e3,1), "mrad ;", round(sigma_t*1e12,2), "ps") # ~44.7 mrad ; ~1.42 ps
Example C3: the high-pass kernel of period jitter
Problem: period jitter (the deviation of a single period, ) is the first difference of phase. Using the spec Section 10.2 kernel , estimate the period jitter for the C1 spectrum ( dBc/Hz @ 1 MHz, 1/f², GHz, ps).
Step-by-step solution
Step 1: write the period-jitter formula (spec Section 10.2 period/cycle-to-cycle kernel):
Step 2: understand what the kernel does: is high-pass — low frequencies () are suppressed (), so period jitter is not dominated by the low-frequency 1/f² lower limit (opposite to the accumulated jitter of C1/C2). This is why period jitter is usually much smaller than the "accumulated jitter" of the same spectrum.
Step 3: numerical integration (not feasible by hand — hand it to the computer; constants aligned with the spec kernel). See the Python below: fs.
Result: fs (versus the C1 accumulated fs — more than an order of magnitude smaller).
Dimension check: the kernel is dimensionless; gives rad²; dividing by the of … note the order: first rad², then dividing by gives s², and the square root gives s ✓. Resolved (v5): the exact prefactor for period/cycle-to-cycle jitter has been derived from first principles + Monte-Carlo verified in jitter_kernels (under the single-sided convention the kernel is with prefactor ; the 27.6 fs here is the band-limited version of that page's closed-form 28.28 fs) Cross-check against standard references; here we use the kernel given in spec Section 10.2, and the number is for order-of-magnitude feel only.
Python verification
import numpy as np
T, f0, fref, Lref = 1/5e9, 5e9, 1e6, -100
f = np.logspace(3, 10, 2_000_000) # wide band: the high-pass kernel suppresses low f
S_phi = 2 * 10**((Lref + 20*np.log10(fref/f))/10) # 1/f^2 phase PSD
kernel = np.abs(1 - np.exp(-1j*2*np.pi*f*T))**2 # first-difference high-pass kernel
trapz = getattr(np, "trapezoid", np.trapz)
sigma_T = np.sqrt(trapz(S_phi*kernel, f)) / (2*np.pi*f0)
print(round(sigma_T*1e15, 1), "fs") # ~27.6 fs
Example C4: ring accumulated jitter
Problem ([P2] Eq.(8)): a ring has jitter proportionality constant (toy value). Find the accumulated rms jitter for measurement intervals s and ms.
Step-by-step solution
Step 1: the random-walk law ([P2] Eq.(8), the signature of an oscillator with no absolute time reference): .
Step 2: s:
Step 3: s:
Result: 1 μs → 10 ps; 1 ms → 316 ps. Interval ×1000, jitter ×.
Dimension check: has units of , is , and their product is s ✓ (which is also why carries that odd unit). Intuition: the phase of a ring (no high-Q tank) is a pure random walk — the longer you wait, the larger the error, and it never converges. This is exactly the time-domain picture of why rings are noisier than LC. Companion figure:

Python verification
import numpy as np
kappa = 1e-8 # sqrt(s)
for dt in [1e-6, 1e-3]:
print(dt, "s ->", kappa*np.sqrt(dt)*1e12, "ps")
# 1e-06 s -> 10.0 ps ; 0.001 s -> 316.2 ps
Level D: design back-calculation
Run the formulas in reverse: given a spec, find the required , how small must be, how many stages .
Example D1: how large must be for −120 dBc/Hz @ 1 MHz?
Problem: spec dBc/Hz, GHz. Assume a single white-noise source A²/Hz (1000× the canonical value, closer to a real node injection) and . Back-solve the required .
Step-by-step solution
Step 1: solve Eq.(21) for . First convert the spec to linear: .
Step 2: plug in numbers (, ):
Step 3: take the square root: C pC.
Result: pC (i.e. raise the canonical 1 pC by about 26%; at this noise level the spec is met).
Dimension check: : ; with , dividing by gives , and after absorbing the PSD's per-Hz it is ✓. Design intuition: , so doubling → 6 dB lower phase noise. Ways to increase : raise the swing or the node capacitance/current.
Python verification
import numpy as np
Grms, Si, dw, Llin = 0.5, 1e-21, 2*np.pi*1e6, 10**(-120/10)
qmax = np.sqrt(Grms**2 * Si / (4*dw**2 * Llin))
print(round(qmax*1e12, 3), "pC") # -> 1.258 pC
Example D2: with fixed, how small a for −120 dBc/Hz?
Problem: same spec and noise as D1 ( dBc/Hz, , MHz, GHz), but this time pC is fixed (the swing cannot be raised further). Back-solve the required .
Step-by-step solution
Step 1: solve Eq.(21) for :
Step 2: evaluate the numerator term by term: ; . Divide by : .
Step 3: .
Result: (the ISF rms must drop from 0.5 to 0.40, about a 20% reduction).
Dimension check: is dimensionless (same argument analysis as B1; all unit-bearing terms cancel) ✓. Design intuition: , so halving → 6 dB lower phase noise. Ways to lower : waveform symmetry (suppress ), schedule noise injection at phases where the ISF is small, more ring stages (see D3). D1 (tune ) and D2 (tune ) are two independent knobs toward the same spec.
Python verification
import numpy as np
qmax, Si, dw, Llin = 1e-12, 1e-21, 2*np.pi*1e6, 10**(-120/10)
Grms = np.sqrt(Llin * qmax**2 * 4*dw**2 / Si)
print(round(Grms, 3)) # -> 0.397
Example D3: choosing the ring stage count (frequency vs ISF)
Problem: build an GHz single-ended ring. (a) With per-stage delay ps, how many stages ? (b) Going from to stages (adjusting to hold ), use to estimate the phase-noise change in dB (looking at the factor only).
Step-by-step solution
Step 1 (a): ring frequency ([P2] Eq.(15)): .
Step 2 (b): ([P2] Eq.(16), p.794, re-verified in v7: the square root covers only the constant; the body text's @ and App.B Eq.(55) triple-confirm this. v3 had misread it as