1、维特比译码简介
目前公开的资料中,对维特比译码介绍的最详细、最通俗易懂的文章,推荐“纸上谈芯”的博文:
“卷积码译码之维特比译码算法”
纸上谈芯原文章https://blog.csdn.net/zhouxuanyuye/article/details/78278292?spm=1001.2014.3001.5506
因此,原理性部分不再赘述,需要了解的可参考该文章。更推荐林舒的《差错控制编码(原书第2版)_[林舒.著][机械工业出版社][2007]》,本文只谈实际应用。
补充:以下推导维特比译码算法原理:
译码器错误概率为:
(1)
其中,P(E|R)为译码器的条件错误概率, 定义为:
因此,译码器的最小错误概率可以等效为:
(2) 根据贝叶斯公式,
(3)
在先验等概率情况下, 转换成 求使得
达到最大的那个码
字Ci。 即似然函数,译码方法为最大似然译码。
若信息长度为L,每个节点有2^k条分支,总共就有:2^(k×L)条不同的路径,CMi为路径度量,表示为:
(4)
最大似然译码也就是求CMi的最大值,也等效为求R与码字C之间的最小欧式距离
(5)
2、工程应用
维特比译码系统可大致分为以下几个单元:分支度量单元(BMU),加比选单元(ACSU),幸存路径存储单元(SMU),回溯路径单元(TBU)。
图1 Viterbi译码流程框图
维特比译码在实际实现时,大体可分为以下步骤:
1)数据预处理:
根据卷积码(n,k,m)参数,以及生成多项式G确定维特比算法中几个重要的数组:
- next_state[
][
] —— 根据当前输入比特(共k bit),确定寄存器下一时刻的状态(寄存器为m bit)
- out_put [
][
] —— 根据当前输入比特(共k bit),确定当前输出比特(每一时隙 k 比特输入, n bit 输出)
- input[
] [
] —— 根据当前状态和下一状态的组合,确定当前输入比特(对算法很重要)
对于数组next_state, out_put,在应用matlab仿真时很容易得到。例如,(3,1,2)卷积码,生成矩 阵为G=[ 1 0 0 ; 1 1 1; 1 0 1],当输入:
ConstraintLength = 3;
CodeGenerator = [4,7,5];
trellis = poly2trellis(ConstraintLength,CodeGenerator);
可得到:
matlab给出的网格参数trellis不包含Input参数,因此可以利用代码自行实现:
%可以用trellis网格图 nextStates,outputs来验证计算是否正确
for j=0:number_of_states-1
%m为从k个输入端的信号组成的状态,总的状态数为2^k,所以循环从0到2^k-1
for m=0:M-1
%next_state完成从当前的状态和输入的矢量得出寄存器组的下一个状态
[next_state,memory_contents]=nxt_stat(j,m,N,k);
%存储寄存器当前输入的信息位M1
input(j+1,next_state+1)=m;
%输出码元
branch_output=rem(memory_contents*G',2);
%存储寄存器下一状态(M2M3)
nextstate(j+1,m+1)=next_state;
%以十进制存储所有输出码元
output(j+1,m+1)=bin2deci(branch_output);
end
end
2)译码过程
根据算法的特点,我们知道其核心思想就是找出众多幸存路径中汉明距离最小的那一条路径,即根据网格图,将上一节点的汉明距离,加上“当前输出比特与实际接收数据的汉明距离度量”,并比较所有输出可能性,选择当前时隙的幸存路径,即ACS过程(Add-Compare-Select)。
由于精力有限,本文只附上详尽的算法理解手稿,希望能帮助大家理解该过程:
3)译码结果输出
根据幸存路径,确定最终幸存状态数组state_sequence:
% 从最佳路径中产生解码
% 译码过程可从数组survivor_state的最后一个位置向前逐级译码
state_sequence=zeros(1,depth_of_trellis+1);
state_sequence(1,depth_of_trellis)=survivor_state(1,depth_of_trellis+1);
for i=1:depth_of_trellis
state_sequence(1,depth_of_trellis-i+1)=
survivor_state((state_sequence(1,depth_of_trellis+2-i)+1),depth_of_trellis+2-i);
end
最后,再根据状态序列当前状态和下一状态,反推出当前输入(用input数组确定):
for i=1:depth_of_trellis-N
%根据数组input的定义来得出从当前状态到下一个状态的输入信号矢量
dec_output_deci=input(state_sequence(1,i)+1,state_sequence(1,i+1)+1);
dec_output_bin=deci2bin(dec_output_deci,k);
%将一次译码存入译码输出矩阵decoder_output_matrix相应的位置
decoder_output_matrix(:,i)=dec_output_bin(k:-1:1)';
end
最后,给出维特比译码仿真链接:
需要的可以自行下载