循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。
CRC算法参数模型解释:
NAME:校验算法模型名称。
WIDTH:CRC校验宽度,即CRC比特数。
POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生成项是0x104C11DB7。
INIT:算法开始时计算(crc)的初始化预置值,十六进制表示。
REFIN:要校验的数据,每个字节是否按位反转,True或False。
REFOUT:在计算后之后,异或输出之前,整个数据是否按位反转,True或False。
XOROUT:计算结果,与此参数异或后,得到输出最终的CRC值。
常见CRC算法模型如下:
多项式的次方位不为0,则该位值为1,如:多项式CRC8 (0x31): x^8 + x^5 + x^4 + 1 即 1_0011_0001 则为8位数据的第0位、第4位、第5位需进行异或校验。
CRC校验码生成步骤如下:
发送端将移位补零后数据的低K位0替换成CRC校验码组成新的数据发送出去,接收端对带有校验码的数据对同样的G(x)做模2除法。由于发送端将余数加入在数据尾部,相当于已做了“去余”处理,故若数据传输正确时,接收端的模2除运算余数应为0。其中校验位数和生成多项式不是随便选定的,一般采用常用的标准形式。其中CRCK是指有K为校验位,不同位数对应不同的纠检错能力。之前本人在网上找到一篇关于CRC校验原理的文章,比较详细且浅显易懂:http://mp.weixin.qq.com/s/RNHLZGPD9Ysbxb1FNDn6EA
最原始的实现方式是采用LFSR(线性反馈移位寄存器)来完成校验功能,以下是结构示意图:
寄存器个数等于G(x)最高次幂,图中gx表示链路通断,与多项式系数相对应:系数为1时连接,0则断开。数据在每个时钟周期从右侧输入1bit,且寄存器内数据右移一位。如此移位,反馈异或的过程即为待发送数据移位后对生成多项式做模2除的过程,故当全部数据位输入完毕,寄存器内部的值即为CRC校验码。我们以较简单的CRC8为例,其G(x) = x^8 + x^2 + x^1 + 1,根据上述分析得到:
reg2(i) = reg1(i-1)^reg7(i-1)^d(i)
reg1(i) = reg0(i-1)^reg7(i-1)^d(i)
reg0(i) = reg7(i-1)^d(i)
regk(i) = regk-1(i-1) (k!=0,1,2)
其中,i表示当前时刻,i-1表示上一时刻。数据位宽定为4bit,经过四个节拍,寄存器内部数据变化过程见表:
注:CRC8理论上进行8轮移位(左移)操作,每轮左移后的要校验的位(本CRC8多项式对应:第0位、第1位、第2位)的数据与上一轮最高位(Reg7)进行异或^操作(上图中省略了^符号);
因为数据位宽是4位,相当于高四位补零,不需要校验只进行左移,并且与0异或也不变,所以只需对4位数据位进行校验。上图中C1~C7为原寄存器初始值(一般在复位后值为0,即省去和C的异或),D为要校验的数据。一个8位数据CRC8校验笔试题:https://www.cnblogs.com/yiquwange/p/14621042.html
根据上述传递方程推导得出四个节拍后reg7~reg0保存的数值,试想一下:既然每个触发器内保存数值表达式已知,那么如果直接将第四行表达式赋值寄存器,下一个时钟节拍即可得到最终校验结果,而无需等待四个时钟节拍。这就是CRC校验的并行实现方式了!传统的CRC校验算法已经非常成熟,在使用过程中不需要完全自己推导公式,了解基本原理即可。CRC校验的Verilog代码线上生成工具 http://www.easics.com/webtools/crctool 我们选定CRC8,并将数据位宽定义为4bit,验证上述推导过程是否正确。
生成源代码:
1 ////////////////////////////////////////////////////////////////////////////////
2 // Purpose : synthesizable CRC function
3 // * polynomial: x^8 + x^2 + x^1 + 1
4 // * data width: 4
5 ////////////////////////////////////////////////////////////////////////////////
6 module CRC8_D4;
7
8 // polynomial: x^8 + x^2 + x^1 + 1
9 // data width: 4
10 // convention: the first serial bit is D[3]
11 function [7:0] nextCRC8_D4;
12
13 input [3:0] Data;
14 input [7:0] crc;
15 reg [3:0] d;
16 reg [7:0] c;
17 reg [7:0] newcrc;
18 begin
19 d = Data;
20 c = crc;
21
22 newcrc[0] = d[0] ^ c[4];
23 newcrc[1] = d[1] ^ d[0] ^ c[4] ^ c[5];
24 newcrc[2] = d[2] ^ d[1] ^ d[0] ^ c[4] ^ c[5] ^ c[6];
25 newcrc[3] = d[3] ^ d[2] ^ d[1] ^ c[5] ^ c[6] ^ c[7];
26 newcrc[4] = d[3] ^ d[2] ^ c[0] ^ c[6] ^ c[7];
27 newcrc[5] = d[3] ^ c[1] ^ c[7];
28 newcrc[6] = c[2];
29 newcrc[7] = c[3];
30 nextCRC8_D4 = newcrc;
31 end
32 endfunction
33 endmodule
参考资料:[1]百度百科:CRC(循环冗余校验)
[2]没落骑士:数据帧CRC32校验算法实现
原文:https://www.cnblogs.com/yiquwange/p/14685775.html