FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP

Help with altera FFT

Altera_Forum
Honored Contributor II
7,746 Views

hello; 

 

what i want to do is to get spectrum of an sinusoidal signal using the altera fft core i have generated a v8 fft with the following setting: 

fft point : 64 (to start with) 

architecture : brust 

data width : 16 

twidle width : 16 

i am including the matlab files in the attachment .. the input is a 64 point 2`compliment form. 

in the compare.m file i am doing three fft,,2 matlab fft and 1 altera core fft  

 

what i cant figure out is why the magnitude of the second and the the third power spectrum has bigger amplitude than the first fft at the signal fundmental frequency ? 

and why are those two are not so clean like the first one ? 

 

please have a look .. thanks to anyone who replies.
0 Kudos
56 Replies
Altera_Forum
Honored Contributor II
362 Views

Are there any advantages and/or disadvantages to pass the SAME audio signal to both the real and imaginary inputs?

0 Kudos
Altera_Forum
Honored Contributor II
362 Views

No, just for test purpose. It will just change the phase of audio signal which is irrelevant to hearing. For test it may improve on amp fluctuation resulting from phase change as explained above in that both channels contribute to final amp. This is trivial but worth trying it.

0 Kudos
Altera_Forum
Honored Contributor II
362 Views

I think my FFT is working in general for analog audio input. I have increased the FFT resolution from 256 points to 512 points, however, I don't seem to notice much difference in the output. 

 

Also, how come for some frequency inputs, I get one pretty clean spike, but for other frequency inputs, the spike fans out at the bottom, with two or more spikes in adjacent bins and/or the amplitude fluctuates a little? My input is always one constant sine wave. For example, at 1335Hz, the spike is very sharp and good, but at 1260Hz, I get two spikes at about 4 bins apart and their magnitudes fluctuate just a little.
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

To be of any help can you tell me about: 

your sampling frequency (of sinusoid)  

your fft sampling frequency 

do you use real and imaginary fft inputs and real/imaginary fft outputs 

how then do you combine real and imaginary into one signal 

your DAC sampling frequency(and do you correct for sinc distortion, see a today's post on that) 

How do you visualise spectrum? is it commercial spectrum analyser and do you have positive negative sides of spectrum?
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

Here's my setup... 

Everything that I am using is on the DE2 board which has a Cyclone II 

 

I'm using the WM8731 CODEC chip on the DE2 board configured as the ADC. 

My input source is a fix frequency sine wave going through the line in on the DE2 to the ADC. 

I've configured the WM8731 with a sampling frequency is 8000Hz. According to the WM8731 doc, this setup requires a MCLK frequency of 18.432MHz. However, the PLL Megawizard can only produce a 18.75MHz clock. I don't know how this slight difference in the clock speed will affect the sampling frequency and everything else. 

 

The clock to the FFT is generated based on the 18.75MHz clock as follows: 

... 

elsif (CLK_18_4MHZ = '1' and CLK_18_4MHZ'event) then -- this is the 18.75MHz clock 

-- ReferenceClk / (SampleRate*2)-1 = 1151 = 10001111111 

-- 18432000Hz / (8000Hz*2)-1 

if (LRCK_1X_DIV >= "10001111111") then 

LRCK_1X_DIV <= (others => '0'); 

FFT_clock <= not FFT_clock; 

else 

LRCK_1X_DIV <= LRCK_1X_DIV + 1; 

end if; 

 

 

The FFT is setup with a 256-point streaming architecture. Both the data and twiddle precision are 16 bits. 

The digitzed signal from the ADC is connected to just the real input of the FFT. 

 

For the FFT output... 

I am scaling the real and imaginary FFT output using the exponent according to the scaling algorithm in the FFT doc. After the scaling, I apply the equation 

sqrt(I^2 + Q^2) 

 

So the FFT input signal is 16 bits and the final output after the equation is 29 bits. 

I have a 256 x 29 bit dual-port RAM to store the 256 output values from the FFT. I can then read from the RAM to see what the magnitude is for a certain frequency bin. 

 

Finally, I have a VGA controller that reads from the RAM and plots the values from the 256 locations as bars on the monitor. 

 

Again, all the components that I have mentioned are implemented on the Cyclone II FPGA on the DE2 board. 

 

I don't know what is the sinc distortion so I guess I am not correcting it. Where is your post on it? What is the sinc distortion? My codec is used as an ADC and not as a DAC, so what is this DAC sampling frequency that you are referring to?
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

For a start. Don't worry about my comments on DAC as you are not using it, instead you are outputting to monitor. 

 

The first issue I can say is that ref clk difference is trivial for your test purpose (but will have some effect on the hearing of audio if you pass your frequencies to human). 

 

second: Is there any reason why you use double Fs (8000*2) for your fft? 

since data is sampled at 8k by ADC then you should run fft at that data rate unless altera fft requires you double the speed of internal fft operation. Even then the fft input and output should run at 8k otherwise you will introduce major error.  

 

third: how did you do your sqrt(I^2 + Q^2)? was it in DSP builder? 

fourth: in your fft scaling do you take account of bit-growth. 

 

fourth: why use 29 bits for result when your data is just 16 bits, it looks excessive, you can truncate it down to 16 bits(not important now)
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

Hi, 

 

I think my conclusion on your fft clk is not right. You are dividing it into 8KHz, fair enough. I wonder why not use the same 8 clk of ADC for your fft, may be it is not connected in hardware. 

 

So generally your design looks ok in principle. You can simplify it by removing sqrt if you want. Just add squred values to get power instead of amplitude. 

 

As such your fft result covers 0 ~ 1 i.e starts as positive from 0 ~ .5 then negative mirror image from -.5 ~ 0 

0 means 0 frequency, .5 means Fs/2 = 4KHz.  

so you can label your frequency axis from 0 ~ 4 then -4 to 0 

You should see two lines on either side. These two should be equal if yur input is connected to real fft only. for example if your input frequency = 2Khz 

then the lines should be at +2 on your frequency axis. 

 

 

I am still not sure what is your ADC actual Fs. If we assume it is 8k  

while your fft clk = 18750/(1152*2) = 8.138... this is a big difference
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

 

--- Quote Start ---  

 

 

I think my conclusion on your fft clk is not right. You are dividing it into 8KHz, fair enough. I wonder why not use the same 8 clk of ADC for your fft, may be it is not connected in hardware. 

 

I am still not sure what is your ADC actual Fs. If we assume it is 8k  

while your fft clk = 18750/(1152*2) = 8.138... this is a big difference 

--- Quote End ---  

 

 

The 8kHz signal is generated internally in the CODEC chip given the Master clock input of  

18.432MHz, and I don't think this 8kHz clock is available to the outside. 18432/(1152*2) = 8. So theorectically, my FFT clock is 8kHz. However, as noted above, my actual clock input is 18.75 and not 18.432, therefore my actual FFT clock is 8.138! 

 

 

--- Quote Start ---  

 

How did you do your sqrt(I^2 + Q^2)?  

You can simplify it by removing sqrt if you want. Just add squred values to get power instead of amplitude. 

--- Quote End ---  

 

 

I am using the Altera megafunctions for doing the sqrt and square, so this is easy. 

 

 

--- Quote Start ---  

 

fourth: in your fft scaling do you take account of bit-growth. 

 

fourth: why use 29 bits for result when your data is just 16 bits, it looks excessive, you can truncate it down to 16 bits(not important now) 

--- Quote End ---  

 

 

According to the Altera FFT doc on the exponent scaling, 29 bits is the resulting output bit width for my FFT setup. However, I am only passing bits 19:12 to the monitor. 

 

 

--- Quote Start ---  

 

As such your fft result covers 0 ~ 1 i.e starts as positive from 0 ~ .5 then negative mirror image from -.5 ~ 0 

0 means 0 frequency, .5 means Fs/2 = 4KHz.  

so you can label your frequency axis from 0 ~ 4 then -4 to 0 

You should see two lines on either side. These two should be equal if yur input is connected to real fft only. for example if your input frequency = 2Khz 

then the lines should be at +2 on your frequency axis. 

--- Quote End ---  

 

 

Yes, I do see the two mirror image lines on either side. 

 

So it seems like that my problems stem from the fact that my master clock is not exactly 18.432MHz?
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

Attached are three screen shots of the spikes on the monitor for 944Hz, 1260Hz, and 1335Hz. And as you can see, 1335Hz is very clean and sharp. 1260Hz is not as good, and 944Hz is the worst. Don't jump to the conclusion that higher frequency will give me a better result, because at 841Hz, again I get a very clean and sharp spike.

0 Kudos
Altera_Forum
Honored Contributor II
362 Views

none of the pictures you posted look alright to me. I was expecting two symmetrical lines (well apart) and more towards the edges than the centre. 

your frequencies are close to 1 Khz so the lines should be close to location +1 out of x axis from 0 to 4, -4 to 0: 

 

......|.....................................|..... 

0....1....2....3....4....-3.....-2....-1....0 

 

if you centre the fft on dc(which I guess you don't) it becomes: 

 

......................|...........|.................. 

-4....-3....-2....-1....0....1.....2.....3....4 

 

 

your truncation of 29 bits by taking bit 19:12 is not clear to me. 

You should be taking the value from MSBs. unless they are "dead" bits i.e. never used by result(indicating low input swing or bad design) 

 

your ADC Fs and FFT Fs must be identical, preferably same clock line, else the two clocks must be equal , related and locked to each other. 

 

In any case of data and clk acquired from outside then I will use that same clk and I will also check for any timing problems at the io registers which is not normally part of fpga timing report. 

 

edit: 

Your picture indicate some high frequencies near 4KH and this is maximum for your fft, possibly due to some flipping of data. 

 

another issue that popped up now is the way you display on the monitor. You must latch your fft output while refrshing the monitor otherwise a free running fft will not give identical block data unless you work hard to do that
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

 

--- Quote Start ---  

I was expecting two symmetrical lines (well apart) and more towards the edges than the centre. 

--- Quote End ---  

 

 

I did not take the pictures with the lines on the right side, but actually I do have the two lines toward the edges. 

 

 

--- Quote Start ---  

your truncation of 29 bits by taking bit 19:12 is not clear to me. 

You should be taking the value from MSBs. unless they are "dead" bits i.e. never used by result(indicating low input swing or bad design) 

--- Quote End ---  

 

 

I noticed that the results never get up pass bit 19. That's why I'm truncating them. 

 

 

--- Quote Start ---  

another issue that popped up now is the way you display on the monitor. You must latch your fft output while refrshing the monitor otherwise a free running fft will not give identical block data unless you work hard to do that 

--- Quote End ---  

 

 

Isn't it good enough to have the dual-port RAM where the FFT is writing its output to it, and the monitor is reading from it? 

 

I just thought of something else that might cause the lines to fluctuate... 

It has to do with my ADC setup. The ADC is outputting the digitized data for the left and right channels alternatively on the same bus, i.e. multiplexing the data. I am de-multiplexing the ADC output to Left and Right channels, but only passing the Left channel data to the FFT. Is it right to say that half of the time the FFT is getting zeros? Hmm, may be the FFT is just using the same left channel data twice because it is latched? What should be the correct way of doing this? Should I pass one channel to the FFT real input and the other channel to the imaginary input?
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

If you are convinced about location of lines, fair enough. 

if your fft output doesn't use all those bits then who to blame, input swing or altera design? 

I guess you have taken care of sign bit(bit index 28) and checked against overflow of your used bits e.g by clipping. 

Your left/rt muxing shouldn't be a problem if you have one channel correctly muxed and sampled, muxing must be correct and don't try patching up with Re/Im trick. 

 

Rd/Wr of data is better frozen under your control so that the monitor displays same block, better only you update it manually, this way you get same lines
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

I am convinced about the location of lines because when I change the input frequency from 0 to 4kHz, one line go from the left edge to the middle while the second go from the right to the middle. 

 

However, for many frequencies, there are these two extra lines on the right half-something like 

 

|---------------------------------|---|-------| 

0  

 

What might be the cause for these two extra lines? 

 

Referring to the earlier three screen shots, I have 3 more concerns: 1) the fact that for many of them, i.e. at different frequencies, the line spreads out very much at the bottom (see picture for 1260Hz). 2) sometimes, the line still fluctuates up and down a little-sometimes slowly and sometimes very fast. 3) sometimes there are two or more lines instead of one that are in adjacent bins and may be with a gap in the middle (see picture for 944Hz)
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

This matlab code models your work. 

amplitude variation from block to block is no more than 1% and depends slightly on frequency value.The line wouldn't be absolute line at the bottom due to quantisation 

and fft resolution so expect some widening at base but any extra spikes means a bug. 

 

% sine function models analogue input % samples taken regularly into digital domain(ADC) % freq = 1 KHz if Fs = 8KHz x = sin(2*pi**1/8); %quantise for 16 bit hardware x = round(x * (2^15-1)); % 256 points fft % random blocks from above stream r =round(rand(1,1)*5000); y = fft(x(r:r+255)); y = round(y/2^7); plot(abs(y))
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

Great, so my screen shot for 1260Hz is OK, but the screen shot for 944Hz is NOT OK. 

And those two extra lines on the right also suggests a bug somewhere. I guess the question is where is the bug?
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

If you don't window the data before the FFT you will have artifacts from the truncation at the end/beginning of the FFT. This would cause some of the change in magnitude that you are seeing. In addition, there will be a less defined spike at the frequency of interest.

0 Kudos
Altera_Forum
Honored Contributor II
362 Views

True, the problem is truncation but windowing is meant for PSD(power spectral density), not fft per se. PSD breaks up a data stream into overlapping sections then windows each section then does fft on all followed by magnitude averaging over the sections - a pretty invloved computation for hardware. 

 

Applying a window crudely and directly to the stream can improve amp fluctuation since it gives less weight to the side values but thus distorts fft output
0 Kudos
Altera_Forum
Honored Contributor II
362 Views

The FFT is not very big. You can easily apply an accurate window with a look-up table.

0 Kudos
Altera_Forum
Honored Contributor II
362 Views

looks like a windowing issue to me.

0 Kudos
Altera_Forum
Honored Contributor II
362 Views

How can I easily apply windowing to it?

0 Kudos
Altera_Forum
Honored Contributor II
362 Views

between your data source and your FFT input you need a multiplier, ROM, and state machine. the input data and ROM output are connected to the multiplier, and the output of the multiplier (truncated) is fed into the FFT. a counter steps through the ROM at the same rate as the input data is fed into the FFT. i will see if i can draw a block diagram, but it is fairly straight forward.

0 Kudos
Reply