The Interlaced NCO: A New Twist on the Digital PLL
a PLL in discrete-time feels more like "black magic" than engineering
Synchronizing a local oscillator to an external reference—like the 77.5 kHz DCF77 time signal—is a classic engineering challenge. While textbook Phase-Locked Loops (PLLs) are ubiquitous, implementing them in the rigid, discrete-time world of an FPGA often feels more like "black magic" than engineering. After struggling with traditional detectors, a "Time-Interlaced" architecture is proposed here, that untangles the loops for a rock-solid lock without the mathematical headache.
The Evolution of the Lock: The Road Not Taken
Before arriving at an interlaced solution, we must look at why the traditional "industry standards" often fail in a precision digital design.
1. The Analog Mixer and XOR: Nonlinearity and Duty Cycles
In the analog world, a common phase detector is a double-balanced mixer. However, sinusoidal mixers are inherently nonlinear Vout ~ sin(phi), meaning the "gain" of your detector changes depending on the phase. While using block-waves (square waves) in a digital XOR gate creates a linear relationship, it introduces a new problem: it is critically duty-cycle dependent. If your signals aren't a perfect 50/50 square, you get a static phase offset that ruins precision.
2. The Traditional PFD: The "Black Magic" of Z-Transforms
Then there is the Type-II Phase Frequency Detector (PFD). In an analog system, time is continuous. In an FPGA, everything is quantized into discrete steps (e.g., 10ns). This quantization turns simple loop filters into complex digital resonators requiring Z-transform mathematics. For most designers, calculating poles and zeros in the complex plane feels like "Magic": get one coefficient slightly wrong, and the system oscillates uncontrollably.
The Core Problem: Control Loop Contamination
The real "showstopper" in a standard digital PLL is the interaction between the loops. In a typical design, the Phase Detector and the Frequency Detector run simultaneously.
Imagine your NCO is running at the correct frequency but is 100ns out of phase. The phase loop detects this and "jumps" the NCO’s phase accumulator forward to align the edges. However, the frequency counter—watching the time between those same edges—suddenly sees a period that is 100ns shorter than expected.
The frequency loop reacts instantly: "Help! The oscillator is too fast!" and yanks the frequency down. This is Control Loop Contamination. The phase correction "pollutes" the frequency measurement, causing the two loops to fight in a tug-of-war that leads to instability and jitter.
The Solution: The Interlaced Strategy
To stop this fight, we use a 32-bit Numerically Controlled Oscillator (NCO) with an Interlaced control strategy. Instead of solving complex equations to decouple the loops, we simply separate them in time.
Cycle A: Frequency Specialist (Integral Action)
On the first rising edge of the DCF77 input, we measure the period duration (TcountInp)
- The Correction: We update the PhaseIncr (velocity). This is our Integral (I) controller.
- The Rule: During this cycle, the phase position is left untouched.
Cycle B: Phase Specialist (Proportional Action)
On the very next edge, we measure the time offset (PcountDelta).
- The Correction: We "nudge" the PhaseAccu (position). This is our Proportional (P) controller.
- The Beauty of the "Skip": During this cycle, we discard the frequency measurement. By intentionally ignoring the period measurement when we perform a phase jump, we prevent the frequency loop from ever "seeing" the disturbance we created. The frequency loop stays calm, and the phase loop snaps into place.
How-To: Implementing the Interlaced PLL
Ready to build your own? Here is the practical guide to tuning your Interlaced NCO.
1. Choose your NCO Bit-Width
For a 100MHz clock and a 77.5kHz target, 32 bits is the sweet spot. It provides a frequency resolution of 0.02328 Hz.
PhaseIncr = (77500 / 100,000,000) * 2^32
2. Implement the Gain Weights (Kp and Ki)
Avoid multipliers. Use bit-shifts (<<) to apply your gain.
- Frequency Gain (Ki): Start with a shift of 6 or 7.
PhaseIncr = PhaseIncr + (Terror << 6)
- Phase Gain (Kp): This should be "stiffer" than the frequency loop. A shift of 9 or 10 is a good starting point.
PhaseAccu = PhaseAccu - (Perror << 9)
3. The State Machine logic
Create a simple 1-bit register (reg_mode) that toggles on every rising edge of your reference signal.
- If reg_mode == 0: Calculate Terror, update PhaseIncr, set reg_mode <= 1.
- If reg_mode == 1: Calculate Perror, update PhaseAccu, set reg_mode <= 0.
Conclusion
By embracing the linear nature of block-waves and the FPGA's ability to time-multiplex logic, a PLL is created that is "stiff" enough to hold a lock and "agile" enough to stay aligned. The interlaced solution replaces "Black Magic" with intuitive logic: simply take turns, and the loops will never fight again.

Discussion (0 comments)