【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校验码。
𝑀(𝑥)𝑥^𝑛−𝑘 表示在信息码后面加上 𝑛 − 𝑘 个零。
𝐴(𝑥) 是系统循环码,
高 𝑘 位为信息码,低 𝑛 − 𝑘 位为监督码。 

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。

根据 IEEE 要求 CRC 的校验和解校验的电路默认初试状态都是 32’hffffffff全 1 状态。

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

 

posted @ 2024-03-30 20:04  NoNounknow  阅读(826)  评论(0编辑  收藏  举报