循環冗余校驗(Cyclic Redundancy Check, CRC)是一種根據網絡數據包或計算機文件等數據產生簡短固定位數校驗碼的一種信道編碼技術,主要用來檢測或校驗數據傳輸或者保存后可能出現的錯誤。
CRC算法參數模型解釋:
NAME:校驗算法模型名稱。
WIDTH:CRC校驗寬度,即CRC比特數。
POLY:生成項的簡寫,以16進制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生成項是0x104C11DB7。
INIT:算法開始時計算(crc)的初始化預置值,十六進制表示。
REFIN:要校驗的數據,每個字節是否按位反轉,True或False。
REFOUT:在計算后之后,異或輸出之前,整個數據是否按位反轉,True或False。
XOROUT:計算結果,與此參數異或后,得到輸出最終的CRC值。
常見CRC算法模型如下:
多項式的次方位不為0,則該位值為1,如:多項式CRC8 (0x31): x^8 + x^5 + x^4 + 1 即 1_0011_0001 則為8位數據的第0位、第4位、第5位需進行異或校驗。
CRC校驗碼生成步驟如下:
- 選定一個CRC生成多項式G(x);
- 將發送數據左移K位,右側補零(其中K為生成多項式最高次冪);
- 用移位補零后的數據對G(x)進行模2除法(其實就是異或運算);
- 用得到的余數即為該數據的CRC校驗碼;
發送端將移位補零后數據的低K位0替換成CRC校驗碼組成新的數據發送出去,接收端對帶有校驗碼的數據對同樣的G(x)做模2除法。由於發送端將余數加入在數據尾部,相當於已做了“去余”處理,故若數據傳輸正確時,接收端的模2除運算余數應為0。其中校驗位數和生成多項式不是隨便選定的,一般采用常用的標准形式。其中CRCK是指有K為校驗位,不同位數對應不同的糾檢錯能力。之前本人在網上找到一篇關於CRC校驗原理的文章,比較詳細且淺顯易懂:http://mp.weixin.qq.com/s/RNHLZGPD9Ysbxb1FNDn6EA
最原始的實現方式是采用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,經過四個節拍,寄存器內部數據變化過程見表:
注:CRC8理論上進行8輪移位(左移)操作,每輪左移后的要校驗的位(本CRC8多項式對應:第0位、第1位、第2位)的數據與上一輪最高位(Reg7)進行異或^操作(上圖中省略了^符號);
因為數據位寬是4位,相當於高四位補零,不需要校驗只進行左移,並且與0異或也不變,所以只需對4位數據位進行校驗。上圖中C1~C7為原寄存器初始值(一般在復位后值為0,即省去和C的異或),D為要校驗的數據。一個8位數據CRC8校驗筆試題:https://www.cnblogs.com/yiquwange/p/14621042.html
根據上述傳遞方程推導得出四個節拍后reg7~reg0保存的數值,試想一下:既然每個觸發器內保存數值表達式已知,那么如果直接將第四行表達式賦值寄存器,下一個時鍾節拍即可得到最終校驗結果,而無需等待四個時鍾節拍。這就是CRC校驗的並行實現方式了!傳統的CRC校驗算法已經非常成熟,在使用過程中不需要完全自己推導公式,了解基本原理即可。CRC校驗的Verilog代碼線上生成工具 http://www.easics.com/webtools/crctool 我們選定CRC8,並將數據位寬定義為4bit,驗證上述推導過程是否正確。
生成源代碼:
1 ////////////////////////////////////////////////////////////////////////////////
2 // Purpose : synthesizable CRC function 3 // * polynomial: x^8 + x^2 + x^1 + 1 4 // * data width: 4
5 ////////////////////////////////////////////////////////////////////////////////
6 module CRC8_D4; 7
8 // polynomial: x^8 + x^2 + x^1 + 1 9 // data width: 4 10 // convention: the first serial bit is D[3]
11 function [7:0] nextCRC8_D4; 12
13 input [3:0] Data; 14 input [7:0] crc; 15 reg [3:0] d; 16 reg [7:0] c; 17 reg [7:0] newcrc; 18 begin
19 d = Data; 20 c = crc; 21
22 newcrc[0] = d[0] ^ c[4]; 23 newcrc[1] = d[1] ^ d[0] ^ c[4] ^ c[5]; 24 newcrc[2] = d[2] ^ d[1] ^ d[0] ^ c[4] ^ c[5] ^ c[6]; 25 newcrc[3] = d[3] ^ d[2] ^ d[1] ^ c[5] ^ c[6] ^ c[7]; 26 newcrc[4] = d[3] ^ d[2] ^ c[0] ^ c[6] ^ c[7]; 27 newcrc[5] = d[3] ^ c[1] ^ c[7]; 28 newcrc[6] = c[2]; 29 newcrc[7] = c[3]; 30 nextCRC8_D4 = newcrc; 31 end
32 endfunction
33 endmodule
參考資料:[1]百度百科:CRC(循環冗余校驗)
[2]沒落騎士:數據幀CRC32校驗算法實現