來(lái)源于kb129的博客,版權(quán)歸原作者所有:
本來(lái)是不想寫(xiě)的,是因?yàn)樽约哼€沒(méi)有徹底搞懂唯一的一個(gè)環(huán)節(jié):軟件實(shí)現(xiàn)和理論怎么對(duì)應(yīng)。對(duì)于我這種黑白是非必須分明的人而言,這是一種折磨。而這周類(lèi)似的,懸而未決的事情遠(yuǎn)不止這一件。這些導(dǎo)致這周過(guò)得很不爽快,但是我很清楚的明白我必須去面對(duì),去接受,去改變,就像昨晚的歐冠,這么虐心的過(guò)程,說(shuō)不定在最后迎來(lái)意想不到的大勝利。
循環(huán)冗余校驗(yàn),也稱(chēng)為CRC檢驗(yàn),這是一個(gè)很常見(jiàn)的,很成熟的算法。該算法的理解很簡(jiǎn)單,隨便用百度百科一搜,然后花半個(gè)小時(shí)估計(jì)就能完全理解了。這篇博文描述:怎么實(shí)現(xiàn)硬件并行的CRC計(jì)算。主要的參數(shù)為:
1.生成多項(xiàng)式,在不同的協(xié)議中有不同的生成多項(xiàng)式,一般這些多項(xiàng)式都是確定的。

2.模2除法
如果已經(jīng)了解CRC算法,就明白它的原理就是將數(shù)據(jù)和多項(xiàng)式進(jìn)行模2除,最后得到的余數(shù)就是最后的CRC。這里需要記住的就是:模2除就是進(jìn)行異或。
但是,如果上面的你都了解后,你會(huì)發(fā)現(xiàn)這些對(duì)于解決CRC算法完全沒(méi)有作用,這就是坑爹的百科。網(wǎng)絡(luò)上大部分的CRC都是軟件實(shí)現(xiàn),其實(shí)在解壓軟件中就有CRC,但是此時(shí)又會(huì)出現(xiàn)一個(gè)問(wèn)題,你會(huì)發(fā)現(xiàn)下載的軟件對(duì)于同一個(gè)字符串,CRC算出來(lái)的結(jié)果會(huì)不同。
這里給一個(gè)表示正確的CRC計(jì)算軟件:http://www.pc6.com/softview/SoftView_100981.html
軟件界面:

軟件說(shuō)明 :(作為一個(gè)搞硬件的,理解這些軟件參數(shù)的確不是一個(gè)容易的活,搜了很多資料)
width : 表示最后CRC的bit的位數(shù)
Poly : 表示多項(xiàng)式對(duì)應(yīng)的二進(jìn)制數(shù),這里沒(méi)有進(jìn)行顛倒,x4+x+1=10011,最高位省略,對(duì)應(yīng)的就是0x03,如果顛倒就是0x1100。init :表示軟件寄存器初值,上圖為0x00.
refin : 如果此值為true,表示輸入的數(shù)據(jù)需要進(jìn)行比特翻轉(zhuǎn),也就是Bit7要變成最低位, Bit0要變成最高位,這里是每個(gè)字節(jié)而言,每個(gè)字節(jié)之間的關(guān)系不需要進(jìn)行顛倒。如果此值為false,表明不需要進(jìn)行字節(jié)的比特翻轉(zhuǎn)
refout:如果此值為true,這表示進(jìn)行異或后算出來(lái)的CRC需要進(jìn)行整個(gè)比特翻轉(zhuǎn),然后存入寄存器,例如:123456789 (實(shí)際中只能為0,1,為了方便解釋這里的 翻轉(zhuǎn)和refin的區(qū)別,此處6,7,8,9等都是一位),轉(zhuǎn)換后就是:987654321.如果此值為false,例如:123456789,則該一步后的輸出為123456789
XorOut:最個(gè)是將異或后的數(shù)據(jù),在refout后的得到的數(shù)據(jù)與該值進(jìn)行異或后,最終結(jié)果才是軟件計(jì)算的CRC。
對(duì)于軟件的詳細(xì)解釋有:
http://www.cnblogs.com/poiu-elab/archive/2012/10/22/2734715.html
好了,下面是硬件實(shí)現(xiàn)。有很多論文都對(duì)CRC進(jìn)行描述,但是其實(shí)都是沒(méi)有實(shí)際作用,但是有一個(gè)網(wǎng)站在這一方面做的特別好。鏈接:
http://www.easics.com/webtools/crctool

通過(guò)該網(wǎng)站,你會(huì)等到一個(gè)硬件代碼,但是,你會(huì)發(fā)現(xiàn)這個(gè)硬件代碼其實(shí)并沒(méi)有用。因?yàn)榇a僅僅是一個(gè)function,并不能直接使用,例如我生成的是CRC32,配置如下:

得到的verilog代碼為:

此時(shí)就需要修改硬件代碼:
1.首先將代碼從function轉(zhuǎn)變?yōu)闀r(shí)序邏輯電路,也就是添加clk,rst,en。
這一部分由于是教研室代碼,所以不能公布,修改還是很簡(jiǎn)單的,只需要花點(diǎn)時(shí)間。
2.修改輸入和輸出,這個(gè)得根據(jù)軟件的配置:

此處的refin,refout,XorOut分別為:true,true,0xFFFFFFFF,也就是輸入需要進(jìn)行比特翻轉(zhuǎn),輸出需要整體比特翻轉(zhuǎn),最后需要和0xFFFFFFFF異或,也就是取反(0^1=1 , 1^1=0).
此處修改代碼:輸入比特翻轉(zhuǎn)

輸出整體翻轉(zhuǎn)和取反

仿真的結(jié)果為:

分析:
可以從仿真圖中看到:如果輸入的是01050005,進(jìn)行CRC32后的結(jié)果為:ef598e1d.對(duì)比軟件算出來(lái)的結(jié)果(上圖的上圖的上圖的上圖):EF598E1D�?梢�(jiàn)兩者算出來(lái)的結(jié)果是一樣的。
最后給出我還沒(méi)有理解的問(wèn)題:為何上面的計(jì)算結(jié)果和我們自己用筆在紙上計(jì)算的CRC不一樣呢?
描述:
情況一:當(dāng)refin 和refout都為true

而此手算結(jié)果為:

此時(shí)的計(jì)算值和軟件算出來(lái)的值,不一樣,就是不清楚軟件那邊是怎么個(gè)翻轉(zhuǎn)
情況二:當(dāng)refin 和refout都為false

手算的結(jié)果:

對(duì)比發(fā)現(xiàn),手算和軟件計(jì)算是一樣的,所以總結(jié)出來(lái)問(wèn)題:
就是在需要bit翻轉(zhuǎn)和整體翻轉(zhuǎn)的時(shí)候,軟件計(jì)算算出來(lái)的CRC是什么字符串的CRC呢?
PS : 在無(wú)意瀏覽網(wǎng)頁(yè)的時(shí)候,發(fā)現(xiàn)了一個(gè)更好的硬件CRC生成網(wǎng)站,但是我沒(méi)有對(duì)代碼進(jìn)行測(cè)試。鏈接為:http://outputlogic.com/?page_id=321