I'm trying to design a software-based PLL that mimics the behavior of an analog PLL based on a 4-quadrant mixer as the phase detector (PD). The input signal is a sinusoid of unknown frequency between \$1\,\text{kHz}\$ and \$100\,\text{kHz}\$. The voltage-controlled oscillator (VCO) should generate a sinusoid with the same frequency and amplitude but with a phase-lag of \$90^{\circ}\$. I've been having considerable trouble getting this to work. I think my primary issue is in understanding how the phase error signal (integrated/low-passed mixer output) works. So, I decided to try to develop an intuition for the math. Unfortunately, this isn't helping. I've described my process below.

I've restricted myself to a simplified example in which my input signal and VCO-generated reference are unchanging and the reference can have a different frequency and phase shift from the input. Of course this is unrealistic in the sense that PLL's rely on feedback, but I'm trying to develop an intuition for the PD output for different reference signal phase shifts and frequencies. What I've done is compute

\$ \begin{equation} \frac{1}{t_2-t_1}\int_{t_1}^{t_2} s(t)r(t)dt \end{equation} \$

where \$s(t)=\sin t\$ is the input signal and \$r(t)=\sin(ft+\phi)\$ is the reference signal. Then for each of several values of \$f\$, I've plotted this integral for \$\phi\in[0,2\pi]\$.

I started out with the signal and reference at the same frequency (i.e., \$f=1\$). I generated the plot in sagemath with the following command:

plot(integrate(sin(t)*sin(1*t+var('x')), (t, 0, 10))/10, x, 0, 2*pi)

The result is

enter image description here

So far so good. This tells me that the error signal is 0 when \$\phi=-\pi/2\$. Additionally, if the phase wanders slightly lower than \$-\pi/2\$ the error signal goes negative, decreasing the VCO frequency and thus pushing to next zero-crossing a little later, thus bring the phase-shift back to equilibrium. Same for wandering above the equilibrium point. I think this is all fine so far.

The problem arises when I increase the frequency of the reference. For example, let's take a bit of an extreme case, \$f=10\$. Even though this might seem a bit extreme, given the bandwidth mentioned earlier this is possible. Here's the same plot for that:

plot(integrate(sin(t)*sin(10*t+var('x')), (t, 0, 10))/10, x, 0, 2*pi)

enter image description here

I'm not so worried about the angle where this phase locks (feedback will mean this isn't a stable frequency, so I'm pretty sure the locations of the zero-crossings in this plot is essentially irrelevant). What worries me more is the magnitude of the error signal: it's 100x lower than in the same frequency case. How can the frequencies converge and then phase lock with such a small error? This result makes sense to me mathematically since we're essentially integrating over a difference frequency, so when the frequencies are the same we get a constant that doesn't zero out. When the frequencies aren't the same we're integrating over a much lower frequency sinusoid. Nevertheless, I'm not making the connection between this fact and how to fix it. I can change the integration period, but I don't see how I can do that to accommodate the full input frequency range.

Is the loop filter more complicated than a simple integrator? Should I be implementing it another way? I can add a proportional term, but then the error signal will oscillate a lot. Is it simply a balancing act between the proportional and integral terms? How can I determine these? I've fiddled around with quite a few combinations and all I've managed is to get it to kind of work at one frequency and fail at others. Are there any algorithms for how to accomplish this, or other resources/textbooks/articles I could use for this? Have I misunderstood the capabilities of PLLs? Are they not able to lock to an unknown frequency in a wide range?

It's probably worth mentioning that I think this problem would be much easier in an unrealistic ideal case where I had the absolute phase difference between the signals. Then my error signal would always increase in one direction and decrease in the other rather than oscillate as it does here, which I think is what makes this case challenging.


1 Answer 1


Without a true phase-frequency-detector, you will be plagued with FALSE LOCKS.

Consider using a 2-flipflop-one-NAND_reset PFD.

You need to make the "analog" signals --- Freference and Fvariable --- be logic level signals. If your FFs are CML current mode logic, as little as 0.2 volts will suffice, but need to be "squared up" thru a limiter.


if you are counting "zero crossings" to allow presetting the F_reference to the approximately correct frequency, then you certainly have already converted the (noisy?) analog signal to rail_rail (or at least logic_0 to logic_1) levels.

  • \$\begingroup\$ Can I use a PFD with analog inputs? \$\endgroup\$
    – MattHusz
    Commented Sep 27, 2020 at 2:38
  • \$\begingroup\$ Would another method be to attempt to estimate the input frequency and use that to place the reference frequency in a reasonable starting range of the input? For example counting zero crossings as described in this answer? \$\endgroup\$
    – MattHusz
    Commented Sep 27, 2020 at 15:07
  • \$\begingroup\$ I've interpreted your last addition to mean that if I can count zero crossings I can also use a PFD. Does this mean you think a PFD is a more robust/better solution? What does better mean here? Faster lock, less computationally expensive? \$\endgroup\$
    – MattHusz
    Commented Sep 27, 2020 at 17:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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