β: This English translation is in beta — the Traditional-Chinese original is the authoritative version.
Lab 40 — Subharmonic (×N) Pulse Injection: Impulse-Train Map vs. Unaveraged Time-Synchronous ODE
Prerequisites: subharmonic_injection (every closed form this lab verifies — the lock range, the realignment factor , discrete-time noise shaping, output jitter, and the reference spur), paper_003 ([P3] Sec. IV's impulse train and footnote 7's subharmonic arithmetic), paper_004 ([P4] Eq.(28)–(30)'s M:N averaging equation) | Next: injection_locked_division (the dual, divider direction), sampling_pll, clock_chain_budget
The subharmonic_injection page has already derived every formula for the injection-locked clock multiplier (ILCM) step by step: the multiplier closed form from [P4] Eq.(29), the scaling from the discrete arithmetic of [P3] footnote 7, the realignment factor from the linearized per-pulse map, and the output-jitter closed form from putting noise on a first-order discrete loop. This page does not re-derive any of it — it uses two independent numerical engines to score every one of those closed forms term by term.
What this lab verifies:
- Does the lock range really go as (Engine 2: sweep with the unaveraged ODE)?
- How does a finite pulse width eat into the lock range — a clean sinc for LC, and what about the ring (Engine 2: sweep the pulse width)?
- At the same rms current, does the pulse train really lock while a pure sine really doesn't (Engine 2: pulse-train vs. sine comparison)?
- How accurate is the first-order prediction for the realignment factor (Engine 2: step response)?
- Is the locked phase noise really a first-order discrete high-pass, with corner (Engine 1: map + white FM noise)?
- Does output jitter really go as , and is the reference spur really independent of (Engine 1: edge-level simulation)?
Physical intuition: the two engines measure the same physics at different resolutions. Engine 1 (the map) compresses one pulse's effect into an instantaneous jump — fast, well suited to long-horizon noise statistics (PSD, jitter), but assumes the pulse is narrow. Engine 2 (the unaveraged ODE) honestly integrates the instantaneous equation through the pulse with RK4 — it sees pulse-width effects and 's second-order correction (the phase is already moving during the pulse), but each data point costs thousands of periods of integration, so it is best suited to "does it lock or not" edge sweeps. The two engines agree to within 0.1%–1% at the canonical parameters — that agreement is this lab's acceptance criterion.
Where this page sits: an independent verification lab. All the theory has already been derived step by step, with sources flagged ([P3]/[P4] verified portions vs. this site's own derivations vs. external literature), on subharmonic_injection; this page lists only the verification core code and the resulting numbers. Pedagogical toy model: phase-only, weak injection, no transistors.
1. Learning goals
- Independently verify using the unaveraged time-synchronous ODE (not the already-averaged map) — this avoids the circular-reasoning trap of "verifying an averaged formula with the same averaged formula" (log-log slope , for both LC and ring).
- Sweep the pulse width : LC's lock range follows exactly (a single harmonic, max deviation ); the ring's sharp ISF spreads its energy across multiple harmonics, so a plain sinc is not enough (deviation up to 0.74) — only a "box-averaged whole ISF" matches (deviation ).
- At equal rms current, the pulse train locks throughout the lock range (15/15 grid points) while a pure sine cannot lock at first order anywhere (0/15) — pinning down numerically what subharmonic_injection Section 1 states in words: "a pure sine cannot lock."
- The realignment factor 's ODE step response against the first-order prediction : ratio – (), tightening to – at — the deviation is a second-order, effect (the phase is already moving during the pulse), matching the precision the linear theory promises.
- Put white FM noise on the map and measure the locked phase's PSD: the low-frequency plateau matches theory to a ratio of , and the corner measures MHz (simplified theory MHz; the exact discrete closed form gives MHz — the measurement rides right on the exact form).
- Edge-level simulation of the output jitter's power law in : fitted slope (theory ); the canonical gives fs (closed form fs).
- The reference spur at a detuned lock: error dB, error dB — the first-order sawtooth approximation is nearly exact at the canonical parameters.
2. Mathematical model (the two engines and notation; full derivation on subharmonic_injection)
2.1 Engine 1: the linearized impulse-train map
is the ISF box-averaged over the pulse width (the -th harmonic multiplied by , reducing to in the impulse limit); rad²/s is the canonical white-FM variance-growth rate (see diffusion_dictionary). Linearizing gives the realignment factor , corner , and the first-order discrete noise-shaping transfer functions , .
2.2 Engine 2: the unaveraged time-synchronous ODE
RK4 is used during the pulse (with the number of sub-steps set by the ISF's curvature: LC at rad per sub-step, the ring's sharp triangle kinks at – rad per sub-step, checked against a 512-sub-step reference to / error); between pulses, is skipped over analytically. "Does it lock" is read directly off the net correction of the lock characteristic (a single integration at ) giving the edges , or cross-checked with a long-time convergence test (2500–4000 periods; locked the last 800–1300 periods satisfy ).
2.3 Two toy ISFs (shared with other labs on this site)
The ring toy is two opposite-sign triangular pulses, height = half-width ( 1/rad), — a pedagogical toy, not transistor-level.
2.4 Applicability and failure conditions
| Condition | When it holds | What happens when it fails |
|---|---|---|
| Weak injection | Engine 1 linearizes correctly; 's first-order prediction is accurate | Large injection: the ODE/map ratio deviates systematically from 1 (measured at in (d)) |
| Pulse width | ; Engines 1 and 2 agree | : LC's lock range collapses to 0 (the null seen in (b)) |
| varies slowly within | The two engines reconcile with each other | Near the lock-range edge: critical slowing, requiring more periods for the long-time convergence test |
| White-FM noise drive (Engine 1's noise part) | ; the PSD closed form holds | Flicker FM: not covered by this lab |
3. Block diagram
4. Core Python code
Excerpted from simulations/lab_40_subharmonic_injection.py (checked against the source). The
box-averaged table, the per-pulse map, and one pulse period of the unaveraged ODE (RK4):
def isf_tables(gamma_func, tp):
"""Gbar(theta) = ISF box-averaged over the pulse (width tp/T0), via FFT:
k-th harmonic multiplied by sinc(k*tp/T0)."""
g = gamma_func(XG)
G = np.fft.rfft(g)
k = np.arange(G.size)
Gb = G * np.sinc(k * tp)
gbar = np.fft.irfft(Gb, NG)
gbar_p = np.fft.irfft(1j * k * Gb, NG) # d Gbar / d theta
return gbar, gbar_p
def pulse_period_step(theta, dw, n_div, qt, gamma_func, tp, nsub):
"""ENGINE 2: one injection period T_inj = n_div*T0 of the UNAVERAGED ODE —
RK4 through the rectangular pulse (width tp), analytic free-run in between."""
h = tp / nsub
amp = qt / tp
t = -tp / 2.0
for _ in range(nsub):
k1 = dw + amp * gamma_func(TWO_PI * t + theta)
k2 = dw + amp * gamma_func(TWO_PI * (t + 0.5 * h) + theta + 0.5 * h * k1)
k3 = dw + amp * gamma_func(TWO_PI * (t + 0.5 * h) + theta + 0.5 * h * k2)
k4 = dw + amp * gamma_func(TWO_PI * (t + h) + theta + h * k3)
theta = theta + (h / 6.0) * (k1 + 2 * k2 + 2 * k3 + k4)
t += h
return theta + dw * (n_div - tp)
def gbar_prime_exact(gamma_func, theta, tp):
"""Exact derivative of the box-averaged ISF (difference of raw Gamma at the
two box ends over the box width) -- used for beta = -q_t * Gbar'(theta*)."""
half_w = np.pi * tp
return (gamma_func(theta + half_w) - gamma_func(theta - half_w)) / (2.0 * half_w)
Numbers printed by the script (PYTHONPATH=. python3 simulations/lab_40_subharmonic_injection.py,
about 35 s single core; seed fixed with default_rng(40), results reproducible):
print(A_edge_pred['LC']) # -> 0.04979 rad/period (qt*max|Gbar|, N=20)
print(fL_pred['LC']/1e6) # -> 1.9813 MHz (with the 10 ps pulse-width sinc correction)
print(slope_N['LC'], slope_N['ring']) # -> -1.000 -1.000 ((a) log-log slope, theory -1)
print(ratio_N['LC'].min(), ratio_N['LC'].max()) # -> 1.0000 1.0000 (LC measured/theory)
print(dev_lc_sinc) # -> 0.0001 ((b) LC: max deviation of ODE/f_L(0) from sinc)
print(dev_ring_box, dev_ring_sinc) # -> 0.0074 0.7434 (ring: box average correct, plain sinc wrong)
print(n_lock_pulse, n_plateau_sine) # -> 15 0 ((c): 15/15 grid points lock for the LC pulse train, 0 for the pure sine)
print(beta_c_lc[5], beta_c_lc[4]) # -> 0.04858 0.04979 ((d) headline beta: ODE vs. first order)
print(r_plateau, fc_meas/1e6, fc_pred/1e6) # -> 0.991 1.9343 1.9813 ((e) plateau ratio, measured/theory corner)
print(slope_j, sig_all[10]/(2*np.pi*5e9)*1e15) # -> 0.497 2.226 ((f1) jitter's power law in N, N=20 output in fs)
print(round(spur1[0], 2)) # -> -67.96 ((f2) reference spur at 100 kHz detuning, dBc)
5. Full script path
simulations/lab_40_subharmonic_injection.py (depends on savefig from
simulations/common/plot_utils.py and gamma_lc_ideal from simulations/common/isf_utils.py;
uses scipy.signal.welch for the PSD and scipy.optimize.brentq to solve the exact discrete
corner).
To run: PYTHONPATH=. python3 simulations/lab_40_subharmonic_injection.py (about 35 s single
core; seed fixed with default_rng(40)).
6. Parameter table
| Parameter | Program variable | Value | Meaning |
|---|---|---|---|
| Carrier | F0 | 5 GHz | canonical |
QMAX | 1 pC | canonical | |
QINJ | 50 fC | charge per pulse () | |
| Pulse width | TAUP | 10 ps | |
| Multiplication ratio | N_HEAD | 20 | MHz, ns |
| sweep ((a)) | N_list | 2, 4, 8, 16, 20 | lock range vs. |
| Pulse-width sweep ((b)) | tp_list | 2–175 ps (9 points) | lock range vs. |
| Detuning sweep ((c)) | r_grid | – (25 points, ) | pulse-train vs. pure-sine drift curves |
| ((d)) | qt_arr | 0.05, 0.01 | two injection strengths for the step response |
KAPPA2 | 0.125 rad²/s | canonical (diffusion_dictionary) | |
| PSD samples ((e)) | K_PSD/M_W | /32 walkers | Welch, nperseg |
| Edge-level samples ((f1)) | K (depends on ) | , 8 walkers | rerun per |
| Ring toy | ETA, NST | 0.75, 17 | [P2] App.B construction, same as lab_39 |
7. Units table
| Quantity | Symbol | Units |
|---|---|---|
| Phase | rad | |
| Half lock range | , | rad/s, Hz |
| Realignment factor | dimensionless | |
| Noise corner | , | rad/s, Hz |
| White-noise variance growth rate | rad²/s | |
| Phase PSD | rad²/Hz | |
| Output jitter | s (fs) | |
| Reference spur | — | dBc |
8. Simulation figure

9. How to read the figure
(a) Lock range vs. : the two theory dashed lines (LC, ring) are ; the circles/squares are the unaveraged-ODE measurements at — LC lies exactly on the theory line (ratio ), the ring runs high (a slightly larger finite-pulse effect at the triangle's sharp corner). Both log-log slopes are : the same pulse has to pay for -times-longer drift, no exceptions to the law.
(b) Lock range vs. pulse width: the black dashed line is the "plain sinc" reference (the decay of the single harmonic). LC's blue measured points lie exactly on that line (max deviation