β: This English translation is in beta — the Traditional-Chinese original is the authoritative version.
Lab 06 — White Noise → 1/f² Phase Noise
This lab runs the entire causal chain — white noise → ISF weighting → integration → phase — in the cleanest possible numerical form, so you can see with your own eyes how a flat (white, frequency-independent) current-noise power spectrum gets colored by the oscillator — a "phase integrator" — into ( dB per decade) phase noise.
Physical intuition (conclusion first): the oscillator's phase has no restoring force (a force that pulls a perturbation back), so every phase step kicked in by noise accumulates permanently — this is an integrator (a system that time-integrates its input; infinite memory). The integrator's transfer-function magnitude is , which is for a PSD. The input is flat (white noise), so the output is multiplied by . White in, out — not because the noise source is , but because phase is obtained by integration.
1. Learning objectives
- Verify by simulation the signature result of [P1]: white current noise becomes phase noise in an oscillator.
- Understand where the dB/decade slope comes from (the integrator, not the noise source).
- Quantitatively verify the theoretical prediction .
- Understand the famous factor-of-2 controversy: the clean time-domain derivation differs from [P1] Eq.(21) by a factor of 2, but the scaling and slope are entirely unaffected.
2. Mathematical model
The phase response is the LTV (linear time-variant) convolution expression [P1] Eq.(11), p.182:
Split it into three blocks: first phase-weight the noise with the ISF, then integrate. The input is white current noise with constant one-sided PSD (power spectral density) (Hz).
Integrating the white input, the clean time-domain result for the output phase PSD is
- Where it comes from: after the ISF weights the white noise, the average power is scaled by (the ISF's rms squared, see [P1] Eq.(20)), with in the denominator (normalization); the integrator is then in the frequency domain, i.e. for the PSD.
- Dimension check: is dimensionless, is Hz, is , is . Overall . Since , (dimensionless = rad²), so ✓.
This has the same scaling as the signature expression [P1] Eq.(21), p.185:
factor-of-2 teaching note (must read): the clean time-domain derivation "white noise × ISF → integrate" gives , corresponding to SSB (denominator ); whereas [P1] Eq.(21) is written with denominator . This factor of 2 comes from the SSB (single-sideband) bookkeeping convention — a famous minor controversy in the literature. It does not affect the scaling, nor the dB/decade slope — those are the physics. The simulation in this lab uses the clean time-domain version (denominator ), so the simulated curve sits on the time-domain theory line. See white_noise_to_phase_noise.
3. Block diagram
4. Core Python code
Verbatim from main() in simulations/lab_06_white_noise_phase_noise.py: three steps
(generate white noise → ISF weighting → cumsum integration), then Welch-estimate the phase PSD and overlay the theory line.
f0 = 1.0
fs = 256.0 # 256 samples per period
n = 2 ** 20 # ~4096 periods -> good low-freq resolution
t = np.arange(n) / fs
q_max = 1.0
S_i = 1.0e-4 # one-sided white current PSD [A^2/Hz] (normalized)
# ISF and its rms
theta_grid = np.linspace(0, 2 * np.pi, 4000, endpoint=True)
Grms = gamma_rms(theta_grid, gamma_lc_ideal(theta_grid)) # = 1/sqrt(2)
# 1) white current noise
i_n = white_noise(n, psd=S_i, fs=fs, rng=RNG)
# 2) ISF weighting
g = gamma_lc_ideal(2 * np.pi * f0 * t) * i_n / q_max
# 3) integrate (cumulative) -> excess phase
dt = 1.0 / fs
phi = np.cumsum(g) * dt
phi = phi - np.mean(phi) # remove the random-walk DC offset for PSD est.
# 4) estimate phase PSD
f, Sphi = estimate_psd(phi, fs, nperseg=2 ** 16)
# theory line
Sphi_theory = Grms ** 2 * S_i / (q_max ** 2 * (2 * np.pi * f) ** 2)
- Step 3,
np.cumsum(g) * dt, discretizes the in the convolution expression — the cumulative sum is the integrator, i.e. the source of the phase's "infinite memory". - The ISF is the ideal-LC
gamma_lc_ideal(), whose (because ).
5. Full script path
simulations/lab_06_white_noise_phase_noise.py
(Dependencies: white_noise and estimate_psd from simulations/common/noise_utils.py;
gamma_lc_ideal and gamma_rms from simulations/common/isf_utils.py.)
How to run: python scripts/run_all_sims.py (generates all figures into static/figures/).
6. Parameter table
| Parameter | Variable | Value | Notes |
|---|---|---|---|
| Oscillation frequency | f0 | (normalized) | the whole lab uses normalization; absolute dBc/Hz is computed in lab_08 |
| Sampling rate | fs | 256 samples per period | |
| Number of samples | n | about 4096 periods, sufficient low-frequency resolution | |
| Maximum charge swing | q_max | for normalization | |
| White current-noise PSD | S_i | one-sided, frequency-independent | |
| ISF | gamma_lc_ideal | ideal LC, | |
| PSD segment length | nperseg | Welch segmentation, traded for low-frequency resolution | |
| Random seed | RNG | default_rng(2024) | reproducible results |
7. Units table
| Quantity | Symbol | Unit (normalized lab) |
|---|---|---|
| Time | s (in units of the "period" when ) | |
| Current-noise PSD | A²/Hz | |
| Maximum charge swing | C | |
| ISF | dimensionless | |
| ISF rms | dimensionless | |
| Excess phase | rad | |
| Phase PSD | rad²/Hz | |
| Offset frequency | Hz (normalized, ) |
8. Simulation figure

9. How to read the figure
- Blue line (simulated ): the PSD actually estimated from the simulated phase sequence. On log–log it is a straight line of slope (dropping dB per decade), with the random fluctuations of a Welch estimate.
- Black dashed line (theory): the analytic line . The blue line hugs the black one — this is "white noise → " confirmed numerically.
- Red dotted line ( dB/dec guide): a pure slope reference confirming the slope is exactly .
- Key point: the input is flat ( independent of ), yet the output is . The extra comes entirely from the integrator in step 3. Swapping in a different ISF shape only changes (shifting the whole line up or down); the slope is always . The height of the whole line is set by , so enlarging (tank swing) is the main knob for lowering phase noise (design usage in tank_swing).
Plugging in this lab's numbers as a sanity check: , , ; at (normalized), , , rad²/Hz. The height of the plot at should be of this order.
10. Corresponding paper equations/figures
- Theory-line source: the clean time-domain version , matching the scaling of [P1] Eq.(21), p.185 (differs by the factor-of-2, see the note above).
- definition: [P1] Eq.(20), p.185, .
- White-noise sum expression: [P1] Eq.(19), p.185, ; substituting Eq.(20) to replace with yields Eq.(21).
- Concept-figure source: paper_001 Eq.(21) (the factor-of-2 SSB note lives in this lab). Corresponding site figure
white_noise_phase_noise_psd.png.
11. Limitations and approximations
- This is a pedagogical toy model, not transistor-level: the ISF is the analytic (ideal LC), not extracted from a real circuit. , are normalized units, so there is no absolute dBc/Hz (for absolute values see lab_08 and numerical_feeling example B).
- Single white-noise source, stationary assumption: real circuits have multiple sources and are cyclostationary (noise intensity varies periodically with the operating point); the correction is (see effective_isf).
- Small-angle approximation: phase is treated as linearly superposable and small; for large phase excursions breaks down.
- factor-of-2: the simulation agrees with the time-domain theory line (denominator ) and differs from the of [P1] Eq.(21) by the SSB-bookkeeping factor of 2 — slope and scaling unaffected.
- Numerical limits: the low-frequency end is limited by the total simulated time ( periods) and
nperseg; the leftmost few points have larger statistical scatter, and the plot shows only the trustworthy region .
Key takeaways
- White noise (flat) → ISF weighting (scale by ) → integrator (multiply by ) → phase noise.
- The dB/decade slope comes from the integrator, independent of the noise source's spectral shape.
- The simulated PSD hugs the theory line .
- The factor-of-2 is an SSB bookkeeping-convention difference; it changes neither the scaling nor the slope.
Further reading
- Full theory derivation: white_noise_to_phase_noise
- Origin of the convolution/integrator: convolution_derivation
- Next lab (1/f upconversion): lab_07_flicker_noise_upconversion
- Converting to absolute jitter: lab_08_jitter_integration
- Use in design/theory: suppress with (tank swing) → tank_swing