基于FPGA的FFT算法实现

项目简述

前面的一篇博客我们已经讲解了FFT算法的发展历程,至于FFT的原理感兴趣的同学可以查阅书本数字信号处理,书本上面的知识特别详细,这里我也就不多说了。接下来我们将利用FPGA实现FFT算法,我们本次实验会利用IP核来实现,但是后面的文章会讲解verilog实现FFT过程。

本次实验所用到的软硬件环境如下:
1、VIVADO2019.1软件环境
2、Modelsim10.7c仿真环境

FFT IP的定制及详解

我们找到FFT的IP核如下:
在这里插入图片描述
在这里插入图片描述
1、这里我们选择1路信号的FFT变换。
2、FFT变换的点数,我们这里是1024点与前面MATLAB中的设置保持一致。
3、模块的参考时钟频率我们选择100MHz。
4、选择实现FFT的算法,我们使用基2算法
在这里插入图片描述
1、我们这里的数据格式选择成定点数即可。
2、缩放比例我们选择成块浮点数,这里是指将FFT每层的运算进行一定缩放,使得最后的结果大小适当。
3、这里选择数据的缩放直接选择截断数据。
4、输入数据的位宽,我们这里选择成16位。
5、相位因子的位宽,这与FFT内部相频的精度有关,这里我们选择默认即可。
6、FFT输出有两种顺序,也就是自然顺序和位反转顺序,我们一般选择自然顺序方便我们之后的处理。
在这里插入图片描述
1、数据我们使用块RAM。
2、相位我们也使用块RAM
3、复数乘法我们使用4乘法器结构
4、乘法使用DSP内部的专用乘法器,效果好一点。
这里我们还要注意IP定制界面的下面信息:
在这里插入图片描述
在这里插入图片描述
从上面的信息中我们可以看到,输入输出数据的高16位代表复数的虚数位,低16位代表复数的实数位。
S_AXIS_CONFIG输入为1代表傅里叶正变换,0代表傅里叶逆变换。

Block Design设计

我们本次实验将继续上次的实验进行讲解。在上一章的block design中加入相应的FFT的IP核,如下:
在这里插入图片描述
上面的设计我们严格遵循了AXI-stream的数据协议,当然因为该项目简单AXI中的ready信号一直为高,可以简化设计。同时注意,上面有我们自定义的IP核,代码如下:
fft_last模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : 
// Module Name  : fft_last.v
// Create Time  : 2020-04-04 22:18:25
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module fft_last(
    input                       sclk            ,
    input                       rst_n           ,
    input                       axi_tvalid      ,
    input                       axi_tready      ,
    output  reg                 axi_tlast           
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
reg                     [10:0]  cnt             ;

//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        axi_tlast           <=          1'b0;       
    else if(cnt == 1023 && axi_tready == 1'b1 && axi_tlast == 1'b1)
        axi_tlast           <=          1'b1;
    else
        axi_tlast           <=          1'b0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt                 <=          11'd0;
    else if(cnt == 1023 && axi_tready == 1'b1 && axi_tlast == 1'b1)
        cnt                 <=          11'd0;
    else if(axi_tready == 1'b1 && axi_tlast == 1'b1) 
        cnt                 <=          cnt + 1'b1;
    else
        cnt                 <=          cnt;
        
endmodule

split模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : 
// Module Name  : split.v
// Create Time  : 2020-04-04 22:48:43
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module split(
    input               [31:0]  d_in        ,
    output  wire        [15:0]  d_out1      ,
    output  wire        [15:0]  d_out2      
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/

 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/

assign      {d_out2,d_out1}         =           d_in;

endmodule

仿真结果

我们对上面的工程进行仿真,仿真结果如下:
在这里插入图片描述
从上面的仿真你图形可以验证我们实验的正确性。

总结

创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。(txt文件、图片文件在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

发布了55 篇原创文章 · 获赞 38 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/zhangningning1996/article/details/105321984