# What could cause a phase difference between a FPGA implemented FFT and numpy.fft.rfft

We have a FPGA system which takes input from an ADC and calculates a FFT. The system identifies the location of our frequencies of interest and sends the coefficients from those bins to my software. In addition to the coefficients I am sent the time series data

While the hardware guys were working on the hardware I developed additional signal processing code. To enable testing and development I wrote some code to synthesize the signals I expected to receive from the hardware and that works fine. Not unexpectedly now that I have live data nothing works.

In the process of debuging the problem I am taking the real world time series data and using np.numpy.fft.rfft to look at the spectrum. When I plot the spectrum I see our frequencies of interest in the correct FFT bins. I normalize the PSD and the Python's FFT and the hardware FFT match well. The problem I see is the phases of the coefficients do not match. The difference in phases don't look ordered. (Just looking at the phase difference in a plot).

When I compute a FFT on the time series provided by the FPGA (this is the real world data) using numpy.fft.rfft I expect the coefficients at my frequencies of interest to have the same phases as the coefficients calculated by the FPGA FFT which is operating on the same time series.

Does anyone have an idea of what could cause FFT's on the same real world time series data to have different coefficient phases?

Thanks

Justin

You have simulated the FFT in Numpty (Python) and you have implemented the FFT in an FPGA, presumably using an FFT core from your FPGA vendor (Xilinx, Altera, etc.), am I right?

Here's what you should do :

1 - Make an FPGA simulation aka a testbench that you can write in VHDL, Verilog, SystemVerilog to test the FFT core. Use the same inputs as you use in Python.

2 - Compare the results from the FPGA testbench against the Python results. Make sure they match, if they don't match there's no point in testing it in real life.

Depending on your FFT core, there a lot of options such as scaling, bin output order, etc. You need to model these FPGA options in your Python code, otherwise you would compare apples and oranges, or more accurately red apples and green apples.

Edit :

Some FPGA vendors also offer a Matlab model of their FFT cores. You should try it with Matlab or Octave (Matlab-clone almost 100% compatible).

Edit 2 :

As Tim Wescott suggested, try to acquire the raw digitized data from the FPGA. Perform the FFT in Python and make sure the result is what you expect.

• Spot on. But I would add to this that if you have a way of extracting a vector of raw measurements from the FPGA, bypassing any FFT or other processing, you should do it. Get that into Python, look at it, make sure it's what you expect. Don't the current crop of FPGA tools essentially include a logic analyzer in the chip, or at least have a logic analyzer IP module that you can just plug in? Commented Dec 14, 2020 at 16:34
• Thanks for the great ideas. I talked with the FPGA guys and we are going to write a testbench as you suggested. We are using spiral.net/hardware/dftgen.html as our FFT core. Spiral has software FFT products so i expect they will have a Matlab model. We are looking at that also. Commented Dec 14, 2020 at 18:53
• We set up a testbench for the FPGA and fed in a set of test data. We ran the FFT on the FPGA and compared the results with the FFT I was generating using python's numpy.fft.rfft. We created a plot of the phase differences between each frequency bin in the spectrum. You can clearly see the phase walk. The plot shows the phase angle differences with 4 increasing ramps. I talked more with the FPGA guys and found out we are we are using a streaming FFT with 4 channels. Each successive sample in the time series is rotated across the 4 FFT channel inputs. Commented Dec 15, 2020 at 6:59
• Thanks for the help. I showed this plot to our physicist and he said we can create a map of phasors that will convert the FPGA coefficients to the regular 8192 sample time series I am using. Commented Dec 15, 2020 at 6:59

Unless the sampling of the real signal is synchronized with the data, the sampled real data will often have different phases from synthesized data. The real signal will also not be noiseless.

Think of this as the difference between: $$x_{\tt real} [n] = A \sin (\omega n + \theta) + \epsilon[n]$$ and $$x_{\tt synthetic} [n] = A \sin (\omega n )$$ Here, $$\theta$$ is the phase offset due to the lack of synchronization and $$\epsilon$$ is the noise sequence.

Another thought: I'm wondering if it's a problem of offsets? The manual entry for rfft says:

The truncated or zero-padded input, transformed along the axis indicated by axis, or the last one if axis is not specified. If n is even, the length of the transformed axis is (n/2)+1. If n is odd, the length is (n+1)/2.

The numerical example at the bottom shows:

which indicates that while fft returns $$N$$ points, rfft returns $$N-1$$ points. Could it be an indexing issue?

• I was not clear enough in my post. I will add additional clarification. Commented Dec 13, 2020 at 23:01