Contents

FFT algoritm

clear;                      % clears all previus values from memory
clc;                        % clear command window
fs =  44100;                % samplinf freq.
fftLength=32;               % windowlength

% signal frequencies
data_length = 8;           % data length in FPGA calculations
max = 2^(data_length-1) - 1 ;            % max aplitude 2^n  /2

f1 = 1000;
a1 = max/2;

f2 = 0;
a2 = max/4;

f3 = 8000;
a3 = max/2;

% calculating signals
comp1 = a1 * cos(2*pi*f1*[0:1/fs:1]);
comp2 = a2 * cos(2*pi*f2*[0:1/fs:1]);
comp3 = a3 * cos(2*pi*f3*[0:1/fs:1]);

% calculatin vector values for step function
d1 = ones(1, 24);
d2 = 0.*ones(1, 1000 );

%data = [ d1 , d2];                  % creates vector with step function
data = comp1 + comp2 + comp3;      % creates vector from 3 sin functions

figure(1)               % plots separete sin functions
plot ( comp1, '-');
hold on;
plot ( comp2, '-');
plot ( comp3, '-');
xlim([1 50])
title('Separete SIN functions')
ylabel('magnitude'), xlabel('time')
hold off;

figure(2)               % plots signal for fft
plot ( data);
title('Signal for FFT analysis FFT')
ylabel('magnitude'), xlabel('time')
xlim([1 100])

figure(3)               % plots resultinf fft from Matlab functions
ft =fft(data,fftLength);
ftMag=abs(ft(1:fftLength/2));
stem (ftMag)
title('Linear Magnitude FFT')
ylabel('magnitude'), xlabel('kHz')

xt = xticks;        % returns the current x-axis tick values as a vector
fstep = fs/fftLength;       % tick of f axis in f domain
xtnew = round((xt-1)*fstep/1000, 1) ;   % calculate new tick in kHz
xticklabels(xtnew)      % set new tick labels

% figure(4)               % plots resultinf fft(in dB)  from Matlab functions
% ft =fft(data,fftLength);
% ftMag=abs(ft(1:fftLength/2));
% plot (20*log10(ftMag))
% title('dB Magnitude')
% ylabel('dB'), xlabel('kHz')
%
% xt = xticks;        % returns the current x-axis tick values as a vector
% fstep = fs/fftLength;       % tick of f axis in f domain
% xtnew = round((xt-1)*fstep/1000, 1) ;   % calculate new tick in kHz
% xticklabels(xtnew)      % set new tick labels

Data preparation for FFT

% reverse bit calulation
bits = length(dec2bin( fftLength - 1 ));    % how many bits in binary number
rev_bit_dec = zeros(1,fftLength);           % create vektor size of fftlength

for n=1:fftLength
    bin_num = dec2bin(n-1 , bits);          % converting to binary number
    rev_bit = [];                           % create empty vector
    for k=bits:-1:1
       rev_bit = [rev_bit , bin_num(k)];
    end
    rev_bit_dec(n) = bin2dec(rev_bit) ;     % add 1 to match Matlab numbering
end

%  creating array
%  create empty array to store values in reverse bit order
stage = zeros(bits + 1,fftLength);

for n=1:fftLength
     stage(1,n)  =  data(rev_bit_dec(n)+1);
end

% Calculating W twiddling factor for all stages
for n = 1 : fftLength/2
    W(n)  = exp(-1i * (n-1) * 2 * pi/ fftLength );
end

% convert to fixed point mumber -> sfi(v,w,f) returns a signed fixed-point object with value v, word length w, and fraction length f.
Wr = sfi(real(W),data_length,data_length-2);
Wi = sfi(imag(W),data_length,data_length-2);

st_real = sfi(real(stage) , data_length + 3 , 0);
st_imag = sfi(imag(stage) , data_length + 3 , 0);
% temp values for multiplaying with W twiddling factor
st_real_tmp = sfi(real(zeros(bits + 1,fftLength)) , data_length + 3 , 0);
st_imag_tmp = sfi(imag(zeros(bits + 1,fftLength)) , data_length + 3 , 0);

First stage

for n = 1 : 2^1 : fftLength
    % Even
    stage(2,n)    = stage(1,n) + stage(1,n+1);
    % Odd
    stage(2,n+1)  = stage(1,n) - stage(1,n+1);
end

% calculations using separate real and imaginary numbers
for n = 1 : 2^1 : fftLength
    % Even
    st_real(2,n)    = st_real(1,n) + st_real(1,n+1);
    % imag is 0
    % Odd
    st_real(2,n+1)  = st_real(1,n) - st_real(1,n+1);
    % imag is 0
end

Second stage

% Calculating W twiddling factor
for n = 1 : 2
    Wn(n)  = exp(-1i * (n-1) * 2 * pi/ 4 );
end

% calculate next stage values
for n = 1 : 2^2 : fftLength
    % Even pair
        stage(3,n+0)   = stage(2,n+0) + Wn(1)*stage(2,n+2);
        stage(3,n+1)   = stage(2,n+1) + Wn(2)*stage(2,n+3);
    % Odd par
        stage(3,n+2)   = stage(2,n+0) - Wn(1)*stage(2,n+2);
        stage(3,n+3)   = stage(2,n+1) - Wn(2)*stage(2,n+3);
end

% calculations using separate real and imaginary numbers
for n = 1 : 2^2 : fftLength
    % Even pair
        st_real(3,n+0)   = st_real(2,n+0) + st_real(2,n+2);
        % imag is 0
        st_real(3,n+1)   = st_real(2,n+1) ;         % real is 0
        st_imag(3,n+1)   = -1 * st_real(2,n+3);     % mult -j
    % Odd par
        st_real(3,n+2)   = st_real(2,n+0) - st_real(2,n+2);
        % imag is 0
        st_real(3,n+3)   = st_real(2,n+1) ;         % real is 0
        st_imag(3,n+3)   = st_real(2,n+3);          % mult -j
end

Therd stage

% Calculating W twiddling factor
for n = 1 : 4
    Wn(n)  = exp(-1i * (n-1) * 2 * pi/ 8 );
end

% calculate next stage values
for n = 1 : 2^3 : fftLength
    for k = 0 : 3
        % Even pair
        stage(4,n+k)   = stage(3,n+k) + Wn(k+1)*stage(3,n+k+4);
        % Odd par
        stage(4,n+k+4) = stage(3,n+k) - Wn(k+1)*stage(3,n+k+4);
    end
end

% calculations using separate real and imaginary numbers
for n = 1 : 2^3 : fftLength
    for k = 0 : 3
        st_real_tmp(3,n+k+4) = ( Wr(k*4+1) * st_real(3,n+k+4) ) - (  Wi(k*4+1) * st_imag(3,n+k+4) );
        st_imag_tmp(3,n+k+4) = ( Wi(k*4+1) * st_real(3,n+k+4) ) + (  Wr(k*4+1) * st_imag(3,n+k+4) );
    end
end
for n = 1 : 2^3 : fftLength
    for k = 0 : 3
        % Even pair
        st_real(4,n+k)   = st_real(3,n+k) + st_real_tmp(3,n+k+4);
        st_imag(4,n+k)   = st_imag(3,n+k) + st_imag_tmp(3,n+k+4);
        % Odd par
        st_real(4,n+k+4) = st_real(3,n+k) - st_real_tmp(3,n+k+4);
        st_imag(4,n+k+4) = st_imag(3,n+k) - st_imag_tmp(3,n+k+4);
    end
end

4th stage

% Calculating W twiddling factor
for n = 1 : 8
    Wn(n)  = exp(-1i * (n-1) * 2 * pi/ 16 );
end

% calculate next stage values
for n = 1 : 2^4 : fftLength
    for k = 0 : 7
        % Even pair
        stage(5,n+k)    = stage(4,n+k) + Wn(k+1)*stage(4,n+k+8);
        % Odd par
        stage(5,n+k+8)  = stage(4,n+k) - Wn(k+1)*stage(4,n+k+8);
    end
end

% calculations using separate real and imaginary numbers
for n = 1 : 2^4 : fftLength
    for k = 0 : 7
         st_real_tmp(4,n+k+8) = ( Wr(k*2+1) * st_real(4,n+k+8) ) - (  Wi(k*2+1) * st_imag(4,n+k+8) );
         st_imag_tmp(4,n+k+8) = ( Wi(k*2+1) * st_real(4,n+k+8) ) + (  Wr(k*2+1) * st_imag(4,n+k+8) );
    end
end
for n = 1 : 2^4 : fftLength
    for k = 0 : 7
        % Even pair
        st_real(5,n+k)    = st_real(4,n+k) + st_real_tmp(4,n+k+8);
        st_imag(5,n+k)    = st_imag(4,n+k) + st_imag_tmp(4,n+k+8);
        % Odd par
        st_real(5,n+k+8)  = st_real(4,n+k) - st_real_tmp(4,n+k+8);
        st_imag(5,n+k+8)  = st_imag(4,n+k) - st_imag_tmp(4,n+k+8);
    end
end

5th stage

% Calculating W twiddling factor
for n = 1 : 16
    Wn(n)  = exp(-1i * (n-1) * 2 * pi/ 32 );
end

% calculate next stage values
for n = 1 : 2^5 : fftLength
    for k = 0 : 15
        % Even pair
        stage(6,n+k)    = stage(5,n+k) + Wn(k+1)*stage(5,n+k+16);
        % Odd par
        stage(6,n+k+16)  = stage(5,n+k) - Wn(k+1)*stage(5,n+k+16);
    end
end

% calculations using separate real and imaginary numbers
for n = 1 : 2^5 : fftLength
    for k = 0 : 15
         st_real_tmp(5,n+k+16) = ( Wr(k*1+1) * st_real(5,n+k+16) ) - (  Wi(k*1+1) * st_imag(5,n+k+16) );
         st_imag_tmp(5,n+k+16) = ( Wi(k*1+1) * st_real(5,n+k+16) ) + (  Wr(k*1+1) * st_imag(5,n+k+16) );
    end
end
for n = 1 : 2^5 : fftLength
    for k = 0 : 15
        % Even pair
        st_real(6,n+k)    = st_real(5,n+k) + st_real_tmp(5,n+k+16);
        st_imag(6,n+k)    = st_imag(5,n+k) + st_imag_tmp(5,n+k+16);
        % Odd par
        st_real(6,n+k+16)  = st_real(5,n+k) - st_real_tmp(5,n+k+16);
        st_imag(6,n+k+16)  = st_imag(5,n+k) - st_imag_tmp(5,n+k+16);
    end
end

Ploting out

slowly plot result

figure(5)
for n = 1 : bits +1
    %plot( abs( real_n(i, :) + j.*imag_n(i,  :) ) );
    stem( abs( stage(n,1:fftLength/2) ) );
%     pause(1);
end
xt = xticks;        % returns the current x-axis tick values as a vector
fstep = fs/fftLength;       % tick of f axis in f domain
xtnew = round((xt-1)*fstep/1000, 1) ;   % calculate new tick in kHz
xticklabels(xtnew)      % set new tick labels
title('FFT using custom function')
ylabel('magnitude'), xlabel('kHz')

figure(6)
for n = 1 : bits +1
    %plot( abs( real_n(i, :) + j.*imag_n(i,  :) ) );
    temp = st_real + 1i * st_imag;
    stem( abs( temp(n,1:fftLength/2) ) );
%      pause(1);
end
xt = xticks;        % returns the current x-axis tick values as a vector
fstep = fs/fftLength;       % tick of f axis in f domain
xtnew = round((xt-1)*fstep/1000, 1) ;   % calculate new tick in kHz
xticklabels(xtnew)      % set new tick labels
title('FFT using custom function real/imag separate')
ylabel('magnitude'), xlabel('kHz')

figure(7)
dif2 = 100* abs(temp(bits +1,1:fftLength/2) - ft(1:fftLength/2))./abs(ft(1:fftLength/2)) ;
plot(dif2, 'blue')
title('Difference in calculations')
xt = xticks;        % returns the current x-axis tick values as a vector
fstep = fs/fftLength;       % tick of f axis in f domain
xtnew = round((xt-1)*fstep/1000, 1) ;   % calculate new tick in kHz
xticklabels(xtnew)      % set new tick labels
ylabel('percents, %'), xlabel('kHz')