fracpll: charge-pump fractional-N PLL design from measured pieces
Abstract
0.2.0 reported that, with a delta-sigma divider, the edge-level loop shows in-band noise that the exact linear sampled-data model misses, even with perfectly matched pumps, and that its mechanism was not identified. 0.3.0 identifies it, computes it and tests it. The mechanism A PFD/charge-pump pulse is a rectangle of charge q = pol Icp tau lasting |tau| on one side of the reference edge, not an impulse at the edge. Expanding the exact response over the pulse gives two moments: The zeroth moment is the impulse the linear model uses. The first moment adds -(pol Icp tau^2 / 2) M B to the loop state. The charge centroid sits tau/2 from the edge for either edge order. The delta-sigma divider makes tau fluctuate, so tau^2 carries difference-frequency content that lands in the loop band. Two parts of the correction nearly cancel: the in-pulse control-voltage ramp, Kvco Icp tau^2 / (2 C_shunt); the filter's charge redistribution. The oscillator row of e^{Mt} M B is Kvco times the filter's control-voltage impulse response, so what lasts is Kvco Icp tau^2 / (2 C_total). That is why the effect does not depend on C_shunt, as 0.2.0 observed. How it was established No fitted parameters were used: The effect was isolated in the residual between the edge-level run and the exact linear map. Its spectral shape was resolved. It peaks near the loop bandwidth, and the 'flat floor' of 0.2.0 was coarse Welch bins. Linear explanations were ruled out, including loop-gain and timing mismatch. The source was measured in single-pulse runs. Ablation showed that each half of the pulse correction alone is about 20 dB off, and together they are right. The second-order divider-timing terms are negligible. New simulate_sampled(order=1|2): a fast per-cycle loop. Order 2 includes every second-order pulse-width effect, computed self-consistently from its own state. It reproduces the edge-level simulator and runs about 5x faster. pulse_doublet_vector: the correction direction M B. How it is checked (7 new tests, 57 total, Python 3.9-3.14) Order 2 vs the edge-level simulator: per-cycle pulse widths to 1e-15 s, time-domain residual more than 1000x below the linear map's, and in-band levels within 0.5 dB. This holds at C_shunt 100 and 400 pF and with negative Kvco. Order 1: equals the exact linear sampled map. Doublet oscillator row: Kvco/C_shunt at t = 0+ and Kvco/C_total at long times. Pulse-width scaling: the effect drops about 6 dB when the pulse width halves at the same loop, in both the edge-level run and the order-2 map. Limits The order-2 map assumes matched pumps, no dead zone and a constant small-signal Kvco. Third-order terms are neglected; in the designs checked they are 60 dB or more below the effect. For mismatch, dead zones, measured curves and large signals, use the edge-level simulator.