(2,1,3)卷积码C语言
- 格式:doc
- 大小:23.50 KB
- 文档页数:6
信息论与编码--卷积码(掌握利用编码电路求生成矩阵和监督矩阵)差错控制编码系统中除了使用分组码之外,另一类广泛应用的称为卷积码,在分组码的编码和译码过程中,每个码字的监督元只与本码字的信息元有关,而与其它码字的信息元无关,即分组码的编码器是一个无记忆的逻辑电路。
但是,卷积码的编码过程中,本码字的监督元不仅与本码字的信息元有关,而且与前m 个码字的信息元有关,因此卷积码的编码器是一个有记忆的时序电路。
卷积码由于更充分地利用码字之间的相关性,可以减少码字长度,简化编译码电路,并得到较好的差错控制性能,因此卷积码在通信领域,特别是卫星通信,空间通信领域得到广泛的应用。
7-1 卷积码的基本原理 7-1-1 卷积码的基本概念[例子]:通过一个例子说明卷积码的一些基本概念;下图给出了一个(3,2,2)卷积码编码器的原理图,当某一时刻,编码器输入并行一个信息码字为mi=[mi(1),mi(2)],编码器并行输出由三个码元组成的卷积码的码字,c i (1)c (1)c i (2) c i (3)m i (1) m i (2)[ci]=[ci(1),ci(2),ci(3)]=[mi(1),mi(2),pi]。
[ci]称为一个码字。
mi 为信息元,pi 为监督元。
可以看出卷积码的输入输出关系为:ci(1)=mi(1) ci(2)=mi(2)ci(3)=mi(1)+mi(2)+mi-1(2)+mi-2(1)可见,卷积码当前输出的码字的监督元不仅与当前输入的信息元有关而且还与前2个码元有关。
这时编码器由2级移位寄存器构成。
定义:卷积码字中码元的个数为n0,码字中信息元个数为k0,由m 级移位寄存器构成的编码器称m 为编码码字约束长度。
有的教材称m’=m+1为约束长度,(m+1)n0为编码码元约束长度。
卷积码记为(n0,k0,m)。
定义:R=k0/n0为码率(Code rate)。
它是表示卷积码的编码效率。
卷积码的编码器的一般形式为:看以下卷积码的约束关系图:在译码时,译码在ci 时要利用到ci-1,ci-2,同时译码字ci+1,ci+2时还要利用到ci 。
No.15 (2,1,3)卷积码的编码及译码摘要:本报告对于 (2,1,3)卷积码原理部分的论述主要参照啜刚教材和课件,编程仿真部分绝对原创,所有的程序都是在Codeblocks 8.02环境下用C语言编写的,编译运行都正常。
完成了卷积码的编码程序,译码程序,因为对于短于 3 组的卷积码,即2 bit 或4 bit 纠错是没有意义的,所以对正确的短序列直接译码,对长序列纠错后译码,都能得到正确的译码结果。
含仿真结果和程序源代码。
如果您不使用Codeblocks 运行程序,则可能不支持中文输出显示,但是所有的数码输出都是正确的。
一、卷积码编码原理卷积码编码器对输入的数据流每次1bit或k bit进行编码,输出n bit编码符号。
但是输出的分支码字的每个码元不仅于此时可输入的k个嘻嘻有关,业余前m个连续式可输入的信息有关,因此编码器应包含m级寄存器以记录这些信息。
k通常卷积码表示为(n,k,m).编码率r —n当k=1时,卷积码编码器的结构包括一个由m个串接的寄存器构成的移位寄存器(成为m级移位寄存器、n个连接到指定寄存器的模二加法器以及把模二加法器的输出转化为穿行的转换开关。
本报告所讲的(2,1,3)卷积码是最简单的卷积码。
就是n 2,k 1,m 3的卷积码。
每次输入1 bit输入信息,经过3级移位寄存器,2个连接到指定寄存器的模二加法器,并把加法器输出转化为串行输出。
EncoderOuTi>iit编码器如题所示。
二、卷积码编码器程序仿真C语言编写的仿真程序。
为了简单起见,这里仅仅提供数组长度30 bit的仿真程序,当然如果需要可以修改数组大小。
为了更精练的实现算法,程序输入模块没有提供非法字符处理过程,如果需要也可以增加相应的功能。
进入程序后,先提示输入数据的长度,请用户输入int (整型数)程序默认用户输入的数据小于30,然后提示输入01数码,读入数码存储与input数组中,然后运算输出卷积码。
实验二卷积码编码及译码实验一、实验目的通过本实验掌握卷积编码的特性、产生原理及方法,卷积码的译码方法,尤其是维特比译码的原理、过程、特性及其实现方法。
二、实验内容1、观察NRZ基带信号及其卷积编码信号。
2、观察帧同步信号的生成及巴克码的特性。
3、观察卷积编码信号打孔及码速率匹配方法。
4、观察接收端帧同步过程及帧同步信号。
5、观察译码结果并深入理解维特比译码的过程。
6、观察随机差错及突发差错对卷积译码的影响。
三、基本原理1、卷积码编码卷积码是一种纠错编码,它将输入的k个信息比特编成n个比特输出,特别适合以串行形式进行传输,时延小。
卷积码编码器的形式如图17-1所示,它包括:一个由N段组成的输入移位寄存器,每段有k段,共Nk个寄存器;一组n个模2和相加器;一个由n级组成的输出移位寄存器,对应于每段k个比特的输入序列,输出n个比特。
图17-1 卷积编码器的一般形式由图17-1可以看到,n个输出比特不仅与当前的k个输入信息有关,还与前(N-1)k 个信息有关。
通常将N称为约束长度(有的书中也把约束长度定为nN或N-1)。
常把卷积码记为:(n 、k 、N ),当k =1时,N -1就是寄存器的个数。
编码效率定义为:/c R k n =(17-1)卷积码的表示方法有图解表示法和解析表示法两种:解析法,它可以用数学公式直接表达,包括离散卷积法、生成矩阵法、码生成多项式法;图解表示法,包括树状图、网络图和状态图(最的图形表达形式)三种。
一般情况下,解析表示法比较适合于描述编码过程,而图形法比较适合于描述译码。
(1)图解表示法 (2)解析法下面以(2,1,3)卷积编码器为例详细讲述卷积码的产生原理和表示方法。
(2,1,3)卷积码的约束长度为3,编码速率为1/2,编码器的结构如图17-2所示。
jj图17-2 (2,1,3)卷积编码器这里我们主要介绍码多项式法。
我们可以用多项式来表示输入序列、输出序列、编码器中移位寄存器与模2和的连接关系。
实验四 卷积码的编解码一、实验目的1、掌握卷积码的编解码原理。
2、掌握卷积码的软件仿真方法。
3、掌握卷积码的硬件仿真方法。
4、掌握卷积码的硬件设计方法。
二、预习要求1、掌握卷积码的编解码原理和方法。
2、熟悉matlab 的应用和仿真方法。
3、熟悉Quatus 的应用和FPGA 的开发方法。
三、实验原理1、卷积码编码原理在编码器复杂度相同的情况下,卷积码的性能优于分组码,因此卷积码几乎被应用在所有无线通信的标准之中,如GSM , IS95和CDMA 2000 的标准中。
卷积码通常记作( n0 , k0 , m) ,它将k 0 个信息比特编为n 0 个比特, 其编码效率为k0/ n0 , m 为约束长度。
( n0 , k0 , m ) 卷积码可用k0 个输入、n0 个输出、输入存储为m 的线性有限状态移位寄存器及模2 加法计数器来实现。
本实验以(2,1,3)卷积码为例加以说明。
图1就是卷积码编码器的结构。
图1 (2,1,3)卷积码编码器其生成多项式为:21()1G D D D =++; 22()1G D D =+;如图1 所示的(2,1,3)卷积码编码器中,输入移位寄存器用转换开关代替,每输入一个信息比特经编码产生二个输出比特。
假设移位寄存器的初始状态为全0,当第一个输入比特为0时,输出比特为00;若输入比特为1,则输出比特为11。
随着第二个比特输入,第一个比特右移一位,此时输出比特同时受到当前输入比特和前一个输入比特的影响。
第三个比特输入时,第一、二个比特分别右移一位,同时输出二个由这三位移位寄存器存储内容所共同决定的比特。
依次下去就完成了编码过程。
下面是卷积码的网格图表示。
他是比较清楚而又紧凑的描述卷积码的一种方式,它是最常用的描述方式之一。
图2(2,1,3)卷积码的网格图表示2、Viterbi译码原理2k N-种状态,每个节点(即每个状态)有2k条支路引入也有2k条如图2所示,卷积码网格图中共有(1)支路引出。
卷积码卷积码是一种有记忆的编码,在任意给定的时间单元处,编码器的n 个输出不仅与此时间单元的k 个输入有关,而且也与前m 个输入有关。
卷积码通常表示为:(n,k,m ) 本次仿真采用(2,1,3)卷积码。
性能参数如下:生成矩阵G : 1 0 1 11 1 1 1编码个数: n=2信息码个数: k=1约束长度: N=m+1=4卷积码的码率:n k R c / =1/2MATLAB 源程序function output=cnv_encd(g,k0,input)%output=cnv_encd(g,k0,input) 卷积码编码函数%g 生成矩阵%k0 输入码长%input 输入信源序列%output 输出卷积编码序列%+ 0..0if rem(length(input),k0)>0input=[input,zeros(size(1:k0-rem(length(input),k0)))]; endn=length(input)/k0;%g sizeif rem(size(g,2),k0)>0error('Error,g is not of the right size.')end%li L,n0li=size(g,2)/k0;n0=size(g,1);%+ 0..0u=[zeros(size(1:(li-1)*k0)),input,zeros(size(1:(li-1)*k0))]; %uu lie i*T,i=1,2...u1=u(li*k0:-1:1);for i=1:n+li-2u1=[u1,u((i+li)*k0:-1:i*k0+1)];enduu=reshape(u1,li*k0,n+li-1);%output reshapeoutput=reshape(rem(g*uu,2),1,n0*(n+li-1));%output=cnv_encd(g,k0,input)卷积码编码函数%卷积码的维特比译码函数function[decoder_output,survivor_state,cumulated_metric]=viterbi(G,k,channel_output)%VITERBI 卷积码的维特比解码器%[decoder_ouput,survivor_state,cumulated_metric]=viterbi(G,k,channel_output)% G是一个n*Lk矩阵,该矩阵的每一行确% 定了从移位记错器到第n个输出间的连接,% 是码速率。
#include<iostream>using namespace std;int table1[8]={1,2,4,8,16,32,64,128};int myn=0;int stalen=0;int stan0[256][2]={0};//输入0时个状态的输出int stan1[256][2]={0};//输入1时各状态的输出int stachn[256][2]={0};//状态装换表int myg1[10]={0};int myg2[10]={0};int myout[100]; //int myoutsym=0;void chartobits(char ch,int *bits);char bitstochar(int *bits);void convolution(void);void creatsta(void);void myinput(void);int main(){char exit_char;myinput();creatsta();convolution();cin>>exit_char;}void myinput(void){int i,j;cout<<"输入编码的约束长度N:(3<N<9)"<<endl;cin>>myn;stalen=int(pow(2、0,myn-1));cout<<"选择默认的编码矢量则输入1,输入2则可输入其她的编码矢量"<<endl;cin>>i;if(i==1){switch(myn){case 3: myg1[0]=1,myg1[1]=1,myg1[2]=1;myg2[0]=1,myg2[1]=0,myg2[2]=1;break;case 4: myg1[0]=1,myg1[1]=1,myg1[2]=1,myg1[3]=1;myg2[0]=1,myg2[1]=0,myg2[2]=1,myg2[3]=1;break;case 5: myg1[0]=1,myg1[1]=0,myg1[2]=1,myg1[3]=1,myg1[4]=1;myg2[0]=1,myg2[1]=1,myg2[2]=0,myg2[3]=1,myg2[4]=1;break;case 6: myg1[0]=1,myg1[1]=0,myg1[2]=1,myg1[3]=1,myg1[4]=1,myg1[5]=1;myg2[0]=1,myg2[1]=1,myg2[2]=0,myg2[3]=1,myg2[4]=0,myg2[5]=1;break;case 7: myg1[0]=1,myg1[1]=0,myg1[2]=0,myg1[3]=1,myg1[4]=1,myg1[5]=1,myg1[6]=1;myg2[0]=1,myg2[1]=1,myg2[2]=0,myg2[3]=1,myg2[4]=1,myg2[5]=0,myg2[6]=1;break;case 8: myg1[0]=1,myg1[1]=0,myg1[2]=0,myg1[3]=1,myg1[4]=1,myg1[5]=1,myg1[6]=1,myg1[7]=1;myg2[0]=1,myg2[1]=1,myg2[2]=1,myg2[3]=0,myg2[4]=0,myg2[5]=1,myg2[6]=0,myg2[7]=1;break;case 9: myg1[0]=1,myg1[1]=1,myg1[2]=0,myg1[3]=1,myg1[4]=0,myg1[5]=1,myg1[6]=1,myg1[7]=1,m yg1[8]=1;myg2[0]=1,myg2[1]=0,myg2[2]=0,myg2[3]=0,myg2[4]=1,myg2[5]=1,myg2[6]=1,myg2[7]=0,m yg2[8]=1;break;}}else{cout<<"输入g1"<<endl;for(j=0;j<myn;j++)cin>>myg1[j];cout<<"输入g2"<<endl;for(j=0;j<myn;j++)cin>>myg2[j];}cout<<"连接矢量1为"<<endl;for(j=0;j<myn;j++)cout<<myg1[j]<<" ";cout<<endl;cout<<"连接矢量2为"<<endl;for(j=0;j<myn;j++)cout<<myg2[j]<<" ";cout<<endl;cout<<"stalen: "<<stalen;cout<<endl;}void creatsta(void){int i,j,k,myi,myj;int tembits[10];for(i=0;i<stalen;i++){stan1[i][0]=0;stan1[i][1]=0;stan0[i][0]=0;stan0[i][1]=0;stachn[i][0]=i/2;myi=i;for(j=0;j<myn;j++){if(myi>=pow(2、0,myn-1-j)){tembits[j]=1;myi=myi-pow(2、0,myn-1-j);}else{tembits[j]=0;}}/*for(k=0;k<myn;k++)cout<<tembits[k]<<" ";cout<<endl;*/for(k=0;k<myn;k++){stan0[i][0]+=myg1[k]*tembits[k];stan0[i][1]+=myg2[k]*tembits[k];}stan0[i][0]=stan0[i][0]%2;stan0[i][1]=stan0[i][1]%2;myi=i+int(pow(2、0,myn-1));stachn[i][1]=myi/2;for(j=0;j<myn;j++){if(myi>=pow(2、0,myn-1-j)){tembits[j]=1;myi=myi-pow(2、0,myn-1-j);}else{tembits[j]=0;}}/*for(k=0;k<myn;k++)cout<<tembits[k]<<" ";cout<<endl;*/for(k=0;k<myn;k++){stan1[i][0]+=myg1[k]*tembits[k];stan1[i][1]+=myg2[k]*tembits[k];}stan1[i][0]=stan1[i][0]%2;stan1[i][1]=stan1[i][1]%2;}cout<<"状态转移出"<<endl;for(i=0;i<stalen;i++)cout<<stachn[i][0]<<","<<stachn[i][1]<<" ";cout<<endl;cout<<"输入0状态转移后的输出"<<endl;for(i=0;i<stalen;i++)cout<<stan0[i][0]<<","<<stan0[i][1]<<" ";cout<<endl;cout<<"输入1状态转移后的输出"<<endl;for(i=0;i<stalen;i++)cout<<stan1[i][0]<<","<<stan1[i][1]<<" ";cout<<endl;}void chartobits(char ch,int *bits){int i;for(i=0;i<8;i++){if(ch<0)bits[i]=1;elsebits[i]=0;ch=ch<<1;}}char bitstochar(int *bits){char temp=0;int i;for(i=0;i<8;i++){if(bits[i]==1)temp+=table1[7-i];}return temp;}void convolution(){FILE *fp_input,*fp_output;if(!(fp_input=fopen("D://input、txt","r"))==1){cout<<"failed to open input_file"<<endl;exit(0);}elsecout<<"we opened the input_file "<<endl;if(!(fp_output=fopen("D://output、txt","w+"))==1){ cout<<"failed to open output_file"<<endl;exit(0);}cout<<"we opened the output_file "<<endl;char ch;int i,j;int mybits[8],mytembits[8];int mysta=0;int wcout;char wch;for(ch=fgetc(fp_input);feof(fp_input)==0;ch=fgetc(fp_input)){ chartobits(ch,mybits);/*cout<<"输入数据为"<<endl;for(i=0;i<8;i++)cout<<mybits[i]<<" ";cout<<endl;*/for(i=0;i<8;i++){if(mybits[i]==0){myout[myoutsym++]=stan0[mysta][0];myout[myoutsym++]=stan0[mysta][1];mysta=stachn[mysta][0];}else{myout[myoutsym++]=stan1[mysta][0];myout[myoutsym++]=stan1[mysta][1];mysta=stachn[mysta][1];}}/*cout<<"输出数据1为"<<endl;for(temi=0;temi<myoutsym;temi++)cout<<myout[temi]<<" ";cout<<endl;*/if(myoutsym>=8){wcout=myoutsym/8;for(i=0;i<wcout;i++){for(j=0;j<8;j++)mytembits[j]=myout[8*i+j];wch=bitstochar(mytembits);fputc(wch,fp_output);/*cout<<"输出数据2为"<<endl;cout<<wch<<" ";*/}for(i=0;i<myoutsym-wcout*8;i++)myout[i]=myout[wcout*8+i];myoutsym=myoutsym-wcout*8;}for(i=0;i<myn-1;i++){myout[myoutsym++]=stan0[mysta][0];myout[myoutsym++]=stan0[mysta][1];mysta=stachn[mysta][0];}wcout=myoutsym/8;for(i=0;i<wcout;i++){for(j=0;j<8;j++)mytembits[j]=myout[8*i+j];wch=bitstochar(mytembits);fputc(wch,fp_output);}for(i=0;i<myoutsym-wcout*8;i++)myout[i]=myout[wcout*8+i];myoutsym=myoutsym-wcout*8;if(myoutsym!=0){for(i=0;i<8-myoutsym;i++)myout[myoutsym++]=0;}for(j=0;j<8;j++)mytembits[j]=myout[j];wch=bitstochar(mytembits);fputc(wch,fp_output);fclose(fp_input);fclose(fp_output);}。
(2,1,3)卷积码C语言#include <stdio.h>#include "Conio.h"#define N 7#include "math.h"#include <stdlib.h>#include<time.h>#define randomize() srand((unsigned)time(NULL))encode(unsigned int *symbols, /*编码输出*/unsigned int *data, /*编码输入*/unsigned int nbytes, /*nbytes=n/16,n为实际输入码字的数目*/unsigned int startstate /*定义初始化状态*/){int j;unsigned int input,a1=0,a2=0;for(j=0;j<nbytes;j++){ input=*data;data++;*symbols = input^a1^a2;symbols++;*symbols = input^a2;symbols++;a2=a1;a1=input;}return 0;}int trandistance(int m, /*符号m与从state1到state2时输出符号的汉明距离,如果state1无法到state2则输出度量值为100*/int state1,int state2){int c;int sym,sym1,sym2;sym1=((state2>>1)&1)^(state2&1)^(state1&1);sym2=((state2>>1)&1)^(state1&1);sym=(sym1<<1) | sym2;if ( ((state1&2)>>1)==(state2&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;c=((b&2)>>1);return(c);}int tranoutput(int a,int b) /*状态从a到b时卷积码输出的符号*/{int c,s1,s2;s1=(a&1)^((a&2)>>1)^((b&2)>>1);s2=(a&1)^((b&2)>>1);c=(s1<<1)|s2;return(c);}void viterbi(int initialstate, /*定义解码器初始状态*/int *viterbiinput, /*解码器输入码字序列*/int *viterbioutput /*解码器输出码字序列*/){struct sta /*定义网格图中每一点为一个结构体,其元素包括*/ {int met; /*转移到此状态累计的度量值*/int value; /*输入符号 */struct sta *last; /*及指向前一个状态的指针*/struct sta state[4][N];struct sta *g,*head;int i,j,p,q,t,r,u,l;for(i=0;i<4;i++) /* 初始化每个状态的度量值*/for(j=0;j<N;j++)state[i][j].met=0;for(l=0;l<4;l++){state[l][0].met=trandistance(*viterbiinput,initialstate,l);state[l][0].value=traninput(initialstate,l);state[l][0].last=NULL;}viterbiinput++; /*扩展第一步幸存路径*/for(t=1;t<N;t++){for(p=0;p<4;p++){state[p][t].met=state[0][t-1].met+trandistance(*viterbiinput,0,p);state[p][t].value=traninput(0,p);state[p][t].last=&state[0][t-1];for(q=0;q<4;q++){if(state[q][t-1].met+trandistance(*viterbiinput,q,p)<state[p][t].met) {state[p][t].met=state[q][t-1].met+trandistance(*viterbiinput,q,p); state[p][t].value=traninput(q,p);state[p][t].last=&state[q][t-1];}}}viterbiinput++;} /*计算出剩余的幸存路径*/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+2;j++){viterbiinput[j]=(input[j*2]<<1)|input[j*2+1];//printf("%3d",viterbiinput[j]);}viterbi(0,viterbiinput,output);}void main(){unsigned int encodeinput[100],wrong[10]={0,0,0,0,0,0,0,0,0,0},encodeoutput[100]; int n=5,i,m,j=0,decodeinput[100],decodeoutput[100];randomize();for(i=0; i<n; i++)encodeinput[i]=rand()%2;encodeinput[n]= encodeinput[n+1]=0;encode(encodeoutput,encodeinput,n+2,0);printf("the input of encoder is :\n");for(i=0;i<n; i++)printf("%2d",encodeinput[i]);printf("\n");printf("the output of encoder is :\n");for(i=0;i<(n+2)*2;i++){printf("%2d",encodeoutput[i]);if(i%20==19)printf("\n");}printf("\n");printf("please input the number of the wrong bit\n");scanf("%d",&m);printf("please input the positions of the wrong bit(0-9)\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("the input of decoder is :\n");for(i=0;i<(n+2)*2;i++){printf("%2d",encodeoutput[i]);if(i%20==19)printf("\n");}printf("\n");decode(encodeoutput,decodeoutput,n+2);printf("the output of decoder is :\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("the number of incorrect bit is:%d\n",j);}。