4、FFT的硬件架构基础:流水线架构与SDF架构对比、复数乘法器与旋转因子生成
各位同学,咱们今天聊点硬核的。FFT在FPGA上怎么落地?说白了,就是两个核心问题:用什么架构,以及怎么算复数乘法。我在项目里见过太多人一上来就写代码,结果资源爆了或者时序跑不通。嗯,咱们先把地基打牢。
4.1 流水线架构 vs 单路径延迟反馈架构
先说说两种主流架构。我个人习惯把流水线架构叫做“空间换时间”的典型代表。你想想看,每一级都配一个独立的蝶形运算单元,数据像流水一样往下推。好处是什么?吞吐量高啊!每拍都能出一个结果。
但代价也很明显——资源消耗大。我记得有一次做16K点的FFT,用全流水线架构,光乘法器就用了小一百个,片子差点没布下。
流水线架构特点:
- 每一级都有独立的蝶形单元
- 数据流单向,无反馈路径
- 吞吐率 = 时钟频率(每拍一个结果)
- 资源消耗:O(N·log₂N) 级别
那单路径延迟反馈架构呢?说白了就是“时间换空间”。它只用一个蝶形单元,通过反馈路径反复使用。数据进来后,先存到延迟线里,等凑够了再算。
我的经验:如果资源紧张,比如在低成本FPGA上做中低速率FFT,SDF架构是首选。我曾经在一个项目里用SDF架构,把乘法器用量从48个降到了8个,片子瞬间就布通了。
来,咱们直接看个对比表:
| 对比项 | 流水线架构 | SDF架构 |
|---|---|---|
| 蝶形单元数量 | log₂N 个 | 1 个 |
| 存储需求 | N/2 个复数 | N-1 个复数 |
| 吞吐率 | 1 结果/时钟 | 1 结果/时钟(有初始延迟) |
| 控制逻辑 | 简单 | 中等 |
| 适用场景 | 高速、连续流 | 资源受限、中低速 |
为什么会这样?你想想看,流水线架构每级都在算,而SDF架构是串行复用。我建议初学者先从SDF架构入手,把蝶形运算的逻辑吃透了,再去看流水线架构会轻松很多。
避坑指南:我曾经在SDF架构里犯过一个低级错误——延迟线的深度没算对。N点FFT,第一级的延迟线长度是N/2,第二级是N/4,以此类推。少一个周期都不行,数据会乱套。
4.2 复数乘法器设计
好,架构选完了,接下来就是核心运算单元——复数乘法器。FFT里最耗资源的就是它了。
一个标准的复数乘法:
(a + jb) × (c + jd) = (ac - bd) + j(ad + bc)
你看,需要4个实数乘法器和2个加法器。但咱们做FPGA的,能省则省。有个经典优化方法:
// 优化后的复数乘法器(3乘法器方案)
temp1 = c × (a + b)
temp2 = a × (d - c)
temp3 = b × (c + d)
real = temp1 - temp3
imag = temp1 + temp2
嗯,这里要注意:虽然乘法器从4个减到了3个,但加法器从2个增加到了5个。在FPGA里,乘法器资源通常比加法器金贵得多。我个人习惯在乘法器紧张的芯片上用这个方案,比如7系列以下的Xilinx片子。
关键点:复数乘法器的位宽选择直接影响精度和资源。我建议输入数据位宽和旋转因子位宽保持一致,这样乘法器输出位宽自动翻倍,再截断到合适位宽。
4.3 旋转因子生成
旋转因子,就是那个W_N^k = e^(-j2πk/N)。说白了就是一组正弦余弦值。怎么生成?两种路子:
- 实时计算:用CORDIC算法现场算。好处是不占存储,坏处是延迟大、精度一般。
- 查表法:提前算好存到ROM里。这是工程中最常用的方法。
我建议用查表法。为什么呢?因为FFT的旋转因子有对称性,你只需要存1/4周期就够了。
// 旋转因子ROM生成示例(Verilog风格)
// 只存储0~π/2范围内的cos值
reg [DATA_WIDTH-1:0] cos_rom [0:ROM_DEPTH-1];
// 地址映射:利用对称性
// 实际角度 = (addr / ROM_DEPTH) * π/2
// 其他象限通过符号变换得到
我的经验:旋转因子的量化精度很关键。我曾经用16位量化,结果FFT出来的信噪比差了3个dB。后来改成18位,效果立竿见影。记住:旋转因子的位宽最好比数据位宽多2位,这样截断误差小。
还有个细节——旋转因子的存储顺序。流水线架构里,每一级需要的旋转因子都不一样。我习惯用计数器生成地址,然后查表得到对应的正余弦值。这样控制逻辑简单,时序也好收敛。
注意:查表法的ROM初始化一定要用同步复位。我曾经吃过异步复位的亏,上电后ROM内容没稳定,FFT算出来的全是乱码。嗯,从那以后我再也不敢偷懒了。
4.4 架构选择实战建议
最后,给各位一个实用建议。做FFT硬件架构时,先问自己三个问题:
- 数据率多高? 如果时钟能覆盖,SDF架构更省资源。
- 资源预算多少? 乘法器少于20个?老老实实用SDF。
- 延迟要求严吗? 流水线架构的初始延迟更小。
我记得有个项目,客户要求256点FFT,数据率只有10MHz。我用SDF架构,只用了4个乘法器,片子成本降了30%。客户很满意,我也省心。
好了,这一章的内容就到这。下一章咱们聊聊FFT的定点实现和溢出处理,那可是个坑多的地方。