*在同时做fft核ifft的时候,尽量选择同一个ip核进行多次例化使用,通过assign s_axis_config_tdata=1/0设置fft或ifft模式
首先为FFT/IFFT核的设置,第一个页面Number of Channels表示输入通道个数,Transform Length位做FFT/IFFT的点数,Target clock为时钟,architecture choice为fft的模式,采用那种可自由选择,radix-4,2皆可。
data format选择fixed point,scaling options如果不做截位的话使用unscaled即可,但是会导致输出的位数越来越大,如果选择block floating point的话输入多少位输出就是多少位,选择scale也可达到同样的目的,但是需要自己设置scale衰减多少,如果选择2048点的fft的话,scale因子为【101010101010】便不会溢出,勾选aresetn作为信号使能,XK_INDEX为输出fft的点数,一般来说XK_INDEX*fsample/FFTpoint便是当前点所代表的频率值。output ordering选择natural order。
第三页的数值可自由选择,不会影响最终输出值。设置完毕后,在implement details界面观察输出端口对应位数
s_axis_config_tdata:控制输入模式,进行fft/ifft以及衰减因子的设置,第0位为1fft,为0做ifft,高位用于scale因子的设置。
s_axis_config_tvalid:拉高若干个时钟周期后归零,之后将s_axis_data_tvalid拉高
s_axis_config_tready:s_axis_config_tvalid拉高两个时钟周期后,该口给1输出;
s_axis_data_tready:s_axis_config_tvalid拉高两个时钟周期后,该口给1输出,ip核初始化完成,可进行数据输入必须进行赋值;
s_axis_data_tvalid:拉高2048个周期,输入2048个数据进行fft;
s_axis_data_tdata:输入32位数据,取低12位数据进行运算;
s_axis_data_tlast:输入2048个数据后拉高,停止数据输入;
做fft需要耗费的时钟周期计算如下s_axis_data_tlast- s_axis_data_tvalid
,在ip核中可看到:
m_axis_data_tdata:高位为实部,低位为虚部,由于本程序在always内将值给fft_real端口,所以会延迟一个时钟周期,实际为41,fft_real为42;
m_axis_data_tvalid:当fft结果输出时拉高,输出2048个点的数据后拉低;
m_axis_data_tuser:输出fft的地址值,输出值*fs/N为对应频点;
m_axis_data_tready:完成2048个点的fft后拉高一个时钟周期表示完成fft;
event_frame_started:输入信号数据时拉高一个时钟周期;
下面采用两中方式对ip核使用进行说明,
第一种采用scale因子的设置方式
尽量不采用文件读入数据进行fft和ifft的方式进行操作,因为fft核只能进行补码的运算,并且会扩大位数,matlab中fft/ifft算法与FPGA中不同,无法一一对应,会出错,所以采用fpga内部生成dds信号的方式进行程序的运行。
本部分采用一个dds生成正余弦信号。cos(2*pi*f*t)-i*sin(2*pi*f*t)
fft输出结果
图1位fft后图像,可以看到在相应的频点有尖峰,图2位截位后的ifft波形,可以看到位5MHz,能够比较好的完成正逆fft运算。
方法2:使用block floating point
该种方法精度不如上述的高,相同精度需要更多的位数输入。可以看到ip核设置完成后直接输出与输入位数相同,本初采用16位的dds输出。
https://download.csdn.net/download/daidai711/11200741
使用该设置的输入位数要尽可能取高一些,否则ifft后图像畸变会很严重。