8点流水线型FFT的Verilog_HDL实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
8点流水线型FFT的Verilog HDL实现
华南理工大学
calaok@
(一)算法介绍
采用图中的结构,x0(0)~x0(7)为输入数据,位宽为16位;输出数据的位宽为32位,倒序输出。
图3 8点FFT算法图
(二)系统设计
图4 系统总框图
1、系统总框图如图4所示,总共包括一下几个模块:
1
. 运算模块。
对应三阶运算,共采用三个运算子模块:
第一阶运算模块:对应蝶形算子只有W 0
(W 0=1), 第二阶运算模块:对应蝶形算子有W 0 、W 2(W 2=-j ), 第三阶运算模块:对应蝶形算子有W 0 、W 1 、W 2 、W 3。 221.第一阶运算模块:
模块功能:完成FFT 第一阶蝶形运算。 模块设计:
此时蝶形算子只有W 0,故蝶形运算结果为C =A +B ,D =A -B 。因此,只需要对输入数据做加减法即可。
考虑资源复用,这里定义一个16位的有符号数加法器和减法器,每次运算直接调用即可。
2.第二阶运算模块
模块功能:完成FFT 第二阶蝶形运算。 模块设计:
第二阶运算有蝶形算子W 0 、W 2。对于W 2蝶形运算结果为C =A +jB ,D =A -jB ,因此,只需另运算结果实部为A ,虚部为+/-B 即可。
对于W 0算子,这里定义了一个17位有符号数加法器和减法器处理。
对于W 2算子,对于运算结果的实部,只需将A 扩展成18位即可;针对虚部,对于结果C ,只需将B 扩展成18位,对于结果D 只用取B 的补码,计算过程流程如下图。
图6 第二阶运算模块
3模块功能:完成FFT 第三阶蝶形运算。
相当于多路开关
这个部分是因为有
模块设计:
第三阶运算模块:对应蝶形算子有W 0 、W 1 、W 2 、W 3。采用设计要求中提示的通用
)/2sin()/2cos(sin cos N p N p add ππ+= )/2sin()/2cos(sin cos N p N p sub ππ−= )/2sin(sin N p π=;这里,N =8。
根据上述公式,在进行一次蝶形运算时,只需首先确定cosaddsin ,cossubsin ,sin ,然后计算出(Ib-Rb)sin ,Rb*cosaddsin ,Ib*cossubsin ,最后将结果相加减即可。
(三)仿真结果分析
1、数据输入
图7 数据输入
(1)输入数据是两组连续8个的串行数据:
A=[1 2 3 4 4 3 2 1]; B=[-5 -5 5 5 -5 -5 5 5];
数据在系统时钟的上升沿被采集。
2、最后蝶形算子运算波形
(1
πp/N)
b c a b b +-R I =I +I cos(2πp/N)-sin(2πp/N)(I )sin(2πp/N)
⎡⎤⎢⎥⎣⎦
{}a d b b b -R =R R cos(2πp/N)+sin(2πp/N)+(I -R )sin(2πp/N)⎡⎤⎢⎥⎣⎦
{}b a d b b -+-R I =I I cos(2πp/N)-sin(2πp/N)(I )sin(2πp/N)⎡⎤⎢⎥⎣⎦
输入信号对应:Imul_Ra->Ra Imul_Ia->Ia Imul_Rb->Rb
Imul_Ib->Ib Imulc_Rout->Rc Imulc_Iout->Ic
Imuld_Rout->Rd
Imuld_Iout->Id 波形上的输入信号为实际大小的有符号数,由于在运算过程中进行了扩展,输出信号是实际公式计算值的512倍。
3、输出信号波形
图9 输出信号波形
输出结果最后经过了排序,在输出数据有效信号高电平时系统时钟的下降沿稳定。输(1)当输入数据为A=[1 2 3 4 4 3 2 1]时,MATLAB 运算的数据为:
20.0000
-5.8284 - 2.4142i 0
-0.1716 - 0.4142i 0 -0.1716 + 0.4142i 0
-5.8284 + 2.4142i 硬件运算的结果为:
10240
-2984-1236i 0
-88-212i 0
-88+212i 0
-2984+1236i
(
2)当输入数据为B=[-5 -5 5 5 -5 -5 5 5]时,MATLAB 运算的数据为:
0 0
-20.0000 +20.0000i 0 0 0
-20.0000 -20.0000i 0
硬件运算结果为:
0 0
-10240+10240i 0 0 0
-10240-10240i 0
(四)源程序
(1)add16.v
module add16(a,b,out);
end
endmodule
(2)sub16.v
module sub16(a,b,out);
input[15:0] a,b;
output[16:0] out;
reg[16:0] out;
wire[16:0] a1={a[15],a[15:0]}; wire[16:0] b1={b[15],b[15:0]};
always @(a1 or b1)
begin
out
=a1-b1;
end
endmodule
(3)add17.v
module add17(a,b,out);
input[16:0] a,b;
output[17:0] out;
reg[17:0] out;
wire[17:0] a1={a[16],a[16:0]}; wire[17:0] b1={b[16],b[16:0]}; always @(a1 or b1)
begin
=a1+b1;
out
end
endmodule
(4)sub17.v
module sub17(a,b,out);
input[16:0] a,b;
output[17:0] out;
reg[17:0] out;
wire[17:0] a1={a[16],a[16:0]}; wire[17:0] b1={b[16],b[16:0]};
always @(a1 or b1)
begin
=a1-b1;
out
end