环境:vivado2017.4,快速傅里叶变换V9.0 IP核
一,介绍:Xilinx FFT IP核是一种计算DFT的有效方式。
特点:前向变换(FFT)和反向变换(IFFT)在复数空间,并且可以在运行的同时进行选择配置
·变换点数范围:N=2^m,m=3~16
·数据精度范围:bx=8~34
·相位精度范围:bw=8~34
·算术处理方式:不放缩(全精度)定点;放缩定点;块浮点
·输入数据定点数类型和浮点数类型
·舍入或者截尾
·数据和相位存储:块RAM和分布式RAM
·运行时可配置变换点数
·放缩定点时放缩方案在运行时可实时配置
·输出数据顺序:自然顺序和比特或字节反转顺序
·数字通信系统应用中插入CP选项
·四种传输方式:流水线 基四突发型 基二突发型 简化基二突发型
·输入输出都由AXI4-Stream协议控制
·丰富的状态接口(eventsignals)
·可选择实时和非实时模式
·优化选项:复数乘法器模式;蝶形运算结构
·多通道同时进行变换运算:通道数范围1~12
二,DDS的配置
三,FFT ip核配置
四,FFT IP核端口介绍:
1,时钟通道(aclk aresetn aclken)
aclk:时钟信号
aclken(可选):时钟使能信号,高电平有效
aresetn(可选):复位信号,同步清除,优先级大于时钟使能信号,低电平有效,需持续两个时钟周期。
2,配置通道(s_axis_config_...)
AXI4-Stream协议中的握手信号s_axis_config_tready和s_axis_config_tvalid,配置信息s_axis_config_tdata信号
NFFT:传输点数,只有勾选了 Run Time Configurable Transform Length选项才可以在运行中配置变换点数,变换点数小于最大点数(在例化IP时选择),占5比特,并且填充0到8比特。
CP_LEN:插入CP的长度,只有在选择输出数据自然排序时勾选Cyclic Prefix Insertion选项时有效。占log2(最大点数)比特,并且填充0到8比特。 注意,在变换点数可配置时,占log2(最大点数)比特中的高位log2(当前点数),低位填0.
FWD/INV:占1比特,1表示FFT,0表示IFFT。多通道时,低位到高位依次表示通道 0通道1……,无填充
SCALE_SCH:放缩倍数,只有在选择放缩定点时有效,占比特数:基四和流水线结构下为2×ceil(NFFT/2) 基二和简化基二结构下为2×NFFT 每两个比特表示突发型一级或流水线型两级(排序从最后到最先)的放缩倍数(00 01 10 11),注意当基四结构下点数不是4的整数倍时,最后一级只占一比特,即00 01。多通道时,低位到高位依次表示通道0通道1……,无填充,最后将整个配置通道数据填充到8比特整数倍。
3,输入数据通道(s_axis_data…)
AXI4-Stream协议中的握手信号s_axis_data_tready和s_axis_data_tvalid
S_axis_tlast:输入帧的最后一个数据时置高,表明帧结束
S_axis_tdata:输入数据,单个通道,低位实数并且填充到8比特,高位虚数并且填充到8比特;多通道时,从低到高位按照单通道数据格式依次排列通道0通道1...
输入数据方式:
输入数据长度定义:
4,输出数据通道(m_axis_data_.....)
(1)AXI4-Stream协议中的握手信号m_axis_data_tready和m_axis_data_tvalid
(2)m_axis_data_tlas:输出帧的最后一个数时置高,表明帧结束。
(3)m_axis_data_tdata:输出数据,同输入数据格式下相同。注意,在未放缩全精度(unscaled)算数模式下,输出数据位数不等于输入位数,bxk=bxn+log2(最大变换点数)+1。
(4)m_axis_data_tuser:从低到高。
(5)XK_INDEX: 只有勾选了XK_INDEX才有效,占位log2(最大变换点数)比特,用来指示帧中的某个数据。
(6)BLK_EXP:只有在选择block floating-point(块浮点)算术模式时才有效,用以指示运行时对数据的实际放缩倍数。一般占一个子节(这个地方文档上写的是bxk,明显不对)。多通道时,从低到高依次为通道1 通道2……
(7)OVFLO:只有选择放缩定点数或者单精度浮点数时有效。用来指示数据在释放时是否存在溢出。每通道占1比特位。多通道时,从低到高依次为通道1 通道2……不需要填充。只有在勾选了OVFLO时才有效.
最后将整个配置通道数据填充到8比特整数倍。
输出数据方式:
输出数据长度定义:
5,状态通道(m_axis_status_......)用来指示整个帧的状态信息;AXI4-Stream协议中的握手信号m_axis_status_tready和m_axis_status_tvalid。
m_axis_status_tdata:
BLK_EXP:只有在选择block floating-point(块浮点)算术模式时才有效,用以指示运行时对帧数据的放缩倍数。占5比特位,填充0到一个子节。多通道时,从低到高依次为通道1 通道2……
OVFLO:只有勾选了OVFLO并且选择放缩定点数或者单精度浮点数时有效。用来指示帧在释放时是否存在溢出。每通道占1比特位。多通道时,从低到高依次为通道1 通道2……不需要填充。
最后将整个配置通道数据填充到8比特整数倍。
6,事件信号(event signals)
event_ftrame_started:IP核开始处理新帧。
event_tlast_missing:当输入数据满一个帧时,s_axis_data_tlast却还是低电平时置高。这表明上流数据源和IP核的帧大小配置没有对齐,上流数据源的帧大小大于IP核。
event_tlast_unexpected:当输入数据没满一帧时,s_axis_data_tlast却是高电平时置高。这表明上流数据源和IP核的帧大小配置没有对齐,上流数据源的帧大小小于IP核。
event_fft_overflow:当选择放缩定点数模式或者单精度输入数据格式时,输出数据中存在溢出时,置高电平。
event_data_in_channel_halt: IP核需要数据但是输入通道不能提供数据时置高。在实时模式(Realtime)下,IP核继续处理(将前一个数据重复使用),这就产生了错误。在非实时模式下(Non-Realtime)模式下,IP核停止处理直到有新的数据输入。这样的话,帧并没有被破坏。
event_data_out_channel_halt:当IP核需要输出数据时但是输出通道的寄存器已满。这时,IP核停止处理,所有活动停止直到输出通道寄存器腾空。帧并没有被破坏。注意,此信号只在非实时模式下有效。
event_status_channel_halt:当IP核需要在Status通道写入数据时但通道寄存器已满。这时,IP核停止处理,所有活动停止直到输出通道寄存器腾空。帧并没有被破坏。注意,此信号只在非实时模式下有效。
五,verilog代码
`timescale 1ns / 1ps
module fft(
input aclk,
input aresetn,
output [7:0] fft_real,
output [7:0] fft_imag,
output [17:0]data,
output [15:0]dds_m_data_tdata,
output [11:0]xk_index
);
wire [15:0] dds_m_data_tdata;
wire dds_m_data_tvalid;
wire dds_m_data_tlast;//未使用
dds_compiler_0 dds_MHz (
.aclk(aclk),
.aresetn(aresetn),
.m_axis_data_tdata(dds_m_data_tdata),
// .m_axis_data_tready(fft_s_data_tready),
.m_axis_data_tvalid(dds_m_data_tvalid)
);
//----------------------FFT core-------------------
wire [7:0] fft_s_config_tdata;//[0:0]FWD_INV_0
wire fft_s_config_tready;
wire fft_s_config_tvalid;
wire [7:0] fft_m_status_tdata;
wire fft_m_status_tvalid;
wire [15:0] fft_m_data_tdata;
wire fft_m_data_tlast;
wire [23:0] fft_m_data_tuser;//[11:0]XK_INDEX
wire fft_m_data_tvalid;
wire fft_event_frame_started;
wire fft_event_tlast_unexpected;
wire fft_event_tlast_missing;
wire fft_event_data_in_channel_halt;
wire [11:0] xk_index;
assign xk_index = fft_m_data_tuser[11:0];
assign fft_s_config_tdata = 8'd1;//定义FFT模块配置信息(第0位为1表示用FFT,为0表示用IFFT)
assign fft_s_config_tvalid = 1'd1;//FFT模块配置使能,从一开始就拉高,表示已经准备好要传入的配置数据了
xfft_0 usr_fft(
.aclk(aclk),//Rising-edge clock
.aresetn(aresetn),//(低有效)Active-Low synchronous clear (optional, always take priority over aclken); A minimum aresetn active pulse of two cycles is required
//S_AXIS_DATA
.s_axis_data_tdata(dds_m_data_tdata),//IN Carries the unprocessed sample data: XN_RE and XN_IM
.s_axis_data_tlast(dds_m_data_tlast),//IN Asserted by the external master on the last sample of the frame
// .s_axis_data_tready(fft_s_data_tready),//OUT Used by the core to signal that it is ready to accept data
.s_axis_data_tvalid(dds_m_data_tvalid),//IN Used by the external master to signal that it is able to provide data
//S_AXIS_CONFIG
.s_axis_config_tdata(fft_s_config_tdata),//IN Carries the configuration information
.s_axis_config_tready(fft_s_config_tready),//OUT Asserted by the core to signal that it is ready to accept data
.s_axis_config_tvalid(fft_s_config_tvalid),//IN Asserted by the external master to signal that it is able to provide data
//M_AXIS_STATUS
.m_axis_status_tdata(fft_m_status_tdata),
.m_axis_status_tvalid(fft_m_status_tvalid),
//M_AXIS_DATA
.m_axis_data_tdata(fft_m_data_tdata),//OUT Carries the processed sample data XK_RE and XK_IM
.m_axis_data_tlast(fft_m_data_tlast),//OUT Asserted by the core on the last sample of the frame
.m_axis_data_tuser(fft_m_data_tuser),//OUT Carries additional per-sample information: XK_INDEX, OVFLO and BLK_EXP
.m_axis_data_tvalid(fft_m_data_tvalid),//OUT Asserted by the core to signal that it is able to provide status data
//EVENTS
.event_frame_started(fft_event_frame_started),//Asserted when the core starts to process a new frame
.event_tlast_unexpected(fft_event_tlast_unexpected),//Asserted when the core sees s_axis_data_tlast High on a data sample that is not the last one in a frame
.event_tlast_missing(fft_event_tlast_missing),//Asserted when s_axis_data_tlast is Low on the last data sample of a frame
.event_data_in_channel_halt(fft_event_data_in_channel_halt)//Asserted when the core requests data from the Data Input channel and none is available
);
//----------------将FFT/IFFT处理完的信号传出(虚部/实部分别传出)-------
assign fft_real = fft_m_data_tdata[7:0];
assign fft_imag = fft_m_data_tdata[15:8];
assign data=fft_real*fft_real+fft_imag*fft_imag;
endmodule
testbench测试代码:
`timescale 1ns / 1ps
module fft_testbench( );
reg aclk,aresetn;
wire [7:0] fft_real,fft_imag;
wire [15:0]dds_m_data_tdata;
wire [11:0]xk_index;
wire [17:0]data;
fft fft_test(
.aclk(aclk),
.aresetn(aresetn),
.fft_real(fft_real),
.fft_imag(fft_imag),
.dds_m_data_tdata(dds_m_data_tdata),
.xk_index(xk_index),
.data(data)
);
initial begin
aclk = 0;
aresetn = 0;//低有效
#10 aresetn = 1;
end
always #5 aclk=~aclk;//时钟频率100MHz
六,仿真效果