本壓縮包中包含維特比編碼和譯碼的全部verilog代碼,包含測試代碼和部分仿真結果 Viterbi 算法是一種最大似然譯碼算法,它是通過計算累積漢明距離,在卷積網(wǎng)絡圖上尋找一條與接收碼字具有最小漢明距離的最大似然路徑。 Viterbi 譯碼算法不需要把每一條路徑都與接收碼字進行比較,而是接收一組碼字,計算一組距離,比較一組路徑,選擇其中“最大”分支度量,再進行下一輪的比較。當接收完所有碼字(多組碼字)時,幸存下來的那條路徑就是我們要尋找的最大似然路徑度量路徑。 Viterbi 譯碼的總體流程是比較各分支的度量值,選擇一段最可能的分支,更新狀態(tài)的度量,并根據(jù)比較結果獲得狀態(tài)轉移表,最后通過狀態(tài)轉移表的回溯算法完成譯碼
 總體:大致下面幾個模塊。我們的卷積碼是(2,1,9),所以有256個狀態(tài)。首先是control模塊輸出所有控制信號,保證其他模塊有序譯碼。然后是bmg模塊,根據(jù)輸入的卷積碼CODE,判斷256個狀態(tài)512個分支的漢明距,即分支度量值,發(fā)送給acs.然后asc模塊從RAM里面的metricmemory里面取出前一級的256個狀態(tài)路徑度量值,與bmg送來的漢明距離,相加以后,進行比較,選擇路徑度量值較小的分支,最終得到256個狀態(tài)的路徑度量值,存儲到RAM,并且把256個狀態(tài)里面最小狀態(tài)傳給TBU回溯模塊。把256個狀態(tài)的幸存比特信息傳給MMU。MMU一次從ACS得到4個狀態(tài)的幸存比特信息,將其拼接成8個狀態(tài),存入RAM中。然后當TB-EN使能信號有效,開始回溯時,TBU模塊給RAM發(fā)11位的地址,從RAM里面尋找當前狀態(tài)的幸存比特信息,RAM把信息傳給MMU,通過MMU傳給TB模塊。最后TB模塊輸出解碼。 testbench.v建立原始時鐘信號,時鐘周期是100ns,頻率10MHz。再建立復位信號,低有效。Active信號為1,開始工作。創(chuàng)建編碼器時鐘D_CLOCK。 最后設置輸入碼字X或者卷積碼code。T=DPERIOD=64*400ns。實例化編碼器,輸出卷積碼。實例化解碼器,輸出解碼。 DPERIOD =128*200=64*400,ACS模塊時鐘是clock1,2,周期是400.ACS模塊里面有四個并行加比選單元,一個周期完成四個狀態(tài)的加比選。然后迭代64次,才完成256個狀態(tài)加比選,所以需要64個clock2。
仿真結果: 1.帶有編碼器。輸入碼字X給卷積編碼器,編碼器輸出卷積碼CODE給解碼器,解碼器輸出DECODEOUT。如圖正確解碼。 
下面兩圖是輸入碼字X,和解碼輸出碼字DecodeOut,我們可以直觀地看出兩者一致。 

2.不帶編碼器。直接輸入卷積碼CODE給解碼器,解碼器輸出DECODEOUT。如圖正確解碼,下圖的輸入卷積碼是和上圖X輸入,在編碼器生成的卷積碼一致。有圖可見,波形一致,仿真正確。  3.維特比譯碼有一定的糾錯能力,下圖驗證。因為維特比會選擇一個路徑度量最小的狀態(tài)回溯,也即差錯最小?梢钥吹藉e誤代碼中,lowestmetric不再為0,說明有差錯,差錯狀態(tài)的路徑度量值為10h. correctcode代碼 
errorcode代碼  control.v功能:控制器模塊//向各個模塊發(fā)送控制信號,保證各模塊有序進行解碼 input Reset, CLOCK, Active; //復位信號,低有效;原始時鐘;開始工作信號 output [`WD_FSM-1:0] ACSSegment; //迭代次數(shù)64, 6bit output [`WD_DEPTH-1:0] ACSPage; //輸出碼字信號 6bit output Clock1, Clock2; //clock的四分頻,有相位差 output Hold, Init, CompareStart; //碼字結束;開始;比較開始(ACS) output TB_EN; //開始回溯 控制單元使用Clock1更新ACSSegment(從而更新BMG單元和ACS單元的輸出)。 時鐘2用于指示何時將地址放置到地址總線。 仿真結果: - reset=0時,異步復位,Clock1 <= 0; Clock2 <= 0; ACSSegment<=111_111;
ACSPage<=111_111;Hold<= 0;Init <=0; TB_EN <= 0;CompareStart <= 0; 2.CLOCK周期為100ns 
3.看出count為二分頻,最終Clock1,Clock2都為Clock的四分頻,T=400ns。 并且,Clock2超前Clock1,90度。Clock1=1100時,Clock2=1001。 因為有的信號操作需要其他信號保持一段時間。所以利用相位差90度,將有些信號在使用前設置好,防止沖突延遲。 例如ASC里面最小路徑產(chǎn)生模塊。其功能是找出256個狀態(tài)中路徑度量最小的狀態(tài)。它在Clock2下降沿更新最小狀態(tài),最后在Clock1下降沿輸出。由于Clock2超前Clock1,剛好可以在更新完最后一個狀態(tài)與重新進行下次256個狀態(tài)的比較之間,輸出最小狀態(tài)。

- 在Clock1的上升沿。{ACSPage,ACSSegment} <= {ACSPage,ACSSegment} + 1;所以ACSSegment由000_000到111_111,然后ACSPage再加一,ACSPage對應一個碼字的輸入時間。
一個碼字的輸入時間就是計數(shù)64個ACSSegment。一個碼字在4個并行ACS單元下迭代64次,才能完成256個狀態(tài)的路徑度量值比較。 Init信號標志著一個碼元處理的開始,在Clock1的上升沿,且ACSSegment=3F的時候為1,持續(xù)一個Clock1。 Hold信號標志著一個碼元處理的結束,在Clock1的上升沿,且ACSSegment=3EH的時候為1,持續(xù)一個Clock1. 
5.ACSPage = 'h3E且ACSSegment = 'h3F時,TB_EN為1,TB單元使能,路徑開始回溯。 
6.在Clock2的上升沿。comparecount計數(shù)到8以后并且ACSSegment = 6'h3F(init)。CompareStart <= 1,開始比較。對于前8個碼字不進行比較。幸存者來自“0”分支,上支路。 
從全0狀態(tài)起始點開始討論。到9級及以后,每個狀態(tài)都有兩支路,才需要加比選。 
acs.v
ASCUNIT模塊分為三塊。一是四個并行的ASC單元,二是RAM Interface(RAM 接口模塊),三是Lowest Pick block(最小路徑選擇模塊)。
功能:ACS 單元從路徑度量存儲模單元中取出前一時刻幸存路徑的度量值, 然后與送入 ACS 單元的分支度量值累計相加進行比較,相加度量值較小的作為該狀態(tài)新的路徑度量值存入RAM里的MetricMemory以備下一時刻加比選使用。并產(chǎn)生幸存比特信息survivor 給MMU模塊。這個幸存信息表示在加比選操作中,表征該狀態(tài)是由前一時刻進入該狀態(tài)的哪條分支轉移而來的,當 survivor =0 時表示該狀態(tài)是由偶狀態(tài)(即上支路)轉移而來,當 survivor =1 時表示該狀態(tài)是由奇狀態(tài)(即下支路)轉移而來。 最后把256個狀態(tài)里面最小狀態(tài)傳給TBU回溯模塊。 - module ACSUNIT (Reset, Clock1, Clock2, Active, Init, Hold, CompareStart,ACSSegment, Distance, Survivors,LowestState,MMReadAddress, MMWriteAddress, MMBlockSelect, MMMetric, MMPathMetric);
- input Reset, Clock1, Clock2, Active, Init, Hold, CompareStart; //由control產(chǎn)生的控制信號。復位;時鐘1,2;開始工作;碼字開始;碼字結束;比較開始
- input [`WD_FSM-1:0] ACSSegment; //由control產(chǎn)生,指明當前的迭代次數(shù) input [`WD_DIST*2*`N_ACS-1:0] Distance; //來自BMG,8個距離,16位
- //連接幸存路徑存儲器Survivor Memory ,MMU
- output [`N_ACS-1:0] Survivors; // 4個1bit的survivor輸出 // 連接路徑回溯單元TB Unit
- output [`WD_STATE-1:0] LowestState; //// 連接度量記憶單元 MetricMemory output [`WD_FSM-2:0] MMReadAddress; //5位,一次讀入8個狀態(tài)。32*8=64*4= output [`WD_FSM-1:0] MMWriteAddress; //6位,一次寫入4個狀態(tài)。64*4
- output MMBlockSelect; //選擇RAMA或RAMB,乒乓操作
- output [`WD_METR*`N_ACS-1:0] MMMetric; //存入MM路徑度量值,4個狀態(tài),32位
- input [`WD_METR*2*`N_ACS-1:0] MMPathMetric; //來自MM的路徑度量值,8個狀態(tài),64位
復制代碼
仿真結果: - 當輸入漢明距離Distance為16'b1000_0101_0010_0101時,即8個分支的漢明距離為2 0 1 1 0 2 1 1。如圖Distance顯示8525。并且路徑度量值MMPathMetric為全0時,進行四個狀態(tài)的加比選。經(jīng)過加比選,得到四狀態(tài)的路徑度量值和幸存路徑信息,如下圖,輸出MMMetric=00_01_00_01,Survivors=0111(7),與分析相符。


- 當輸入漢明距離Distance為16'b1000_1000_0000_0000時,即8個分支的漢明距離為2 0 2 0 0 0 0 0。如圖Distance顯示8800。并且路徑度量值MMPathMetric為1 2 3 4 b c d e時,進行四個狀態(tài)的加比選。經(jīng)過加比選,得到四狀態(tài)的路徑度量值和幸存路徑信息,如下圖,輸出MMMetric=02_04_0b_0d,Survivors=0011(3),與分析相符。


3.找到256個狀態(tài)最小狀態(tài)的功能。如圖,只有在前四個狀態(tài)八個分支輸入的Distance=16'b1000_0101_0110_0101; //2 0 1 1 1 2 1 1 ;其余情況漢明距離均為1.又因為初始存儲的路徑度量值為0.故其,路徑度量值最小的狀態(tài)為0對應的狀態(tài),狀態(tài)號為3,和仿真一致。 
4.和RAM接口模塊,存入和讀取路徑度量值。MMBlockSelect=0為A寫B(tài)讀。在下一個碼字輸入時,MMBlockSelect翻轉。例如,寫A讀B時,實現(xiàn)先讀取B中上一級的256個狀態(tài)路徑度量值,用于加比選,同時把加比選的結果存入A。然后下一狀態(tài)讀A寫B(tài),交替操作,實現(xiàn)同時讀寫。 A,B都是64個32bit的存儲模塊。64*4*8
下圖仿真中,可以看到先是寫A讀B,在第一個碼字輸入時,取出的MMpathmetirc為0。然后第一個碼字結束后,全部存入256個狀態(tài)的路徑度量值在A中。在一個碼字來時,讀A, MMpathmetirc先為64H0101010100010101,可以看到3-0狀態(tài),路徑度量值為0111,和之前輸入一致。其余時刻均為64H0101010101010101(路徑度量值都是1) 
- output [`WD_FSM-2:0] MMReadAddress; //5位,一次讀入8個狀態(tài)。32*8=64*4
output [`WD_FSM-1:0] MMWriteAddress; //6位,一次寫入4個狀態(tài)。64*4=256 MMReadAddress <= ACSSegment [`WD_FSM-2:0]; //低五位。0-31 MMWriteAddress = ACSSegment; //寫地址6bit 為什么讀地址是五位,寫地址是6位。 因為四個狀態(tài),有8個分支,對應著前面8個狀態(tài)。所以需要讀出8個狀態(tài)的路徑度量值。 如當 ACSSegment為ABCDEF時,他對應的4個狀態(tài)是這樣,它對應的前八個狀態(tài)一定是BCDEF對應的8個狀態(tài)。前后狀態(tài)只有一位不同,相當于右移一位,輸入放最高位。所以只需要ACSSegment低五位,就可以讀出對應的前8個狀態(tài)路徑度量值。另一方面,讀地址5BIT,尋址32個,即32*8=256,實現(xiàn)256個狀態(tài)的讀取。32個,32*8=256個狀態(tài)。寫地址6BIT,尋址64個,一次寫4個狀態(tài),64*4=256,完成256個狀態(tài)的存入。 

51hei.png (3.88 KB, 下載次數(shù): 44)
下載附件
2022-3-28 22:00 上傳
以上8個.v文件下載(verilog程序):
維特比編碼譯碼器.zip
(1.49 MB, 下載次數(shù): 87)
2022-3-28 20:27 上傳
點擊文件名下載附件
|