實戰(zhàn):初始化調(diào)試與工程落地避坑指南)
1. 從一塊板卡說起為什么ZYNQAD9361的組合值得反復(fù)琢磨第一次拿到璞致PZSDR系列板卡的時候我盯著上面那顆ZYNQ和AD9361看了很久。不是因為沒見過而是因為這個組合在寬頻射頻圈子里實在太經(jīng)典了——經(jīng)典到幾乎每個做軟件無線電的團隊都會在某個階段繞回這套架構(gòu)。ZYNQ負責(zé)邏輯與協(xié)議棧AD9361負責(zé)射頻收發(fā)兩者通過LVDS和SPI咬合在一起形成一個從基帶到天線的完整鏈路。但經(jīng)典不等于簡單。我見過太多人在調(diào)試AD9361初始化時卡住0x247寄存器讀出來永遠是0x80CP OVRG HIGH被置位RX PLL死活鎖不上。也見過有人在ZYNQ裸機環(huán)境下折騰USB通信翻遍文檔才發(fā)現(xiàn)libusb的方案在裸機下根本跑不通。這些坑璞致PZSDR系列板卡的用戶大概率都會遇到因為這套硬件把ZYNQ和AD9361的能力都拉滿了暴露出來的細節(jié)自然也更多。這篇內(nèi)容適合誰看如果你正在評估PZSDR系列板卡是否適合你的寬頻射頻項目或者已經(jīng)上手但被初始化、DMA、固化燒寫這些問題絆住了那接下來的內(nèi)容應(yīng)該能幫你省下不少時間。我會從硬件架構(gòu)的底層邏輯講起把ZYNQ和AD9361之間的配合關(guān)系拆開然后落到具體的調(diào)試場景和實操步驟上。不堆砌手冊里能查到的東西重點講那些手冊不會告訴你、但實際調(diào)試中一定會碰到的細節(jié)。2. ZYNQ與AD9361的咬合關(guān)系異構(gòu)架構(gòu)到底異構(gòu)在哪2.1 為什么不是純FPGA或純處理器很多人第一次接觸這個架構(gòu)時會問既然AD9361是射頻前端為什么不用一顆純FPGA來驅(qū)動非要塞一顆ARM核進去這個問題背后其實是對異構(gòu)架構(gòu)本質(zhì)的理解。純FPGA方案的問題在于射頻鏈路的控制面太復(fù)雜了。AD9361有上百個寄存器需要配置增益控制、濾波系數(shù)、采樣率切換、校準(zhǔn)流程這些如果全部用狀態(tài)機在FPGA里實現(xiàn)邏輯資源消耗大不說調(diào)試起來極其痛苦。而純處理器方案的問題正好相反ARM核跑Linux或裸機處理控制面很舒服但基帶數(shù)據(jù)的實時處理根本扛不住采樣率稍微高一點就丟包。ZYNQ的PS-PL架構(gòu)恰好把這兩件事分開了。PL端負責(zé)硬實時的數(shù)據(jù)通路比如ADC/DAC接口、數(shù)字上下變頻、DMA搬運PS端負責(zé)控制面跑協(xié)議棧、做參數(shù)計算、管理AD9361的寄存器配置。兩者通過AXI總線交互各干各擅長的事。璞致PZSDR系列板卡把這個分工做得很清晰PL端的引腳分配和PS端的外設(shè)映射都是圍繞AD9361的接口需求來設(shè)計的。2.2 AD9361的接口時序?qū)YNQ PL端提出的硬約束AD9361和ZYNQ之間的數(shù)據(jù)接口是LVDS差分對分為RX和TX兩組。RX方向AD9361輸出12位I/Q數(shù)據(jù)伴隨幀同步信號和時鐘TX方向反過來ZYNQ輸出數(shù)據(jù)給AD9361。這個接口的時序約束非常緊尤其是DDR模式下數(shù)據(jù)在時鐘的上下沿都要采樣。我在實際調(diào)試中發(fā)現(xiàn)璞致PZSDR板卡的LVDS走線長度匹配做得不錯但如果你自己改板或者換用其他載板一定要用示波器確認眼圖。曾經(jīng)有個項目因為LVDS差分對的走線差了5mm導(dǎo)致RX數(shù)據(jù)偶爾出現(xiàn)位錯誤查了兩天才定位到是PCB走線問題。ZYNQ的SelectIO資源支持IDELAY和ISERDES可以在一定程度上補償時序偏差但前提是你得知道怎么用。SPI接口相對簡單但AD9361的SPI時序有個坑它支持4線模式和3線模式璞致板卡默認是4線。如果你在ZYNQ端配置SPI控制器時沒注意模式匹配會出現(xiàn)讀寫寄存器返回值全為0的情況。這個后面講初始化的時候會詳細說。2.3 時鐘樹設(shè)計一顆晶振如何撐起整個射頻鏈路AD9361需要的外部時鐘只有一顆參考晶振通常是40MHz。這顆時鐘進入AD9361后內(nèi)部PLL會生成射頻本振、采樣時鐘、數(shù)字接口時鐘。但ZYNQ端也需要一個時鐘來同步LVDS接口這個時鐘從哪來璞致PZSDR系列板卡的做法是讓AD9361輸出一個DATA_CLK給ZYNQZYNQ用這個時鐘來采樣RX數(shù)據(jù)并生成TX數(shù)據(jù)。這樣做的好處是收發(fā)時鐘天然同步不需要額外的時鐘域轉(zhuǎn)換。但代價是ZYNQ的PL端邏輯必須在這個時鐘域下工作如果你的基帶處理邏輯跑在另一個時鐘域就得做跨時鐘域處理。我實測下來DATA_CLK的頻率跟采樣率相關(guān)AD9361在不同采樣率下輸出的DATA_CLK頻率不同。如果你在運行時動態(tài)切換采樣率ZYNQ端的邏輯必須能適應(yīng)時鐘頻率的變化否則會出現(xiàn)數(shù)據(jù)錯位。這一點在官方例程里往往被簡化處理了實際項目中需要特別注意。3. AD9361初始化從0x247寄存器讀出0x80說起3.1 初始化流程的完整鏈路AD9361的初始化不是簡單地寫幾個寄存器就完事。完整的流程包括SPI接口驗證、基帶PLL配置、射頻PLL配置、采樣率設(shè)定、濾波器加載、增益模式設(shè)置、校準(zhǔn)觸發(fā)。每一步都有依賴關(guān)系順序錯了后面全亂。我習(xí)慣把初始化分成三個階段。第一階段是SPI通信驗證讀AD9361的版本寄存器確認返回值正確。第二階段是時鐘和PLL配置包括基帶PLL和射頻PLL的鎖定。第三階段是數(shù)據(jù)通路配置包括接口模式、數(shù)據(jù)格式、增益控制。璞致PZSDR板卡的參考設(shè)計里提供了一套初始化序列但那是針對特定頻段和采樣率調(diào)好的。如果你的應(yīng)用需要不同的采樣率或頻段必須自己重新生成初始化參數(shù)。AD9361的官方評估軟件可以導(dǎo)出寄存器配置腳本但那個腳本是給FPGA用的移植到ZYNQ上需要做適配。3.2 0x247寄存器讀出0x80的根因分析0x247是AD9361的校準(zhǔn)控制寄存器之一正常情況下寫入特定值后讀回應(yīng)該反映校準(zhǔn)狀態(tài)。如果你讀出來一直是0x80說明校準(zhǔn)沒有完成或者SPI通信有問題。我排查這個問題的順序是這樣的先確認SPI讀寫是否正常讀一個已知的只讀寄存器比如版本號看返回值對不對。如果版本號都不對那就是SPI接口的問題檢查片選、時鐘極性、相位這些。如果版本號對但0x247不對那就是校準(zhǔn)流程沒走完。常見的原因有幾個一是基帶PLL沒有鎖定導(dǎo)致后續(xù)校準(zhǔn)無法進行二是參考時鐘頻率不對AD9361內(nèi)部PLL算出來的分頻比超出范圍三是初始化序列中遺漏了某個必要的寫操作。我遇到過最隱蔽的一次是SPI時鐘頻率太高AD9361在某個溫度下響應(yīng)不過來降頻到10MHz以下就正常了。3.3 CP OVRG HIGH與RX PLL失鎖的關(guān)聯(lián)CP OVRG是Charge Pump Overrange的縮寫這個標(biāo)志置位說明電荷泵的輸出超出了正常范圍通常意味著PLL環(huán)路濾波器參數(shù)不對或者VCO頻段選擇錯誤。RX PLL失鎖和CP OVRG往往是同時出現(xiàn)的因為電荷泵過載會直接導(dǎo)致環(huán)路無法鎖定。解決這個問題的關(guān)鍵是檢查VCO頻段配置。AD9361的RX PLL有一個VCO工作頻段表你需要根據(jù)目標(biāo)本振頻率選擇正確的頻段。如果頻段選錯了VCO輸出頻率偏離太遠電荷泵就會過載。璞致板卡的參考設(shè)計里通常會給一個頻段對照表但如果你改了參考時鐘頻率這個表就得重新算。我自己的經(jīng)驗是先用AD9361的官方評估軟件算出目標(biāo)頻率對應(yīng)的VCO頻段和分頻比然后手動寫入寄存器不要依賴自動校準(zhǔn)。自動校準(zhǔn)在參考時鐘有偏差的時候容易選錯頻段手動指定反而更可靠。3.4 初始化調(diào)試的實操檢查清單下面這個清單是我調(diào)試AD9361初始化時必查的項目按順序執(zhí)行可以覆蓋大部分問題檢查項正常表現(xiàn)異常處理SPI版本寄存器讀取返回0x0A或0x0B檢查SPI模式、片選、時鐘頻率基帶PLL鎖定鎖定標(biāo)志置位檢查參考時鐘頻率和分頻比射頻PLL鎖定鎖定標(biāo)志置位檢查VCO頻段和電荷泵電流0x247校準(zhǔn)寄存器校準(zhǔn)完成后返回預(yù)期值確認前序步驟全部完成DATA_CLK輸出頻率與采樣率匹配檢查接口模式和時鐘使能RX/TX數(shù)據(jù)通路環(huán)回測試數(shù)據(jù)正確檢查LVDS時序和IDELAY設(shè)置注意每次修改初始化參數(shù)后建議完整復(fù)位AD9361再重新配置不要試圖在運行中修改關(guān)鍵寄存器。AD9361的某些寄存器在PLL鎖定后修改會導(dǎo)致不可預(yù)期的行為。4. ZYNQ端的工程落地從裸機USB到DMA數(shù)據(jù)搬運4.1 裸機USB通信方案的選擇困境ZYNQ的PS端有USB控制器但在裸機環(huán)境下使用USB并不是一件輕松的事。Xilinx的Standalone庫提供了USB控制器的驅(qū)動但只支持Host和Device模式的基本功能要實現(xiàn)自定義的數(shù)據(jù)傳輸協(xié)議需要自己寫類驅(qū)動。我試過基于libusb的方案但在裸機下libusb根本跑不起來因為它依賴操作系統(tǒng)的USB子系統(tǒng)。裸機下可行的方案有兩種一是把ZYNQ的USB控制器配置成Device模式自己實現(xiàn)一個簡單的Bulk傳輸協(xié)議二是用USB Host模式通過EHCI控制器枚舉外接設(shè)備。璞致PZSDR板卡的參考設(shè)計里通常會用USB來做調(diào)試通道或者數(shù)據(jù)回傳。如果你只是傳一些控制命令和低速數(shù)據(jù)Device模式下的Bulk傳輸足夠了。但如果你要傳高速采樣數(shù)據(jù)USB2.0的帶寬理論480Mbps實際300Mbps左右可能不夠用這時候就得考慮用千兆以太網(wǎng)或者PCIe。4.2 ZYNQ DMA的配置邏輯與帶寬計算ZYNQ的PL端有專門的DMA控制器通常用AXI DMA IP核來實現(xiàn)。配置DMA的時候有幾個關(guān)鍵參數(shù)需要計算突發(fā)長度、FIFO深度、數(shù)據(jù)位寬。以AD9361的12位I/Q數(shù)據(jù)為例假設(shè)采樣率是30.72MSPS那么單通道數(shù)據(jù)率是30.72M * 12bit 368.64MbpsI/Q兩路加起來約737Mbps。如果DMA的數(shù)據(jù)位寬是64位時鐘頻率是100MHz理論帶寬是6.4Gbps看起來綽綽有余。但實際中DMA的效率受限于總線仲裁和內(nèi)存帶寬通常只能達到理論值的60%到70%。我一般會留出50%的余量也就是說如果計算出來需要737Mbps我會選擇能提供至少1.5Gbps有效帶寬的配置。AXI DMA的突發(fā)長度設(shè)置也很關(guān)鍵太短會導(dǎo)致總線利用率低太長會增加延遲。實測下來突發(fā)長度設(shè)為64或128比較平衡。4.3 JTAG固化Flash時DDR的必要性這個問題在熱詞里出現(xiàn)了“zynq 7020 使用jtag固化flash時必須使用ddr嗎”。答案是不一定但大多數(shù)情況下需要。ZYNQ的啟動流程是BootROM先運行然后加載FSBLFSBL再加載bitstream和應(yīng)用程序。如果你用JTAG固化FlashFSBL需要把Flash里的數(shù)據(jù)讀到內(nèi)存中再寫入。如果應(yīng)用程序比較大或者bitstream比較大沒有DDR的話內(nèi)存不夠用。但如果你只是固化一個很小的裸機程序ZYNQ的OCMOn-Chip Memory有256KB勉強夠用。不過實際操作中FSBL本身就要占一部分OCM再加上bitstream動輒幾MB沒有DDR幾乎不可能完成固化。所以結(jié)論是固化Flash時DDR是必須的除非你的程序極小且不需要bitstream。璞致PZSDR板卡上通常板載了DDR3容量足夠。固化的時候注意FSBL的配置要正確指定DDR的型號和時序參數(shù)否則FSBL跑不起來JTAG連接會失敗。4.4 Qt與ZYNQ串口庫的編譯適配如果你打算在ZYNQ的Linux系統(tǒng)上跑Qt應(yīng)用并且需要通過串口跟AD9361或者其他外設(shè)通信那Qt的SerialPort庫編譯可能會遇到問題。ZYNQ的ARM核是Cortex-A9屬于ARMv7架構(gòu)Qt的預(yù)編譯包通常不包含這個架構(gòu)。我的做法是在Ubuntu主機上交叉編譯Qt的SerialPort模塊。需要先配置Qt的交叉編譯環(huán)境指定ZYNQ的交叉編譯器通常是arm-xilinx-linux-gnueabi-然后單獨編譯qtserialport模塊。編譯的時候注意把sysroot指向ZYNQ的根文件系統(tǒng)否則頭文件和庫路徑會找不到。編譯完成后把生成的庫文件拷貝到ZYNQ的根文件系統(tǒng)里在Qt應(yīng)用里通過QSerialPort類來操作串口。實測下來ZYNQ的UART控制器在Linux下工作穩(wěn)定波特率最高可以到921600足夠配置AD9361使用。5. 寬頻射頻場景下的實測經(jīng)驗與避坑要點5.1 寬頻覆蓋的增益平坦度問題AD9361的射頻前端覆蓋70MHz到6GHz但并不是整個頻段內(nèi)增益都平坦。在頻段邊緣比如接近70MHz和接近6GHz的地方增益會下降噪聲系數(shù)會惡化。璞致PZSDR板卡的外圍匹配電路是針對寬頻應(yīng)用優(yōu)化的但如果你要覆蓋整個頻段仍然需要在軟件里做增益補償。我的做法是在初始化完成后對目標(biāo)頻段內(nèi)的幾個頻點做增益校準(zhǔn)記錄每個頻點的實際增益然后在基帶處理里做數(shù)字補償。補償?shù)木热Q于校準(zhǔn)點的密度通常每100MHz一個校準(zhǔn)點就夠了。5.2 采樣率切換時的時鐘穩(wěn)定時間AD9361在切換采樣率的時候內(nèi)部PLL需要重新鎖定這個過程需要時間。如果你在運行中頻繁切換采樣率每次切換后都要等待PLL鎖定標(biāo)志置位才能繼續(xù)收發(fā)數(shù)據(jù)。我實測下來鎖定時間在幾十微秒到幾毫秒之間取決于切換的幅度。如果你的應(yīng)用需要快速切換采樣率建議在ZYNQ的PL端做一個狀態(tài)機自動等待PLL鎖定后再使能數(shù)據(jù)通路。不要依賴軟件輪詢因為軟件輪詢的延遲不確定容易丟數(shù)據(jù)。5.3 LVDS接口的IDELAY校準(zhǔn)ZYNQ的SelectIO資源支持IDELAY可以用來調(diào)整LVDS數(shù)據(jù)的采樣相位。AD9361的DATA_CLK和數(shù)據(jù)之間的相位關(guān)系受PCB走線和溫度影響固定延遲不一定能在所有條件下都正確采樣。我通常會在初始化階段做一次IDELAY掃描找到一個穩(wěn)定的采樣窗口。具體做法是發(fā)送已知的測試圖案然后逐步調(diào)整IDELAY值記錄每個值下的誤碼率選擇誤碼率最低的窗口中心作為最終值。這個過程可以在FSBL或者應(yīng)用程序啟動時自動執(zhí)行。5.4 電源噪聲對射頻性能的影響AD9361對電源噪聲非常敏感尤其是射頻PLL的供電。璞致PZSDR板卡在電源設(shè)計上做了濾波但如果你把板卡放在開關(guān)電源附近或者電源本身紋波較大射頻性能會明顯下降。我遇到過一次RX靈敏度突然變差的情況查了半天發(fā)現(xiàn)是實驗室的開關(guān)電源換了型號紋波從10mV漲到了50mV。換回線性電源后立刻恢復(fù)正常。所以如果你在做射頻調(diào)試電源的質(zhì)量一定要保證有條件的話用電池供電做對比測試。6. 從項目落地角度再看這套架構(gòu)的取舍璞致PZSDR系列板卡把ZYNQ和AD9361組合在一起本質(zhì)上是在靈活性和開發(fā)效率之間找了一個平衡點。ZYNQ的PS端讓你可以用軟件的方式處理復(fù)雜的控制邏輯PL端又保留了硬件加速的空間。AD9361則把射頻前端的復(fù)雜度封裝成了一組寄存器接口你不需要懂射頻電路設(shè)計只需要會配置寄存器就能收發(fā)信號。但這套架構(gòu)也有它的邊界。如果你的應(yīng)用需要超過6GHz的頻段AD9361就不夠了得換其他射頻前端。如果你需要極高的實時性比如納秒級的響應(yīng)ZYNQ的PS-PL交互延遲可能成為瓶頸。如果你需要極低的功耗ZYNQ加AD9361的組合功耗在幾瓦級別不適合電池供電的便攜設(shè)備。我在實際項目中選型的時候會先問三個問題頻段覆蓋夠不夠、數(shù)據(jù)吞吐量能不能滿足、功耗和體積有沒有硬約束。這三個問題回答完了基本就能判斷這套架構(gòu)適不適合。對于大多數(shù)寬頻射頻的科研和工業(yè)應(yīng)用來說ZYNQ加AD9361的組合仍然是性價比很高的選擇璞致PZSDR系列板卡把這個組合做成了標(biāo)準(zhǔn)產(chǎn)品省去了自己畫板調(diào)試的麻煩對于快速原型驗證來說很實用。最后分享一個小技巧調(diào)試AD9361的時候手邊常備一份寄存器手冊和官方評估軟件的安裝包。遇到寄存器行為不符合預(yù)期的時候先在評估軟件里復(fù)現(xiàn)確認是配置問題還是硬件問題。評估軟件里能正常工作但板卡上不行的多半是SPI時序或者電源問題兩邊都不行的那就是配置參數(shù)本身有問題。這個排查思路幫我省了很多時間。