I'm working on a crude circuit simulator with the goal of implementing PAL encoding and decoding, so that I can experiment with generating images that look like video transmissions.

In the simulation engine, a circuit consists of circuit elements with input and output ports that express a voltage level as a double. Output ports are connected by wires to input ports of other elements. At each timestep, the sources (elements with no inputs) propagate their output values to other elements, which are evaluated once they have all inputs ready, repeating until every element has been visited. Feedback is handled using special feedback elements that act like wires but with a one timestep delay.

A simple flashing LED circuit is defined as follows:

var circuit = new Circuit();
// add a 5V power source
var power = circuit.AddElement(new VoltageSourceDC(5.0));
// add a 1Hz 50% duty cycle square wave oscillator
var clock = circuit.AddElement(new SquareOscillator(1.0, 0.5));
// add an LED
var led = circuit.AddElement(new LED());

// wire the power source output to the clock level input.
circuit.AddWire(new Wire(power.Output, clock.Level));
// wire the clock output to the LED
circuit.AddWire(new Wire(clock.Output, led.Input));

I have implemented a fair number of circuit elements, including a sine oscillator, VCO, comparator, logic gates, D flip-flop, 2:1 mux, and a charge pump. Using these elements, I have created a PLL.

The schematic diagram for the PLL looks like this:

PLL schematic

Vref is the reference waveform being locked against. In this scenario it is a square wave. The D flip-flops act as a phase detector, identifying which rising edge appears first. If both flip-flops are high, the reset signal is asserted via feedback on the next timestep. The charge pump only acts when either HI or LO are asserted, not both. The charge pump simply increases its output voltage or decreases it depending on which signal is asserted, otherwise it holds steady. The charge pump's dV/dt is configured at time of creation.

The output of the charge pump is fed through a feedback element to the input of the VCO. The feedback element could instead be placed in the feedback path after the comparator, but that seems to produce less stable results. The VCO's output is then compared against Vcmp, which is Vdd/2, to turn it into a square wave for Vout.

This mostly works:

Screenshot of waveforms

Vpump initially oscillates beyond the target frequency, but then it settles and keep the VCO output locked very closely in phase and frequency. This is what I expected to see - the frequency ramps up to "catch up" with the phase of the reference, then slows down to match the frequency.

Zooming in a bit, we can see the phase error being very small with UP/DOWN mostly being asserted simultaneously:

Close-up of waveforms

Unfortunately, this does not hold over long periods of time, and the charge pump voltage begins to oscillate:

Oscillation of the charge pump voltage

Over longer times the oscillation reaches a peak and then locks again, repeating over and over. Changing the charge pump dV/dt has a major effect on this.

Twice the dV/dt

The timestep is small in comparison with the signal frequencies, and there is little behavioural change between 10us and 1us steps.

Why is this occurring? What should I do to fix it?


I found the answer. I built the same circuit in a simulator and watched its behaviour. The critical missing piece was the behaviour of the signal being fed into the VCO.

Circuit diagram

I had modelled the charge pump as a floating point value that increased when UP was set, and decreased when DOWN was set, at a predefined rate (dV/dt), or doing nothing when neither or both signals were set. This is close to what happened in my original circuit, which omitted the resistor in series with the charge pump capacitor. I found that changing the input frequency easily led to oscillation of the PLL, meaning it never locked. You can see this for yourself by closing the bypass switch and changing the frequency from 3.5kHz to 2.0kHz - it'll oscillate forever.

However, if you look at the pump voltage signal at the bottom right, with the bypass switch open (and therefore with the resistor in place) it does not exhibit a simple smooth curve. Instead, it has discontinuities. This occurs because the resistor forms a voltage divider with the Rds(on) of a FET when either UP or DOWN is asserted, leading to a brief "spike" in the signal instead of a perfectly smooth curve.

This turns out to be critical. If the signal going into the VCO is limited to the dV/dt of the charge pump, the PLL generates an output signal that approaches the input signal with the correct phase, but the wrong frequency. It then tries to correct the frequency, but it can only do so relatively slowly due to the dV/dt limit. By the time the frequency is correct, the phase is not, and the oscillation continues until both frequency and phase happen to align by chance. This is what creates the repetitive behaviour I saw before.

By applying small discontinuities to the VCO input during the UP and DOWN pulses, the VCO can more quickly correct its output frequency once the phases converge.

In my simulation, I modelled this as a pair of voltage dividers that are enabled when UP or DOWN are asserted. The result is significantly more stable.

Simulation output


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.