Verilog語言實現並行(循環冗余碼)CRC校驗


 

1 前言

(1)    什么是CRC校驗?

CRC即循環冗余校驗碼:是數據通信領域中最常用的一種查錯校驗碼,其特征是信息字段和校驗字段的長度可以任意選定。循環冗余檢查(CRC)是一種數據傳輸檢錯功能,對數據進行多項式計算,並將得到的結果附在幀的后面,接收設備也執行類似的算法,以保證數據傳輸的正確性和完整性。

LFSR計算CRC,可以用多項式G(x)表示,G(x) = X16+X12+X5+1模型可如下圖所示。

 

 

(2)    校驗原理

其根本思想就是先在要發送的幀后面附加一個數(這個就是用來校驗的校驗碼,但要注意,這里的數也是二進制序列的,下同),生成一個新幀發送給接收端。當然,這個附加的數不是隨意的,它要使所生成的新幀能與發送端和接收端共同選定的某個特定數整除(注意,這里不是直接采用二進制除法,而是采用一種稱之為“模2除法”)。到達接收端后,再把接收到的新幀除以(同樣采用“模2除法”)這個選定的除數。因為在發送端發送數據幀之前就已通過附加一個數,做了“去余”處理(也就已經能整除了),所以結果應該是沒有余數。如果有余數,則表明該幀在傳輸過程中出現了差錯。

要校驗的數據加上此數據計算出來的crc組成新的數據幀,如下圖所示。

模2除法:

模2除法與算術除法類似,但每一位除的結果不影響其它位,即不向上一位借位,所以實際上就是異或。在循環冗余校驗碼(CRC)的計算中有應用到模2除法。

(3)    步驟

CRC校驗中有兩個關鍵點,一是預先確定一個發送送端和接收端都用來作為除數的二進制比特串(或多項式),可以隨機選擇,也可以使用國際標准,但是最高位和最低位必須為1;二是把原始幀與上面計算出的除數進行模2除法運算,計算出CRC碼。

1. 選擇合適的除數

2. 看選定除數的二進制位數,然后再要發送的數據幀上面加上這個位數-1位的0,然后用新生成的幀以模2除法的方式除上面的除數,得到的余數就是該幀的CRC校驗碼。注意,余數的位數一定只比除數位數少一位,也就是CRC校驗碼位數比除數位數少一位,如果前面位是0也不能省略。

3. 將計算出來的CRC校驗碼附加在原數據幀后面,構建成一個新的數據幀進行發送;最后接收端在以模2除法方式除以前面選擇的除數,如果沒有余數,則說明數據幀在傳輸的過程中沒有出錯。

(4)    計算實例

現假設選擇的CRC生成多項式為G(X) = X4 + X3 + 1,要求出二進制序列10110011的CRC校驗碼。下面是具體的計算過程:

①將多項式轉化為二進制序列,由G(X) = X4 + X3 + 1可知二進制一種有五位,第4位、第三位和第零位分別為1,則序列為11001

②多項式的位數位5,則在數據幀的后面加上5-1位0,數據幀變為101100110000,然后使用模2除法除以除數11001,得到余數。

③將計算出來的CRC校驗碼添加在原始幀的后面,真正的數據幀為101100110100,再把這個數據幀發送到接收端。

④接收端收到數據幀后,用上面選定的除數,用模2除法除去,驗證余數是否為0,如果為0,則說明數據幀沒有出錯。

2 流程

(1)並行計算crc用verilog語言描述是復雜繁瑣的,所以可以使用在線工具生成verilog或者VHDL模板:http://www.easics.com/webtools/crctool,模板生成的代碼稍加修改即可使用。

(2)本次校驗模型為G(x) = X16+X12+X5+1。在在線工具中操作相關選項生成模板。

 

模板v文件如下:

 1 ////////////////////////////////////////////////////////////////////////////////
 2 // Copyright (C) 1999-2008 Easics NV.
 3 // This source file may be used and distributed without restriction
 4 // provided that this copyright statement is not removed from the file
 5 // and that any derivative work contains the original copyright notice
 6 // and the associated disclaimer.
 7 //
 8 // THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
 9 // OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 // WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 //
12 // Purpose : synthesizable CRC function
13 //   * polynomial: x^16 + x^12 + x^5 + 1
14 //   * data width: 16
15 //
16 // Info : tools@easics.be
17 //        http://www.easics.com
18 ////////////////////////////////////////////////////////////////////////////////
19 module CRC16_D16;
20 
21   // polynomial: x^16 + x^12 + x^5 + 1
22   // data width: 16
23   // convention: the first serial bit is D[15]
24   function [15:0] nextCRC16_D16;
25 
26     input [15:0] Data;
27     input [15:0] crc;
28     reg [15:0] d;
29     reg [15:0] c;
30     reg [15:0] newcrc;
31   begin
32     d = Data;
33     c = crc;
34 
35     newcrc[0] = d[12] ^ d[11] ^ d[8] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[8] ^ c[11] ^ c[12];
36     newcrc[1] = d[13] ^ d[12] ^ d[9] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[9] ^ c[12] ^ c[13];
37     newcrc[2] = d[14] ^ d[13] ^ d[10] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[10] ^ c[13] ^ c[14];
38     newcrc[3] = d[15] ^ d[14] ^ d[11] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[11] ^ c[14] ^ c[15];
39     newcrc[4] = d[15] ^ d[12] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[12] ^ c[15];
40     newcrc[5] = d[13] ^ d[12] ^ d[11] ^ d[9] ^ d[8] ^ d[5] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[5] ^ c[8] ^ c[9] ^ c[11] ^ c[12] ^ c[13];
41     newcrc[6] = d[14] ^ d[13] ^ d[12] ^ d[10] ^ d[9] ^ d[6] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[6] ^ c[9] ^ c[10] ^ c[12] ^ c[13] ^ c[14];
42     newcrc[7] = d[15] ^ d[14] ^ d[13] ^ d[11] ^ d[10] ^ d[7] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[7] ^ c[10] ^ c[11] ^ c[13] ^ c[14] ^ c[15];
43     newcrc[8] = d[15] ^ d[14] ^ d[12] ^ d[11] ^ d[8] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[8] ^ c[11] ^ c[12] ^ c[14] ^ c[15];
44     newcrc[9] = d[15] ^ d[13] ^ d[12] ^ d[9] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[9] ^ c[12] ^ c[13] ^ c[15];
45     newcrc[10] = d[14] ^ d[13] ^ d[10] ^ d[9] ^ d[5] ^ c[5] ^ c[9] ^ c[10] ^ c[13] ^ c[14];
46     newcrc[11] = d[15] ^ d[14] ^ d[11] ^ d[10] ^ d[6] ^ c[6] ^ c[10] ^ c[11] ^ c[14] ^ c[15];
47     newcrc[12] = d[15] ^ d[8] ^ d[7] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[7] ^ c[8] ^ c[15];
48     newcrc[13] = d[9] ^ d[8] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[8] ^ c[9];
49     newcrc[14] = d[10] ^ d[9] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[9] ^ c[10];
50     newcrc[15] = d[11] ^ d[10] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[10] ^ c[11];
51     nextCRC16_D16 = newcrc;
52   end
53   endfunction
54 endmodule

 

(3)修改模板最終如下:

 1 `timescale 1ns/1ps
 2 module crc16_test (
 3     input     wire              i_clk                 , //時鍾;
 4     input     wire              i_rst_n               , //同步復位;
 5     input     wire              i_din_valid           , //輸入數據有效;
 6     input     wire    [15:0]    i_din                 , //輸入數據;
 7     output    wire              o_dout_valid          , //輸出CRC值有效;
 8     output    wire    [15:0]    o_dout                  //輸出CRC;         
 9 );
10 reg [15:0] r_dout;
11 wire [15:0] d;
12 wire [15:0] c;
13 assign d = i_din;
14 assign c = r_dout;
15 always @(posedge i_clk) begin
16     if (~i_rst_n) 
17         r_dout <= 16'hffff; //初始值為ffff;
18     else if (i_din_valid) 
19     begin //計算邏輯;
20         r_dout[0]  = d[12] ^ d[11] ^ d[8] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[8] ^ c[11] ^ c[12];
21         r_dout[1]  = d[13] ^ d[12] ^ d[9] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[9] ^ c[12] ^ c[13];
22         r_dout[2]  = d[14] ^ d[13] ^ d[10] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[10] ^ c[13] ^ c[14];
23         r_dout[3]  = d[15] ^ d[14] ^ d[11] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[11] ^ c[14] ^ c[15];
24         r_dout[4]  = d[15] ^ d[12] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[12] ^ c[15];
25         r_dout[5]  = d[13] ^ d[12] ^ d[11] ^ d[9] ^ d[8] ^ d[5] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[5] ^ c[8] ^ c[9] ^ c[11] ^ c[12] ^ c[13];
26         r_dout[6]  = d[14] ^ d[13] ^ d[12] ^ d[10] ^ d[9] ^ d[6] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[6] ^ c[9] ^ c[10] ^ c[12] ^ c[13] ^ c[14];
27         r_dout[7]  = d[15] ^ d[14] ^ d[13] ^ d[11] ^ d[10] ^ d[7] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[7] ^ c[10] ^ c[11] ^ c[13] ^ c[14] ^ c[15];
28         r_dout[8]  = d[15] ^ d[14] ^ d[12] ^ d[11] ^ d[8] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[8] ^ c[11] ^ c[12] ^ c[14] ^ c[15];
29         r_dout[9]  = d[15] ^ d[13] ^ d[12] ^ d[9] ^ d[8] ^ d[4] ^ c[4] ^ c[8] ^ c[9] ^ c[12] ^ c[13] ^ c[15];
30         r_dout[10] = d[14] ^ d[13] ^ d[10] ^ d[9] ^ d[5] ^ c[5] ^ c[9] ^ c[10] ^ c[13] ^ c[14];
31         r_dout[11] = d[15] ^ d[14] ^ d[11] ^ d[10] ^ d[6] ^ c[6] ^ c[10] ^ c[11] ^ c[14] ^ c[15];
32         r_dout[12] = d[15] ^ d[8] ^ d[7] ^ d[4] ^ d[0] ^ c[0] ^ c[4] ^ c[7] ^ c[8] ^ c[15];
33         r_dout[13] = d[9] ^ d[8] ^ d[5] ^ d[1] ^ c[1] ^ c[5] ^ c[8] ^ c[9];
34         r_dout[14] = d[10] ^ d[9] ^ d[6] ^ d[2] ^ c[2] ^ c[6] ^ c[9] ^ c[10];
35         r_dout[15] = d[11] ^ d[10] ^ d[7] ^ d[3] ^ c[3] ^ c[7] ^ c[10] ^ c[11];
36     end
37 end 
38 reg r_dout_valid = 0; 
39 always @(posedge i_clk) //輸入數據在一個時鍾內完成CRC計算,下一個時鍾輸出;
40 begin
41     r_dout_valid <= i_din_valid;
42 end
43 
44 assign o_dout_valid = r_dout_valid;
45 assign o_dout = r_dout ;
46 
47 endmodule // end the crc16_test model;

 

3 仿真

仿真結果和在線工具計算結果進行比較,在線工具地址:http://www.ip33.com/crc.html

(1)編寫tb文件,對代碼進行測試,測試結果如下圖所示:

(2)在線校驗。輸入需要校驗的數據,選擇參數模型,輸入初始值(此次crc結果的前一個crc值,代碼中初始化為ffff)。可以對比發現計算無誤。

第一次計算0011(初始值為ffff),結果為1f1f。

第二次計算0013(初始值為1f1f),結果為d2c1。

 

4 綜合

本次綜合參考芯片為:xc7k325tffg676-2

(1)    資源使用量如下圖所示。

 

(2)    模塊時鍾約束為100M,裕量如下圖所示,滿足時序要求。

 

以上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM