• 0

FFT output result using Xilinx FFT core (v9.0)


Question

I had inserted FFT core in a design after FIFO .at the output i am expecting a frequency bin on certain index but i am not getting the result.FFT core is working on 100mhz clock .

Following steps i had implemented .

-        For FIFO to be work on 100 MHz, I verified this by sending the captured data to MATLAB and analyze DATA over there. So I received data correctly.

 

-        I inserted FFT core after ADC_FIFO in the reference design. That FIFO working correctly on 100MHz clock. But I didn’t get the correct DATA from the core.

 

For verifying FFT core settings, I debugged FFT core with a DDS core. I mean generate a signal from DDS core and passed to FFT core, at the output I got correct result. So FFT core is also working fine

 s_axis_data_tdata[31:0] ( input [ real 16 bit , q 16 bit ]    )

s_axis_data_tlast (I provide this signal from a counter which run upto FFT points)

s_axis_data_tready [ output]

s_axis_data_tvalid [coming from fifo]

s_axis_config_tdata [ passed 0]

s_axis_config_tready [ output]

s_axis_config_tvalid [constant 1]

m_axis_status_tready [constant 1]

m_axis_data_tready [constant 1]

FFT_out.png

Edited by FR
explanation
Link to post
Share on other sites

18 answers to this question

Recommended Posts

  • 0

@FR,

Since you haven't provided me with enough information to really answer what's going on, here are some guesses:

  • You mentioned that your FFT and FIFO are both running at 100MHz.  May I assume that this is your system clock rate?
  • Looking at your image above, it appears as though you have a much lower data rate than 100MHz.  Can you tell me what your data rate is?
  • I notice that you are using a FIFO.  Can you explain the purpose of this FIFO within your design?  If the data rate going into the FFT is at 100MHz, then the FIFO really only makes sense if you have bursty data at a rate faster than 100MHz.
  • I have strong reason to believe that your tlast isn't quite right.  Can you verify that if TLAST && !TVALID, then TLAST will be remain true on the next clock?
  • Indeed, is your TLAST generation done at the rate of your incoming data?  Or is your counter independent of incoming data samples?
  • I understand you double checked your FIFO with MATLAB.  You can read about my experiences with double checking my FIFO here, and the problems that remained unchecked.

These are just some ideas I had.  They are by no means definitive.  It is difficult to be definitive without more information about your design.

Dan

Link to post
Share on other sites
  • 0

Dear Sir

Thanks again for your suggestions. I tried to answer your questions first. Then I tried to put my data and assumptions regarding this design. 

You mentioned that your FFT and FIFO are both running at 100MHz.  May I assume that this is your system clock rate?

I have used the this FIFO for clock domain crossing. FIFO's input clock is running at 61Mhz and output clock is running at 100Mhz. I'm passing the data from FIFO output to FFT core input. My FFT core is running at 100Mhz. 

Looking at your image above, it appears as though you have a much lower data rate than 100MHz.  Can you tell me what your data rate is?

Yes my data rate is 61MSPS. My FIFO outputs valid signal at the frequency of data rate so i connected this valid signal at FFT s_axis_data_tvalid signal. I also connected FFT out s_axis_data_tready  to FIFO's m_axis_data_tready signal. You can see in screenshot that fft_s_axis_data_tready is asserted and util_fifo_m_axis_valid  is toggling at the rate of 61MSPS. (ILA is running at 100Mhz)

I notice that you are using a FIFO.  Can you explain the purpose of this FIFO within your design?  If the data rate going into the FFT is at 100MHz, then the FIFO really only makes sense if you have bursty data at a rate faster than 100MHz.

I used the FIFO for clock domain crossing. Actually my data rate (61MSPS) is slower then my system clock(100Mhz). So if i lowered my system clock to 61Mhz, I would hurt my system's performance. 

Indeed, is your TLAST generation done at the rate of your incoming data?  Or is your counter independent of incoming data samples?

yes TLAST is being generated at incoming data rate (61Mhz).

Here is how i'm calculating bins and indices. (Please correct me if i'm wrong.) My FFT size 65536 and FFT core is running at 100Mhz. So

bin size -->100M/65536=1525.87890625Hz

--Input 1Mhz signal

expected index-->1M/1525.87890625 = 655

actual index  = 1068 

offset =413

--input 2Mhz

expected index-->2Mhz/1525.87890625=1310  (2*655)

actual index  =2135 (2*1068)

offset = 825 (2*413)

This calculation shows that output has a fixed offset. I'm not using square root while calculating magnitude. My multipliers and adders are all combination so they won't add extra latency. 

Index.png

Link to post
Share on other sites
  • 0

Hi @[email protected] @FR can you please help me with my FFT design?

 Here are the details: 

I am testing the design with sine wave input from DDS compiler: Frequency 1 MHz. 

100 MHz System clock driving DDS compiler, BRAM for storing frame data from DDS 16 bit output and transferring the same data to FFT core. 

FFT IP core: 100 MHz clock, 4096 point, pipelined streaming, no run time configuration (8'b00000000) & config_tvalid(1'b1), unscaled and testing both bit reversed and natural orders.

Block design contains FFT IP core with register slices (64 bit M_AXIS_DATA from FFT is sliced for real and imaginary components as real:15:0 & imag: 47:32) -> multipliers -> add/sub -> CORDIC IP for square root magnitude generation. 

frame_tlast signal is generated by a 12-bit counter in a bram_to_fft module for frame data transfer.

Simulation through a test bench and analysis via vivado waveform viewer. Vivado version 2019.1

I could see that the output of DDS compiler and the input of the FFT module match (image attached). I do not understand the FFT output (the real and imaginary components) and the magnitude data that follows it. Can you point what changes I need to carry out for a correct output? 

FFT ouput in reverse bit order configuration:

I see that the magnitude data (and x_slice_0(real part), x_slice_1(imaginary part)) have bands of waveform of high magnitude followed by lower magnitude values. I was expecting only one spike in the magnitude output. What do you think has gone wrong here? Also, how can I verify this result with regard to expected FFT bin number (on a time based x-axis) and the magnitude value?

image.thumb.png.0168c0124a240de39d0e1fb895fb0cc6.png

 

 

Output in the natural order (option in FFT IP core) is something like this: 

I could not make anything of this result. 

image.png.0bb0f73e5d54c0a62c310482e4ed9c09.png

 

Requesting your help. 

- Ram

  

 

Link to post
Share on other sites
  • 0

@RCB,

Did you notice the glitch in your source signal in the second plot?  It's in both data[] and frame_data.  You'll want to chase down where that glitch is coming from.

After looking at that source signal, I noticed that the incoming frequency of your first image didn't match the 1MHz frequency you described.  At 1MHz, you should have one wavelength inside of 1us.  In your first plot, it appears that one wavelength fits in 20us, for a frequency of closer to 50kHz?

Further, I don't get your comment about holding config_tvalid = 1.  If you have created an FFT that isn't configurable ...  then why are you configuring it?  It's been a while since I've read the book on the configuration --- did you hard code the scaling schedule into the FFT, or are you configuring that in real time?  I can't tell from what you are showing.  You also weren't clear about what config_tdata is.  Was that the all zeros value you were sending?

Finally, the difference you are seeing between natural order and bit-reversed order is not explained by the simple difference between the two orderings.  There's something else going on in your design.

Dan

Link to post
Share on other sites
  • 0
On 1/16/2020 at 9:58 PM, [email protected] said:

@RCB,

Did you notice the glitch in your source signal in the second plot?  It's in both data[] and frame_data.  You'll want to chase down where that glitch is coming from.

After looking at that source signal, I noticed that the incoming frequency of your first image didn't match the 1MHz frequency you described.  At 1MHz, you should have one wavelength inside of 1us.  In your first plot, it appears that one wavelength fits in 20us, for a frequency of closer to 50kHz?

@[email protected] I am sorry! The frequency is 50 kHz. My FFT resolution would be (100*10^6)/4096 about 24.5 kHz. X[3] would be the frequency bin with spike.   

Quote

Further, I don't get your comment about holding config_tvalid = 1.  If you have created an FFT that isn't configurable ...  then why are you configuring it?  It's been a while since I've read the book on the configuration --- did you hard code the scaling schedule into the FFT, or are you configuring that in real time?  I can't tell from what you are showing.  You also weren't clear about what config_tdata is.  Was that the all zeros value you were sending?

No scaling and no runtime configuration. I think I tested with s_axis_config_tvalid with both 1'b0 and 1'b1 but I did not find changes in the output waveforms (of magnitude data).  I'd check this again. Yes,  config_data is all the zeros.

Finally, the difference you are seeing between natural order and bit-reversed order is not explained by the simple difference between the two orderings.  There's something else going on in your design.

 

Quote

Appreciate your help. 

 

 

 

Edited by RCB
Link to post
Share on other sites
  • 0
On 4/3/2019 at 8:41 AM, FR said:

Dear Sir

Thanks again for your suggestions. I tried to answer your questions first. Then I tried to put my data and assumptions regarding this design. 

You mentioned that your FFT and FIFO are both running at 100MHz.  May I assume that this is your system clock rate?

I have used the this FIFO for clock domain crossing. FIFO's input clock is running at 61Mhz and output clock is running at 100Mhz. I'm passing the data from FIFO output to FFT core input. My FFT core is running at 100Mhz. 

Looking at your image above, it appears as though you have a much lower data rate than 100MHz.  Can you tell me what your data rate is?

Yes my data rate is 61MSPS. My FIFO outputs valid signal at the frequency of data rate so i connected this valid signal at FFT s_axis_data_tvalid signal. I also connected FFT out s_axis_data_tready  to FIFO's m_axis_data_tready signal. You can see in screenshot that fft_s_axis_data_tready is asserted and util_fifo_m_axis_valid  is toggling at the rate of 61MSPS. (ILA is running at 100Mhz)

I notice that you are using a FIFO.  Can you explain the purpose of this FIFO within your design?  If the data rate going into the FFT is at 100MHz, then the FIFO really only makes sense if you have bursty data at a rate faster than 100MHz.

I used the FIFO for clock domain crossing. Actually my data rate (61MSPS) is slower then my system clock(100Mhz). So if i lowered my system clock to 61Mhz, I would hurt my system's performance. 

Indeed, is your TLAST generation done at the rate of your incoming data?  Or is your counter independent of incoming data samples?

yes TLAST is being generated at incoming data rate (61Mhz).

Here is how i'm calculating bins and indices. (Please correct me if i'm wrong.) My FFT size 65536 and FFT core is running at 100Mhz. So

bin size -->100M/65536=1525.87890625Hz

--Input 1Mhz signal

expected index-->1M/1525.87890625 = 655

actual index  = 1068 @FR @[email protected] how can I check/verify the index number from the waveform? In the waveform attached to this point, @FR got a peak at 31,344. What information I can extract from this about the bin number as well as the expected add value?

offset =413

--input 2Mhz

expected index-->2Mhz/1525.87890625=1310  (2*655)

actual index  =2135 (2*1068)

offset = 825 (2*413)

This calculation shows that output has a fixed offset. I'm not using square root while calculating magnitude. My multipliers and adders are all combination so they won't add extra latency. 

Index.png

 

Link to post
Share on other sites
  • 0
On 1/16/2020 at 9:58 PM, [email protected] said:

@RCB,

Did you notice the glitch in your source signal in the second plot?  It's in both data[] and frame_data.  You'll want to chase down where that glitch is coming from.

After looking at that source signal, I noticed that the incoming frequency of your first image didn't match the 1MHz frequency you described.  At 1MHz, you should have one wavelength inside of 1us.  In your first plot, it appears that one wavelength fits in 20us, for a frequency of closer to 50kHz?

Further, I don't get your comment about holding config_tvalid = 1.  If you have created an FFT that isn't configurable ...  then why are you configuring it?  It's been a while since I've read the book on the configuration --- did you hard code the scaling schedule into the FFT, or are you configuring that in real time?  I can't tell from what you are showing.  You also weren't clear about what config_tdata is.  Was that the all zeros value you were sending?

Finally, the difference you are seeing between natural order and bit-reversed order is not explained by the simple difference between the two orderings.  There's something else going on in your design.

Dan

Hi @[email protected]

I still am facing issues with the design and request your help. I think the problem is with how the xfft core handles the input (32 bit) data.

Some information on my input data:

1) Output of DDS compiler: 16 bit sine wave (DDS input 100 MHz clock, output: sine 100 KHz)

2) 16 bit o/p from DDS compiler is converted to signed magnitude form (dds_output - 1<<15) and is concatenated with 16'b0 (MSBs). 

Alternately, earlier I tried with DDS compiler output as is with 16'b0 concatenation. 

FFT details: 100 MHz clock, 4096, natural order, pipelined streaming and unscaled.

 

FFT magnitude output with signed 32 bit inputimage.thumb.png.d541724370240a4c508fc277abcad0f2.png

 

FFT magnitude with unsigned 32 bit input:

magnitude: mag_data[23:0]

Dout0[15:0] and Dout1[15:0] are real and imaginary output slices from FFT.

Real: 15:0 sliced from 64 bit FFT output

Imaginary: 47:32 sliced from 64 bit FFT output; magnitude being sqrt(real+imaginary)

 

image.thumb.png.cef39c126b59ee999cda4d89c63cdbed.png

 

 

 

 

 

 

Edited by RCB
Link to post
Share on other sites
  • 0

@RCB,

Why are you converting things to sign magnitude form, vs just leaving them in twos complement again?

I'm not certain what's going on.  Were this my own project, I'd use an FFT I'd be able to "see" inside of so that I might debug the problem.  Specifically, I'd look for overflow problems within the FFT--at least that's the only thing I can think of that might cause the bug you are referencing above.  It doesn't make sense, though, that you'd have overflow with one FFT and not with an identical FFT that only differed in output ordering.  You might wish to compare the .xml files of the two FFT's to see if they are truly the same as you believe.  You might also wish to try dropping the amplitude by a factor of 4x or perhaps even 64x to see if that makes a difference.  It might be that you have the scaling schedule messed up and that things are overflowing within.  It might also be that you aren't looking at all of the output bits with your bit-cut selection above--I can't tell by just looking at it from here.

Dan

P.S.  I don't work for Digilent, and do not get paid for answering forum posts.

Link to post
Share on other sites
  • 0
On 1/22/2020 at 10:01 AM, [email protected] said:

@RCB,

Why are you converting things to sign magnitude form, vs just leaving them in twos complement again?

I'm not certain what's going on.  Were this my own project, I'd use an FFT I'd be able to "see" inside of so that I might debug the problem.  Specifically, I'd look for overflow problems within the FFT--at least that's the only thing I can think of that might cause the bug you are referencing above.  It doesn't make sense, though, that you'd have overflow with one FFT and not with an identical FFT that only differed in output ordering.  You might wish to compare the .xml files of the two FFT's to see if they are truly the same as you believe.  You might also wish to try dropping the amplitude by a factor of 4x or perhaps even 64x to see if that makes a difference.  It might be that you have the scaling schedule messed up and that things are overflowing within.  It might also be that you aren't looking at all of the output bits with your bit-cut selection above--I can't tell by just looking at it from here.

Dan

P.S.  I don't work for Digilent, and do not get paid for answering forum posts.

Hi @[email protected]

I think I got the design right after some experimentation. My mistake was about handling the real and imaginary components. Thank you for your suggestions. I'll document the steps and post it here hopefully soon. Appreciate your help. 

I would move on with replacing DDS synthesizer with XADC to test external signals with a function generator.

 

image.thumb.png.5a2b1fce7227af6178830c3f8f13abec.png

 

- Ram

Edited by RCB
Link to post
Share on other sites
  • 0
On 3/31/2020 at 7:59 AM, petriggg said:

Can you post what you did? Thank you.

And, please, show your blockdesign (or part of it with FFT), FFT IP parameters.

Hey @petriggg

I am still debugging some blocks and hence decided not to document with bugs. 

Edited by RCB
Link to post
Share on other sites
  • 0

Hi @RCB!

I read that article from Levi's blog. According to it I customized DDS compiler and get the 25 MHz sine wave. Now I try to tune up the FFT Core.
Thank you for source files (I sent a request for access), but I work in a Vivado 2015.4 and, probably, will not open files from Vivado 2019.1.
Can you share some screenshots with your FFT IP customization window and part of blockdesign with FFT core? Only screenshots will enougth.
Especially I interesting about input data. Where need to place phase factor, I guess that in a least significant bits, right?
And one more question. How you get the signal on magnitude_tdata? It's just a sum of real and imaginary components of FFT result? How you get this, by Adder/Substracter IP?

Edited by petriggg
Link to post
Share on other sites
  • 0
On 4/1/2020 at 3:00 AM, petriggg said:

Hi @RCB!

I read that article from Levi's blog. According to it I customized DDS compiler and get the 25 MHz sine wave. Now I try to tune up the FFT Core.
Thank you for source files (I sent a request for access), but I work in a Vivado 2015.4 and, probably, will not open files from Vivado 2019.1.
Can you share some screenshots with your FFT IP customization window and part of blockdesign with FFT core? Only screenshots will enougth.
Especially I interesting about input data. Where need to place phase factor, I guess that in a least significant bits, right?
And one more question. How you get the signal on magnitude_tdata? It's just a sum of real and imaginary components of FFT result? How you get this, by Adder/Substracter IP?

FFT IP: 4096 point, Fixed point, non-real time, unscaled

Yes, you may populate the least significant bits with the DDS output. I tried square root operation for handling the FFT core output. 

 

Edited by RCB
Link to post
Share on other sites
  • 0

Please help me, I am a little confuse to configure the IP cores.

is s_axis_data_tdata in FFT ip core, the sin signal that is converted to the digital value with ADC?

the output data of the FFT includes the real and image values. is the output data the frequency or phase?

if I use DDS after FFT to generate the cos signal, can I connect the output data of FFT (m_axis_data_tdata) to s_axis_phase_tdata in DDS?

Thanks

Link to post
Share on other sites
  • 0

Hi, 

Quote

is s_axis_data_tdata in FFT ip core, the sin signal that is converted to the digital value with ADC?

Yes.

Quote

the output data of the FFT includes the real and image values. is the output data the frequency or phase?

It's neither frequency or phase, you have to calculate sqrt(real^2 + imag^2) to get the amplitude and arctan(imag/real) to get the phase.

This can be done manually or with ip cores like CORDIC core.

If you want the exact values of amplitudes in original signal you have to divide the calculated amplitude by your FFT resolution and multiply it by 2 additionally.

Also its important that you choose your FFT resolution accordingly so that you know on which position in the array of complex FFT values you can find the frequency of your interest.

Quote

if I use DDS after FFT to generate the cos signal, can I connect the output data of FFT (m_axis_data_tdata) to s_axis_phase_tdata in DDS?

That makes no sense. The output on m_axis_data_tdata of FFT is the input signal in frequency domain.

The input of s_axis_phase_tdate is the phase increment for the accumulator of your DDS and refers to the the output frequency of your DDS in the time domain.

You have to calculate a value for phase increment according to the desired output frequency of your cosine and then put this value into s_axis_phase_tdata port of your DDS.

Greetings

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now