CRC全称循环冗余校验(Cyclic Redundancy Check, CRC)
CRC校验的基本思路是数据发送方发送数据之前,先生成一个CRC校验码,可以是单bit也可以是多bit,并附在有效数据末尾,以串行方式发送到接收方。接收方接收到数据后,进行CRC校验,根据校验结果就可以知道数据是否有误。
CRC校验码的生成:将有效数据扩展后作为被除数,使用一个指定的多项式作为除数,进行模二除法,得到的余数就是校验码。
数据接收方的CRC校验:将接受的数据(有效数据+CRC校验码)扩展后作为被除数,用指定的多项式作为除数,进行模二除法,得到余数为0,则表示校验正确。
手算推导过程可见视频
【[CRC校验]手算与直观演示-哔哩哔哩】 https://b23.tv/2qvVvCF
以CRC16为例,他的生产多项式为: 。在计算开始时,CRC寄存器初始化为全0
// For CRC7: Use (7, 7'h00, 7'h09)
// For CRC16: Use (16, 16'h0000, 16'h1021)
module general_crc
#( parameter WIDTH = 16,
parameter [WIDTH-1] INIT_VALUE = 0,
parameter [WIDTH-1] CRC_EQUATION = 0)
( input clk,
input res_n,
input init, // initialize crc_value with INIT_VALUE
input enable, // calculate crc_value from data_in
input draint, // crc_calue is shifted out from data_out
output data_out,
output reg [WIDTH-1 : 0] crc_value, //parallel out crc_value
);
wire crc_next;
wire [WIDTH-1] crc_temp;
assign crc_next = data_in ^ crc_value[WIDTH-1];
assign crc_temp = {crc_value[WIDTH-2], 1'b0};
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
crc_value <= {WIDTH{1'b0}};
else if (init)
crc_value <= INIT_VALUE;
else if (enable)
if(crc_next)
crc_value <= crc_temp ^ CRC_EQUATION;
else
crc_value <= crc_temp;
else if (draint)
crc_value <= crc_value[WIDTH-2];
end
assign crc_out = crc_value[WIDTH-1];
endmodule