β: This English translation is in beta — the Traditional-Chinese original is the authoritative version.
Lab 08 — rms Jitter by Integrating L(f)
This lab turns something you see on every datasheet — the single-sideband phase-noise curve (dBc/Hz) — into the number designers actually care about: rms timing jitter . We use a canonical scenario ( GHz, dBc/Hz, slope, integrated 1→100 MHz) and make the numerical integration and the analytic closed form agree digit by digit: fs.
Physical intuition (conclusion first): phase noise is "how much phase power density sits at each offset frequency"; jitter is "add it all up, take the square root, convert to time". So going from to is three things: (1) convert dBc/Hz back to linear and multiply by 2 to recover ; (2) integrate over offset frequency to get the phase variance; (3) take the square root and divide by to convert to time. For a shape, the integral is dominated by the lower limit — "where you start integrating" matters far more than "how high you go".
1. Learning objectives
- Convert (dBc/Hz) step by step into rms phase and rms jitter .
- Build a feel for the 5 GHz conversion: dBc/Hz @ 1 MHz, , integrated 1→100 MHz → about 448 fs.
- Verify numerical integration = analytic closed form ( has a closed form).
- Understand why jitter is dominated by the lower integration limit.
2. Mathematical model
Step 1: → . Under the small-angle / single-sideband approximation (canonical formula 16):
Step 2: write the shape (anchored at MHz, canonical example C):
Step 3: integrate to get the phase variance (canonical formula 18):
For the shape this integral has a closed form ():
Step 4: convert to rms jitter (canonical formula 19):
- Dimension check (step 4): is rad, is rad/s, ✓.
- Lower-limit dominance: , of which contributes 99%. So the integral depends almost entirely on .
Substituting the canonical numbers digit by digit (identical to numerical_feeling example C):
3. Block diagram
4. Core Python code
Verbatim from main() in simulations/lab_08_jitter_integration.py: first build the curve with
leeson_one_over_f2, then integrate numerically with integrate_rms_jitter,
and finally check against the hand-computed closed form.
import numpy as np
from simulations.common.noise_utils import leeson_one_over_f2, integrate_rms_jitter
f0 = 5e9
f_ref = 1e6
L_ref = -100.0 # dBc/Hz
f1, f2 = 1e6, 100e6
f = np.logspace(np.log10(f1), np.log10(f2), 4000)
L = leeson_one_over_f2(f, L_ref, f_ref)
# numerical integration
sigma_t, sigma_phi = integrate_rms_jitter(f, L, f0, f1, f2)
# analytic closed form (1/f^2)
L_ref_lin = 10 ** (L_ref / 10)
sigma_phi2_analytic = 2 * L_ref_lin * f_ref ** 2 * (1 / f1 - 1 / f2)
sigma_phi_analytic = np.sqrt(sigma_phi2_analytic)
sigma_t_analytic = sigma_phi_analytic / (2 * np.pi * f0)
print(round(sigma_t * 1e15, 1)) # -> 447.9 (sigma_t in fs)
print(round(sigma_phi * 1e3, 2)) # -> 14.07 (sigma_phi in mrad)
The underlying function integrate_rms_jitter (noise_utils.py) implements exactly steps 1, 3, and 4:
l_linear = 10 ** (l_dbc_per_hz[mask] / 10) # dBc/Hz -> linear
s_phi = 2 * l_linear # L ~= 0.5 * S_phi
sigma_phi = np.sqrt(_trapz(s_phi, f[mask])) # integrate + square root
sigma_t = sigma_phi / (2 * np.pi * f0) # convert to time
- The script prints
sigma_phi (numeric) ≈ sigma_phi (analytic)andsigma_t ≈ 447.9 fs; the numerical and analytic values agree digit by digit (the only difference is the negligible discretization error of logspace sampling and trapezoidal integration).
5. Full script path
simulations/lab_08_jitter_integration.py
(Dependencies: leeson_one_over_f2 and integrate_rms_jitter from simulations/common/noise_utils.py.)
How to run: python scripts/run_all_sims.py.
6. Parameter table
| Parameter | Variable | Value | Notes |
|---|---|---|---|
| Oscillation frequency | f0 | Hz | 5 GHz carrier |
| Reference offset | f_ref | Hz | 1 MHz, anchor point |
| Reference phase noise | L_ref | dBc/Hz | single datasheet-style number |
| Lower integration limit | f1 | Hz | 1 MHz (dominates the integral) |
| Upper integration limit | f2 | Hz | 100 MHz |
| Number of sample points | — | (logspace) | log-uniform sampling |
| Slope | — | ( dB/dec) | pure skirt |
7. Units table
| Quantity | Symbol | Unit | Result in this lab |
|---|---|---|---|
| Phase noise | dBc/Hz | @ 1 MHz | |
| Phase PSD | rad²/Hz | @ 1 MHz | |
| Phase variance | rad² | ||
| rms phase | rad | mrad | |
| rms jitter | s | fs | |
| Offset frequency | Hz | 1–100 MHz | |
| Carrier frequency | Hz | 5 GHz |
8. Simulation figure

9. How to read the figure
- Blue line (): a straight line on semilog (logarithmic x-axis), because has a constant slope in dBc/Hz vs log-f ( dB/dec). The red dot marks the anchor point dBc/Hz.
- Blue shading: illustrates "where the phase power sits over offset frequency". Under , the part closest to contributes the most — the visual rendering of "lower-limit dominance".
- Text box: lists the integration results mrad, fs, and notes that the analytic value equals the numerical one, proving the closed form matches the trapezoidal integration.
- How to use it: take any datasheet curve, integrate the area under the blue line, take the square root, divide by , and you have the jitter. Remember the 5 GHz conversion point: fs in this example. With phase noise 20 dB better ( dBc/Hz @ 1 MHz), the power is 100× smaller and 10× smaller → fs.
10. Corresponding paper equations/figures
- This lab uses the standard jitter integration (canonical formulas 16–19), general DSP/communications practice — not among the five source PDFs, supplemented from standard references; consistent in spirit with the jitter discussion in [P2] (period/accumulated jitter).
- : canonical formula 16 (small-angle approximation).
- Phase variance: canonical formula 18, .
- rms jitter: canonical formula 19, .
- Concept-figure source: standard jitter integration / SerDes practice. Corresponding site figure
phase_noise_to_jitter_integration.png, also cited in numerical_feeling example C, psd_phase_noise_jitter, and serdes_clocking_connection.
11. Limitations and approximations
- Small-angle approximation