Forum Discussion
Help with altera FFT
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.56 Replies
- Altera_Forum
Honored Contributor
Hi Mesbah,
if you plot(y2) or (y) you will see the distortion you are causing... good luck - Altera_Forum
Honored Contributor
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 - Altera_Forum
Honored Contributor
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') - Altera_Forum
Honored Contributor
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.
- Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
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! - Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
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? - Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
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?