戰(zhàn):BPSK調(diào)制解調(diào)與卷積編解碼完整鏈路設(shè)計(jì))
簡(jiǎn)介這是基于BPSK調(diào)制解調(diào)與卷積編解碼的FPGA工程源碼采用Vivado2020.1開(kāi)發(fā)并已通過(guò)測(cè)試適合通信相關(guān)專(zhuān)業(yè)學(xué)生、FPGA開(kāi)發(fā)者以及需要搭建數(shù)字基帶收發(fā)驗(yàn)證平臺(tái)的工程師。壓縮包共包含1691個(gè)文件約88.43MB其中除了7個(gè)Verilog源文件與5個(gè)IP核配置外還包括大量VHDL/Verilog源碼、xdc約束、xci配置、do/sh/bat仿真腳本、log日志與txt說(shuō)明等工程結(jié)構(gòu)清晰便于直接打開(kāi)、仿真與綜合。目前已有433人學(xué)習(xí)下載說(shuō)明該方案在通信系統(tǒng)課程設(shè)計(jì)與FPGA實(shí)現(xiàn)方面有一定關(guān)注度。工程內(nèi)的模塊劃分明確配合博客中的方案介紹讀者可以快速理解BPSK調(diào)制解調(diào)與卷積編解碼在FPGA上的實(shí)現(xiàn)思路根據(jù)仿真腳本和約束文件進(jìn)行復(fù)現(xiàn)也可針對(duì)具體參數(shù)做修改或二次開(kāi)發(fā)適合課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)及通信FPGA入門(mén)實(shí)踐。1. 項(xiàng)目概述與設(shè)計(jì)思路1.1 這個(gè)工程解決什么問(wèn)題最近在整理一套基于BPSK調(diào)制解調(diào)與卷積編解碼的完整FPGA工程發(fā)射鏈路從隨機(jī)數(shù)據(jù)源開(kāi)始依次經(jīng)過(guò)卷積編碼、BPSK映射、基帶成型、中頻調(diào)制最終形成可供DAC輸出的中頻信號(hào)接收鏈路則從ADC采樣數(shù)據(jù)出發(fā)依次完成數(shù)字下變頻、匹配濾波、載波同步、定時(shí)同步、數(shù)據(jù)判決最后用Viterbi譯碼還原出原始信息比特。這條鏈路是數(shù)字通信物理層最經(jīng)典、最基礎(chǔ)的一條完整通路把BPSK調(diào)制解調(diào)和卷積編解碼這兩塊獨(dú)立的知識(shí)點(diǎn)真正串成了閉環(huán)。這個(gè)工程適合三類(lèi)人看。一是正在做無(wú)線(xiàn)通信相關(guān)FPGA開(kāi)發(fā)的工程師需要一套能完整復(fù)現(xiàn)的收發(fā)鏈路參考二是通信工程或電子工程專(zhuān)業(yè)的學(xué)生做課設(shè)或者畢業(yè)設(shè)計(jì)時(shí)可以直接在這個(gè)源碼基礎(chǔ)上改參數(shù)、加模塊三是對(duì)同步算法、誤碼性能如何在硬件上落地感興趣的同學(xué)。整個(gè)工程不依賴(lài)特定廠(chǎng)商的高級(jí)加密IP代碼盡量手工RTL實(shí)現(xiàn)方便理解和二次修改這是這套源碼最核心的定位。1.2 關(guān)鍵參數(shù)選型先給出整套系統(tǒng)的核心參數(shù)后續(xù)模塊都圍繞這些參數(shù)展開(kāi)參數(shù)數(shù)值說(shuō)明符號(hào)速率1 MspsBPSK一個(gè)符號(hào)對(duì)應(yīng)一個(gè)編碼后碼元ADC/DAC采樣率16 MSps16倍過(guò)采樣方便濾波與同步環(huán)路工作中頻頻率4 MHz低中頻方案規(guī)避零中頻直流偏置問(wèn)題卷積碼(2,1,3)生成多項(xiàng)式[7,5]八進(jìn)制約束長(zhǎng)度3編碼后碼率2 Msps1/2碼率卷積編碼輸出后符號(hào)速率翻倍成型濾波RRC滾降0.3收發(fā)端各一級(jí)根升余弦濾波器FPGA平臺(tái)Artix-7 XC7A35T資源占用約15%適合入門(mén)板卡復(fù)現(xiàn)為什么不直接用更高階的調(diào)制BPSK雖然頻譜效率只有1bps/Hz但結(jié)構(gòu)極其簡(jiǎn)單相位只有0和π兩種狀態(tài)判決域非常清晰用來(lái)驗(yàn)證卷積編解碼、同步環(huán)路這些核心機(jī)制是最不會(huì)被調(diào)制復(fù)雜度干擾的路線(xiàn)。等這套鏈路跑通把映射級(jí)改成QPSK或者16QAM再對(duì)應(yīng)改一下判決門(mén)限和誤差提取方式就能平滑升級(jí)到高階調(diào)制這點(diǎn)在后面擴(kuò)展章節(jié)細(xì)說(shuō)。參數(shù)里最值得留意的是中頻和采樣率的配比。4MHz中頻、16MHz采樣正好滿(mǎn)足帶通采樣定理而且采樣率是中頻的4倍數(shù)字混頻時(shí)NCO產(chǎn)生4MHz正弦波頻率控制字正好是2^30這種整數(shù)硬件上極大簡(jiǎn)化了頻率字計(jì)算。實(shí)際調(diào)試中這個(gè)整數(shù)關(guān)系能幫你快速排除NCO配置錯(cuò)誤因?yàn)榛祛l后頻譜位置非常干凈。1.3 為什么選BPSK卷積碼這套組合BPSK與卷積碼的組合本質(zhì)上是很多實(shí)際通信系統(tǒng)的基礎(chǔ)原型。卷積碼是記憶型糾錯(cuò)碼它不把輸入比特獨(dú)立編碼而是通過(guò)移位寄存器把前后比特的約束關(guān)系編碼到輸出中因此抗突發(fā)噪聲的能力比分組碼更平滑。FPGA實(shí)現(xiàn)卷積碼最大的優(yōu)勢(shì)在于編碼器結(jié)構(gòu)就是移位寄存器和異或門(mén)資源消耗幾乎可以忽略譯碼端雖然Viterbi算法復(fù)雜度隨約束長(zhǎng)度指數(shù)增長(zhǎng)但(2,1,3)這種約束長(zhǎng)度只有4個(gè)狀態(tài)在FPGA里跑起來(lái)非常輕松。另一個(gè)選擇原因是調(diào)試友好。BPSK調(diào)制解調(diào)的所有中間信號(hào)都是窄位寬數(shù)據(jù)用ILA抓波形非常直觀(guān)。卷積編碼器輸出可以直接和BPSK映射前的源數(shù)據(jù)對(duì)照Viterbi譯碼輸出可以和發(fā)射端最原始的比特流逐位比對(duì)整個(gè)鏈路任何一個(gè)環(huán)節(jié)出問(wèn)題都能通過(guò)波形快速定位到具體模塊這對(duì)一個(gè)供學(xué)習(xí)參考的工程源碼來(lái)說(shuō)至關(guān)重要。2. 發(fā)射端實(shí)現(xiàn)編碼與調(diào)制2.1 卷積編碼器的RTL實(shí)現(xiàn)卷積編碼器是發(fā)射鏈路數(shù)據(jù)進(jìn)入信道前的第一步。(2,1,3)卷積碼由三級(jí)移位寄存器、兩個(gè)異或求和節(jié)點(diǎn)和一個(gè)串并變換輸出組成。生成多項(xiàng)式[7,5]六進(jìn)制對(duì)應(yīng)二進(jìn)制111和101意思是第一個(gè)輸出碼字由當(dāng)前輸入與前兩級(jí)寄存器異或得到第二個(gè)輸出碼字由當(dāng)前輸入與第二級(jí)寄存器異或得到。寄存器每個(gè)符號(hào)周期移位一次每個(gè)輸入比特產(chǎn)生兩個(gè)輸出碼元碼率自然就是1/2。RTL實(shí)現(xiàn)代碼量很小核心就是三段式輸入打拍、異或計(jì)算、輸出拼接。但有一點(diǎn)必須提醒編碼器啟動(dòng)前寄存器必須清零否則前幾個(gè)符號(hào)的編碼輸出是無(wú)效的。連續(xù)幀傳輸時(shí)每幀開(kāi)始前都要對(duì)編碼器做一次復(fù)位操作。我在工程里習(xí)慣在編碼器前面加一個(gè)幀頭插入模塊幀頭采用固定PN序列這樣接收端可以用幀頭做同步捕獲和相位翻轉(zhuǎn)消除。幀頭不參與卷積編碼相當(dāng)于已知序列調(diào)試時(shí)非常有用。編碼器輸出是2比特并行但后續(xù)BPSK映射按符號(hào)處理所以需要一個(gè)2比特轉(zhuǎn)1符號(hào)的緩沖。可以直接把兩個(gè)碼元并行送到映射模塊每拍處理一個(gè)碼元對(duì)應(yīng)一個(gè)BPSK符號(hào)速率等于碼元速率2Msps也可以先做并串轉(zhuǎn)換再按符號(hào)時(shí)鐘處理。我用的是后一種方案同時(shí)引入隨路有效信號(hào)valid標(biāo)示數(shù)據(jù)有效后續(xù)所有模塊都遵守AXI4-Stream握手約定。這種接口風(fēng)格雖然看起來(lái)比簡(jiǎn)單valid-enable多幾個(gè)信號(hào)但模塊之間天然支持反壓后續(xù)插入FIFO、調(diào)試模塊或者替換成DMA都非常順。2.2 BPSK映射與成型濾波BPSK映射就是把1比特?cái)?shù)據(jù)映射成雙極性電平。我采用的映射關(guān)系是編碼輸出0映射為1編碼輸出1映射為-1。這里要注意映射關(guān)系本身不影響系統(tǒng)性能只需要發(fā)射端和接收端的判決規(guī)則保持一致即可。如果映射反了接收端要么全部判反要么譯碼輸出全錯(cuò)排查起來(lái)也簡(jiǎn)單看解調(diào)前星座圖兩簇點(diǎn)是否與理論位置匹配就行。成型濾波選擇根升余弦濾波器滾降系數(shù)0.3。接收端再接一級(jí)相同的根升余弦濾波器兩級(jí)級(jí)聯(lián)等效為升余弦濾波器實(shí)現(xiàn)無(wú)碼間干擾傳輸。濾波器階數(shù)我選了40階16倍過(guò)采樣下每符號(hào)16個(gè)采樣點(diǎn)加上濾波器自身的抽頭數(shù)整體運(yùn)算量不大。FPGA實(shí)現(xiàn)有兩種路線(xiàn)一種直接調(diào)用Xilinx FIR Compiler IP另一種手工用乘累加器實(shí)現(xiàn)轉(zhuǎn)置結(jié)構(gòu)FIR。如果目標(biāo)是學(xué)習(xí)源碼和二次開(kāi)發(fā)建議手工實(shí)現(xiàn)這樣能徹底搞清抽頭系數(shù)怎么量化、信號(hào)位寬怎么增長(zhǎng)后續(xù)換成定制濾波器也能繞開(kāi)IP。濾波器系數(shù)先用MATLAB的rcosdesign函數(shù)生成然后轉(zhuǎn)成Q定點(diǎn)格式。系數(shù)定點(diǎn)化之后一定要重新看頻響特性幅度波動(dòng)一般控制在0.1dB以?xún)?nèi)即可。濾波輸出的信號(hào)位寬會(huì)隨著抽頭累加而增長(zhǎng)需要根據(jù)仿真結(jié)果做截位把有效位保留下來(lái)防止信號(hào)飽和或者量化噪聲惡化。這里有個(gè)經(jīng)驗(yàn)截位前先看濾波輸出波形峰峰值再對(duì)應(yīng)選擇保留位寬不要盲目截?cái)嗟臀弧?.3 中頻調(diào)制與DDS載波生成基帶成型后的信號(hào)是16MSps采樣率的基帶波形需要搬到4MHz中頻。數(shù)字上變頻的標(biāo)準(zhǔn)做法是產(chǎn)生一個(gè)4MHz的NCO正弦載波與基帶信號(hào)相乘。由于16MHz采樣率正好是4MHz的4倍NCO相位累加器每四個(gè)采樣點(diǎn)走過(guò)一個(gè)完整周期相位步進(jìn)正好是2^30硬件實(shí)現(xiàn)非常直接。我用32位相位累加器頻率控制字通過(guò)公式freq f_carrier * 2^32 / f_s計(jì)算4MHz載波代入后正好是2^30。乘法器這里有一個(gè)關(guān)鍵點(diǎn)基帶信號(hào)和載波相乘后會(huì)產(chǎn)生2倍頻分量這個(gè)分量在接收端下變頻之后會(huì)被低通濾波器濾除但中間信號(hào)位寬必須擴(kuò)到足夠大否則乘法器輸出溢出會(huì)導(dǎo)致整個(gè)信號(hào)失真。實(shí)際編碼里我給了基帶信號(hào)12bitNCO正余弦各12bit乘法輸出截位到16bit送給DAC功耗和指標(biāo)都比較均衡這也是很多通信板卡常用的位寬配比。中頻調(diào)制完成后發(fā)射鏈路處理完畢。DAC芯片如果是16bit信號(hào)動(dòng)態(tài)范圍完全夠用如果DA位寬不足可以做簡(jiǎn)單的MSB截位或者加噪聲整形不過(guò)這個(gè)工程里14bit以上都無(wú)所謂調(diào)試時(shí)優(yōu)先關(guān)注頻譜是否干凈、符號(hào)速率是否正確即可。3. 接收端實(shí)現(xiàn)同步與解調(diào)3.1 數(shù)字下變頻與匹配濾波接收端ADC采樣后的信號(hào)是4MHz中頻數(shù)字信號(hào)第一步做數(shù)字混頻把信號(hào)搬回零中頻?;祛l需要一個(gè)與發(fā)射端同頻同相的本地載波由Costas環(huán)產(chǎn)生。初始階段先假設(shè)本地NCO頻率接近4MHz后續(xù)通過(guò)環(huán)路鎖定校正頻偏和相偏?;祛l后的I/Q兩路分別代表基帶信號(hào)的實(shí)部和虛部BPSK信號(hào)此時(shí)能量主要集中在I路上。數(shù)字混頻之后是低通濾波器主要濾除混頻產(chǎn)生的和頻分量同時(shí)起到抗混疊作用。這個(gè)低通濾波器我直接復(fù)用了發(fā)射端RRC匹配濾波器的硬件結(jié)構(gòu)只是系數(shù)替換成低通模式。如果中頻頻率和采樣率關(guān)系處理得好可以先在混頻輸出用CIC抽取濾波器把采樣率降到適當(dāng)倍數(shù)再用FIR做精細(xì)濾波能省不少乘法器資源。但這個(gè)工程里符號(hào)率只有1Msps直接16倍采樣率跑FIR乘法器數(shù)量也在可接受范圍內(nèi)所以我沒(méi)做抽取反而讓后面同步環(huán)路的性能更好調(diào)試。匹配濾波放在混頻之后將接收信號(hào)與發(fā)射端RRC進(jìn)行匹配兩級(jí)RRC級(jí)聯(lián)為升余弦輸出波形在采樣點(diǎn)位置的信噪比達(dá)到最大。匹配濾波系數(shù)必須和發(fā)射端完全一致兩個(gè)濾波器系數(shù)在工程里放在同一個(gè)頭文件或常量定義中防止版本不一致。這個(gè)問(wèn)題我踩過(guò)坑有一次發(fā)射端改系數(shù)只改了RTL文件沒(méi)改仿真文件結(jié)果MATLAB模型和RTL仿真對(duì)不上排查了一個(gè)多小時(shí)。3.2 Costas載波同步環(huán)BPSK解調(diào)必須有載波同步否則本地載波和接收信號(hào)之間存在頻率偏差和相位偏差解調(diào)結(jié)果會(huì)旋轉(zhuǎn)誤碼率直線(xiàn)上升。我使用的是經(jīng)典Costas環(huán)利用I/Q兩路輸出提取相位誤差e sign(I) × Q。這個(gè)誤差信號(hào)經(jīng)過(guò)環(huán)路濾波器之后反饋控制本地NCO的頻率字形成一個(gè)負(fù)反饋閉環(huán)。環(huán)路濾波器采用二階結(jié)構(gòu)包含比例項(xiàng)和積分項(xiàng)。比例系數(shù)Kp決定環(huán)路的快速響應(yīng)能力積分系數(shù)Ki決定穩(wěn)態(tài)精度。這兩個(gè)系數(shù)需要根據(jù)環(huán)路帶寬和符號(hào)速率來(lái)設(shè)定工程上常用公式Kp 2ξωnTs、Ki ωn2Ts2估算。我實(shí)測(cè)下來(lái)環(huán)路帶寬取符號(hào)速率的1/100左右比較合適帶寬太寬會(huì)引入噪聲導(dǎo)致星座點(diǎn)抖動(dòng)太窄則鎖定時(shí)間過(guò)長(zhǎng)測(cè)試耐心都要被磨沒(méi)了。Costas環(huán)鎖定之后本地NCO頻率字就是接收信號(hào)載波頻率的精確估計(jì)可以直接讀出來(lái)做頻率顯示或校準(zhǔn)。這里必須點(diǎn)一下BPSK特有的相位模糊問(wèn)題Costas環(huán)穩(wěn)定在0度和180度兩個(gè)收斂點(diǎn)0度時(shí)星座正確180度時(shí)解調(diào)輸出完全反相。工程上最簡(jiǎn)單的解決方法是在編碼前做差分編碼接收端判決后做差分譯碼代價(jià)是引入一定誤碼擴(kuò)散但換來(lái)絕對(duì)的相位魯棒性。這個(gè)工程里我先用幀頭獨(dú)特字檢測(cè)判斷是否反相如果反相則在判決輸出端對(duì)符號(hào)取反再通過(guò)FIFO對(duì)齊到正確幀起始位置。兩種方案都可以差分編碼對(duì)連續(xù)業(yè)務(wù)更穩(wěn)獨(dú)特字方案對(duì)突發(fā)幀更友好。3.3 Gardner定時(shí)同步與判決載波同步解決了相位問(wèn)題但采樣時(shí)刻不一定落在符號(hào)峰值點(diǎn)所以還需要定時(shí)同步。我用的是Gardner算法它不需要額外導(dǎo)頻利用每個(gè)符號(hào)的兩個(gè)采樣點(diǎn)和中間點(diǎn)做誤差提取誤差公式為e mid × (late - early)。這里的early和late分別表示當(dāng)前符號(hào)峰值前的采樣點(diǎn)和下一符號(hào)峰值前的采樣點(diǎn)mid是二者中間位置。Gardner環(huán)路的符號(hào)定時(shí)NCO控制插值濾波器的分?jǐn)?shù)間隔輸出符號(hào)率數(shù)據(jù)流給判決模塊。插值濾波器我用四次多項(xiàng)式插值比線(xiàn)性插值精度高很多資源消耗也不大。環(huán)路濾波同樣用二階結(jié)構(gòu)系數(shù)設(shè)計(jì)和Costas環(huán)類(lèi)似只是輸入信號(hào)不同。調(diào)試時(shí)有一個(gè)直觀(guān)現(xiàn)象環(huán)路鎖定時(shí)誤差信號(hào)的平均值接近零同時(shí)眼圖張開(kāi)最大從ILA里看I路波形就能判斷定時(shí)是否準(zhǔn)確。定時(shí)同步完成之后輸出數(shù)據(jù)送到判決模塊。BPSK判決就是根據(jù)I路符號(hào)的正負(fù)決定輸出0還是1非常直接。如果接收鏈路想再做完整一點(diǎn)這里還可以加AGC或者信道均衡但在室內(nèi)短距離、信噪比足夠的情況下不加也不影響鏈路演示。工程里我保留了AGC接口預(yù)留位后續(xù)接真實(shí)射頻前端時(shí)可以直接補(bǔ)上。4. Viterbi譯碼器從理論到RTL4.1 譯碼器架構(gòu)與狀態(tài)管理Viterbi譯碼是整個(gè)工程里計(jì)算量最大的部分。(2,1,3)卷積碼有4個(gè)狀態(tài)每個(gè)狀態(tài)對(duì)應(yīng)移位寄存器前兩級(jí)寄存器的取值組合。譯碼過(guò)程就是在一張時(shí)間為橫軸、狀態(tài)為縱軸的網(wǎng)格圖上尋找一條累計(jì)度量最小的幸存路徑。FPGA實(shí)現(xiàn)Viterbi譯碼器首先要確定判決方式。硬判決把解調(diào)輸出量化成0或1分支度量用漢明距離軟判決則保留多比特軟信息分支度量用歐氏距離。軟判決在AWGN信道下相對(duì)硬判決有大約2dB的編碼增益代價(jià)是分支度量和路徑度量的位寬增加。這個(gè)工程里我實(shí)現(xiàn)了軟判決版本解調(diào)器判決模塊只做符號(hào)到軟信息的映射不直接輸出硬比特軟信息位寬選4bit兼顧性能和資源。實(shí)際測(cè)試下來(lái)4bit軟信息和8bit軟信息的性能差距小于0.3dB但資源省了不少。狀態(tài)度量存儲(chǔ)是Viterbi的核心問(wèn)題。每級(jí)路徑度量需要存儲(chǔ)4個(gè)狀態(tài)的值并且度量值會(huì)持續(xù)增長(zhǎng)需要?dú)w一化處理。工程上用模2^M自動(dòng)溢出的辦法讓兩個(gè)并發(fā)路徑之差保持在較小范圍內(nèi)省去額外歸一化電路前提是M選得足夠大真實(shí)路徑度量差不發(fā)生翻轉(zhuǎn)。我這里是10bit度量位寬實(shí)測(cè)沒(méi)出過(guò)問(wèn)題。如果約束長(zhǎng)度升級(jí)到7狀態(tài)數(shù)變成64度量位寬也需要同步加大。4.2 ACS單元與路徑回溯的工程實(shí)現(xiàn)Viterbi譯碼器的核心是加比選單元每個(gè)狀態(tài)完成三步把前級(jí)兩個(gè)狀態(tài)的路徑度量加上對(duì)應(yīng)分支度量比較大小選擇較小值作為當(dāng)前狀態(tài)路徑度量同時(shí)記錄幸存路徑信息。四個(gè)狀態(tài)就是四個(gè)并行的ACS單元。因?yàn)?2,1,3)結(jié)構(gòu)簡(jiǎn)單我直接展開(kāi)成4個(gè)ACS單元每個(gè)單元工作在一個(gè)符號(hào)周期內(nèi)16MHz時(shí)鐘處理2Msps碼元速率運(yùn)算量不是瓶頸流水線(xiàn)控制在3級(jí)以?xún)?nèi)就能收時(shí)序。路徑回溯長(zhǎng)度一般取約束長(zhǎng)度的5到8倍約束長(zhǎng)度3時(shí)回溯深度取32足夠?;厮輰?shí)現(xiàn)有寄存器交換法和回溯法兩種。寄存器交換法實(shí)時(shí)性高但寄存器消耗大回溯法用RAM存儲(chǔ)幸存路徑信息每解碼一個(gè)符號(hào)需要回溯幾拍。我用的是回溯法狀態(tài)幸存路徑寫(xiě)入雙口RAM回溯時(shí)從當(dāng)前最優(yōu)狀態(tài)倒推。這里有個(gè)容易忽略的細(xì)節(jié)回溯輸出的順序和編碼順序是反的需要做一個(gè)反序FIFO修正否則譯碼結(jié)果完全不可用。整個(gè)Viterbi譯碼模塊的流水線(xiàn)節(jié)拍設(shè)計(jì)很有講究。ACS、幸存路徑寫(xiě)入、回溯、反序輸出四個(gè)階段用四級(jí)流水并行吞吐率就能穩(wěn)定跟上符號(hào)率。如果以后要升級(jí)成約束長(zhǎng)度7的(2,1,7)碼狀態(tài)數(shù)變成64個(gè)ACS單元可以復(fù)用同一個(gè)硬件結(jié)構(gòu)做時(shí)分復(fù)用代價(jià)是時(shí)鐘頻率要求更高工作量主要在狀態(tài)映射和RAM深度的修改上。5. 工程源碼結(jié)構(gòu)、仿真與板上驗(yàn)證5.1 源碼模塊劃分這個(gè)工程采用典型的層次化設(shè)計(jì)頂層模塊下面掛發(fā)射和接收兩條子鏈路收發(fā)之間在頂層直接相連做成一個(gè)自環(huán)模式方便在單板上完成全鏈路驗(yàn)證。模塊劃分如下模塊功能top_bpsk_conv頂層例化收發(fā)鏈路連接時(shí)鐘復(fù)位tx_data_gen偽隨機(jī)數(shù)據(jù)源用于誤碼統(tǒng)計(jì)tx_conv_encoder卷積編碼器tx_bpsk_modBPSK映射、成型濾波、中頻調(diào)制rx_nco_mixer本地NCO、數(shù)字混頻rx_match_filterRRC匹配濾波rx_costasCostas載波同步rx_gardnerGardner定時(shí)同步rx_viterbiViterbi譯碼rx_bit_align幀對(duì)齊、反相補(bǔ)償、誤碼統(tǒng)計(jì)所有模塊都使用AXI4-Stream接口傳輸數(shù)據(jù)tvalid和tready握手tlast表示幀尾。這種接口風(fēng)格雖然比簡(jiǎn)單valid-enable多幾個(gè)信號(hào)但模塊之間天然支持反壓后續(xù)在模塊間插入FIFO、調(diào)試模塊或者把某一段替換成DMA都非常順。頂層連接時(shí)也做了跨時(shí)鐘域處理ADC時(shí)鐘和系統(tǒng)邏輯如果不同域在接口處加異步FIFO同步避免亞穩(wěn)態(tài)問(wèn)題。5.2 Testbench設(shè)計(jì)與仿真觀(guān)測(cè)點(diǎn)Testbench是整個(gè)工程調(diào)試的第一道防線(xiàn)。我寫(xiě)tb的時(shí)候重點(diǎn)不是把所有信號(hào)都拉出來(lái)看而是盯幾個(gè)關(guān)鍵節(jié)點(diǎn)發(fā)射端的原始數(shù)據(jù)、編碼輸出、調(diào)制波形接收端的混頻I/Q波形、環(huán)路誤差信號(hào)、定時(shí)誤差信號(hào)、軟信息輸出、Viterbi譯碼輸出。在Vivado Simulator里跑完仿真直接把發(fā)射端原始數(shù)據(jù)和接收端Viterbi譯碼后數(shù)據(jù)做逐位比對(duì)統(tǒng)計(jì)出誤碼率。仿真里加噪聲是必要測(cè)試項(xiàng)。我在發(fā)射端中頻輸出處疊加高斯白噪聲模塊用Box-Muller法生成高斯隨機(jī)數(shù)噪聲功率按SNR設(shè)定換算。不同SNR下跑誤碼率曲線(xiàn)可以驗(yàn)證編碼增益是否正常。BPSK卷積碼(2,1,3)在10dB以上基本零誤碼8dB左右會(huì)有少量誤碼這個(gè)結(jié)果和理論曲線(xiàn)對(duì)得上說(shuō)明鏈路實(shí)現(xiàn)正確。如果發(fā)現(xiàn)誤碼率明顯偏大優(yōu)先查定時(shí)同步是否鎖定準(zhǔn)確其次查Costas誤差符號(hào)是否正確。5.3 板級(jí)調(diào)試經(jīng)驗(yàn)板級(jí)調(diào)試最大的問(wèn)題不是算法本身而是如何高效觀(guān)察內(nèi)部信號(hào)。建議優(yōu)先把ILA核掛在三個(gè)位置混頻后I路、Costas誤差信號(hào)、Viterbi處理前的軟信息。這三個(gè)點(diǎn)能快速判斷載波同步是否鎖定、定時(shí)同步后的眼圖是否張開(kāi)、軟信息幅度是否正常。VIO核用來(lái)動(dòng)態(tài)調(diào)整環(huán)路系數(shù)和復(fù)位信號(hào)省去每次改參數(shù)都要重新綜合的麻煩調(diào)試效率提升非常明顯。另外一點(diǎn)自環(huán)模式下發(fā)射和接收都在同一塊FPGA里不考慮空口衰減和多徑板子能跑通只代表功能正確不代表真實(shí)信道性能。如果需要逼近實(shí)際信道場(chǎng)景可以在中頻自環(huán)路徑上加可調(diào)衰減器或者人為加噪聲讓接收端實(shí)際感受到信號(hào)幅度變化再觀(guān)察AGC和同步環(huán)路的表現(xiàn)。如果要在兩個(gè)板卡之間做無(wú)線(xiàn)收發(fā)測(cè)試那就要額外考慮射頻前端和天線(xiàn)的匹配問(wèn)題這個(gè)工程里暫時(shí)沒(méi)有包含。6. 常見(jiàn)問(wèn)題與排錯(cuò)經(jīng)驗(yàn)6.1 載波同步鎖不死的調(diào)試Costas環(huán)鎖不定的現(xiàn)象是星座點(diǎn)在I/Q平面上始終旋轉(zhuǎn)或者鎖定之后相位抖動(dòng)很大。排查順序一般是先看NCO頻率字初值是否準(zhǔn)確再看環(huán)路濾波器系數(shù)是否合理最后檢查誤差信號(hào)極性。誤差極性反了的話(huà)負(fù)反饋會(huì)變正反饋環(huán)路必然發(fā)散。常見(jiàn)原因是在寫(xiě)sign(I)的時(shí)候把符號(hào)邏輯寫(xiě)反排查方法很簡(jiǎn)單把環(huán)路斷開(kāi)手動(dòng)給一個(gè)固定相偏看誤差信號(hào)能否收斂到零點(diǎn)附近。6.2 相位模糊與誤碼統(tǒng)計(jì)自環(huán)狀態(tài)下如果收發(fā)同源相位模糊往往不明顯因?yàn)榘l(fā)射端和接收端默認(rèn)同相。一旦鏈路里出現(xiàn)模擬器件或者真實(shí)空口相位模糊就會(huì)顯現(xiàn)。排查技巧是看Viterbi譯碼前的硬判決比特流是否整體取反如果誤碼率接近50%大概率是180度相位翻轉(zhuǎn)。解決方法就是前面提到的差分編碼或獨(dú)特字檢測(cè)。用獨(dú)特字檢測(cè)時(shí)要注意幀同步狀態(tài)機(jī)的穩(wěn)定性別把誤碼引起的假獨(dú)特字當(dāng)成真同步否則幀同步會(huì)反復(fù)跳變誤碼統(tǒng)計(jì)結(jié)果完全不可信。6.3 時(shí)序收斂與資源優(yōu)化整套工程在Artix-7上跑16MHz時(shí)鐘沒(méi)有壓力但如果把采樣率抬高到100MSps以上FIR濾波器和Viterbi回溯路徑就需要認(rèn)真做流水線(xiàn)設(shè)計(jì)。我的建議有兩條一是所有跨模塊信號(hào)統(tǒng)一遵守AXI-Stream握手在長(zhǎng)組合邏輯路徑中間插寄存器二是FIR濾波器系數(shù)用對(duì)稱(chēng)結(jié)構(gòu)乘法器數(shù)量減半。Viterbi譯碼如果資源緊張可以把并行ACS改成時(shí)分復(fù)用用一個(gè)ACS單元串行處理所有狀態(tài)用更高時(shí)鐘頻率換面積這個(gè)思路對(duì)未來(lái)擴(kuò)展更高速率的卷積碼很有用。還有一個(gè)容易被忽略的點(diǎn)RRC成型濾波器輸出位寬裁剪。濾波器增益會(huì)帶來(lái)二進(jìn)制位增長(zhǎng)如果直接截掉低位信號(hào)量化噪聲會(huì)明顯增加如果保留過(guò)多低位后續(xù)乘法器和加法器位寬全被撐大。正確做法是仿真觀(guān)察濾波輸出信號(hào)峰峰值確定有效位范圍后裁位并補(bǔ)上直流偏置防止信號(hào)削波。6.4 調(diào)試順序建議最后分享一個(gè)老套但非常有效的調(diào)試順序。先驗(yàn)證環(huán)回鏈路把發(fā)射端調(diào)制部分直接接到接收端解調(diào)部分不經(jīng)過(guò)同步環(huán)路確認(rèn)卷積編碼和Viterbi譯碼功能完全正確再加入載波同步不加定時(shí)同步確認(rèn)Costas環(huán)能穩(wěn)定鎖定再加入定時(shí)同步確認(rèn)Gardner環(huán)正確工作最后把AGC、幀同步這些完整功能打開(kāi)做全鏈路聯(lián)合調(diào)試。每加一個(gè)模塊就回歸一次誤碼率問(wèn)題出現(xiàn)時(shí)大概率就集中在最后一次新增的模塊里。按照這個(gè)順序調(diào)試這套BPSK卷積碼工程一共花了兩天中間踩的最大的坑反而是仿真時(shí)忘記給復(fù)位信號(hào)做同步釋放導(dǎo)致仿真波形前幾百拍全是無(wú)效狀態(tài)。把復(fù)位同步器加上之后一切都順了。工程源碼里保留了完整的約束文件和仿真腳本拿到直接跑能看到一個(gè)從編碼到譯碼全通的自環(huán)演示。這里也提醒一句仿真通過(guò)只是第一步上板調(diào)試時(shí)時(shí)鐘約束一定要如實(shí)填寫(xiě)否則時(shí)序收斂問(wèn)題會(huì)掩蓋算法問(wèn)題到時(shí)候查起來(lái)會(huì)非常頭疼。本文還有配套的精品資源點(diǎn)擊獲取