CRC(Cyclic Redundancy Check,循环冗余校验)是一种用于检测数据传输或存储过程中错误的技术。它基于二进制除法,并通过生成多项式来实现数据的校验。
CRC校验过程,其实就是规定一个除数(这个二进制的除数也对应一个 生成多项式 )。原始数据除以这个数据,除不尽,那我们就把余数,也就是 校验码 checksum 附加到原始数据末尾。这样接收方除以这个除数时就能除尽了。
只不过在这个除法计算中,使用的是模二运算。模二除法的过程和平时的除法的逻辑是一样的。只是不考虑进位;要完成除法运算其实也隐含了你必须知道加减乘法。
模2运算的加法和减法,只做加减,不管进退位。这样就相当于按bit做XOR运算。例如
0101+0011=0110
0110-0011=0101
运算规则:
1x1=1; 1x0=0; 0x1=0; 0x0=0
1011
x 101
-----------
1011
0000
+1011
------------
100111
运算规则:
被除数 / 除数 = 商 ... 余数
1011 商
1101 | 1111000 除数|被除数
1101 1 x 除数,商=1
-----------
010000 作差,余数010000
0000 0 x 除数,商=0
----------
10000 作差,余数10000
1101 1 x 除数,商=1
---------
1010 作差,余数1010
1101 1 x 除数,商=1
--------
111 作差,余数111
余数111小于除数1101的位数,最终商=1011,余数=111
这里用到一个技巧是数组切片,详见 VerilogAMS-Model#2.2 数组切片
`define SPI_MAX 1023
function [7:0] checksum_cal;
input [`SPI_MAX:0] rawData;
integer i;
integer rawDataOrder;
begin
rawData = rawData << 8;
rawDataOrder = 0;
for( i=`SPI_MAX; (i>=0 && rawDataOrder==0); i=i-1 )
rawDataOrder = (rawData[i]==1 && i>rawDataOrder) ? i : rawDataOrder);
for(i=rawDataOrder; i>=8; i=i-1 )
rawData[i -:9] =rawData[i] ? rawData[i -:9] ^ 9'b1_0000_0111 : rawData[i -:9];
checksum_cal = rawData[7:0];
end
endfunction