当前位置:   article > 正文

CRC(循环冗余校验)的verilog实现

CRC(循环冗余校验)的verilog实现

算法简介:

一种信道编码技术,用来检测数据传输或者保存后可能出现的错误,其使用模2除法进行校验,计算速度快,检错能力强,有不同的标准参数模型,标准越高则检错能力和精度越好。

算法实现:

(以CRC-5为例(初值00)):其生成多项式为X5+X3+1 输入输出无需翻转。设数据串为100101

  1. 根据生成多项式不同幂次的系数得到其二进制为:101001(除数),由于首位和末尾必为1,所以省略首位为01001 = 0x099 (POLY)
  2. 给数据串后补上省略首位后的系数位数的0,得到新数据串100101 00000(被除数).
  3. 将新数据串和除数进行模2除法运算,得到5位余数即CRC校验码10111.
  4. 将得到的余数拼接在数据串末尾,得到新数据串,
  5. 用该数据串模2除以除数,若无余数,说明无误码。

实现电路:

根据多项式画出标准电路

列出表达式:

D0 <= data_in ^ D4 ;

D1 <= D0 ;

D2 <= D1 ;

D3 <= data_in ^ D4 ^D2 ;

D4 <= D3 ;

 Data-in

D0

D1

D2

D3

D4

0

0

0

0

0

0

1

1

0

0

1

0

0

0

1

0

0

1

0

1

0

1

1

0

1

1

1

0

0

1

0

1

1

1

1

0

1

1

1

1

0

1

当6个时钟周期结束后,D4-D0的值即是CRC校验码10111

verilog实现:(.V文件)

  1. module crc (
  2. input [5:0] data_in , //输入待检测数据
  3. output [4:0] crc_data , //CRC校验码输出
  4. input rst ,
  5. input clk ,
  6. output wire [4:0] result , // 最后用来检验的余数
  7. output wire [10:0] string_data // 定义输出的CRC数据串
  8. ) ;
  9. reg [4:0] reminder_1 , reminder_2 , //两组中间变量, 用来储存电路现态和次态的值
  10. mod1 , mod2 ;
  11. wire [5:0] data ;
  12. integer i =0 ;
  13. integer j = 0;
  14. assign string_data = {crc_data[0],crc_data[1],crc_data[2],crc_data[3],crc_data[4],data_in[0],data_in[1],data_in[2],data_in[3],data_in[4],data_in[5]} ; //将输入数据和CRC校验码拼接
  15. assign data = {data_in[0],data_in[1],data_in[2],data_in[3],data_in[4],data_in[5]} ; //储存输入数据100101
  16. assign crc_data= {reminder_2[4],reminder_2[3],reminder_2[2],reminder_2[1],reminder_2[0]} ; //将中间变量数据传入CRC值
  17. assign result = {mod2[4],mod2[3],mod2[2],mod2[1],mod2[0]} ; //余数
  18. always @ (*) begin
  19. reminder_1[0] <= data [i] ^ reminder_2 [4] ; //根据电路图写出关系式
  20. reminder_1[1] <= reminder_2 [0] ; //D0 <= data_in ^ D4
  21. reminder_1[2] <= reminder_2 [1] ; //D1 <= D0
  22. reminder_1[3] <= data [i] ^ reminder_2 [4] ^ reminder_2 [2] ; //D2 <= D1
  23. reminder_1[4] <= reminder_2 [3] ; //D3 <= data_in ^ D4 ^D2
  24. //D4 <= D3
  25. mod1[0] <= string_data [j] ^ mod2 [4] ;
  26. mod1[1] <= mod2 [0] ;
  27. mod1[2] <= mod2 [1] ;
  28. mod1[3] <= string_data [j] ^ mod2 [4] ^ mod2 [2] ;
  29. mod1[4] <= mod2 [3] ;
  30. end
  31. always @ (posedge clk or posedge rst ) begin
  32. if(rst) begin
  33. reminder_2 <= {5{1'b0}} ; //复位使电路状态清0
  34. mod2 <= {5{1'b0}};
  35. end
  36. else if (i <= 5 && j<=10)begin
  37. mod2 <= mod1 ;
  38. reminder_2 <= reminder_1 ; // i递增,控制data_in的顺序进入 (LSB)
  39. i = i +1 ; // j递增,控制string_data的顺序进入 (LSB)
  40. j = j + 1;
  41. end
  42. else if (i > 5 && j>10)begin
  43. mod2 <= mod2 ;
  44. reminder_2 <=reminder_2 ;
  45. end
  46. else begin
  47. reminder_2 <=reminder_2 ;
  48. mod2 <= mod1 ;
  49. j = j+1 ;
  50. end
  51. end
  52. endmodule

 (测试文件)

  1. `timescale 1 ps/ 1 ps
  2. module crc_vlg_tst();
  3. reg clk;
  4. reg [5:0] data_in;
  5. reg rst;
  6. wire [4:0] crc_data;
  7. wire [4:0] result ;
  8. wire [10:0] string_data ;
  9. crc i1 (
  10. .clk(clk),
  11. .crc_data(crc_data),
  12. .data_in(data_in),
  13. .rst(rst) ,
  14. .string_data(string_data) ,
  15. .result(result)
  16. );
  17. always #10 clk = ~clk ;
  18. initial
  19. begin
  20. clk = 0;
  21. rst = 1 ;
  22. data_in <= 6'b100101 ;
  23. #20
  24. rst = 0 ;
  25. $display("Running testbench");
  26. end
  27. endmodule

波形验证:

 

可以看到对于拼接CRC校验码后的数据串,通过电路,最后留下的余数为00000,证明数据无误,且通过在线计算得到CRC校验码无误。

刚开始研究,代码较为繁琐,如有错误,欢迎大神沟通指正! 

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

闽ICP备14008679号