近似核FFT的实现及其仿真

文章目录

参考《基于单比特和近似核FFT的瞬时测频算法及FPGA实现_袁俊榆_2.2_3.1》
参考《一种基于高阶近似核DFT的快速实现算法_吕远》
参考《数字信号处理_胡广书_4.2.2》

近日在查单比特测频方面的论文时,看到了使用近似核FFT来简化DFT运算的方式,颇感兴趣,研究一下。

近似核FFT

近似核FFT的实现及其仿真
利用圆的外切正方形上的点,近似相同角度的Wn系数值,
近似核FFT的实现及其仿真
对应到64点FFT的话,则系数如下图
近似核FFT的实现及其仿真

代码实现

参照DIF-FFT的实现方式,函数fft_pipe使用多级蝶形运算级联的方式进行运算。值得注意的是,compensation的使用,当需要对Wn系数进行放缩的时候(诸如使用硬件实现),为了保证在运算过程中,各级联部分的上下两路数据处于同一量级,需要在不含Wn的运算式中对运算结果进行放大。

function [result] = fft_pipe(Xn,Wn,compensation)
    pipe1 = zeros(1,64);
    pipe2 = zeros(1,64);
    pipe3 = zeros(1,64);
    pipe4 = zeros(1,64);
    pipe5 = zeros(1,64);
    pipe6 = zeros(1,64);

    %-- 第一级蝶形运算
    % disp('----第一级蝶形运算');
    for n=0:2:1
        for m=1:32
            pipe1(1,m+(n+0)*32) = compensation*(Xn(1,m+(n+0)*32) + Xn(1,m+(n+1)*32));
    %         index_0 = m+(n+0)*32-1;
    %         index_1 = m+(n+0)*32-1;
    %         index_2 = m+(n+1)*32-1;
    %         disp(['Y',num2str(index_0),'=(X',num2str(index_1),'+X',num2str(index_2),')']);
        end
        for m=1:32
            pipe1(1,m+(n+1)*32) = (Xn(1,m+(n+0)*32) - Xn(1,m+(n+1)*32)) * Wn(1,(m-1)*1+1);
    %         index_0 = m+(n+1)*32-1;
    %         index_1 = m+(n+0)*32-1;
    %         index_2 = m+(n+1)*32-1;
    %         index_3 = (m-1)*1+1-1;
    %         disp(['Y',num2str(index_0),'=(X',num2str(index_1),'-X',num2str(index_2),') *Wn',num2str(index_3)]);
        end
    end

    %-- 第二级蝶形运算
    for n=0:2:3
        for m=1:16
            pipe2(1,m+(n+0)*16) = compensation*(pipe1(1,m+(n+0)*16) + pipe1(1,m+(n+1)*16));
        end
        for m=1:16
            pipe2(1,m+(n+1)*16) = (pipe1(1,m+(n+0)*16) - pipe1(1,m+(n+1)*16)) * Wn(1,(m-1)*2+1);
        end
    end

    %-- 第三级蝶形运算
    for n=0:2:7
        for m=1:8
            pipe3(1,m+(n+0)*8) = compensation*(pipe2(1,m+(n+0)*8) + pipe2(1,m+(n+1)*8));
        end
        for m=1:8
            pipe3(1,m+(n+1)*8) = (pipe2(1,m+(n+0)*8) - pipe2(1,m+(n+1)*8)) * Wn(1,(m-1)*4+1);
        end
    end

    %-- 第四级蝶形运算
    for n=0:2:15
        for m=1:4
            pipe4(1,m+(n+0)*4) = compensation*(pipe3(1,m+(n+0)*4) + pipe3(1,m+(n+1)*4));
        end
        for m=1:4
            pipe4(1,m+(n+1)*4) = (pipe3(1,m+(n+0)*4) - pipe3(1,m+(n+1)*4)) * Wn(1,(m-1)*8+1);
        end
    end

    %-- 第五级蝶形运算
    for n=0:2:31
        for m=1:2
            pipe5(1,m+(n+0)*2) = compensation*(pipe4(1,m+(n+0)*2) + pipe4(1,m+(n+1)*2));
        end
        for m=1:2
            pipe5(1,m+(n+1)*2) = (pipe4(1,m+(n+0)*2) - pipe4(1,m+(n+1)*2)) * Wn(1,(m-1)*16+1);
        end
    end

    %-- 第六级蝶形运算
    for n=0:2:63
        for m=1:1
            pipe6(1,m+(n+0)*1) = compensation*(pipe5(1,m+(n+0)*1) + pipe5(1,m+(n+1)*1));
        end
        for m=1:1
            pipe6(1,m+(n+1)*1) = (pipe5(1,m+(n+0)*1) - pipe5(1,m+(n+1)*1)) * Wn(1,(m-1)*32+1);
        end
    end
    %-- 逆序取数
    result = zeros(1,64);
    for m = 0:63
        index = bin2dec(reverse(dec2bin(m,6)))+1;
        result(1,index) = pipe6(1,m+1);
    end
end
%清空一切
clc;clear all;close all;

%获得 近似核系数
W00 = complex(+4.0,-0.0);    W08 = complex(4.0,-4);      W16 = complex(-0.0,-4);     W24 = complex(-4,-4.0);
W01 = complex(+4.0,-0.5);    W09 = complex(3.5,-4);      W17 = complex(-0.5,-4);     W25 = complex(-4,-3.5);
W02 = complex(+4.0,-1.0);    W10 = complex(3.0,-4);      W18 = complex(-1.0,-4);     W26 = complex(-4,-3.0);
W03 = complex(+4.0,-1.5);    W11 = complex(2.5,-4);      W19 = complex(-1.5,-4);     W27 = complex(-4,-2.5);
W04 = complex(+4.0,-2.0);    W12 = complex(2.0,-4);      W20 = complex(-2.0,-4);     W28 = complex(-4,-2.0);
W05 = complex(+4.0,-2.5);    W13 = complex(1.5,-4);      W21 = complex(-2.5,-4);     W29 = complex(-4,-1.5);
W06 = complex(+4.0,-3.0);    W14 = complex(1.0,-4);      W22 = complex(-3.0,-4);     W30 = complex(-4,-1.0);
W07 = complex(+4.0,-3.5);    W15 = complex(0.5,-4);      W23 = complex(-3.5,-4);     W31 = complex(-4,-0.5);

W32 = complex(-4.0,0.0);     W40 = complex(-4.0,4);      W48 = complex(0.0,4);       W56 = complex(4,4.0);
W33 = complex(-4.0,0.5);     W41 = complex(-3.5,4);      W49 = complex(0.5,4);       W57 = complex(4,3.5);
W34 = complex(-4.0,1.0);     W42 = complex(-3.0,4);      W50 = complex(1.0,4);       W58 = complex(4,3.0);
W35 = complex(-4.0,1.5);     W43 = complex(-2.5,4);      W51 = complex(1.5,4);       W59 = complex(4,2.5);
W36 = complex(-4.0,2.0);     W44 = complex(-2.0,4);      W52 = complex(2.0,4);       W60 = complex(4,2.0);
W37 = complex(-4.0,2.5);     W45 = complex(-1.5,4);      W53 = complex(2.5,4);       W61 = complex(4,1.5);
W38 = complex(-4.0,3.0);     W46 = complex(-1.0,4);      W54 = complex(3.0,4);       W62 = complex(4,1.0);
W39 = complex(-4.0,3.5);     W47 = complex(-0.5,4);      W55 = complex(3.5,4);       W63 = complex(4,0.5);

W_approx = zeros(1,64);
W_approx(1,0*8+1:1*8) = [W00 W01 W02 W03 W04 W05 W06 W07];
W_approx(1,1*8+1:2*8) = [W08 W09 W10 W11 W12 W13 W14 W15];
W_approx(1,2*8+1:3*8) = [W16 W17 W18 W19 W20 W21 W22 W23];
W_approx(1,3*8+1:4*8) = [W24 W25 W26 W27 W28 W29 W30 W31];
W_approx(1,4*8+1:5*8) = [W32 W33 W34 W35 W36 W37 W38 W39];
W_approx(1,5*8+1:6*8) = [W40 W41 W42 W43 W44 W45 W46 W47];
W_approx(1,6*8+1:7*8) = [W48 W49 W50 W51 W52 W53 W54 W55];
W_approx(1,7*8+1:8*8) = [W56 W57 W58 W59 W60 W61 W62 W63];

% 获得精确的Wn系数
for m=0:63
   W_exact(1,m+1) = exp(-j*2*pi*m/64);
end

%生成单频信号
N = 64;
t = (0:N-1);
sig = sin(2*pi*0.2*t);
Xn = 25*sig;

%近似核算法运算
Wn = W_approx*2;     %W_approx约是W_exact的4倍
compensation = 8;
[result] = fft_pipe(Xn,Wn,compensation);
figure;
plot(20*log10(abs(result)/max(abs(result))));
title(['近似核多级蝴蝶运算结果']);

%精确FFT运算
Wn = floor(1024*W_exact);
Xn = 25*sig;
compensation = 1024;
[result] = fft_pipe(Xn,Wn,compensation);
figure;
plot(20*log10(abs(result)/max(abs(result))));
title(['精确的多级蝴蝶运算结果']);

%内置FFT函数运算
figure;
plot(20*log10(abs(fft(Xn,64))/max(abs(fft(Xn,64)))));
title('内置FFT运算结果');

W_approx是近似核的系数,W_exact是精确的Wn系数,仿真过程很简单,产生单频信号,改变幅度、W系数的幅度。使用近似核FFT的话,动态会差一些。
近似核FFT的实现及其仿真