基於FPGA的千兆以太網的實現


一、簡介

  一般來說,我們要將 FPGA 板子上采集的數據傳輸到 PC 端有多種方式,如  UART、USB、千兆網、光纖、PCIe等手段,感覺還是千兆網傳輸的性價比最高,實現上不是很難,傳輸速率也比較快。以太網的分類有標准以太網(10Mbit/s),快速以太網(100Mbit/s)和千兆以太網(1000Mbit/s)。隨着以太網技術的飛速發展,市場上也出現了萬兆以太網(10Gbit/s),它擴展了IEEE802.3協議和MAC規范,使其技術支持 10Gbit/s的傳輸速率。然而在實際應用中,標准以太網和快速以太網已經能夠滿足我們的日常需求,對通信速率較高的場合才會用到千兆以太網。

二、對以太網數據包格式的協議一一講解

 

  由上圖可知,要發送的數據是加載在UDP協議中,UDP協議又是加載在IP協議中,IP協議加載在MAC協議中,是一種層層包含的關系,下面對MAC、IP、UDP協議一一詳細講解。

  1、MAC幀格式

     1)前導碼(Preamble):實現底層數據的正確闡述,物理層使用 7 個字節同步碼(0和1交替(55_55_55_55_55_55_55))實現數據的同步。

     2)幀起始界定符:一個字節,固定為(0xd5)來表示一幀的開始,即后面緊跟着傳輸的就是以太網的幀頭。

     3)目的MAC地址:六個字節,表明幀的接受者(電腦的MAC地址)。

     4)源MAC地址:六個字節,表明幀的發送者(板子的MAC地址,一般為自己設置一個地址)。

     5)長度/類型:兩個字節,長度/類型具有兩個意義,當着連個字節的值小於1536(十六進制為0x0600)時,代表該以太網中數據段的長度;如果這兩個字節的值大於1536,則表示該以太網中的數據屬於哪個上層協議,例如0x0800代表IP協議、0x0806代表ARP協議等。

     6)數據:以太網中的數據段長度最小 46 字節,最大1500個字節。最大值1500稱為以太網的最大傳輸單元,之所以閑置最大傳輸單元是因為在多個計算機的數據幀排隊等待傳輸時,如果某個數據幀太大的話,那么其他數據幀等待的時間就會加長,導致體驗變差。

     7)幀校驗序列(FCS):四個字節,為了保證數據的正確傳輸,在數據的尾部加入了4個字節的循環冗余校驗碼(CRC校驗)來檢測數據是否傳輸錯誤。CRC數據校驗從以太網幀頭開始即不包含前導碼和幀起始界定符。

    值得注意的地方:以太網相鄰兩幀之間的時間間隔,即幀間隙(IFG)。幀間隙的時間就是網絡設備和組件在接收一幀之后,需要短暫的時間來恢復並未接收下一幀做准備的時間。不管是10M/100M/1000M的以太網,兩幀之間最少要有96bit time,IFG的最小間隔時間計算方法如下:

    10Mbit/s 最小時間為 :96 * 100ns = 9600ns;

    100Mbit/s最小時間為 :96 *10ns = 960ns;

    1000Mbit/s最小時間為:96 * 1ns = 96ns;

  2、IP數據報格式

    IP數據報前 20 個字節是固定的,IP首部的每一行以32位(4個字節)為單位。

 

    1)版本:4位IP版本號,設置為0x4時,表示 IPv4,設置為0x6,表示IPv6,目前使用較多的IP協議版本號是IPv4。

    2)首部長度:4位首部長度,表示IP首部一共有多少個32位。在沒有可選字段時,IP首部長度為20個字節,因此首部長度的值為0x5。

    3)服務類型:8位服務類型,一般設置為全零,8'h00。

    4)總長度:16位,IP首部長度 + UDP首部長度 + 數據部分的長度(如:IP首部長度固定為 20個字節 + UDP首部長度為 8個字節 + 數據部分的字節數)。

    5)標識:16位,用來標識主句發送的每一份數據報,通常每發一份報文它的值就會加1。(也可以設置為0)

    6)標志字段:3位,第一位為保留為;第二位表示禁止分片(1表示不分片,0表示分片);第三位表示更多分片。(也可以設置為0)

    7)片偏移:13位,在接收方進行數據報重組時用來標識分片的順序。(也可以設置為0)

    8)生存時間:8位,防止丟失的數據包在無休止的傳播,一般被設置為64或者128。

    9)協議:8位,表示此數據包所攜帶上層數據使用的協議類型,ICMP為1,TCP為6,UDP為17。

    10)首部校驗和:16位,該字段只校驗數據報的首部,不包含數據部分,校驗IP數據報頭部是否被破壞、篡改和丟失等。

    11)源IP地址:32位,即發送端的IP地址(板子的IP地址),一般為自己設置,如192.168.0.2。

    12)目的IP地址:32位,即接收端的IP地址(電腦的IP地址),也可以自己設置,如192.168.0.3。在上板實驗時,需將電腦上的IP改為自己設置的那個IP地址。

    IP首部校驗和的計算方法:

      (1)將16位檢核和字段置為0,然后將IP首部按照16位分成多個單元;

      (2)將各個單元采用反碼加法運算(即高位溢出會加到低位,通常的補碼運算時直接丟掉溢出的高位);

      (3)此時仍然可能出現進位的情況,將得到的和再次分成高16位和低16位進行累加;

      (4)最后將得到的和的反碼填入校驗和字段;

      如:0 - 31:  45_00_00_32

        0 - 31:  00_00_00_00

        0 - 31:  40_11_00_00

        0 - 31 :  c0_a8_00_02

        0 - 31 :  c0_a8_00_03

        (a)0x4500 + 0x0032 +0x0000 +0x0000 +0x4011 +0x0000 + 0xc0a8 +0x 0002 + 0xc0a8 +0x0003 = 0x20698

        (b)0x0002 + 0x0698 = 0x0698

        (c)0x0000 + 0x0698 = 0x0698

        (d)ip_checksm = ~0x0698 = 0xf967

 

  3、UDP協議

 

     1)源端口號:16位發送端端口號,用於區分不同服務的端口。

     2)目的端口號:16位接收端端口號。

     3)UDP長度:16位UDP長度,包含UDP首部長度 + 數據長度,單位是字節;(如,UDP首部長度 8 個字節 + 傳輸的數據字段的字節數)

     4)UDP校驗和:16位UDP校驗和,在大多數情況下設置 0x0000

三、接口時序

    1、接口信號介紹

    (1)GTX_CLK:發送時鍾信號,由FPGA中的PLL產生發送給以太網芯片,頻率為 125MHz;

    (2)TX_EN:發送數據使能信號,高電平有效;

    (3)TX_ER:發送錯誤信號,高電平有效,用以破壞數據包的發送,這個信號有些博文中設置為零,但是有條件的話還是設置一下,這個信號挺有用的;

    (4)TXD:發送數據線,FPGA通過該數據線將需要發送的數據依次發送給PHY芯片;

    (5)RX_CLK:由PHY芯片產生,125MHz;

    (6)RX_EN:接收使能信號,高電平有效;

    (7)RX_ER:接收錯誤信號,高電平有效;

    (8)RXD:接收數據線,FPGA通過該數據線從PHY接收數據;

    2、接口時序(僅列出發送時序)

 

     這個GMII模式的千兆網的發送時序,在TX_EN為高電平時,在時鍾的上升沿發送數據給以太網芯片,在千兆網中,發送數據是先發高位,再發低位;

   3、按照上述的協議,發送數據實現協議的順序如下:

    (1)前導碼 + 幀定界符:64'h55_55_55_55_55_55_55_d5;

    (2)MAC首部:des_mac:48'hff_ff_ff_ff_ff_ff;src_mac:48'h00_0a_35_01_fe_c0;type_len:16'h08_00;

    (3)IP首部:0~31:45_00_00_(ip_total_len)

           :0~31:00_00_00_00(注:這一列數據要慎重考慮,可以設為零,也可以按照正經要求來填寫)

           :0~31:40_11_(ip_checksum)

           :0~31:c0_a8_00_02

           :0~31:c0_a8_00_03

    (4)UDP首部:0~31:13_88_17_70(這里源端口和目的端口分別為5000,6000)

           :0~31:(udp_len)_00_00

    (5)數據部分,自定義;

    (6)CRC校驗,我用的是一個普遍適用的CRC校驗,代碼會在下文給出;

四、代碼實現(僅做參考用)

  1、硬件平台:MP801

  2、軟件環境:Quartus II 13.0

  3、RTL視圖:

 

   注:以太網芯片為 RTL8211EG;以太網復位是高電平有效;gtx_clk這個時鍾信號是由FPGA通過PLL倍頻到 125MHz;

  4、實現源碼:

  頂層模塊:gmii_test.v

 1 // *********************************************************************************
 2 // Project Name : udpsend
 3 // Email             : 
 4 // Create Time    : 2020/07/06 15:21
 5 // Module Name  : udpsend
 6 // editor         : qing
 7 // Version         : Rev1.0.0
 8 // *********************************************************************************
 9 
10 module gmii_test(
11     input                    sclk            ,
12     
13     output                phy_rst_n,
14     output    [7:0]               tx_data            ,
15     output                tx_en        ,
16     output                tx_er        ,
17     output                gtx_clk    
18 );
19 
20 
21 
22 pll u0 (
23     .inclk0 (sclk    ),
24     .c0     (gtx_clk )
25     );
26     
27 
28 
29 udp_send u2(
30         .gtx_clk        (gtx_clk        ),                   //GMII發送的時鍾信號
31         .tx_en        (tx_en        ),                  //GMII數據使能信號
32         .tx_er        (tx_er        ),                  //GMII發送錯誤信號
33         .tx_data        (tx_data        ),
34         .phy_rst_n        (phy_rst_n         )
35 );
36 
37 
38 
39 endmodule
40    
View Code

  子模塊:udp_send.v

  1 // *********************************************************************************
  2 // Project Name : gmii_tx_test
  3 // Email        : 
  4 // Create Time  : 2020/07/06 19:15
  5 // Module Name  : udp_send
  6 // editor        : qing
  7 // Version        : Rev1.0.0
  8 // *********************************************************************************
  9 
 10 module udp_send(
 11         input                    gtx_clk        ,
 12 
 13         output    reg                tx_en        ,
 14         output    reg                tx_er        ,
 15         output    reg[7:0]        tx_data        ,
 16         output                    phy_rst_n
 17     );
 18 
 19 //========================================================================\
 20 // =========== Define Parameter and Internal signals =========== 
 21 //========================================================================/
 22 
 23 wire            [15:0]        data_length        ;  // 數據字段的長度
 24 wire            [15:0]        ip_total_length ;  // ip首部 + udp首部 + 數據字段的長度
 25 
 26 reg                [3:0]        state             ;
 27 
 28 reg        [31:0]    ip_head        [6:0]            ;  // ip首部 + udp首部
 29 reg        [ 7:0]    premeble     [7:0]            ;
 30 reg        [ 7:0]  mac_addr    [13:0]            ;  // mac 首部
 31 
 32 reg        [ 4:0]  i,j                         ;
 33 
 34 reg        [31:0]  check_buff                    ;
 35 reg     [31:0]    delay_cnt                    ;
 36 reg     [15:0]    cnt_data                    ;
 37 
 38 reg                crcen                        ;
 39 reg                crcre                         ;
 40 wire     [31:0]    crc                         ;
 41 wire    [31:0]    CrcNext                     ;
 42 
 43 
 44 parameter         idle         =    4'b0000        ;
 45 parameter         start       =   4'b0001        ;
 46 parameter         make         =    4'b0010     ;
 47 parameter         send55      =   4'b0011        ;
 48 parameter         sendmac     =     4'b0100     ;
 49 parameter         sendhead    =   4'b0101     ;
 50 parameter         senddata    =    4'b0110     ;
 51 parameter         sendcrc     =   4'b0111     ;
 52 
 53 //=============================================================================
 54 //****************************     Main Code    *******************************
 55 //=============================================================================
 56 
 57 crc u0(
 58     .Clk         (gtx_clk    ), 
 59     .Reset        (crcre        ), 
 60     .Data_in    (tx_data    ), 
 61     .Enable        (crcen      ), 
 62     .Crc         (crc           ),
 63     .CrcNext    (CrcNext    )
 64     );
 65 
 66 assign data_length = 16'd33 ;
 67 assign ip_total_length = 16'd28 + data_length;
 68 assign phy_rst_n = 1'b1;
 69 
 70 always @(posedge gtx_clk ) begin
 71     premeble[0]    <= 8'h55;
 72     premeble[1]    <= 8'h55;
 73     premeble[2]    <= 8'h55;
 74     premeble[3]    <= 8'h55;
 75     premeble[4]    <= 8'h55;
 76     premeble[5]    <= 8'h55;
 77     premeble[6]    <= 8'h55;
 78     premeble[7]    <= 8'hd5;
 79 
 80     mac_addr[0] <= 8'hff;
 81     mac_addr[1] <= 8'hff;
 82     mac_addr[2] <= 8'hff;
 83     mac_addr[3] <= 8'hff;
 84     mac_addr[4] <= 8'hff;
 85     mac_addr[5] <= 8'hff;
 86 
 87     mac_addr[6] <= 8'h00;
 88     mac_addr[7] <= 8'h0a;
 89     mac_addr[8] <= 8'h35;
 90     mac_addr[9] <= 8'h01;
 91     mac_addr[10] <= 8'hfe;
 92     mac_addr[11] <= 8'hc0;
 93 
 94     mac_addr[12] <= 8'h08;
 95     mac_addr[13] <= 8'h00;
 96 end
 97 
 98 initial
 99     begin
100         //state <= idle;
101         
102         delay_cnt <= 0;
103         check_buff <= 32'h00000000;
104     end
105 
106 always @(posedge gtx_clk) begin
107     //state <= idle;
108     case(state)
109         idle:begin
110             tx_er <= 1'b0;
111             tx_en <= 1'b0;
112 
113             crcen <= 1'b0;
114             crcre <= 1'b1;
115             i <= 0;
116             j <= 0;
117             tx_data <= 8'd0;
118             cnt_data <= 0;
119 
120             if(delay_cnt == 32'h1000) begin  // 04000000
121                 state <= start;
122                 delay_cnt <= 0;
123             end
124             else
125                 delay_cnt <= delay_cnt + 1'b1;
126         end
127 
128         start:begin
129             ip_head[0] <= {16'h4500,ip_total_length};
130             ip_head[1][31:16] <= ip_head[1][31:16] + 1'b1;  //ip_head[1][31:16] + 1'b1
131             ip_head[1][15:0] <= 16'h0000;  // 4000
132             ip_head[2] <= 32'h80110000;
133             ip_head[3] <= 32'hc0a80002;
134             ip_head[4] <= 32'hc0a80003;
135             ip_head[5] <= 32'h13881770;
136             ip_head[6] <= {data_length,16'h0000};
137             state <= make; 
138         end
139 
140         make:begin
141             if(i==0) begin
142                 check_buff <= (ip_head[0][15:0] + ip_head[0][31:16] + ip_head[1][15:0] + ip_head[1][31:16]
143                              +ip_head[2][15:0] + ip_head[2][31:16] + ip_head[3][15:0] + ip_head[3][31:16]
144                              +ip_head[4][15:0] + ip_head[4][31:16] );
145                 i <= i + 1'b1;
146             end
147             else if(i == 1) begin
148                 check_buff[15:0] <= check_buff[31:16] + check_buff[15:0];
149                 i <= i + 1'b1;
150             end
151             else begin
152                 ip_head[2][15:0] <= ~check_buff[15:0];
153                 i <= 0;
154                 state <= send55;
155             end
156         end
157 
158         send55:begin
159             tx_en <= 1'b1;
160             crcre <= 1'b1;
161             if(i == 7) begin
162                 tx_data[7:0] <= premeble[i][7:0];
163                 i <= 0;
164                 state <= sendmac;
165             end
166             else begin
167                 tx_data[7:0] <= premeble[i][7:0];
168                 i <= i + 1'b1;
169             end
170         end
171 
172         sendmac:begin
173             crcen <= 1'b1;
174             crcre <= 1'b0;
175             if(i == 13) begin
176                 tx_data[7:0] <= mac_addr[i][7:0];
177                 i <= 0;
178                 state <= sendhead;
179             end
180             else begin
181                 tx_data[7:0] <= mac_addr[i][7:0];
182                 i <= i + 1'b1;
183             end
184         end
185 
186         sendhead:begin
187             if(j == 6) begin
188                 if(i == 0) begin
189                     tx_data[7:0] <= ip_head[j][31:24];
190                     i <= i + 1'b1;
191                 end
192                 else if(i == 1)begin
193                     tx_data[7:0] <= ip_head[j][23:16];
194                     i <= i + 1'b1;
195                 end
196                 else if(i == 2)begin
197                     tx_data[7:0] <= ip_head[j][15:8];
198                     i <= i + 1'b1;
199                 end
200                 else if(i == 3) begin
201                     tx_data <= ip_head[j][7:0];
202                     i <= 0;
203                     j <= 0;
204                     state <= senddata;
205                 end
206                 else
207                     tx_er <= 1'b1;
208             end
209             else begin
210                 if(i == 0) begin
211                     tx_data[7:0] <= ip_head[j][31:24];
212                     i <= i + 1'b1;
213                 end
214                 else if(i == 1) begin
215                     tx_data <= ip_head[j][23:16];
216                     i <= i + 1'b1;
217                 end
218                 else if(i == 2) begin
219                     tx_data <= ip_head[j][15:8];
220                     i <= i + 1'b1;
221                 end
222                 else if(i == 3) begin
223                     tx_data <= ip_head[j][7:0];
224                     i <= 0;
225                     j <= j + 1'b1;
226                 end
227                 else
228                     tx_er <= 1'b1;
229             end
230         end
231 
232         senddata:begin
233             if(cnt_data == data_length - 1) begin
234                 cnt_data <= 0;
235                 state <= sendcrc;
236                 tx_data <= 8'haa;
237             end
238             else begin
239                 cnt_data <= cnt_data + 1'b1;
240                 state <= senddata;
241             end
242             case(cnt_data)
243                 0:tx_data <= 8'hff;
244                 1:tx_data <= 8'h01;
245                 2:tx_data <= 8'h02;
246                 3:tx_data <= 8'h03;
247                 4:tx_data <= 8'h04;
248                 5:tx_data <= 8'h05;
249                 6:tx_data <= 8'h06;
250                 7:tx_data <= 8'h07;
251                 8:tx_data <= 8'h08;
252                 9:tx_data <= 8'h09;
253                 10:tx_data <= 8'h0a;
254                 11:tx_data <= 8'h0b;
255                 12:tx_data <= 8'h0c;
256                 13:tx_data <= 8'h0d;
257                 14:tx_data <= 8'h0e;
258                 15:tx_data <= 8'h0f;
259                 16:tx_data <= 8'hf0;
260                 17:tx_data <= 8'hf1;
261                 18:tx_data <= 8'hf2;
262                 19:tx_data <= 8'hf3;
263                 20:tx_data <= 8'hf4;
264                 21:tx_data <= 8'hf5;
265                 22:tx_data <= 8'hf6;
266                 23:tx_data <= 8'hf7;
267                 24:tx_data <= 8'hf8;
268                 25:tx_data <= 8'hf9;
269                 26:tx_data <= 8'hfa;
270                 27:tx_data <= 8'hfb;
271                 28:tx_data <= 8'hfc;
272                 29:tx_data <= 8'hfd;
273                 30:tx_data <= 8'hfe;
274                 31:tx_data <= 8'h11;
275                 32:tx_data <= 8'h22;
276                 default:tx_data <= 8'hff;
277             endcase
278         end
279 
280         sendcrc:begin
281             crcen <= 1'b0;
282             if(i == 0) begin
283                 tx_data[7:0] <= {~crc[24], ~crc[25], ~crc[26], ~crc[27], ~crc[28], ~crc[29], ~crc[30], ~crc[31]};
284                 i <= i + 1'b1; 
285             end
286             else begin
287                 if(i == 1) begin
288                     tx_data[7:0] <= {~crc[16], ~crc[17], ~crc[18], ~crc[19], ~crc[20], ~crc[21], ~crc[22], ~crc[23]};
289                     i <= i + 1'b1;
290                 end
291                 else if(i == 2) begin
292                     tx_data[7:0] <= {~crc[8], ~crc[9], ~crc[10], ~crc[11], ~crc[12], ~crc[13], ~crc[14], ~crc[15]};
293                     i <= i + 1'b1;
294                 end
295                 else if(i == 3) begin
296                     tx_data[7:0] <= {~crc[0], ~crc[1], ~crc[2], ~crc[3], ~crc[4], ~crc[5], ~crc[6], ~crc[7]};
297                     i <= 0;
298                     state <= idle;
299                 end
300                 else begin
301                     tx_er <= 1'b1;
302                 end
303             end
304         end
305         default:state <= idle;
306     endcase
307 end
308 
309 endmodule
View Code

  子模塊:crc.v

 1 `timescale 1ns / 1ps
 2 /****************************************/
 3 //       CRC32數據校驗模塊          //
 4 /****************************************/
 5 module crc (Clk, Reset, Data_in, Enable, Crc,CrcNext);
 6 
 7 
 8 parameter Tp = 1;
 9 
10 input Clk;
11 input Reset;
12 input [7:0] Data_in;
13 
14 input Enable;
15 
16 output [31:0] Crc;
17 reg  [31:0] Crc;
18 
19 output [31:0] CrcNext;
20 
21 wire [7:0] Data;
22 
23 assign Data={Data_in[0],Data_in[1],Data_in[2],Data_in[3],Data_in[4],Data_in[5],Data_in[6],Data_in[7]};
24 
25 
26 assign CrcNext[0] = Crc[24] ^ Crc[30] ^ Data[0] ^ Data[6];
27 assign CrcNext[1] = Crc[24] ^ Crc[25] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[6] ^ Data[7];
28 assign CrcNext[2] = Crc[24] ^ Crc[25] ^ Crc[26] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[2] ^ Data[6] ^ Data[7];
29 assign CrcNext[3] = Crc[25] ^ Crc[26] ^ Crc[27] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[3] ^ Data[7];
30 assign CrcNext[4] = Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[4] ^ Data[6];
31 assign CrcNext[5] = Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4] ^ Data[5] ^ Data[6] ^ Data[7];
32 assign CrcNext[6] = Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5] ^ Data[6] ^ Data[7];
33 assign CrcNext[7] = Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Crc[31] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[5] ^ Data[7];
34 assign CrcNext[8] = Crc[0] ^ Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4];
35 assign CrcNext[9] = Crc[1] ^ Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5];
36 assign CrcNext[10] = Crc[2] ^ Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[5];
37 assign CrcNext[11] = Crc[3] ^ Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4];
38 assign CrcNext[12] = Crc[4] ^ Crc[24] ^ Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Data[0] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5] ^ Data[6];
39 assign CrcNext[13] = Crc[5] ^ Crc[25] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[3] ^ Data[5] ^ Data[6] ^ Data[7];
40 assign CrcNext[14] = Crc[6] ^ Crc[26] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Crc[31] ^ Data[2] ^ Data[3] ^ Data[4] ^ Data[6] ^ Data[7];
41 assign CrcNext[15] =  Crc[7] ^ Crc[27] ^ Crc[28] ^ Crc[29] ^ Crc[31] ^ Data[3] ^ Data[4] ^ Data[5] ^ Data[7];
42 assign CrcNext[16] = Crc[8] ^ Crc[24] ^ Crc[28] ^ Crc[29] ^ Data[0] ^ Data[4] ^ Data[5];
43 assign CrcNext[17] = Crc[9] ^ Crc[25] ^ Crc[29] ^ Crc[30] ^ Data[1] ^ Data[5] ^ Data[6];
44 assign CrcNext[18] = Crc[10] ^ Crc[26] ^ Crc[30] ^ Crc[31] ^ Data[2] ^ Data[6] ^ Data[7];
45 assign CrcNext[19] = Crc[11] ^ Crc[27] ^ Crc[31] ^ Data[3] ^ Data[7];
46 assign CrcNext[20] = Crc[12] ^ Crc[28] ^ Data[4];
47 assign CrcNext[21] = Crc[13] ^ Crc[29] ^ Data[5];
48 assign CrcNext[22] = Crc[14] ^ Crc[24] ^ Data[0];
49 assign CrcNext[23] = Crc[15] ^ Crc[24] ^ Crc[25] ^ Crc[30] ^ Data[0] ^ Data[1] ^ Data[6];
50 assign CrcNext[24] = Crc[16] ^ Crc[25] ^ Crc[26] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[7];
51 assign CrcNext[25] = Crc[17] ^ Crc[26] ^ Crc[27] ^ Data[2] ^ Data[3];
52 assign CrcNext[26] = Crc[18] ^ Crc[24] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Data[0] ^ Data[3] ^ Data[4] ^ Data[6];
53 assign CrcNext[27] = Crc[19] ^ Crc[25] ^ Crc[28] ^ Crc[29] ^ Crc[31] ^ Data[1] ^ Data[4] ^ Data[5] ^ Data[7];
54 assign CrcNext[28] = Crc[20] ^ Crc[26] ^ Crc[29] ^ Crc[30] ^ Data[2] ^ Data[5] ^ Data[6];
55 assign CrcNext[29] = Crc[21] ^ Crc[27] ^ Crc[30] ^ Crc[31] ^ Data[3] ^ Data[6] ^ Data[7];
56 assign CrcNext[30] = Crc[22] ^ Crc[28] ^ Crc[31] ^ Data[4] ^ Data[7];
57 assign CrcNext[31] = Crc[23] ^ Crc[29] ^ Data[5];
58 
59 always @ (posedge Clk, posedge Reset)
60  begin
61   if (Reset) begin
62     Crc <={32{1'b1}};
63   end
64    else if (Enable)
65     Crc <=CrcNext;
66  end
67 endmodule
View Code

  5、用Wireshark捕捉的數據包

 

   這個代碼還是有些瑕疵的如:

    (1)在代碼中,我發送的數據長度是 33 個字節,用Wireshark捕捉到的數據長度也有 33 個字節,但是像這個圖中顯示的數據長度 Len = 25,這個我還沒搞明白;

    (2)在RTL仿真時,有些信號會出現未知的狀態,但是上板卻又能正常的工作;

  6、在學習千兆網的過程中,看了好幾個人的百兆網,千兆網代碼,下面列出一個自己寫的代碼,上板實驗沒有成功,但是RTL仿真和Signal Tap II仿真都是正常的,思路較為簡單,容易上手,僅供參考。

  頂層模塊:gmii_tx_test.v

 1 `timescale 1ns/1ps
 2 module gmii_tx_test(
 3     input                    clk            ,
 4     input                    rst_n            ,
 5     output                gtx_clk        ,
 6     output                tx_en            ,
 7     output                tx_er            ,
 8     output    [7:0]        tx_data        ,
 9     output                tx_done        ,
10     output                phy_rst_n
11 );
12 
13 
14 pll_125m    u0 (
15     .inclk0 ( clk                     ),
16     .c0     ( gtx_clk              )
17     );
18 
19 
20 gmii_tx u1(
21       .rst_n            (rst_n        ),
22       .tx_done        (tx_done        ),
23       .gtx_clk        (gtx_clk      ),
24       .tx_en            (tx_en        ),
25       .tx_er            (tx_er        ),
26       .tx_data        (tx_data        ),
27       .phy_rst_n    (phy_rst_n    )
28 );
29 
30 endmodule
View Code

  子模塊:gmii_tx.v

  1  // *********************************************************************************
  2 // Project Name : gmii_tx
  3 // Email        : 
  4 // Create Time  : 2020/06/22  10:41
  5 // Module Name  : 
  6 // editor         : 
  7 // Version         : Rev1.0.0
  8 // *********************************************************************************
  9 
 10 // Notice : 較為主流的CRC復位是發生在 前導碼 的時候,而我的復位是在 IDLE 狀態
 11 //            主流的 CRC_EN 是發生在發送 MAC幀和CRC幀前面,我的都是組合邏輯來實現的,而其他的都是時序邏輯
 12 
 13 module gmii_tx(
 14       rst_n        ,
 15       tx_done    ,
 16 
 17       gtx_clk    ,
 18       tx_en        ,
 19       tx_er        ,
 20       tx_data    ,
 21 
 22       phy_rst_n    
 23 );
 24 input                    gtx_clk            ;
 25 input                    rst_n            ;
 26 output    reg                   tx_en            ;
 27 output    reg             tx_er            ;
 28 output    reg[7:0]        tx_data            ; 
 29 output    reg                 tx_done            ;
 30 output    wire            phy_rst_n        ;
 31 
 32 //========================================================================\
 33 // =========== Define Parameter and Internal signals =========== 
 34 //========================================================================/
 35 
 36 parameter   Tx_Idle            =    4'd0                    ;
 37 parameter     Tx_premeble        =    4'd1                    ;
 38 parameter   Tx_Mac            =    4'd2                    ;
 39 parameter   Tx_ip            =    4'd3                    ;
 40 parameter   Tx_udp            =    4'd4                    ;
 41 parameter    Tx_data            =   4'd5                    ;
 42 parameter   Tx_crc            =    4'd6                    ;
 43 
 44 reg            [47:0]            des_mac                        ;
 45 reg            [47:0]            src_mac                        ;
 46 reg            [15:0]            type_length                    ;
 47 
 48 reg            [7:0]            ver_hdr_len                    ;
 49 reg            [7:0]            tos                            ;
 50 reg            [15:0]            ip_length                    ;
 51 reg            [15:0]            id                             ;
 52 reg         [15:0]            offset                        ;
 53 reg         [7:0]            ttl                         ;
 54 reg         [7:0]            protocol                    ;
 55 reg         [31:0]            des_ip                        ;
 56 reg         [31:0]            src_ip                        ;
 57 
 58 reg            [15:0]            des_port                    ;
 59 reg         [15:0]            src_port                    ;
 60 reg            [15:0]            udp_length                    ;
 61 reg         [15:0]            udp_checksum                ;
 62 
 63 /*
 64 parameter    data_length        =    16'h22                    ;  // 
 65 
 66 // -------------------- MAC ----------------------------
 67 parameter    des_mac            =    48'hff_ff_ff_ff_ff_ff    ;  // 18_31_bf_b8_b9_d9
 68 parameter    src_mac            =    48'h00_0a_35_01_fe_c0    ;
 69 parameter    type_length        =    16'h08_00                ;
 70 
 71 // -------------------- IP -----------------------------
 72 parameter    ver_hdr_len        =    8'h45                        ;
 73 parameter    tos             =    8'h00                         ;
 74 parameter    ip_length        =    16'h001c + data_length        ;  // 之前是 ip首部 + 數據部分,現在是 ip首部 + udp首部 + 數據長度
 75 parameter    id                =    16'h0000                     ;
 76 parameter    offset            =    16'h0000                     ;
 77 parameter    ttl             =    8'h40                         ;
 78 parameter    protocol        =    8'h11                         ;
 79 parameter    des_ip            =    32'hc0_a8_00_03                ;
 80 parameter    src_ip            =    32'hc0_a8_00_02                ;
 81 
 82 // -------------------- UDP ----------------------------
 83 
 84 parameter    des_port        =    16'h17_70                    ; // 6000
 85 parameter    src_port        =    16'h13_88                    ; // 5000
 86 parameter    udp_length        =    16'h0008 + data_length        ;
 87 parameter    udp_checksum    =    16'h0000                     ;
 88 */
 89 
 90 wire            [7:0]            tx_delay                ;
 91 reg                [19:0]            cnt                     ;
 92 
 93 reg                [3:0]            current_state            ;
 94 reg                [3:0]            next_state                ;
 95 
 96 wire            [15:0]            ip_checksum                ;
 97 wire            [31:0]            crc_result                ;
 98 wire            [31:0]            sum                        ;
 99 reg                                CRC_EN                    ;
100 reg                                CRC_reset                ;
101 
102 wire            [31:0]            crc                     ;
103 wire            [31:0]            crcNext                    ;
104 
105 reg                [4:0]            cnt_premeble            ;
106 reg                [4:0]            cnt_mac                    ;
107 reg                [4:0]            cnt_ip                    ;
108 reg                [4:0]            cnt_udp                    ;
109 reg                [5:0]            cnt_data                ;
110 reg                [4:0]            cnt_crc                    ;
111 
112 //=============================================================================
113 //****************************     Main Code    *******************************
114 //=============================================================================
115 
116 parameter    data_length        =    16'h22                    ;
117 
118 always @(posedge gtx_clk) begin  // MAC
119     des_mac    <=    48'hffffffffffff;
120     src_mac    <=    48'h000a3501fec0;
121     type_length    <= 16'h0800;
122 end
123 
124 always @(posedge gtx_clk) begin  // IP
125     ver_hdr_len    <=    8'h45;                    
126     tos         <=    8'h00 ;                    
127     ip_length    <=    16'h001c + data_length;    
128     id            <=    16'h0021;                 
129     offset        <=    16'h4000;                 
130     ttl         <=    8'h80;          //             
131     protocol    <=    8'h11;                     
132     des_ip        <=    32'hc0_a8_00_03;            
133     src_ip        <=    32'hc0_a8_00_02;            
134 end
135 
136 always @(posedge gtx_clk) begin  // UDP
137     des_port        <=    16'h17_70;                
138     src_port        <=    16'h13_88;                
139     udp_length        <=    16'h0008 + data_length;    
140     udp_checksum    <=    16'h0000 ;                
141 end
142 
143 assign sum = {ver_hdr_len,tos} + ip_length + id 
144             + offset + {ttl,protocol} + src_ip[31:16]
145             + src_ip[15:0] + des_ip[31:16] + des_ip[15:0];
146 
147 /*
148 CRC32_D8 u0 (
149     .Clk        (gtx_clk     ),
150     .Reset         (CRC_reset     ),
151     .Data_in    ( tx_data    ), 
152     .Enable     ( CRC_EN     ),
153     .Crc        (   Crc       ),
154     .CrcNext    (   CrcNext  ),
155     .Crc_eth    ( crc_result )
156 );
157 */
158 
159 crc u0(
160     .Clk        (gtx_clk   ), 
161     .Reset    (CRC_reset ),   // CRC_reset
162     .Data_in (tx_data   ), 
163     .Enable    (CRC_EN      ), 
164     .Crc        (    crc      ),
165     .CrcNext (crcNext   )
166 );
167     
168 //assign CRC_reset = (current_state == Tx_Idle) ? 1'b1 : 1'b0;
169 
170 //assign CRC_EN    = (current_state >= Tx_Mac && current_state <= Tx_data) ? 1'b1 : 1'b0;
171 
172 assign ip_checksum = ~(sum[31:16] + sum[15:0]);
173 
174 assign phy_rst_n   =  1'b1;
175 
176 always @(posedge gtx_clk or negedge rst_n) begin  // cnt
177     if(!rst_n)
178         cnt <= 20'd0;
179     else if(cnt == 80000)
180         cnt <= 20'd0;
181     else
182         cnt <= cnt + 1'b1;
183 end
184 
185 assign  tx_delay = (cnt == 80000)? 1'b1 : 1'b0;
186 
187 //=============================================================================\\
188 //****************************    State Machine    *******************************\\
189 //=============================================================================\\
190 
191 always @(posedge gtx_clk or negedge rst_n) begin
192     if(!rst_n)
193         current_state <= Tx_Idle;
194     else
195         current_state <= next_state;
196 
197 end
198 
199 always @(*) begin
200     next_state = Tx_Idle;
201     case(current_state)
202         Tx_Idle:begin
203             if(tx_delay == 1'b1)
204                 next_state = Tx_premeble;
205             else
206                 next_state = current_state;
207         end
208 
209         Tx_premeble:begin
210             if(cnt_premeble >= 8 -1 )
211                 next_state = Tx_Mac;
212             else
213                 next_state = current_state;
214         end
215 
216         Tx_Mac:begin
217             if(cnt_mac >= 14-1)
218                 next_state = Tx_ip;
219             else
220                 next_state = current_state;
221         end
222 
223         Tx_ip:begin
224             if(cnt_ip >= 20-1)
225                 next_state = Tx_udp;
226             else
227                 next_state = current_state;
228         end
229 
230         Tx_udp:begin
231             if(cnt_udp >= 8-1)
232                 next_state = Tx_data;
233             else
234                 next_state = current_state;
235         end
236 
237         Tx_data:begin
238             if(cnt_data >= data_length- 1 )
239                 next_state = Tx_crc;
240             else
241                 next_state = current_state;
242         end
243 
244         Tx_crc:begin
245             if(cnt_crc >= 4-1 ) 
246                 next_state = Tx_Idle;
247             else
248                 next_state = current_state;
249         end
250 
251         default:begin
252             next_state = Tx_Idle;
253         end
254     endcase
255 end
256 
257 always @(posedge gtx_clk or negedge rst_n) begin
258     if(!rst_n) begin
259         tx_data <= 8'h00;
260         tx_en <= 1'b0;
261         tx_er <= 1'b0;
262         tx_done <= 1'b0;
263         cnt_premeble <= 0;
264         cnt_mac <= 0;
265         cnt_ip <= 0;
266         cnt_udp <= 0;
267         cnt_data <= 0;
268         cnt_crc <= 0;
269         CRC_EN <= 1'b0;
270         CRC_reset <= 1'b0;
271     end
272     else begin
273         case(current_state)  // next_satae
274             Tx_Idle: begin
275                 tx_done <= 1'b0;
276                 tx_en <= 1'b0;
277                 tx_er <= 1'b0;
278                 tx_data <= 8'h00;
279                 CRC_reset <= 1'b1;
280             end
281 
282             Tx_premeble:begin
283                 CRC_reset <= 1'b1;
284                 tx_en <= 1'b1;
285                 if(cnt_premeble >= 8 -1 )
286                     cnt_premeble <= 0;
287                 else
288                     cnt_premeble <= cnt_premeble + 1'b1;
289                 case(cnt_premeble)
290                     0,1,2,3,4,5,6:
291                         tx_data <= 8'h55;
292                     7:tx_data <= 8'hd5;
293                     default:tx_data <= 8'h55;
294                 endcase
295             end
296 
297             Tx_Mac:begin
298                 CRC_reset <= 1'b0;
299                 CRC_EN <= 1'b1;
300                 if(cnt_mac >= 14 -1)
301                     cnt_mac <= 0;
302                 else
303                     cnt_mac <= cnt_mac + 1'b1;
304                 case(cnt_mac)
305                     0 :tx_data <= des_mac[47:40];
306                     1 :tx_data <= des_mac[39:32];
307                     2 :tx_data <= des_mac[31:24];
308                     3 :tx_data <= des_mac[23:16];
309                     4 :tx_data <= des_mac[15: 8];
310                     5 :tx_data <= des_mac[ 7: 0];
311                     
312                     6 :tx_data <= src_mac[47:40];
313                     7 :tx_data <= src_mac[39:32];
314                     8 :tx_data <= src_mac[31:24];
315                     9 :tx_data <= src_mac[23:16];
316                     10:tx_data <= src_mac[15: 8];
317                     11:tx_data <= src_mac[ 7: 0];
318                     
319                     12:tx_data <= type_length[15:8];
320                     13:tx_data <= type_length[ 7:0];
321                     default:tx_data <= 8'hff;
322                 endcase
323             end
324 
325             Tx_ip:begin
326                 if(cnt_ip >= 20-1 )
327                     cnt_ip <= 0;
328                 else
329                     cnt_ip <= cnt_ip + 1'b1;
330                 case(cnt_ip)
331                     0 : tx_data <= ver_hdr_len;
332                     1 :    tx_data <= tos;
333                     2 :    tx_data <= ip_length[15:8];
334                     3 :    tx_data <= ip_length[7:0];
335                     4 :    tx_data <= id[15:8];
336                     5 :    tx_data <= id[7:0];
337                     6 :    tx_data <= offset[15:8];
338                     7 :    tx_data <= offset[7:0];
339                     8 :    tx_data <= ttl;
340                     9 :    tx_data <= protocol;
341                     10:    tx_data <= ip_checksum[15:8];
342                     11:    tx_data <= ip_checksum[7:0];
343                     12:    tx_data <= src_ip[31:24];
344                     13:    tx_data <= src_ip[23:16];
345                     14:    tx_data <= src_ip[15:8];
346                     15:    tx_data <= src_ip[7:0];
347                     16:    tx_data <= des_ip[31:24];
348                     17:    tx_data <= des_ip[23:16];
349                     18:    tx_data <= des_ip[15:8];
350                     19:    tx_data <= des_ip[7:0];
351                     default:tx_data <= 8'hff;
352                 endcase
353             end
354 
355             Tx_udp:begin
356                 if(cnt_udp >= 8 -1)
357                     cnt_udp <= 0;
358                 else
359                     cnt_udp <= cnt_udp + 1'b1;
360                 case(cnt_udp)
361                     0: tx_data <= src_port[15:8];
362                     1: tx_data <= src_port[7:0];
363                     2: tx_data <= des_port[15:8];
364                     3: tx_data <= des_port[7:0];
365                     4: tx_data <= udp_length[15:8];
366                     5: tx_data <= udp_length[7:0];
367                     6: tx_data <= udp_checksum[15:8];
368                     7: tx_data <= udp_checksum[7:0];
369                     default:tx_data <= 8'hff;
370                 endcase
371             end
372 
373             Tx_data:begin
374                 if(cnt_data >= data_length -1)
375                     cnt_data <= 0;
376                 else
377                     cnt_data <= cnt_data + 1'b1;
378                 case(cnt_data)
379                     0:  tx_data <= 8'hf;
380                     1:  tx_data <= 8'h0;
381                     2:  tx_data <= 8'h1;
382                     3:  tx_data <= 8'h2;
383                     4:  tx_data <= 8'h3;
384                     5:  tx_data <= 8'h4;
385                     6:  tx_data <= 8'h5;
386                     7:  tx_data <= 8'h6;
387                     8:  tx_data <= 8'h7;
388                     9:  tx_data <= 8'h8;
389                     10: tx_data <= 8'h9;
390                     11: tx_data <= 8'ha;
391                     12: tx_data <= 8'hb;
392                     13: tx_data <= 8'hc;
393                     14: tx_data <= 8'hd;
394                     15: tx_data <= 8'he;
395                     16: tx_data <= 8'hf;
396                     17: tx_data <= 8'h1;
397                     18: tx_data <= 8'h2;
398                     19: tx_data <= 8'h3;
399                     20: tx_data <= 8'h4;
400                     21: tx_data <= 8'h5;
401                     22: tx_data <= 8'h6;
402                     23: tx_data <= 8'h7;
403                     24: tx_data <= 8'h8;
404                     25: tx_data <= 8'h9;
405                     26: tx_data <= 8'ha;
406                     27: tx_data <= 8'hb;
407                     28: tx_data <= 8'hc;
408                     29: tx_data <= 8'hd;
409                     30: tx_data <= 8'he;
410                     
411                     31: tx_data <= 8'haa;
412                     32: tx_data <= 8'hab;
413                     33: tx_data <= 8'hac;
414                     default:tx_data <= 8'hff;
415                 endcase
416             end
417 
418             Tx_crc:begin
419                 CRC_EN <= 1'b0;
420                 if(cnt_crc >= 4 -1) begin
421                     tx_done <= 1'b1;
422                     cnt_crc <= 0;
423                     //tx_en <= 1'b0;
424                 end
425                 else
426                     cnt_crc <= cnt_crc + 1'b1;
427                 case(cnt_crc)
428                     0: tx_data <= {~crc[24], ~crc[25], ~crc[26], ~crc[27], ~crc[28], ~crc[29], ~crc[30], ~crc[31]};                        // 8'h1b;
429                     1: tx_data <= {~crc[16], ~crc[17], ~crc[18], ~crc[19], ~crc[20], ~crc[21], ~crc[22], ~crc[23]};                        // 8'h75;
430                     2: tx_data <= {~crc[8], ~crc[9], ~crc[10], ~crc[11], ~crc[12], ~crc[13], ~crc[14], ~crc[15]};                        // 8'h49;
431                     3: tx_data <= {~crc[0], ~crc[1], ~crc[2], ~crc[3], ~crc[4], ~crc[5], ~crc[6], ~crc[7]};                        // 8'h0c;
432                     default:tx_data <= 8'hff;
433                 endcase
434             end
435             default:tx_data <= 8'h00;
436         endcase
437     end
438 end
439 
440 
441 endmodule
442 
443 /*
444 crc_result[31:24];
445 crc_result[23:16];
446 crc_result[15:8];
447 crc_result[7:0];
448 */
View Code

  子模塊:CRc32_D8.v

 1 `timescale 1ns/1ns
 2 module CRC32_D8(
 3     Clk,
 4     Reset,
 5     Data_in, 
 6     Enable,
 7     Crc,
 8     CrcNext,
 9     Crc_eth
10 );
11 
12     parameter Tp = 1;
13 
14     input Clk;
15     input Reset;
16     input [7:0] Data_in;
17     input Enable;
18 
19     output reg [31:0] Crc;
20     
21     output [31:0]Crc_eth;
22 
23     output [31:0] CrcNext;
24 
25     wire [7:0] Data;
26 
27     assign Data={Data_in[0],Data_in[1],Data_in[2],Data_in[3],Data_in[4],Data_in[5],Data_in[6],Data_in[7]};
28 
29     assign CrcNext[0] = Crc[24] ^ Crc[30] ^ Data[0] ^ Data[6];
30     assign CrcNext[1] = Crc[24] ^ Crc[25] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[6] ^ Data[7];
31     assign CrcNext[2] = Crc[24] ^ Crc[25] ^ Crc[26] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[2] ^ Data[6] ^ Data[7];
32     assign CrcNext[3] = Crc[25] ^ Crc[26] ^ Crc[27] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[3] ^ Data[7];
33     assign CrcNext[4] = Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[4] ^ Data[6];
34     assign CrcNext[5] = Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4] ^ Data[5] ^ Data[6] ^ Data[7];
35     assign CrcNext[6] = Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5] ^ Data[6] ^ Data[7];
36     assign CrcNext[7] = Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Crc[31] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[5] ^ Data[7];
37     assign CrcNext[8] = Crc[0] ^ Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4];
38     assign CrcNext[9] = Crc[1] ^ Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5];
39     assign CrcNext[10] = Crc[2] ^ Crc[24] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Data[0] ^ Data[2] ^ Data[3] ^ Data[5];
40     assign CrcNext[11] = Crc[3] ^ Crc[24] ^ Crc[25] ^ Crc[27] ^ Crc[28] ^ Data[0] ^ Data[1] ^ Data[3] ^ Data[4];
41     assign CrcNext[12] = Crc[4] ^ Crc[24] ^ Crc[25] ^ Crc[26] ^ Crc[28] ^ Crc[29] ^ Crc[30] ^ Data[0] ^ Data[1] ^ Data[2] ^ Data[4] ^ Data[5] ^ Data[6];
42     assign CrcNext[13] = Crc[5] ^ Crc[25] ^ Crc[26] ^ Crc[27] ^ Crc[29] ^ Crc[30] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[3] ^ Data[5] ^ Data[6] ^ Data[7];
43     assign CrcNext[14] = Crc[6] ^ Crc[26] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Crc[31] ^ Data[2] ^ Data[3] ^ Data[4] ^ Data[6] ^ Data[7];
44     assign CrcNext[15] =  Crc[7] ^ Crc[27] ^ Crc[28] ^ Crc[29] ^ Crc[31] ^ Data[3] ^ Data[4] ^ Data[5] ^ Data[7];
45     assign CrcNext[16] = Crc[8] ^ Crc[24] ^ Crc[28] ^ Crc[29] ^ Data[0] ^ Data[4] ^ Data[5];
46     assign CrcNext[17] = Crc[9] ^ Crc[25] ^ Crc[29] ^ Crc[30] ^ Data[1] ^ Data[5] ^ Data[6];
47     assign CrcNext[18] = Crc[10] ^ Crc[26] ^ Crc[30] ^ Crc[31] ^ Data[2] ^ Data[6] ^ Data[7];
48     assign CrcNext[19] = Crc[11] ^ Crc[27] ^ Crc[31] ^ Data[3] ^ Data[7];
49     assign CrcNext[20] = Crc[12] ^ Crc[28] ^ Data[4];
50     assign CrcNext[21] = Crc[13] ^ Crc[29] ^ Data[5];
51     assign CrcNext[22] = Crc[14] ^ Crc[24] ^ Data[0];
52     assign CrcNext[23] = Crc[15] ^ Crc[24] ^ Crc[25] ^ Crc[30] ^ Data[0] ^ Data[1] ^ Data[6];
53     assign CrcNext[24] = Crc[16] ^ Crc[25] ^ Crc[26] ^ Crc[31] ^ Data[1] ^ Data[2] ^ Data[7];
54     assign CrcNext[25] = Crc[17] ^ Crc[26] ^ Crc[27] ^ Data[2] ^ Data[3];
55     assign CrcNext[26] = Crc[18] ^ Crc[24] ^ Crc[27] ^ Crc[28] ^ Crc[30] ^ Data[0] ^ Data[3] ^ Data[4] ^ Data[6];
56     assign CrcNext[27] = Crc[19] ^ Crc[25] ^ Crc[28] ^ Crc[29] ^ Crc[31] ^ Data[1] ^ Data[4] ^ Data[5] ^ Data[7];
57     assign CrcNext[28] = Crc[20] ^ Crc[26] ^ Crc[29] ^ Crc[30] ^ Data[2] ^ Data[5] ^ Data[6];
58     assign CrcNext[29] = Crc[21] ^ Crc[27] ^ Crc[30] ^ Crc[31] ^ Data[3] ^ Data[6] ^ Data[7];
59     assign CrcNext[30] = Crc[22] ^ Crc[28] ^ Crc[31] ^ Data[4] ^ Data[7];
60     assign CrcNext[31] = Crc[23] ^ Crc[29] ^ Data[5];
61 
62     always @ (posedge Clk,posedge Reset)
63     if (Reset)
64         Crc <={32{1'b1}};
65    else if (Enable)
66         Crc <= #1 CrcNext;
67 
68 assign Crc_eth = ~{
69                         CrcNext[24], CrcNext[25], CrcNext[26], CrcNext[27],CrcNext[28], CrcNext[29], CrcNext[30], CrcNext[31],
70                         Crc[16], Crc[17], Crc[18], Crc[19],Crc[20], Crc[21], Crc[22], Crc[23],
71                         Crc[ 8], Crc[ 9], Crc[10], Crc[11],Crc[12], Crc[13], Crc[14], Crc[15],
72                         Crc[ 0], Crc[ 1], Crc[ 2], Crc[ 3],Crc[ 4], Crc[ 5], Crc[ 6], Crc[ 7]};        
73 
74 endmodule
View Code

 

五、參考

  【1】代碼實現上參考了小梅哥和黑金的千兆網程序;

  【2】文字敘述上參考了《基於ac620的fpga系統設計與驗證實戰指南20190516》,《開拓者FPGA開發指南_V1.2》,草山FPGA等;

  

  上面的文字中若有不當或者疏漏之處,還望各位道友能告知一二,我會立即訂正~

 

  


免責聲明!

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



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