基2频率抽取实现FFT的Verilog程序

这里以一个8点FFT设计为例作为介绍,整体电路架构如下图(可点击放大看),实现了一个数据串行输入,结果并行输出的FFT算法(data_in_real为输入值的实部,data_in_img为虚部):

 

上图架构是不是跟8点基2频率抽取FFT算法的蝶形运算框图(如下图)很相像:

 

因此结果很明了,最右边第一个模块one_stage_1实现第一级输出的4个蝶形运算,每个对应的蝶形运算如下:

 

这四个蝶形运算对应输出八个结果,分别送到one_stage_21,one_stage_22。也就是对应第二级的上下两个蝶形运算。

one_stage_21,one_stage_22又分别会有四个运算结果出来,两两被送到最后一级蝶形运算,由四个蝶形运算单元组成,分别为one_stage_31,one_stage32,one_stage33,one_stage_34。

每级单元的one_stage具体实现如下框架所示:

 

buffer_inst存储本级将要做蝶形运算的数据,比如one_stage_1里面的buffer_inst将会获取原始输入数据; one_stage_21,one_stage_22,one_stage_31,one_stage32,one_stage33,one_stage_34的buffer_inst里面将存取上一级相应的运算的结果。各级之间的握手信号为in_valid和o_valid。当每级拿到了完整的待计算数据之后,相应的o_valid就会被拉高,以告知下一级开始取数据,当本级运算结束,o_valid信号拉低。

w_coef_inst里面存的是蝶形运算的旋转因子,目前是作为9位有符号数来存储的,即将旋转因子扩大了255倍之后只保留整数位(原本旋转因子的范围在-1~1之间),也就是低8位表示的是小数点后的数。

实现如下:

 

addr为其旋转因子寻址信号。

目前的蝶形运算实现单元如下arithmetic_unit_inst(日后可能会做改进):

由于输入数据为24位的有符号定点数(低八位为小数),而蝶形运算因子为9位的,所以对于有符号数运算先要对蝶形运算因子做符号位扩展(原因见《有符号数单元加法器设计要点》),使其变为24位数据(c,d即符号位扩展后的蝶形运算因子),实现如下:

 

每个蝶形运算:

 

得第一个输出的计算代码如下(后缀real代表实部,img代表虚部,a_real,a_img 分别代表x(n)这个输入的实部和虚部;b_real,b_img分别代表x(n+N/2)这个输入的实部和虚部):

第二个输出(d_o2_real,d_02_img)计算代码如下:

 

(这里是直接用了 "*" 来做乘法运算,FPGA会直接综合成DSP里面的乘法模块,后面我们将会使用自己设计的乘法器来替换,那时候我们对数字信号运算电路设计的理解就会更深了)

d_o2_real_full,d_02_img_full为输入数据与蝶形运算因子相乘之后的完整结果;

而蝶形运算因子被扩大了255倍,其低8位都是表示小数,同样输入的数据a_real,a_img,b_real,b_img为24位数据,其低8位也表示小数位。

因此8位小数位与8位小数位相乘,其结果的低16位都是表示小数位。

因此我们的输出d_o2_real,d_02_img只取了d_o2_real_full,d_02_img_full的高24位,把低8位直接舍弃掉了,也就相当于每级的蝶形运算把小数位舍掉了8位,只保留了8位小数位的精度。

即每级运算的精度只能达到 1/256 ,如果级数越多,那么累积的误差也就可能会更大。

输入的8个数据如下:

那么对应的实际的输入的实部与虚部为上面的值除以256

对应为:

下面是仿真结果:

 

可以看到仿真结果相应的最后一级的输出结果的十进制如上。

把上述结果除以256(即第八位表示小数),得相应的每级输出结果如下(real 表示实部,img表示虚部):

 

  • 8
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值