Forum Discussion
Altera_Forum
Honored Contributor
17 years agoAltera FFT - output scaling. How to do this correctly?
Hi,
I do not get correct scaled results if I do everything the FFT user guide recommends. I have instantiated a 1024 points FFT, with single output and burst architecture. The data width and twiddle factor precision is 16bits. I input 1024 times 16bit signed integers from the ADC to the 16bit real-input of the FFT module. (The ADC has a +/-2.5V input) To the imaginary input of the FFT module I apply 16bit zeros. This should be correct, shouldn’t it? The FFT module outputs 1024 pairs of 16bit real and 16bit imaginary part. First question: Are the real and imaginary 16bit values the mantissa in the sense of a floating point mantissa (first bit = sign, second bit = 1.digit in front of the radix point, remaining 14bits = decimal places) OR do I have to interpret these values as fixed point values. I have a sample frequency of 3kHz and used a very low frequency of 1Hz and 9Hz to verify the scaling to not have additional falsifications, caused by the rectangular window I used for the first shot. I input samples of an ideal sine waveform with different amplitudes and the same frequency, BUT whether I scale the output back with the given exponent value or not, the calculated magnitude is not the expected one. For example: For a 9Hz sine with an amplitude of +/-2,3V which is equal to +30146/-30147 decimal (+/-2.5V ADC input) I got the following real and imaginary parts for the corresponding frequency. Real: 3384 (0x0D38) Imaginary: -14391 (0xC7C9) I would expect a magnitude in the range of 30146 decimal, but using these values the magnitude is 14783. Using the exponent makes the results too big and I see no relation to input signal with such big numbers. How can such a large output (31bits in my case, max exponent = 15bits) provide unity gain, if the input is much smaller (16bits). Just choosing the lower 16bits of the shifted/scaled values can not be correct, because of the sign. I am a bit confused. Can somebody give me a hint? An example calcualtion would also be a great help.22 Replies
- Altera_Forum
Honored Contributor
Ignore my above remarks since your fft output is 16 bits.
I understand from your equations that you are converting the 16 bit output into 32 bit bus then doing the two stage shift(by exponent then by 9). Your work-around of 9 bits shift then taking 16 LSBs doesn't make sense to me. To avoid calculation problems of software Let us go back to your simple example: You said for your input sine of 30146 amplitude you get fft output as: Real: 3384 (0x0D38) Imaginary: -14391 (0xC7C9) fair enough. what is your exponent value in above example? It should be -1 so that output scales to 2^ -(-1) = 2 otherwise there is something wrong. - Altera_Forum
Honored Contributor
--- Quote Start --- Your work-around of 9 bits shift then taking 16 LSBs doesn't make sense to me. --- Quote End --- This does not makes sense to me, too. That's why I'm not happy with this solution. --- Quote Start --- To avoid calculation problems of software Let us go back to your simple example: You said for your input sine of 30146 amplitude you get fft output as: Real: 3384 (0x0D38) Imaginary: -14391 (0xC7C9) fair enough. what is your exponent value in above example? It should be -1 so that output scales to 2^ -(-1) = 2 otherwise there is something wrong. --- Quote End --- The exponent within this example is -10. Yes, there seems to be something wrong, but what is the question. - Altera_Forum
Honored Contributor
I should add, that I have monitored the exponent output of the FFT IP-core. The value I read is correct.
Then the question raises: Is the input correct? - Altera_Forum
Honored Contributor
You siad your inputis 30146, I assume you checked that in signaltap.
This matlab code can be used as reference: % generate a sinusoid at 9Hz, Fs at 3Khz x = round(30146*cos(2*pi*[0:1023]*9/3000)); % fft scaled for unity gain y = 1/512*fft(x); plot(abs(y)); max(abs(y)) - Altera_Forum
Honored Contributor
Mmmmhhh I have no Mathlab at my company. But I can check this at home this evening.
Referring to the input problem. I simulated the IP-core (this time with a quad-output architecture, for the reason of performance) with my test data, I attached it in form of two text files which are required by the simulation. Within the simulation, I verfied again that the sine amplitude is 30146 (first screenshot) and that the exponent is also -10 (second screenshot). (I also checked this in signaltapII) The real bin# 3 (=> 3x 2.92Hz frequency resolution = about 9Hz) has a value of 0x0D3A (with single output architecture this was 0x0D38). The imaginary bin# 3 has a value of 0xC7C7 (with single output architecture this was 0xC7C9). Look at the screenshots I attached. So the results depend on my input OR on the FFT IP-core itself and not on my processor system or my wrapper. What could be the reason for this behavior? P.S.: Thank KAZ for spending time on helping me. - Altera_Forum
Honored Contributor
I checked your inputs in matlab. All is ok if you scale the output by 2.
for example amplitude given by matlab fft for your input is 29569 which is pretty close to double your first example result. Now you proved that the problem is indeed to do with fft IP scaling, that is what you started with anyway(-10 should be -1). You now either cautiously use your workaround of rescaling (exp=exp+9) and wait for other people on the form to respond with their experience or ask Altera for help. - Altera_Forum
Honored Contributor
--- Quote Start --- I checked your inputs in matlab. All is ok if you scale the output by 2. for example amplitude given by matlab fft for your input is 29569 which is pretty close to double your first example result. Now you proved that the problem is indeed to do with fft IP scaling, that is what you started with anyway(-10 should be -1). You now either cautiously use your workaround of rescaling (exp=exp+9) and wait for other people on the form to respond with their experience or ask Altera for help. --- Quote End --- I will ask Altera, because waiting is not a solution. The last idea I have refers to the input signal. Are x(n), the samples, really the real bins OR are they the magnitude? If it would be the magnitude, the real and imaginary bins would not be correct. But then another question would raise... Where is the phase information?! By the way kaz, did you ever implement an Altera FFT? How does it work at your project? - Altera_Forum
Honored Contributor
First I did altera fft in 2001 !! no problem then except that the output bit resolution wasn't well done by altera, later they improved that. I did the scaling manually by bit shifting in vhdl as speed was crucial and couldn't depend on software speed. My exponent was correct at that time.
your input(x): xreal(n) is only real, ximag is zero so the magnitude of your input is same whether you view your input as x=x(n) or x=complex (xreal,ximag). I don't get what you say about magnitude?? but don't mix up between magnitude of a complex signal and amlpitude of a sinusoid. The maximum |magnitude| of your input(if you think of it as complex) is the amplitude of your sinusoid. your output(y): y is complex i.e. (y= complex(yreal, yimag)) and both elements together determine amplitude and phase(abs(y),angle(y)) in frequency domain. Your phase info is not relevant here, phase is only relevant when comparing two sinusoids at same frequency e.g. ouput/input of a system then phase tells you what this system is doing to phase at various frequencies. - Altera_Forum
Honored Contributor
--- Quote Start --- The maximum |magnitude| of your input(if you think of it as complex) is the amplitude of your sinusoid. your output(y): y is complex i.e. (y= complex(yreal, yimag)) and both elements together determine amplitude and phase(abs(y),angle(y)) in frequency domain. --- Quote End --- That's exactly what I mean and that's how I learned/understood it. Ok I understood everthing correct, the input signal seems to be correct (you also looked at it), and the simulation outputs the same results as real module. Than there must be some problem with the IP-core. I opened a service request. Maybe this will result in a solution of the problem. So far I'm using my workaround with the additional shifting by 9. - Altera_Forum
Honored Contributor
Hello Kaz,
I got the answer from Altera support. The guy who answered me, said, that my workaround can not work for every signal input, as you said and as I thought. Further he said I should find the maximum of my input samples, either by scaling up to a certain maximum or by just looking htrough the samples. Then if I have read the samples at the FFT output I have to calculate the magnitude of the vector (sqrt(RE²+IM²)) of each bin, serach through the block for the maximum magnitude nad compare it to the maximum input amplitude. With the factor between these two maxima I can scale up every calculated magnitude. This is really frustrating and also slow, because I first have to calulate the magnitude before scaling up. Doing this in hardware is not so easy for me, because i only now the basics of VHDL. It's just more complicated. Thanks for the help kaz.