Sunday, July 4, 2010

FFT results from Matlab fft, Bit Accurate C model and SysGen FFT block

The usage of the FFT core is straightforward, however, it does have a lot more knobs to turn compared to a simple fft() function in Matlab. Sometimes when the output from the FFT core doesn't match Matlab fft() result you start to question if there is a bug in the FFT core. I will use a simple example here hopefully to
  • provide some assurance that the result from the FFT core match well with Matlab fft() function and FFT bit accurate C model
  • provide a starting point so you can look at configurations as well as timing of control and data signals of the core in case you didn't have time to read the FFT core data sheet
Below is the SysGen model that uses a 256-point FFT with pipelined streaming IO and unscaled output in natural order. The input vector is a simple ramp (-128:127)/128 in fixed 16.15 format.
The waveform below shows the FFT signals at the beginning of the simulation in WaveScope (a great tool in Xilinx Blockset for debugging, by the way). Note that in FFT v7.0 and newer, there is no longer a requirement of 3 cycle offset between xn_index and xn_re/xn_im inputs.


The waveform below is at the end of FFT computation and data start to unload. Note that xk_index is incrementing as the core output is in natural order.


The simulation results are collected in workspace. A m script is then run to compare the results from Matlab fft(), FFT bit accurate C model, and the Simulink simulation. Below is an overlay plot showing all three outputs, where the difference is negligible.

The script also prints all elements of outputs side by side for easy comparison.


idx    Matlab       Bit Accurate SysGen
0      1.000000     1.000000     1.000000
1      81.489376    81.489504    81.489595
2      40.747756    40.747746    40.747868
3      27.168581    27.168709    27.168739
4      20.380016    20.380048    20.380078
5      16.307697    16.307667    16.307587
...
251    16.307697    16.307667    16.307545
252    20.380016    20.380048    20.380017
253    27.168581    27.168709    27.168495
254    40.747756    40.747746    40.747960
255    81.489376    81.489504    81.489687

In case you want to play with the example design, you can download it from here. You will need to download the bit accurate C model from FFT core web site yourself because it requires registration.

28 comments:

  1. Thanks for the great post...

    Is there a way to eliminate the 608 delay that's occurring in the SysGen model. Specifically on line 37 in the fft_compare script.

    fft_sg = xk_re.signals.values(608:863) + j*xk_im.signals.values(608:863);

    The reason I'm asking, say I generate a HWcosim model from this model and call it from a Matlab script that passes data in an out to it. Will there be a delay associated with the "zeros/NaNs" on either side of the FFT output?

    ReplyDelete
  2. There will always be some latency between xn_re/im inputs and the fft results xk_re/im. You need to save xk_re/im only when dv output is high.

    ReplyDelete
  3. Sounds like xk_re/im can be selected using the following statement:
    ind = find(dv);
    re/me = re(ind);

    But how would this work on a standalone FPGA? i.e what's the best way to deal with this sort of delay?

    Thanks!

    ReplyDelete
  4. This is easy in FPGA. You just use dv as the enable signal for registers or block RAMs that save the xk_re/im results.

    ReplyDelete
  5. I'm doing a slightly different design which involves DDS & FFT IP core. While generating HDL i get the following error :

    Error from hdlshared : dtconvertsl2pir: invaliddatatype

    My dds output is 10-bit.
    Input to xn_im is via constant(simulink) double type connected to gateway_in which is signed 10-bit with 9 bit binary pt. scaling.

    Any ideas?

    Unknown data-type Fix_10_9 is the error.

    ReplyDelete
  6. I'm having a hard time adapting this to work with Fast Fourier Transform 8.0 in SysGen 12.3.

    ReplyDelete
  7. Please check the new blog I just posted with a SysGen example using FFT v8.0 core. http://myfpgablog.blogspot.com/2010/12/example-of-fft-v80-with-axi.html

    ReplyDelete
  8. Just so you know you put "The input vector is a simple ramp (-128:127)/256 in fixed 16.15 format." When the input vector that you actually put in was (-128:127)/128.

    ReplyDelete
  9. Thanks for pointing that out. Just corrected it in the blog.

    ReplyDelete
  10. Hi Jim Wu, I appear to have some problems running your code. Error message is as follows:

    ??? Undefined function or method 'xfft_v7_1_bitacc_mex' for input arguments of type 'struct'.

    Error in ==> fft_compare at 32
    [fft_ba, blkexp, overflow] = xfft_v7_1_bitacc_mex(generics, nfft, input, scaling_sch, direction);

    Can you advice on your settings/environment? My Matlab version is R2009b.

    Thanks in advance

    ReplyDelete
  11. You will need to download the bit accurate C model from FFT core web site yourself because it requires registration

    http://www.xilinx.com/products/ipcenter/FFT.htm

    ReplyDelete
  12. Hi
    How can I change the input source and change the fft length from 256 to smaller values. when I try to do it it is giving me an error. could you please give some comments on this?
    Thank you,
    Mayur

    ReplyDelete
  13. Great Post!

    I'd love to try this on an fpga.. using a clock output from a pll, and see if it calculates the frequency correctly! I imagine that would require some tweaking on sampling, and memory, but should be doable.

    But at the moment, I thought I'd just simulate the model project as-is, but I'm getting an error: "Error loading simulation dll fftv71_CModel". I think I have everything installed correctly.. I've unzipped the contents of xfft_v7_1_bitacc_cmodel.zip into the same folder as fft_test.mdl. As a matter of fact, I sprinkled "nt/libIp_xfft_v7_1_bitacc_cmodel.dll" all over the place including the winxp system folder, yet always get that same error. Any ideas?

    ReplyDelete
  14. Have you tried putting all individual files in xfft_v7_1_bitacc_cmodel.zip (i.e. without nt subdirectory) in the same directory as your model? Also make sure the current working directory in Matlab is the same as your model directory. In case it helps, below are the files I have in my Matlab working directory:

    fft_compare.m
    fft_test.mdl
    libIp_xfft_v7_1_bitacc_cmodel.dll
    libIp_xfft_v7_1_bitacc_cmodel.lib
    stlport.5.1.dll
    xfft_v7_1_bitacc_cmodel
    xfft_v7_1_bitacc_mex.mexw32

    ReplyDelete
  15. sir,

    i am running fft logicore,but in simulation i get "0" output. can u help me providing me proper testbench code of it.

    ReplyDelete
  16. Please post your question and/or attach your project to the Xilinx forum below. You will get more and faster response from the froum.

    http://forums.xilinx.com/t5/Digital-Signal-Processing-IP-and/bd-p/DSP

    ReplyDelete
  17. hey JIM ...
    can you pls tell me how to take a simple sinusoidal function and take its FFT and then add some phase shift in it and again take IFFT ...so that delay could be seen on scope

    ReplyDelete
  18. Check http://forums.xilinx.com/t5/DSP-Tools/FFT-and-IFFT-of-simple-sinusoidal-on-System-generatorr/td-p/250792

    ReplyDelete
  19. Jim, do you know if it possible to get the frequency of a signal using the FFT 7.1 output?

    ReplyDelete
  20. FFT doesn't tell the exact frequency of the signal. FFT will tell you which frequency bin the input signal falls in.

    ReplyDelete
  21. Thanks. Do you know any other System Generator block (or Combination of blocks) that can help get the exact input frequency of a signal? I know that by using that frequency bin information I could calculate an approximation of the input frequency but what is the maximum precision I can achive with the calculation? Let say I what to calculate the input signal freq. of signals from 1MHz to 10MHz?

    ReplyDelete
  22. hi jim
    i implement your design and it works well thanks alot but when i change the architecture from pipelined_streaming to radix_4_burst or radix-2_burst an error occure telling that an FFT block is undriven input port (The input ports on this block must be driven by other Xilinx blocks).
    please can you help me?

    ReplyDelete
  23. Hi Jim ,

    I would like to try this FFT block with analog data comming from the XADC and see what happens can you explain how we can do that because I am starting with zedboard and I am quite lost in the documentation

    Thanks

    ReplyDelete
  24. Hi jim,

    i m also work on fft...nd right now i m facing some problem.., can you plz help me...i have error

    ERROR:HDLCompiler:69 - "D:\temp\abc\fft33\main_prog.vhd" Line 263: is not declared.
    ERROR:HDLCompiler:192 - "D:\temp\abc\fft33\main_prog.vhd" Line 263: Actual of formal out port shift_out cannot be an expression


    what can do....i can't understand it...

    ReplyDelete
  25. hello mr.jim wu
    i have an error running your blockset
    it is illegal input type on port: addr
    Please helppp

    ReplyDelete
  26. Hello Dear,
    Thank you for you design, i want to implement this design in Xilinx Spartan 3An card, but i have a problem with pins (gatway in, gatway out), i want to view the result in the real scope, so can you please help me with the out pins? in the out we have a 16 bits signal so we need 16 pins or what? i am waiting for response thank you .

    ReplyDelete