【信道编码/Channel Coding】卷积码和Viterbi译码及其MATLAB实现

简介:


这是本专栏信道编码/Channel Coding的最后一站,想对信道编码有一个系统性的认识可以看本专栏的 信道编码的整体框架 一文。而在本篇文章中,将介绍卷积码的基本原理和Viterbi译码的过程,以及其MATLAB实现。为什么是最后一站呢,明明还有Turbo码,LDPC码和Polar码,这是因为这是我本科的总结,那些码由于实现起来需要很多细节,有很多研究价值,我希望在我的研究生生涯能够完善。

目录

简介:

一、卷积码的原理

1.1 卷积码的符号表示

1.2 运作原理

二、 举例:(2,1,2)卷积编码器

2.1 状态转移表

2.2 状态转移图

2.3 网格图

三、Viterbi译码

3.1 译码过程(以上述(2,1,2)卷积码为例)(假设用硬判决)

3.2 硬判决和软判决

四、MATLAB实现


一、卷积码的原理


1.1 卷积码的符号表示

和分组码稍有不同,卷积码的符号表示有三个维度,(n,k,L)中,n和k和分组码不同,n是每次输出的码字长度,k是每次输入的信息比特长度,而L就是记忆深度,卷积编码器的图表示如下:

1.2 运作原理

  • 每过一个时间单位,比如从 t=0 到 t=1, k个比特从输入端输入k位的移位寄存器,而每一个移位寄存器里的k个比特输入到这个寄存器之后的一个寄存器。总共有L个k位移位寄存器。
  • 紧接着上面的,有L个k位寄存器意味着有k*L个比特。根据设计的不同,每一个比特对n个模二加运算器有独特的影响。
  • 模二加运算器的输出结果作为输出,所以一次输出n个比特。
  • 移位寄存器初始状态都是0

二、 举例:(2,1,2)卷积编码器


 可以看到,(2,1,2)卷积编码器是一个,每一时刻只有一个输入,但是会输出两位(两个模二加运算器)的卷积编码器,里面的寄存器都是1位的,共有两个寄存器(两个记忆深度)。而模二加运算器的数学表达如下:

y_1=Input\bigoplus D_1\bigoplus D_2

y_2=Input\bigoplus D_2

 假如输入序列为 x=10101,则其规律会是这样:

2.1 状态转移表

我们会发现,寄存器的状态就只有00,01,10,11四种可能,而输入只有0/1两种可能,所以输出一定也是伪随机的,也就是说输入输出的关系只有2x4=8种可能,我们将其列表:

输入当前状态下个状态输出1输出2
0000000
0010011
0100110
0110101
1001011
1011000
1101101
1111110

这就是状态转移表,通过查表可以非常简单的看出不同寄存器状态对应的输入输出之间的关系。这种表结构常用于编程。

2.2 状态转移图

我们只需要稍微改一下,将表转化成图就能得到状态转移图,如下:

 箭头表示从某一状态到每一状态,0/10表示在这个状态下,输入0得到输出10.

2.3 网格图

 网格图也非常直观简单,每行是一种寄存器的状态,所以有四行分别是00,01,10,11,而箭头仍然表示从什么状态到什么状态,0/00仍然表示在这个状态下输入0则输出11。但是不同的是,网格图能体现时刻的变化导致状态的转移路线的变化。

三、Viterbi译码


Viterbi译码实际上并不是非常复杂,其基于最大似然估计思想(ML)。我们先通过一个简单的例子迅速的理解一下Viterbi译码的流程。

3.1 译码过程(以上述(2,1,2)卷积码为例)(假设用硬判决)

  • 将接收到的码两两分组(毕竟编码的时候一个输入对应两个输出)
  • 利用和编码器一样的网格图,此时t=0,从状态00出发,画出输入为0和输入为1的两条路线,。并将输入为0的输出 和 输入为1的输出 分别和 t=0 要翻译的码进行异或(计算汉明距离),得到的值称为路径度量(PM,Path Metric),我们将其作为像路径的重量一样累积起来。注意,这时候应该有两个路径了、
  • t=1,t=2,...的操作和上一步一样,从每个路径在上一时刻的状态出发,比较输入为0输入为1的输出和此时刻要翻译的码,计算汉明距离,再计算路径度量(累积的汉明距离)。所以在t=n时刻,理应有 2^{n+1} 个路径
  • 剪枝(Pruning):由于路径过于多,所以在路径达到某个数量的时候,译码器仅保留路径度量(累积汉明距离)最小的两个路径,然后继续译码。直至译码结束。

举例:

假设接收端接收到信号,并将其量化判决为011100(体现了硬判决,下面会讲)

(1)第一步是把信息两两分组:01 11 00,作为t=0,t=1,t=2时刻的输入

(2)第二步,译码,按照上面所述的流程,t=0时,收到的码为00;此时译码器状态为00,输入为0时输出为00,和收到的码的汉明距离是0,故PM=0;输入为1时输出为11,和收到的码汉明距离是2,故PM=2.

(3)继续译码,从上一步的两条路径出发,会衍生出四条路径

(4)进行剪枝(看系统的设计,不一定是这个时候剪枝),只保留最小PM的两个路径,继续译码

(5)回溯,从PM最短的路径开始回溯,译码为110

【注意】通常接收端会在一帧的信息比特发完末尾加入0 0,这样接收端的译码器就会回归00状态

3.2 硬判决和软判决

大家都注意到了,上面栗子的小标题提示了这是硬判决,那么什么是硬判决什么是软判决呢?

  • 硬判决(Hard Decision)是指在接收端,信号被接收后,先进行种种滤波,均衡等操作,然后直接被判决器判为0或1,根据得到的比特串进行如上面所述的Viterbi译码。注意,这时候我们的PM(路径度量)是以汉明距离为度量。由它的二元特性判断,它比较适合BPSK等二元系统。
  • 软判决(Soft Decision)是指在接收端,信号被接收后,进行完种种滤波,均衡等操作,在采样量化后,先不进行判决(也就是先不把多电平状态的量化信号变成0101的数字信号),而是直接经过软判决Viterbi译码器,这时候译码器会以欧氏距离为PM(路径度量),判断某一电平状态距离欧氏距离最近的符号。软判决通常会比硬判决性能更好,因为软判决减少了因量化器判决导致的量化噪声。

四、MATLAB实现


%%
clear all;clc;close all;
% Generation of Bits stream
nob=100; % The amount of bit
bit_stream=[randi([0 1],nob,1);[0;0]];

codeword=zeros(2*(nob+2),1);
D1=0; % Initial state of registers
D2=0;
for i_b=1:1:nob+2
    y1=mod(bit_stream(i_b)+D1+D2,2);
    y2=mod(bit_stream(i_b)+D2,2);
    D2=D1;
    D1=bit_stream(i_b);
    codeword(2*i_b-1)=y1;
    codeword(2*i_b)=y2;
end

%%
% Viterbi Decoding
received_codeword=codeword;
state_table=[0 0;0 1;1 0;1 1];  %find(ismember(state_table,[1 1],'row')==1)
Transfer_table={[0 0],[0 0],[1 1],[1 0]; % Output with input 0/1;Next State
    [1 1],[0 0],[0 0],[1 0];
    [1 0],[0 1],[0 1],[1 1];
    [0 1],[0 1],[1 0],[1 1]};
D=[0 0]; % State of registers
branch=cell(8,4); % weight, estimated bit stream, last state
branch{1,1}=0;branch{1,2}=[];branch{1,3}=[0 0];branch{1,4}=1;
for i=2:1:8
    branch{i,1}=0;
    branch{i,4}=0;
end

for i_b=1:2:length(received_codeword)
    code_buffer=received_codeword(i_b:i_b+1,1).';
    a_b=find([branch{:,4}]==0); % Available Branches
    n_b=8-length(a_b);
    for i_s=1:1:n_b
        i_a_b1=i_s;
        i_a_b2=a_b(i_s);
        weight=branch{i_s,1};  % Accumulated weight of branch
        est_b_s=branch{i_s,2}; % Estimated Bit stream
        last_state=branch{i_s,3}; % Last state of this branch
        index=find(ismember(state_table,last_state,'row')==1); % Find the index of Last state
        
        % Look up table
        weight1=weight+sum(xor(code_buffer,Transfer_table{index,1})); % Hamming Distance
        weight2=weight+sum(xor(code_buffer,Transfer_table{index,3}));
        est_b_s1=[est_b_s,0];
        est_b_s2=[est_b_s,1];
        last_state1=Transfer_table{index,2};
        last_state2=Transfer_table{index,4};
        
        % Update the branch list
        branch{i_a_b1,1}=weight1;
        branch{i_a_b1,2}=est_b_s1;
        branch{i_a_b1,3}=last_state1;
        branch{i_a_b1,4}=1;
        branch{i_a_b2,1}=weight2;
        branch{i_a_b2,2}=est_b_s2;
        branch{i_a_b2,3}=last_state2;
        branch{i_a_b2,4}=1;
    end
    
    % Pruning
    if n_b==4
        weight_list=[branch{:,1}];
        [~,i_tmw]=sort(weight_list); % Get the index of the two minimum weight
        buf11=branch{i_tmw(1),1};
        buf12=branch{i_tmw(1),2};
        buf13=branch{i_tmw(1),3};
        buf21=branch{i_tmw(2),1};
        buf22=branch{i_tmw(2),2};
        buf23=branch{i_tmw(2),3};
        
        branch{1,1}=buf11;
        branch{1,2}=buf12;
        branch{1,3}=buf13;
        branch{1,4}=1;
        branch{2,1}=buf21;
        branch{2,2}=buf22;
        branch{2,3}=buf23;
        branch{2,4}=1;
        for i=3:1:8
            branch{i,4}=0;
        end
    end
end

%%
n_survival_branch=length(find([branch{:,4}]==1));
w_survival_branch=[branch{1:n_survival_branch,1}];
[~,i_weight]=sort(w_survival_branch);
i_minimum_weight=i_weight(1);
estimated_bit_stream=branch{i_minimum_weight,2};
BER=sum(abs(estimated_bit_stream-bit_stream'))/(nob+2)

  • 21
    点赞
  • 147
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
卷积码是在信息序列通过有限状态移位寄存器的过程中产生的。通常,移存器包含N级(每级A比特),并对应有基于生成多项式的m个线性代数方程,输入数据每次以A位(比特)移入移位寄存器,在此同时有n位(比特)数据作为己编码序列输出,编码效率为A/n。参数N被称作约束长度,它指明了当前的输出数据与多少输入数据有关。它决定了编码的复杂度。 译码器的功能就是,运用一种可以将错误的发生减小到最低程度的规则或方法,从已编码的码字中解出原始信息。在信息序列和码序列之间有一对一的关系。此外,任何信息序列和码序列将与网格图中的唯一一条路径相联系。因而,卷积译码器的工作就是找到网格图中的这一条路径。 Viterbi算法可被描述如下; 把在时刻i,状态 所对应的网格图节点记作 ,每个网相节点被分配一个值 。节点值按如下方式计算: (1)设 , 。 (2)在时刻i,对于进入每个节点的所有路径计算其不完全路径的长度。 (3)令 为在i时刻,到达与状态 。相对应的节点 的最小不完全路径长度。通过在前一节点随机选择一条路径就可产生新的结果。非存留支胳将从网格图中删除。以这种方式,可以从 。处生成一组最小路径。 (4)当L表示输入编码段的数目,其中每段为k比特,m为编码器中的最大穆存器的长度,如果 ,那么令 ,返回第二步。 一旦计算出所有节点值,则从 时刻,状态 。开始,沿网格图中的存留支路反向追寻即可。这样被定义的支路与解码输出将是一一对应的。关于不完全路径长度,硬判决解码将采用Hamming距离,而软判决解码将采用Euclidean距离。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值