Verilog数字系统基础设计-CRC

面包板社区 2021-09-23 20:00

CRC(循环冗余校验)

CRC介绍

临时“插播”,后面有实例。

CRC(Cyclic Redundancy Check,循环冗余校验)是数据帧传输中常用的一种差错控制编码方式,针对要发送的数据帧,使用一些特定的多项式可以计算出CRC校验结果,CRC校验结果和原始数据一起传输到接收端,如图6.13所示。

接收端在接收数据的同时按照相同的多项式对接收数据进行校验运算,并将校验结果和接收的结果进行对比,如果二二者相同则认为没有发生传输错误;如果不同,则认为是发生了传输错误。从理论上说,如 果接收端计算出的CRC值与接收到的CRC值匹配,数据中仍有出错的可能,但由于这种可能性极低,在实际应用中可以视为0,即没有错误出现。当接收端CRC不匹配时,接收端可以采取不同的措施,例如,丢弃数据包并通知对端,要求对端重新发送,或者只进行丢弃处理,通过高层协议实现数据的重传。

串行CRC计算

计算CRC步骤如下:

  • 选择一个CRC算法或生成多项式,如CRC8-CCITT的生成多项式表示为(x^8+x^2+x+1);

  • CRC8硬件上由8个触发器实现,整合为一个移位寄存器,称为CRC寄存器,如图6.14所示;

  • 计算CRC之前,CRC寄存器初始化为一个已知的值,称为CRC初始值;这里要求确定的初始值,因为接收端的CRC校验电路需要使用和发送端相同的初始值;

  • CRC寄存器初始化之后,每个时钟都有一个数据比特输入,与当前寄存器的值共同参与计算;CRC校验电路中,一些寄存器的输入直接来自前级的输出,有的是前级的输出与当前输入数据进行逻辑运算的结果;

  • 在每个周期,新的数据不断输入,CRC寄存器不断更新,直到最后一个输入比特到达;

  • 当最后一个数据比特到达时,CRC内部所存储的就是最后的CRC校验结果;

  • 正如上面提到的,CRC校验结果的位宽取决于具体的CRC算法。例如,CRC5-USB中的CRC校验结果为5比特,CRC8-CCITT中CCRC校验结果为8比特;

  • 在最后1个数据比特发出后,存储在寄存器中的的CRC校验结果逐比特依次输出,直至最后一个比特。可以看岀,校验结果紧跟在用户数据后面输出;

以下是CRC8-CCITT算法图:

module CRC8_CCITT
 (clk,reset,
 din,
 init_crc,
 calc_crc,
 crc_out);
input clk,reset;
input din;
input [7:0]init_crc;
input calc_crc;
output [7:0] crc_out;
parameter CRC_INIT_VALUE = 8'hFF;
reg [7:0]crcreg,crcreg_nxt;
wire [7:0] newcrc;
wire [7:0] crc_out;
assign newcrc[0] = crcreg[7]^din;
assign newcrc[1] = (crcreg[7]^din)^crcreg[0];
assign newcrc[2] = (crcreg[7]^din)^crcreg[1];
assign newcrc[3] = crcreg[2];
assign newcrc[4] = crcreg[3];
assign newcrc[5] = crcreg[4];
assign newcrc[6] = crcreg[5];
assign newcrc[7] = crcreg[6];
always @(*)begin
 if(init_crc)
 crcreg_nxt = CRC_INIT_VALUE;
 else if(calc_crc)
 crcreg_nxt = newcrc;
 else
 crcreg_nxt = crcreg;
end
always @(posedge clk or negedge reset)begin
 if(!reset)
 crcreg = CRC_INIT_VALUE;
 else
 crcreg = crcreg_nxt;
end
assign crc_out = crcreg;
endmodule

测试testbench

`timescale 1ns/1ns
module testbench_CRC8_CCITT;
reg clk_tb,reset_tb;
reg din_tb;
reg init_crc_tb,calc_crc_tb;
wire [7:0] crc_out_tb;
parameter CLK_HALF_PERIOD = 5;
parameter RST_DEASSERT_DLY = 100;
initial begin
 clk_tb = 1'b0;
 forever begin
  #CLK_HALF_PERIOD clk_tb = ~clk_tb;
 end
end
initial begin
 reset_tb = 1'
b0;
 #RST_DEASSERT_DLY reset_tb = 1'b1;
end
initial begin
 din_tb = 0; 
 #RST_DEASSERT_DLY;
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 0;
 @(posedge clk_tb);
 #1 din_tb = 0;
 @(posedge clk_tb);
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 0;
 @(posedge clk_tb);
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 1;
 @(posedge clk_tb);
 #1 din_tb = 0;
end
initial begin
 init_crc_tb = 0;
 calc_crc_tb = 1;
end
CRC8_CCITT  test_CRC8_CCITT
 (.clk(clk_tb),.reset(reset_tb),
 .din(din_tb),
 .init_crc(init_crc_tb),
 .calc_crc(calc_crc_tb),
 .crc_out(crc_out_tb)
 );
endmodule

仿真结果:

并行CRC计算

在前一部分,我们讨论了单比特输人数据的CRC计算方法。然而,在实际应用中,数据路径宽度通常为多 比特的,并且每个时钟周期并行数据邡会改变。例如,对于32位宽的并行数据,我们可以通过递归方法推导出32比特之后CRC寄存器的值。推导出来的每个32位并行CRC寄存器的输入值是当前输入datain[31:0]当前CRC寄存器的值crcreg组成的函数,如图6.15所示。

这一递归推导过程可以在理论上进行,但十分烦琐。Easics公司已经开发了网页版的工具(http://www.easics.com)/(https://www.easics.com/crctool/),设计者可以根据需要得到所需的计算公式。

部分数据CRC计算

我们讨论了串行数据的CRC计算,又讨论了使用递归方法计算并行数据的CRC在并行CRC计算时,如果最后一个输入数据中只有部分字节是有效的,那么应该怎么办呢?本部分将进行讨论。

以每个时钟周期到达8字节的PCle x8为例,在最后一个周期,有两种可能的情况,一种是所有8字节都是有效的,另一种是只有4字节32比特)是有效的。不携带有效数据的4字节由专用符号进行填充,称为PAD,PAD不参与CRC计算。

这意味着在前期每个时钟周期需要处理64比特数据,且需要在一个时钟周期内计算其CRC值。在最后一个周期中,CRC计算涉及所有8字节或只有4字节。此时,可以通过两种方式进行处理:第一种方式是在一个计算CRC校验值的流水线中使用两个CRC校验计算电路,一个对64位数据进行计算,一个对32位数据进行计算,二者结合起来计算最后的CRC结果;第二种方式中只用一组CRC寄存器,但是,对于最后输入的并行数据,使用两个不同的电路计算CRC内部寄存器的输入值。这两种方式将在后面分别介绍。

流水线方式

这种机制需要两个CRC校验计算电路,一个用于每次计算64比特的CRC值,一个用于每次计算32比特的CRC值,如图6.16所示

下面是具体内容:

  • 使用一个64比特CRC计算电路和一个32比特CRC计算电路;
  • 64比特CRC计算电路用于计算64位数据的CRC值;
  • 对于最后一个并行数据,如果所有的8字节都是有效字节,则CRC校验结果由64比特CRC计算电路计算得到(32位的CRC计算电路在此次计算中没有起作用);
  • 如果最后一个数据中只有4字节是有效的,最终的CRC校验结果由32比特CRC计算电路计算得到;
  • 在倒数第二个并行数据输入64比特CRC计算电路之后,64比特CRC计算电路中每个寄存器的输入值(注意,不是寄存器的输出值)被传递给32比特CRC计算电路,这样,当最后一组并行数据到达时,32位CRC计算电路的寄存器中存储的是来自于64位计算电路中前期计算的结果,该结果与当前数据一起进行32位并行计算,得到最终的校验结果。

仅使用一组CRC寄存器

在这种电路结构中,只使用一组CRC寄存器,如图6.17所示

下面是其相关细节:

  • 电路中有两个异或逻辑模块,第一个的输入是基于当前寄存器的值和64比特输入数据,第二个的输入是当前寄存器的值和32比特输入数据;

  • 对于前面的数据,每个时钟周期内CRC计算电路使用64比特异或逻辑模块的输出结果;

  • 对于最后一组数据,如果所有的8字节都有效,则使用64比特异或逻辑模块的计算结果作为最后一个时钟周期CRC寄存器的输入;如果只有4字节有效,则使用32比特异或逻辑模块的输出结果作为最后一个时钟周期CRC寄存器的输入。

从定时特性上看,使用流水线结构的并行CRC校验电路可以达到更高的速度,但它需要两组CRC寄存器。第二种方式仅需要一组CRC寄存器,但是其组合逻辑部分更为复杂,路径延迟更大,从而不利于提高处理速度.

下面是每个时钟周期计算64比特并行数据CRC校验结果的RTL代码,由Easics网站上的Web工具具计算得到。我们还可以生成32比特或者所需要的任何其他位宽的CRC并行计算电路。

// Copyright 2008 Altera Corporation. All rights reserved.  
// Altera products are protected under numerous U.S. and foreign patents, 
// maskwork rights, copyrights and other intellectual property laws.  
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design 
// License Agreement (either as signed by you or found at www.altera.com).  By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation.  In the event that you do
// not agree with such terms and conditions, you may not use the reference 
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an 
// accommodation and therefore all warranties, representations or guarantees of 
// any kind (whether express, implied or statutory) including, without 
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed.  By making this reference
// design file available, Altera expressly does not recommend, suggest or 
// require that this reference design file be used in combination with any 
// other product not provided by Altera.
/////////////////////////////////////////////////////////////////////////////

//
// 24 bit CRC of 64 data bits (reversed - MSB first)
// polynomial : 00328b63 
//    x^21 + x^20 + x^17 + x^15 + x^11 + x^9 + x^8 + x^6 + x^5 + x^1 + x^0
//
//        CCCCCCCCCCCCCCCCCCCCCCCC DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD 
//        000000000011111111112222 0000000000111111111122222222223333333333444444444455555555556666 
//        012345678901234567890123 0123456789012345678901234567890123456789012345678901234567890123 
// C00  = .#....#.##..##..#.###.## #..##.###.##..#.#......#.....####.#.####.#....#.##..##..#.###.## 
// C01  = ###...###.#.#.#.###..##. ##.#.##..##.#.####.....##....#...####...###...###.#.#.#.###..##. 
// C02  = .###...###.#.#.#.###..## .##.#.##..##.#.####.....##....#...####...###...###.#.#.#.###..## 
// C03  = ..###...###.#.#.#.###..# ..##.#.##..##.#.####.....##....#...####...###...###.#.#.#.###..# 
// C04  = ...###...###.#.#.#.###.. ...##.#.##..##.#.####.....##....#...####...###...###.#.#.#.###.. 
// C05  = ##..##..####.##....#.#.# #..#.##.##.#.#....####.#...########.#...##..##..####.##....#.#.# 
// C06  = ..#..#..#.##.####.##...# ##.#....##.##...#..######...#....#.##.##..#..#..#.##.####.##...# 
// C07  = #..#..#..#.##.####.##... .##.#....##.##...#..######...#....#.##.##..#..#..#.##.####.##... 
// C08  = #...#.#####....#.#.#.### #.#.#####....#..#.#..##.###..#.##.###..##...#.#####....#.#.#.### 
// C09  = #....###..####.....#.... ##..##...###....##.#..#..###.#.#.###..###....###..####.....#.... 
// C10  = ##....###..####.....#... .##..##...###....##.#..#..###.#.#.###..###....###..####.....#... 
// C11  = #.#...##......###.###### #.#.#...#.#.###.#.##.#.##..##.#.####..###.#...##......###.###### 
// C12  = ##.#...##......###.##### .#.#.#...#.#.###.#.##.#.##..##.#.####..###.#...##......###.##### 
// C13  = ###.#...##......###.#### ..#.#.#...#.#.###.#.##.#.##..##.#.####..###.#...##......###.#### 
// C14  = .###.#...##......###.### ...#.#.#...#.#.###.#.##.#.##..##.#.####..###.#...##......###.### 
// C15  = .####...######..#....... #..#...#..###....##.#.#..#.####..........####...######..#....... 
// C16  = ..####...######..#...... .#..#...#..###....##.#.#..#.####..........####...######..#...... 
// C17  = .#.###..####..###..##.## #.############..#..##.###..#......#.####.#.###..####..###..##.## 
// C18  = #.#.###..####..###..##.# .#.############..#..##.###..#......#.####.#.###..####..###..##.# 
// C19  = ##.#.###..####..###..##. ..#.############..#..##.###..#......#.####.#.###..####..###..##. 
// C20  = #.#.#..#.#.#..#.##..#... #...##...#..##.#...#..#..###.#.##.#.#.#.#.#.#..#.#.#..#.##..#... 
// C21  = ...#.##..##..#.###.##### ##.###.##..#.#......#.....####.#.####.#....#.##..##..#.###.##### 
// C22  = ....#.##..##..#.###.#### .##.###.##..#.#......#.....####.#.####.#....#.##..##..#.###.#### 
// C23  = #....#.##..##..#.###.### ..##.###.##..#.#......#.....####.#.####.#....#.##..##..#.###.### 
//
// Number of XORs used is 24
// Total XOR inputs 1090

module crc24_dat64 (
 input[23:0] crc_in,
 input[63:0] dat_in,
 output[23:0] crc_out
);

parameter METHOD = 1;

generate
  if (METHOD == 0)
    crc24_dat64_flat cc (.c(crc_in),.d(dat_in),.crc_out(crc_out));
  else
    crc24_dat64_factor cc (.c(crc_in),.d(dat_in),.crc_out(crc_out));
endgenerate

endmodule

module crc24_dat64_flat (c,d,crc_out);
input[23:0] c;
input[63:0] d;
output[23:0] crc_out;
wire[23:0] crc_out;

assign crc_out[0] =
    c[1] ^ c[6] ^ c[8] ^ c[9] ^ c[12] ^ c[13] ^ 
    c[16] ^ c[18] ^ c[19] ^ c[20] ^ c[22] ^ c[23] ^ d[63] ^ 
    d[62] ^ d[60] ^ d[59] ^ d[58] ^ d[56] ^ d[53] ^ d[52] ^ 
    d[49] ^ d[48] ^ d[46] ^ d[41] ^ d[39] ^ d[38] ^ d[37] ^ 
    d[36] ^ d[34] ^ d[32] ^ d[31] ^ d[30] ^ d[29] ^ d[23] ^ 
    d[16] ^ d[14] ^ d[11] ^ d[10] ^ d[8] ^ d[7] ^ d[6] ^ 
    d[4] ^ d[3] ^ d[0];

assign crc_out[1] =
    c[0] ^ c[1] ^ c[2] ^ c[6] ^ c[7] ^ c[8] ^ 
    c[10] ^ c[12] ^ c[14] ^ c[16] ^ c[17] ^ c[18] ^ c[21] ^ 
    c[22] ^ d[62] ^ d[61] ^ d[58] ^ d[57] ^ d[56] ^ d[54] ^ 
    d[52] ^ d[50] ^ d[48] ^ d[47] ^ d[46] ^ d[42] ^ d[41] ^ 
    d[40] ^ d[36] ^ d[35] ^ d[34] ^ d[33] ^ d[29] ^ d[24] ^ 
    d[23] ^ d[17] ^ d[16] ^ d[15] ^ d[14] ^ d[12] ^ d[10] ^ 
    d[9] ^ d[6] ^ d[5] ^ d[3] ^ d[1] ^ d[0];

assign crc_out[2] =
    c[1] ^ c[2] ^ c[3] ^ c[7] ^ c[8] ^ c[9] ^ 
    c[11] ^ c[13] ^ c[15] ^ c[17] ^ c[18] ^ c[19] ^ c[22] ^ 
    c[23] ^ d[63] ^ d[62] ^ d[59] ^ d[58] ^ d[57] ^ d[55] ^ 
    d[53] ^ d[51] ^ d[49] ^ d[48] ^ d[47] ^ d[43] ^ d[42] ^ 
    d[41] ^ d[37] ^ d[36] ^ d[35] ^ d[34] ^ d[30] ^ d[25] ^ 
    d[24] ^ d[18] ^ d[17] ^ d[16] ^ d[15] ^ d[13] ^ d[11] ^ 
    d[10] ^ d[7] ^ d[6] ^ d[4] ^ d[2] ^ d[1];

assign crc_out[3] =
    c[2] ^ c[3] ^ c[4] ^ c[8] ^ c[9] ^ c[10] ^ 
    c[12] ^ c[14] ^ c[16] ^ c[18] ^ c[19] ^ c[20] ^ c[23] ^ 
    d[63] ^ d[60] ^ d[59] ^ d[58] ^ d[56] ^ d[54] ^ d[52] ^ 
    d[50] ^ d[49] ^ d[48] ^ d[44] ^ d[43] ^ d[42] ^ d[38] ^ 
    d[37] ^ d[36] ^ d[35] ^ d[31] ^ d[26] ^ d[25] ^ d[19] ^ 
    d[18] ^ d[17] ^ d[16] ^ d[14] ^ d[12] ^ d[11] ^ d[8] ^ 
    d[7] ^ d[5] ^ d[3] ^ d[2];

assign crc_out[4] =
    c[3] ^ c[4] ^ c[5] ^ c[9] ^ c[10] ^ c[11] ^ 
    c[13] ^ c[15] ^ c[17] ^ c[19] ^ c[20] ^ c[21] ^ d[61] ^ 
    d[60] ^ d[59] ^ d[57] ^ d[55] ^ d[53] ^ d[51] ^ d[50] ^ 
    d[49] ^ d[45] ^ d[44] ^ d[43] ^ d[39] ^ d[38] ^ d[37] ^ 
    d[36] ^ d[32] ^ d[27] ^ d[26] ^ d[20] ^ d[19] ^ d[18] ^ 
    d[17] ^ d[15] ^ d[13] ^ d[12] ^ d[9] ^ d[8] ^ d[6] ^ 
    d[4] ^ d[3];

assign crc_out[5] =
    c[0] ^ c[1] ^ c[4] ^ c[5] ^ c[8] ^ c[9] ^ 
    c[10] ^ c[11] ^ c[13] ^ c[14] ^ c[19] ^ c[21] ^ c[23] ^ 
    d[63] ^ d[61] ^ d[59] ^ d[54] ^ d[53] ^ d[51] ^ d[50] ^ 
    d[49] ^ d[48] ^ d[45] ^ d[44] ^ d[41] ^ d[40] ^ d[36] ^ 
    d[34] ^ d[33] ^ d[32] ^ d[31] ^ d[30] ^ d[29] ^ d[28] ^ 
    d[27] ^ d[23] ^ d[21] ^ d[20] ^ d[19] ^ d[18] ^ d[13] ^ 
    d[11] ^ d[9] ^ d[8] ^ d[6] ^ d[5] ^ d[3] ^ d[0];

assign crc_out[6] =
    c[2] ^ c[5] ^ c[8] ^ c[10] ^ c[11] ^ c[13] ^ 
    c[14] ^ c[15] ^ c[16] ^ c[18] ^ c[19] ^ c[23] ^ d[63] ^ 
    d[59] ^ d[58] ^ d[56] ^ d[55] ^ d[54] ^ d[53] ^ d[51] ^ 
    d[50] ^ d[48] ^ d[45] ^ d[42] ^ d[39] ^ d[38] ^ d[36] ^ 
    d[35] ^ d[33] ^ d[28] ^ d[24] ^ d[23] ^ d[22] ^ d[21] ^ 
    d[20] ^ d[19] ^ d[16] ^ d[12] ^ d[11] ^ d[9] ^ d[8] ^ 
    d[3] ^ d[1] ^ d[0];

assign crc_out[7] =
    c[0] ^ c[3] ^ c[6] ^ c[9] ^ c[11] ^ c[12] ^ 
    c[14] ^ c[15] ^ c[16] ^ c[17] ^ c[19] ^ c[20] ^ d[60] ^ 
    d[59] ^ d[57] ^ d[56] ^ d[55] ^ d[54] ^ d[52] ^ d[51] ^ 
    d[49] ^ d[46] ^ d[43] ^ d[40] ^ d[39] ^ d[37] ^ d[36] ^ 
    d[34] ^ d[29] ^ d[25] ^ d[24] ^ d[23] ^ d[22] ^ d[21] ^ 
    d[20] ^ d[17] ^ d[13] ^ d[12] ^ d[10] ^ d[9] ^ d[4] ^ 
    d[2] ^ d[1];

assign crc_out[8] =
    c[0] ^ c[4] ^ c[6] ^ c[7] ^ c[8] ^ c[9] ^ 
    c[10] ^ c[15] ^ c[17] ^ c[19] ^ c[21] ^ c[22] ^ c[23] ^ 
    d[63] ^ d[62] ^ d[61] ^ d[59] ^ d[57] ^ d[55] ^ d[50] ^ 
    d[49] ^ d[48] ^ d[47] ^ d[46] ^ d[44] ^ d[40] ^ d[39] ^ 
    d[36] ^ d[35] ^ d[34] ^ d[32] ^ d[31] ^ d[29] ^ d[26] ^ 
    d[25] ^ d[24] ^ d[22] ^ d[21] ^ d[18] ^ d[16] ^ d[13] ^ 
    d[8] ^ d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[0];

assign crc_out[9] =
    c[0] ^ c[5] ^ c[6] ^ c[7] ^ c[10] ^ c[11] ^ 
    c[12] ^ c[13] ^ c[19] ^ d[59] ^ d[53] ^ d[52] ^ d[51] ^ 
    d[50] ^ d[47] ^ d[46] ^ d[45] ^ d[40] ^ d[39] ^ d[38] ^ 
    d[35] ^ d[34] ^ d[33] ^ d[31] ^ d[29] ^ d[27] ^ d[26] ^ 
    d[25] ^ d[22] ^ d[19] ^ d[17] ^ d[16] ^ d[11] ^ d[10] ^ 
    d[9] ^ d[5] ^ d[4] ^ d[1] ^ d[0];

assign crc_out[10] =
    c[0] ^ c[1] ^ c[6] ^ c[7] ^ c[8] ^ c[11] ^ 
    c[12] ^ c[13] ^ c[14] ^ c[20] ^ d[60] ^ d[54] ^ d[53] ^ 
    d[52] ^ d[51] ^ d[48] ^ d[47] ^ d[46] ^ d[41] ^ d[40] ^ 
    d[39] ^ d[36] ^ d[35] ^ d[34] ^ d[32] ^ d[30] ^ d[28] ^ 
    d[27] ^ d[26] ^ d[23] ^ d[20] ^ d[18] ^ d[17] ^ d[12] ^ 
    d[11] ^ d[10] ^ d[6] ^ d[5] ^ d[2] ^ d[1];

assign crc_out[11] =
    c[0] ^ c[2] ^ c[6] ^ c[7] ^ c[14] ^ c[15] ^ 
    c[16] ^ c[18] ^ c[19] ^ c[20] ^ c[21] ^ c[22] ^ c[23] ^ 
    d[63] ^ d[62] ^ d[61] ^ d[60] ^ d[59] ^ d[58] ^ d[56] ^ 
    d[55] ^ d[54] ^ d[47] ^ d[46] ^ d[42] ^ d[40] ^ d[39] ^ 
    d[38] ^ d[35] ^ d[34] ^ d[33] ^ d[32] ^ d[30] ^ d[28] ^ 
    d[27] ^ d[24] ^ d[23] ^ d[21] ^ d[19] ^ d[18] ^ d[16] ^ 
    d[14] ^ d[13] ^ d[12] ^ d[10] ^ d[8] ^ d[4] ^ d[2] ^ 
    d[0];

assign crc_out[12] =
    c[0] ^ c[1] ^ c[3] ^ c[7] ^ c[8] ^ c[15] ^ 
    c[16] ^ c[17] ^ c[19] ^ c[20] ^ c[21] ^ c[22] ^ c[23] ^ 
    d[63] ^ d[62] ^ d[61] ^ d[60] ^ d[59] ^ d[57] ^ d[56] ^ 
    d[55] ^ d[48] ^ d[47] ^ d[43] ^ d[41] ^ d[40] ^ d[39] ^ 
    d[36] ^ d[35] ^ d[34] ^ d[33] ^ d[31] ^ d[29] ^ d[28] ^ 
    d[25] ^ d[24] ^ d[22] ^ d[20] ^ d[19] ^ d[17] ^ d[15] ^ 
    d[14] ^ d[13] ^ d[11] ^ d[9] ^ d[5] ^ d[3] ^ d[1];

assign crc_out[13] =
    c[0] ^ c[1] ^ c[2] ^ c[4] ^ c[8] ^ c[9] ^ 
    c[16] ^ c[17] ^ c[18] ^ c[20] ^ c[21] ^ c[22] ^ c[23] ^ 
    d[63] ^ d[62] ^ d[61] ^ d[60] ^ d[58] ^ d[57] ^ d[56] ^ 
    d[49] ^ d[48] ^ d[44] ^ d[42] ^ d[41] ^ d[40] ^ d[37] ^ 
    d[36] ^ d[35] ^ d[34] ^ d[32] ^ d[30] ^ d[29] ^ d[26] ^ 
    d[25] ^ d[23] ^ d[21] ^ d[20] ^ d[18] ^ d[16] ^ d[15] ^ 
    d[14] ^ d[12] ^ d[10] ^ d[6] ^ d[4] ^ d[2];

assign crc_out[14] =
    c[1] ^ c[2] ^ c[3] ^ c[5] ^ c[9] ^ c[10] ^ 
    c[17] ^ c[18] ^ c[19] ^ c[21] ^ c[22] ^ c[23] ^ d[63] ^ 
    d[62] ^ d[61] ^ d[59] ^ d[58] ^ d[57] ^ d[50] ^ d[49] ^ 
    d[45] ^ d[43] ^ d[42] ^ d[41] ^ d[38] ^ d[37] ^ d[36] ^ 
    d[35] ^ d[33] ^ d[31] ^ d[30] ^ d[27] ^ d[26] ^ d[24] ^ 
    d[22] ^ d[21] ^ d[19] ^ d[17] ^ d[16] ^ d[15] ^ d[13] ^ 
    d[11] ^ d[7] ^ d[5] ^ d[3];

assign crc_out[15] =
    c[1] ^ c[2] ^ c[3] ^ c[4] ^ c[8] ^ c[9] ^ 
    c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[16] ^ d[56] ^ d[53] ^ 
    d[52] ^ d[51] ^ d[50] ^ d[49] ^ d[48] ^ d[44] ^ d[43] ^ 
    d[42] ^ d[41] ^ d[30] ^ d[29] ^ d[28] ^ d[27] ^ d[25] ^ 
    d[22] ^ d[20] ^ d[18] ^ d[17] ^ d[12] ^ d[11] ^ d[10] ^ 
    d[7] ^ d[3] ^ d[0];

assign crc_out[16] =
    c[2] ^ c[3] ^ c[4] ^ c[5] ^ c[9] ^ c[10] ^ 
    c[11] ^ c[12] ^ c[13] ^ c[14] ^ c[17] ^ d[57] ^ d[54] ^ 
    d[53] ^ d[52] ^ d[51] ^ d[50] ^ d[49] ^ d[45] ^ d[44] ^ 
    d[43] ^ d[42] ^ d[31] ^ d[30] ^ d[29] ^ d[28] ^ d[26] ^ 
    d[23] ^ d[21] ^ d[19] ^ d[18] ^ d[13] ^ d[12] ^ d[11] ^ 
    d[8] ^ d[4] ^ d[1];

assign crc_out[17] =
    c[1] ^ c[3] ^ c[4] ^ c[5] ^ c[8] ^ c[9] ^ 
    c[10] ^ c[11] ^ c[14] ^ c[15] ^ c[16] ^ c[19] ^ c[20] ^ 
    c[22] ^ c[23] ^ d[63] ^ d[62] ^ d[60] ^ d[59] ^ d[56] ^ 
    d[55] ^ d[54] ^ d[51] ^ d[50] ^ d[49] ^ d[48] ^ d[45] ^ 
    d[44] ^ d[43] ^ d[41] ^ d[39] ^ d[38] ^ d[37] ^ d[36] ^ 
    d[34] ^ d[27] ^ d[24] ^ d[23] ^ d[22] ^ d[20] ^ d[19] ^ 
    d[16] ^ d[13] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ 
    d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[2] ^ d[0];

assign crc_out[18] =
    c[0] ^ c[2] ^ c[4] ^ c[5] ^ c[6] ^ c[9] ^ 
    c[10] ^ c[11] ^ c[12] ^ c[15] ^ c[16] ^ c[17] ^ c[20] ^ 
    c[21] ^ c[23] ^ d[63] ^ d[61] ^ d[60] ^ d[57] ^ d[56] ^ 
    d[55] ^ d[52] ^ d[51] ^ d[50] ^ d[49] ^ d[46] ^ d[45] ^ 
    d[44] ^ d[42] ^ d[40] ^ d[39] ^ d[38] ^ d[37] ^ d[35] ^ 
    d[28] ^ d[25] ^ d[24] ^ d[23] ^ d[21] ^ d[20] ^ d[17] ^ 
    d[14] ^ d[13] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ 
    d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[1];

assign crc_out[19] =
    c[0] ^ c[1] ^ c[3] ^ c[5] ^ c[6] ^ c[7] ^ 
    c[10] ^ c[11] ^ c[12] ^ c[13] ^ c[16] ^ c[17] ^ c[18] ^ 
    c[21] ^ c[22] ^ d[62] ^ d[61] ^ d[58] ^ d[57] ^ d[56] ^ 
    d[53] ^ d[52] ^ d[51] ^ d[50] ^ d[47] ^ d[46] ^ d[45] ^ 
    d[43] ^ d[41] ^ d[40] ^ d[39] ^ d[38] ^ d[36] ^ d[29] ^ 
    d[26] ^ d[25] ^ d[24] ^ d[22] ^ d[21] ^ d[18] ^ d[15] ^ 
    d[14] ^ d[13] ^ d[12] ^ d[11] ^ d[10] ^ d[9] ^ d[8] ^ 
    d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[2];

assign crc_out[20] =
    c[0] ^ c[2] ^ c[4] ^ c[7] ^ c[9] ^ c[11] ^ 
    c[14] ^ c[16] ^ c[17] ^ c[20] ^ d[60] ^ d[57] ^ d[56] ^ 
    d[54] ^ d[51] ^ d[49] ^ d[47] ^ d[44] ^ d[42] ^ d[40] ^ 
    d[38] ^ d[36] ^ d[34] ^ d[32] ^ d[31] ^ d[29] ^ d[27] ^ 
    d[26] ^ d[25] ^ d[22] ^ d[19] ^ d[15] ^ d[13] ^ d[12] ^ 
    d[9] ^ d[5] ^ d[4] ^ d[0];

assign crc_out[21] =
    c[3] ^ c[5] ^ c[6] ^ c[9] ^ c[10] ^ c[13] ^ 
    c[15] ^ c[16] ^ c[17] ^ c[19] ^ c[20] ^ c[21] ^ c[22] ^ 
    c[23] ^ d[63] ^ d[62] ^ d[61] ^ d[60] ^ d[59] ^ d[57] ^ 
    d[56] ^ d[55] ^ d[53] ^ d[50] ^ d[49] ^ d[46] ^ d[45] ^ 
    d[43] ^ d[38] ^ d[36] ^ d[35] ^ d[34] ^ d[33] ^ d[31] ^ 
    d[29] ^ d[28] ^ d[27] ^ d[26] ^ d[20] ^ d[13] ^ d[11] ^ 
    d[8] ^ d[7] ^ d[5] ^ d[4] ^ d[3] ^ d[1] ^ d[0];

assign crc_out[22] =
    c[4] ^ c[6] ^ c[7] ^ c[10] ^ c[11] ^ c[14] ^ 
    c[16] ^ c[17] ^ c[18] ^ c[20] ^ c[21] ^ c[22] ^ c[23] ^ 
    d[63] ^ d[62] ^ d[61] ^ d[60] ^ d[58] ^ d[57] ^ d[56] ^ 
    d[54] ^ d[51] ^ d[50] ^ d[47] ^ d[46] ^ d[44] ^ d[39] ^ 
    d[37] ^ d[36] ^ d[35] ^ d[34] ^ d[32] ^ d[30] ^ d[29] ^ 
    d[28] ^ d[27] ^ d[21] ^ d[14] ^ d[12] ^ d[9] ^ d[8] ^ 
    d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1];

assign crc_out[23] =
    c[0] ^ c[5] ^ c[7] ^ c[8] ^ c[11] ^ c[12] ^ 
    c[15] ^ c[17] ^ c[18] ^ c[19] ^ c[21] ^ c[22] ^ c[23] ^ 
    d[63] ^ d[62] ^ d[61] ^ d[59] ^ d[58] ^ d[57] ^ d[55] ^ 
    d[52] ^ d[51] ^ d[48] ^ d[47] ^ d[45] ^ d[40] ^ d[38] ^ 
    d[37] ^ d[36] ^ d[35] ^ d[33] ^ d[31] ^ d[30] ^ d[29] ^ 
    d[28] ^ d[22] ^ d[15] ^ d[13] ^ d[10] ^ d[9] ^ d[7] ^ 
    d[6] ^ d[5] ^ d[3] ^ d[2];

endmodule

module crc24_dat64_factor (c,d,crc_out);
input[23:0] c;
input[63:0] d;
output[23:0] crc_out;
wire[23:0] crc_out;

wire[114:0] h ;

xor6 cx_0 (crc_out[0],    h[51] , h[60] , h[66] , h[73] , h[80] , h[93]);
xor6 cx_1 (crc_out[1],    h[16] , h[37] , h[44] , h[61] , h[104] , h[114]);
xor6 cx_2 (crc_out[2],    h[35] , h[36] , h[44] , h[57] , h[112] , h[113]);
xor6 cx_3 (crc_out[3],    h[32] , h[35] , h[37] , h[40] , h[41] , h[111]);
xor6 cx_4 (crc_out[4],    h[44] , h[46] , h[59] , h[65] , h[109] , h[110]);
xor6 cx_5 (crc_out[5],    h[45] , h[46] , h[63] , h[64] , h[107] , h[108]);
xor6 cx_6 (crc_out[6],    h[24] , h[34] , h[65] , h[67] , h[105] , h[106]);
xor6 cx_7 (crc_out[7],    h[40] , h[49] , h[58] , h[67] , h[102] , h[103]);
xor6 cx_8 (crc_out[8],    h[35] , h[39] , h[63] , h[66] , h[100] , h[101]);
xor6 cx_9 (crc_out[9],    h[27] , h[45] , h[61] , h[66] , h[98] , h[99]);
xor6 cx_10 (crc_out[10],    h[33] , h[44] , h[48] , h[95] , h[96] , h[97]);
xor6 cx_11 (crc_out[11],    h[22] , h[33] , h[36] , h[49] , h[59] , h[94]);
xor6 cx_12 (crc_out[12],    h[12] , h[44] , h[62] , h[90] , h[91] , h[92]);
xor6 cx_13 (crc_out[13],    h[35] , h[38] , h[50] , h[64] , h[88] , h[89]);
xor6 cx_14 (crc_out[14],    h[34] , h[50] , h[56] , h[62] , h[86] , h[87]);
xor6 cx_15 (crc_out[15],    h[19] , h[38] , h[48] , h[55] , h[84] , h[85]);
xor6 cx_16 (crc_out[16],    h[30] , h[38] , h[42] , h[54] , h[62] , h[83]);
xor6 cx_17 (crc_out[17],    h[25] , h[31] , h[54] , h[66] , h[81] , h[82]);
xor6 cx_18 (crc_out[18],    h[41] , h[55] , h[60] , h[63] , h[78] , h[79]);
xor6 cx_19 (crc_out[19],    h[21] , h[28] , h[74] , h[75] , h[76] , h[77]);
xor6 cx_20 (crc_out[20],    h[42] , h[45] , h[51] , h[57] , h[71] , h[72]);
xor6 cx_21 (crc_out[21],    h[29] , h[56] , h[67] , h[68] , h[69] , h[70]);
xor6 cx_22 (crc_out[22],    h[31] , h[37] , h[39] , h[52] , h[53] , h[58]);
xor6 cx_23 (crc_out[23],    h[19] , h[23] , h[43] , h[47] , h[63] , h[73]);
xor6 hx_0 (h[0],    c[19] , c[23] , d[63] , d[59] , d[36] , d[13]);   // used by 8
xor6 hx_1 (h[1],    c[16] , c[20] , d[60] , d[56] , d[36] , d[12]);   // used by 5
xor6 hx_2 (h[2],    c[17] , c[21] , d[61] , d[57] , d[35] , d[5]);   // used by 8
xor6 hx_3 (h[3],    c[9] , c[17] , d[57] , d[49] , d[37] , d[4]);   // used by 4
xor6 hx_4 (h[4],    c[9] , c[10] , d[50] , d[49] , d[11] , d[7]);   // used by 4
xor6 hx_5 (h[5],    c[5] , c[10] , c[11] , d[51] , d[50] , d[45]);   // used by 8
xor6 hx_6 (h[6],    c[0] , c[7] , d[47] , d[40] , d[34] , d[10]);   // used by 4
xor6 hx_7 (h[7],    c[6] , d[46] , d[39] , d[34] , d[8] , d[4]);   // used by 3
xor6 hx_8 (h[8],    c[18] , c[22] , d[62] , d[58] , d[16] , d[2]);   // used by 3
xor6 hx_9 (h[9],    c[0] , d[40] , d[29] , d[25] , d[22] , d[9]);   // used by 4
xor6 hx_10 (h[10],    c[12] , c[13] , d[53] , d[52] , d[29] , d[11]);   // used by 3
xor6 hx_11 (h[11],    c[1] , c[16] , c[22] , d[62] , d[56] , d[41]);   // used by 5
xor6 hx_12 (h[12],    c[15] , c[20] , d[60] , d[55] , d[39] , d[20]);   // used by 4
xor6 hx_13 (h[13],    c[8] , c[14] , d[54] , d[48] , d[23] , d[3]);   // used by 4
xor6 hx_14 (h[14],    c[2] , c[14] , d[54] , d[42] , d[38] , d[19]);   // used by 3
xor6 hx_15 (h[15],    c[4] , c[9] , d[49] , d[44] , d[21] , d[6]);   // used by 3
xor6 hx_16 (h[16],    c[6] , c[12] , d[52] , d[46] , d[24] , d[12]);   // used by 3
xor6 hx_17 (h[17],    c[1] , c[13] , d[53] , d[41] , d[30] , d[18]);   // used by 4
xor6 hx_18 (h[18],    c[18] , d[58] , d[37] , d[31] , d[30] , d[3]);   // used by 3
xor6 hx_19 (h[19],    c[8] , c[11] , c[12] , d[52] , d[51] , d[48]);   // used by 3
xor6 hx_20 (h[20],    c[16] , d[56] , d[33] , d[28] , d[8] , d[0]);   // used by 3
xor6 hx_21 (h[21],    c[3] , d[43] , d[38] , d[26] , d[18] , d[8]);   // used by 2
xor6 hx_22 (h[22],    c[23] , d[63] , d[32] , d[30] , d[23] , d[14]);   // used by 3
xor6 hx_23 (h[23],    c[7] , c[22] , d[62] , d[47] , d[29] , d[2]);   // used by 3
xor6 hx_24 (h[24],    c[19] , c[23] , d[63] , d[59] , d[35] , d[16]);   // used by 2
xor6 hx_25 (h[25],    c[3] , d[43] , d[34] , d[24] , d[11] , d[10]);   // used by 3
xor6 hx_26 (h[26],    d[38] , d[17] , d[9] , d[1] , 1'b0 , 1'b0);   // used by 1
xor6 hx_27 (h[27],    c[6] , c[19] , d[59] , d[46] , d[39] , d[17]);   // used by 2
xor6 hx_28 (h[28],    c[21] , d[61] , d[21] , d[15] , d[10] , d[6]);   // used by 2
xor6 hx_29 (h[29],    c[3] , d[43] , d[31] , d[26] , d[3] , d[1]);   // used by 1
xor6 hx_30 (h[30],    c[14] , d[54] , d[28] , d[23] , d[21] , d[1]);   // used by 1
xor6 hx_31 (h[31],    c[4] , d[44] , d[37] , d[27] , d[9] , d[6]);   // used by 2
xor6 hx_32 (h[32],    c[3] , c[4] , d[44] , d[43] , d[26] , d[17]);   // used by 1
xor6 hx_33 (h[33],    c[6] , c[20] , d[60] , d[46] , d[39] , d[27]);   // used by 3
xor6 hx_34 (h[34],    c[2] , d[42] , d[38] , d[24] , d[22] , d[21]);   // used by 2
xor6 hx_35 (h[35],    c[8] , d[48] , d[25] , d[18] , 1'b0 , 1'b0);   // used by 4
xor6 hx_36 (h[36],    c[15] , d[55] , d[35] , d[18] , 1'b0 , 1'b0);   // used by 2
xor6 hx_37 (h[37],    c[18] , d[58] , d[14] , 1'b0 , 1'b0 , 1'b0);   // used by 3
xor6 hx_38 (h[38],    c[2] , c[4] , d[44] , d[42] , 1'
b0 , 1'b0);   // used by 3
xor6 hx_39 (h[39],    c[10] , d[50] , d[32] , 1'
b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_40 (h[40],    c[12] , d[52] , d[2] , 1'b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_41 (h[41],    d[37] , d[8] , d[3] , 1'
b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_42 (h[42],    c[17] , d[57] , d[13] , d[4] , 1'b0 , 1'b0);   // used by 2
xor6 hx_43 (h[43],    d[15] , d[9] , h[0] , h[2] , h[18] , 1'b0);   // used by 1
xor6 hx_44 (h[44],    d[17] , d[15] , d[6] , d[1] , 1'
b0 , 1'b0);   // used by 5
xor6 hx_45 (h[45],    d[31] , d[27] , d[5] , d[0] , 1'
b0 , 1'b0);   // used by 3
xor6 hx_46 (h[46],    d[32] , d[19] , d[9] , 1'
b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_47 (h[47],    c[5] , c[15] , d[55] , d[45] , d[38] , d[33]);   // used by 1
xor6 hx_48 (h[48],    d[28] , d[20] , d[12] , 1'b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_49 (h[49],    d[24] , d[21] , d[13] , 1'
b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_50 (h[50],    c[1] , d[41] , d[26] , 1'b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_51 (h[51],    c[9] , d[49] , d[32] , 1'
b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_52 (h[52],    h[1] , h[2] , h[7] , h[23] , 1'b0 , 1'b0);   // used by 1
xor6 hx_53 (h[53],    c[23] , d[63] , d[30] , d[28] , d[21] , d[1]);   // used by 1
xor6 hx_54 (h[54],    c[9] , d[49] , d[12] , d[8] , 1'b0 , 1'b0);   // used by 2
xor6 hx_55 (h[55],    c[16] , d[56] , d[25] , d[10] , 1'b0 , 1'b0);   // used by 2
xor6 hx_56 (h[56],    c[5] , c[22] , d[62] , d[45] , 1'b0 , 1'b0);   // used by 2
xor6 hx_57 (h[57],    c[7] , c[11] , d[51] , d[47] , 1'b0 , 1'b0);   // used by 2
xor6 hx_58 (h[58],    c[11] , c[14] , d[54] , d[51] , 1'b0 , 1'b0);   // used by 2
xor6 hx_59 (h[59],    c[19] , c[21] , d[61] , d[59] , 1'b0 , 1'b0);   // used by 2
xor6 hx_60 (h[60],    d[32] , d[30] , h[22] , 1'b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_61 (h[61],    d[33] , d[9] , d[0] , 1'
b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_62 (h[62],    c[3] , d[43] , d[19] , 1'b0 , 1'b0 , 1'b0);   // used by 3
xor6 hx_63 (h[63],    c[0] , d[40] , d[28] , d[7] , 1'
b0 , 1'b0);   // used by 4
xor6 hx_64 (h[64],    d[34] , d[29] , d[20] , 1'
b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_65 (h[65],    c[13] , d[53] , d[36] , 1'b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_66 (h[66],    d[38] , d[22] , d[16] , d[0] , 1'
b0 , 1'b0);   // used by 4
xor6 hx_67 (h[67],    c[15] , d[55] , d[20] , d[1] , 1'
b0 , 1'b0);   // used by 3
xor6 hx_68 (h[68],    h[0] , h[2] , h[4] , h[20] , 1'
b0 , 1'b0);   // used by 1
xor6 hx_69 (h[69],    d[38] , d[34] , d[29] , d[27] , d[4] , d[1]);   // used by 1
xor6 hx_70 (h[70],    c[13] , d[53] , d[39] , d[27] , h[33] , 1'
b0);   // used by 1
xor6 hx_71 (h[71],    h[9] , h[14] , 1'b0 , 1'b0 , 1'b0 , 1'b0);   // used by 1
xor6 hx_72 (h[72],    c[4] , d[44] , d[34] , d[26] , d[15] , h[1]);   // used by 1
xor6 hx_73 (h[73],    d[22] , d[10] , d[6] , 1'b0 , 1'b0 , 1'b0);   // used by 2
xor6 hx_74 (h[74],    h[9] , h[11] , h[16] , 1'
b0 , 1'b0 , 1'b0);   // used by 1
xor6 hx_75 (h[75],    d[11] , d[7] , d[5] , d[4] , d[2] , h[5]);   // used by 1
xor6 hx_76 (h[76],    c[18] , d[58] , d[39] , d[36] , d[14] , d[13]);   // used by 1
xor6 hx_77 (h[77],    c[7] , c[13] , c[17] , d[57] , d[53] , d[47]);   // used by 1
xor6 hx_78 (h[78],    c[2] , d[42] , h[15] , h[16] , h[26] , 1'b0);   // used by 1
xor6 hx_79 (h[79],    d[13] , d[11] , d[4] , h[2] , h[5] , h[12]);   // used by 1
xor6 hx_80 (h[80],    c[8] , c[19] , c[20] , d[60] , d[59] , d[48]);   // used by 1
xor6 hx_81 (h[81],    h[5] , h[11] , h[12] , h[13] , 1'
b0 , 1'b0);   // used by 1
xor6 hx_82 (h[82],    d[19] , d[7] , d[5] , d[4] , d[2] , h[0]);   // used by 1
xor6 hx_83 (h[83],    d[31] , d[30] , d[26] , d[18] , h[5] , h[10]);   // used by 1
xor6 hx_84 (h[84],    d[3] , d[0] , h[4] , h[17] , 1'
b0 , 1'b0);   // used by 1
xor6 hx_85 (h[85],    c[3] , d[43] , d[29] , d[27] , d[22] , d[17]);   // used by 1
xor6 hx_86 (h[86],    h[2] , h[4] , h[18] , 1'
b0 , 1'b0 , 1'b0);   // used by 1
xor6 hx_87 (h[87],    d[33] , d[27] , d[17] , d[16] , d[15] , h[0]);   // used by 1
xor6 hx_88 (h[88],    h[22] , h[28] , 1'b0 , 1'b0 , 1'b0 , 1'b0);   // used by 1
xor6 hx_89 (h[89],    c[0] , d[40] , d[35] , h[1] , h[3] , h[8]);   // used by 1
xor6 hx_90 (h[90],    d[3] , h[0] , h[2] , h[9] , h[11] , 1'b0);   // used by 1
xor6 hx_91 (h[91],    d[31] , d[28] , d[24] , d[14] , d[11] , d[6]);   // used by 1
xor6 hx_92 (h[92],    c[7] , c[8] , d[48] , d[47] , d[34] , d[33]);   // used by 1
xor6 hx_93 (h[93],    d[36] , d[7] , h[7] , h[10] , h[11] , h[18]);   // used by 1
xor6 hx_94 (h[94],    d[12] , d[4] , h[6] , h[8] , h[14] , h[20]);   // used by 1
xor6 hx_95 (h[95],    h[17] , h[19] , 1'
b0 , 1'b0 , 1'b0 , 1'b0);   // used by 1
xor6 hx_96 (h[96],    d[23] , d[15] , d[11] , d[5] , d[2] , h[6]);   // used by 1
xor6 hx_97 (h[97],    c[14] , d[54] , d[36] , d[35] , d[32] , d[26]);   // used by 1
xor6 hx_98 (h[98],    h[5] , h[6] , h[10] , 1'
b0 , 1'b0 , 1'b0);   // used by 1
xor6 hx_99 (h[99],    d[35] , d[26] , d[25] , d[19] , d[4] , d[1]);   // used by 1
xor6 hx_100 (h[100],    d[24] , h[0] , h[2] , h[7] , h[15] , h[23]);   // used by 1
xor6 hx_101 (h[101],    c[15] , d[55] , d[38] , d[31] , d[28] , d[26]);   // used by 1
xor6 hx_102 (h[102],    h[3] , h[9] , h[27] , 1'b0 , 1'b0 , 1'b0);   // used by 1
xor6 hx_103 (h[103],    d[24] , d[23] , d[11] , h[1] , h[25] , 1'
b0);   // used by 1
xor6 hx_104 (h[104],    c[2] , c[10] , d[50] , d[42] , d[36] , d[29]);   // used by 1
xor6 hx_105 (h[105],    d[9] , h[5] , h[13] , h[20] , 1'b0 , 1'b0);   // used by 1
xor6 hx_106 (h[106],    c[18] , d[58] , d[39] , d[19] , d[12] , d[11]);   // used by 1
xor6 hx_107 (h[107],    h[0] , h[5] , h[13] , h[15] , h[17] , 1'b0);   // used by 1
xor6 hx_108 (h[108],    c[21] , d[61] , d[33] , d[11] , d[8] , d[7]);   // used by 1
xor6 hx_109 (h[109],    d[1] , h[3] , h[5] , h[12] , h[21] , 1'
b0);   // used by 1
xor6 hx_110 (h[110],    c[4] , d[44] , d[27] , d[13] , d[12] , d[3]);   // used by 1
xor6 hx_111 (h[111],    d[31] , d[5] , h[1] , h[4] , h[14] , h[24]);   // used by 1
xor6 hx_112 (h[112],    h[17] , h[25] , 1'b0 , 1'b0 , 1'b0 , 1'b0);   // used by 1
xor6 hx_113 (h[113],    c[2] , d[42] , d[7] , h[0] , h[3] , h[8]);   // used by 1
xor6 hx_114 (h[114],    d[16] , h[2] , h[6] , h[11] , h[13] , 1'b0);   // used by 1
endmodule

常用CRC类型

PCIe:CRC16

  • 用于链路层帧的校验;
  • 多项式是100Bh(16,12,3,1,0);
  • 初始值是16’hFFFF;
  • 发送电路中对计算结果(余数)取补,即在发送过程中进行比特取反;
  • 接收电路比较本地计算的CRC结果与接收到的CRC结果,判断两者是否匹配,接收到的CRC不参与校验计算。

PCIe:CRC32

  • 用于处理层数据包的校验;
  • 多项式是04CllDB7h(32,26,23,22,16,12,11,10,8,7,5,4,2,1,0);
  • 初始值是32’hFFFF_FFFF;
  • 发送电路中对计算结果(余数)取补,即在发送过程中对比特取反;
  • 接收电路比较本地计算的CRC结果与接收到的CRC结果,判断两者是否匹配,接收到的CRC不参与校验计算。

USB3.0:CRC16

  • 用于USB3.0包头校验;
  • 多项式是l00Bh(16,12,3,1,0);
  • 初始值是16’hFFFF;
  • 在传输过程中对结果取补;
  • 接收电路的余数是16’hFCAA;
  • 接收的CRC值参与接收端的CRC计算。

关于和已知余数进行比较:

接收电路边接收数据边计算CRC校验值,如果接收数据中没有错误,则计算得到的余数为5’b0_100。将接收端的CRC计算结果和一个已知的值进行比较,比和接收的CRC进行比较要更加简单。在实际电路设计中,当接收到END符号时,电路内部产生end_pkt(包结束)信号,但此时接收数据中的CRC已经进入接收CRC计算电路中了,对于变长的数据包来说,预先知道接收的数据何时结束及接收包中CRC域何时开始是比较困难的。此时可以考虑使用多级移位寄存器对数据进行缓冲,然后得到新的start_pkt及end_pkt信号,并利用它们将接收数据域和接收的CRC域区分开。

USB2.0:CRC16

  • 用于USB2.0数据传输;
  • 多项式是8005h(16,15,2,0);
  • 初始值是16’hFFFF;
  • 在发送过程中对计算结果进行取补;
  • 接收电路的余数是16’h800D;
  • 在接收端,接收到的CRC值包含在CRC计算中。

USB:CRC5

  • 用于链路控制字段的校验;
  • 多项式是05h(5,2,0);
  • 初始值是5’b1_lll;
  • 在发送过程中对计算结果取补;
  • 接收端的校验结果都是5’b0_l100;
  • 接收的CRC值参与CRC计算;
  • 接收电路将校验结果和5’b0_1100进行比较。

USB3.0:CRC32

  • 用于USB3.0数据包传输;
  • 多项式是04Cl_1DB7h(32,26,23,22,16,12,11,10,8,7,5,4,2,1,0);
  • 初始值是32’hFFFF_FFFF;
  • 发送电路在传输过程中对余数(校验结果)取补;
  • 接收电路的校验余数是32’hC704_DD7B;
  • 接收到的CRC值参与CRC计算;
  • 接收电路将校验结果和32’hC704_DD7B进行比较。

SATA:CRC32

  • 用于FIS(Frame Information Structure)包;
  • 多项式是04C11DB7h(32,26,23,22,16,12,11,10,8,7,5,4,2,1,0);
  • 初始值是32’h5232_5032;
  • 发送电路对校验余数校验结果取补,在传输过程中,将1字节内的比特翻转;
  • 接收电路的余数是16’h0000;
  • 接收端,接收的CRC值参与校验运算,校验结果应该为全0。

关于实例

整篇文章偏理论,计算实例可以通过(https://www.easics.com/crctool/)(可以直接得到Verilog源码)计算得到,当然还有一个脚本可以使用-任意多项式,任意位宽crc verilog代码自动生成perl脚本《https://cloud.tencent.com/developer/article/1652744》。

使用方法:

链接:https://pan.baidu.com/s/1pBlDHDxGRoXwyFKVuypR9A 提取码:open

gen_crc.pl   输入数据位宽    多项式

多项式输入方法:从低位向高位依次输入,以USB TOKEN为例,x^5 + x^2 + 1,从低到高位输入为101001 usb token的crc生成方法:gen_crc.pl 8 101001 usb data的crc(x^16+x^15+x^2+1)生成方法:gen_crc.pl  8 10100000000000011

链接: https://pan.baidu.com/s/1kqRsSBJRq64tNnmv1SYjXQ

提取码: jr8i

说明:

windows下要安装ActivePerl。

1、在Windows上用ActivePerl写一个HelloWorld,测试完毕后,我们在C盘创建一个文件。

HelloWorld.pl

2、右键HelloWorld.pl文件 -> 用记事本打开该文件,然后输入以下代码:

#!/usr/bin/env perl

print "HelloWorld"

3、然后保存

4、回到cmd命令提示符。

cd

返回到C盘根目录

perl HelloWorld.pl

或者直接键入HelloWorld.pl

解释下:2行代码的作用

#!/usr/bin/env perl是典型的解释器路径声明(魔法声明),如果考虑到跨平台,在Unix/Linux上使用的,是必须要加上这个声明的,如果只是单纯的在windows上学习Perl,这个声明无关紧要。

print "HelloWorld"则是一条语句,作用就是在屏幕上输出一个字符串,""内的则是字符串,例如小伙伴可以尝试修改""内的内容。

Linux下就命令行perl perlname.pl

我是在虚拟机下运行的,所以无需安装特殊软件,直接perl gen_crc.pl 8 101001

就可以了。

最后就是Intel官方的算法资料,只能说很强大,每个实例图解很完美,截图看下:

链接:https://pan.baidu.com/s/12Ag-pkDsY_5EL0UoWgy7cQ 提取码:open


参考资料

https://www.lammertbies.nl/comm/info/crc-calculation

https://cloud.tencent.com/developer/article/1652744




点击图片了解活动详情



更多精彩干货,点击下方关注查看



关注『面包板社区』,后台回复"关键词"领取300 G学习资料包如:电源、电机、嵌入式、信号系统、模电、华为、电子学、电路、c语言...)



#推荐阅读#

  • USB 接口电路设计常见问题

  • 画好原理图的技巧

  • 完美通俗解读小波变换,终于懂了小波是什么

  • 电流检测电路

  • Altium Design PCB拼板完整教程

  • 怎么办?单片机固件又被人破解了~~

  • 示波器接地良好,反而容易炸机?

  • 数学之美:谈Smith圆图

  • 硬件知识“三重奏”



点击阅读原文,下载《Verilog数字系统设计教程

面包板社区 面包板社区——中国第一电子人社交平台 面包板社区是Aspencore旗下媒体,整合了电子工程专辑、电子技术设计、国际电子商情丰富资源。社区包括论坛、博客、问答,拥有超过250万注册用户,加入面包板社区,从菜鸟变大神,打造您的电子人脉社交圈!
评论
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 166浏览
  • 日前,商务部等部门办公厅印发《手机、平板、智能手表(手环)购新补贴实施方案》明确,个人消费者购买手机、平板、智能手表(手环)3类数码产品(单件销售价格不超过6000元),可享受购新补贴。每人每类可补贴1件,每件补贴比例为减去生产、流通环节及移动运营商所有优惠后最终销售价格的15%,每件最高不超过500元。目前,京东已经做好了承接手机、平板等数码产品国补优惠的落地准备工作,未来随着各省市关于手机、平板等品类的国补开启,京东将第一时间率先上线,满足消费者的换新升级需求。为保障国补的真实有效发放,基于
    华尔街科技眼 2025-01-17 10:44 221浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 547浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 70浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 187浏览
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 108浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 160浏览
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 173浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 78浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 82浏览
  • 随着消费者对汽车驾乘体验的要求不断攀升,汽车照明系统作为确保道路安全、提升驾驶体验以及实现车辆与环境交互的重要组成,日益受到业界的高度重视。近日,2024 DVN(上海)国际汽车照明研讨会圆满落幕。作为照明与传感创新的全球领导者,艾迈斯欧司朗受邀参与主题演讲,并现场展示了其多项前沿技术。本届研讨会汇聚来自全球各地400余名汽车、照明、光源及Tier 2供应商的专业人士及专家共聚一堂。在研讨会第一环节中,艾迈斯欧司朗系统解决方案工程副总裁 Joachim Reill以深厚的专业素养,主持该环节多位
    艾迈斯欧司朗 2025-01-16 20:51 202浏览
  • 80,000人到访的国际大展上,艾迈斯欧司朗有哪些亮点?感未来,光无限。近日,在慕尼黑electronica 2024现场,ams OSRAM通过多款创新DEMO展示,以及数场前瞻洞察分享,全面展示自身融合传感器、发射器及集成电路技术,精准捕捉并呈现环境信息的卓越能力。同时,ams OSRAM通过展会期间与客户、用户等行业人士,以及媒体朋友的深度交流,向业界传达其以光电技术为笔、以创新为墨,书写智能未来的深度思考。electronica 2024electronica 2024构建了一个高度国际
    艾迈斯欧司朗 2025-01-16 20:45 494浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 204浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 126浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦