循环冗余校验原理及程序
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
dtemp(8DOWNTO3):=dtemp(8DOWNTO3)XORPOLYNOMIAL;
ENDIF;
IFdtemp(7)='1'THEN
dtemp(7DOWNTO2):=dtemp(7DOWNTO2)XORPOLYNOMIAL;
ENDIF;
IFdtemp(6)='1'THEN
dtemp(6DOWNTO1):=dtemp(6DOWNTO1)XORPOLYNOMIAL;
rdata_r <=X"000";
dfinish_r <='0';
error01_r <='0';
ELSIFhrecv='1'THEN
rdatacrc <=datacrci;
rdtemp :=datacrci(16DOWNTO5);
IFrdtemp(11)='1'THEN
rdtemp(11DOWNTO6):=rdtemp(11DOWNTO6)XORPOLYNOMIAL;
while(--len>=0)
{
ch=*crcbuf++;ch<<=8;
for(i=0;i<8;i++)
{
crc<<=1;
if((ch&0x8000)!=0)crc|=1;
if(crc>=gx)crc∧=gx;
ch<<=1;
}
}
return((crc==0)?0∶1)
}
以上CRC编码和校验函数结构良好,调用接口清晰,执行效率很高,且具有良好的可
hsend<=hsend_r;
datacrco<=datacrco_r;
ENDPROCESS;
PROCESS(clk,rst_n)--接收端CRC5校验模块.
VARIABLErdtemp:STD_LOGIC_VECTOR(11DOWNTO0);
BEGIN
IFRISING_EDGE(clk)THEN
IFrst_n='0'THEN
用软件方法实现CRC校验,即实现编码、检错和译码功能。
从CRC校验码编码规则可以看出,CRC校验码实际上是由原始数据位串和紧跟其后的
与G(X)位串等长的冗余位串组成,只要求出此冗余位串,发送方即可将原始数据和冗余位
串装配成一CRC位串序列后再发送。CRC校验码译码非常简单,只需从接收到正确CRC
校验码尾部截掉与G(X)位串等长冗余位串,余下的部分即为原始数据位串。CRC校验码错
误检测按模2除法运算,用接收到的CRC位串除以G(X)位串,看是否能够除尽即可确定。
下面的C语言模块实现了CRC校验码编码和检错功能,程序中的G(X)使用CRC-16,
相应的位串为1100000000000101,用十六进制表示为0xc005。函数CrcGen以待发送的原始
数据缓冲区地址和缓冲区长度(字节数)为入口参数,产生并返回遵循CRC校验码编码规则
阶二进制码多项式B7X7+B6X6+B5X5+B4X4+B3X3+B2X2+B1X1+B0X0表示。
例如11000001可表示为
1X7+1X6+0X5+0X4+0X3+0X2+0X1+0X0
一般说,n位二进制数可用(n-1)阶多项式表示。它把要发送的数据位串看成是系数只能
为“1”或“0”的多项式。一个n位的数据块可以看成是从Xn-1到X0的n项多项式的系数
dfinish:OUTSTD_LOGIC;--数据接收完毕
error01:OUTSTD_LOGIC--数据接收错误
);
END;
ARCHITECTUREoneOFcrc5IS
SIGNALdatacrco_r:STD_LOGIC_VECTOR(16DOWNTO0);
SIGNALhsend_r:STD_LOGIC;
BEGIN
PROCESS(clk,rst_n)-----------------------CRC码产生模块.
VARIABLEdtemp:STD_LOGIC_VECTOR(11DOWNTO0);
VARIABLEsdtemp:STD_LOGIC_VECTOR(11DOWNTO0);
BEGIN
IFRISING_EDGE(clk)THEN
ENDIF;
IFdtemp(5)='1'THEN
dtemp(5DOWNTO0):=dtemp(5DOWNTO0)XORPOLYNOMIAL;
ENDIF;
datacrco_r<=sdtemp & dtemp(4DOWNTO0);
hsend_r<='1';
ELSE
hsend_r<='0';
ENDIF;
ENDIF;
rdtemp(6DOWNTO1):=rdtemp(6DOWNTO1)XORPOLYNOMIAL;
ENDIF;
IFrdtemp(5)='1'THEN
rdtemp(5DOWNTO0):=rdtemp(5DOWNTO0)XORPOLYNOMIAL;
ENDIF;
IF(rdtemp(4DOWNTO0)XORrdatacrc(4DOWNTO0))="00000"THEN
ENDIF;
IFrdtemp(10)='1'THEN
rdtemp(10DOWNTO5):=rdtemp(10DOWNTO5)XORPOLYNOMIAL;
ENDIF;
IFrdtemp(9)='1'THEN
rdtemp(9DOWNTO4):=rdtemp(9DOWNTO4)XORPOLYNOMIAL;
ENDIF;
序列,位于数据块左边的最高位是X n-1项的系数,次高位是X n-2项的系数,依此类推,位
于数据块右边的最低位是X0项的系数,这个多项式的阶数为n-1。
多项式乘除法运算过程与普通代数多项式的乘除法相同。多项式的加减法运算以2为
模,加减时不进、错位,如同逻辑异或运算。
采用CRC校验时,发送方和接收方事先约定一个生成多项式G(X),并且G(X)的最高
SIGNALrdata_r:STD_LOGIC_VECTOR(11DOWNTO0);
SIGNALdfinish_r:STD_LOGIC;
SIGNALerror01_r:STD_LOGIC;
SIGNALrdatacrc:STD_LOGIC_VECTOR(16DOWNTO0);
CONSTANTPOLYNOMIAL:STD_LOGIC_VECTOR(5DOWNTO0):="110101";--生成多项式G(x)=x^5 + x^4 + x^2 + 1
ENTITYcrc5IS
PORT(
clk:INSTD_LOGIC;--系统时钟
rst_n:INSTD_LOGIC;--复位信号
sdata:INSTD_LOGIC_VECTOR(11DOWNTO0);--12位有效信息输入
dload:INSTD_LOGIC;--数据装载信号
hrecv:INSTD_LOGIC;--握手信号输入.
生成数据块的CRC校验码的方法是:
(1)设G(X)为r阶,在数据块末尾添加r个0,使数据块为m+r位,则相应的多项式
为XrM(X);
(2)以2为模,用对应于G(X)的位串去除对应于XrM(X)的位串,求得余数位串;
(3)以2为模,从对应于XrM(X)的位串中减去余数位串,结果就是为数据块生成的
带足够校验信息的CRC校验码位串。
项和最低项的系数必须为1。设m位数据块的多项式为M(X),生成多项式G(X)的阶数必需
比M(X)的阶数低。CRC校验码的检错原理是:发送方先为数据块生成CRC校验码,使这
个CRC校验码的多项式能被G(X)除尽,实际发送此CRC校验码;接收方用收到的CRC校
验码除以G(X),如果能除尽,表明传输正确,否则,表示有传输错误,请求重发。
ENDIF;
IFdtemp(10)='1'THEN
dtemp(10DOWNTO5):=dtemp(10DOWNTO5)XORPOLYNOMIAL;
ENDIF;
IFdtemp(9)='1'THEN
dtemp(9DOWNTO4):=dtemp(9DOWNTO4)XORPOLYNOMIAL;
ENDIF;
IFdtemp(8)='1'THEN
rdata_r <=rdatacrc(16DOWNTO5);--校验正确,输出数据.
datacrci:INSTD_LOGIC_VECTOR(16DOWNTO0);--带5位冗余信息的17位CRC码输入
datacrco:OUTSTD_LOGIC_VECTOR(16DOWNTO0);--带5位冗余信息的17位CRC码输出
hsend:OUTSTD_LOGIC;--握手信号输出
rdata:OUTSTD_LOGIC_VECTOR(11DOWNTO0);--12位有效信息输出
在远距离数据通信中,为确保高效而无差错地传送数据,必须对数据进行校验即差错控
制。循环冗余校验CRC(Cyclic Redundancy Check)是对一个传送数据块进行校验,是
一种高效的差错控制方法。
1、循环冗余校验码原理
CRC校验采用多项式编码方法,如一个8位二进制数(B7B6B5B4B3B2B1B0)可以用7
ch<<=1;
}}Βιβλιοθήκη for(i=0;i<16;i++)
{
crc<<=1;
if(crc>=gx)crc∧=gx;
}
return(crc);
}
int crcerr (unsigned char*crcbuf,short len)
{
register short short crc=0,ch,i;
unsigned short gx=0xc005;
例如,设要发送的数据为1101011011,G(X)=X4+X+1,则首先在发送数据块的末尾加4
个0,得到11010110110000,然后用G(X)的位串10011去除,再用11010110110000减去余
数位串1110,得到的即为CRC位串11010110111110,将对应多项式称为T(X),显然,T(X)
{
register unsigned short crc=0,ch,i;
unsigned short gx=0xc005;
while(--len>=0)
{
ch=*databuf++;ch<<=8;
for(i=0;i<8,i++)
{
crc<<=1;
if((ch&0x8000)!=0)crc|=1;
if(crc>=gx)crc∧=gx;
CRC-16 X16+X15+X2+1
CCITT X16+X12+X5+1
CRC校验码实际上是一种线性码,将任意CRC校验码循环移位后仍然是一个CRC校
验码。由于它有良好的结构,检错能力强,易于实现硬件编、译码,因此在数据通信系统中
得到广泛的应用。
2、CRC校验码生成和校验程序
对于某些不宜用硬件实现CRC校验而又需要用CRC校验码进行差错控制的系统中,须
能被G(X)除尽。这样,一旦接收到的CRC位串不能被同样的G(X)的位串除尽,那么一定
有传输错误。
当使用CRC校验码进行差错控制时,除了为G(X)的整数倍的差错多项式不能被检测外,
其它差错均能被查出。CRC校验码的差错控制效果取决于G(X)的阶数,阶数越高,效果越
好。目前,常用的有两种生成多项式G(X)的方法,分别是:
IFrdtemp(8)='1'THEN
rdtemp(8DOWNTO3):=rdtemp(8DOWNTO3)XORPOLYNOMIAL;
ENDIF;
IFrdtemp(7)='1'THEN
rdtemp(7DOWNTO2):=rdtemp(7DOWNTO2)XORPOLYNOMIAL;
ENDIF;
IFrdtemp(6)='1'THEN
IFrst_n='0'THEN
hsend_r<='0';
datacrco_r<=B"0_0000_0000_0000_0000";
ELSIFdload='1'THEN
dtemp :=sdata;
sdtemp :=sdata;
IFdtemp(11)='1'THEN
dtemp(11DOWNTO6):=dtemp(11DOWNTO6)XORPOLYNOMIAL;
移植性。需使用CRC校验码机制的通信软件,均可调用这两个函数高效地实现CRC校验码
软件编码和校验功能。
外加程序
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_Arith.ALL;
USEIEEE.STD_LOGIC_Unsigned.ALL;
的且与G(X)位串等长的2字节冗余位串。函数CrcErr以接收到的CRC校验码缓冲区地址
和缓冲区长度(字节数)为入口参数,返回CRC校验结果,若有错,返回1(真),否则,返回
0(假)。函数代码如下:
unsigned short crcgen(unsigned char* databuf,short len)
ENDIF;
IFdtemp(7)='1'THEN
dtemp(7DOWNTO2):=dtemp(7DOWNTO2)XORPOLYNOMIAL;
ENDIF;
IFdtemp(6)='1'THEN
dtemp(6DOWNTO1):=dtemp(6DOWNTO1)XORPOLYNOMIAL;
rdata_r <=X"000";
dfinish_r <='0';
error01_r <='0';
ELSIFhrecv='1'THEN
rdatacrc <=datacrci;
rdtemp :=datacrci(16DOWNTO5);
IFrdtemp(11)='1'THEN
rdtemp(11DOWNTO6):=rdtemp(11DOWNTO6)XORPOLYNOMIAL;
while(--len>=0)
{
ch=*crcbuf++;ch<<=8;
for(i=0;i<8;i++)
{
crc<<=1;
if((ch&0x8000)!=0)crc|=1;
if(crc>=gx)crc∧=gx;
ch<<=1;
}
}
return((crc==0)?0∶1)
}
以上CRC编码和校验函数结构良好,调用接口清晰,执行效率很高,且具有良好的可
hsend<=hsend_r;
datacrco<=datacrco_r;
ENDPROCESS;
PROCESS(clk,rst_n)--接收端CRC5校验模块.
VARIABLErdtemp:STD_LOGIC_VECTOR(11DOWNTO0);
BEGIN
IFRISING_EDGE(clk)THEN
IFrst_n='0'THEN
用软件方法实现CRC校验,即实现编码、检错和译码功能。
从CRC校验码编码规则可以看出,CRC校验码实际上是由原始数据位串和紧跟其后的
与G(X)位串等长的冗余位串组成,只要求出此冗余位串,发送方即可将原始数据和冗余位
串装配成一CRC位串序列后再发送。CRC校验码译码非常简单,只需从接收到正确CRC
校验码尾部截掉与G(X)位串等长冗余位串,余下的部分即为原始数据位串。CRC校验码错
误检测按模2除法运算,用接收到的CRC位串除以G(X)位串,看是否能够除尽即可确定。
下面的C语言模块实现了CRC校验码编码和检错功能,程序中的G(X)使用CRC-16,
相应的位串为1100000000000101,用十六进制表示为0xc005。函数CrcGen以待发送的原始
数据缓冲区地址和缓冲区长度(字节数)为入口参数,产生并返回遵循CRC校验码编码规则
阶二进制码多项式B7X7+B6X6+B5X5+B4X4+B3X3+B2X2+B1X1+B0X0表示。
例如11000001可表示为
1X7+1X6+0X5+0X4+0X3+0X2+0X1+0X0
一般说,n位二进制数可用(n-1)阶多项式表示。它把要发送的数据位串看成是系数只能
为“1”或“0”的多项式。一个n位的数据块可以看成是从Xn-1到X0的n项多项式的系数
dfinish:OUTSTD_LOGIC;--数据接收完毕
error01:OUTSTD_LOGIC--数据接收错误
);
END;
ARCHITECTUREoneOFcrc5IS
SIGNALdatacrco_r:STD_LOGIC_VECTOR(16DOWNTO0);
SIGNALhsend_r:STD_LOGIC;
BEGIN
PROCESS(clk,rst_n)-----------------------CRC码产生模块.
VARIABLEdtemp:STD_LOGIC_VECTOR(11DOWNTO0);
VARIABLEsdtemp:STD_LOGIC_VECTOR(11DOWNTO0);
BEGIN
IFRISING_EDGE(clk)THEN
ENDIF;
IFdtemp(5)='1'THEN
dtemp(5DOWNTO0):=dtemp(5DOWNTO0)XORPOLYNOMIAL;
ENDIF;
datacrco_r<=sdtemp & dtemp(4DOWNTO0);
hsend_r<='1';
ELSE
hsend_r<='0';
ENDIF;
ENDIF;
rdtemp(6DOWNTO1):=rdtemp(6DOWNTO1)XORPOLYNOMIAL;
ENDIF;
IFrdtemp(5)='1'THEN
rdtemp(5DOWNTO0):=rdtemp(5DOWNTO0)XORPOLYNOMIAL;
ENDIF;
IF(rdtemp(4DOWNTO0)XORrdatacrc(4DOWNTO0))="00000"THEN
ENDIF;
IFrdtemp(10)='1'THEN
rdtemp(10DOWNTO5):=rdtemp(10DOWNTO5)XORPOLYNOMIAL;
ENDIF;
IFrdtemp(9)='1'THEN
rdtemp(9DOWNTO4):=rdtemp(9DOWNTO4)XORPOLYNOMIAL;
ENDIF;
序列,位于数据块左边的最高位是X n-1项的系数,次高位是X n-2项的系数,依此类推,位
于数据块右边的最低位是X0项的系数,这个多项式的阶数为n-1。
多项式乘除法运算过程与普通代数多项式的乘除法相同。多项式的加减法运算以2为
模,加减时不进、错位,如同逻辑异或运算。
采用CRC校验时,发送方和接收方事先约定一个生成多项式G(X),并且G(X)的最高
SIGNALrdata_r:STD_LOGIC_VECTOR(11DOWNTO0);
SIGNALdfinish_r:STD_LOGIC;
SIGNALerror01_r:STD_LOGIC;
SIGNALrdatacrc:STD_LOGIC_VECTOR(16DOWNTO0);
CONSTANTPOLYNOMIAL:STD_LOGIC_VECTOR(5DOWNTO0):="110101";--生成多项式G(x)=x^5 + x^4 + x^2 + 1
ENTITYcrc5IS
PORT(
clk:INSTD_LOGIC;--系统时钟
rst_n:INSTD_LOGIC;--复位信号
sdata:INSTD_LOGIC_VECTOR(11DOWNTO0);--12位有效信息输入
dload:INSTD_LOGIC;--数据装载信号
hrecv:INSTD_LOGIC;--握手信号输入.
生成数据块的CRC校验码的方法是:
(1)设G(X)为r阶,在数据块末尾添加r个0,使数据块为m+r位,则相应的多项式
为XrM(X);
(2)以2为模,用对应于G(X)的位串去除对应于XrM(X)的位串,求得余数位串;
(3)以2为模,从对应于XrM(X)的位串中减去余数位串,结果就是为数据块生成的
带足够校验信息的CRC校验码位串。
项和最低项的系数必须为1。设m位数据块的多项式为M(X),生成多项式G(X)的阶数必需
比M(X)的阶数低。CRC校验码的检错原理是:发送方先为数据块生成CRC校验码,使这
个CRC校验码的多项式能被G(X)除尽,实际发送此CRC校验码;接收方用收到的CRC校
验码除以G(X),如果能除尽,表明传输正确,否则,表示有传输错误,请求重发。
ENDIF;
IFdtemp(10)='1'THEN
dtemp(10DOWNTO5):=dtemp(10DOWNTO5)XORPOLYNOMIAL;
ENDIF;
IFdtemp(9)='1'THEN
dtemp(9DOWNTO4):=dtemp(9DOWNTO4)XORPOLYNOMIAL;
ENDIF;
IFdtemp(8)='1'THEN
rdata_r <=rdatacrc(16DOWNTO5);--校验正确,输出数据.
datacrci:INSTD_LOGIC_VECTOR(16DOWNTO0);--带5位冗余信息的17位CRC码输入
datacrco:OUTSTD_LOGIC_VECTOR(16DOWNTO0);--带5位冗余信息的17位CRC码输出
hsend:OUTSTD_LOGIC;--握手信号输出
rdata:OUTSTD_LOGIC_VECTOR(11DOWNTO0);--12位有效信息输出
在远距离数据通信中,为确保高效而无差错地传送数据,必须对数据进行校验即差错控
制。循环冗余校验CRC(Cyclic Redundancy Check)是对一个传送数据块进行校验,是
一种高效的差错控制方法。
1、循环冗余校验码原理
CRC校验采用多项式编码方法,如一个8位二进制数(B7B6B5B4B3B2B1B0)可以用7
ch<<=1;
}}Βιβλιοθήκη for(i=0;i<16;i++)
{
crc<<=1;
if(crc>=gx)crc∧=gx;
}
return(crc);
}
int crcerr (unsigned char*crcbuf,short len)
{
register short short crc=0,ch,i;
unsigned short gx=0xc005;
例如,设要发送的数据为1101011011,G(X)=X4+X+1,则首先在发送数据块的末尾加4
个0,得到11010110110000,然后用G(X)的位串10011去除,再用11010110110000减去余
数位串1110,得到的即为CRC位串11010110111110,将对应多项式称为T(X),显然,T(X)
{
register unsigned short crc=0,ch,i;
unsigned short gx=0xc005;
while(--len>=0)
{
ch=*databuf++;ch<<=8;
for(i=0;i<8,i++)
{
crc<<=1;
if((ch&0x8000)!=0)crc|=1;
if(crc>=gx)crc∧=gx;
CRC-16 X16+X15+X2+1
CCITT X16+X12+X5+1
CRC校验码实际上是一种线性码,将任意CRC校验码循环移位后仍然是一个CRC校
验码。由于它有良好的结构,检错能力强,易于实现硬件编、译码,因此在数据通信系统中
得到广泛的应用。
2、CRC校验码生成和校验程序
对于某些不宜用硬件实现CRC校验而又需要用CRC校验码进行差错控制的系统中,须
能被G(X)除尽。这样,一旦接收到的CRC位串不能被同样的G(X)的位串除尽,那么一定
有传输错误。
当使用CRC校验码进行差错控制时,除了为G(X)的整数倍的差错多项式不能被检测外,
其它差错均能被查出。CRC校验码的差错控制效果取决于G(X)的阶数,阶数越高,效果越
好。目前,常用的有两种生成多项式G(X)的方法,分别是:
IFrdtemp(8)='1'THEN
rdtemp(8DOWNTO3):=rdtemp(8DOWNTO3)XORPOLYNOMIAL;
ENDIF;
IFrdtemp(7)='1'THEN
rdtemp(7DOWNTO2):=rdtemp(7DOWNTO2)XORPOLYNOMIAL;
ENDIF;
IFrdtemp(6)='1'THEN
IFrst_n='0'THEN
hsend_r<='0';
datacrco_r<=B"0_0000_0000_0000_0000";
ELSIFdload='1'THEN
dtemp :=sdata;
sdtemp :=sdata;
IFdtemp(11)='1'THEN
dtemp(11DOWNTO6):=dtemp(11DOWNTO6)XORPOLYNOMIAL;
移植性。需使用CRC校验码机制的通信软件,均可调用这两个函数高效地实现CRC校验码
软件编码和校验功能。
外加程序
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_Arith.ALL;
USEIEEE.STD_LOGIC_Unsigned.ALL;
的且与G(X)位串等长的2字节冗余位串。函数CrcErr以接收到的CRC校验码缓冲区地址
和缓冲区长度(字节数)为入口参数,返回CRC校验结果,若有错,返回1(真),否则,返回
0(假)。函数代码如下:
unsigned short crcgen(unsigned char* databuf,short len)