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

Help with altera FFT

Altera_Forum
Honored Contributor II
11,855 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
3,203 Views

Hi Mesbah, 

 

if you plot(y2) or (y) you will see the distortion you are causing... 

 

good luck
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

i dont think its distortion i just raised the negitive part of the signal up... do u think i shouldnt do that ?..... should i feed y1(has pos & neg ) to the altera fft ? 

if so how can i express negative part of the signal in vhdl ? 

 

thanks
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

Hi Mesbah, 

 

you are causing fatal distortion to your nice sine waves by offsetting the negative halves up as this implies high frequencies due to sudden changes. Remember time domain and freq domain are related: sudden changes of amplitude or phase in time domain imply high frequencies, and high freq imply sudden changes in time domain... 

 

your ifft expects signed input, so I am told. 

The vhdl people allow you + representation. std_logic is read according to the way you decide(or ifft decides). If you want to store your sine data in lut then use mif and it accepts signed values. if you want to store 64 data on wires(as constants) then and to avoid the hassle of conversions use type "signed" then convert as required. 

 

Here is my adjustment of your code: 

clear; 

N = 64; 

Fs = 64; 

INVERSE = 0; 

y = round((2^15-1)*sin(2*pi*5*[0:63]/Fs)); 

 

Matlab_fft = fft(y); 

%[Y, exp_out] = fft_1_model(y,N,INVERSE); 

%Altera_fft = Y.*2.^(-exp_out); 

 

power_fft1 = abs(Matlab_fft); 

%power_fft2 = abs(Altera_fft); 

plot(power_fft1);hold 

%plot(power_fft2,'r') 

 

************* 

if for any other reason you want to get rid of negative sine data then offset all values up, you will then get your frequency and some dc: 

 

y2 = y + abs(min(y)); 

figure;hold 

plot(y); 

plot(y2,'r')
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

I have a different but probably somewhat related question. I have a continuous digitized 1000Hz sine wave going to the FFT input. The FFT is configured with a streaming architecture. I get the expected two (almost identical) peaks from the output-one at the positive side and the other at the negative side. My question is how come the values for the peaks fluctuate constantly. In other words, the amplitudes for these two peaks keep changing, and the difference between the maximum and minimum amplitude is quite large.

0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

Hi, 

 

You got a bug somewhere. One possible subtlety is this: 

 

Is your sine input continuous in phase. If you are reading sine LUT make sure there is phase continuity at the end of the cycle. You need to carefully choose your data points and not repeat the first value at the end. 

 

for a correct cycle I will do this: 

sin_data = sin(2*pi*[0:1023]/1024); 

plot(sin_data) 

 

then scale it for hardware. choose other than [0:1023]/1024 for your frequency case. 

 

You should see the first sample is 0 but the last sample is just under zero and shouldn't be zero. 

 

Having said that it is unlikley that phase will cause major amp fluctuations unless it is grossly wrong. So look for timing issues, your sampling clk and the way your input actually enters the fft.
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

Thanks for your quick reply... 

 

My input is an analog sine wave passing through an ADC and then into the FFT, so I guess it can't be a phase problem. So what am I supposed to look for related to timing issues? The FFT did not output any errors!
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

If your fft functional simulation is ok and your timing report is ok then we can forget about timing. I will check these issues: 

 

1) is your analogue input not fluctuating. can you exclude that by inputting from a LUT as a test. 

 

2) is your data representation from ADC correct. Some ADCs use 2's complement, others use offset binary. They are different of course. 

 

3) is your scaling correct. This is the most likely culprit for now. Remember altera has left scaling algorithm to the designer. make sure you are scaling each block correctly and not latching the exponent from block to block. 

 

4) is there any clipping/overflow of data, though clipping will lead to widening of spectrum side lobes, overflow and unwrapping will lead to spikes on either side of your sine point.
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

I changed the FFT to a 256-point burst architecture with the inputs coming from a ROM. When the ROM content is from a digitized 1000Hz analog sine wave, I get two peaks with sidelobes (is that what you call them?). However, when I change the ROM data to numbers generated by the equation 

 

ROM_data = sin(2*1000*pi*[0:255]/256) 

 

The FFT output is all zeros, and even the exponent is all zeros. What happened?
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

Try make changes gradually, too many changes will not help you. So put back your design streaming as original then input from LUT instead of ADC. 

 

your equation below is not right for its purpose: 

ROM_data = sin(2*1000*pi*[0:255]/256) 

plot(ROM_data) and see. 

 

It should be like this: 

ROM_data = sin(2*pi*[0:255]/256); 

 

then scale up: 

 

data = round(ROM_data * (2^15-1)); %for 16 bit signed 

 

Use plot(data) to check result before you go to hardware.  

 

The frequency you get from this sinusoid = Fs/256 

so if your sampling clk = 50MHz then you should get a line at 50/256MHz 

since each cycle takes that many clks to finish.If you want other higher frequencies then you can jump the LUT regularly.
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

This question is on interpreting the FFT outputs... 

So I have this 64-point streaming FFT with the inputs generated by the equation 

 

ROM_data = sin(2*pi*[0:63]/64); 

 

then scale up by 

 

data = round(ROM_data * (2^15-1)); %for 16 bit signed 

 

These numbers for the FFT input are stored in ROM (LUT). 

 

When the first sample is 0 and the last sample is just under zero, the FFT outputs are: 

source_exp = -7 for all the bins 

source_real = 0 for all the bins 

source_imag = -8192 in the second bin and +8192 in bin 64 (last bin) 

 

However, when the first sample is just above 0 and the last sample is zero, i.e., the input data is shifted one sample point to the right, the FFT outputs are: 

source_exp = -6 for all the bins 

source_real = 1606 in the second bin and 1606 in bin 64 (last bin) 

source_imag = -16304 in the second bin and +16304 in bin 64 (last bin) 

 

In these two cases, the FFT input samples are exactly the same, the only difference is that the second case is shifted to the right by one sample point. 

 

Shouldn't the FFT outputs be the same for both cases? And if so, how do you interpret what I got as shown above to see that they are the same? Are you supposed to somehow combine the real and the imag parts together?
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

Continuing with my question on interpreting the FFT output... 

May be the observation that I described in my previous post has something to do with my initial question several posts ago, i.e., the amplitudes fluctuate constantly with a constant input. 

 

Because I am only looking at the source_exp and source_real FFT outputs, and ignoring the source_imag output, therefore, in every 64th cycle, source_real goes to 0. And for the other cycles, source_real decreases between the max and 0? Do you thing this is the reason?
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

Hi, 

 

To avoid guess work you better compare results with matlab. 

 

in matlab: 

test = round(fftshift(fft(ROM_data)); 

 

test must equal your hardware fft(allowing for rounding variations) 

 

You may use cos instead of sin since sin will give zero real. 

 

you may also want to visulaise the spectrum of your output or matlab output by typing: 

 

f = linspace(-.5,.5,64); 

plot(f,abs(test)) 

or plot(f,abs(your fft output));
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

Thanks, however, I do not have Matlab. Attached is the mif file for my ROM data if it is possible for you to check it out in Matlab for me. 

 

Can you tell me how do I easily combine the real and the imag together to form one meaningful number?
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

I glanced at your mif and it looks ok to me, tomorrow I will do fft in Matlab and send you my results(hopefully). 

 

complex signals in hardware are represented on two (real) channels. One is treated as real and the other as representing the imaginary value(units of sqrt(-1). Don't worry about details now. All you need is that to see amplitude response you look at absolute value i.e. Amplitude of complex vector = sqrt(I^2 + Q^2). plot amplitude and you should see two symmetrical lines unless your input is sine/cosine which leads to one line only(non-symmetrical spectrum). Complex math is same as vector math...
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

What are the I and Q in your equation sqrt(I^2 + Q^2)? Are they the real and imaginary values from the FFT source_real and source_imag? 

 

Do I do the scaling with source_exp on both the source_real AND source_imag? 

Also do I do the scaling before or after doing the sqrt(I^2 + Q^2)?
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

 

--- Quote Start ---  

What are the I and Q in your equation sqrt(I^2 + Q^2)? Are they the real and imaginary values from the FFT source_real and source_imag? 

--- Quote End ---  

 

 

yes, I & Q are the special names in communications given to the two channels representing in effect a complex signal, I = inphase, Q=Qudrature. 

 

 

--- Quote Start ---  

 

Do I do the scaling with source_exp on both the source_real AND source_imag? 

 

--- Quote End ---  

you need to scale according to the way altera have done their IP. 

I believe it is the output of fft that must be scaled...ofcourse, check the IP data sheet. 

 

 

--- Quote Start ---  

 

Also do I do the scaling before or after doing the sqrt(I^2 + Q^2)? 

--- Quote End ---  

 

In normal computation such as matlab you don't need any scaling. Altera simply left that for you. So for your hardware results yes do scaling first.  

 

I checked the matlab output and it looks like your results: 

 

your result .....................matlab fft 

real = zeros .....................same 

imag(0) = 0 .....................same 

imag(1) = -8192 ..............-1048576 

imag(63) = +8192 ............+1048576 

imag(others) = 0 ..............same 

 

If you now multiply 8192 by 2^7 you get matlab result. 

Your problem now is this: your final output value needs far more bits than just 16 signed so you need to divide down by truncation to a max of 32767 or less. 

 

Your other case of having one sample just above zero ...etc. No don't do that. By doing that you are no longer having a proper sine in the sense of orthogonality in a complex vector.
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

Thanks a lot Kaz. You have been so helpful. 

 

I am now going to change the input to analog audio data passing through an ADC. When I get that to work, I think I will post my entire results here so that people like me don't have to keep asking the same questions about implementating the FFT. 

 

Enoch
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

However, my suspicion now is that the fluctuating amp is due to one or both of the following: 

 

1) wrong fft scaling 

2) fft and its scaling ok but your test is misleading as you may be injecting the analog sinusoid with different phase each fft block. Your fft resolution is too low, it is better to have many sinusoid cycles per fft block rather than just one cycle as phase changes become exagerated. So either increase the fft resolution to say 2048 and/or increase the speed of your sinusoid.
0 Kudos
Altera_Forum
Honored Contributor II
3,203 Views

How can I increase the speed of my sinusoid if my input is a sound wave with a certain frequency?

0 Kudos
Altera_Forum
Honored Contributor II
3,145 Views

The easiest fix for you is to first make sure your fft scaling is ok. Not just the use of exponent but your truncation afterwards. If this is ok then your fft is ok and I wouldn't worry about the test. 

 

If you want your test to do better then increase fft resolution. 

 

If your audio is received upsampled then you may decimate it down to minimum (for test purposes only). Thats what I labelled speed by mistake. Remember fft resolution doesn't have to be equal to number of points per sinusoid cycle, that ruins the test unless you get the phase exactly same per each block. In short make your fft 2048 and repeat the test. Try also pass the audio to both real and imaginary so that the phase change is on both channels(again for test purpose only).
0 Kudos
Reply