基於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文件、圖片文件在羣中)對文章有什麼看法或者需要更近一步交流的同學,可以加入下面的羣:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章