• 基于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等;

      

      上面的文字中若有不当或者疏漏之处,还望各位道友能告知一二,我会立即订正~

      

  • 相关阅读:
    MySQL5.7 多主一从(多源复制)同步配置
    mysql 树形查询 结果
    【教程】Chrome 浏览器安装Vue插件方法 (十分详细)
    MySQL数据库备份
    nginx之ngnix搭建静态服务器,前端css,js,图片,视频等静态资源走nginx代理,实现Nginx缓存,压缩
    尽量不要让儿女从事这3种工作,钱再多也别做,坚持再久也没前途
    【MySQL】mysql5.7多源复制报错问题处理
    MyBatis 多条件查询、动态SQL、多表操作、注解开发,应有尽有,一网打尽!
    MySQL 5.7多源复制配置详解
    mysql 逆向生成Pmd 文件
  • 原文地址:https://www.cnblogs.com/571328401-/p/13268689.html
Copyright © 2020-2023  润新知