計(jì):從時(shí)分復(fù)用到硬件過采樣)
兩年前我第一次在 Xilinx FPGA 上把 FIR 濾波器跑起來那時(shí)還是一個(gè)通道拿著 MATLAB 算好的系數(shù)往 FIR Compiler IP 里面一扔仿真一跑波形對(duì)了就覺得萬事大吉。等到后來項(xiàng)目變成四通道同步采集我才發(fā)現(xiàn)事情沒那么簡(jiǎn)單通道數(shù)從 1 改成 4 只是最表面的操作背后牽涉到數(shù)據(jù)時(shí)序、硬件過采樣、多通道 AXI4-Stream 交織格式、濾波延遲對(duì)齊甚至資源優(yōu)化和時(shí)序收斂。這篇文章就圍繞“Xilinx FIR IP 核的多通道濾波器設(shè)計(jì)”這個(gè)主題把我實(shí)際踩過坑、反復(fù)看手冊(cè)才搞清楚的內(nèi)容從零到一完整過一遍。無論你是在做多路 ADC 預(yù)處理、通信基帶濾波還是軟件無線電的多通道分集接收這套思路基本都能直接套用。1. 多通道 FIR 濾波器需求與設(shè)計(jì)思路1.1 FIR 的基本結(jié)構(gòu)和為什么多通道不是簡(jiǎn)單的“復(fù)制粘貼”FIR 濾波器的本質(zhì)就是一組帶延遲的乘加運(yùn)算。對(duì)第 n 個(gè)輸出采樣點(diǎn)來說它等于輸入序列和濾波器系數(shù)序列做卷積y[n] Σ h[k] · x[n-k]其中 k 從 0 到 N-1N 就是濾波器的抽頭數(shù)。舉個(gè)容易理解的例子如果 N64那么每產(chǎn)生一個(gè)輸出樣本都要完成 64 次乘法和 63 次加法。用 FPGA 做實(shí)現(xiàn)時(shí)思路無非兩種一是把 64 個(gè)乘法器并行擺開一個(gè)時(shí)鐘周期出 64 次乘加結(jié)果二是用一個(gè)乘法器在時(shí)鐘節(jié)拍里循環(huán)使用N 個(gè)時(shí)鐘周期出一個(gè)輸出。前者吞吐率高但 DSP48 資源消耗直接就是 64 個(gè)起步后者資源省但對(duì)時(shí)鐘頻率要求更高。單通道的時(shí)候這個(gè)選擇比較簡(jiǎn)單資源不夠就多花幾個(gè)周期時(shí)序緊張就多鋪幾個(gè)乘法器。多通道就不一樣了四路信號(hào)同時(shí)采樣通道之間還要保證齊套性。很多人第一反應(yīng)是把 FIR IP 例化四次一個(gè)通道一個(gè) IP。這種方法不是不能用但相當(dāng)于把四個(gè)獨(dú)立的濾波器塞進(jìn)芯片里DSP48、LUT、寄存器成本直接翻四倍。而 FIR Compiler IP 本身提供的多通道模式恰恰就是專門解決這種場(chǎng)景的它允許你在同一個(gè)濾波核內(nèi)部用時(shí)分復(fù)用方式處理多個(gè)通道共享大量算術(shù)資源。所以我的觀點(diǎn)是多路 FIR 設(shè)計(jì)首先應(yīng)該考慮用官方 IP 的多通道能力而不是簡(jiǎn)單復(fù)制單通道模塊。這不是為了省事而是在面積、功耗、時(shí)序上都有明顯收益。當(dāng)然也要清楚多通道模式依賴時(shí)鐘資源和通道順序管理后面我會(huì)詳細(xì)展開。1.2 時(shí)分復(fù)用FIR 多通道實(shí)現(xiàn)的核心機(jī)制FIR Compiler IP 的多通道模式靠的是時(shí)分復(fù)用也就是讓多個(gè)通道的數(shù)據(jù)輪流使用同一套乘加器。打個(gè)比方單通道 FIR 是一個(gè)柜臺(tái)只服務(wù)一個(gè)客戶多通道 FIR 是同一個(gè)柜臺(tái)四個(gè)客戶按順序輪流辦業(yè)務(wù)。只要每個(gè)人的業(yè)務(wù)都足夠快外部看起來就像四人同時(shí)被服務(wù)一樣。具體到 FPGA 里這個(gè)“業(yè)務(wù)速度”由系統(tǒng)時(shí)鐘和采樣頻率的比值決定。Xilinx 手冊(cè)里把這個(gè)比值叫“硬件過采樣率”Hardware Over-sample Rate。如果系統(tǒng)時(shí)鐘是 100MHz每個(gè)通道的采樣率是 1MHz四個(gè)通道合在一起每秒需要處理四百萬個(gè)樣本。用 100MHz 的時(shí)鐘去處理每個(gè)樣本的窗口期里有 25 個(gè)時(shí)鐘周期可用這個(gè) 25 就是做過采樣計(jì)算后得到的余量。FIR 要完成 64 次乘加在 25 個(gè)時(shí)鐘周期內(nèi)做不完于是 IP 會(huì)適當(dāng)增加乘法器并行度直到滿足時(shí)序要求。這里有一個(gè)實(shí)際工程里很關(guān)鍵的概念硬件過采樣率決定了共享程度和乘法器數(shù)量的折中。過采樣率越高意味著每個(gè)樣本可用的時(shí)鐘周期越多IP 越傾向于用一個(gè)或少數(shù)幾個(gè)乘法器串行完成累加DSP48 用得就少過采樣率不足那就只能堆并行乘法器。設(shè)置 IP 時(shí)你可以手動(dòng)指定過采樣率也可以讓它根據(jù)“時(shí)鐘頻率”和“采樣頻率”自動(dòng)計(jì)算。我建議大多數(shù)場(chǎng)景下先自動(dòng)計(jì)算跑完綜合看資源報(bào)告再回頭微調(diào)。多通道和時(shí)分復(fù)用是一對(duì)天然的搭檔。每多一個(gè)通道需要處理的樣本量就多一倍留給每個(gè)樣本的時(shí)鐘周期就少一半乘法器并行度就得提上來。這也是為什么多通道 FIR 的資源消耗并不是“按通道數(shù)線性增長(zhǎng)那么夸張”而是階梯式上漲只要樣本速率和系統(tǒng)時(shí)鐘之間還有富余通道增加可能不增加任何 DSP48。1.3 一個(gè)具體的設(shè)計(jì)指標(biāo)四通道低通濾波器我把這次設(shè)計(jì)的初始需求定成一個(gè)比較典型的工程場(chǎng)景后面所有配置都圍繞它展開通道數(shù)4 通道輸入數(shù)據(jù)位寬16 bit帶符號(hào)補(bǔ)碼每個(gè)通道采樣率1 MHz系統(tǒng)時(shí)鐘100 MHz濾波需求低通濾波器截止頻率 100 kHz阻帶衰減不小于 60 dB目標(biāo)實(shí)現(xiàn)器件Xilinx 7 系列或者 UltraScale 都行這里不限定具體型號(hào)用 MATLAB 的firls或fir1設(shè)計(jì)得到大約 64 階的濾波器系數(shù)量化到 16 bit保存成 COE 文件。為什么選 64 抽頭因?yàn)樵谶@個(gè)指標(biāo)下64 抽頭的阻帶衰減和過渡帶寬度已經(jīng)比較合適再多抽頭就意味著更多 DSP48而在 1MHz 采樣率下 16 抽頭和 64 抽頭的實(shí)時(shí)性壓力其實(shí)差不多。有了這個(gè)明確的小目標(biāo)之后接下來最值得花時(shí)間的是搞清楚 FIR Compiler IP 內(nèi)部的各種配置項(xiàng)到底是怎么影響實(shí)現(xiàn)的。我們先把原理講透再去 Vivado 里操作。2. FIR Compiler IP 的架構(gòu)與關(guān)鍵配置概念2.1 IP 支持哪幾種濾波器模式FIR Compiler IP 在 Filter Options 頁面里會(huì)先讓你選濾波器類型。常見的有 Single Rate、Interpolated、Decimation、Interpolation以及 Xilinx 手冊(cè)里專門提到的 Multi-phase 多相濾波器。Single Rate 是標(biāo)準(zhǔn)配置輸入輸出采樣率相同我們做四通道低通就屬于這一類。Interpolation 和 Decimation 則是在濾波同時(shí)改變采樣率比如把 48kHz 音頻插值到 192kHz或者在做數(shù)字下變頻時(shí)把 100MHz 的數(shù)據(jù)抽取到 10MHz。這類場(chǎng)景下你可能需要配合多相結(jié)構(gòu)來降低運(yùn)算壓力。我見過不少新手在做一個(gè)帶抽取的濾波器時(shí)直接在 FIR IP 里選 Decimation然后把系數(shù)文件一股腦塞進(jìn)去結(jié)果輸出數(shù)據(jù)總是不對(duì)。原因是抽取模式下IP 對(duì)輸入數(shù)據(jù)的時(shí)間槽和輸出樣本的對(duì)應(yīng)關(guān)系有嚴(yán)格規(guī)定而且通常會(huì)要求你先做多相分解再配置。換個(gè)更省心的做法是先用一個(gè)普通單速率 FIR 濾波再單獨(dú)用另一個(gè)模塊做抽取兩個(gè) IP 分開設(shè)計(jì)。雖然資源多一點(diǎn)但調(diào)試復(fù)雜度低很多。Multi-phase模式才是 FIR IP 真正體現(xiàn)“多相濾波”優(yōu)勢(shì)的地方。所謂多相分解就是把一個(gè)大濾波器拆成若干個(gè)小濾波器并行處理。例如把一個(gè) 64 抽頭的低通濾波器按 4 相位分解變成 4 組每組 16 抽頭的子濾波器每個(gè)子濾波器在多相輸入序列上分別運(yùn)行再把結(jié)果重新交織回原始速率。這樣做的直接好處是每個(gè)乘法器的工作時(shí)鐘可以降低到原來的 1/4 或者資源占用大幅下降。Xilinx 的 FIR Compiler 在處理多通道和高速率濾波器時(shí)內(nèi)部也會(huì)自動(dòng)采用類似多相展開的結(jié)構(gòu)所以你在 IP 配置界面看到“multiphase”時(shí)不必慌張它只是把你要求的濾波器和時(shí)鐘關(guān)系在底層拆成了更聰明的實(shí)現(xiàn)。2.2 多通道模式下的系數(shù)與通道關(guān)系FIR Compiler 里關(guān)于系數(shù)的配置通常有幾層概念系數(shù)集合、每個(gè)集合里的系數(shù)個(gè)數(shù)、通道如何使用這些集合。對(duì)于多數(shù)標(biāo)準(zhǔn)應(yīng)用濾波器抽頭數(shù)就是系數(shù)集合的個(gè)數(shù)比如 64 個(gè)系數(shù)算一組。配置里允許你有多個(gè) Coefficient Set并且可以給不同通道分配不同集合。也就是說通道和系數(shù)不是必須一一對(duì)應(yīng)的。你可以讓四個(gè)通道共用同一組低通系數(shù)也可以讓通道 0 和通道 1 用低通系數(shù)通道 2 和通道 3 用高通系數(shù)甚至可以給四個(gè)通道分別配置四組完全不同的系數(shù)。這個(gè)能力在做多頻段、多速率系統(tǒng)時(shí)非常有用。但代價(jià)也很明顯多組系數(shù)意味著 IP 內(nèi)部要有額外的存儲(chǔ)和切換邏輯資源占用會(huì)上升而且對(duì)接口控制時(shí)序的要求更高。我的建議是如果所有通道的濾波特性一致那就老老實(shí)實(shí)用一組系數(shù)讓所有通道共享。這樣既簡(jiǎn)單又省資源。只有當(dāng)指標(biāo)明確要求每個(gè)通道獨(dú)立濾波時(shí)才去碰多系數(shù)集合。還有一個(gè)容易被忽略的選項(xiàng)Reloadable Coefficients也就是系數(shù)可動(dòng)態(tài)更新。打開這個(gè)選項(xiàng)后軟件處理器可以通過 AXI4-Lite 接口在運(yùn)行中改寫濾波器系數(shù)適合做自適應(yīng)濾波或頻率切換。但開啟后IP 的面積和時(shí)序約束都會(huì)變復(fù)雜。如果產(chǎn)品階段不需要重新配系數(shù)我建議關(guān)閉這個(gè)選項(xiàng)把系數(shù)固定死在 COE 文件里。2.3 多相濾波架構(gòu)與高速濾波場(chǎng)景“多相濾波”這個(gè)詞在網(wǎng)絡(luò)論壇和 Xilinx 資料里出現(xiàn)頻率很高但它不是 FIR Compiler 特有的新特性而是一種信號(hào)處理優(yōu)化方法。它的核心思想是濾波器系數(shù)不是從頭到尾串行處理而是按相位重新排列成多個(gè)子濾波器。舉一個(gè)具體數(shù)字某系統(tǒng)需要采樣率 200MSPS64 抽頭 FIR系統(tǒng)時(shí)鐘剛好也是 200MHz。如果直接做每 5ns 內(nèi)必須完成 64 次乘加硬件壓力很大。如果做 4 相分解每一相子濾波器只處理 16 個(gè)抽頭乘法器的數(shù)據(jù)率其實(shí)不需要一下子高到原始采樣率只要最后把四個(gè)子濾波器輸出交織起來就能還原出 200MSPS 的濾波結(jié)果。這種技術(shù)也經(jīng)常配合插值/抽取使用所以叫多相插值、多相抽取。對(duì) FIR Compiler IP 來說你不需要手動(dòng)寫多相分解的代碼只需要在配置里給出采樣率、系統(tǒng)時(shí)鐘和濾波器系數(shù)它會(huì)自動(dòng)判斷是否采用多相結(jié)構(gòu)。但在多通道項(xiàng)目里我還是建議你腦子里有一張“相位圖”當(dāng)采樣率很高而系統(tǒng)時(shí)鐘不夠快時(shí)IP 內(nèi)部必然會(huì)把運(yùn)算拆到多個(gè)并行數(shù)據(jù)路徑上這時(shí)通道交織順序、輸出對(duì)齊關(guān)系都會(huì)發(fā)生變化調(diào)試時(shí)不能用單通道的思維去看波形。如果你非要手動(dòng)做多相濾波通常需要先把系數(shù)分解成多組然后例化多個(gè) FIR Compiler 并自己做輸出交織。這種事情只在極端定制場(chǎng)景下才有必要平常直接用 IP 自帶的優(yōu)化就行。這里我主要是提醒大家看到“多相濾波”不要頭大它反而是你處理高速 FIR 的救星。3. Vivado 實(shí)操?gòu)膭?chuàng)建工程到跑通 FIR IP 核3.1 創(chuàng)建 IP 并導(dǎo)入濾波器系數(shù)實(shí)際操作是從 Vivado 的 IP Catalog 開始的。在項(xiàng)目管理器里搜索 FIR選擇 FIR Compiler雙擊創(chuàng)建 IP命名成fir_multi_ch。打開配置界面后第一頁是 Filter Options。Filter Type 選 Single RateNumber of Channels 設(shè)成 4。這一頁還會(huì)要求你選擇過采樣率來源默認(rèn)是“Determined by Frequency Specification”。我們暫時(shí)不改它跳到后面填時(shí)鐘頻率和采樣頻率。再往下是系數(shù)部分。你可以手動(dòng)一個(gè)個(gè)填但工程上一般不這么干。先用 MATLAB 生成系數(shù)然后導(dǎo)出成.coe文件。COE 文件的格式很簡(jiǎn)單radix16; coefdata04A3, F501, 0032, FF06, 0B5F, ...上面只是示意實(shí)際系數(shù)要根據(jù)濾波器設(shè)計(jì)結(jié)果填寫。在 FIR Compiler 界面選擇 Load Coefficients載入這個(gè) COE 文件后IP 會(huì)自動(dòng)識(shí)別抽頭數(shù)并在界面上畫出幅度響應(yīng)預(yù)覽。這一步最好養(yǎng)成習(xí)慣配置完后先看一眼幅度響應(yīng)曲線確認(rèn)帶內(nèi)平坦、阻帶衰減符合指標(biāo)再去生成例化代碼。我遇到過同事載入系數(shù)后沒檢查結(jié)果系數(shù)導(dǎo)出時(shí)本來就有格式問題到板子上才折騰半天才發(fā)現(xiàn)是系數(shù)反了。如果需要讓多個(gè)通道使用不同系數(shù)就在系數(shù)頁面里把 Coefficient Sets 數(shù)量改成通道數(shù)再分別加載不同的 COE 文件。我前面建議過初期盡量一組系數(shù)。3.2 通道規(guī)格、位寬與輸出量化設(shè)置接下來是 Channel Specification 和 Sample Specification。這里有幾個(gè)選項(xiàng)必須認(rèn)真選Input Sample Type選 Signed絕大多數(shù) ADC 輸出的模擬采樣值是帶符號(hào)的。Input Width16。如果輸入是 14 bit 或 12 bit我建議仍然按 16 bit 接進(jìn) IP然后在高位對(duì)齊低位補(bǔ)零。Coefficient Width選 16。Output Width默認(rèn) FP 全精度會(huì)給出一個(gè)較寬的位寬。如果后面接的模塊不需要這么多位可以改成自定義位寬。輸出位寬導(dǎo)致“數(shù)據(jù)看起來不對(duì)”是最常見的坑之一尤其是當(dāng)你選擇了 Truncation 而不是 Round 時(shí)輸出會(huì)比全精度結(jié)果在幅度上低一些波形形狀沒有大變化但和 MATLAB 仿真結(jié)果對(duì)不上的時(shí)候往往就是量化策略造成的。仿真驗(yàn)證階段我建議直接選 Full Precision先保證算法鏈路正確再根據(jù)最終位寬需求做截?cái)嗷蛏崛搿ample Frequency 填 1MHzClock Frequency 填 100MHzIP 會(huì)自動(dòng)算出每通道的硬件過采樣率。四通道模式下總樣本率為 4MHz100MHz 系統(tǒng)時(shí)鐘對(duì)應(yīng)每個(gè)樣本窗口有 25 個(gè)周期所以對(duì)于 64 抽頭濾波器它會(huì)在內(nèi)部用 3 到 4 個(gè)乘法器把 64 次乘加分?jǐn)偼?。如果你在這里發(fā)現(xiàn) IP 給的 DSP48 估算數(shù)量遠(yuǎn)超預(yù)期可以加大系統(tǒng)時(shí)鐘頻率或者減小抽頭數(shù)也可以在硬件過采樣率上做合并調(diào)整。反過來如果資源很寬裕但時(shí)序吃緊可以降低過采樣率讓更多 DSP 并行工作換取更短的組合邏輯鏈。3.3 AXI4-Stream 接口配置與連接完整數(shù)據(jù)通路FIR Compiler IP 外部接口默認(rèn)采用 AXI4-Stream這在現(xiàn)代 Xilinx 設(shè)計(jì)里是事實(shí)標(biāo)準(zhǔn)前端數(shù)據(jù)源、后端的 DMA 或 FFT IP 核全都用這套協(xié)議。AXI4-Stream 的四個(gè)基礎(chǔ)信號(hào)是s_axis_data_tvalid主設(shè)備告訴從設(shè)備本次送的數(shù)據(jù)有效。s_axis_data_tready從設(shè)備告訴主設(shè)備當(dāng)前可以接收數(shù)據(jù)。s_axis_data_tdata實(shí)際數(shù)據(jù)總線。s_axis_data_tlast幀結(jié)束標(biāo)志用于多通道多幀場(chǎng)景。需要特別注意FIR Compiler 的多通道數(shù)據(jù)不是把四個(gè)通道分別放在tdata的不同 bit 段里而是在多個(gè)時(shí)鐘周期里按通道順序依次送出。這是很多人最容易搞錯(cuò)的地方。正確格式是第一個(gè)有效周期里tdata是通道 0 的樣本第二個(gè)周期是通道 1 的樣本第三個(gè)是通道 2第四個(gè)是通道 3然后tlast拉高表示一幀結(jié)束下一組樣本又從通道 0 開始。整個(gè)過程中tvalid可以一直保持高電平tready由 IP 決定。在頂層代碼里例化 IP 時(shí)復(fù)位信號(hào)通常叫s_axis_aresetn低電平有效。如果你用的是高有效復(fù)位一定自己取反。時(shí)鐘信號(hào)是s_axis_aclk和整個(gè)邏輯域的時(shí)鐘接在一起即可。輸出端的m_axis_data_tdata同樣按通道順序交織m_axis_data_tvalid拉高時(shí)表示輸出數(shù)據(jù)有效。此外 IP 還會(huì)給出m_axis_data_sync信號(hào)這個(gè)信號(hào)在每幀的第一個(gè)有效輸出周期拉高用來標(biāo)記通道 0 對(duì)齊位置后面做多通道校驗(yàn)時(shí)特別好用。如果你的數(shù)據(jù)源是某個(gè) ADC 接口 IP那大概率它已經(jīng)按 AXI4-Stream 輸出你只需要確保它的通道排列順序和 FIR IP 期望的通道排列順序一致。如果順序不一致在 FIR 前面加一個(gè)重新排序的小模塊比在 FIR 后面補(bǔ)救要簡(jiǎn)單得多因?yàn)?FIR 有延遲通道錯(cuò)位在輸出端不太好查。4. 多通道仿真驗(yàn)證讓每一路數(shù)據(jù)都對(duì)齊4.1 Testbench 怎么生成四通道交錯(cuò)數(shù)據(jù)仿真驗(yàn)證是整個(gè)多通道 FIR 設(shè)計(jì)里最見功力的一步。單通道可以隨便給個(gè)正弦波看看幅度幅度對(duì)不對(duì)就完事。四通道則要先在 Testbench 里正確生成按通道交織的數(shù)據(jù)序列。簡(jiǎn)單來說Testbench 要模擬一個(gè)數(shù)據(jù)源每四個(gè)時(shí)鐘周期組成一個(gè)樣本幀依次發(fā)送通道 0 到通道 3 的樣本。下面是一段很常用的行為級(jí)驅(qū)動(dòng)代碼可以直接拿去改reg [15:0] sample_mem [0:3]; reg [15:0] sample_axis_tdata; reg sample_axis_tvalid; reg sample_axis_tlast; integer ch_index; always (posedge clk) begin if (!rst_n) begin ch_index 0; sample_axis_tvalid 1b0; sample_axis_tlast 1b0; end else if (s_axis_tready) begin sample_axis_tvalid 1b1; sample_axis_tdata sample_mem[ch_index]; sample_axis_tlast (ch_index 3); if (ch_index 3) ch_index 0; else ch_index ch_index 1; end end我這個(gè)寫法是用一個(gè)計(jì)數(shù)器在 0、1、2、3 之間循環(huán)tlast在通道 3 時(shí)拉高。你每次更新sample_mem的內(nèi)容模擬四路 ADC 分別送新樣本就行。實(shí)際工程中 ADC 的采樣時(shí)鐘如果和 FIR 的系統(tǒng)時(shí)鐘不一致你還需要做異步 FIFO 跨時(shí)鐘不能簡(jiǎn)單用寄存器的時(shí)序邏輯驅(qū)動(dòng)。有了正確的激勵(lì)后仿真里最先看的是s_axis_tready。如果這個(gè)信號(hào)始終為低說明 IP 沒有進(jìn)入可接收狀態(tài)常見原因是復(fù)位沒有正確釋放或者是時(shí)鐘沒有跑起來。先把這兩個(gè)基本問題排除再去分析濾波結(jié)果。4.2 輸出檢查延遲、通道順序和 sync 信號(hào)FIR 濾波器本身有加法器樹和流水線延遲再加上多通道時(shí)分復(fù)用輸出相對(duì)輸入會(huì)有明顯延遲。調(diào)試的第一步不是拿第一個(gè)輸出和第一個(gè)輸入對(duì)上而是先找m_axis_data_sync信號(hào)。這個(gè)信號(hào)拉高對(duì)應(yīng)的輸出樣本就是通道 0 當(dāng)前幀的第一個(gè)樣本。對(duì)四通道設(shè)計(jì)建議同時(shí)抓四路解交織后的通道數(shù)據(jù)和 sync 信號(hào)的相對(duì)關(guān)系。在波形窗口里用一個(gè) generate 或手寫一個(gè)解交織寄存器組把四個(gè)通道分別緩存起來。然后檢查每個(gè)通道的波形形狀是否正常低通濾波后不應(yīng)出現(xiàn)高頻毛刺。四個(gè)通道的基帶信號(hào)相位是否和預(yù)期一致。如果輸入是同一信號(hào)源四路輸出應(yīng)該幾乎同步只有固定群延遲。通道 0 的延遲就是 IP 的固有延遲可以在 vivado 的 IP 配置摘要里查到 latency 估算用它來校準(zhǔn)你的解交織邏輯。如果發(fā)現(xiàn)通道 1 的輸出和通道 0 一樣但通道 2、通道 3 沒波形八成不是 FIR IP 的問題而是你 Testbench 的通道數(shù)據(jù)本來就沒送全。先檢查sample_mem四個(gè)地址是否有更新再看tlast是否按幀結(jié)束。4.3 仿真中常見的三個(gè)“假故障”我總結(jié)過仿真多通道 FIR 時(shí)最容易遇到的三個(gè)異常它們表面上像是濾波壞了其實(shí)都出在接口或測(cè)試環(huán)境上第一個(gè)是“輸出全是常量”。原因通常是s_axis_data_tvalid一直為低IP 內(nèi)部沒有新的樣本進(jìn)來輸出自然保持不變。這種問題可以抓 IP 的s_axis_tready和tvalid如果握手一直沒有成立就是數(shù)據(jù)源沒發(fā)對(duì)。第二個(gè)是“輸出波形有跳變但不平滑”。這種一般發(fā)生在輸入樣本隨機(jī)數(shù)生成或者數(shù)據(jù)位寬沒有對(duì)齊時(shí)。重點(diǎn)檢查發(fā)送端的tdata是否按補(bǔ)碼格式送數(shù)。如果本來是帶符號(hào)的 ADC 采樣值你用無符號(hào)整數(shù)去驅(qū)動(dòng)波形可能就出現(xiàn)一條類似“削頂”的跳變。第三個(gè)是“通道順序錯(cuò)亂”。你以為通道 0 的輸出在tdata的第一段于是從低位解交織結(jié)果取出來的是通道 1 的數(shù)據(jù)。這種問題很難通過波形輪廓看出來必須用四個(gè)不同的正弦波頻率做激勵(lì)再在接收端分別檢查頻率成分。只要每個(gè)通道拿到的信號(hào)頻率和激勵(lì)聲明相符就能確認(rèn)通道順序正確。5. 資源、時(shí)序與工程化落地經(jīng)驗(yàn)5.1 位寬選擇和 DSP48 資源估算FIR 濾波器的硬件開銷大頭永遠(yuǎn)是 DSP48 乘法器。一個(gè) 16bit×16bit 的乘加需要一個(gè) DSP48這個(gè)基本是鐵的定律。64 抽頭的單通道 FIR理想情況下至少需要 64 個(gè)乘法器。如果濾波器系數(shù)對(duì)稱即 h[k]h[N-1-k]IP 會(huì)做系數(shù)折疊把乘法器需求砍掉近一半只需要約 33 個(gè)乘法器。多通道不代表乘法器數(shù)量乘以通道數(shù)。四通道 64 抽頭如果系統(tǒng)時(shí)鐘足夠快使每個(gè)通道都能時(shí)分復(fù)用同一套乘加器DSP48 可能只比單通道多一點(diǎn)點(diǎn)甚至持平。你可以通過調(diào)整硬件過采樣率來控制這個(gè)比例。過采樣率高資源少但時(shí)鐘周期緊過采樣率低資源多但組合邏輯輕松一些。輸出位寬對(duì)面積的影響沒有 DSP48 那么強(qiáng)但也不容小覷。如果選擇 32bit 全精度輸出后面接一級(jí)更寬的累加邏輯面積會(huì)明顯上升。我的習(xí)慣是在系統(tǒng)鏈路允許的前提下盡早截位但要在截位之前先保留足夠位數(shù)避免帶內(nèi)信號(hào)的動(dòng)態(tài)范圍被壓縮。具體截到多少位要結(jié)合 ADC 有效位數(shù)和最終信噪比指標(biāo)來決定。5.2 時(shí)序收斂與跨時(shí)鐘域處理多通道 FIR 設(shè)計(jì)本身比較規(guī)矩時(shí)序問題更多出在它和數(shù)據(jù)源、數(shù)據(jù)宿的接口邊界上。系統(tǒng)時(shí)鐘設(shè)為 100MHzFIR 內(nèi)部是干凈的同步時(shí)序加上寄存器級(jí)數(shù)很多一般不會(huì)成為關(guān)鍵路徑。反而是在多路 ADC 采樣數(shù)據(jù)和 FIR 的時(shí)鐘域交匯處如果直接拿異步信號(hào)打拍綜合工具會(huì)報(bào)告一堆時(shí)序違例。常見解決辦法是在 FIR 之前加異步 FIFO 或使用 Xilinx 原語做跨時(shí)鐘域處理。如果 ADC 數(shù)據(jù)是 4 通道并行總線先把四路信號(hào)各自同步到系統(tǒng)時(shí)鐘域再組裝成 AXI4-Stream 交織格式送進(jìn) FIR。這一步無論如何不能省省了不僅時(shí)序難收斂板級(jí)調(diào)試時(shí)還會(huì)看到隨機(jī)毛刺。后級(jí)如果接的是 DMA 或 PCIe 之類的接口 IP你還要注意 AXI4-Stream 的帶寬匹配。4 通道 × 1MHz × 32bit 輸出大約是 16MB/s 左右PCIe DMA 完全沒壓力。但如果你把采樣率提高幾十倍那 DMA 吞吐和 FIFO 深度就要重新評(píng)估FIR 本身反而不會(huì)成為瓶頸。5.3 前后端接口、DMA/高速收發(fā)器聯(lián)調(diào)的實(shí)際體會(huì)在實(shí)際項(xiàng)目里多通道 FIR 很少是獨(dú)立存在的。前面可能接 JESD204B 的高速 ADC后面可能接 FFT IP 或 PCIe DMA。你的 FIR 設(shè)計(jì)最終要能塞進(jìn)這條大鏈里。我吃過一個(gè)虧把 FIR IP 的 AXI4-Stream 輸出直接接到 DMA 的輸入通道順序沒仔細(xì)查結(jié)果上位機(jī)里看到的四個(gè)通道數(shù)據(jù)其實(shí)是錯(cuò)位的。后來修改 FIR 輸出后的解交織模塊才解決。所以在你把 FIR 集成進(jìn)整體系統(tǒng)前一定先單獨(dú)做多通道仿真把通道序號(hào)在硬件上驗(yàn)證明白。等到和 DMA 聯(lián)調(diào)之后再發(fā)現(xiàn)問題定位成本就高多了。另外如果項(xiàng)目里有 Aurora、SGMII 這類高速收發(fā)器把數(shù)據(jù)遠(yuǎn)距離傳輸通道交織格式往往會(huì)受到傳輸層幀格式的影響。比如你的傳輸協(xié)議每次傳一個(gè) AXI4-Stream 幀而幀里剛好包含四通道樣本那 FIR 的 tlast 就要和傳輸層的幀邊界對(duì)齊。這種對(duì)齊問題在系統(tǒng)調(diào)試階段特別煩人但只要仿真階段把 tlast 的時(shí)序校準(zhǔn)好上板后就只是接線的活了。最后再分享一個(gè)經(jīng)驗(yàn)做多通道 FIR 項(xiàng)目無論多忙我都會(huì)先把四路輸入用四種不同頻率的測(cè)試信號(hào)跑一遍行為仿真再跑一遍綜合后仿真最后才上板。前兩步能解決絕大多數(shù)邏輯問題第三步往往只驗(yàn)證接口電氣信號(hào)和真實(shí)噪聲。這套流程看起來繁瑣但比板級(jí)示波器現(xiàn)查波形快得多。等你真的遇到了又玄又難查的通道錯(cuò)亂問題就會(huì)感謝當(dāng)時(shí)這個(gè)小小的習(xí)慣。