Electronic – FPGA – synchronise “very close” clock from signal

clockfpgaintel-fpgapllvideo

This is more of a learning question, I can solve the problem but it would be good to know how to do it – can a clock be reconstructed from a signal, and is it easier when the frequency of the clock is basically known?

I am using a Terasic DE10 Lite board, mirroring video from a Mac SE/30 (512x342x1bpp) on a VGA display. Mac connections are vsync, hsync and pixel from the analog board, level converted to 3.3V and then connected to FPGA board GPIOs. At 1024×768 it’s a fairly good fit if pixel doubled. Getting VGA out at 60Hz is not hard, an ALTPLL IP block at 65Mhz makes it just a matter of counting front/back porch and sync pulses.

Copying the Mac signal is a little harder. I ended up with one @always on an ALTPLL clock running at 15.67 MHz (and experiemented with mult/div numbers to try to get it as close as possible), the Mac’s pixel output rate. I cannot exactly match the clock rate this way. This counts down the vertical blank period then for each line counts in until pixels begin and samples each pixel. Pixels are written to a slab of dual port RAM made from another IP block and output by the VGA routine.

This works and is perfectly readable. But it is ugly since there are sampling errors due to the slightly mismatched clocks. If instead of the ALTPLL clock I take CPUCLK from the Mac's PDS connector and use that to clock in the pixels, everything is as steady as can be. Using the FPGA clock the pixels are unsteady and randomly change where they should not.

The question is, what do you do if you can’t take the system clock? I think there must be some way to dynamically adjust frequency and phase shift based on input but I don’t know where to look.

(this question got no response at Stack Overflow, is perhaps a better fit here)

Best Answer

No two clocks will ever perfectly match. The method of determining the true clock frequency from the data is called "clock recovery".

If you know the nominal bit rate, then one straightforward method that doesn't require use of a PLL/DCM block is to over-sample the data and look for edges. Normally you would need to over sample by at least 4X the bit rate. Here is how it works...

  1. Create a clock in your part that is 4X the bit rate. In the case of a 65MHz bit rate this is a 260MHz clock.

  2. Using the 260Mhz clock double or triple register the incoming bits to avoid meta-stability issues. These types of issues can occur if an input signal changes very close to a clock edge. This is almost guaranteed to happen when sampling data using a different clock from which the data was generated.

  3. Optionally do an extra two register stages and do a 2 out of 3 majority vote on the last three stages. This will reduce false detection of edges due to noise, which becomes important in the next step since you are using edges in the data to find the clock rate.

  4. Make a two bit free running counter that counts from 0 to 3 and then rolls over back to 0. The counter is clocked by the 260MHz clock.

  5. Whenever you see a 0 to 1 or 1 to 0 transition on the input data then assume you are at a clock edge and reset the counter to 1 (cnt <= "01").

  6. Whenever the counter has a value of 2 (cnt = "10") use the output of your majority vote as your input sample. And if you are keeping a pixel count, also increment that.

I have personally used the above method to successfully recover the clock on serial data up to 100Mbps.

Depending on whether the incoming data is slightly faster or slower than your clock the counter will skip one tick or hold an extra tick to adjust the count rate to match the data.

For a slower data rate you will see something like...
...0,1,2,3,0,1,2,3,0,1,1,2,3,0,1,2,3,0,1,2,3...

For a faster data rate you will see something like...
...0,1,2,3,0,1,2,3,1,2,3,0,1,2,3,0,1,2,3...

There is another method where you can do the 4X over-sampling using two clocks that are the same rate as your pixel clock but 90 degrees out of phase. By sampling into four registers (one on rising and one on falling for each clock) you can achieve the same effect as is done with the counter based setup above. The maximum possible pixel rates are higher for that method, but the logic is a little more complex.