From a Single Impulse to Arbitrary Noise: the Convolution Derivation
β: This English translation is in beta — the Traditional-Chinese original is the authoritative version.
Prerequisites: isf_definition (the operational definition of and the single phase step), impulse_to_phase_shift (the phase response to a single impulse), oscillator_phase (excess phase has no restoring force and accumulates).
The previous page, isf_definition, gave the definition "one current impulse → one phase step". But the noise current in a real circuit is injected continuously and persistently — it does not arrive as separate, isolated pulses. This page answers:
What is the total excess phase produced by a continuous noise current ?
The answer is the single most central integral in ISF theory ([P1] Eq.(11), p.182):
Our job is to derive it, step by step, from the previous page's "single step" using the superposition principle — and to see clearly that although it looks like a convolution, it is an LTV (linear time-variant) convolution, not the LTI convolution of a signals-and-systems textbook.
Physical intuition (conclusion first): slice the noise current into countless thin slivers, each a miniature impulse; each miniature impulse produces a miniature phase step weighted by the phase at that instant, ; because phase has no restoring force, every step, once it happens, stays forever; so the total phase "now" = the accumulation of all past steps. Accumulating a continuum of infinitely many steps is an integral; "accumulate only the past" is why the upper limit is . changes with the injection instant, so the weight is time-varying — that is LTV.
Step 1: slice the noise into small impulses
Any continuous current can be approximated by a train of adjacent, very narrow rectangular pulses. The slice at time of width deposits a charge
- Physics used: the definition of current, , inverted: .
- Unit check: ✓.
- Why this is legitimate: as long as each slice width (one period), each slice can be treated as "a lump of charge injected instantaneously" — exactly the applicability condition of the impulse on the previous page.
Step 2: each small charge produces a small phase step
Apply the previous page's operational definition to the slice of charge at time :
- Key point: the weight is evaluated at the phase of the injection instant, — not at the observation time . The same charge injected at a zero crossing (large ) produces a large step; at the peak () it produces almost none.
- Unit check: ✓.
Step 3: each step persists permanently into the "future"
This is the soul of the whole derivation, and where an oscillator differs most from an ordinary RLC filter.
Once a phase step occurs at time , because there is no restoring force along the phase direction (claim C2, [P1] Sec. III-A; geometric reason in isf_definition, Step 2), it does not decay — it persists through every future . Written as an impulse response, this brings a unit step ([P1] Eq.(10), p.182):
- (for ), (for ). Its physical meaning: "visible only in the future, and never fades" — the phase integrator has infinite memory.
- Contrast: if this were an amplitude perturbation, the impulse response would carry a decaying term (e.g. ) — the perturbation gets pulled back. Phase gets a step, amplitude gets a decaying exponential — this is the mathematical face of "why phase noise accumulates and amplitude noise does not".
Step 4: superpose all past steps → an integral
In a linear (small-signal) system, the total phase = the sum of all contributions.
Step by step: discrete superposition → limit → integral (no skipped steps). First slice the time axis into cells of width , with injection instants ().
- Charge of the -th slice (step: treat the continuous current as a train of small impulses):
- Phase step produced by the -th slice (step: apply Step 2's operational definition, with the weight taken at the injection-instant phase ):
-
Each step persists permanently (step: phase has no restoring force): at the observation time , only steps with have already happened and are still present; their contribution is multiplied by (equal to 1 when , 0 otherwise).
-
Add up all past steps (discrete superposition):
- Take the limit (step: Riemann sum → Riemann integral): as the cells become infinitely fine, the discrete injection instants become a continuous variable , , and . This step is legitimate provided and are approximately constant within each cell (an integrable integrand), which for noise physically always holds:
Written in the superposition form with ([P1] Eq.(11)):
- Why appears naturally at the "adding" step: it is not inserted by hand — it is the mathematical notation for two facts, "a step persists forever" + "only steps that have already happened can be added". The condition of item 3 becomes in the continuum limit. Right below, you see it cut the upper integration limit to .
The role of is to "cut" the upper integration limit at : for , — future noise has not happened yet and cannot affect the present (causality). Hence
- Why the upper limit is : causality + infinite phase memory. The lower limit says "all noise since power-up is still remembered" — precisely the root of long-term jitter's random walk, drifting further the longer it runs (see in [P2] Eq.(8)).
- Unit check: ✓.
- Degeneration check: for (a single impulse), the integral picks out : (for ), recovering exactly the previous page's ✓.
Why this is LTV, not ordinary LTI convolution
The LTI convolution taught in signals-and-systems is — the kernel depends only on the time difference . Here the kernel is
which depends explicitly on the absolute injection instant (through ) and cannot be written as just . Physically: the same impulse, injected at different phases of the waveform, gives different responses (claim C1, [P1] Sec. III).
- LTI (time-invariant): delay the entire input by and the output is merely delayed by , shape unchanged.
- LTV (time-variant): delay the input by , and because takes different values at different phases, the output changes shape.
But be careful: it is still linear (linear in , superposable) — it is just not time-invariant. Hence LTV (Linear Time-Variant). Slicing , weighting each slice, and superposing works precisely because of this "linearity"; the weight varying with time is the "time variance". For the graphical comparison see lti_vs_ltv.
One-line mnemonic: is first multiplied pointwise by the periodic weight , then fed into an infinite-memory integrator. Multiplication (time-varying weight) + integration (memory) = the LTV phase response.
Block diagram
Draw Eq.(11) as two blocks: a time-varying multiplier and an integrator.
- Block B (multiplication) provides the "time variance": the weight varies periodically with the waveform phase — the origin of LTV.
- Block C (integration) provides the "memory": it accumulates all past weighted noise — the origin of phase accumulation and of long-term jitter's random walk.
Python numerical verification
integrate_phase_from_noise is exactly block B (time-varying multiplication) followed by block C (cumulative integration) — an implementation of Eq.(11). Below we verify it with a single-tone injection: in theory, feeding in a single tone (very small offset, near DC), the excess phase should approach [P1] Eq.(15), p.183:
For the ideal LC () the DC coefficient is and the response is suppressed; only with an asymmetric ISF carrying DC (, giving ) does the slow phase drift of the form above — proportional to with amplitude — appear. The code below runs both for comparison:
import numpy as np
from simulations.common.isf_utils import (
gamma_lc_ideal, gamma_asymmetric, integrate_phase_from_noise,
)
# --- setup ---
f0 = 1.0 # normalized carrier
w0 = 2 * np.pi * f0
fs = 8000.0 # amply oversampled
t = np.arange(0, 200.0, 1/fs) # run many periods to see the slow phase drift
qmax = 1.0
I0 = 1e-3
d_omega = 2 * np.pi * 0.01 # offset 0.01 Hz (near DC, far below w0)
i_n = I0 * np.cos(d_omega * t) # inject a single tone
# --- blocks B×C: run Eq.(11) once for each ISF ---
phi_lc = integrate_phase_from_noise(t, i_n, gamma_lc_ideal(w0 * t), qmax) # c0 = 0
alpha = 0.4
phi_asy = integrate_phase_from_noise(t, i_n, gamma_asymmetric(w0 * t, alpha), qmax) # c0 = 2*alpha
# --- theory Eq.(15): phi ~ I0 c0 sin(d_omega t)/(2 qmax d_omega) ---
c0_asy = 2 * alpha
phi_theory = I0 * c0_asy * np.sin(d_omega * t) / (2 * qmax * d_omega)
print("LC (c0=0) max|phi| =", np.max(np.abs(phi_lc))) # tiny: DC is suppressed
print("asym sim max|phi| =", np.max(np.abs(phi_asy)))
print("asym theory max|phi| =", np.max(np.abs(phi_theory))) # same order as sim, same 1/d_omega trend
- How to read it:
phi_lcbarely drifts because ;phi_asyshows a slow phase drift with amplitude , matching the analytic Eq.(15) in order of magnitude and in trend. This verifies "time-domain integration of Eq.(11) = the literature's frequency-domain result". - Why compare only magnitude/trend: the toy ISF (
gamma_asymmetric) is not transistor-level, and the numerical integration carries sampling and finite-length errors; the point is that the scaling () matches, not point-by-point numbers. - The full version, splitting this integral into "each ISF harmonic down-converting separately", is [P1] Eq.(13), p.183 — taught in fourier_series_of_isf.
Implementation for reference (simulations/common/isf_utils.py, quoted verbatim from the real code):
def integrate_phase_from_noise(t, i_noise, gamma_values, qmax):
dt = np.mean(np.diff(t))
return np.cumsum(gamma_values * i_noise / qmax) * dt
np.cumsum(...)*dt is the "infinite-memory integrator" (block C, accumulating all of the past); gamma_values * i_noise / qmax is the time-varying weighting (block B). Full library: simulations/common/isf_utils.py; noise utilities: simulations/common/noise_utils.py.
Numerical feel (tying back to the single impulse)
Degenerating the continuous integral back to a single kick reproduces Example A of impulse_to_phase_shift: pC, fC, , GHz → rad → fs. What continuous noise means: every kicks like this, and the integrator remembers and accumulates all of it, so the rms phase grows with time (or with the lower limit of the integration bandwidth) — the starting point of the next stage, where the PSD of is connected to the phase noise .
Worked examples
Format per spec 10.4: problem → step-by-step substitution (with units) → result → dimension check → one-line Python verification. We deliberately pick constant scenarios that can be hand-computed, dissecting integrate_phase_from_noise (the implementation of Eq.(11)) for verification.
Example 1: constant ISF × constant noise current — numerical integration vs hand calculation
Problem: take a constant ISF , a constant noise current , and pC, injected over the window . Use Eq.(11) to find the final phase and compare with the hand calculation.
Step-by-step substitution (by hand): the integrand is constant, so the integral degenerates into a multiplication.
Numerator first: . Then divide by :
Cross-check from the "charge viewpoint" (degenerate back to a single impulse): the total injected charge is C fC; applying rad ✓ (consistent with the integral — with constant , the continuous integral equals injecting the total charge all at once).
Result: mrad; the numerical integration integrate_phase_from_noise gives rad, matching the hand calculation (the difference comes from the endpoint effect of the discrete np.cumsum accumulation, relative error).
Dimension check: dimensionless (rad) ✓.
import numpy as np
from simulations.common.isf_utils import integrate_phase_from_noise
qmax, I0, gamma = 1e-12, 2e-6, 0.5
t = np.linspace(0, 1e-9, 100001) # 0 -> 1 ns
i = np.full_like(t, I0) # constant noise current
gv = np.full_like(t, gamma) # constant ISF
phi = integrate_phase_from_noise(t, i, gv, qmax)
print(phi[-1], "rad") # -> 0.00100001 rad (hand calc = 1e-3 rad)
Example 2: time-varying ISF () × constant noise — net phase over a half period
Problem: now use the real, time-varying ISF , constant , pC, (normalized, so ), integrated over an integer number of periods. Find .
Step-by-step substitution (by hand):
Over an integer number of periods , , so the integral = 0:
Result: under (zero DC, ), constant (DC) noise produces zero net phase shift per full period — the positive and negative half cycles cancel. This is the time-domain face of "a symmetric ISF suppresses DC/near-DC injection" (echoing the single-tone example above: the LC has , so the Eq.(15) response is suppressed). If you stop at a half period (), leaves a nonzero transient phase offset (the Python below prints rad). (Note: here , pC, and the half period s are all normalized numbers; , further divided by , so the "rad count" of is enormous. This is purely a bookkeeping artifact of normalized units, not a physical phase of rad — in fact, the small-signal/linear premises (Step 1's ; a single impulse charging only about 10% of the total charge, [P1] p.182) are badly violated long before that. The point is the sign structure — full periods cancel, half periods do not — not the magnitude of that rad number.)
Dimension check: as in Example 1, the final is dimensionless (rad) ✓.
import numpy as np
from simulations.common.isf_utils import gamma_lc_ideal, integrate_phase_from_noise
f0, w0, qmax, I0 = 1.0, 2*np.pi, 1e-12, 2e-6
t = np.arange(0, 10.0, 1/8000.0) # 10 full periods
i = np.full_like(t, I0)
gv = gamma_lc_ideal(w0 * t) # Γ = -sin(w0 t)
phi = integrate_phase_from_noise(t, i, gv, qmax)
assert abs(phi[-1]) < 1e-6 # net phase cancels over full periods (residual ~6e-10, purely cumsum discretization)
print(round(abs(phi[-1]), 6)) # -> 0.0 (net phase cancels over full periods)
print(round(phi[len(t)//20], 1)) # -> -636619.7 (near the half period: nonzero transient)
Full library: simulations/common/isf_utils.py.
Validity and failure conditions
| Condition | When it holds | What happens when it fails |
|---|---|---|
| Small-signal / linear | superposition holds; slice and superpose | large noise → nonlinearity; itself is altered, no simple superposition |
| known and frequency-independent | plug directly into Eq.(11) | a frequency-dependent needs a more complete model |
| Infinite phase memory (no phase restoring) | upper limit ; permanent accumulation | with phase pulling (e.g. injection locking) a restoring term must be added — see the generalized Adler equation in [P3] |
| Amplitude perturbations negligible | the phase-only model suffices | strong AM–PM requires including the APF ([P4]) |
Key takeaways
- Slice the noise → each slice carries charge → each slice gives a step → each step persists forever into the future → superpose all of the past → upper integration limit .
- Result: ([P1] Eq.(11), p.182).
- This is LTV: the kernel depends on the absolute injection instant (through ), not just on ; still linear, but time-varying.
- Structure = time-varying multiplier () + infinite-memory integrator ().
integrate_phase_from_noiseimplements this integral asnp.cumsum(gamma*i/qmax)*dt; the single-tone injection verification matches the trend of Eq.(15).
Further reading
- The operational definition for a single impulse: impulse_to_phase_shift
- What is, and why LTV: isf_definition
- LTI vs LTV, illustrated: lti_vs_ltv
- Splitting the integral into ISF harmonics (frequency translation): fourier_series_of_isf
- White noise → 1/f² phase noise: white_noise_to_phase_noise
- Quick numerical-feel reference: numerical_feeling