I think my digital PLL is almost ready, but I've encountered this problem and I don't know what might be causing it, so I'd appreciate if you could help.

I'm using the DPLL in a Costas loop. It seems to work fine but whenever the message crosses zero, lock is lost. After that, it ends up locking again. You can see here:

enter image description here

Input to the Costas loop is: $$ x(t) = m(t)cos(2\pi f_ct+\theta_{in}) $$ $$ m(t) = cos(2\pi f_mt) $$ where $f_m << f_c$

Not sure if this is a known phenomenom (it probably is) but I haven't been able to find anything related. It'd be nice if you could point out what's going on and/or how to fix the temporary loss of lock?

One way I've managed to get it "working" consisted of squaring the message signal (although phase error rises a bit when message goes near zero), but I don't wish to square it so that wouldn't be of use to me.

This is the Costas loop I'm implementing for this test:

costas loop

  • $\begingroup$ You need to show more detail. Can you show your Costas loop, and describe what constitutes a symbol? It looks like your "Costas" loop is locking to the phase of $x(t)$ independent of the message. $\endgroup$
    – TimWescott
    Commented Oct 22, 2019 at 17:31
  • $\begingroup$ I edited the original post to show the Costas loop (the pic at the bottom). As for the symbols, well, for this test I'm simply generating $m(t)$ as described in my main post, once this is successful, I'd move on to BPSK and pulse shaping. Not too sure if this solves your question; let me know if it doesn't. Thanks. $\endgroup$ Commented Oct 22, 2019 at 18:01

2 Answers 2


You are having trouble because that's not a Costas loop. A Costas loop uses demodulated data in some form to change the phase that's expected from the signal.

You're just taking the I/Q demodulated signal and applying it to the atan2 function; that makes a sort of linearized extended phase detector, but without determining that the phase should have flipped by 180 degrees, your loop is naturally trying to follow the phase that's actually coming in.

You could make your loop into a simple Costas loop by changing the atan2 function into a multiply, and following it by a proper loop filter.

  • $\begingroup$ It did work! Changing atan2 by a multiplier and adding a loop filter, it's working now! Thank you very much. When you say it's a simple Costas loop, it's because it could be improved somehow? Also, I'd like to know some more info about it: as far as I understand by your reply, if I wanted to use atan2 I'd need some sort of decision-directed method? $\endgroup$ Commented Oct 22, 2019 at 18:39
  • 1
    $\begingroup$ I tend to conflate "Costas loop" with "decision directed" loop. I'm not sure what's considered to be the dividing line these days. I think the improvements I had in the back of my mind would push it more into decision-directed territory. $\endgroup$
    – TimWescott
    Commented Oct 22, 2019 at 20:06
  • 1
    $\begingroup$ And yes, if you wanted to use an atan2 function in there you'd want a decision-directed loop. But you'd want to ask yourself why you were doing it -- you want your phase error to be small, and that implies that the approximation $\theta \simeq \sin \theta$ holds -- so why bother with atan2? $\endgroup$
    – TimWescott
    Commented Oct 22, 2019 at 20:07
  • $\begingroup$ Oh, I see. So as long as I'm sure that the initial $\theta_{in}-\theta$ is small enough so that $sin(2\theta_{in} - 2\theta)\simeq2\theta_{in} - 2\theta$, I can use the simple Costas loop you proposed, right? And if I wanted to address a larger $\theta_{in}-\theta$, I'd need to consider implementing a decision-directed loop. At least that's what I'm seeing in my simulations, it works fine for $\theta_{in}-\theta$ not bigger than $\pi/2$ $\endgroup$ Commented Oct 23, 2019 at 14:05
  • $\begingroup$ In general a PLL is assumed to work on a data stream, and it is acceptable for it to take some time to lock. Just a plain multiplier will always lock, at least if there's noise to kick it out of the unstable equilibrium when the phase difference is equal to $\pi$. If you need to acquire the phase of a packet or something then you need a different synchronization technique. $\endgroup$
    – TimWescott
    Commented Oct 23, 2019 at 14:12

It seems like your error jumps to -$\pi$ and then to $\pi$

I think you need to unwrap your phase. Let me explain with an example

Say that the output of atan2 block is $\pi - 0.001$ and then the phase difference increases by 0.002 rad, the outuput of the atan 2 block should then be $\pi$ + 0.001, however the atan2 output is limited to ±$\pi$. Therefore the output will be -$\pi$ + 0.001 rad instead of $\pi$ + 0.001. It is up to you to manage these discontinuties with an unwrap function.


Please note however, that for some PLLs (like in power systems), we do not unwrap the phase, we simply switch to FLL mode (frequency-locked-loop) when the frequency difference is too great. Once, the frequency is locked, we switch to PLL mode. In this implementation we do not need to unwrap the phase.


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.