Xilinx FFT IP v9.1的使用学习

概述

该ip可以实现N= 2 m 2^m 2m点的DFT或者IDFT,(m=3~16).

  • 输入数据精度 bx= 8 – 34
  • 相位因子精度 bw= 8 – 34
  • 输入的数据类型:
    1. 未缩放(全精度)的定点数
    2. 缩放的定点数
    3. 块浮点数
  • 可以在运行时配置变换点数
  • 有四种运算架构可供选择
    1. Pipelined Streaming I/O
    2. Radix-4 Burst I/O
    3. Radix-2 Burst I/O
    4. Radix-2 Lite Burst I/O

主要端口描述

name描述备注
s_axis_dataAXI总线输入
s_axis_config_tdata配置接口配置正反变换,变换长度,缩放倍数等信息
aclk时钟
s_axis_config_tdataAXI总线输出

相关标志信号

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_haltIP核需要数据而输入端口不能够提供数据
event_data_out_channel_haltIP核要输出数据但是输出缓冲区已满,只出现在非实时模式。
event_status_channel_haltIP核写状态寄存器但无法写入,只出现在非实时模式。

详细信息请查看官方数据手册。

配置通道

填充格式

Field NameWidthPaddedDescription
NFFT5Yes传输点的长度,就是FFT变换的实际长度,其值:N= 2 n 2^n 2n
CP_LENlog 2(maximum pointsize)Yes循环前缀长度,其值介于0到N之间,仅存在循环前缀插入勾选的时候
FWD_INV1 bit per FFT datachannelNo1为正变换,0为逆变换,一个数据通道一个bit
SCALE_SCH2 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怎么选取

posted @ 2022-04-19 19:47  san_si  阅读(731)  评论(0编辑  收藏  举报