当前位置:   article > 正文

CRC循环冗余校验 (Cyclic Redundancy Check) 原理/电路实现/Verilog实现

crc循环冗余校验

目录

1 什么是CRC循环冗余校验?

2 CRC校验的原理

2.1 多项式表示

2.2 模二

多项式除法

2.3 传输端

 2.4 接收端

3 CRC码的产生

3.1 产生CRC码步骤

3.2 Verilog实现

4 电路实现原理—线性反馈移位寄存器

4.1 循环移位寄存器结构

4.2 最大长度移位寄存器

 4.3 多项式除法电路(线性反馈移位寄存器)

4.4 Verilog实现


1 什么是CRC循环冗余校验?

循环冗余校验(英语:Cyclic redundancy check,通称“CRC”)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。CRC有以下特性:

  • 多项式表示:把所有二进制位字符串视为变量 (x) 的多项式方程;
  • 多项式除法:使用“多项式除法” (模2算术运算) 进行校验;
  • 在检测单bit和多bit错误时极其可靠;
  • 可以简单地通过反馈移位寄存器和XOR门高效地实现。

2 CRC校验的原理

2.1 多项式表示

对如下二进制bit字符串:

可以将其表示为一个虚拟变量 (x) 的多项式方程 (二进制加权形式):

 例:字符串 (1100101) 可以表示为:

 这样做的目的是,方便之后进行数学编码和对二进制数据串的操作 (如:模二运算)。

2.2 模二多项式除法

通常一个多项式B(x)除以另一个多项式G(x)会产生一个商多项式Q(x)和一个余数多项式R(x):

 由于 模二减法=模二加法,上式可重写为:

B(x)+R(x)=Q(x)\cdot G(x)

这表明可以可以通过添加一个特定的二进制组合R(x)到原原数据串,来产生一个刚好能被多项式G(x)整除的新的多项式。

2.3 传输端

T(x)=B(x)+R(x)=Q(x)\cdot G(x)

 2.4 接收端

\frac{T'(x)}{G(x)}=Q(x)+R'(x)

where T'(x) = T(x) + E(x) and R'(x) = \frac{E(x)}{G(x)}

T'(x) 是接收端的接收到的二进制bit串对应的多项式,E(x) 是错误的二进制bit构成的多项式。

如果余数多项式R'(x)=0, 则表明接收到的数据没有错误。否则,在传输过程中存在单bit或多bit的错误,需要重新传输。G(x)为选定的能够检测出几乎所有单bit和多bit错(突发错误)误的生成多项式。

3 CRC码的产生

3.1 产生CRC码步骤

第一步:对r次的生成多项式G(x)=g_{r}x^{r}+g_{r-1}x^{r-1}+...+g_{1}x+g_{0},在原二进制bit串后方增加r个“0”,形成新的数据多项式B'(x):

 第二步:用B'(x)除以生成多项式G(x),得到余数多项式R'(x):

 第三步:传输T(x)=B'(x)+R'(x)。此时,T(x) 等于 Q'(x)·R'(x) 且正好能被G(x)整除。

3.2 Verilog实现

  1. module CRC_Gen(
  2. input clk,
  3. input rst_n,
  4. input [7:0] data,
  5. input data_valid,
  6. output reg [15:0] crc
  7. );
  8. reg [23:0] temp;
  9. parameter polynomial=17'b1_0001_0000_0010_0001;
  10. always@(posedge clk or negedge rst_n)
  11. begin
  12. if(~rst_n)
  13. begin
  14. crc <= 0;
  15. temp <= {data,16'd0}; //复位时,将初始数据放入寄存器
  16. end
  17. else if(data_valid)
  18. begin
  19. if(temp[23]) temp[23:7] <= temp[23:7]^polynomial;
  20. else if(temp[22]) temp[22:6] <= temp[22:6]^polynomial;
  21. else if(temp[21]) temp[21:5] <= temp[21:5]^polynomial;
  22. else if(temp[20]) temp[20:4] <= temp[20:4]^polynomial;
  23. else if(temp[19]) temp[19:3] <= temp[19:3]^polynomial;
  24. else if(temp[18]) temp[18:2] <= temp[18:2]^polynomial;
  25. else if(temp[17]) temp[17:1] <= temp[17:1]^polynomial;
  26. else if(temp[16]) temp[16:0] <= temp[16:0]^polynomial;
  27. else crc <= temp[15:0];
  28. end
  29. end
  30. endmodule

4 电路实现原理—线性反馈移位寄存器

4.1 循环移位寄存器结构

数据通寄存器循环,输出被反馈到输入。例:一个下图所示的4-bit移位寄存器初始载入0001,则可以得到四种不同的bit pattern,但这并不是所有可能的4-bit pattern(2_{}^{n}种)。

4.2 最大长度移位寄存器

当XOR门(执行模二和运算)被加在反馈路径上时,可能得到的bit patterns的数量增加了。

最大长度移位寄存器定义为:一个在不同时钟下能产生(2_{}^{n}-1)种bit patterns 的 n-bit 反馈移位寄存器。

最大长度寄存器对任意输入序列都拥有除法器的作用。其他任何不能产生最大序列的电路都不能执行除法操作。

例:如下图所示的最大序列产生器是一个含有XOR门的3-bit移位寄存器,假设起始值为001。

例:如上图所示(由移位寄存器和XOR门构成的除法器电路)(该电路表示的G(x)=x^{3}+x^{2}+1):使用最大序列移位寄存器结构,假设寄存器中初始值均为0并且有一个四位的输入(1110 MSB先入)。在四次移位后,留在寄存器R3 R2 R1中的bit pattern就是余数,可以看到在周期4,我们得到余数R(x) = 011(R3 R2 R1)。

验证得到的余数是否准确:

 4.3 多项式除法电路(线性反馈移位寄存器)

V(x)=v_{n-1}x^{n-1}+v_{n-2}x^{n-2}+...+v_{1}x+v_{0}

 G(x)=g_{r}x^{r}+g_{r-1}x^{r-1}+...+g_{1}x+g_{0}

用下图电路执行\frac{V(x)}{G(x)}=Q(x)+\frac{R(x)}{G(x)}

 可以看出,对一个n次多项式,最多使用n-1个移位寄存器和最多n-2个异或门可以构成一个线性移位寄存器。线性移位寄存器可以实现模二除法。

 重新编排多项式后的编码电路如下,由于当移位开始时,输入可以直接在输出得到,这节省了k个Cycle的时间:

  •  在开始的k次移位,开关打开 (选择下端)。k位信号bits同时移入寄存器和移到输出。
  • 在之后的n-k次移位,开关关闭 (选择上端)。剩下的寄存器中的 (n-k)位check bit移动到输出。

4.4 Verilog实现

  1. // CRC = x16+x12+x5+1
  2. module CRC_GenSerial(
  3. input clk,
  4. input rst_n,
  5. output reg [15:0] crc
  6. );
  7. reg [31:0] data_parallel;
  8. reg data_serial;
  9. reg [5:0] cnt;
  10. parameter source_data = 32'h96E32077;
  11. always@(posedge clk or negedge rst_n)
  12. begin
  13. if(~rst_n)
  14. begin
  15. cnt <= 0;
  16. data_parallel <= source_data;
  17. data_serial <= 0;
  18. end
  19. else if(cnt < 32)
  20. begin
  21. cnt <= cnt+1;
  22. data_serial <= data_parallel[31];
  23. data_parallel <= data_parallel<<1;
  24. end
  25. else
  26. begin
  27. cnt <= 33;
  28. data_serial <= 0;
  29. data_parallel <= 0;
  30. end
  31. end
  32. always@(posedge clk or negedge rst_n)
  33. begin
  34. if(~rst_n)
  35. begin
  36. crc <= 0;
  37. end
  38. else if(cnt <= 32)
  39. begin
  40. crc[0] <= crc[15]^data_serial;
  41. crc[4:1] <= crc[3:0];
  42. crc[5] <= crc[4]^crc[15]^data_serial;
  43. crc[11:6] <= crc[10:5];
  44. crc[12] <= crc[11]^crc[15]^data_serial;
  45. crc[15:13] <= crc[14:12];
  46. end
  47. else
  48. begin
  49. crc <= crc;
  50. end
  51. end
  52. endmodule

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

闽ICP备14008679号