15-25 MHz Fractional-N Synthesizer

Design Schematics Embedded CPU JAM STAPL Loop Filter Spectra MASH Simulation Back to projects

The manufacturer's published data for VCO tuning sensitivity df/dv (MHz/volt) is tabulated below:

V-TUNE Frequency (MHz) df/dv 1/f * df/dv
1 10.714 0.71 0.07
2 11.523 0.81 0.07
3 12.669 1.15 0.09
4 13.304 1.63 0.12
5 16.424 2.12 0.13
6 19.008 2.58 0.14
7 22.138 3.13 0.14
8 25.862 3.72 0.14
9 29.932 4.07 0.14
10 33.412 3.48 0.10
11 35.618 2.21 0.06

The product 1/f * df/dv is fairly constant over the frequency range of interest. As kVCO increases, VCO divider gain kN will decrease, and loop gain remains fairly constant. I've used kVCO = 2π * 2e6 and kN = 1/155 in the Bode analysis below.

First attempt

My first stab at this loop filter was not successful, because I was overly fixated with reference frequency rejection. To achieve a (theoretical) supression of -146 dB at 100 KHz, I used 22k resistors at R4 and R5 (44k split by 4n7) between the PFD output and the op-amp summing node. Consequently, the open-loop gain crossed 0dB at under 200 Hz. The loop bandwidth was rather low.

I couldn't understand why the close-in phase noise level was so high; and why, unless I placed it inside a metal screening box, the loop was so susceptible to 50 Hz line frequency pickup. The penny didn't drop.

Things seemed to be looking up when I secured a dramatic improvement by adding C8, a 100µF decoupling capacitor, at the op-amp non-inverting input. A further big improvement was had by replacing the original OP42FZ op-amp with an NE5534, which has ten times lower input voltage noise. Close-in phase noise was now around -70 dBc/Hz, from the carrier out to 200 Hz; but this still seemed too-high to be reference noise multiplied. I looked around for other noise sources. The thermal noise of the 22k resistors was comparable to that of the op-amp I had replaced.

Finally, it was something one of the knowledgeable folks at sci.electronics.design said, in response to my plea for help there, which made me see my mistake: I just needed more loop gain. The feedback action of a PLL can only remove noise if it has loop gain at the frequencies in question. Crossing 0dB at under 200Hz, my loop only had a few dB at 50 Hz. Watching the tuning voltage on the 'scope, I'd noticed it seemed a bit slow to lock. Slightly reducing one of the 22k resistors speeded-up the locking and reduced the close-in phase noise. Bingo!

I redesigned the loop filter for higher gain and wider bandwidth - using small resistors, to minimise thermal noise. I also splashed-out on an AD797 op-amp, which has extremely low input voltage noise. The close-in phase noise is now -86 dBc/Hz rising to a peak of -82 dBc/Hz at an offset of 500 Hz. The 4 dB peaking is predicted by the analysis below.

Loop filter design

The objectives, in no particular order, are: These are in conflict: improving one worsens the others. A compromise is required. I got the balance wrong, as explained above, because I was afraid to settle for less than -146 dB of reference attenuation. Eventually, I took a chance on -108 dB and it paid off.

Loop dynamics were analysed in SCILAB using the following script:

s = poly(0,'s');

// Loop coefficients
kvco = 2*%pi*2e6;  // POS-25
kpd = 5/2/%pi;     // AD9901-style with 5V output
kn = 1/155;        // Note: kvco*kn is fairly constant

// Active feedback network
c15 = 3.3e-6;
c12 = 330e-9;
R7 = 180;

z1 = 1/s/c15 + R7;
z2 = 1/s/c12;

// Input RC (pole)
R4=1.8e3;
R5=1.5e3;
C13=47e-9;

// Output RC (pole)
R6=220;
C14=100e-9;

// Loop filter transfer function
f = 1 / (R4+R5) / (1+s*C13/(1/R4+1/R5)) / (1/z1+1/z2) / (1+s*R6*C14);    

// Open loop gain
g = kpd * f * kvco/s * kn;

// Closed loop gain
h = kpd * f * kvco/s /. kn;

I usually start by shifting the input/output poles "out of play" (as it were) by temporarily making C13 and C14 very small. I concentrate on the active filter first. As a rule of thumb, the ratio of C12 to C15 should be about 10:1. Plotting open loop gain, the value of R7 can then be adjusted to centre the phase minima on the 0dB crossover frequency. Use the input resistors to adjust overall gain. Finally, maximise reference attenuation by bringing the other poles back into play - but watch the phase margin as you do so. You want 45° if you can get it.

Performance ...

Open loop gain
Gain and phase margin
Closed loop gain (un-normalised)
Pole/Zero positions
Open loop gain at 50 Hz line frequency
Step Response
100 KHz Reference attenuation
VCO Phase Noise

Open Loop Gain

xbasc(0);
xselect();
bode(syslin('c', g), 10, 9e4, .01);

Gain and phase margin

20 dB and 45° are nice to have, but I can live with less ...
-->g_margin(g)
 ans  =

    16.37573

-->180+p_margin(g)
 ans  =

    41.539021

Closed loop gain (un-normalised)

Peaking causes phase noise "humps" aside the carrier, and too much indicates a loop on the edge of instability:
xbasc(0);
xselect();
bode(syslin('c', h), 10, 2e3, .01);

-3 dB Bandwidth = 1 KHz
Peaking = 4 dB @ 400 Hz

Pole/Zero positions

-->f
 f  =

                 2.783D+08 + 165289.26s
    ------------------------------------------------
                           2            3            4
    3333333.3s + 381.51515s + 0.0137018s + 1.523D-07s

-->roots(denom(f))/2/%pi
 ans  =

!   0         !
! - 2947.3138 !
! - 4138.781  !
! - 7234.3156 !

-->roots(numer(f))/2/%pi
 ans  =

  - 267.93761

Open loop gain at 50 Hz line frequency

-->20*log10(abs(horner(g, 2*%pi*50*%i)))
 ans  =

    34.885532

Step Response

xbasc(0);
xselect();
t = 0:1e-5:5e-3;
plot2d(t', csim('step', t, tf2ss(h*kn, 1e-40))');

37.5% overshoot (ouch)
0.2% settling time ~ 3.5ms

100 KHz Reference attenuation

NBFM sideband amplitude (dBc):
-->pfd_out_volts_pk = 2.5 * 1.2;
-->fmod = 100e3;
-->theta_pk = pfd_out_volts_pk * abs(horner((f*kvco/s) /. (kn*kpd) , 2*%pi*fmod*%i));
-->nbfm_spurs = 20*log10(theta_pk/2)
 nbfm_spurs  =

  - 77.670178
Notes
1. Fundamental Fourier component = 1.2 * square wave amplitude
2. Using SCILAB /. operator, closed-loop gain = A/(1+AB) = A /. B
3. theta_pk = peak phase deviation at VCO output (aka modulation index)

VCO Phase Noise

VCO noise is modelled by inserting a summer at the output. Forward gain after the summer is unity. Feedback passes round the entire loop:
r = 1 /. (kn*kpd*f*kvco/s);
xbasc(0);
xselect();
bode(syslin('c', r), 10, 9e3, .01);

The loop exhibits a high-pass response to VCO phase noise. The model predicts 3.5 dB peaking at 1 KHz. According to Mini-Circuits, POS-25 phase noise is -86 dBc/Hz at 1 KHz. No doubt VCO performance is slightly better than this worst-case figure, and other sources make some contribution, but the VCO is mainly responsible for the measured phase noise of -82 dBc/Hz at 1 KHz.