使用Verilog实现FFT
代码有参考学习自菜鸟教程的文章<Verilog 教程 7.5 Verilog FFT 设计>
原地址:https://www.runoob.com/w3cnote/verilog-fft.html
github仓库:https://github.com/woodecode/fft_verilog
script/project
使用C实现了生成旋转因子的代码。
目前实现了可通用的Butterfly和四点的FFT/IFFT,代码也配有非常完整的注释,方便理解。
非常适合入门verilog练手。😝
本工程使用iverlog和modelsim通过了仿真,
蝶形运算
蝶形运算模块将运算分成了三级,过程如下
推荐:如果你只是想检查Verilog文件的语法是否有错误,然后进行一些基本的时序仿真,iverilog 是一个不错的选择。相比于各大FPGA厂商的IDE几个G的大小,iverilog 极其小巧,并且支持全平台:Windows + Linux + MacOS 。下面这篇帖子介绍了如何使用Icarus Verilog来进行verilog文件的编译和仿真。非常简单轻便😁。
地址:https://zhuanlan.zhihu.com/p/95081329
至于如何使用iverilog+gtkwave仿真本工程,可参照下面的过程.
第一步:这个命令会将Verilog文件butterfly.v、ifft4.v和ifft4_tb.v编译,并生成一个名为test_ifft4的可执行文件。
iverilog -o test_ifft4 ..\butterfly.v ..\ifft4.v ..\ifft4_tb.v
第二步:这个命令会运行ifft4模块的testbench。
vvp test_ifft4
第三步:这个命令会打开波形查看器,以可视化保存在VCD文件wave_ifft4_tb.vcd中的仿真结果。
gtkwave wave_ifft4_tb.vcd
cd中的仿真结果。
gtkwave wave_ifft4_tb.vcd
butterfly.v
module Butterfly #(
parameter DATA_WIDTH = 4,// 默认位宽为
parameter EXPAND = 9 // 默认将旋转因子扩大1<<9=512倍
)(
input wire clk,
input wire rst_n,
input wire en,
// Input 1 and Input 2
input wire signed [DATA_WIDTH-1:0] in1_real,
input wire signed [DATA_WIDTH-1:0] in1_imag,
input wire signed [DATA_WIDTH-1:0] in2_real,
input wire signed [DATA_WIDTH-1:0] in2_imag,
// rotation factor
// 多出的1位用于存放符号位
input wire signed [EXPAND+1:0] ro_real,
input wire signed [EXPAND+1:0] ro_imag,
// Output 1 and Output 2
// 输出要比输入多富余出一个位宽
output wire signed [DATA_WIDTH:0] out1_real,
output wire signed [DATA_WIDTH:0] out1_imag,
output wire signed [DATA_WIDTH:0] out2_real,
output wire signed [DATA_WIDTH:0] out2_imag,
//
output wire valid
);
//因为有3级流水线,故为每一级流水线计算富余出一个位宽,确保精度
localparam PRECISION = 3;
// localparam EXPAND = 13;
// initial begin
// valid <= 'b0;
// end
reg [4:0] en_r;
// 每次将en的值保存到en_r寄存器的最低位,
// 保存en的值用于判断当流水线计算完毕输出时的数据是否是在en置位时的输入的,
// 这样是为了判断输出是否合法.
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
en_r <= 'b0;
end else begin
en_r <= {en_r[3:0], en};// 保存en的值到en_r寄存器的最低位
end
end
/*
* 整个过程分为三级计算.
*
* 第一步当然是要先计算x2 和 ro 的乘积的系数.
* 假设x2 = x2_r + i * x2_i;ro = ro_r + i * ro_i;
* 假设这两个虚数计算的结果是 rod = rod_r + i * rod_i;
* 计算过程如下:
* rod = x2 * ro;
* 即 rod = (x2_r + i * x2_i) * (ro_r + i * ro_i);
* 整理后 rod = (x2_r * ro_r - x2_i * ro_i) + i * (x2_r * ro_i + x2_i * ro_r);
*
* 第一级就是 在给定x2和ro(旋转因子)后,通过上式计算四个乘积的结果;
*
* 第二级就是 将这四个乘积结果进行加减组合后得出rod = rod_r + i * rod_i的过程.具体过程如下:
* rod_r = x2_r * ro_r - x2_i * ro_i;
* rod_i = x2_r * ro_i + x2_i * ro_r;
*
* 第三级则是 将x1和rod进行加减计算的过程.假设结果是y1和y2,具体过程如下: