前言
傅里叶变换能将信号的时域变换到频域。在频域中,系统响应等于信号与系统传函的频域相乘(时域上是卷积)。相比于直接在时域做卷积,先进行傅里叶变换,再在频域相乘,最后通过逆傅里叶变换反变换回来的步骤看似更长,但在工程技术上却相对容易实现。
传统的傅里叶变换属于工程数学范畴,主要针对连续时间信号。离散傅里叶变换(DFT)针对离散时间信号。由于 DFT 算法时间复杂度太高,快速傅里叶变换(FFT)将其从 O(n^2) 降到了 O(nlogn)。
本文主要以 FPGA 中实现快速傅里叶变换为主,重点介绍配置、实例化及数据处理流程。
一、原理与目的
1. 傅里叶变换
傅里叶变换是将任意信号通过多种不同频率的正弦信号叠加而成。通过频率与幅值的一一对应,得到任意信号的幅频特性曲线。
2. 快速傅里叶变换
在傅里叶变换的基础上加入了对离散时间信号的应用,即离散傅里叶变换;对离散傅里叶变换的算法进行优化,得到了快速傅里叶变换(FFT)。
FFT 的核心是蝶形运算和旋转因子。这里以基 2 的 8 点 FFT 为例。注意事项包括时域抽取和频域抽取的关系是在单向运算中的两种不同的运算方法。重点关注二进制逆序排列的操作。
3. 目的
学会配置 FFT,并知道如何获取频谱数据,利用频谱数据进行后续操作。
二、配置 FFT
在 IP Catalog 中搜索 FFT,双击选项进行命名。
1. Transform
- Length(长度):数字信号处理里的 N 点 FFT。N 越大,频率分辨率越高。资源占用也越大。本例选用 1024 点 FFT。
- Direction(方向):正向 FFT、反向 FFT 或双向变换。本例选择双向变换。
2. I/O
- Data Flow(数据流):Streaming(流水线)、Burst(爆发)等。本例选择 Streaming,输入一个周期数据后下一个周期即可输出,速度快但资源占用较高。
- Input/Output Order:选择 Nature(自然数)。
3. Data and Twiddle
- Representation(表示):Fixed Point(固定点)、Single Floating Point(单浮点)、Block Floating Point(块浮点)。本例采用 Block Floating Point,兼顾精度与资源。
- Data Input Width / Twiddle Width:位宽越宽,精度越高。
三、实例化
生成 HDL 工作后确认模块引脚。
1. 芯片接入
- clk/reset_n:时钟与复位信号。
- inverse:0 代表正变换,1 代表逆变换。
- sink_valid/sink_ready:握手信号。
- sink_error:高低位分别代表实部和虚部是否正确。高电平代表功能生效(数据错误),不进行运算。
- sink_sop/sink_eop:起始和结束标识,高电平有效。间隔为设置的 N 点 FFT 的 N 倍时钟。
- sink_real/sink_imag:输入信号的实部和虚部。正变换通常只有实部,虚部置 0。
- source_exp:配合 source_real/source_imag 使用的公共指数值。
2. 数据准备
最重要的是起始符和结束符、输入信号要换成补码格式。起始符上升沿代表数据开始输入,结束符在起始符的前一个时钟信号上升沿开始。
3. 数据处理
获取输出数据的实部、虚部、指数后,首先进行补码转原码,再进行能量谱转换。注意幅频特性线的对称性,只取前 N/2 部分。

