赞
踩
调用DDS IP核,进行如下设置,生成10MHz正弦信号:
代码如下,例化了一个DDS输出10MHz正交信号,例化2个FFT,分别用作FFT/IFFT
`timescale 1ns / 1ps // // Company: UESTC // Engineer: RJY // // Create Date: 2019/05/24 10:32:04 // Design Name: // Module Name: fft // Project Name: // Target Devices: // Tool Versions: // Description: // 用于实现DDS输出信号的FFT和IFFT // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module fft( input aclk, input aresetn, output [7:0] fft_real, output [7:0] fft_imag, output [7:0] ifft_real, output [7:0] ifft_imag ); //-----------------DDS core(44.96MHz)------------------ wire [15:0] dds_m_data_tdata; wire fft_s_data_tready; 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_tready; wire fft_m_status_tvalid; wire [15:0] fft_m_data_tdata; wire fft_m_data_tlast; wire ifft_s_data_tready; 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_status_channel_halt; wire fft_event_data_in_channel_halt; wire fft_event_data_out_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_tready(fft_m_status_tready), .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_tready(ifft_s_data_tready),//IN Asserted by the external slave to signal that it is ready to accept data. Only present in Non-Realtime mode .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_status_channel_halt(fft_event_status_channel_halt),//Asserted when the core tries to write data to the Status channel and it is unable to do so .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 .event_data_out_channel_halt(fft_event_data_out_channel_halt)//Asserted when the core tries to write data to the Data Output channel and it is unable to do so ); //-----------------------------IFFT core---------------------------- wire [7:0] ifft_s_config_tdata;//[0:0]FWD_INV_0 wire ifft_s_config_tready; wire ifft_s_config_tvalid; wire [7:0] ifft_m_status_tdata; wire ifft_m_status_tready; wire ifft_m_status_tvalid; wire [15:0] ifft_m_data_tdata; wire ifft_m_data_tlast; wire ifft_m_data_tready; wire [23:0] ifft_m_data_tuser;//[11:0]XK_INDEX wire ifft_m_data_tvalid; wire ifft_event_frame_started; wire ifft_event_tlast_unexpected; wire ifft_event_tlast_missing; wire ifft_event_status_channel_halt; wire ifft_event_data_in_channel_halt; wire ifft_event_data_out_channel_halt; wire [11:0] ixk_index; assign ixk_index = ifft_m_data_tuser[11:0]; assign ifft_s_config_tdata = 8'd0;//定义FFT模块配置信息(第0位为1表示用FFT) assign ifft_s_config_tvalid = 1'd1;//FFT模块配置使能,从一开始就拉高,表示已经准备好要传入的配置数据了 assign ifft_m_data_tready = 1'd1;//从一开始就拉高,表示已经准备好接收IFFT模块输出的数据 xfft_0 usr_ifft( .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(fft_m_data_tdata),//IN Carries the unprocessed sample data: XN_RE and XN_IM .s_axis_data_tlast(fft_m_data_tlast),//IN Asserted by the external master on the last sample of the frame .s_axis_data_tready(ifft_s_data_tready),//OUT Used by the core to signal that it is ready to accept data .s_axis_data_tvalid(fft_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(ifft_s_config_tdata),//IN Carries the configuration information .s_axis_config_tready(ifft_s_config_tready),//OUT Asserted by the core to signal that it is ready to accept data .s_axis_config_tvalid(ifft_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(ifft_m_status_tdata), .m_axis_status_tready(ifft_m_status_tready), .m_axis_status_tvalid(ifft_m_status_tvalid), //M_AXIS_DATA .m_axis_data_tdata(ifft_m_data_tdata),//OUT Carries the processed sample data XK_RE and XK_IM .m_axis_data_tlast(ifft_m_data_tlast),//OUT Asserted by the core on the last sample of the frame .m_axis_data_tready(ifft_m_data_tready),//IN Asserted by the external slave to signal that it is ready to accept data. Only present in Non-Realtime mode .m_axis_data_tuser(ifft_m_data_tuser),//OUT Carries additional per-sample information: XK_INDEX, OVFLO and BLK_EXP .m_axis_data_tvalid(ifft_m_data_tvalid),//OUT Asserted by the core to signal that it is able to provide status data //EVENTS .event_frame_started(ifft_event_frame_started),//Asserted when the core starts to process a new frame .event_tlast_unexpected(ifft_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(ifft_event_tlast_missing),//Asserted when s_axis_data_tlast is Low on the last data sample of a frame .event_status_channel_halt(ifft_event_status_channel_halt),//Asserted when the core tries to write data to the Status channel and it is unable to do so .event_data_in_channel_halt(ifft_event_data_in_channel_halt),//Asserted when the core requests data from the Data Input channel and none is available .event_data_out_channel_halt(ifft_event_data_out_channel_halt)//Asserted when the core tries to write data to the Data Output channel and it is unable to do so ); //----------------将FFT/IFFT处理完的信号传出(虚部/实部分别传出)------- assign fft_real = fft_m_data_tdata[7:0]; assign fft_imag = fft_m_data_tdata[15:8]; assign ifft_real = ifft_m_data_tdata[7:0]; assign ifft_imag = ifft_m_data_tdata[15:8]; endmodule
具体代码如下:
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2019/05/22 12:11:32 // Design Name: // Module Name: fft_tb // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module fft_tb( ); reg aclk,aresetn; wire [7:0] fft_real,fft_imag; wire [7:0] ifft_real,ifft_imag; fft fft_test( .aclk(aclk), .aresetn(aresetn), .fft_real(fft_real), .fft_imag(fft_imag), .ifft_real(ifft_real), .ifft_imag(ifft_imag) ); initial begin aclk = 0; aresetn = 0;//低有效 #10 aresetn = 1; end always #5 aclk=~aclk;//时钟频率100MHz //-----------将FFT变换结果写入文件-------------(下面的可以删除) integer w_file; initial w_file = $fopen("C:/Users/luobl/Desktop/fft_test/fft_real.txt"); always @(posedge aclk) begin $fdisplay(w_file,"%b",fft_real);//写数据 end integer w_file2; initial w_file2 = $fopen("C:/Users/luobl/Desktop/fft_test/fft_imag.txt"); always @(posedge aclk) begin $fdisplay(w_file2,"%b",fft_imag); end endmodule
生成图形如下:
下图可以看到FFT输出的模拟波形尖峰处对应的index为409;
那么对应的频率应该是 409*100e6/4096 = 9.985e6,约等于10MHz;
其中100e6是采样频率,4096是FFT点数
将IFFT波形信号调整为模拟有符号十进制,可以看到下图IFFT输出的波形,可以根据图中的时钟信号计算出波形周期为100ns,即频率为10MHz
这应该是最简单的方式实现FFT/IFFT了吧,如果大家有更好的方法,可以留言交流~
文中的完整工程文件可以在这里下载:https://download.csdn.net/download/luobluesky/11200680
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。