Xilinx FFT IP v9.1的使用学习
概述
该ip可以实现N= 2 m 2^m 2m点的DFT或者IDFT,(m=3~16).
- 输入数据精度 bx= 8 – 34
- 相位因子精度 bw= 8 – 34
- 输入的数据类型:
- 未缩放(全精度)的定点数
- 缩放的定点数
- 块浮点数
- 可以在运行时配置变换点数
- 有四种运算架构可供选择
- Pipelined Streaming I/O
- Radix-4 Burst I/O
- Radix-2 Burst I/O
- Radix-2 Lite Burst I/O
主要端口描述
name | 描述 | 备注 |
---|---|---|
s_axis_data | AXI总线 | 输入 |
s_axis_config_tdata | 配置接口 | 配置正反变换,变换长度,缩放倍数等信息 |
aclk | 时钟 | |
s_axis_config_tdata | AXI总线 | 输出 |
相关标志信号
name | 描述 | 备注 |
---|---|---|
event_frame_started | 新帧 | 当P核开始处理一个新帧 |
event_tlast_unexpected | 断帧 | 数据未满一帧而 s_axis_data_tlast却置高 |
event_tlast_missing | 错帧 | 数据满一帧而 s_axis_data_tlast却保持低电平 |
event_fft_overflow | 溢出 | 计算结果溢出,在使用缩放定点和单精度浮点时才会出现,仅当溢出是有效选项时才出现。 |
event_data_in_channel_halt | IP核需要数据而输入端口不能够提供数据 | |
event_data_out_channel_halt | IP核要输出数据但是输出缓冲区已满,只出现在非实时模式。 | |
event_status_channel_halt | IP核写状态寄存器但无法写入,只出现在非实时模式。 |
详细信息请查看官方数据手册。
配置通道
Field Name | Width | Padded | Description |
---|---|---|---|
NFFT | 5 | Yes | 传输点的长度,就是FFT变换的实际长度,其值:N= 2 n 2^n 2n |
CP_LEN | log 2(maximum pointsize) | Yes | 循环前缀长度,其值介于0到N之间,仅存在循环前缀插入勾选的时候 |
FWD_INV | 1 bit per FFT datachannel | No | 1为正变换,0为逆变换,一个数据通道一个bit |
SCALE_SCH | 2 x ceil ( N F F T 2 ) \left(\frac{NFFT}{2})\right. (2NFFT) | No | 简单点说,就是设置缩放倍数,比如 SCALE_SCH = [01 10 00 11 10]就表示右移了(1+2+0+3+2)位,也就是缩小了256倍,那么计算的结果就要扩大256倍 |
那么在使用时,位宽的多少,是否填充,填充多少,这些都需要我们自己去计算吗?当然不用,Vivado IDE可以自动计算。就以NFFT为例,当我们勾选run time configurable时,我们可以看到s_axis_config_tdata 的位宽发生了变化,而且,具体的某一位代表什么也可以从中看出。
具体使用
Configuration Tab
Channels:选择一个通道
Transform Length:选择1024,注意这个是最大长度,只果勾选了run time configurable,配置长度才可变。
Implementation Options:运算的架构,其资源与数据吞吐量如下图所示
Implementation Tab
Data Format:选择Fixed Point,选择其它选项会发现资源使用暴增。
Scaling Options :缩放选项,选择Scaled,同样有其它选项,但是资源使用量会暴增
因此,要合理权衡资源、运算速度、精度,选择合适的选项,如果资源太多用不完,当我没说。
Precision Options: 输入数据位宽和相位因子位宽。相位因子具体干什么用,我也不太清楚,看了下手册,好像和噪声有关,这里保持默认16bit即可,至于输入位宽,这里是指实部和虚部的位宽,实际上输入应是32bit。可以看到,高16位是虚部,低16位是实部。输出数据同理。
Control Signals: 选择复位信号,至少保持两个周期。
Output Ordering:输出时自然序列还是倒序。
其它保持默认选项,都不勾选,如果有需要使用的,可以查阅官方手册。因为这些配置已经可以进行正常的运算了。
Detailed Implementation Tab
这里主要选择资源的使用类型,比如是否使用BRAN,是否使用乘法器,用多少什么的,同样,权衡资源与速度,保持默认即可。
最后看一下Latency,这个与你计算的点数,实际时钟屏率,选择资源类型有关,所以这个Latency仅供参考。
仿真测试
在生成IP核以后,将其导出,然后进行仿真验证,在这里我选用ModelSim,个人建议不要选择Vivado自带的仿真,个人感觉有卡又慢又难用。然后还需要Matlab生成波形和验证结果。什么?没有Matlab,那你搞什么FFT,赶快去装一个。有了Matlab,我们可以更方便的进行仿真。
初始化部分代码
首先,需要初始化CONFIG_tdata,其一共有16个bit(为什么是16bit,去IP核配置界面自己看)这里,我们选用正变换,所以最低一个bit为1,然后10个bit是缩放因子,2个一组,选择缩放32倍,剩下的用0填充。所以结果因该是这样:
assign S_AXIS_CONFIG_tdata = 16'b0000_0_01_01_01_01_01_1;
M_AXIS_DATA_tready这个一直拉高即可,详情请看AXI协议。
assign M_AXIS_DATA_tready = 1'b1;
定义变换的最大点数:
parameter MAX_SIZE=16'd1024 - 1;
然后我们需要1024个数据,这1024个数据采用Matlab生成,然后ModelSim读取。
reg[15:0] memory[MAX_SIZE:0];//测试波形数据存储空间
initial $readmemh("./sin_bit.txt",memory);//读取原始波形数据读到memory中
我们还需要将FFT的输出数据导出,然后由Matlab分析查看结果。
integer handle1;
initial
begin//sequence block
handle1 = $fopen("fsave.txt");
#5000;
@(negedge M_AXIS_DATA_tvalid);//等待数据输出完毕
#5000;
$fclose(handle1);
$stop;
end
always @(posedge aclk)
begin
if(M_AXIS_DATA_tvalid)
$fwrite(handle1,"%d %d \n",M_AXIS_DATA_tdata[31:16],M_AXIS_DATA_tdata[15:0]);
end
剩下的就是控制传输数据。
always @(posedge aclk)
begin
if(all_en)
begin
cnt <= cnt + 1'b1;
if(cnt == 0)
begin
S_AXIS_CONFIG_tvalid <=1;
end
else if(cnt == 3)
S_AXIS_CONFIG_tvalid <= 0;
else if(cnt == 5)
begin
S_AXIS_DATA_tvalid <= 1;
index = 0;
end
else if(cnt == MAX_SIZE + 5)
begin
S_AXIS_DATA_tlast <= 1'b1;
end
else if(cnt == MAX_SIZE + 6)
begin
S_AXIS_DATA_tvalid <= 1'b0;
S_AXIS_DATA_tlast <= 1'b0;
end
if(S_AXIS_DATA_tlast)
index <= 'd0;
else if(S_AXIS_DATA_tvalid)
index <= index +1;
end
end
确认代码无误后,开始仿真,仿真主要看一下有没有错误发生,如果有,检查一下错误的原因,没有错误接下来就用Matlab处理数据。
先用Matlab生成测试的波形:
F1=1000000; F2=500000; F3=1500000; %信号的频率
Fs= F1*4;%采样频率
A1=135; A2=296; A3=502; %振幅
P1=50; P2=-60; P3=110; %信号初始相位
ADC = 400; %直流分量
N=1024;%采样点数为N
WIDTH = 12;%信号位宽
t=0:1/Fs:(N-1)/Fs;%采样时刻
s= ADC+A1*cos(2*pi*F1*t+pi*P1/180)+A2*cos(2*pi*F2*t+pi*P2/180)+A3*cos(2*pi*F3*t+pi*P3/180);%生成信号
plot(s);%绘制图形
title('原始波形');
figure
由于采样点数过高,这个图估计连它亲娘都不认识,所以还是看函数吧。
我们将生成的波形文件放到ModelSim中仿真,完成后,再将生成的波形文件和Matlab的FFT结果对比,这里需要注意的是,我们在IP核中,设置了放缩,所以在Matlab中需要将IP核的结果乘以32.
然后以下是Matlab和IP核的结果对比,将计算得到的数据分别转成了幅度-频率图和相位-频率图。可以发现,两者之间误差很小。
参考资料
官方手册
Xilinx FFT IP v9.0 使用
VIVADO FFT核的实现
基于MATLAB的FFT分析
matlab关于fft的应用(一)
[数字信号处理]Matlab做fft时点数N怎么选取