[2,1,7]卷积码的编码与维特比译码matlab仿真

本文详细介绍了如何使用MATLAB实现2,1,7卷积码的编码过程,以及维特比译码算法,通过实例展示了编码生成多项式、输入比特流处理和编码输出的计算过程,最后讨论了branch数据结构在解码中的应用。
摘要由CSDN通过智能技术生成

目录

一、前言

二、matlab代码

三、总结


一、前言

branch里存储了路径的所有信息,包括寄存器状态、编码输入状态、编码结果、汉明距离,理解起来很方便。

二、matlab代码

%%  [2,1,7]卷积码的编码与维特比译码

% 卷积码(n,k,L) *还有一种叫法(n,k,m)感觉容易混淆?以生成式为准。
% 其中n表示输出码字长度,
% k表示输入信息比特长度,
% L表示卷积码中的约束长度(L=m+1,m为卷积码中寄存器个数)

%% 
%****************编码******************************
clear all
close all
clc

%%生成多项式,八进制表示[133 171]
G = [
    1,0,1,1,0,1,1;
    1,1,1,1,0,0,1
    ]; 
%%输入比特流,这里可以随便更改
M = [1 0 0 1 1 0 0 0 1 1 1 1 0 0 1 1 1 1 1 0];


%%编码
k=1;                %输入信息比特长度=1,每次输入一个码元
[n,L] =  size(G);   %n表示输出码字长度,L表示卷积码中的约束长度
len = length(M);
coded_output = zeros(1,n*len); %编码结果输出,初始化

inputs = zeros(k,L);%参与编码的输入状态共7b,1b新输入拼上6b寄存器
for i = 1:len
    %状态更新(输入更新,寄存器右移)
    inputs = [M(i),inputs(1:end-1)];    
    %编码过程一条语句完成,即横矩阵(输入)*竖矩阵(多项式)
    coded_output(n*i-(n-1):n*i) =  mod(inputs*G',2);     
end
coded_output1 = coded_output.';  %加了很多转置,方便观察 
%% 
% 使用matlab自带函数进行对比
ConstraintLength = 7;
CodeGenerator = [133 171];%2列表示n=2;1行表示k=1?
trellis = poly2trellis(ConstraintLength,CodeGenerator);
coded_matlab = convenc(M,trellis);
coded_matlab1 = coded_matlab.';
decode_matlab = vitdec(coded_matlab,trellis,7,'trunc','hard');
decode_matlab1 = decode_matlab.';




%%
%****************解码******************************

%列出所有输入状态对应的输出,2^L*n的矩阵,供后面直接按输入状态查找输出
states_val=0:2^L-1;
states_str=dec2bin(states_val);
[x,y]=size(states_str);
states_all=zeros(x,y);
for i=1:x
    for j=1:y
    states_all(i,j)=str2num(states_str(i,j));    
    end
end
output_all=mod(states_all*G',2);

%初始化分支(路径)容器branch,branch存储了每条路径的6项关键信息:
% isuse,    此条路径是否已使用
% regs,     6b寄存器
% state,    7b输入状态,等于1b新输入拼上6b寄存器
% output,   7b的输入对应的编码输出
% weight,   编码输出与读取的数据间的汉明重量(距离)
% bits,     从t0时刻开始此条路径所有的输入记录,也就是可回溯每条路径对应的译码结果
%最终在branch里找到weight最小的那条路径,取出bits就是最终译码结果。           
branch=cell(2^L,6);
branch{1,1}=1;
branch{1,2}=zeros(1,L-1);
branch{1,5}=0;
for i=2:2^L
    branch{i,1}=0;
end

%开始读取已编码数据
code_in=coded_output;
n_bits=length(code_in)/n;%n位数据对应1位原始未编码比特流
for n_bits_i=1:n_bits
    %每次读取1bit原始数据对应的编码
    code_in_1bit=code_in(1:n);code_in=[code_in(n+1:end),zeros(1,n)]; 

    branch_used=find([branch{:,1}]==1);
    branch_free=find([branch{:,1}]==0);
    %每条现有路径branch_used都会分裂为2条(输入0or1),所以遍历branch_used
    %第1条使用原来的路径容器,第2条使用新的路径容器
    for branch_used_i=1:length(branch_used)        
        %当前待分裂路径(老的)
        branch1=branch_used(branch_used_i);
        %当前待填充路径(新的)
        branch2=branch_free(branch_used_i);        
        %先缓存此路径在分裂前的值,分裂时要使用
        regs    = branch{branch1,2};
        weight  = branch{branch1,5};
        bits    = branch{branch1,6};
        %开始分裂
        state1=[0,regs];        
        state1_index=vector2val(state1)+1;
        state1_output=output_all(state1_index,:);%按输入状态查找输出
        state1_weight=sum(xor(code_in_1bit,state1_output));
        state2=[1,regs];
        state2_index=vector2val(state2)+1;
        state2_output=output_all(state2_index,:);
        state2_weight=sum(xor(code_in_1bit,state2_output));
        %计算完毕,把分裂后的数据填到两条路径容器里
        branch{branch1,1}=1;
        branch{branch1,2}=state1(1:end-1);
        branch{branch1,3}=state1;
        branch{branch1,4}=state1_output;
        branch{branch1,5}=state1_weight+weight;
        branch{branch1,6}=[bits,0];
        branch{branch2,1}=1;
        branch{branch2,2}=state2(1:end-1);
        branch{branch2,3}=state2;
        branch{branch2,4}=state2_output;
        branch{branch2,5}=state2_weight+weight;
        branch{branch2,6}=[bits,1];
    %打断点用
    breakpoint=1; 
    end

    % 剪枝    分裂到所有路径填满时,要开始修去一半被淘汰的路径,释放空间以供下次迭代
    if(length(branch_used)==2^(L-1))
        for(i=1:2^(L-1))
            index1=i*2-1;
            index2=i*2;
            if(branch{index1,5}>branch{index2,5})
                branch{index1,1}=0;
            else
                branch{index2,1}=0;
            end
        end
    %打断点用
    breakpoint=1; 
    end

%打断点用
breakpoint=1; 
end

%到此,其实直接观察branch就能找到重量最短的那条路径了

weight_all=[branch{:,5}];
[weight_sorted,weight_index]=sort(weight_all);
%几个数据转置一下,方便观察
weight_all1=weight_all.';
weight_sorted1=weight_sorted.';
weight_index1=weight_index.';
%最终译码结果
decode_output=branch{weight_index(1),6};
decode_output1=decode_output.';

%% 函数
function val = vector2val(Q)  %数列表示的二进制转为数值,高位在左
    len = length(Q);
    val=0;
    for i=1:len
        val = Q(i) * 2^(len-i)+val;
    end
end

三、总结

熟悉了之后,branch里可以作一些精简。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值