来源于kb129的博客,版权归原作者所有:
本来是不想写的,是因为自己还没有彻底搞懂唯一的一个环节:软件实现和理论怎么对应。对于我这种黑白是非必须分明的人而言,这是一种折磨。而这周类似的,悬而未决的事情远不止这一件。这些导致这周过得很不爽快,但是我很清楚的明白我必须去面对,去接受,去改变,就像昨晚的欧冠,这么虐心的过程,说不定在最后迎来意想不到的大胜利。
循环冗余校验,也称为CRC检验,这是一个很常见的,很成熟的算法。该算法的理解很简单,随便用百度百科一搜,然后花半个小时估计就能完全理解了。这篇博文描述:怎么实现硬件并行的CRC计算。主要的参数为:
1.生成多项式,在不同的协议中有不同的生成多项式,一般这些多项式都是确定的。
![](http://c.51hei.com/a/old/up/0/468116774727.jpg)
2.模2除法
如果已经了解CRC算法,就明白它的原理就是将数据和多项式进行模2除,最后得到的余数就是最后的CRC。这里需要记住的就是:模2除就是进行异或。
但是,如果上面的你都了解后,你会发现这些对于解决CRC算法完全没有作用,这就是坑爹的百科。网络上大部分的CRC都是软件实现,其实在解压软件中就有CRC,但是此时又会出现一个问题,你会发现下载的软件对于同一个字符串,CRC算出来的结果会不同。
这里给一个表示正确的CRC计算软件:http://www.pc6.com/softview/SoftView_100981.html
软件界面:
![](http://c.51hei.com/a/old/up/0/468117797880.jpg)
软件说明 :(作为一个搞硬件的,理解这些软件参数的确不是一个容易的活,搜了很多资料)
width : 表示最后CRC的bit的位数
Poly : 表示多项式对应的二进制数,这里没有进行颠倒,x4+x+1=10011,最高位省略,对应的就是0x03,如果颠倒就是0x1100。init :表示软件寄存器初值,上图为0x00.
refin : 如果此值为true,表示输入的数据需要进行比特翻转,也就是Bit7要变成最低位, Bit0要变成最高位,这里是每个字节而言,每个字节之间的关系不需要进行颠倒。如果此值为false,表明不需要进行字节的比特翻转
refout:如果此值为true,这表示进行异或后算出来的CRC需要进行整个比特翻转,然后存入寄存器,例如:123456789 (实际中只能为0,1,为了方便解释这里的 翻转和refin的区别,此处6,7,8,9等都是一位),转换后就是:987654321.如果此值为false,例如:123456789,则该一步后的输出为123456789
XorOut:最个是将异或后的数据,在refout后的得到的数据与该值进行异或后,最终结果才是软件计算的CRC。
对于软件的详细解释有:
http://www.cnblogs.com/poiu-elab/archive/2012/10/22/2734715.html
好了,下面是硬件实现。有很多论文都对CRC进行描述,但是其实都是没有实际作用,但是有一个网站在这一方面做的特别好。链接:
http://www.easics.com/webtools/crctool
![](http://c.51hei.com/a/old/up/0/4681112733759.jpg)
通过该网站,你会等到一个硬件代码,但是,你会发现这个硬件代码其实并没有用。因为代码仅仅是一个function,并不能直接使用,例如我生成的是CRC32,配置如下:
![](http://c.51hei.com/a/old/up/0/4681114721565.jpg)
得到的verilog代码为:
![](http://c.51hei.com/a/old/up/0/4681114749378.jpg)
此时就需要修改硬件代码:
1.首先将代码从function转变为时序逻辑电路,也就是添加clk,rst,en。
这一部分由于是教研室代码,所以不能公布,修改还是很简单的,只需要花点时间。
2.修改输入和输出,这个得根据软件的配置:
![](http://c.51hei.com/a/old/up/0/4681115760568.jpg)
此处的refin,refout,XorOut分别为:true,true,0xFFFFFFFF,也就是输入需要进行比特翻转,输出需要整体比特翻转,最后需要和0xFFFFFFFF异或,也就是取反(0^1=1 , 1^1=0).
此处修改代码:输入比特翻转
![](http://c.51hei.com/a/old/up/0/4681116716521.jpg)
输出整体翻转和取反
![](http://c.51hei.com/a/old/up/0/4681121753697.jpg)
仿真的结果为:
![](http://c.51hei.com/a/old/up/0/4681121723142.jpg)
分析:
可以从仿真图中看到:如果输入的是01050005,进行CRC32后的结果为:ef598e1d.对比软件算出来的结果(上图的上图的上图的上图):EF598E1D。可见两者算出来的结果是一样的。
最后给出我还没有理解的问题:为何上面的计算结果和我们自己用笔在纸上计算的CRC不一样呢?
描述:
情况一:当refin 和refout都为true
![](http://c.51hei.com/a/old/up/0/4681122766591.jpg)
而此手算结果为:
![](http://c.51hei.com/a/old/up/0/4681123790028.jpg)
此时的计算值和软件算出来的值,不一样,就是不清楚软件那边是怎么个翻转
情况二:当refin 和refout都为false
![](http://c.51hei.com/a/old/up/0/4681124785655.jpg)
手算的结果:
![](http://c.51hei.com/a/old/up/0/4681124787832.jpg)
对比发现,手算和软件计算是一样的,所以总结出来问题:
就是在需要bit翻转和整体翻转的时候,软件计算算出来的CRC是什么字符串的CRC呢?
PS : 在无意浏览网页的时候,发现了一个更好的硬件CRC生成网站,但是我没有对代码进行测试。链接为:http://outputlogic.com/?page_id=321