通信原理--信道编码--卷积码--Viterbi译码

版权声明:转载请注明出处 https://blog.csdn.net/DengFengLai123/article/details/79839967

Viterbi译码

卷积码的译码可分为代数译码和概率译码,其中代数译码包括门限译码,概率译码包括Viterbi译码和序贯译码等。Viterbi译码的实质是最大似然译码,但它利用了编码网格图的特殊结构,降低了计算复杂性,译码建立的基础是编码器状态的马尔可夫性:即当前状态完全概括了编码器的历史信息,以前的状态不会影响将来的状态或者将来的分支输出。在二进制对称信道(BSC)中,汉明距离是合适的距离量度。

参考资料:
- https://blog.csdn.net/dengfenglai123/article/details/79835108及该博文中涉及的参考资料
- 数字通信——基础与应用(第二版).[美]Bernard Sklar著,徐平平等译. 电子工业出版社
- https://www.cnblogs.com/sddai/p/5461372.html


译码流程

算法理论基础

假设发送序列Um和接收译码序列Z长度均为L比特,对于二进制对称信道而言,即寻找与序列Z具有最小汉明距离的码字Um’。若Um与Z之间有dm个数据比特不同,即汉明距离为dm,由于二进制对称信道是离散无记忆信道的特例,即信道无记忆,所以序列Um被转换成与它汉明距离为dm的特定接收序列Z的概率为

      P(Z|Um) = (p^dm) * (1-p)^(L-dm) 

其对数似然函数为

       logP(Z|Um) = -dm*log[ (1-p) / p ]+ L* log(1-p)

上式中,发送概率p有确定值,L也可确定,可看出等式中的变量只有dm,假设p < 0.5,则

      logP(Z|Um) = -dm*A + B,且A、B为常数,A>0,B>0

故应该选择使得与接收序列Z之间汉明距离dm最小的码字Um,以获得最大对数似然概率,即最大似然概率(单调性一致)。

算法描述

(1)从时间 j=m 开始,计算进入每个状态的路径度量(汉明距离)。
(2)j=j+1,计算分支度量,比较并选出路径度量最似然者, 将所对应的转移路径作为此时刻进入每一个状态的幸存路径,存储其路径信息和度量值,并删去其它所有的路径。
(3)若j

栅格图

如下图所示的状态转移,在蓝色框内的初始两个时刻对应过程(1),绿色框内对应过程(2),褐色框内是输入全0进行“点亮”寄存器,使状态回到S0,对应过程(3)。
reg [13:0] a_out, a_out1, a1, a2, a3, a4; //搜索序列寄存器
reg [3:0] c1, c2, c3, c4; //汉明距离
reg [6:0] c_t, c_t1, c_t2, c_t3, c_t4; //记录译码估算值
当状态在时刻7回到S0时,a1中保存的是7个分支路径上的输出,共2bit*7=14bit,c1中保存从初始时刻到时刻7的所有路径中与输入序列的最小汉明距离,c_t1保存着最大似然译码。
这里写图片描述

栅格图分析

  1. 以时刻3为例,在时刻3时到达状态S0的路径有两条,可以是有时刻2的S0状态在输入0的时到达,也可由S1状态在输入0的情况下到达,此时可以看出想要到达S0,首先确定输入一定为0,观察时刻3的状态S0~状态S3,可以看出到达一个状态的两条路径确定的输入要么同时为0,要么同时为1。
  2. 在绿色框内的每一时刻均有8条路径,对应4个状态,且每个状态的两条路径所确定的输入相同,还是以时刻3为例,设时刻2的S0到达时刻3的S0的汉明距离为d1,时刻2的S1到达时刻3的S0的汉明距离为d2,时刻3的S0到达时刻4的任意可到达状态的汉明距离为d3,则只要时刻3的状态确定为S0,则该状态所确定的d3不受d1和d2影响(马尔可夫性),所以只需判断d1和d2的大小即可,选取其中小的,若二者一样,任选一条。

代码块

/*
1.到达每个状态的都有两条路径,通过计算汉明距离舍弃距离较大的那一条
2.观察发现:两条路径对应的输入值是一样的,都为0或都为1
3.注意高、低位的顺序
*/

…… 部分代码 ……
//4个状态,每个状态有2个分支,保留路径较小的一个分支
//S0:00 要到达00状态,则前一个状态需要为00状态或01状态且输入为0,对应的输出是00或11
if((c1+{3'b000,x_t[5]^0}+{3'b000,x_t[4]^0})>
 (c2+{3'b000,x_t[5]^1}+{3'b000,x_t[4]^1})) begin
    c1 <= c2+{3'b000,x_t[5]^1}+{3'b000,x_t[4]^1};   //保留小的量度(汉明距离)
    a1[3:0] <= a2[3:0];     //前一个状态是S1->01
    a1[5:4] <= 2'b11;       //输出为11
    c_t1[4] <= 0;           //输入的是0,记录本次译码的最大似然估算值
    c_t1[6:5] <= c_t2[6:5]; //记录当前所有译码的最大似然估算值
end                  
else begin
    c1 <= c1+{3'b000,x_t[5]^0}+{3'b000,x_t[4]^0};   //保留小的
    a1[3:0] <= a1[3:0];     //当前状态由00状态输入0得来,即上一状态为S0->00
    a1[5:4] <= 2'b00;       //输出为00
    c_t1[4] <= 0;           //输入的0,S1(00)状态下输入0,输出00,得到状态S1->00
    c_t1[6:5] <= c_t1[6:5]; //记录当前所有译码的最大似然估算值
end

输出:

扫描二维码关注公众号,回复: 4024880 查看本文章
/*
最小状态判决,在所有路径的状态寄存器中,挑选一个具有最小路径度量的状态,
以它的路径寄存器的第一段信息元作为译码器的输出,因为进行了收尾处理,所以
最后必然会回到S0->00状态,
即a1里保存的数据就是最小路径下的输出码元,c_t1保存着译码结果
*/
…… 部分代码 ……
a_out1[13:0] <= {a_out1[0],a_out1[13:1]};  //移位,每次输出最低位a_out1[0],保存着输出码元  
if(cnt[0]==1)   //相当于时钟clk的2分频,每输出2bit的a_out1,输出1bit的c_t
    c_t[6:0] <={c_t[5:0], c_t[6]};  //移位,每次输出最高位c_t[6],保存着译码结果

…… 部分代码 ……

assign y = a_out1[0];   //输出,此时已经回到00状态,a_out1里保存着最后的
                        //整条路径,每次译得的码都存在[0]位
assign c = c_t[6];      //输出译码估值

仿真验证

输入 10 01 01 00 10 11 00
对应的输出 11 01 01 00 10 11 00
译码 1 0 1 1 0 0 0
这里写图片描述


猜你喜欢

转载自blog.csdn.net/DengFengLai123/article/details/79839967