实验九 (2,1,5)卷积码编码译码技术一、实验目的1、掌握(2,1,5)卷积码编码译码技术2、了解纠错编码原理。
二、实验内容1、(2,1,5)卷积码编码。
2、(2,1,5)卷积码译码。
三、预备知识1、纠错编码原理。
2、(2,1,5)卷积码的工作原理。
四、实验原理/卷积码是将发送的信息序列通过一个线性的,有限状态的移位寄存器而产生的编码。
通常卷积码的编码器由K级(每级K比特)的移位寄存器和n个线性代数函数发生器(这里是模2加法器)组成。
若以(n,k,m)来描述卷积码,其中k为每次输入到卷积编码器的bit数,n 为每个k元组码字对应的卷积码输出n元组码字,m为编码存储度,也就是卷积编码器的k元组的级数,称m+1= K为编码约束度m称为约束长度。
卷积码将k 元组输入码元编成n元组输出码元,但k和n通常很小,特别适合以串行形式进行传输,时延小。
与分组码不同,卷积码编码生成的n元组元不仅与当前输入的k元组有关,还与前面m-1个输入的k元组有关,编码过程中互相关联的码元个数为n*m。
卷积码的纠错性能随m的增加而增大,而差错率随N的增加而指数下降。
在编码器复杂性相同的情况下,卷积码的性能优于分组码。
编码器随着信息序列不断输入,编码器就不断从一个状态转移到另一个状态并同时输出相应的码序列,所以图3所示状态图可以简单直观的描述编码器的编码过程。
因此通过状态图很容易给出输入信息序列的编码结果,假定输入序列为110100,首先从零状态开始即图示a状态,由于输入信息为“1”,所以下一状态为b并输出“11”,继续输入信息“1”,由图知下一状态为d、输出“01”……其它输入信息依次类推,按照状态转移路径a->b->d->c->b->c->a输出其对应的编码结果“”。
译码方法⒈代数代数译码是将卷积码的一个编码约束长度的码段看作是[n0(m+1),k0(m+1)]线性分组码,每次根据(m+1)分支长接收数字,对相应的最早的那个分支上的信息数字进行估计,然后向前推进一个分支。
上例中信息序列 =(10111),相应的码序列 c=(1)。
若接收序列R=(1),先根据R的前三个分支(101000)和码树中前三个分支长的所有可能的 8条路径(000000…)、(000011…)、(001110…)、(001101…)、(111011…)、(111000…)、(110101…)和(110110…)进行比较,可知(111001)与接收序列(101000)的距离最小,于是判定第 0分支的信息数字为 0。
然后以R的第 1~3分支数字(100001)按同样方法判决,依此类推下去,最后得到信息序列的估值为=(10111),遂实现了纠错。
这种译码法,译码时采用的接收数字长度或译码约束长度为(m+1)n0,所以只能纠正不多于(dmin-1)/2个错误(n长上的)。
实用中多采用反馈择多逻辑译码法实现。
⒉维特比维特比译码是根据接收序列在码的格图上找出一条与接收序列距离(或其他量度)为最小的一种算法。
它和运筹学中求最短路径的算法相类似。
若接收序列为R=(1),译码器从某个状态,例如从状态ɑ出发,每次向右延伸一个分支(对于l<L,从每个节点出发都有 2=2种可能的延伸,其中L是信息序列段数,对l≥L,只有一种可能),并与接收数字相应分支进行比较,计算它们之间的距离,然后将计算所得距离加到被延伸路径的累积距离值中。
对到达每个状态的各条路径(有2=2条)的距离累积值进行比较,保留距离值最小的一条路径,称为幸存路径(当有两条以上取最小值时,可任取其中之一),译码过程如图。
图中标出到达各级节点的幸存路径的距离累积值。
对给定 R的估值序列为=(10111)。
这种算法所保留的路径与接收序列之间的似然概率为最大,所以又称为最大似然译码。
这种译码的译码约束长度常为编码约束长度的数倍,因而可以纠正不多于(df/2)个错误。
维特比译码器的复杂性随m呈指数增大。
实用中m不大于10。
它在卫星和深空通信中有广泛的应用。
在解决码间串扰和数据压缩中也可应用。
⒊ 序贯译码序贯译码是根据接收序列和编码规则,在整个码树中搜索(既可以前进,也可以后退)出一条与接收序列距离(或其他量度)最小的一种算法。
由于它的译码器的复杂性随m值增大而线性增长,在实用中可以选用较大的m值(如20~40)以保证更高的可靠性。
许多深空和海事通信系统都采用序贯译码。
五、实验仿真这里我用c语言实现(2,1,5)卷积码编码,viterbi解码。
六、实验仿真程序#include <>#include ""#define N 34》#include ""#include <>#include<>#define randomize() srand((unsigned)time(NULL))int s[16]={0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};encode(unsigned int *symbols, /*编码输出*/unsigned int *data, /*编码输入*/unsigned int nbytes, /*nbytes=n/16,n为实际输入码字的数目 */ unsigned int startstate /*定义初始化状态*/'){int j;unsigned int input,a0=0,a1=0,a2=0,a3=0;for(j=0;j<nbytes;j++){input=*data;data++;*symbols = input^a0^a1;symbols++;*symbols = input^a0^a2^a3;{symbols++;a3=a2;a2=a1;a1=a0;a0=input;}return 0;}int trandistance(int m, int stat1,int stat2) /*符号m与从state1到state2时输出符号的汉明距离,¥如果state1无法到state2则输出度量值为10000*/{int c;int sym,sym1,sym2;sym1=((stat2>>3)&1)^((stat1>>3)&1)^((stat1>>2)&1);sym2=((stat2>>3)&1)^((stat1>>3)&1)^((stat1>>1)&1)^(stat1&1);sym=(sym1<<1) | sym2;if((((stat1>>3)&1)==((stat2>>2)&1))&&(((stat1>>2)&1)==((stat2>>1)&1))&&( ( (st at1>>1)&1)==(stat2&1)))c=((m&1)^(sym&1))+(((m>> 1)&1)^((sym >> 1)&1));elsec=10000;~return(c);}int traninput(int a,int b) /*状态从a到b时输入卷积码的符号*/{int c;if((((a>>3)&1)==((b>>2)&1))&&(((a>>2)&1)==((b>>1)&1))&&(((a>>1)&1)==(b&1))) c=((b>>3)&1);elsec=-1;"return(c);}int tranoutput(int a,int b) /*状态从a到b时卷积码输出的符号*/{int c,s1,s2;s1=((b>>3)&1)^((a>>3)&1)^((a>>2)&1);s2=((b>>3)&1)^((a>>3)&1)^((a>>1)&1)^(a&1);if((((a>>3)&1)==((b>>2)&1))&&(((a>>2)&1)==((b>>1)&1))&&(((a>>1)&1)==(b&1)) )c=(s1<<1)|s2;else,c=-1;return(c);}void viterbi(int initialstate, /*定义解码器初始状态*/int *viterbiinput, /*解码器输入码字序列*/int *viterbioutput) /*解码器输出码字序列*/{struct sta /*定义网格图中每一点为一个结构体,其元素包括*/{int met; /*转移到此状态累计的度量值*/【int value; /*输入符号 */struct sta *last; /*及指向前一个状态的指针*/ };struct sta state[16][N];struct sta *g;int i,j,p,q,t,r,u,l;for(i=0;i<16;i++) /* 初始化每个状态的度量值*/ {for(j=0;j<N;j++)state[i][j].met=0;、}for(int m=0;m<16;m++){state[m][0].met=trandistance(*viterbiinput,initialstate,s[m]);state[m][0].value=traninput(initialstate,s[m]);state[m][0].last=NULL;}for(t=1;t<N;t++){】for(p=0;p<8;p++)for(q=0;q<16;q++){if((trandistance(viterbiinput[t],s[p],s[q])==10000)||(trandistance(viterbi input[t],s[p+8],s[q])==10000)){ast=NULL;0continue;}else{(intmet1=state[p][t-1].met+trandistance(viterbiinput[t],s[p],s[q]);intmet2=state[p+8][t-1].met+trandistance(viterbiinput[t],s[p+8],s[q]);if(met1>met2){state[q][t].met=met2;state[q][t].value=traninput(s[p+8],s[q]);state[q][t].last=&state[p+8][t-1];}else{state[q][t].met=met1;)state[q][t].value=traninput(s[p],s[q]);state[q][t].last=&state[p][t-1];}}}}r=state[0][N-1].met; /*找出n步后度量值最小的状态,准备回溯路由*/g=&state[0][N-1];)for(u=N;u>0;u--) /*向前递归的找出最大似然路径 */{viterbioutput[u-1]=g->value;g=g->last;}/* for(u=0;u<8;u++)*(viterbioutput+u)=state[u][2].met; */ /*此行程序可用于检测第n列的度量值*/}void decode(unsigned int *input, int *output,int n)|{int viterbiinput[100];int j;for(j=0;j<n+4;j++){viterbiinput[j]=(input[j*2]<<1)|input[j*2+1];//printf("%3d",viterbiinput[j]);}viterbi(s[0],viterbiinput,output);}~void main(){int n=30,i,m,j=0,decodeoutput[100],jj=0;unsigned int encodeinput[100],wrong[10]={0},encodeoutput[100];randomize();for(i=0; i<n; i++)encodeinput[i]=rand()%2;encodeinput[n]=0;encodeinput[n+1]=0;encodeinput[n+2]=0;|encodeinput[n+3]=0;encode(encodeoutput,encodeinput,n+4,s[0]);printf("信息序列 :\n");for(i=0;i<n; i++)printf("%2d",encodeinput[i]);printf("\n");printf("对信息序列编码后的输出 :\n");for(i=0;i<(n+4)*2;i++){`printf("%2d",encodeoutput[i]);if(i%20==19)printf("\n");}printf("\n");decode(encodeoutput,decodeoutput,n+4);printf("无错误出现时对编码输出viterbi译码得到的序列:\n");for(int ii=0;ii<n;ii++)printf("%2d",decodeoutput[ii]);:printf("\n");for(i=0;i<n;i++){if(encodeinput[i]!=decodeoutput[i])jj++;}printf("译错的个数:%d\n",jj);printf("请输入出错的个数\n");scanf("%d",&m);printf("请输入每个出错所在的位数\n");:for(i=0;i<m;i++){scanf("%d",&wrong[m]);if(encodeoutput[wrong[m]]==0)encodeoutput[wrong[m]]=1;elseencodeoutput[wrong[m]]=0;}printf("输入viterbi解码器的待解码序列(即有误的序列) :\n");for(i=0;i<(n+4)*2;i++){%printf("%2d",encodeoutput[i]);if(i%20==19)printf("\n");}printf("\n");decode(encodeoutput,decodeoutput,n+4);printf("经viterbi解码后得到的信息序列:\n");for(i=0;i<n;i++)printf("%2d",decodeoutput[i]);printf("\n");for(i=0;i<n;i++){if(encodeinput[i]!=decodeoutput[i])j++;}printf("译错的个数:%d\n",j);system("pause");}。