【CRC校验方法】+【FPGA实现(接收端)】
参考:
【科普向】谁都能看懂的CRC(循环冗余校验)原理_crc循环冗余校验原理-CSDN博客
CRC校验原理和推导过程及Verilog实现(一文讲透)_crc verilog-CSDN博客
介绍两个CRC源码生成工具,可生成Verilog和VHDL - nios II 爱好者 - 博客园 (cnblogs.com)
Generator for CRC HDL code (bues.ch)
http://www.easics.com/webtools/crctool
OutputLogic.com » CRC Generator
P(x)
P(x)是由一种称为本原元的特殊多项式计算而来的,P(x)应该满足:
最高位和最低位都是1
当被传送信息任何一位发生错误时 P(x)不被T(x)整除
不同位发生错误时,余数应该不同
对余数继续做模二除法时,应该使余数循环
基于这些限定条件,在有限域内求解本原元以及对P ( x ) P(x)P(x)的取值是通信领域的一个研究课题
这些是常用的循环冗余检验(CRC )算法及其应用的简要列表。CRC是一种常见的用于检测数据传输或存储中出现错误的技术。
-
CRC-8: 使用多项式
X^8 + X^2 + X + 1
,表示法为0x07
。这个简单的CRC通常用于小块数据的错误检测。 -
CRC-12: 使用多项式
X^12 + X^11 + X^3 + X^2 + X + 1
,表示法为0x80F
。主要用于电信系统中。 -
CRC-16: 使用多项式
X^16 + X^15 + X^2 + 1
,表示法为0x8005
。这是一个广泛使用的CRC,应用于Bisync, Modbus, USB, ANSI X3.28, SIA DC-07等多种标准和协议,也称为CRC-16或CRC-16-ANSI。 -
CRC-CCITT: 使用多项式
X^16 + X^12 + X^5 + 1
,表示法为0x1021
。它主要用于ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS等通讯标准。 -
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
,表示法为0x04C11DB7
。这是一个非常常见的CRC,用于ZIP, RAR文件格式,IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS等。 - crc[31:0]=1+x^1+x^2+x^4+x^5+x^7+x^8+x^10+x^11+x^12+x^16+x^22+x^23+x^26+x^32;
-
CRC-32C: 使用多项式
X^32 + X^28 + X^27 + X^26 + X^25 + X^23 + X^22 + X^20 + X^19 + X^18 + X^14 + X^13 + X^11 + X^10 + X^9 + X^8 + X^6 + 1
,表示法为0x1EDC6F41
。它用于iSCSI, SCTP, G.hn负载,SSE4.2指令集,以及Btrfs, ext4, Ceph等文件系统。
CRC校验公式
CRC串行计算公式推导
LFSR线性反馈移位寄存器
线性反馈移位寄存器简称LFSR,用于产生可重复的伪随机序列,也可用来实现CRC校验。
LFSR主要由触发器(寄存器)、异或门以及反馈线路组成。
推荐伽罗瓦LFSR,如图所示,对于二进制来说,gn 到g0的各个系数表示这条支路是否存在,1为存在,0则不存在。
各个寄存器储存着上一次CRC校验运算的结果,寄存器的输出即为CRC的值,
这里还是以CRC-32举例,其生成多项式为:
G(x)
X^32 + X^28 + X^27 + X^26 + X^25 + X^23 + X^22 + X^20 + X^19 +
X^18 + X^14 + X^13 + X^11 + X^10 + X^9 + X^8 + X^6 + 1,
M(x)
K = 32
上一轮R(x)
上一次CRC计算的结果为:
并行处理
CRC初始值
寄存器需要赋初值,一般赋全1或全0。
FPGA实现
采用参考链接中的最后一个网站来生成,虽然我也手算了两个周期,但是crc32实在太长了。
crc[31:0]=1+x^1+x^2+x^4+x^5+x^7+x^8+x^10+x^11+x^12+x^16+x^22+x^23+x^26+x^32;
module CRC32_D8 ( input wire i_clk , input wire i_rst_n , input wire [7:0] i_data , input wire i_vaild , output wire o_crc_error , output wire o_crc_end ); reg r_i_vaild ; reg [7:0] r_i_data ; reg [31:0] crc_r ; reg [31:0] crc_lfsr ; reg r_crc32_error ; reg [15:0] vaild_cnt ; reg filter_vaild ; wire crc_end ; reg r_crc_end ; /////////////////////////////////////////////////////////////////////////// assign crc_end = (i_vaild == 1'b0 && r_i_vaild == 1'b1); assign o_crc_error = r_crc32_error; assign o_crc_end = r_crc_end ; always @(posedge i_clk) begin if (i_rst_n==0) begin vaild_cnt <= 'd0; end else if(i_vaild == 1'b0 && r_i_vaild == 1'b1) begin vaild_cnt <= 'd0; end else if(i_vaild == 1'b1) begin vaild_cnt <= vaild_cnt + 1'b1; end else begin vaild_cnt <= vaild_cnt; end end always @(*) begin if(vaild_cnt >= 4'd8 && i_vaild == 1'b1) begin filter_vaild <= 1'b1; end else begin filter_vaild <= 1'b0; end end always @(posedge i_clk) begin r_i_vaild <= i_vaild; r_crc_end <= crc_end; end always@(posedge i_clk) begin if (i_rst_n==0) begin r_crc32_error <= 1'b0; end else if (i_vaild == 1'b0 && r_i_vaild == 1'b1) begin if (crc_r==32'hc704dd7b) begin r_crc32_error <= 1'b0; end else begin r_crc32_error <= 1'b1; end end else begin r_crc32_error <= 1'b0; end end always @(posedge i_clk) begin if(i_rst_n == 1'b0) begin crc_r <= 32'hffff_ffff; end else if(filter_vaild == 1'b1) begin crc_r <= crc_lfsr; end else if(i_vaild == 1'b0 && r_i_vaild == 1'b1)begin crc_r <= 32'hffff_ffff; end else begin crc_r <= crc_r; end end reg [3:0] data_inver_i; always @(*) begin for(data_inver_i = 0;data_inver_i < 8;data_inver_i = data_inver_i + 1) begin r_i_data[data_inver_i] <= i_data[7-data_inver_i]; end end always @(*) begin crc_lfsr[0] = crc_r[24] ^ crc_r[30] ^ r_i_data[0] ^ r_i_data[6]; crc_lfsr[1] = crc_r[24] ^ crc_r[25] ^ crc_r[30] ^ crc_r[31] ^ r_i_data[0] ^ r_i_data[1] ^ r_i_data[6] ^ r_i_data[7]; crc_lfsr[2] = crc_r[24] ^ crc_r[25] ^ crc_r[26] ^ crc_r[30] ^ crc_r[31] ^ r_i_data[0] ^ r_i_data[1] ^ r_i_data[2] ^ r_i_data[6] ^ r_i_data[7]; crc_lfsr[3] = crc_r[25] ^ crc_r[26] ^ crc_r[27] ^ crc_r[31] ^ r_i_data[1] ^ r_i_data[2] ^ r_i_data[3] ^ r_i_data[7]; crc_lfsr[4] = crc_r[24] ^ crc_r[26] ^ crc_r[27] ^ crc_r[28] ^ crc_r[30] ^ r_i_data[0] ^ r_i_data[2] ^ r_i_data[3] ^ r_i_data[4] ^ r_i_data[6]; crc_lfsr[5] = crc_r[24] ^ crc_r[25] ^ crc_r[27] ^ crc_r[28] ^ crc_r[29] ^ crc_r[30] ^ crc_r[31] ^ r_i_data[0] ^ r_i_data[1] ^ r_i_data[3] ^ r_i_data[4] ^ r_i_data[5] ^ r_i_data[6] ^ r_i_data[7]; crc_lfsr[6] = crc_r[25] ^ crc_r[26] ^ crc_r[28] ^ crc_r[29] ^ crc_r[30] ^ crc_r[31] ^ r_i_data[1] ^ r_i_data[2] ^ r_i_data[4] ^ r_i_data[5] ^ r_i_data[6] ^ r_i_data[7]; crc_lfsr[7] = crc_r[24] ^ crc_r[26] ^ crc_r[27] ^ crc_r[29] ^ crc_r[31] ^ r_i_data[0] ^ r_i_data[2] ^ r_i_data[3] ^ r_i_data[5] ^ r_i_data[7]; crc_lfsr[8] = crc_r[0] ^ crc_r[24] ^ crc_r[25] ^ crc_r[27] ^ crc_r[28] ^ r_i_data[0] ^ r_i_data[1] ^ r_i_data[3] ^ r_i_data[4]; crc_lfsr[9] = crc_r[1] ^ crc_r[25] ^ crc_r[26] ^ crc_r[28] ^ crc_r[29] ^ r_i_data[1] ^ r_i_data[2] ^ r_i_data[4] ^ r_i_data[5]; crc_lfsr[10] = crc_r[2] ^ crc_r[24] ^ crc_r[26] ^ crc_r[27] ^ crc_r[29] ^ r_i_data[0] ^ r_i_data[2] ^ r_i_data[3] ^ r_i_data[5]; crc_lfsr[11] = crc_r[3] ^ crc_r[24] ^ crc_r[25] ^ crc_r[27] ^ crc_r[28] ^ r_i_data[0] ^ r_i_data[1] ^ r_i_data[3] ^ r_i_data[4]; crc_lfsr[12] = crc_r[4] ^ crc_r[24] ^ crc_r[25] ^ crc_r[26] ^ crc_r[28] ^ crc_r[29] ^ crc_r[30] ^ r_i_data[0] ^ r_i_data[1] ^ r_i_data[2] ^ r_i_data[4] ^ r_i_data[5] ^ r_i_data[6]; crc_lfsr[13] = crc_r[5] ^ crc_r[25] ^ crc_r[26] ^ crc_r[27] ^ crc_r[29] ^ crc_r[30] ^ crc_r[31] ^ r_i_data[1] ^ r_i_data[2] ^ r_i_data[3] ^ r_i_data[5] ^ r_i_data[6] ^ r_i_data[7]; crc_lfsr[14] = crc_r[6] ^ crc_r[26] ^ crc_r[27] ^ crc_r[28] ^ crc_r[30] ^ crc_r[31] ^ r_i_data[2] ^ r_i_data[3] ^ r_i_data[4] ^ r_i_data[6] ^ r_i_data[7]; crc_lfsr[15] = crc_r[7] ^ crc_r[27] ^ crc_r[28] ^ crc_r[29] ^ crc_r[31] ^ r_i_data[3] ^ r_i_data[4] ^ r_i_data[5] ^ r_i_data[7]; crc_lfsr[16] = crc_r[8] ^ crc_r[24] ^ crc_r[28] ^ crc_r[29] ^ r_i_data[0] ^ r_i_data[4] ^ r_i_data[5]; crc_lfsr[17] = crc_r[9] ^ crc_r[25] ^ crc_r[29] ^ crc_r[30] ^ r_i_data[1] ^ r_i_data[5] ^ r_i_data[6]; crc_lfsr[18] = crc_r[10] ^ crc_r[26] ^ crc_r[30] ^ crc_r[31] ^ r_i_data[2] ^ r_i_data[6] ^ r_i_data[7]; crc_lfsr[19] = crc_r[11] ^ crc_r[27] ^ crc_r[31] ^ r_i_data[3] ^ r_i_data[7]; crc_lfsr[20] = crc_r[12] ^ crc_r[28] ^ r_i_data[4]; crc_lfsr[21] = crc_r[13] ^ crc_r[29] ^ r_i_data[5]; crc_lfsr[22] = crc_r[14] ^ crc_r[24] ^ r_i_data[0]; crc_lfsr[23] = crc_r[15] ^ crc_r[24] ^ crc_r[25] ^ crc_r[30] ^ r_i_data[0] ^ r_i_data[1] ^ r_i_data[6]; crc_lfsr[24] = crc_r[16] ^ crc_r[25] ^ crc_r[26] ^ crc_r[31] ^ r_i_data[1] ^ r_i_data[2] ^ r_i_data[7]; crc_lfsr[25] = crc_r[17] ^ crc_r[26] ^ crc_r[27] ^ r_i_data[2] ^ r_i_data[3]; crc_lfsr[26] = crc_r[18] ^ crc_r[24] ^ crc_r[27] ^ crc_r[28] ^ crc_r[30] ^ r_i_data[0] ^ r_i_data[3] ^ r_i_data[4] ^ r_i_data[6]; crc_lfsr[27] = crc_r[19] ^ crc_r[25] ^ crc_r[28] ^ crc_r[29] ^ crc_r[31] ^ r_i_data[1] ^ r_i_data[4] ^ r_i_data[5] ^ r_i_data[7]; crc_lfsr[28] = crc_r[20] ^ crc_r[26] ^ crc_r[29] ^ crc_r[30] ^ r_i_data[2] ^ r_i_data[5] ^ r_i_data[6]; crc_lfsr[29] = crc_r[21] ^ crc_r[27] ^ crc_r[30] ^ crc_r[31] ^ r_i_data[3] ^ r_i_data[6] ^ r_i_data[7]; crc_lfsr[30] = crc_r[22] ^ crc_r[28] ^ crc_r[31] ^ r_i_data[4] ^ r_i_data[7]; crc_lfsr[31] = crc_r[23] ^ crc_r[29] ^ r_i_data[5]; end // always /////////////////////////////////////////////////////////////////////////// endmodule