并行快速傅里叶变换(PFFT)模块设计
概述
花了一天半的时间设计了这个并行FFT(PFFT)模块, 关于时域抽取(DIT)基-2分解的FFT结构这里不做说明,感兴趣的小伙伴请自行查阅相关资料, 这里不做过多赘述.
网上也有一些并行FFT设计的文档,但多是针对固定点数的并行FFT模块设计,我这里设计了一个通用化的并行FFT模块, 仅需要修改一个参数即可实现2, 4, 8, 16, 32 和64点的FFT 计算. 模块代码和测试代码已上传至GitHub上,有兴趣的小伙伴可以克隆下来自己研究.
如果你觉得这份代码对你有帮助,请在GitHub页面帮我点个⭐.
PFFT 模块采用时域抽取基-2分解方法来计算N点DFT, N为2的指数幂(2^FFT_ORDER, FFT_ORDER = 1,2,…,6).对于64点(2^6)以上的FFT计算, 需要对代码进行适当修改. 下图是生成的8点并行FFT的RTL原理图.

创建工程
- 使用
git工具克隆此仓库.
git clone https://github.com/falwat/code_repo.git
- 打开
vivado tcl shell, 使用cd命令切换至pfft目录 - 运行
source ./create_project.tcl,创建测试工程
cd <仓库所在文件夹/code_repo/pfft>
source ./create_project.tcl
文件组成
| 文件 | 说明 |
|---|---|
| ./pfft.v | 并行FFT模块. |
| ./butterfly_block.v | DIT-FFT 的一次分解模块. 在pfft模块和自己内部实例化由两个子一级的 butterfly_block和 一层蝶形运算模块butterfly构成. |
| ./butterfly.v | 蝶形运算模块 |
| …/common/cmult.v | 复数乘法器. 在butterfly模块中实例化. |
| ./sim_butterfly.v | butterfly模块的测试激励文件 |
| ./sim_pfft.v | pfft模块的测试激励文件 |
| ./sim_pfft.py | pfft模块测试分析脚本 |
| ./sim_data_gen.py | 为pfft模块测试激励文件生成测试数据. |
| ./create_project.tcl | 用于生成测试工程的tcl脚本. |
| ./readme.md | 说明文件(英文) |
| ./readme_zh.md | 说明文件(中文) |
参数说明
| 名称 | 类型 | 描述 |
|---|---|---|
| FFT_ORDER | integer | FFT的阶数. FFT_ORDER = log2(N), N = 2,4,8,16,32,64. |
| COMPLEX_DWIDTH | integer | 数据位宽. |
端口描述
| 名称 | I/O | 描述 |
|---|---|---|
| aclk | I | 上升沿触发. |
| aresetn | I | 同步复位信号. 低电平有效. |
| scale_sch | I | 缩放控制. 每个位控制一级蝶形运算模块. 0: 不对蝶形运算的输出进行缩放; 1: 对蝶形运算的输出缩小到1/2. |
| s_axis_tvalid | I | 数据输入通道的TVALID端口. 1表示输入数据有效. |
| s_axis_tdata | I | 数据输入通道的TDATA端口. 位宽由参数FFT_ORDER 和 COMPLEX_DWIDTH 决定, 通过如下公式进行计算: 2 ** FFT_ORDER * COMPLEX_DWIDTH. 输入数据 x在端口的映射为: {x[N-1].imag, x[N-1].real, ..., x[1].imag, x[1].real, x[0].imag, x[0].real} |
| m_axis_tvalid | O | 数据输出通道的TVALID端口. 1表示输出数据有效. |
| m_axis_tdata | O | 数据输出通道的TDATA端口. 位宽由参数FFT_ORDER 和 COMPLEX_DWIDTH 决定, 通过如下公式进行计算: 2 ** FFT_ORDER * COMPLEX_DWIDTH. 输出数据 X在端口的映射为: {X[N-1].imag, X[N-1].real, ..., X[1].imag, X[1].real, X[0].imag, X[0].real} |
资源消耗
DSP48E 的使用量满足如下公式:
3 ∗ 2 N − 1 ∗ ( log 2 ( N ) − 1 ) 3 * 2^{N-1} * (\log_2(N) - 1)3∗2N−1∗(log2(N)−1)
对于16点的PFFT, 需要的DSP48E的数量为: 3 * 8 * 3 = 72
实际综合后的资源消耗如下表所示:
| N-点FFT | Slice LUTs | Slice Registers | DSPs |
|---|---|---|---|
| 8 | 1667 | 2372 | 24 |
| 16 | 4611 | 6560 | 72 |
| 32 | 11779 | 16754 | 192 |
| 64 | 28678 | 40751 | 480 |
时延
数据输入到N点FFT计算结果输出所需的时延满足如下计算公式:
L a t e n c y ( N ) = ( log 2 ( N ) − 1 ) ∗ 8 + 2 Latency(N) = (\log_2(N)-1) * 8 + 2Latency(N)=(log2(N)−1)∗8+2
N点FFT的时延如下表:
| N点FFT | 时延(clks) |
|---|---|
| 2 | 2 |
| 4 | 10 |
| 8 | 18 |
| 16 | 26 |
| 32 | 34 |
| 64 | 42 |
测试
- 根据需要修改./pfft.v中参数
FFT_ORDER的值. - 修改./sim_data_gen.py中
fft_len参数的值.fft_len表示计算FFT的点数. - 运行./sim_data_gen.py, 生成测试数据文件
numbers.txt, 默认保存路径为D:\. - 在
Vivado中,点击Flow Navigator中的Run Simulation,或使用菜单Flow|Run Simulation - 运行仿真后, 在
D:\下会生成输出数据文件output.dat. - 运行./sim_pfft.py,查看测试结果. 打印信息中,
x代表输入数据的值,vhd表示pfft模块输出的计算结果,myfft为python实现的基-2 DIT-FFT函数的输出结果,fft为numpy.fft.fft函数输出的计算结果,diff为PFFT模块输出结果与python函数myfft计算结果的偏差.
版权声明:本文为falwat原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。