USB2.0IP設計
最近,在學習USB2.0IP的設計,其中包含了CRC校驗碼的內容,之前學習千兆乙太網曾經用到過CRC32校驗(https://www.cnblogs.com/Xwangzi66/p/14185143.html),CRC詳細原理可見括號的連結,今天則從怎麼用工具快速生成Verilog程式碼的角度介紹。
一 確定CRC5的多項式
G(X)= X^5 + X^2 + 1,輸入資料的位寬為11bit,即CRC5中的輸入訊號[10:0]data_i.
二 線上網頁生成CRC5的Verilog程式碼
連結如下:https://www.easics.com/crctool/
線上生成CRC5校驗程式碼如下圖:第一步是確定多項式,此處是CRC5的多項式。第二步選擇CRC的類別,如CRC16,CRC32等。第三步,選擇待校驗資料的位寬。第四步,選擇輸出的程式語言,用Verilog實現。第五步,下載開啟就。注意填好郵箱,此處為了保護本人隱私則空著。
2.線上工具生成CRC5的Verilog程式碼
1 module CRC5_D11;
2
3 // polynomial: x^5 + x^2 + 1
4 // data width: 11
5 // convention: the first serial bit is D[10]
6 function [4:0] nextCRC5_D11;
7
8 input [10:0] Data;
9 input [4:0] crc;
10 reg [10:0] d;
11 reg [4:0] c;
12 reg [4:0] newcrc;
13 begin
14 d = Data;
15 c = crc;
16
17 newcrc[0] = d[10] ^ d[9] ^ d[6] ^ d[5] ^ d[3] ^ d[0] ^ c[0] ^ c[3] ^ c[4];
18 newcrc[1] = d[10] ^ d[7] ^ d[6] ^ d[4] ^ d[1] ^ c[0] ^ c[1] ^ c[4];
19 newcrc[2] = d[10] ^ d[9] ^ d[8] ^ d[7] ^ d[6] ^ d[3] ^ d[2] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[3] ^ c[4];
20 newcrc[3] = d[10] ^ d[9] ^ d[8] ^ d[7] ^ d[4] ^ d[3] ^ d[1] ^ c[1] ^ c[2] ^ c[3] ^ c[4];
21 newcrc[4] = d[10] ^ d[9] ^ d[8] ^ d[5] ^ d[4] ^ d[2] ^ c[2] ^ c[3] ^ c[4];
22 nextCRC5_D11 = newcrc;
23 end
24 endfunction
25 endmodule
三 修改成自己USB的IP設計的CRC5校驗模組
通過線上工具生成後,自己可以修改模組名,輸入輸出訊號名,暫存器名,以更好地用在自己的FPGA專案中,本人CRC5修改如下:
1 module usbh_crc5
2 (
3 input [4:0] crc_i,
4 input [10:0] data_i,
5 output [4:0] crc_o
6 );
7
8 //-----------------------------------------------------------------
9 // Implementation
10 //-----------------------------------------------------------------
11 assign crc_o[0] = data_i[10] ^ data_i[9] ^ data_i[6] ^ data_i[5] ^ data_i[3] ^ data_i[0] ^
12 crc_i[0] ^ crc_i[3] ^ crc_i[4];
13
14 assign crc_o[1] = data_i[10] ^ data_i[7] ^ data_i[6] ^ data_i[4] ^ data_i[1] ^
15 crc_i[0] ^ crc_i[1] ^ crc_i[4];
16
17 assign crc_o[2] = data_i[10] ^ data_i[9] ^ data_i[8] ^ data_i[7] ^ data_i[6] ^ data_i[3] ^ data_i[2] ^ data_i[0] ^
18 crc_i[0] ^ crc_i[1] ^ crc_i[2] ^ crc_i[3] ^ crc_i[4];
19
20 assign crc_o[3] = data_i[10] ^ data_i[9] ^ data_i[8] ^ data_i[7] ^ data_i[4] ^ data_i[3] ^ data_i[1] ^
21 crc_i[1] ^ crc_i[2] ^ crc_i[3] ^ crc_i[4];
22
23 assign crc_o[4] = data_i[10] ^ data_i[9] ^ data_i[8] ^ data_i[5] ^ data_i[4] ^ data_i[2] ^
24 crc_i[2] ^ crc_i[3] ^ crc_i[4];
25
26 endmodule
通過修改後,程式碼更簡潔高效,更方便呼叫,直接在USB中呼叫即可!
後續的CRC16的Verilog實現,同CRC5生成方法一樣,先用線上工具生成,再修改一些模組名,輸入輸出訊號即可。
CRC16程式碼如下:


1 module usbh_crc16
2 (
3 input [15:0] crc_i,
4 input [7:0] data_i,
5 output [15:0] crc_o
6 );
7
8 //-----------------------------------------------------------------
9 // Implementation
10 //-----------------------------------------------------------------
11 assign crc_o[15] = data_i[0] ^ data_i[1] ^ data_i[2] ^ data_i[3] ^ data_i[4] ^
12 data_i[5] ^ data_i[6] ^ data_i[7] ^ crc_i[7] ^ crc_i[6] ^
13 crc_i[5] ^ crc_i[4] ^ crc_i[3] ^ crc_i[2] ^
14 crc_i[1] ^ crc_i[0];
15 assign crc_o[14] = data_i[0] ^ data_i[1] ^ data_i[2] ^ data_i[3] ^ data_i[4] ^ data_i[5] ^
16 data_i[6] ^ crc_i[6] ^ crc_i[5] ^ crc_i[4] ^
17 crc_i[3] ^ crc_i[2] ^ crc_i[1] ^ crc_i[0];
18 assign crc_o[13] = data_i[6] ^ data_i[7] ^ crc_i[7] ^ crc_i[6];
19 assign crc_o[12] = data_i[5] ^ data_i[6] ^ crc_i[6] ^ crc_i[5];
20 assign crc_o[11] = data_i[4] ^ data_i[5] ^ crc_i[5] ^ crc_i[4];
21 assign crc_o[10] = data_i[3] ^ data_i[4] ^ crc_i[4] ^ crc_i[3];
22 assign crc_o[9] = data_i[2] ^ data_i[3] ^ crc_i[3] ^ crc_i[2];
23 assign crc_o[8] = data_i[1] ^ data_i[2] ^ crc_i[2] ^ crc_i[1];
24 assign crc_o[7] = data_i[0] ^ data_i[1] ^ crc_i[15] ^ crc_i[1] ^ crc_i[0];
25 assign crc_o[6] = data_i[0] ^ crc_i[14] ^ crc_i[0];
26 assign crc_o[5] = crc_i[13];
27 assign crc_o[4] = crc_i[12];
28 assign crc_o[3] = crc_i[11];
29 assign crc_o[2] = crc_i[10];
30 assign crc_o[1] = crc_i[9];
31 assign crc_o[0] = data_i[0] ^ data_i[1] ^ data_i[2] ^ data_i[3] ^ data_i[4] ^ data_i[5] ^
32 data_i[6] ^ data_i[7] ^ crc_i[8] ^ crc_i[7] ^ crc_i[6] ^
33 crc_i[5] ^ crc_i[4] ^ crc_i[3] ^ crc_i[2] ^
34 crc_i[1] ^ crc_i[0];
35
36 endmodule
Crc16 Code
總結,一直都是根據多項式,確定硬體電路的形式,然後查表,如V3學院千兆乙太網的CRC32校驗教程,很繁瑣,得理解原理,今天意外知道一種新的方法,通過線上工具生成Verilog實現: