当前位置:   article > 正文

CRC计算-Verilog实现

CRC计算-Verilog实现

一、前言

循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包和计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。(只能检验错误,而不能纠错)。

CRC校验的原理可以参考此篇文章:CRC校验详解(附代码示例)_crc校验代码-CSDN博客

在此不做过多的赘述。

二、数据宽度为8bit的CRC校验

CRC校验的verilog代码可以通过Easics CRC Tool此网站生成,在此网站可以选择常用的生成多项式,比如32位的以太网生成多项式。

也可以自己选择生成多项式,然后根据这篇博客中的表项,选择初始值以及是否要进行数据反转、取反。 

下面是根据8位输入,32位输出的CRC代码

  1. module CRC32_D8(
  2. input i_clk ,
  3. input i_rst ,
  4. input [7:0] i_data ,
  5. input i_en ,
  6. output[31:0] o_crc
  7. );
  8. reg [31:0] crc ;
  9. wire [7:0] d ;
  10. wire [31:0] c ;
  11. wire [31:0] newcrc ;
  12. assign o_crc = ~{crc[0],crc[1],crc[2],crc[3],crc[4],crc[5],crc[6],crc[7],crc[8],crc[9],
  13. crc[10],crc[11],crc[12],crc[13],crc[14],crc[15],crc[16],crc[17],crc[18],crc[19],
  14. crc[20],crc[21],crc[22],crc[23],crc[24],crc[25],crc[26],crc[27],crc[28],crc[29],
  15. crc[30],crc[31]} ;//本次计算的CRC结果输出,数据反转,并进行取反
  16. assign d = {i_data[0],i_data[1],i_data[2],i_data[3],i_data[4],i_data[5],i_data[6],i_data[7]}; //需不需要反转需要查表
  17. assign c = crc;//将本次计算的赋值给下一次运算的中间变量
  18. assign newcrc[0] = d[6] ^ d[0] ^ c[24] ^ c[30];
  19. assign newcrc[1] = d[7] ^ d[6] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[30] ^ c[31];
  20. assign newcrc[2] = d[7] ^ d[6] ^ d[2] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[26] ^ c[30] ^ c[31];
  21. assign newcrc[3] = d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[25] ^ c[26] ^ c[27] ^ c[31];
  22. assign newcrc[4] = d[6] ^ d[4] ^ d[3] ^ d[2] ^ d[0] ^ c[24] ^ c[26] ^ c[27] ^ c[28] ^ c[30];
  23. assign newcrc[5] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[27] ^ c[28] ^ c[29] ^ c[30] ^ c[31];
  24. assign newcrc[6] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ c[25] ^ c[26] ^ c[28] ^ c[29] ^ c[30] ^ c[31];
  25. assign newcrc[7] = d[7] ^ d[5] ^ d[3] ^ d[2] ^ d[0] ^ c[24] ^ c[26] ^ c[27] ^ c[29] ^ c[31];
  26. assign newcrc[8] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[0] ^ c[24] ^ c[25] ^ c[27] ^ c[28];
  27. assign newcrc[9] = d[5] ^ d[4] ^ d[2] ^ d[1] ^ c[1] ^ c[25] ^ c[26] ^ c[28] ^ c[29];
  28. assign newcrc[10] = d[5] ^ d[3] ^ d[2] ^ d[0] ^ c[2] ^ c[24] ^ c[26] ^ c[27] ^ c[29];
  29. assign newcrc[11] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[3] ^ c[24] ^ c[25] ^ c[27] ^ c[28];
  30. assign newcrc[12] = d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ d[0] ^ c[4] ^ c[24] ^ c[25] ^ c[26] ^ c[28] ^ c[29] ^ c[30];
  31. assign newcrc[13] = d[7] ^ d[6] ^ d[5] ^ d[3] ^ d[2] ^ d[1] ^ c[5] ^ c[25] ^ c[26] ^ c[27] ^ c[29] ^ c[30] ^ c[31];
  32. assign newcrc[14] = d[7] ^ d[6] ^ d[4] ^ d[3] ^ d[2] ^ c[6] ^ c[26] ^ c[27] ^ c[28] ^ c[30] ^ c[31];
  33. assign newcrc[15] = d[7] ^ d[5] ^ d[4] ^ d[3] ^ c[7] ^ c[27] ^ c[28] ^ c[29] ^ c[31];
  34. assign newcrc[16] = d[5] ^ d[4] ^ d[0] ^ c[8] ^ c[24] ^ c[28] ^ c[29];
  35. assign newcrc[17] = d[6] ^ d[5] ^ d[1] ^ c[9] ^ c[25] ^ c[29] ^ c[30];
  36. assign newcrc[18] = d[7] ^ d[6] ^ d[2] ^ c[10] ^ c[26] ^ c[30] ^ c[31];
  37. assign newcrc[19] = d[7] ^ d[3] ^ c[11] ^ c[27] ^ c[31];
  38. assign newcrc[20] = d[4] ^ c[12] ^ c[28];
  39. assign newcrc[21] = d[5] ^ c[13] ^ c[29];
  40. assign newcrc[22] = d[0] ^ c[14] ^ c[24];
  41. assign newcrc[23] = d[6] ^ d[1] ^ d[0] ^ c[15] ^ c[24] ^ c[25] ^ c[30];
  42. assign newcrc[24] = d[7] ^ d[2] ^ d[1] ^ c[16] ^ c[25] ^ c[26] ^ c[31];
  43. assign newcrc[25] = d[3] ^ d[2] ^ c[17] ^ c[26] ^ c[27];
  44. assign newcrc[26] = d[6] ^ d[4] ^ d[3] ^ d[0] ^ c[18] ^ c[24] ^ c[27] ^ c[28] ^ c[30];
  45. assign newcrc[27] = d[7] ^ d[5] ^ d[4] ^ d[1] ^ c[19] ^ c[25] ^ c[28] ^ c[29] ^ c[31];
  46. assign newcrc[28] = d[6] ^ d[5] ^ d[2] ^ c[20] ^ c[26] ^ c[29] ^ c[30];
  47. assign newcrc[29] = d[7] ^ d[6] ^ d[3] ^ c[21] ^ c[27] ^ c[30] ^ c[31];
  48. assign newcrc[30] = d[7] ^ d[4] ^ c[22] ^ c[28] ^ c[31];
  49. assign newcrc[31] = d[5] ^ c[23] ^ c[29];
  50. always@(posedge i_clk,posedge i_rst)begin
  51. if(i_rst)
  52. crc <= 32'hFFFFFFFF;
  53. else if(i_en)
  54. crc <= newcrc;
  55. else
  56. crc <= crc;
  57. end
  58. endmodule

三、数据宽度打入8bit的CRC校验

当输入的数据宽度大于1byte时,假设为B1B2B3B4B5B6B7,需要首先计算出B1的CRC1,然后在CRC1的基础上(CRC2的初值变为CRC1)计算B2的CRC2,之后一直持续此过程,直到所有的输入的字节全部计算完成。同时需要将每一个字节CRC计算的结果输出。以64bit位宽的输入为例,计算CRC-32.

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2024/04/28 15:49:12
  7. // Design Name:
  8. // Module Name: CRC32_64bKEEP
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. // 多位宽的CRC运算,也是按照字节进行的,下一个字节CRC运算值,是在上一个字节的CRC运算值的基础上进行的
  20. //
  21. module CRC32_64bKEEP(
  22. input i_clk ,
  23. input i_rst ,
  24. input [7:0] i_data ,
  25. input [7:0] i_data_1 ,
  26. input [7:0] i_data_2 ,
  27. input [7:0] i_data_3 ,
  28. input [7:0] i_data_4 ,
  29. input [7:0] i_data_5 ,
  30. input [7:0] i_data_6 ,
  31. input [7:0] i_data_7 ,
  32. input i_en ,
  33. output[31:0] o_crc ,
  34. output[31:0] o_crc_1 ,
  35. output[31:0] o_crc_2 ,
  36. output[31:0] o_crc_3 ,
  37. output[31:0] o_crc_4 ,
  38. output[31:0] o_crc_5 ,
  39. output[31:0] o_crc_6 ,
  40. output[31:0] o_crc_7
  41. );
  42. reg [31:0] crc ;
  43. wire [7:0] d[0:7] ;
  44. wire [31:0] c[0:7] ;
  45. wire [31:0] newcrc[0:7] ;
  46. reg [31:0] ro_crc[0:7] ;
  47. assign d[0] = {i_data[0],i_data[1],i_data[2],i_data[3],i_data[4],i_data[5],i_data[6],i_data[7]}; //需不需要反转需要查表
  48. assign d[1] = {i_data_1[0],i_data_1[1],i_data_1[2],i_data_1[3],i_data_1[4],i_data_1[5],i_data_1[6],i_data_1[7]};
  49. assign d[2] = {i_data_2[0],i_data_2[1],i_data_2[2],i_data_2[3],i_data_2[4],i_data_2[5],i_data_2[6],i_data_2[7]};
  50. assign d[3] = {i_data_3[0],i_data_3[1],i_data_3[2],i_data_3[3],i_data_3[4],i_data_3[5],i_data_3[6],i_data_3[7]};
  51. assign d[4] = {i_data_4[0],i_data_4[1],i_data_4[2],i_data_4[3],i_data_4[4],i_data_4[5],i_data_4[6],i_data_4[7]};
  52. assign d[5] = {i_data_5[0],i_data_5[1],i_data_5[2],i_data_5[3],i_data_5[4],i_data_5[5],i_data_5[6],i_data_5[7]};
  53. assign d[6] = {i_data_6[0],i_data_6[1],i_data_6[2],i_data_6[3],i_data_6[4],i_data_6[5],i_data_6[6],i_data_6[7]};
  54. assign d[7] = {i_data_7[0],i_data_7[1],i_data_7[2],i_data_7[3],i_data_7[4],i_data_7[5],i_data_7[6],i_data_7[7]};
  55. assign o_crc = ro_crc[0];
  56. assign o_crc_1 = ro_crc[1];
  57. assign o_crc_2 = ro_crc[2];
  58. assign o_crc_3 = ro_crc[3];
  59. assign o_crc_4 = ro_crc[4];
  60. assign o_crc_5 = ro_crc[5];
  61. assign o_crc_6 = ro_crc[6];
  62. assign o_crc_7 = ro_crc[7];
  63. assign c[0] = crc;//第一次运算c[0]=32'hFFFFFFFF,第二次运算c[0]=上一次运算的crc结果
  64. genvar i;
  65. generate for(i = 0; i < 8;i = i + 1)
  66. begin
  67. assign newcrc[i][0] = d[i][6] ^ d[i][0] ^ c[i][24] ^ c[i][30];
  68. assign newcrc[i][1] = d[i][7] ^ d[i][6] ^ d[i][1] ^ d[i][0] ^ c[i][24] ^ c[i][25] ^ c[i][30] ^ c[i][31];
  69. assign newcrc[i][2] = d[i][7] ^ d[i][6] ^ d[i][2] ^ d[i][1] ^ d[i][0] ^ c[i][24] ^ c[i][25] ^ c[i][26] ^ c[i][30] ^ c[i][31];
  70. assign newcrc[i][3] = d[i][7] ^ d[i][3] ^ d[i][2] ^ d[i][1] ^ c[i][25] ^ c[i][26] ^ c[i][27] ^ c[i][31];
  71. assign newcrc[i][4] = d[i][6] ^ d[i][4] ^ d[i][3] ^ d[i][2] ^ d[i][0] ^ c[i][24] ^ c[i][26] ^ c[i][27] ^ c[i][28] ^ c[i][30];
  72. assign newcrc[i][5] = d[i][7] ^ d[i][6] ^ d[i][5] ^ d[i][4] ^ d[i][3] ^ d[i][1] ^ d[i][0] ^ c[i][24] ^ c[i][25] ^ c[i][27] ^ c[i][28] ^ c[i][29] ^ c[i][30] ^ c[i][31];
  73. assign newcrc[i][6] = d[i][7] ^ d[i][6] ^ d[i][5] ^ d[i][4] ^ d[i][2] ^ d[i][1] ^ c[i][25] ^ c[i][26] ^ c[i][28] ^ c[i][29] ^ c[i][30] ^ c[i][31];
  74. assign newcrc[i][7] = d[i][7] ^ d[i][5] ^ d[i][3] ^ d[i][2] ^ d[i][0] ^ c[i][24] ^ c[i][26] ^ c[i][27] ^ c[i][29] ^ c[i][31];
  75. assign newcrc[i][8] = d[i][4] ^ d[i][3] ^ d[i][1] ^ d[i][0] ^ c[i][0] ^ c[i][24] ^ c[i][25] ^ c[i][27] ^ c[i][28];
  76. assign newcrc[i][9] = d[i][5] ^ d[i][4] ^ d[i][2] ^ d[i][1] ^ c[i][1] ^ c[i][25] ^ c[i][26] ^ c[i][28] ^ c[i][29];
  77. assign newcrc[i][10] = d[i][5] ^ d[i][3] ^ d[i][2] ^ d[i][0] ^ c[i][2] ^ c[i][24] ^ c[i][26] ^ c[i][27] ^ c[i][29];
  78. assign newcrc[i][11] = d[i][4] ^ d[i][3] ^ d[i][1] ^ d[i][0] ^ c[i][3] ^ c[i][24] ^ c[i][25] ^ c[i][27] ^ c[i][28];
  79. assign newcrc[i][12] = d[i][6] ^ d[i][5] ^ d[i][4] ^ d[i][2] ^ d[i][1] ^ d[i][0] ^ c[i][4] ^ c[i][24] ^ c[i][25] ^ c[i][26] ^ c[i][28] ^ c[i][29] ^ c[i][30];
  80. assign newcrc[i][13] = d[i][7] ^ d[i][6] ^ d[i][5] ^ d[i][3] ^ d[i][2] ^ d[i][1] ^ c[i][5] ^ c[i][25] ^ c[i][26] ^ c[i][27] ^ c[i][29] ^ c[i][30] ^ c[i][31];
  81. assign newcrc[i][14] = d[i][7] ^ d[i][6] ^ d[i][4] ^ d[i][3] ^ d[i][2] ^ c[i][6] ^ c[i][26] ^ c[i][27] ^ c[i][28] ^ c[i][30] ^ c[i][31];
  82. assign newcrc[i][15] = d[i][7] ^ d[i][5] ^ d[i][4] ^ d[i][3] ^ c[i][7] ^ c[i][27] ^ c[i][28] ^ c[i][29] ^ c[i][31];
  83. assign newcrc[i][16] = d[i][5] ^ d[i][4] ^ d[i][0] ^ c[i][8] ^ c[i][24] ^ c[i][28] ^ c[i][29];
  84. assign newcrc[i][17] = d[i][6] ^ d[i][5] ^ d[i][1] ^ c[i][9] ^ c[i][25] ^ c[i][29] ^ c[i][30];
  85. assign newcrc[i][18] = d[i][7] ^ d[i][6] ^ d[i][2] ^ c[i][10] ^ c[i][26] ^ c[i][30] ^ c[i][31];
  86. assign newcrc[i][19] = d[i][7] ^ d[i][3] ^ c[i][11] ^ c[i][27] ^ c[i][31];
  87. assign newcrc[i][20] = d[i][4] ^ c[i][12] ^ c[i][28];
  88. assign newcrc[i][21] = d[i][5] ^ c[i][13] ^ c[i][29];
  89. assign newcrc[i][22] = d[i][0] ^ c[i][14] ^ c[i][24];
  90. assign newcrc[i][23] = d[i][6] ^ d[i][1] ^ d[i][0] ^ c[i][15] ^ c[i][24] ^ c[i][25] ^ c[i][30];
  91. assign newcrc[i][24] = d[i][7] ^ d[i][2] ^ d[i][1] ^ c[i][16] ^ c[i][25] ^ c[i][26] ^ c[i][31];
  92. assign newcrc[i][25] = d[i][3] ^ d[i][2] ^ c[i][17] ^ c[i][26] ^ c[i][27];
  93. assign newcrc[i][26] = d[i][6] ^ d[i][4] ^ d[i][3] ^ d[i][0] ^ c[i][18] ^ c[i][24] ^ c[i][27] ^ c[i][28] ^ c[i][30];
  94. assign newcrc[i][27] = d[i][7] ^ d[i][5] ^ d[i][4] ^ d[i][1] ^ c[i][19] ^ c[i][25] ^ c[i][28] ^ c[i][29] ^ c[i][31];
  95. assign newcrc[i][28] = d[i][6] ^ d[i][5] ^ d[i][2] ^ c[i][20] ^ c[i][26] ^ c[i][29] ^ c[i][30];
  96. assign newcrc[i][29] = d[i][7] ^ d[i][6] ^ d[i][3] ^ c[i][21] ^ c[i][27] ^ c[i][30] ^ c[i][31];
  97. assign newcrc[i][30] = d[i][7] ^ d[i][4] ^ c[i][22] ^ c[i][28] ^ c[i][31];
  98. assign newcrc[i][31] = d[i][5] ^ c[i][23] ^ c[i][29];
  99. if(i > 0)begin
  100. assign c[i] = newcrc[i - 1];
  101. end
  102. end
  103. endgenerate
  104. //8字节的数据输入,每一个字节都会产生一个CRC的运算结果,将每一次计算的数据输入都输出出来
  105. genvar j;
  106. generate for(j = 0;j < 8;j = j + 1)
  107. begin
  108. always@(posedge i_clk,posedge i_rst)begin
  109. if(i_rst)
  110. ro_crc[j] <= 'd0;
  111. else if(!i_en)
  112. ro_crc[j] <= 'd0;
  113. else
  114. ro_crc[j] <= ~{ newcrc[j][0],newcrc[j][1],newcrc[j][2],newcrc[j][3],newcrc[j][4],newcrc[j][5],newcrc[j][6],newcrc[j][7],newcrc[j][8],newcrc[j][9],
  115. newcrc[j][10],newcrc[j][11],newcrc[j][12],newcrc[j][13],newcrc[j][14],newcrc[j][15],newcrc[j][16],newcrc[j][17],newcrc[j][18],newcrc[j][19],
  116. newcrc[j][20],newcrc[j][21],newcrc[j][22],newcrc[j][23],newcrc[j][24],newcrc[j][25],newcrc[j][26],newcrc[j][27],newcrc[j][28],newcrc[j][29],
  117. newcrc[j][30],newcrc[j][31]};
  118. end
  119. end
  120. endgenerate
  121. always@(posedge i_clk,posedge i_rst)begin
  122. if(i_rst || !i_en)
  123. crc <= 32'hFFFFFFFF;
  124. else if(i_en)
  125. crc <= newcrc[7];
  126. else
  127. crc <= crc;
  128. end
  129. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/523279
推荐阅读
相关标签
  

闽ICP备14008679号