并行CRC计算方法

数据帧CRC32校验算法实现

  本文设计思想采用明德扬至简设计法。由于本人项目需要进行光纤数据传输,为了保证通信质量要对数据进行校验。在校验算法中,最简单最成熟的非CRC校验莫属了。

  得出一个数的CRC校验码还是比较简单的:

  1. 选定一个CRC生成多项式G(x);
  2. 将发送数据左移K位,右侧补零(其中K为生成多项式最高次幂);
  3. 用移位补零后的数据对G(x)进行模2除法(其实就是异或运算);
  4. 用得到的余数即为该数据的CRC校验码;

  发送端将移位补零后数据的低K位0替换成CRC校验码组成新的数据发送出去,接收端对带有校验码的数据对同样的G(x)做模2除法。由于发送端将余数加入在数据尾部,相当于已做了“去余”处理,故若数据传输正确时,接收端的模2除运算余数应为0。其中校验位数和生成多项式不是随便选定的,一般采用常用的标准形式。其中CRCK是指有K为校验位,不同位数对应不同的纠检错能力。之前本人在网上找到一篇关于CRC校验原理的文章,比较详细且浅显易懂:http://mp.weixin.qq.com/s/RNHLZGPD9Ysbxb1FNDn6EA

  当刚看完这些资料,对CRC有了大概认识之后,我和很多初学的朋友们一样充满疑惑。CRC如何用硬件实现呢?如何对包含多个数据的数据帧进行校验呢?FCS又是如何在帧尾的下一个时钟周期就得到结果的呢?

  最原始的实现方式是采用LFSR(线性反馈移位寄存器)来完成校验功能,以下是结构示意图:

  寄存器个数等于G(x)最高次幂,图中gx表示链路通断,与多项式系数相对应:系数为1时连接,0则断开。数据在每个时钟周期从右侧输入1bit,且寄存器内数据右移一位。如此移位,反馈异或的过程即为待发送数据移位后对生成多项式做模2除的过程,故当全部数据位输入完毕,寄存器内部的值即为CRC校验码。我们以较简单的CRC8为例,其G(x) = x^8 + x^2 + x^1 + 1,根据上述分析得到:

              reg2(i) = reg1(i-1)^reg7(i-1)^d(i)

              reg1(i) = reg0(i-1)^reg7(i-1)^d(i)

              reg0(i) = reg7(i-1)^d(i)

              regk(i) = regk-1(i-1)       (k!=0,1,2)

  其中,i表示当前时刻,i-1表示上一时刻。数据位宽定为4bit,经过四个节拍,寄存器内部数据变化过程见表:

  根据上述传递方程推导得出四个节拍后reg7~reg0保存的数值,试想一下:既然每个触发器内保存数值表达式已知,那么如果直接将第四行表达式赋值寄存器,下一个时钟节拍即可得到最终校验结果,而无需等待四个时钟节拍。这就是CRC校验的并行实现方式了!传统的CRC校验算法已经非常成熟,在使用过程中不需要完全自己推导公式,了解基本原理即可。至于代码,有做好的线上生成工具  Easics CRC Tool    OutputLogic.com » CRC Generator  CRC(循环冗余校验)在线计算_ip33.com(在线计算)我们选定CRC8,并将数据位宽定义为4bit,验证上述推导过程是否正确


// Purpose : synthesizable CRC function
//   * polynomial: x^8 + x^2 + x^1 + 1
//   * data width: 4

module CRC8_D4;

  // polynomial: x^8 + x^2 + x^1 + 1
  // data width: 4
  // convention: the first serial bit is D[3]
  function [7:0] nextCRC8_D4;

    input [3:0] Data;
    input [7:0] crc;
    reg [3:0] d;
    reg [7:0] c;
    reg [7:0] newcrc;
  begin
    d = Data;
    c = crc;

    newcrc[0] = d[0] ^ c[4];
    newcrc[1] = d[1] ^ d[0] ^ c[4] ^ c[5];
    newcrc[2] = d[2] ^ d[1] ^ d[0] ^ c[4] ^ c[5] ^ c[6];
    newcrc[3] = d[3] ^ d[2] ^ d[1] ^ c[5] ^ c[6] ^ c[7];
    newcrc[4] = d[3] ^ d[2] ^ c[0] ^ c[6] ^ c[7];
    newcrc[5] = d[3] ^ c[1] ^ c[7];
    newcrc[6] = c[2];
    newcrc[7] = c[3];
    nextCRC8_D4 = newcrc;
  end
  endfunction
endmodule

  • 7
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值