CRC校验

CRC校验是怎么回事?

CRC校验又叫做循环冗余校验码,利用二进制除法和求余的方式进行数据查错校验,以保证传输过程中数据的正确完整性。其中多项式为二进制除数,进行校验的数据为被除数,余数则为CRC校验码。

具体地,如发送操作时,对发送数据进行CRC多项式计算,得到固定位数的CRC校验值,将该值附在发送数据的后面一起发送。
接收时首先将接收到的数据进行数据和校验码的分离,然后对数据采用同样的多项式进行计算,若计算结果和接收到的校验值一致,说明数据校验正确,该数据保留,否则说明传输过程中出错,该次传输数据丢弃重发。


CRC多项式计算时采用线性反馈移位寄存器(lfsr)的方式,各级寄存器储存着上一次CRC运算的结果,经整个lfsr后,得到最终的CRC校验结果。
另外不同的多项式表示不同的CRC校验,其对应的lsfr模型不同,检测效果以及CRC校验结果也就不同
比如说16多项式= X16+X12+X^5+1,即CRC16,其CRC码有16bit。


有了多项式之后如何计算
1、 首先确定多项式,根据多项式得到二进制数,多项式最高次数为多少,则在待校验数据后加多少bit的0。
若多项式 = X^4 + x^3 + 1,则对应二进制数11001,最高次=4,因此在被除数后加4bit0。
2、 然后开始模2运算(异或运算),即求余数。
3、 算出来的余数即为CRC校验码,注意余数位数必须比除数少1位,如果不够前面加0补齐
4、 将该校验码加在原数据帧的后面,构成新的发送数据
5、 接收端再次对接收到的数据进行模2运算,比较余数,若相同,说明传输正确。


以上是CRC校验码计算的过程,但实际应用中存在不同的CRC参数模型,从而导致相同的多项式也可能计算出不同的CRC校验码。
因此计算前首先要确定所采用的CRC参数模型。

一个完成的CRC参数模型 = CRC数据位宽(width)、十六进制多项式(POLY)、多项式输入初值(INIT)、输入数据反转(REFIN)、输出数据反转(REFOUT)、输出结果异或(XOROUT).


具体如下:
Width:表示CRC校验位宽;多使用CRC16,CRC校验位宽为16bit

POLY:十六进制多项式。如 x8 + x2 + x + 1,二进制为1 0000 0111,省略最高位1,转换为十六进制为0x07 ( 之所以把最高位去掉,是因为任意多项式生成的二进制数的最高位肯定为1,所以为了便于16进制表示,统一把最高位去掉 )

INIT:和Width位宽一致,如全1或全0

REFIN:决定输入是否进行字节反转,false不反转;true反转

REFOUT:决定输出是否bit反转, false不反转;true反转

XOROUT:输出结果异或,若异或值全0,那么结果与全0异或运算,运算后得到最终的CRC校验结果。

通常如果只给了一个多项式,那么默认:INIT=0x00,REFIN=false,REFOUT=false,XOROUT=0x00


Verilog如何实现?
当已知CRC多项式时,可以首先在某网址下生成对应的verilog代码。
然后根据CRC参数模型在生成的代码基础上进行修改即可。

给出具体的例子:
比如采用CRC16 = X16 + X12 +X5 + 1 ;根据多项式以及width=16生成对应的verilog代码后,若:INIT = 16’hFFFF; XOROUT = 16’h0000; REFIN = false; REFOUT = false;

那么代码如下:

//INIT = 16'hFFFF;     XOROUT = 16'h0000;      REFIN = false;   REFOUT = false;
//crc[15:0]=1+x^5+x^12+x^16;

module crc_16(
        input                  USER_CLK  ,
        input                  SYS_RST   ,
        input                  CRC_EN    ,
        input          [15:0]  DATA_IN   ,
        
        output         [15:0]  CRC_OUT    
    );
    
    wire [15:0]  c        ;
    reg  [15:0]  newcrc   ;
    reg  [15:0]  d        ;
    
    //输入不反转
    assign c = DATA_IN; 
 
    always @ (posedge USER_CLK)begin
        if(SYS_RST)
            d <= 16'hFFFF;//初值
        else begin
            if(CRC_EN)
                d <= newcrc;
            else
                d <= 16'hFFFF; 
        end 
    end

   
    //输出不反转,且进行异或运算    
    assign CRC_OUT = d ^ 16'h0000;
 
    always @ (*)  begin 
       newcrc[0] = d[12] ^ d[11] ^ d[8] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[8] ^ c[11] ^ c[12];
       newcrc[1] = d[13] ^ d[12] ^ d[9] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[9] ^ c[12] ^ c[13];
       newcrc[2] = d[14] ^ d[13] ^ d[10] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[10] ^ c[13] ^ c[14];
       newcrc[3] = d[15] ^ d[14] ^ d[11] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[11] ^ c[14] ^ c[15];
       newcrc[4] = d[15] ^ d[12] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[12] ^ c[15];
       newcrc[5] = d[13] ^ d[12] ^ d[11] ^ d[9] ^ d[8] ^ d[5] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[5] ^ c[8] ^ c[9] ^ c[11] ^ c[12] ^ c[13];
       newcrc[6] = d[14] ^ d[13] ^ d[12] ^ d[10] ^ d[9] ^ d[6] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[6] ^ c[9] ^ c[10] ^ c[12] ^ c[13] ^ c[14];
       newcrc[7] = d[15] ^ d[14] ^ d[13] ^ d[11] ^ d[10] ^ d[7] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[7] ^ c[10] ^ c[11] ^ c[13] ^ c[14] ^ c[15];
       newcrc[8] = d[15] ^ d[14] ^ d[12] ^ d[11] ^ d[8] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[8] ^ c[11] ^ c[12] ^ c[14] ^ c[15];
       newcrc[9] = d[15] ^ d[13] ^ d[12] ^ d[9] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[9] ^ c[12] ^ c[13] ^ c[15];
       newcrc[10] = d[14] ^ d[13] ^ d[10] ^ d[9] ^ d[5] ^ c[5] ^ c[9] ^ c[10] ^ c[13] ^ c[14];
       newcrc[11] = d[15] ^ d[14] ^ d[11] ^ d[10] ^ d[6] ^ c[6] ^ c[10] ^ c[11] ^ c[14] ^ c[15];
       newcrc[12] = d[15] ^ d[8] ^ d[7] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[7] ^ c[8] ^ c[15];
       newcrc[13] = d[9] ^ d[8] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[8] ^ c[9];
       newcrc[14] = d[10] ^ d[9] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[9] ^ c[10];
       newcrc[15] = d[11] ^ d[10] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[10] ^ c[11];
    end
    
    
    
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fighting_FPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值