基于FPGA的快速傅里叶变换加速(二)


蝶形运算模块介绍及matlab代码实现)

1. 基二FFT的基本原理

1.1 快速傅里叶变换

简单形式离散傅立叶变换(DFT)和逆离散傅立叶变换(IDFT)所需的复杂乘法和加法运算的数量为N2,因为有N个数据点要计算,每个数据点都需要N复杂的算术运算。
对于长度为n的输入向量x,DFT是长度为n的向量X,具有n个元素:
在这里插入图片描述

用计算机科学术语来说,我们可以说它们具有算法复杂度O(N2),因此不是一种非常有效的方法。如果我们不能做得更好,那么DFT对于大多数实际的DSP应用将不是很有用。但是,有许多不同的“快速傅立叶变换”(FFT)算法使计算信号的傅立叶变换的速度比DFT快得多。
顾名思义,FFT是用于快速计算数据矢量离散傅里叶变换的算法。 FFT是一种DFT算法,可将N点所需的计算次数从O(N2 )减少到O(N log N),其中log是以2为底的对数。如果要变换的函数与采样频率不是谐波相关,则FFT的响应看起来像是“ sinc”函数(sin x)/ x如果N为2的常规幂(N = 2p),则“基数2”算法很有用。如果我们假设算法复杂度提供了执行时间的直接量度,并且相关对数的底数是2,则如图1.1所示,(DFT)与(Radix 2 FFT)的执行时间之比(表示为“速度”改善因子’)随着N的增加而大大增加。
1.1

1.2 常用FFT算法

术语“ FFT”实际上有点含糊,因为有几种常用的“ FFT”算法。 Radix 2有两种不同的算法,即所谓的“时间抽取”(DIT)和“频率抽取”(DIF)算法。这两个都依赖于将N点变换递归分解为2(N / 2)点变换。此分解过程可以应用于任何复合(非素数)N。如果N可被2整除,并且N是2的幂,则该方法特别简单,可以重复应用分解,直到进行琐碎的“ 1点”变换为止到达了。

1.2.1 时域抽取

(1) 实现过程

将序列x(n)按n为奇、偶数分为x1(n)、x2(n)两组序列;用2个N/2点DFT来完成一个N点DFT的计算。
设序列x(n)的长度为N,且满足:N = 2**M,M是自然数;
(1) 按n的奇偶把x(n)分解为两个N/2点的子序列
X1 ( r ) = X(2r), X2 ( r ) = X(2r + 1), r = 0,…,N/2;
(2)用N/2点X1(k)和X2(k)表示序列x(n)的N点DFT X(k)
在这里插入图片描述
由于X1(k)和X2(k)均以N/2为周期,且由于旋转系数的性质, X(k)又可表示为:
在这里插入图片描述
对上式的运算用下图所示的流图符号来表示
在这里插入图片描述

一次分解结果如图:
在这里插入图片描述
二次分解
在这里插入图片描述
结果如图:
在这里插入图片描述
三次分解如图:
在这里插入图片描述

(2)运算规律及编程思想
原位计算

序列长为N=2**M点的FFT,有M级蝶形,每级有N/2个蝶形运算。
同一级中,每个蝶形的两个输入数据只对本蝶形有用,每个蝶形的输入、输出数据节点在用一条水平线上。这样,当计算完一个蝶形后,所得的输出数据可立即存入原输入数据所占用的存储单元。经过M级运算后,原来存放输入序列数据的N个存储单元中可依次存放X(k)的N个值。
原位计算:利用同一存储单元存储蝶形计算输入、输出数据的方法。
优点:节约存储空间、降低设备成本。

旋转因子

N点DIT―FFT运算流图中,每个蝶形都要乘以旋转因子WpN,p称为旋转因子的指数。N=8 =2**3 时各级的旋转因子
在这里插入图片描述

距离

同一级中,同一旋转因子对应蝶形数目
第L级FFT运算中,同一旋转因子用在2M-L个蝶形中;
同一级中,蝶形运算使用相同旋转因子之间相隔的“距离”
第L级中,蝶距:D=2
L。
同一蝶形运算两输入数据的距离
在输入倒序,输出原序的FFT变换中,第L级的每一个蝶形的2个输入数据相距:B=2*L-1。

码位颠倒

输入序列x(n)经过M级时域奇、偶抽选后,输出序列X(k)的顺序和输入序列的顺序关系为倒位关系。

1.2.2 频域抽取

由于本项目未使用频域抽取,故不作实现介绍

(1) 运算规律比较

相同:
DIF-FFT算法也可采用原位计算;N=2M时,共有M级运算,每级共有N/2个蝶形,DIT与DIF算法的运算次数相同。
不同:
DIF-FFT算法输入序列为自然序列,输出为倒序序列。因此,在M级运算完成后,需对输出数据进行倒序才能得到自然顺序的X(k)。
蝶形运算符号不同:DIT-FFT蝶形是先相乘,后加/减;而DIF-FFT蝶形是先加/减,后相乘。

(2)运算量比较

DIF,DIR运算量相同
在这里插入图片描述

2. Matlab实现

由于matlab可直接使用fft函数进行运算,故matlab代码较简单,也只用来生成初始化数据及标准结果对比;

% 构建输入数据并写入文件用于verilog
width = 8;
depth = 64;
index = linspace(0, 2*pi, depth);
sin_value = sin(index);
sin_value = sin_value * (2^(width-1) -1 );
sin_value = fix(sin_value);
toVerilog = mod(sin_value+256, 256);
fid = fopen('Data_Input.txt', 'wt');
fprintf(fid, '%02x 00\n', toVerilog);
fclose(fid);

% 计算用于verilog的Wn的参数,均乘以255
fid = fopen('Data_Parameter.txt', 'wt');
for i = 1:6
    N = 2^i;
    for j = 0:N/2-1
        real_f = cos(2*pi*j/N);
        imag_f =-sin(2*pi*j/N); 
        real_d = fix(real_f * 127);
        imag_d = fix(imag_f * 127);
        real_d = mod(real_d + 256, 256);
        imag_d = mod(imag_d + 256, 256);
        %fprintf(fid, '(%02d.%02d) %02x %02x \t%1.4f     %1.4f\n',i, j, real_d, imag_d, real_f, imag_f);
        fprintf(fid, '%02x %02x\n',real_d, imag_d);
    end
end
fclose(fid);  

% 计算FFT
n = 0:depth-1;
y = fft(sin_value);
for i = 1 : depth
    yreal(i) = fix(real(y(i)));
    yimag(i) = fix(imag(y(i)));
end
yint = [yreal; yimag]'; % 最终比对用FFT结果

本文结束,详情可见下篇博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

生如昭诩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值