参考:CRC校验原理及步骤https://blog.csdn.net/d_leo/article/details/73572373
什么是CRC校验?
CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。
CRC校验原理:
其根本思想就是先在要发送的帧后面附加一个数(这个就是用来校验的校验码,但要注意,这里的数也是二进制序列的,下同),生成一个新帧发送给接收端。当然,这个附加的数不是随意的,它要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除(注意,这里不是直接采用二进制除法,而是采用一种称之为“模2除法”)。到达接收端后,再把接收到的新帧除以(同样采用“模2除法”)这个选定的除数。因为在发送端发送数据帧之前就已通过附加一个数,做了“去余”处理(也就已经能整除了),所以结果应该是没有余数。如果有余数,则表明该帧在传输过程中出现了差错。
模2除法:
模2除法与算术除法类似,但每一位除的结果不影响其它位,即不向上一位借位,所以实际上就是异或。在循环冗余校验码(CRC)的计算中有应用到模2除法。
例:
CRC校验码计算示例:
现假设选择的CRC生成多项式为G(X) = X4 + X3 + 1,要求出二进制序列10110011的CRC校验码。下面是具体的计算过程:
①将多项式转化为二进制序列,由G(X) = X4 + X3 + 1可知二进制一种有五位,第4位、第三位和第零位分别为1,则序列为11001
②多项式的位数位5,则在数据帧的后面加上5-1位0,数据帧变为101100110000,然后使用模2除法除以除数11001,得到余数。
③将计算出来的CRC校验码添加在原始帧的后面,真正的数据帧为101100110100,再把这个数据帧发送到接收端。
④接收端收到数据帧后,用上面选定的除数,用模2除法除去,验证余数是否为0,如果为0,则说明数据帧没有出错。
CRC校验电路原理图
对应的并行CRC代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 14:18:49 08/14/2018
// Design Name:
// Module Name: crc16-papa
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module crc16papa (reset, gclk, soc, data_in, crc_out);
input reset,gclk,soc;
input [7:0] data_in;
output reg [15:0] crc_out;
reg temp;
reg [15:0] crc_temp;
parameter delay = 1'b1;
integer i,j,k,l;
//产生crc_out
always @(posedge gclk or negedge reset)
begin
if (!reset)
crc_out <= #delay 16'b0;
else if (soc)
crc_out <= #delay 16'b0;
else
crc_out <= #delay crc_temp;
end
//产生crc_temp
always @(crc_out or data_in)
begin
crc_temp = crc_out;
for (i=7;i>=0;i=i-1)
begin
temp = data_in[i] ^crc_temp[15];
for (j=15; j>12; j=j-1)
crc_temp[j] = crc_temp[j-1];
crc_temp[12] = temp ^ crc_temp[11];
for (k=11; k>5; k=k-1)
crc_temp[k] = crc_temp[k-1];
crc_temp[5] = temp ^ crc_temp[4];
for (l=4; l>0; l=l-1)
crc_temp[l] = crc_temp[l-1];
crc_temp[0] = temp;
end
end
endmodule