1.卷积码的概念
卷积码最早由埃利斯(Elias)于1955年提出。卷积码是一个有限记忆系统,是一种非分组码。它与分组码类似,也是先将信息序列分割成长度k的一个个分组,不同的是某一时刻的编码输出不仅取决于本时刻的分组,而且取决于本时刻以前的L个分组,所以把卷积码写成(n,k,L)形式以突出卷积码最重要的3个参数,其中n表示码元数,即输出比特个数。另外,分组码经过编码生成的码组可以分为信息位和校验位,而卷积码编码生成的码整体看作校验码或者监督码。卷积码的纠错能力随约束长度的增加而增强,差错率则随着约束长度增加而呈指数下降。
相比于其它纠错编码方式,卷积码具有以下优点:
1.码率可变:卷积码可以灵活地调整码率,从而适应不同的信道带宽和传输速率需求。
2.良好的抗噪声性能:卷积码的解码算法 Viterbi 算法可以有效地消除干扰和误差,保证数据的正确传输。
3.低延迟:卷积码采用滑动窗口的方式进行编解码,具有较低的延迟,适合对时延要求敏感的应用场景。
4.高效率:卷积码实现简单、计算量小、速度快,适用于多种嵌入式系统
2.卷积码的编码
由图1可见,卷积码将信息序列串/并变换后存入由k个L级移存器构成的kL阵列中,其中最左列存放当前输入的信息组。按一定规则对阵列中的数据进行线性组合,编出当前时刻的各码元
,j=0,…,n-1,最后由并/串变换合成当前码字后输出。
图1:卷积码编码器示意图
下面通过一个具体例子来说明卷积码的表达方法。
例:某二级制(2,1,3)卷积编码器如图2所示。其第一个码元的生成多项式,连接矢量
,亦即第一个输出码元
。第二个码元的生成多项式
,连接矢量
,亦即第二个输出码元
。
图2:卷积码编码器的生成多项式及输出码元表达式
如图3所示,在初始时刻,假设寄存器状态为(0,0,0)。 在t1时刻,输入1,则寄存器状态变为(1,0,0),相当于把初始寄存器状态(0,0,0)中从左往右第二个0“挤”掉了,编码输出11。在t2时刻,输入0,则寄存器状态变为(0,1,0),相当于把t1时刻寄存器状态(1,0,0)中从左往右第二个0“挤”掉了,编码输出10。在t3时刻,输入1,则寄存器状态变为(1,0,1),相当于把t2时刻寄存器状态(0,1,0)中从左往右第二个0“挤”掉了,编码输出00。接着输入两个冲洗比特(连续输入两个0),用以清空寄存器。 在t4时刻,输入0,则寄存器状态从t3时刻的(1,0,1)变为(0,1,0),相当于把t3时刻寄存器状态(1,0,1)中从左往右第二个1“挤”掉了,编码输出10。在t5时刻,输入0,则寄存器状态从t4时刻的(0,1,0)变为(0,0,1),相当于把t4时刻寄存器状态(0,1,0)中从左往右第二个0“挤”掉了,编码输出11。
图3:编码器编码结果示意图
所以编码输出C如下表所示。
表1:编码输出结果C
t | t1 | t2 | t3 | t4 | t5 |
C | 11 | 10 | 00 | 10 | 11 |
为什么用两个冲洗比特就可以达到清空寄存器的目的呢?为什么不是三个呢?毕竟再输入一个0,寄存器状态才恢复为初始状态(0,0,0)。其实,输入两个就达到清空寄存器的目的了。如果在t6时刻输入一个1,这时候寄存器状态就从(0,0,1)变为(1,0,0),t5时刻的寄存器状态中的1被“挤”掉了,也就是这个1被舍弃掉了。换言之,这个1是没用的,所以两个冲洗比特足矣,只需要把寄存器状态变为(0,0,X)的形式即可,其中,X可为0或1。不管X为0还是1,都对下一个输入的寄存器状态没有影响。在下一个输入进来的时候,X都会被舍弃掉。
图4所示是卷积码的状态流图,圆圈代表状态,箭头代表转移,与箭头对应的标注表示编出的码字。每个状态都有两个箭头发出,对应输入分别是0、1两种情况下的转移路径。知晓输入序列之后,从状态流图可以容易地找到输入/输出和状态的转移。
图4:卷积码的状态流图
从上面可以看到,状态流图为利用信号流图的数学工具奠定了基础。但美中不足的是状态流图缺少一根时间轴,不能记录下状态转移的轨迹。网格图(也有人称为格栅图、格子图、篱笆图)弥补了这一个缺点,它以状态为纵轴,以时间(单位为码字周期T)为横轴。如图5所示为(2,1,3)网格图。给定输入数据序列,根据网格图,可以方便地得到编码输出序列。虚线代表输入比特为1,实线代表输入比特为0。例如,当输入数据序列为1 1 0 1 1时,可根据网格图得到其对应的编码输出序列为11 01 01 00 01,如图5所示:
图5:卷积码的网格图
3.卷积码的译码
卷积码的译码是根据接收序列来求解最可能的发送序列。已知接收序列,可以得到卷积码的编码器结构和发送序列的长度,我们可以对所有的可能发送结果进行编码,将结果同接收序列进行比较,记录汉明距离,则汉明距离最小的就可能是发送序列。但这种方法计算量成指数增大,信息量很大,无法实现。
卷积码的译码主要采用概率译码(最大似然译码),比较典型的是维特比(Viterbi)算法。维特比算法就是寻找一条路径,使得该路径的编码输出与接收序列的汉明距离最小,其关键就是路径的寻找过程,如下例所示:
首先,从第一个状态出发,到下一个状态有两种途径,分别计算这两条路径的编码输出与接受序列的汉明距离(注意,此时不能进行任何舍弃,不能将距离大的舍弃)
图6:卷积码译码第一步示意图
第二步,从第一步到达的两个状态出发,继续寻找路径,由于2位移位寄存器共有四种状态,因此此时我们得到到达所有状态的路径(无论是否最优)。
图7:卷积码译码第二步示意图
第三步,从这四个状态出发,继续寻找路径,此时我们将得到8种路径。这一步是算法的关键,此时要保留到达各状态的最短路径,舍弃其他路径,即舍弃后仍保留四条路径,且四条路径分别对应四个状态(无论该状态以后的路径如何选择,当到达该状态时,该状态以前的路径一定是最优的)。对于(n,k,N)卷积码,进行维特比译码时,当到达第N步时,要对路径进行舍弃,只保留幸存路径的信息,储存幸存路径以及当前的累计距离。
图8:卷积码译码第三步示意图
第四步:继续进行路径寻找,同样只保留每个状态下的幸存路径,直至步数达到输入序列的个数。
图9:卷积码译码第四步示意图
由此可以看出,维特比算法是复杂的:每步要比较条路径(每个状态两条),计算量与步数(输入码的个数)成正比。
4.基于Matlab的汉明码,RS,卷积码三种编码技术的对比
下面基于Matlab对卷积码、RS码和汉明码三种编码技术的误码率随信道差错概率的变化、误码率随信道差错概率以及仿真速度的变化进行对比。卷积码、RS码、汉明码的对应Matlab代码以及仿真结果分别如下所示。
4.1卷积码
clc;
clear;
close all;
%% 参数初始化
sel = 0;
if sel == 1;
trel = poly2trellis(7,[171 133]);%多项式
tblen = 9; %回溯深度
else
trel = poly2trellis(3,[6 7]);%多项式
tblen = 9; %回溯深度
end
Step = 10;%仿真时间间隔
Simu_Len = 10000; %仿真的时间长度
Simu_time = 1000;
Pf = 1e-3 : (10e-3-1e-3)/Step : 10e-3-(10e-3-1e-3)/Step; %信道差错概率
Simu_speed = 3*10^10/Step : 3*10^Step/10 : 3*10^10;
msg = (double(rand(1,Simu_Len)>0.5))';
%% 主体代码
for i = 1:length(Pf)
Err = zeros(1,Simu_time);
for j = 1:Simu_time
i
j
%编码
Msg_Enc = convenc(msg,trel);
Msg_Enc2 = Msg_Enc;
%将数据通过信道
idx = round(length(Msg_Enc)*Pf(i));
idx2 = round(length(Msg_Enc)*rand(1,idx));
idx2(find(idx2 == 0)) = 1;
for ii = 1:length(idx2)
if Msg_Enc(idx2(ii)) == 1
Msg_Enc2(idx2(ii)) = 0;
else
Msg_Enc2(idx2(ii)) = 1;
end
end
%译码
Msg_Dec = vitdec(Msg_Enc2,trel,tblen,'cont','hard');
%计算误码率
[n2,r2] = biterr(Msg_Dec(tblen+1:end),msg(1:end-tblen));
Err(j) = n2;
end
Err2(i) = sum(Err)/(Simu_time*Simu_Len);
end
%% 曲线仿真
figure;
plot(Pf,Err2,'b-*');
xlabel('channel error rate');
ylabel('BER');
%% 3D图
figure;
[X,Y] = meshgrid(Simu_speed,Pf);
Error = [Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' ];
mesh(X,Y,Error);
xlabel('信道差错概率');
ylabel('仿真速度');
zlabel('误码率');
if sel == 1;
save JJ7.mat X Y Error Pf Err2
else
save JJ5_4.mat X Y Error Pf Err2
end
图10:卷积码的误码率随信道差错概率的变化、误码率随信道差错概率以及仿真速度的变化
由图10可见,卷积编码的性能优秀。但由于卷积编码的性能并不是针对突发中断,所以卷积编码在效果较好的情况下,仍然存在一定的误码率。
4.2 RS码
clc;
clear;
close all;
%% 参数初始化
sel = 0;
if sel == 1;
k = 5; %15
n = 7; %31
else
k = 15; %15
n = 31; %31
end
Step = 10;%仿真时间间隔
Simu_Len = 1000*k; %仿真的时间长度
Simu_time = 500;
Pf = 1e-3 : (10e-3-1e-3)/Step : 10e-3-(10e-3-1e-3)/Step; %信道差错概率
Simu_speed = 3*10^10/Step : 3*10^Step/10 : 3*10^10;
msg = (double(rand(1,Simu_Len)>0.5))';
Rs_Encoder = fec.rsenc(n,k);
Rs_Decoder = fec.rsdec(Rs_Encoder);
%% 主体代码
for i = 1:length(Pf)
Err = zeros(1,Simu_time);
for j = 1:Simu_time
i
j
%编码
Msg_Enc = encode(Rs_Encoder,msg);
Msg_Enc2 = Msg_Enc;
%将数据通过信道
idx = round(length(Msg_Enc)*Pf(i));
idx2 = round(length(Msg_Enc)*rand(1,idx));
idx2(find(idx2 == 0)) = 1;
Msg_Enc2(idx2) = floor(rand(1,1)*Msg_Enc(idx2));%设置出错值
%译码
[Msg_Dec,cnumerr,ccode] = decode(Rs_Decoder,Msg_Enc2);
%计算误码率
Err(j) = biterr(Msg_Dec,msg);
end
Err2(i) = sum(Err)/(Simu_time*Simu_Len);
end
%% 曲线仿真
figure;
plot(Pf,Err2,'b-*');
xlabel('channel error rate');
ylabel('BER');
%% 3D图
figure;
[X,Y] = meshgrid(Simu_speed,Pf);
Error = [Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' ];
mesh(X,Y,Error);
xlabel('信道差错概率');
ylabel('仿真速度');
zlabel('误码率');
if sel == 1;
save RS5_7.mat X Y Error Pf Err2
else
save RS15_31.mat X Y Error Pf Err2
end
图11:RS码的误码率随信道差错概率的变化、误码率随信道差错概率以及仿真速度的变化
由于RS编码的特点就是针对突发错误,所以在RS编码的时候,对于性能较好的RS3115编码效果较好,其误码率曲线的值为0,而RS75,其纠错能力较差,所以上面的仿真结果中红色部分仿真结果为零。
4.3汉明码
clc;
clear;
close all;
%% 参数初始化
sel = 0;
if sel == 1;
k = 4; %15
n = 7; %31
else
k = 11; %15
n = 15; %31
end
Step = 10;%仿真时间间隔
Simu_Len = 100*k; %仿真的时间长度
Simu_time = 500;
Pf = 1e-3 : (10e-3-1e-3)/Step : 10e-3-(10e-3-1e-3)/Step; %信道差错概率
Simu_speed = 3*10^10/Step : 3*10^Step/10 : 3*10^10;
% msg = (double(rand(1,Simu_Len)>0.5))';
msg = randint(Simu_Len,1,[0,2^k-1]);
%% 主体代码
for i = 1:length(Pf)
Err = zeros(1,Simu_time);
for j = 1:Simu_time
i
j
%编码
Msg_Enc = encode(msg,n,k,'hamming/decimal');
Msg_Enc2 = Msg_Enc;
%将数据通过信道
idx = round(length(Msg_Enc)*Pf(i));
idx2 = round(length(Msg_Enc)*rand(1,idx));
idx2(find(idx2 == 0)) = 1;
Msg_Enc2(idx2) = floor(rand(1,1)*Msg_Enc(idx2));%设置出错值
%译码
Msg_Dec = decode(Msg_Enc2,n,k,'hamming/decimal');
%计算误码率
Err(j) = biterr(Msg_Dec,msg);
end
Err2(i) = sum(Err)/(Simu_time*Simu_Len);
end
%% 曲线仿真
figure;
plot(Pf,Err2,'b-*');
xlabel('channel error rate');
ylabel('BER');
%% 3D图
figure;
[X,Y] = meshgrid(Simu_speed,Pf);
Error = [Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' Err2' ];
mesh(X,Y,Error);
xlabel('信道差错概率');
ylabel('仿真速度');
zlabel('误码率');
if sel == 1;
save hmm5_7.mat X Y Error Pf Err2
else
save hmm15_31.mat X Y Error Pf Err2
end
图12:汉明码的误码率随信道差错概率的变化、误码率随信道差错概率以及仿真速度的变化
汉明编码的误码率和信道误码率呈线性变化,上图中蓝色部分是由于仿真点数少,所以其误码率略有抖动,当仿真点数时间长的时候,其仿真波形可线性变化。
5.卷积码在通信系统的应用
卷积码是一种性能优越的信道编码,它的编码器和译码器都比较容易实现,同时也具有较强的纠错能力,随着纠错编码理论研究的不断深入,卷积码的实际应用越来越广泛。
(一)卷积码在GSM系统中的应用
GSM系统话音卷积编码器在全速率业务信道和控制信道就采用了(2,1,4)卷积编码。其连接矢量为G1=(10011)(23),G2=(11011)(33)。
在GSM系统中,话音编码采用规则脉冲激励-长期预测编码(RPE-LTP)。它以20ms为一帧,共260bit,分为3类,信道编码对它们进行CRC编码,它们再经过按规定的次序重新排列后,在其后面加上4个尾比特0000,形成卷积码编码器的输入序列。
卷积编码是按帧进行的,尾比特的作用就是在每帧编码后使编码器回到初始状态,准备下一帧的编码。卷积编码器的输出和Ⅱ类的比特串接在一起,形成每帧456bit的话音编码块器,速率为456bit/20ms=22.8kbit/s。
图13:GSM系统中的卷积编、译码
(二)卷积码在CDMA/IS-95系统中的应用
在前向和方向信道,CDMA/IS-95系统都使用了约束长度K=9的编码器。其中前向信道编码率r=1/2,连接矢量为: G1= (111101011) (753);G2=(101110001)(561),自由距离为df=12。反向为信道编码率为r=1/3, 编码器的连接矢量为: G1= (101101111)(557);G2= (110110011) (663);G3=(111001001) (711)。自由距离df=18。由于反向信道编码的自由距离大于正向信道的自由距离,因此反向信道有更强的抗噪声干扰能力。事实上,由于前向信道是一点对多点的传输,基站可以向移动台发射导频信号,移动台利用导频信号进行相干解调,而反向信道是多点对一点的传输,采用导频是不现实的,基站只能采用非相干解调。因此,很难保证基站接收各移动台发来的信号都是正交的。所以在反向信道采取许多措施提高抗干扰能力,加大编码码距就是其中之一。对反向全速率业务信道,系统首先对数据帧(172bit/20ms) 进行CRC编码,得到184bit/20ms编码块,接着在其后加上K-1=8位尾比特,再进行卷积编码。信道编码的结果输出速率为3×(184+8) /20ms=28.8kbit/s的编码符号。
图14:CDMA/IS-95系统中的卷积编、译码