说明:通过对比Matlab实践来运用Xilinx FFT IP核实现复数的FFT。 代码下载:Xilinx FFT IP核 Verilog代码实现 工程下载:FFT工程
一、Fast Fourier Transform IP核介绍
![在这里插入图片描述](https://img-blog.csdnimg.cn/dbdb11bd59b14c1097da49b851ef998e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_14,color_FFFFFF,t_70,g_se,x_16#pic_center) IP核主要端口介绍:
名称 | 方向 | 说明 |
---|
aclk | 输入 | 模块工作时钟,上升沿有效 | aclken | 输入 | 时钟使能信号,高电平有效,低电平时内核暂停工作,可通过此信号降低内核运行的最大时钟频率 | aresetn | 输入 | 低电平同步复位信号,优先级高于aclken,低电平至少持续两个时钟周期 | 配置: | | | s_axis_config_tvalid | 输入 | 配置通道的 tvalid,由外部主机断言以表示它能够提供数据 | s_axis_config_tready | 输出 | 配置通道的 tready,由内核断言以表示它已准备好接收数据 | s_axis_config_tdata | 输入 | 配置通道的tdata,携带配置信息,NFFT、FWD/INV、CP_LEN和SCALE_SCH | 输入数据: | | | s_axis_data_tvalid | 输入 | 输入数据通道tvalid,由外部主机断言以表示它能够提供数据 | s_axis_data_tready | 输出 | 输入数据通道tready,由内核断言以表示它能够接收数据 | s_axis_data_tdata | 输入 | 输入数据通道tdara,由外部主机提供待处理的数据 | s_axis_data_tlast | 输入 | 输入数据通道tdara,由外部主机断言表示最后一组数据。 只在生成事件event_tlast_unexpected 和 event_tlast_missing时,内核才使用它 | 输出数据: | | | m_axis_data_tvalid | 输出 | 输出数据通道tvalid,由内核断言表示它能够提供数据 | m_axis_data_tready | 输入 | 输出数据通道tready,由外部丛机断言表示它能够接收数据 | m_axis_data_tdata | 输出 | 输出数据通道tdata,由内核提供FFT后的数据 | m_axis_data_tuser | 输出 | 输出数据通道tuser,由内核提供XK_INDEX,OVFLO,BLK_EXP信息 | m_axis_data_tlast | 输出 | 数据数据通道tlast,由内核断言表示最后一个输出数据 | … | | |
s_axis_data_tdata 输入数据格式: 根据你的配置比如1024个点,每个点为32bit,高16bit为虚部,低16bit为实部。
![在这里插入图片描述](https://img-blog.csdnimg.cn/5935a6adb3974e75be6f2dcf8e62218a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_11,color_FFFFFF,t_70,g_se,x_16) s_axis_config_tdata 配置数据格式: : ![在这里插入图片描述](https://img-blog.csdnimg.cn/af831b84177e4e89868362376329f852.png) m_axis_data_tdata 输出数据格式: :
根据你的配置比如1024个点,每个点为32bit,高16bit为虚部,低16bit为实部。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/4d8e5e1db1544d75a456315c82b57550.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_11,color_FFFFFF,t_70,g_se,x_16)
IP核配置 ![在这里插入图片描述](https://img-blog.csdnimg.cn/bd505802fc2349e7a35c91725ae5bf2a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16) ①:通道数,1~12。 ②:变换点数,8~65536。 ③:工作时钟频率,1~1000。 ④:数据比特率。 ⑤:根据时钟频率与比特率自动选择。 ⑥:流水线IO,允许连续数据处理,仅当使用单通道时,流水线IO可选。 ⑦:碟4,突发IO,使用迭代方法分别加载和处理数据。它的资源消耗比流水线架构小,但转换时间更长 一点不同:蝶4架构的变换点数为64 ~ 65536,其它架构点数为 8 ~ 65536。 ⑧:碟2,突发IO,使用与 Radix-4 相同的迭代方法,但蝶形运算单元更小。 它的资源消耗比 Radix-4 架构的尺寸更小,但转换时间更长。 ⑨:碟2 -Lite,突发IO,基于 Radix-2 架构,此变体使用分时复用方法实现蝶形运算单元, 以实现更少的资源消耗,但代价是转换时间更长。 ⑩:运行期间可配置变换点数。
四种FFT架构的资源消耗与吞吐量的关系: ![在这里插入图片描述](https://img-blog.csdnimg.cn/5141747d64b445eab30c77e2d091dd80.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_16,color_FFFFFF,t_70,g_se,x_16#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/69093bf0cbe548d3aba7f75ce0da8644.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16) ①:数据格式,定点、浮点。 ②:缩放选项,。 ③:数据省入模式。 ④:输入数据宽度。 ⑤:相位因子宽度。 ⑥:输出位序。 ⑦:输出序号。 ⑧:数据溢出标志。
![在这里插入图片描述](https://img-blog.csdnimg.cn/f5a6547064d44f2fadfe0937059b004e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16) ①:数据。 ②:相位因子。 ③:重排序缓冲。 ④:复数乘法器。 ⑤:蝶形运算单元。
二、FFT IP核的使用
1、1KHz采样率、1024点FFT
Matlab产生原实信号 s,将1024点的数据写入FPGA的ROM 采样率为1000Hz,信号为100Hz、200Hz、300Hz叠加,FFT点数为1024。
clc
clear all;
row=3;
column=1;
N=1024;
fs=1000; %采样间隔为1/1000
t=(1:1024)/fs; %时间轴
f0=100; %载频频率
f1=200; %载频频率
f2=300; %载频频率
y1=100*exp(1i*2*pi*f0*t);
y2=100*exp(1i*2*pi*f1*t);
y3=100*exp(1i*2*pi*f2*t);
y=y1+y2+y3; %信号产生
real_y = int32(real(y)); %实部
imag_y = int32(imag(y)); %虚部
a=[real_y;imag_y];
s = int32(bitshift(imag_y,16)+real_y);%将实部和虚部拼接为32bit(实部16bit+虚部16bit)
s = s'; %此数据输出到FPGA
%绘制原信号
subplot(row,column,1);
plot(t,y);
title("时域");
xlabel('t');
ylabel('y');
grid on;
%FFT
f=(0:N-1)*(fs/N);
fft_y=fft(y,N); %FFT
abs_fft_y=abs(fft(y,N)); %FFT取绝对值
subplot(row,column,2); %FFT波形
plot(f,fft_y);
title("FFT");
xlabel('t');
ylabel('y');
grid on;
subplot(row,column,3); %FFT取绝对值波形
plot(f,abs_fft_y);
title("FFT取绝对值");
xlabel('t');
ylabel('y');
grid on;
![在这里插入图片描述](https://img-blog.csdnimg.cn/568fc877cbd14ec5a3b1aa736dc4de64.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16)
数据通过coe文件写入ROM: ![在这里插入图片描述](https://img-blog.csdnimg.cn/e375152c7df848188f999158b0e8a211.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16)
FPGA端IP核的配置: ![在这里插入图片描述](https://img-blog.csdnimg.cn/94c8843f17ea42349e43f1b9621a6f66.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16) ![在这里插入图片描述](https://img-blog.csdnimg.cn/b245e3baa8dc4dae82cea09f581ee9d3.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16) ![在这里插入图片描述](https://img-blog.csdnimg.cn/d6990792e4e14614b30b0157d73f1919.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16) 将时域数据写入ROM,通过FFT IP核后得到以下结果:
结果展现: FPGA FFT波形 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2fef0d21098f47919d4f3ab06de9f058.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16)
采样率为1000Hz,1024个点。
观察下图中f变量(可以表示频率的横轴),三个峰值对应的频率为100Hz,200Hz,300Hz。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f06534dcbbba4d32a68daf3c03b94412.gif) Verilog代码: Xilinx FFT IP核 Verilog代码实现
2、2.5GHz采样率、8192点FFT
Matlab产生原实信号 s,将8192点的数据写入FPGA的ROM
采样率为2.5GHz,信号为100Hz、350Hz、500Hz叠加,FFT点数为1024。
clc
clear all;
close all;
row=3;
column=1;
N=8192;
fs=2.5e9; %采样间隔为1/1000
t=(1:N)/fs; %时间轴
f0=100e6; %载频频率
f1=350e6; %载频频率
f2=500e6; %载频频率
y1=20*exp(1i*2*pi*f0*t);
y2=20*exp(1i*2*pi*f1*t);
y3=20*exp(1i*2*pi*f2*t);
y=y1+y2+y3; %信号产生
real_y = int32(real(y)); %实部
imag_y = int32(imag(y)); %虚部
a=[real_y;imag_y];
s = int32(bitshift(imag_y,16)+real_y);%将实部和虚部拼接为32bit(实部16bit+虚部16bit)
s = s'; %此数据输出到FPGA
%绘制原信号
subplot(row,column,1);
plot(t,y);
title("时域");
xlabel('t');
ylabel('y');
grid on;
%FFT
f=(0:N-1)*(fs/N);
fft_y=fft(y,N); %FFT
abs_fft_y=abs(fft(y,N)); %FFT取绝对值
subplot(row,column,2); %FFT波形
plot(f,fft_y);
title("FFT");
xlabel('t');
ylabel('y');
grid on;
subplot(row,column,3); %FFT取绝对值波形
plot(f,abs_fft_y);
title("FFT取绝对值");
xlabel('t');
ylabel('y');
grid on;
![在这里插入图片描述](https://img-blog.csdnimg.cn/525db477e77a45f5b57c1318c14db82d.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16) 将时域数据写入ROM,通过FFT IP核后得到以下结果:
结果展示: ![在这里插入图片描述](https://img-blog.csdnimg.cn/3901917ec91942e781cefc087a62a6c4.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQ3Jhenp5X00=,size_20,color_FFFFFF,t_70,g_se,x_16)
观察图中f变量(可以表示频率的横轴),三个峰值对应的频率为100Hz,350Hz,500Hz。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5ab83e9ba749498c8e06568f63368c0c.gif) Verilog代码: Xilinx FFT IP核 Verilog代码实现
|