基于vivado实现FFT/IFFT


前言

使用vivado2018.3实现FFT/IFFT,过程比较详细。


一、基本过程

例化一个DDS的IP核和两个FFT的IP核分别用作FFT和IFFT变换,将DDS生成的正交信号输入到FFT,再将FFT的信号输出到IFFT中。
在这里插入图片描述

二、vivado配置

1.新建工程

打开vivado,界面如下
在这里插入图片描述

点击Open Project,进入如下页面,点击Next
在这里插入图片描述
编辑工程名字和保存路径,点击Next
在这里插入图片描述
查找所需要的板子型号(我所用的是xc7z020-1clg400c),但是后面只进行了仿真,未进行上板实验。
在这里插入图片描述
工程信息汇总,点击Finish,即可完成工程的新建。
在这里插入图片描述
工程界面如下
在这里插入图片描述

2.调用DDS的IP核

调用DDS的IP核,生成10MHz正弦信号

单击IP Catalog,输入dds,找到IP核后,双击
在这里插入图片描述
进入dds的IP核配置界面,各项选择如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置完成,点击OK即可。

2.调用FFT的IP核

搜索fft,然后找到Digital Signal Processing->Transforms->FFTs目录下的Fast Fourier Transform,双击进入配置界面。
在这里插入图片描述
各项选择配置如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置完成,点击OK即可。

三、编写Verilog程序

1.顶层文件fft.v

例化IP核,将三个模块连接起来。

点击Add Sources,弹出右侧窗口,选择Add or create design sources,点击Next
在这里插入图片描述
点击Create File
在这里插入图片描述
输入文件名称fft,点击OK
在这里插入图片描述
点击Finish
在这里插入图片描述
点击OK
在这里插入图片描述
点击Yes,即可完成新建。
在这里插入图片描述
vivado会自动生成IP核的调用方式的模板,双击相应IP核的.veo文件,可以看到Verilog版本的例化模板,可根据该模板写top文件,也就是驱动这个IP核的文件。

代码如下:

`timescale 1ns / 1ps

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
    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

2.仿真文件fft_tb.v

与上面步骤类似,不过在下面该步骤时,选择Add or create simulation sources
在这里插入图片描述
代码如下:

`timescale 1ns / 1ps

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;//低有效
        #30 aresetn = 1;
    end

    always #5 aclk=~aclk;//时钟频率100MHz
endmodule

四、运行仿真

1. 运行仿真设置

在运行仿真之前需要设置仿真时间,在下图SIMULATION处右击,进入Simulation Settings
在这里插入图片描述
设置仿真时间为300us,点击OK即可完成设置
在这里插入图片描述
接下来就是进行仿真,点击Run Simulation,然后点击Run Behavioral Simulation,即可开始仿真,等待一段时间。
在这里插入图片描述

2. 仿真波形设置

仿真之后只会显示仿真文件中的信号,结果分析需要查看内部模块的信号。在下图中,单击fft_test即可看到内部信号,将未显示的信号选中右击,选择Add to Wave Window,这些信号即可添加进仿真波形图中。
在这里插入图片描述
添加完成后,再次进行仿真。

找到dds_m_data_tdata,fft_m_data_tdata,ifft_m_data_tdata信号,分别进行如下设置。
选中信号,右击,找到Waveform Style,选择Analog。
在这里插入图片描述
选中信号,右击,找到Radix,选择Signed decimal。
在这里插入图片描述

3. 结果分析

DDS产生波形,周期为100ns,即频率为10MHz。复位信号至少拉低两个时钟周期。
在这里插入图片描述
下图可以看到FFT输出的模拟波形尖峰处对应的index为409;那么对应的频率应该是409*100e6/4096 = 9.985e6,约为10MHz;其中100e6是采样频率为100MHz,4096是FFT点数。
在这里插入图片描述
可以看到下图IFFT输出的波形,可以看出图中波形周期为100ns,即频率为10MHz。
在这里插入图片描述
在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值