摘要:基于卷積碼的編譯碼原理,使用VHDL語言和FPGA芯片設計并實現了(2,1,3)卷積碼編譯碼器。其中譯碼器設計采用“截尾”的Vite-rbi譯碼算法,在支路量度計算、路徑量度和譯碼路徑的更新與存儲以及判決與輸出等環節的實現中采取了若干有效措施,節省了存儲空間,提高了設計性能。最后通過仿真驗證了設計的正確性與合理性。
關鍵詞:FPGA;卷積碼;編譯碼器;Viterbi譯碼器:VHDL
由于卷積碼具有較好的糾錯性能,因而在通信系統中被廣泛使用。采用硬件描述語言VerilogHDL或VHDL和FPGA(Field Programmable Gate Array——現場可編程門陣列)進行數字通信系統設計,可在集成度、可靠性和靈活性等方面達到比較滿意的效果。
文獻以生成矩陣G=[101,111]的(2,1,3)卷積碼為例,介紹了卷積碼編碼器的原理和VerilogHDL語言的描述方式;文獻采用VerilogHDL語言,對(2,1,7)卷積碼的Viterbi硬判決譯碼進行了FPGA設計。本文基于卷積碼編/譯碼的基本原理,使用VHDL語言和FPGA芯片設計并實現了(2,1,3)卷積碼編碼器及其相應的Viterbi譯碼器,通過仿真驗證了設計的正確性。
1 (2,1,3)卷積碼編碼器的設計
1.1 (2,1,3)卷積碼編碼器的原理
卷積碼編碼器通常記作(n,k,N),對應于每段k個比特的輸入序列,輸出n個比特;這n個輸出比特不僅與當前的k個輸入比特有關,而且還與以前的(N-1)k個輸入比特有關。(n,k,N)卷積碼編碼器包括:一個由Ⅳ段組成的輸入移位寄存器,每段有k級,共Nk位;一組n個模2加法器;一個由n級組成的輸出移位寄存器。整個編碼過程可以看成是輸入序列與由移位寄存器和模2加法器連接方式所決定的另一個序列的卷積。
對于(2,1,3)卷積碼編碼器來說,n=2,k=1,N=3,即每輸入1個信息比特時經編碼后產生2個輸出比特,輸出比特不僅與當前的1個輸入比特有關.而且還與以前的2個輸入比特有關。(2,1,3)卷積編碼器框圖如圖1所示。
由圖可以看出,輸出為:
1.2 設計思路
編碼器為串入串出結構。這里一共定義4個端口信號,它們分別是:
當編碼使能start為0時不進行編碼,并將狀態state清零;start為1時進行編碼,此時每2個時鐘周期輸入一個新的信息比特,同時狀態信號改變,輸出2位已編碼比特,即每個時鐘周期輸出1位已編碼比特。
2 維特比譯碼器的設計
2.1 維特比譯碼器的原理
卷積碼的譯碼一般采用維特比譯碼。維特比譯碼本質上是對長度為L的二進制序列的最佳譯碼,需要對可能發送的2L個不同的序列的2L條路徑量度進行計算和比較,選取其中量度最小的一條作為幸存路徑。其基礎是基于網格圖的描寫,即對于不同的路徑的量度進行比較,如某一節點上發出的某條路徑已經不可能獲得最大似然函數,那么就放棄這條路徑,并在保存下來的路徑中重新選擇譯碼路徑,一直到最后,復雜度較高。維特比譯碼器實際上對各個可能路徑進行比較,比較原則是計算其路徑的對數似然函數,而計算似然函數就是計算該路徑與接收序列之間的漢明距(量度)。譯碼過程的操作可歸納為“加-比-選”3個部分。
實際的維特比譯碼中,譯碼幾步后可能的路徑便合為一條,因此,不必等全部譯出后再輸出,即譯碼一定長度后便可將已經相同的部分輸出,這樣做可以大量節省譯碼所需路徑的存儲空間。只要保證譯碼深度在5~10倍的約束長度之間就不影響譯碼效果,這就是所謂的“截尾譯碼”。
2.2 結構框圖
維特比譯碼器的結構框圖如圖2所示。
在設計中。將框圖簡化為“加”(支路量度計算)、“比選”(路徑量度和譯碼路徑的更新與存儲)以及定時與控制三部分。
2.3 設計思路
2.3.1 端口及信號定義
輸入輸出端口為:
其中“比前路徑長度”中下劃線前的數字代表該路徑最后停在的狀態,下劃線后的數字代表是由哪個狀態轉移過來的。如果是“0”則代表由狀態號較小的狀態轉移過來的那條路徑,反之如果為“1”則代表由狀態號較大的狀態轉移過來的那條路徑;“選后路徑長度”和“譯碼路徑”的序號表示該路徑最后停在的狀態號。圖3為維特比譯碼過程的網格圖。
2.3.2 定時與控制
由時鐘控制,每個時鐘輸入一位,每兩個時鐘輸出一位,稱為一個譯碼周期。在每個譯碼周期的前一個時鐘周期內完成“加”,此時譯碼狀態為“0”;在后一個時鐘周期內完成“比和選”,譯碼狀態為“1”。
2.3.3 支路量度計算
由于(2,1,3)卷積碼的形式已經固定,因此,可以事先把支路量度表做好,如表1所示。譯碼器工作時可根據輸入通過查表得到“比前路徑長度”的增加值,暫存到addi_j中,而后統一加入“比前路徑長度”chni_j中。
2.3.4 路徑量度和譯碼路徑的更新與存儲
在到達同一狀態的兩條路徑中選取路徑長度較小的作為幸存路徑,即在chnk_0和chnk_1中選擇較小的存入rlengthk(k=0~3)。
由于每個狀態譯碼路徑的最后一位在每一步中是不變的,均是"0101”(狀態0~3),因此更新譯碼路徑時只需將選中的譯碼路徑向高位移一位后存儲即可。即進行如下判斷:
1)對于新路徑0的判斷,如果chn0_0<=chn0_1則選擇舊路徑0,否則選擇舊路徑2;
2)對于新路徑1的判斷,如果chn1_0<=chn1_1則選擇舊路徑0,否則選擇舊路徑2;
3)對于新路徑2的判斷,如果chn2_0<=chn2_1則選擇舊路徑1,否則選擇舊路徑3;
4)對于新路徑3的判斷,如果chn3_0<=chn3_1則選擇舊路徑1,否則選擇舊路徑3;
其中chn0_0,chn0_1,chn1_0,chn1_l,chn2_0,chn2_1,chn3_0,chn3_1已由上一步得出。
2.3.5 判決與輸出
譯碼深度為10,譯碼的輸出只需將譯碼路徑的最高位中出現較多的一位輸出,當“0”和“1”的個數相等時輸出任意一個。由圖4所示的卡諾圖可得,譯碼輸出的邏輯表達式為:
dataout=(route0 (9) and routel (9)) 0r (route2 (9) and route3 (9))
2. 3.6 譯碼初始化
由于剛開始譯碼的第一步和第二步,譯碼路徑并未完全展開,“加-比-選”與后面的步驟略有不同。因此設置一個譯碼步驟計數器step,對譯碼前兩步的“加”進行單獨處理,而不改變“比選”部分。
2.3.7 路徑量度的溢出
由于路徑量度是一直累加的,如果不進行處理則計數器將溢出。設計中發現,各條路徑之間的路徑量度相差不會太大。解決的辦法是:如果有一個路徑量度超過了某一門限,就將所有記錄的路徑量度減一個小量。在實際中,由于(2,1,3)卷積碼每一步譯碼后路徑量度最多增加2,因此為避免溢出,設置門限為8,當超過該門限時各路徑量度都減小2。這樣就可以用很少容量的寄存器保存任意長的路徑量度。
3 仿真結果
仿真在MaxplusII10.2環境下進行,選擇FLEX1OK系列中的EPF10K30RC240-3器件。以下是部分仿真結果。
3.1 卷積碼編碼器仿真
卷積碼編碼器的仿真波形如圖5所示。在編碼使能之后輸入序列data_in為110111001000…(每個bit持續2個時鐘周期),編碼輸出序列data_out為110101000110011111101100……(每個bit持續1個時鐘周期),結果與文獻中的例12-1完全一致。
3.2 維特比譯碼器仿真
維特比譯碼器的仿真波形如圖6所示。其中圖(a)為輸入無誤碼時的情形,圖中輸入序列為1101010001100111…,譯碼輸出序列為110111 00…;圖(b)為輸入有誤碼時的情形,圖中假設輸入序列為1001010101100101…(其中黑體的bit為誤碼),則譯碼輸出序列仍為11011100…。
由仿真結果可以看出。用上述方法設計的卷積碼編/譯碼器功能正確,并具有較好的糾錯能力。
4 結論
本文用VHDL語言和FPGA芯片設計并實現了(2,1,3)卷積碼編碼器及維特比譯碼器。仿真結果表明,編/譯碼器的功能正確,達到設計要求。在設計中采用了模塊化結構,維特比譯碼器設計采用了截尾譯碼算法,節省了存儲空間。另外,設計中還較好的解決了譯碼過程中的支路度量計算、路徑量度和譯碼路徑的更新與存儲以及譯碼判決與輸出等關鍵技術問題。
由于卷積碼具有相似的結構和特點,所以文中(2,1,3)卷積碼編/譯碼器的設計思路,對其他形式的卷積碼編/譯碼器也是適用的。