一、CRC概述
已经有大量的文章中解释了CRC的原理实现,稍作赘述只是为了自己遗忘。
1.概念
Cyclic Redundancy Check,循环冗余校验,是一种对数字信号进行编码的技术或者过程,特点是有效数据和检验数据的长度可以自定义。
2.原理
原码和某一多项式(一组二进制位串)进行模2除法,得到一组校验码,检验码续到原码后面组合成CRC信息。
简单来说,就是原数据和一固定的01字符串不停的进行异或运算,最后剩下的余数就是我要求的数据。
3.常见CRC应用
名称 | 多项式 | 应用场景 |
---|---|---|
CRC-8 | x^8 + x^2 + x^1 + 1 | ATM… |
CRC-16 | x^16 + x^15 + x^2 + 1 | USB… |
CRC-32 | x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 | Ethernet… |
二、实现原理
1.串行原理
LFSR,Linear Feedback Shift Register,线性反馈移位寄存器,用于通信加扰解扰。
其过程是在 移位寄存器 中上一时刻状态的输出,当做此刻状态的输入;由于移位寄存器的的运算是固定的,而且其位宽也是确定的,所以最终的结果肯定是可控的;也就是说,在若干的时刻后,每一个移位寄存器中的当下的值,取决于上一位的数据和初始移位寄存器中的值。
我们自行推导模2除法的过程,可明白其过程和LFSR是一样的,数据和多项式的异或运算中,逢1变换,逢0移位。
2.并行原理
FPGA本身是用空间换时间,我们明白在LFSR的过程后,自然会想到,刚开始的数据遍历完所有的移位寄存器后,最后几个还在走的路上,而最后几位数据完成,之前的数据无非是向前平移而已。
据此我们可以推算出,对于任意一组数据,在最终时刻下,他的移位寄存器中的剩余值,或者说校验中CRC的值是,完全取决于初始数据各个位宽的值和移位寄存器各个初始值。
三、代码实现
我们用CRC-16检验8位位宽的数据,其公式是x^16 + x^15+ x^2 + 1。
其二进制字符串是1100 0000 0000 0101.
命名 | 定义 | 初始值 |
---|---|---|
c | 上一状态移位寄存器的值(一般也就是上一时刻crc的校验值) | crc[15:0] |
d | 此刻要检测的数据 | data[7:0] |
newcrc | 此刻生成的新的crc的值 | newcrc[15:0] |
以下代码是化简了过程,其过程是对应的二进制字符串中的0和1进行异或运算
newcrc[0] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15]; newcrc[1] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15]; newcrc[2] = d[1] ^ d[0] ^ c[8] ^ c[9]; newcrc[3] = d[2] ^ d[1] ^ c[9] ^ c[10]; newcrc[4] = d[3] ^ d[2] ^ c[10] ^ c[11]; newcrc[5] = d[4] ^ d[3] ^ c[11] ^ c[12]; newcrc[6] = d[5] ^ d[4] ^ c[12] ^ c[13]; newcrc[7] = d[6] ^ d[5] ^ c[13] ^ c[14]; newcrc[8] = d[7] ^ d[6] ^ c[0] ^ c[14] ^ c[15]; newcrc[9] = d[7] ^ c[1] ^ c[15]; newcrc[10] = c[2]; newcrc[11] = c[3]; newcrc[12] = c[4]; newcrc[13] = c[5]; newcrc[14] = c[6]; newcrc[15] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[1] ^ d[0] ^ c[7] ^ c[8] ^ c[9] ^ c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[15]; nextCRC16_D8 = newcrc;
四、备忘录
没有回复内容