Xilinx IP解析之 Fast Fourier Transform(FFT) v9.1
Xilinx IP解析之 Fast Fourier Transform(FFT) v9.1
前言——兩個FFT IP核的區分
在Vivado的IP中搜索FFT,會顯示出FFT和LTE FFT,如下圖所示。FFT就是我們一般使用的FFT IP核,而LTE FFT是什?它和FFT有什么區別?什么時候使用它?為消除這些疑問,下面簡單介紹下LTE FFT。
LTE(Long Term Evolution,長期演進)項目是3G向4G演進的過渡技術(具體可參考3G、3GPP、LTE、4G解釋),此IP是為了滿足LTE技術特殊的FFT要求而專門開發的,它與常規的FFT IP核有兩個區別:
1。LTE FFT有一個Enable 15MHz Bandwidth Support的可選項,選中后Maximum Transform Length可選384、768、1536,3072這幾個非2n的點數,這應該是LTE技術特有的FFT處理點數要求。
2。LTE FFT的輸入數據寬度為14~17。
暫時就發現這兩個區別。顯然只有在開發LTE相關技術時我們才會使用LTE FFT IP核。
一般來說,我們使用FFT IP核。下面介紹FFT IP核。
一。IP概述
可參考Xilinx官網Fast Fourier Transform (FFT)概述,
1.1 產品描述
Fast Fourier Transform (FFT) 是 DSP 系統內使用的基本構建模塊,其應用范圍從基于 OFDM 的數字調制解調器到超聲波、RADAR 和 CT 圖像重建算法。盡管它的算法很容易理解,但實現架構和特性的變體很重要,而且對于今天的硬件工程師來說,非常耗時。
FFT LogiCORE? IP 核不僅提供 4 種不同的架構,而且還提供系統級定點 C 模型,可將 3-6 個月的典型實現時間銳減至按下按鈕所需的時間。此外,它還可幫助用戶針對所有必要的算法和實現方案做出 DSP 算法及硬件工程師所要求的權衡。這些容易做出的權衡有助于用戶針對其應用所需的特定點大小及轉換時間選擇最多資源的低功耗解決方案。
FFT LogiCORE 不僅可增加數據和高達 34 位的相位因數寬度支持,而且還可支持 IEEE 單精度浮點數據類型,從而可擴展對更高動態范圍的關注。浮點選項是通過內部利用精度更高的定點 FFT 實現的,可通過數量顯著減少的資源,實現與完整浮點實現方案類似的噪聲性能。
1.2 主要功能與優勢
-
與 AXI4-Stream 兼容的接口。
-
正反向的復雜 FFT,運行時可配置
-
轉換尺寸 n = 2m、m = 3 – 16
-
數據采樣精度 bx = 8 – 34
-
相位因數精度 bw = 8 – 34
-
運算類型:
- 未定標(全精度)定點
- 定標定點
- 塊浮點
-
定點或浮點接口
-
蝶后取舍
-
用于數據和相位因數存儲的分布式 RAM 的塊 RAM
-
運行時可配置的可選轉換點大小
-
運行時可配置的擴展計劃支持定標定點內核
-
位/數顛倒(或自然)輸出順序
-
數字通信系統的可選循環前綴插入
-
4 種架構可提供內核大小和轉換時間之間的平衡
-
比特位精確的 C 模型和 MEX 可供下載,滿足系統建模需求
二。IP產品手冊
可參考Xilinx官網Fast Fourier Transform (FFT)文檔
下載PG109 - Fast Fourier Transform v9.1 Product Guide (v9.1)。
三。IP框圖與信號端口
3.1 IP模塊框圖
3.2 端口信號列表
| 時鐘與復位 | aclk | I | 必須 | 1 | 模塊工作時鐘,上升沿有效 |
| aclken | I | 可選 | 1 | 時鐘使能信號,高電平有效,低電平時內核暫停工作,可通過此信號降低內核運行的最大時鐘頻率 | |
| aresetn | I | 可選 | 1 | 低電平同步復位信號,優先級高于aclken,低電平至少持續兩個時鐘周期 | |
| 配置 | s_axis_config_tvalid | I | 必須 | 1 | 配置通道的 tvalid,由外部主機斷言以表示它能夠提供數據 |
| s_axis_config_tready | O | 必須 | 1 | 配置通道的 tready,由內核斷言以表示它已準備好接收數據 | |
| s_axis_config_tdata | I | 必須 | 可配置,8的倍數 | 配置通道的tdata,攜帶配置信息,NFFT、FWD/INV、CP_LEN和SCALE_SCH | |
| 輸入數據 | s_axis_data_tvalid | I | 必須 | 1 | 輸入數據通道tvalid,由外部主機斷言以表示它能夠提供數據 |
| s_axis_data_tready | O | 必須 | 1 | 輸入數據通道tready,由內核斷言以表示它能夠接收數據 | |
| s_axis_data_tdata | I | 必須 | 可配置,16的倍數 | 輸入數據通道tdara,由外部主機提供待處理的數據 | |
| s_axis_data_tlast | I | 必須 | 1 | 輸入數據通道tdara,由外部主機斷言表示最后一組數據。 只在生成事件event_tlast_unexpected 和 event_tlast_missing時,內核才使用它 | |
| 輸出數據 | m_axis_data_tvalid | O | 必須 | 1 | 輸出數據通道tvalid,由內核斷言表示它能夠提供數據 |
| m_axis_data_tready | I | 必須 | 1 | 輸出數據通道tready,由外部叢機斷言表示它能夠接收數據 | |
| m_axis_data_tdata | O | 必須 | 可配置,16的倍數 | 輸出數據通道tdata,由內核提供FFT后的數據 | |
| m_axis_data_tuser | O | 可選 | 可配置,8的倍數 | 輸出數據通道tuser,由內核提供XK_INDEX,OVFLO,BLK_EXP信息 | |
| m_axis_data_tlast | O | 必須 | 1 | 數據數據通道tlast,由內核斷言表示最后一個輸出數據 | |
| 狀態(可選) | m_axis_status_tvalid | O | 可選 | 1 | 狀態通道tvalid,由內核斷言表示它能夠提供狀態數據 |
| m_axis_status_tready | I | 可選 | 1 | 狀態通道tready,由外部叢機斷言表示它能夠接收狀態數據 | |
| m_axis_status_tdata | O | 可選 | 16 | 狀態通道tdata,由內核提供的狀態數據,包含BLK_EXP 或 OVFLO | |
| 事務 | event_frame_started | O | 必須 | 1 | 當內核開始處理新幀時,該事件信號在一個時鐘周期內被置位。提供此信號是為了允許您對幀進行計數,并在需要時將內核的配置同步到特定的幀。 |
| event_tlast_unexpected | O | 必須 | 1 | 當內核在不是幀中最后一個的任何傳入數據樣本上看到 s_axis_data_tlast High 時,該事件信號被置位為一個時鐘周期。這表明核心和上游數據源在幀大小方面的配置不匹配,并表明上游數據源配置為比核心更小的點大小。這僅在內核開始處理幀時計算,因此事件可能會滯后 s_axis_data_tlast 上的意外高點大量時鐘周期 如果一幀的 s_axis_data_tlast 上有多個意外的高點,則對它們中的每一個都進行斷言。 | |
| event_tlast_missing | O | 必須 | 1 | 當 s_axis_data_tlast 在幀最后傳入的數據樣本上為低時,該事件信號在單個時鐘周期內被置位。這表明內核和上游數據源在幀大小方面的配置不匹配,并表明上游數據源配置為比核心更大的點大小。 這僅在內核開始處理幀時計算,因此事件可能會滯后丟失的 s_axis_data_tlast 大量時鐘周期 | |
| event_fft_overflow | O | 可選 | 1 | 當在 m_axis_data_tdata 上傳輸的數據樣本中出現溢出時,該事件信號在每個時鐘周期置位。 只有在使用縮放算術或單精度浮點 I/O 時才會出現 FFT 溢出。在所有其他配置中,此引腳被移除 | |
| event_data_in_channel_halt | O | 必須 | 1 | 該事件在內核需要來自數據輸入通道的數據且沒有數據可用的每個周期被置位。 在實時模式下,即使幀已不可恢復地損壞,內核仍會繼續處理該幀。 在非實時模式下,核心處理停止并僅在數據寫入數據輸入通道時繼續。幀沒有損壞。 在這兩種模式下,事件保持有效,直到數據輸入通道中的數據可用 | |
| event_data_out_channel_halt | O | 必須 | 1 | 該事件在內核需要將數據寫入數據輸出通道,但因為通道中的緩沖區已滿而無法寫入的每個周期中被置位。發生這種情況時,核心處理會停止,所有活動都會停止,直到通道緩沖區中有可用空間。幀沒有損壞。 此事件引腳僅在非實時模式下可用。 | |
| event_status_channel_halt | O | 必須 | 1 | 該事件在內核需要將數據寫入狀態通道但不能因為通道上的緩沖區已滿而無法寫入的每個周期中被置位。發生這種情況時,核心處理會停止,所有活動都會停止,直到通道緩沖區中有可用空間。幀沒有損壞。 此事件引腳僅在非實時模式下可用 |
3.3 關鍵信號解析
3.3.1 aresetn (同步復位)
如果內核上存在 aresetn 引腳,則將引腳驅動為低電平會導致所有輸出引腳、內部計數器和狀態變量重置為其初始值。表 3-1 中描述的初始值也是電路上電時采用的默認值,無論內核是否配置為 aresetn。所有掛起的加載過程、轉換計算和卸載過程都停止并重新初始化。
NFFT 設置為允許的最大 FFT 點大小(在 Vivado 集成設計環境 (IDE) 中設置的變換長度值)。
擴展計劃設置為 1/N。對于具有非四次冪點大小的 Radix-4 Burst I/O 和 Pipelined Streaming I/O 架構,最后一個階段的縮放比例為 1,其余階段的縮放比例為 2。見表 3- 1。
aresetn 引腳優先于 aclken。如果 aresetn 被置位,則無論 aclken 的值如何,都會發生復位。需要兩個周期的最小aresetn 活動脈沖。
3.3.2 s_axis_config_tdata(配置數據)
s_axis_config_tdata字段里面包含多個小字段,如下表。
| NFFT | 可選 | 5 | 000/111 | 實際變換的點數 = 2NFFT,IDE中設置的是最大點數,NFFT的值可以比最大點數要小。例如,一個1024點的FFT可以計算的點數為1024,512,256或者更小。注意: 僅選中了run time configurable transform length(運行期間可配置變換長度)時,此字段才可用 |
| CP_LEN | 可選 | log2(maxinum point size) | 是 | 循環前綴長度: 從轉換結束起,在輸出整個轉換之前,最初作為循環前綴輸出的樣本數。CP_LEN可以是零 ~ 實際點大小(不包括) 之間的任何數字。 CP_LEN的前NFFT位是有效的,后面補0。 該字段僅在循環前綴插入時出現 |
| FWD_INV | 必須 | FFT通道數 | – | 此字段指定FFT IP核是進行FFT變換還是IFFT變換。當FWD_INV = 1時,FFT變換;當FWD_INV = 0時,IFFT變換。此字段寬度等于通道數。bit0(LSB)表示通道0,bit1表示通道1,以此類推。 |
| SCALE_SCH | 可選 | 見下方詳解 | – | 見下發詳解 |
這些字段構成的tdata的位寬必須是8的倍數,如果不是8的倍數,應該填充位到8的倍數。
IP核在讀取字段值時會忽略填充位的值,所以填充位可以填任意值,但應該設為常量(通常是全0),這樣可以減小資源消耗。
SACLE_SCH是可選的,只有當縮放選項選為Scaled時,SCALE_SCH才被需要,表示將輸出數據縮放到與輸入數據相同的位寬。在進行FFT運算時,有多次加法或乘法運算,運算結果的位寬會逐漸增加,最終導致最終輸出結果的位寬增加。為了防止輸出結果出現位寬溢出,需要對每一級的輸入數據進行縮放,SACLE_SCH就表示每一級的縮放倍數,比如 SCALE_SCH = [01 10 00 11 10],以2位為隔斷,從左向右數,10表示第一級縮放倍數=22=4,即右移兩位。11表示第二級縮放倍數=23=8,即右移3位,以此類推。最終輸出數據數據右移(1+2+0+3+2)=8位,也就是縮小了256倍,最終輸出的結果要放大256倍才是正確的。
SACLE_SCH的位寬與運算架構和運算點數相關,對于流水線IO與蝶4突發IO,SACLE_SCH位寬=2×ceil(NFFT/2),ceil表示進一取整。例如NFFT = 11(對應FFT點數=2048),SACLE_SCH位寬=2×ceil(11/2)=2×6=12。對于蝶2突發IO與蝶2Lite突發IO,SACLE_SCH位寬=2×NFFT,例如NFFT = 11,SACLE_SCH位寬=22。
SACLE_SCH是指定的每一級的縮放倍數,當FFT點數不是4的n次冪時,最后一級只有2位,對應的縮放倍數最多為2,即此時SACLE_SCH的最高兩位只能是00或者01,表示不縮放或縮放2倍。例如FFT點數 = 512,512 = 44×2,所以最后一級只有2位數,此時SACLE_SCH的最高兩位只能是00或者01。
為完全防止數據溢出,應保證縮放倍數=2×FFT點數,一種可用的SACLE_SCH的取值方式為:
當FFT點數=1024,架構為蝶4突發IO時,SCALE_SCH = [10 10 10 10 11],對應總縮放倍數=2^(2+2+2+2+3)=2048,它完全避免了輸出數據溢出。
同理,當當FFT點數=2048,架構為蝶4突發IO時,SCALE_SCH = [01 10 10 10 10 11],對應總縮放倍數=4096。
當FFT點數=1024,架構為蝶2突發IO時,SCALE_SCH = [01 01 01 01 01 01 01 01 01 10],對應總縮放倍數=2^(1×9+2)=2048,同樣完全避免的輸出數據溢出。
這些字段如何構成s_axis_config_tdata字段如下圖所示,其中,PAD表示填充位,可選字段用虛線表示。
配置數據示例:
字段解讀:
| NFFT | 000 | 00011 | 實際變換的點數 = 2NFFT = 23 = 8 |
| CP_LEN | 0 | 1000000 | CP_LEN位寬 = log2(maxinum point size),所以IDE中設置的變換長度N = 27 = 128。 因NFFT = 3,所以CP_LEN只有高3位有效,所以這里CP_LEN的值為100 = 4,后面4位是補的0。 |
| FWD_INV | 無 | 100 | 通道0反變換,通道1反變換,通道2正變換 |
3.3.3 s_axis_data_tdata(輸入數據)
| XN_RE 輸入數據實部 | bxn | 0或1任選 (一般為全0) | 二進制補碼或單精度浮點格式的實數分量,bxn = 8 ~ 34 |
| XN_IM 輸入數據虛部 | bxn | 0或1任選 (一般為全0) | 二進制補碼或單精度浮點格式的虛數分量,bxn = 8 ~ 34 |
多通道的s_axis_data_tdata字段如下圖所示,其中虛線框表示可選,PAD表示填充。
輸入數據示例:
3.3.4 m_axis_data_tdata(輸出數據)
| XK_RE 輸出數據實部 | bxk | 符號位擴展 | 二進制補碼或浮點格式的實數分量。 當數據格式為定點數時: 1. 對于縮放算術和塊浮點運算,輸出數據位寬bxk = 輸入數據位寬bxn 2. 對于未縮放算術,bxk = bxn + log2(最大變換點數) + 1 當數據格式為單精度浮點數時:bxk = 32 |
| XK_IM 輸出數據虛部 | bxk | 符號位擴展 | 二進制補碼或浮點格式的虛數分量。 其余同上 |
bxk必須是8的倍數,不是則符號位擴展為8的倍數。
多通道的m_axis_data_tdata字段如下圖所示,其中虛線框表示可選,PAD表示符號位填充。
輸出數據示例:
3.3.5 m_axis_data_tuser(輸出用戶字段)
| XK_INDEX | 可選 | log2(maxinum point size) | 全0 | 輸出數據的索引(無符號 2 的補碼)。 此字段是可選的,僅在 IDE 中啟用 XK_INDEX 時才包含 |
| BLK_EXP | 可選 | 8 | 全0 | 塊指數(無符號 2 的補碼):應用的縮放量(即未縮放的輸出值向下移動的位數)。 每個 FFT 通道都包含一個單獨的 BLK_EXP 字段。 僅當使用塊浮點時可用 |
| OVFLO | 可選 | 1 | – | 算術溢出指示器(高電平有效):如果數據幀中的任何值溢出,則在結果卸載期間 OVFLO 為高電平。 OVFLO 信號在新數據幀開始時復位。 每個 FFT 通道都包含一個單獨的 OVFLO 字段。 此字段是可選的,僅可用于縮放算術或單精度浮點 I/O |
所有構成tuser的字段都是可選的, 當一個也沒有被選擇時, tuser將自動從輸出數據通道中去除。
多通道的m_axis_data_tuser字段如下圖所示,其中虛線框表示可選,PAD表示0填充。
輸出用戶字段示例1:
輸出用戶字段示例2:
3.3.6 m_axis_status_tdata(輸出狀態數據)
| BLK_EXP | 可選 | 5 | 全0 | 塊指數(無符號 2 的補碼):應用的縮放量(即未縮放的輸出值向下移動的位數)。 每個 FFT 通道都包含一個單獨的 BLK_EXP 字段。 僅當使用塊浮點時可用 |
| OVFLO | 可選 | 1 | – | 算術溢出指示器(高電平有效):如果數據幀中的任何值溢出,則在結果卸載期間 OVFLO 為高電平。 OVFLO 信號在新數據幀開始時復位。 每個 FFT 通道都包含一個單獨的 OVFLO 字段。 此字段是可選的,僅可用于縮放算術或單精度浮點 I/O |
相比較輸出用戶字段,輸出狀態字段省略了XK_INDEX,它適用于不直接對數據進行操作但可能需要知道信息來控制系統另一部分的下游從站。
多通道的m_axis_status_tdata字段如下圖所示,其中虛線框表示可選,PAD表示0填充。
輸出狀態示例:
四。IP配置
4.1 Configuration
| Number of Channels | 通道數,取值范圍:1~12 |
| Transform Length | 變換點數,取值范圍:23 ~ 216 (8 ~ 65536) |
| Target Clock Frequency | 目標時鐘頻率(MHz),取值范圍:1 ~ 1000 |
| Target Data Throughput | 目標數據比特率(MSPS),取值范圍:1 ~ 1000 目標時鐘頻率和目標數據吞吐量僅用于自動選擇的執行情況,并計算延遲。 不保證內核以指定的目標時鐘頻率或目標數據吞吐量運行 |
| Automatically | 自動選擇,由IP根據上面給定的時鐘頻率與比特率自行選擇架構 |
| Pipelined, Streaming I/O | 流水線IO,允許連續數據處理,僅當使用單通道時,流水線IO可選 |
| Radix-4, Burst I/O | 蝶4突發IO,使用迭代方法分別加載和處理數據。它的資源消耗比流水線架構小,但轉換時間更長 一點不同:蝶4架構的變換點數為64 ~ 65536,其它架構點數為 8 ~ 65536 |
| Radix-2, Burst I/O | 蝶2突發IO,使用與 Radix-4 相同的迭代方法,但蝶形運算單元更小。 它的資源消耗比 Radix-4 架構的尺寸更小,但轉換時間更長 |
| Radix-2 Lite, Burst I/O | 蝶2-Lite突發IO,基于 Radix-2 架構,此變體使用分時復用方法實現蝶形運算單元, 以實現更少的資源消耗,但代價是轉換時間更長 |
| Run Time Configurable Transform Length | 選擇運行時是否可配置轉換長度。 當不可配置時,內核使用更少的邏輯資源并具有更快的最大時鐘速度; 當可配置時,配置數據s_axis_config_tdata中的NFFT字段被激活, s_axis_config_tdata的位寬會增加8位 |
四種FFT架構的資源消耗與吞吐量的關系如下圖所示。
4.2 Implementation
| Data Format(數據格式) | Fixed Point | 定點數 |
| Floating Point | IEEE-754 單精度(32 位)浮點格式。 僅當使用單通道時,浮點數可用; 使用多通道時,僅可選擇定點數。 | |
| Scaling Options(縮放選項) (僅當數據格式選為定點數時可用) | Block Floating Point | 塊浮點,內核確定需要多少縮放才能充分利用可用動態范圍,并將縮放因子報告為塊指數 |
| Scaled | 縮放,用戶定義的縮放計劃決定了數據在 FFT 階段之間的縮放方式 | |
| Unscaled | 不縮放,運算過程中的所有位增長都會疊加到輸出。 輸出實部位寬 = 輸入實部位寬 + log2(變換點數) + 1。 虛部位寬 = 實部位寬 | |
| Rounding Modes(省入模式) (僅當數據格式選為定點數時可用) | Truncation | 截斷,小數部分直接丟棄 |
| Convergent Rounding | 收斂省入,四省五入,特殊的: 當小數部分 = 0.5時,如果整數部分是奇數,則收斂舍入向上舍入, 如果整數部分為偶數,則向下舍入。 收斂舍入可用于避免 DC 偏置,但會增加資源使用量和延遲而導致轉換時間略有增加 | |
| Precision Options(精度選項) | Input Date Width | 輸入數據寬度,8 ~ 32;當數據格式為浮點數時固定為32 |
| Phase Factor Width | 相位因子寬度,8 ~ 32;當數據格式為浮點數時僅可選24/25 | |
| Control Signals(控制信號) | ACLKEN | 時鐘使能 |
| ARESETn | 同步復位,低電平有效且低電平至少要持續兩個時鐘周期 | |
| Output Ordering(輸出位序) | Bit/Digit Reversed Order | 位/數反轉排序 |
| Normal Order | 正常順序 | |
| Cycle Prefix Insertion | 循環前綴插入 | |
| Optional Output Fields(可選輸出字段) | XK_INDEX | 輸出序號,輸出數據通道m_axis_data_tuser中的可選字段 |
| OVFLO | 數據溢出標志,輸出數據通道m_axis_data_tuser中的可選字段, 也是輸出狀態通道m_axis_status_tdata中的可選字段 | |
| Throttle Scheme(節流方案) | Non Real Time | 非實時 |
| Real Time | 實時 |
4.2.1 Bit/Digit Reversed Order(位/數反轉排序)
四種FFT架構都提供輸出數據的 正常順序 或 位/數反轉排序 選項。
默認為位/數反轉排序,此時數據以正常順序輸入時,但FFT 算法在處理過程中會對輸入數據重新排序,所以輸出數據會以位/數反轉的順序輸出。
當選擇位/數字反轉順序時,基于 Radix-2 的架構(流水線流 I/O、Radix-2 Burst I/O 和 Radix-2 Lite Burst I/O)提供位反轉排序,而基于 Radix-4 的架構(Radix-4 Burst I/O) O) 提供數字反轉排序。
當選中正常順序時,對于流水線 I/O 架構,內核使用的內存會增加。對于突發 I/O 架構,因為需要單獨的卸載階段,整體轉換時間會增加。
4.2.2 Cyclic Prefix Insertion(循環前綴插入)
如果輸出順序是自然順序,則可以選擇循環前綴插入。循環前綴插入適用于所有架構,通常用于 OFDM 無線通信系統。
4.2.3 Throttle Scheme(節流方案)
選擇性能和數據定時需求之間的平衡。Real time模式通常提供更小、更快的設計,但是在必須提供和使用數據時有嚴格的限制。非實時模式沒有這樣的約束,但是設計可能會更大、更慢。
TODO,實時模式與非實時模式的區別
4.3 Detailed Implementation(詳細實現)
| Data | Block RAM | 使用塊RAM存儲數據,性能較好 |
| Distributed RAM | 使用分布式RAM存儲數據,資源消耗少 | |
| Phase Factors (相位因子) | Block RAM | 使用塊RAM存儲相位因子 |
| Distributed RAM | 使用分布式RAM存儲相位因子 | |
| Number of stages using Block RAM for Data and Phase Factors (數據和相位因子使用塊RAM的級數) | – | 范圍:1 ~ 5,流水線級數,越大運算速度越快,消耗資源越多 |
| Reorder Buffer 重排序緩沖 | Block RAM | 使用塊RAM存儲重排序的數據 |
| Distributed RAM | 使用分布式RAM存儲重排序的數據 | |
| Complex Multipliers (復數乘法器) | Use 3-multiplier structure(resource optimization) | 使用3乘法結構(資源優化) 所有復數乘法器都使用三個實數乘法、五個加/減結構,其中乘法器使用 DSP Slice。這減少了 DSP 片數,但使用了一些片邏輯。這種結構可以利用DSP Slice 預加器來減少或消除對額外Slice 邏輯的需求,并提高性能 |
| Use 4-multiplier structure(performance optimization) | 使用4乘法結構(性能優化) 所有復數乘法器都使用四實數乘法、兩個加/減結構,利用 DSP Slice。這種結構以犧牲更多專用乘法器為代價獲得了最高的時鐘性能。在帶有 DSP Slice 的設備中,加/減操作在 DSP Slice 內實現 | |
| Use CLB Logic | 所有復數乘法器都是使用切片邏輯構造的。這適用于具有低性能要求的目標應用程序,或具有很少 DSP Slice 的目標設備。 | |
| Butterfly Arithmetic (蝶形運算單元) | Use CLB Logic | 所有蝶形運算單元都使用切片邏輯構建 |
| Use Xtremedsp Slices | 此選項強制使用 DSP Slice 中的加法器/減法器實現所有蝶形運算單元 |
4.4 Implementation Details(實現詳情)與Latency(延遲)
同上圖。
可在IP配置界面的左側mplementation Details子頁查看到實現架構類型,變換點數,資源消耗情況,AXI Stram端口數據構成情況的信息。
可在Latency子頁查看運算延遲,延遲指的是從上游主機提供第一個輸入數據到最后一個輸出數據輸出完成的時間,它取決于IP核工作時鐘頻率,所以以時鐘數的形式給出。
五. IP仿真
5.1 仿真框圖
仿真FFT IP,掌握輸入輸出時序。IP配置如下圖所示。
流水線架構,單通道,1024個定點數,不縮放,小數截斷,輸入數據位寬24,相位因子位寬16,正常順序輸出,非實時模式。
將FFT IP核的輸入/輸出端口信號引出,在testbench中進行賦值/觀測。
說明:
根據傅里葉變換的公式,FFT的計算結果關于采樣頻率的一般對稱。但在實際計算中,這種對稱是不完全的。
計算結果的兩半之間的不對稱性在較大的變換點大小上更為明顯。此外,噪聲在較低頻率段中更為突出。因此,賽靈思建議在執行實值 FFT 時使用輸出數據的上半部分(N/2 + 1 ~ N 點,N表示變換點數)。(此處參考pg109-xfft第33頁)
所以,總是使用N/2 + 1 ~ N之間的數據作為傅里葉變換的結果是有好處的。
5.2 testbench
5.2.1 生成輸入波形數據
以下matlab程序可以根據設置,生成各種單頻率或是混合頻率的波形,并轉為二進制補碼,注意實際值與二進制值的關系。
%{* @Author : Xu Dakang* @Email : XudaKang_up@qq.com* @Date : 2021-07-05 15:18:49* @LastEditors : Xu Dakang* @LastEditTime : 2021-07-05 17:38:18* @Filename :* @Description : %}N = 256; % 采樣頻率 T_NUM = 10; % 波形周期數BIT_WIDTH = 24; % 二進制位數t = linspace(0, 1, N);% y0 = 0.7 * sin(2 * pi * 1 * t); y0 = 0.5 + 0.7 * sin(2 * pi * 1 * t) + 0.8 * sin(2 * pi * 2 * t); % y0 = 0.7 * sin(2 * pi * 1 * t) + sin(2 * pi * 2 * t);WAVE_MAX = 2; % 波形可能的最大值 y1 = round((2^(BIT_WIDTH - 1) - 1) * y0 / WAVE_MAX); y = []; for i = 0:T_NUMy = [y, y1]; endplot(y);A = myDec2Bin(y, BIT_WIDTH);filepath = './sin.txt';myWriteTxt(A, filepath);function yout_signed_bin_str = myDec2Bin(xin_int, BIT_WIDTH)%{* description:輸入十進制整數矩陣,得到指定位數的二進制補碼字符矩陣, 整數數值滿足范圍:-(2^(BIT_WIDTH - 1))~2^(BIT_WIDTH - 1) - 1* @param xin_int 十進制數矩陣* @param BIT_WIDTH 二進制位數* return yout_signed_bin_str 有符號的指定位數的二進制字符矩陣%}% 判斷輸入參數是否合法for i = 1:numel(xin_int)if fix(xin_int(i)) ~= xin_int(i) % 輸入應是整數error('Error!, xin_int %d should be int, but there is %s', i, class(xin_int(i)));elseif xin_int(i) < -(2^(BIT_WIDTH - 1)) || xin_int(i) > 2^(BIT_WIDTH -1) - 1 % 輸入不能超過有符號BIT_WIDTH的范圍error('Error!, xin_int %d should be in %d ~ %d, but it is %d', ...i, -(2^(BIT_WIDTH - 1)), 2^(BIT_WIDTH -1) - 1, xin_int(i));endendyout_signed_bin_str = strings(size(xin_int)); % 創造一個與輸入格式相同的字符串數組for i = 1:numel(xin_int) % numel(A)表示矩陣A元素個數yout_signed_bin_str(i) = dec2bin(xin_int(i) + (xin_int(i) < 0) * 2^BIT_WIDTH, BIT_WIDTH);if xin_int(i) < 0yout_signed_bin_str(i) = dec2bin((2^BIT_WIDTH + xin_int(i)), BIT_WIDTH);elseyout_signed_bin_str(i) = dec2bin(xin_int(i), BIT_WIDTH);endendend%{ * @description:輸入字符串矩陣, 每一行寫入對應路徑的文件中 * @param xin_str_matrix 字符串矩陣 * @return {*} %} function myWriteTxt(xin_str_matrix, filepath)% 檢查輸入是否合法if ~ischar(filepath) % filepath必須為字符向量error('Error!, filepath should be string, but it is %s', class(filepath))endfor i = 1:numel(xin_str_matrix)if ~isstring(xin_str_matrix(i))error('Error!, xin_str_matrix %d should be string matrix, but it is %s', i, class(xin_str_matrix(i)))endendfid = fopen(filepath, 'w');for i = 1:numel(xin_str_matrix)fprintf(fid, xin_str_matrix(i));if i ~= numel(xin_str_matrix) % 除最后一行外, 每行加換行符fprintf(fid, '\r\n');endendfclose(fid); end5.2.2 testbench
/** @Author : Xu Dakang* @Email : XudaKang_up@qq.com* @Date : 2021-07-01 16:04:26* @LastEditors : Xu Dakang* @LastEditTime : 2021-07-05 16:53:26* @Filename : myFFT_tb.sv* @Description : testbench of myFFT */module myFFT_tb ();timeunit 1ns; timeprecision 1ps;logic aclk;logic [47:0] din_tdata; logic din_tlast; logic din_tready; logic din_tvalid;logic [79:0] dout_tdata; logic dout_tlast; logic dout_tready; logic dout_tvalid;logic event_data_in_channel_halt; logic event_data_out_channel_halt; logic event_frame_started; logic event_status_channel_halt; logic event_tlast_missing; logic event_tlast_unexpected;logic [7:0] fft_config_tdata; logic fft_config_tready; logic fft_config_tvalid;myFFT_wrapper myFFT_wrapper_u0(.*);// 生成時鐘 localparam CLKT = 4; initial beginaclk = 0;forever #(CLKT / 2) aclk = ~aclk; end// 導入輸入波形文件 // * 注意修改路徑 string work_path = "D:/Onedrive/VivadoPrj/FFT/myFFT/myFFT.srcs/sim_1/new/"; string din_path = {work_path, "sin.txt"};localparam DIN_WIDTH = 24; localparam DATA_NUM = 2816; // 數據量, 也就是txt文件的行數, 如果此參數大于數據行數, 讀取到的內容為不定態 logic signed [DIN_WIDTH-1 : 0] din_wave_data [DATA_NUM]; // 讀取輸入波形數據initial begin$readmemb(din_path, din_wave_data, 0, DATA_NUM-1); // vivado讀取txt文件 endinitial begin// 輸入數據端口初始化din_tdata = '0;din_tlast = 1'b0;din_tvalid = 1'b0;// 配置端口初始化fft_config_tvalid = 1'b0;fft_config_tdata = '0;// 輸出數據端口初始化dout_tready = 1'b1; endint file_din_re; initial beginfile_din_re = $fopen({work_path, "fft_din_re.txt"});#CLKT;for (int i = 0; i < 1024; i++) beginif (i == 1023)din_tlast = 1'b1;din_tvalid = 1'b1;din_tdata = {24'b0, din_wave_data[i]};$fdisplay(file_din_re, "%d", din_wave_data[i]);wait(din_tready == 1'b1) #CLKT;enddin_tvalid = 1'b0;din_tlast = 1'b0;$fclose(file_din_re);#(CLKT * 3000) $stop; end//< 將輸出實部虛部分別寫入兩個文件 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 得到輸出結果,再寫入到txt logic signed [39 : 0] dout_re; assign dout_re = dout_tdata[39 : 0];logic signed [39 : 0] dout_im; assign dout_im = dout_tdata[79 : 40];int file_dout_re; int file_dout_im; initial beginfile_dout_re = $fopen({work_path, "fft_re.txt"});file_dout_im = $fopen({work_path, "fft_im.txt"});wait(dout_tlast) #(CLKT * 2);$fclose(file_dout_re);$fclose(file_dout_im); endalways @(posedge aclk) beginif (dout_tready && dout_tvalid) begin$fdisplay(file_dout_re, "%d", dout_re);$fdisplay(file_dout_im, "%d", dout_im);end end //< 將輸出實部虛部分別寫入兩個文件 ------------------------------------------------------------endmodule5.2.3 繪制頻譜
%{* @Author:Xu Dakang* @Email:XudaKang_up@qq.com* @Date:2021 - 05 - 17 21:56:19* @LastEditors : Xu Dakang* @LastEditTime : 2021-07-05 17:41:41* @Filename:* @Description: %}Fs = 256; % 采樣頻率 T = 1 / Fs;%% matlab根據輸入數據進行fft并繪制頻譜 file_din_re = './fft_din_re.txt'; din_re_id = fopen(file_din_re, 'r'); din_re = fscanf(din_re_id, '%d\n');L = length(din_re); f = Fs * (0:(L / 2)) / L;din_X = din_re + 1i * 0; din_Y = fft(din_X);din_P1 = abs(din_Y) / L; din_P2 = din_P1(1:L / 2 + 1); din_P2(2:end - 1) = 2 * din_P2(2:end - 1); % 除了直流,其余頻率幅值×2figure; set(gcf, 'position', [300 200 1200 600]); subplot 121; plot(f, din_P2); title('matlab fft 頻譜');%% 接收Vivado的fft輸出,繪制頻譜 file_fft_im = './fft_im.txt'; file_fft_re = './fft_re.txt';file_re_id = fopen(file_fft_re, 'r'); file_im_id = fopen(file_fft_im, 'r'); re = fscanf(file_re_id, '%d\n'); im = fscanf(file_im_id, '%d\n');% 繪制單邊頻譜 Y = re + 1i * im; P1 = abs(Y) / L;P2 = [P1(1)', P1(end:-1:(L / 2 + 1))']; % 使用直流幅值與后半部分頻譜 P2(2:end - 1) = 2 * P2(2:end - 1); % 除了直流,其余頻率幅值×2subplot 122; plot(f, P2); title('Vivado fft 頻譜');5.3 仿真波形
5.3.1 輸入波形1
幅值0.7(對應24位2進制補碼整數 2936012),頻率1Hz,采樣頻率256,fft點數1024包含4個周期
對應頻譜:
可見結果還是比較準確的,
5.3.2 輸入波形2
幅值0.7(2936012)頻率1Hz正弦 + 幅值0.9(3774873)頻率2Hz正弦
對應頻譜:
5.3.3 輸入波形3
幅值0.5(2097152)的直流 + 幅值0.7(2936012)頻率1Hz正弦 + 幅值0.8(3355443)頻率10Hz正弦
對應頻譜:
5.4 仿真工程分享
FFT v9.1 Xilinx IP解析 Vivado 2020.2工程.7z
鏈接:https://pan.baidu.com/s/1WuePsCHHfaUwX_PaDkSjWw
提取碼:rvvf
六. 總結
FFT IP的使用比較復雜,而且IP手冊很長且繁瑣,本次提煉了手冊中關于IP使用的一些基本信息,省略了原理性介紹。最后通過仿真理清了此IP的輸入輸出數據格式與時序。
對于位/數反轉排序以及循環前綴插入還沒有深入理解,也沒有使用到,有懂的歡迎評論交流。
總結
以上是生活随笔為你收集整理的Xilinx IP解析之 Fast Fourier Transform(FFT) v9.1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据通信的基本概念
- 下一篇: Cadence原理图导出智能PDF(带图