• FPGA实现精简版UDP通信,占资源很少但很稳定,提供2套工程源码


    1.高端、中等和精简版UDP通信的选择

    FPGA实现UDP协议可难可易,具体根据项目需求而定,目前项目上的需求大概有如下几种:
    1、使用Xilinx系列FPGA实现UDP通信,且传输的数据量大,速率快,带宽高,这类的UDP通信必然要用到Xilinx的三速网IP,用户接口的数据必然是AXIS流,此类UDP协议功能齐全,无疑是很好的方案,关于这类的UDP通信介绍以及工程源码请参考我之前写的文章点击查看:高端UDP通信,附带工程源码
    此类UDP协议虽然很好,但占用FPGA资源较多,对于A7、Spatan6、Altera之类的低端FPGA来说资源消耗太大,不太可能被采用,再者,对于国产FPGA来说,没有三速网IP也无法实现;
    2、不使用三速网IP,通信速率相对较低,实现过程几乎使用纯verilog代码实现的中等UDP通信方案,关于这类的UDP通信介绍以及工程源码请参考我之前写的文章点击查看:中等UDP通信,附带工程源码
    此类方案没有了IP的限制,任何品牌的FPGA均可实现,但占用FPGA资源还是较多,低端FPGA依然很难实现;
    3、精简版UDP通信方案
    就是此文介绍的方案
    优点:
    纯verilog代码实现,没有任何IP;
    代码量很少,所占逻辑资源很少;
    通用性好,Xilinx、Altera、国产FPGA均可使用;
    稳定性好,本人反复测试,很稳定;

    2.精简版UDP通信实现方案

    总体实现方案如下:
    在这里插入图片描述
    RGMII-GMII模块实现网络PHY数据与FPGA接口的数据转换,由PHY的4位DDR双边沿采样数据到FPGA接口8位单边沿采样数据的转换;模块接口顶层如下:

    module gmii_to_rgmii(
        input              idelay_clk  , //IDELAY时钟
        //以太网GMII接口
        output             gmii_rx_clk , //GMII接收时钟
        output             gmii_rx_dv  , //GMII接收数据有效信号
        output      [7:0]  gmii_rxd    , //GMII接收数据
        output             gmii_tx_clk , //GMII发送时钟
        input              gmii_tx_en  , //GMII发送数据使能信号
        input       [7:0]  gmii_txd    , //GMII发送数据            
        //以太网RGMII接口   
        input              rgmii_rxc   , //RGMII接收时钟
        input              rgmii_rx_ctl, //RGMII接收数据控制信号
        input       [3:0]  rgmii_rxd   , //RGMII接收数据
        output             rgmii_txc   , //RGMII发送时钟    
        output             rgmii_tx_ctl, //RGMII发送数据控制信号
        output      [3:0]  rgmii_txd     //RGMII发送数据          
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    ARP模块顾名思义就是实现了ARP协议,该模块在不同应用中可有可无,在于上位机通信时需要,在FPGA板间通信时则可以不需要,模块接口顶层如下:

    module arp(
        input                rst_n      , //复位信号,低电平有效
        //GMII接口
        input                gmii_rx_clk, //GMII接收数据时钟
        input                gmii_rx_dv , //GMII输入数据有效信号
        input        [7:0]   gmii_rxd   , //GMII输入数据
        input                gmii_tx_clk, //GMII发送数据时钟
        output               gmii_tx_en , //GMII输出数据有效信号
        output       [7:0]   gmii_txd   , //GMII输出数据          
    
        //用户接口
        output               arp_rx_done, //ARP接收完成信号
        output               arp_rx_type, //ARP接收类型 0:请求  1:应答
        output       [47:0]  src_mac    , //接收到目的MAC地址
        output       [31:0]  src_ip     , //接收到目的IP地址    
        input                arp_tx_en  , //ARP发送使能信号
        input                arp_tx_type, //ARP发送类型 0:请求  1:应答
        input        [47:0]  des_mac    , //发送的目标MAC地址
        input        [31:0]  des_ip     , //发送的目标IP地址
        output               tx_done      //以太网发送完成信号    
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    UDP模块顾名思义就是实现了UDP协议,该部分内部已经包含了IP协议的编解码,这部分时整个工程的核心,UDP协议其实真的很简单,接收部分就是根据协议进行数据解包,解出帧头部分并丢弃,解出有效数据并输出;发送部分就是根据协议进行数据组包,把发送数据加上帧头发出去就完事儿了,模块接口顶层如下:

    module udp(
        input                rst_n       , //复位信号,低电平有效
        //GMII接口
        input                gmii_rx_clk , //GMII接收数据时钟
        input                gmii_rx_dv  , //GMII输入数据有效信号
        input        [7:0]   gmii_rxd    , //GMII输入数据
        input                gmii_tx_clk , //GMII发送数据时钟    
        output               gmii_tx_en  , //GMII输出数据有效信号
        output       [7:0]   gmii_txd    , //GMII输出数据 
        //用户接口
        output               rec_pkt_done, //以太网单包数据接收完成信号
        output               rec_en      , //以太网接收的数据使能信号
        output       [31:0]  rec_data    , //以太网接收的数据
        output       [15:0]  rec_byte_num, //以太网接收的有效字节数 单位:byte     
        input                tx_start_en , //以太网开始发送信号
        input        [31:0]  tx_data     , //以太网待发送数据  
        input        [15:0]  tx_byte_num , //以太网发送的有效字节数 单位:byte  
        input        [47:0]  des_mac     , //发送的目标MAC地址
        input        [31:0]  des_ip      , //发送的目标IP地址    
        output               tx_done     , //以太网发送完成信号
        output               tx_req        //读数据请求信号    
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    工程介绍:
    在这里插入图片描述
    简而言之就是实现UDP自发自收,以验证UDP协议的正确性;

    3.工程1介绍及资源占用率和性能表现

    工程1介绍;
    开发板:Kintex7开发板;
    网络PHY:B50610
    输出:RJ45网口
    接收:电脑上位机;
    B50610不需要配置,使用默认的配置,工作在延时模式,PHY的发送时钟rgmii_txc 与FPGA发送时钟gmii_tx_clk一致;
    代码部分如下:

    assign rgmii_txc = gmii_tx_clk;
    
    • 1

    工程顶层代码如下:

    
    module eth_udp_loop(
        input              clk_50   , //系统时钟
        //PL以太网RGMII接口   
        input              phy1_rgmii_rx_clk   , //RGMII接收数据时钟
        input              phy1_rgmii_rx_ctl, //RGMII输入数据有效信号
        input       [3:0]  phy1_rgmii_rx_data   , //RGMII输入数据
        output             phy1_rgmii_tx_clk   , //RGMII发送数据时钟    
        output             phy1_rgmii_tx_ctl, //RGMII输出数据有效信号
        output      [3:0]  phy1_rgmii_tx_data   , //RGMII输出数据          
        output             phy_reset   //以太网芯片复位信号,低电平有效   
        );
    
    //parameter define
    parameter  BOARD_MAC = 48'h00_11_22_33_44_55;   //开发板MAC地址 
    parameter  BOARD_IP  = {8'd192,8'd168,8'd10,8'd1};  //开发板IP地址
    parameter  DES_MAC   = 48'hff_ff_ff_ff_ff_ff; 	//目的MAC地址    
    parameter  DES_IP    = {8'd192,8'd168,8'd10,8'd2};	//目的IP地址 
    parameter IDELAY_VALUE = 0;	//输入数据IO延时,此处为0,即不延时(如果为n,表示延时n*78ps) 
    parameter  BOARD_POART =16'd1234;
    parameter  DES_POART   =16'd1234;
    
    //wire define
    wire          clk_200m   ; //用于IO延时的时钟         
    wire          gmii_rx_clk; //GMII接收时钟
    wire          gmii_rx_dv ; //GMII接收数据有效信号
    wire  [7:0]   gmii_rxd   ; //GMII接收数据
    wire          gmii_tx_clk; //GMII发送时钟
    wire          gmii_tx_en ; //GMII发送数据使能信号
    wire  [7:0]   gmii_txd   ; //GMII发送数据     
    wire          arp_gmii_tx_en; //ARP GMII输出数据有效信号 
    wire  [7:0]   arp_gmii_txd  ; //ARP GMII输出数据
    wire          arp_rx_done   ; //ARP接收完成信号
    wire          arp_rx_type   ; //ARP接收类型 0:请求  1:应答
    wire  [47:0]  src_mac       ; //接收到目的MAC地址
    wire  [31:0]  src_ip        ; //接收到目的IP地址    
    wire          arp_tx_en     ; //ARP发送使能信号
    wire          arp_tx_type   ; //ARP发送类型 0:请求  1:应答
    wire  [47:0]  des_mac       ; //发送的目标MAC地址
    wire  [31:0]  des_ip        ; //发送的目标IP地址   
    wire          arp_tx_done   ; //ARP发送完成信号
    wire          udp_gmii_tx_en; //UDP GMII输出数据有效信号 
    wire  [7:0]   udp_gmii_txd  ; //UDP GMII输出数据
    wire          rec_pkt_done  ; //UDP单包数据接收完成信号
    wire          rec_en        ; //UDP接收的数据使能信号
    wire  [31:0]  rec_data      ; //UDP接收的数据
    wire  [15:0]  rec_byte_num  ; //UDP接收的有效字节数 单位:byte 
    wire  [15:0]  tx_byte_num   ; //UDP发送的有效字节数 单位:byte 
    wire          udp_tx_done   ; //UDP发送完成信号
    wire          tx_req        ; //UDP读数据请求信号
    wire  [31:0]  tx_data       ; //UDP待发送数据
    wire sys_rst_n;
    //*****************************************************
    //**                    main code
    //*****************************************************
    assign gmii_tx_clk = gmii_rx_clk ;
    assign tx_start_en = rec_pkt_done;
    assign tx_byte_num = rec_byte_num;
    assign des_mac = src_mac;
    assign des_ip = src_ip;
    assign phy_reset = sys_rst_n;
    
    clk_wiz_0 instance_name
       (
        // Clock out ports
        .clk_200m(clk_200m),     // output clk_200m
        .clk_125m(),     // output clk_125m
        .clk_125m_90(),     // output clk_125m_90
        // Status and control signals
        .locked(sys_rst_n),       // output locked
       // Clock in ports
        .clk_in1(clk_50));      // input clk_in1
    
    //GMII接口转RGMII接口
    gmii_to_rgmii 
        #(
         .IDELAY_VALUE (IDELAY_VALUE)
         )
        u_gmii_to_rgmii(
        .idelay_clk    (clk_200m    ),
        .gmii_rx_clk   (gmii_rx_clk ),
        .gmii_rx_dv    (gmii_rx_dv  ),
        .gmii_rxd      (gmii_rxd    ),
        .gmii_tx_clk   (gmii_tx_clk ),
        .gmii_tx_en    (gmii_tx_en  ),
        .gmii_txd      (gmii_txd    ),
        .rgmii_rxc     (phy1_rgmii_rx_clk     ),
        .rgmii_rx_ctl  (phy1_rgmii_rx_ctl  ),
        .rgmii_rxd     (phy1_rgmii_rx_data     ),
        .rgmii_txc     (phy1_rgmii_tx_clk     ),
        .rgmii_tx_ctl  (phy1_rgmii_tx_ctl  ),
        .rgmii_txd     (phy1_rgmii_tx_data     )
        );
    
    //ARP通信
    arp                                             
       #(
        .BOARD_MAC     (BOARD_MAC),      //参数例化
        .BOARD_IP      (BOARD_IP ),
        .DES_MAC       (DES_MAC  ),
        .DES_IP        (DES_IP   )
        )
       u_arp(
        .rst_n         (sys_rst_n  ),             
        .gmii_rx_clk   (gmii_rx_clk),
        .gmii_rx_dv    (gmii_rx_dv ),
        .gmii_rxd      (gmii_rxd   ),
        .gmii_tx_clk   (gmii_tx_clk),
        .gmii_tx_en    (arp_gmii_tx_en ),
        .gmii_txd      (arp_gmii_txd),              
        .arp_rx_done   (arp_rx_done),
        .arp_rx_type   (arp_rx_type),
        .src_mac       (src_mac    ),
        .src_ip        (src_ip     ),
        .arp_tx_en     (arp_tx_en  ),
        .arp_tx_type   (arp_tx_type),
        .des_mac       (des_mac    ),
        .des_ip        (des_ip     ),
        .tx_done       (arp_tx_done)
        );
    
    //UDP通信
    udp                                             
       #(
        .BOARD_MAC     (BOARD_MAC),      //参数例化
        .BOARD_IP      (BOARD_IP ),
        .DES_MAC       (DES_MAC  ),
        .DES_IP        (DES_IP   ),
    	.BOARD_POART     (BOARD_POART),
    	.DES_POART       (DES_POART  )	
        )
       u_udp(
        .rst_n         (sys_rst_n   ),  
        .gmii_rx_clk   (gmii_rx_clk ),           
        .gmii_rx_dv    (gmii_rx_dv  ),         
        .gmii_rxd      (gmii_rxd    ),                   
        .gmii_tx_clk   (gmii_tx_clk ), 
        .gmii_tx_en    (udp_gmii_tx_en),         
        .gmii_txd      (udp_gmii_txd),  
        .rec_pkt_done  (rec_pkt_done),    
        .rec_en        (rec_en      ),     
        .rec_data      (rec_data    ),         
        .rec_byte_num  (rec_byte_num),      
        .tx_start_en   (tx_start_en ),        
        .tx_data       (tx_data     ),         
        .tx_byte_num   (tx_byte_num ),  
        .des_mac       (des_mac     ),
        .des_ip        (des_ip      ),    
        .tx_done       (udp_tx_done ),        
        .tx_req        (tx_req      )           
        ); 
    
    //同步FIFO
    sync_fifo_2048x32b u_sync_fifo_2048x32b (
        .clk      (gmii_rx_clk),  // input wire clk
        .rst      (~sys_rst_n),  // input wire rst
        .din      (rec_data  ),  // input wire [31 : 0] din
        .wr_en    (rec_en    ),  // input wire wr_en
        .rd_en    (tx_req    ),  // input wire rd_en
        .dout     (tx_data   ),  // output wire [31 : 0] dout
        .full     (),            // output wire full
        .empty    ()             // output wire empty
        );    
    
    //以太网控制模块
    eth_ctrl u_eth_ctrl(
        .clk            (gmii_rx_clk),
        .rst_n          (sys_rst_n),
        .arp_rx_done    (arp_rx_done   ),
        .arp_rx_type    (arp_rx_type   ),
        .arp_tx_en      (arp_tx_en     ),
        .arp_tx_type    (arp_tx_type   ),
        .arp_tx_done    (arp_tx_done   ),
        .arp_gmii_tx_en (arp_gmii_tx_en),
        .arp_gmii_txd   (arp_gmii_txd  ),               
        .udp_gmii_tx_en (udp_gmii_tx_en),
        .udp_gmii_txd   (udp_gmii_txd  ),            
        .gmii_tx_en     (gmii_tx_en    ),
        .gmii_txd       (gmii_txd      )
        );
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181

    K7上的资源消耗和性能表现如下:
    在这里插入图片描述
    由于工程中使用到了PLL和fifo,实际UDP部分所占资源更小;

    4.工程2介绍及资源占用率和性能表现

    工程2介绍;
    开发板:Artix7开发板;
    网络PHY:RTL8211
    输出:RJ45网口
    接收:电脑上位机;
    RTL8211不需要配置,使用默认的配置,工作在延时模式,PHY的发送时钟rgmii_txc 与FPGA发送时钟gmii_tx_clk不一致;rgmii_txc与gmii_tx_clk相位偏差+90°;
    代码部分如下:

    
    module rgmii_tx(
        //GMII发送端口
        input              gmii_tx_clk , //GMII发送时钟
    	input              gmii_tx_clk_90 ,
        input              gmii_tx_en  , //GMII输出数据有效信号
        input       [7:0]  gmii_txd    , //GMII输出数据        
        
        //RGMII发送端口
        output             rgmii_txc   , //RGMII发送数据时钟    
        output             rgmii_tx_ctl, //RGMII输出数据有效信号
        output      [3:0]  rgmii_txd     //RGMII输出数据     
        );
    
    assign rgmii_txc = gmii_tx_clk_90;
    
    //输出双沿采样寄存器 (rgmii_tx_ctl)
    ODDR #(
        .DDR_CLK_EDGE  ("SAME_EDGE"),  // "OPPOSITE_EDGE" or "SAME_EDGE" 
        .INIT          (1'b0),         // Initial value of Q: 1'b0 or 1'b1
        .SRTYPE        ("SYNC")        // Set/Reset type: "SYNC" or "ASYNC" 
    ) ODDR_inst (
        .Q             (rgmii_tx_ctl), // 1-bit DDR output
        .C             (gmii_tx_clk),  // 1-bit clock input
        .CE            (1'b1),         // 1-bit clock enable input
        .D1            (gmii_tx_en),   // 1-bit data input (positive edge)
        .D2            (gmii_tx_en),   // 1-bit data input (negative edge)
        .R             (1'b0),         // 1-bit reset
        .S             (1'b0)          // 1-bit set
    ); 
    
    genvar i;
    generate for (i=0; i<4; i=i+1)
        begin : txdata_bus
            //输出双沿采样寄存器 (rgmii_txd)
            ODDR #(
                .DDR_CLK_EDGE  ("SAME_EDGE"),  // "OPPOSITE_EDGE" or "SAME_EDGE" 
                .INIT          (1'b0),         // Initial value of Q: 1'b0 or 1'b1
                .SRTYPE        ("SYNC")        // Set/Reset type: "SYNC" or "ASYNC" 
            ) ODDR_inst (
                .Q             (rgmii_txd[i]), // 1-bit DDR output
                .C             (gmii_tx_clk),  // 1-bit clock input
                .CE            (1'b1),         // 1-bit clock enable input
                .D1            (gmii_txd[i]),  // 1-bit data input (positive edge)
                .D2            (gmii_txd[4+i]),// 1-bit data input (negative edge)
                .R             (1'b0),         // 1-bit reset
                .S             (1'b0)          // 1-bit set
            );        
        end
    endgenerate
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    相应的工程顶层代码的时钟部分也有改变,如下:

    
    module eth_udp_loop(
        input              clk_50   , //系统时钟
        //PL以太网RGMII接口   
        input              phy1_rgmii_rx_clk   , //RGMII接收数据时钟
        input              phy1_rgmii_rx_ctl, //RGMII输入数据有效信号
        input       [3:0]  phy1_rgmii_rx_data   , //RGMII输入数据
        output             phy1_rgmii_tx_clk   , //RGMII发送数据时钟    
        output             phy1_rgmii_tx_ctl, //RGMII输出数据有效信号
        output      [3:0]  phy1_rgmii_tx_data   , //RGMII输出数据          
        output             phy_reset   //以太网芯片复位信号,低电平有效   
        );
    
    //parameter define
    parameter  BOARD_MAC = 48'h00_11_22_33_44_55;   //开发板MAC地址 
    parameter  BOARD_IP  = {8'd192,8'd168,8'd10,8'd1};  //开发板IP地址
    parameter  DES_MAC   = 48'hff_ff_ff_ff_ff_ff; 	//目的MAC地址    
    parameter  DES_IP    = {8'd192,8'd168,8'd10,8'd2};	//目的IP地址 
    parameter IDELAY_VALUE = 0;	//输入数据IO延时,此处为0,即不延时(如果为n,表示延时n*78ps) 
    parameter  BOARD_POART =16'd1234;
    parameter  DES_POART   =16'd1234;
    
    //wire define
    wire          clk_200m   ; //用于IO延时的时钟              
    wire          gmii_rx_clk; //GMII接收时钟
    wire          gmii_rx_dv ; //GMII接收数据有效信号
    wire  [7:0]   gmii_rxd   ; //GMII接收数据
    wire          gmii_tx_clk; //GMII发送时钟
    wire          gmii_tx_en ; //GMII发送数据使能信号
    wire  [7:0]   gmii_txd   ; //GMII发送数据     
    wire          arp_gmii_tx_en; //ARP GMII输出数据有效信号 
    wire  [7:0]   arp_gmii_txd  ; //ARP GMII输出数据
    wire          arp_rx_done   ; //ARP接收完成信号
    wire          arp_rx_type   ; //ARP接收类型 0:请求  1:应答
    wire  [47:0]  src_mac       ; //接收到目的MAC地址
    wire  [31:0]  src_ip        ; //接收到目的IP地址    
    wire          arp_tx_en     ; //ARP发送使能信号
    wire          arp_tx_type   ; //ARP发送类型 0:请求  1:应答
    wire  [47:0]  des_mac       ; //发送的目标MAC地址
    wire  [31:0]  des_ip        ; //发送的目标IP地址   
    wire          arp_tx_done   ; //ARP发送完成信号
    wire          udp_gmii_tx_en; //UDP GMII输出数据有效信号 
    wire  [7:0]   udp_gmii_txd  ; //UDP GMII输出数据
    wire          rec_pkt_done  ; //UDP单包数据接收完成信号
    wire          rec_en        ; //UDP接收的数据使能信号
    wire  [31:0]  rec_data      ; //UDP接收的数据
    wire  [15:0]  rec_byte_num  ; //UDP接收的有效字节数 单位:byte 
    wire  [15:0]  tx_byte_num   ; //UDP发送的有效字节数 单位:byte 
    wire          udp_tx_done   ; //UDP发送完成信号
    wire          tx_req        ; //UDP读数据请求信号
    wire  [31:0]  tx_data       ; //UDP待发送数据
    wire sys_rst_n;
    wire clk_125m;
    wire clk_125m_90;
    
    //*****************************************************
    //**                    main code
    //*****************************************************
    assign gmii_tx_clk = clk_125m ;
    assign tx_start_en = rec_pkt_done;
    assign tx_byte_num = rec_byte_num;
    assign des_mac = src_mac;
    assign des_ip = src_ip;
    assign phy_reset = sys_rst_n;
    
    clk_wiz_0 instance_name
       (
        // Clock out ports
        .clk_200m(clk_200m),     // output clk_200m
        .clk_125m(clk_125m),     // output clk_125m
        .clk_125m_90(clk_125m_90),     // output clk_125m_90
        // Status and control signals
        .locked(sys_rst_n),       // output locked
       // Clock in ports
        .clk_in1(clk_50));      // input clk_in1
    
    //GMII接口转RGMII接口
    gmii_to_rgmii 
        #(
         .IDELAY_VALUE (IDELAY_VALUE)
         )
        u_gmii_to_rgmii(
        .idelay_clk    (clk_200m    ),
        .gmii_rx_clk   (gmii_rx_clk ),
        .gmii_rx_dv    (gmii_rx_dv  ),
        .gmii_rxd      (gmii_rxd    ),
        .gmii_tx_clk   (gmii_tx_clk ),
    	.gmii_tx_clk_90(clk_125m_90),
        .gmii_tx_en    (gmii_tx_en  ),
        .gmii_txd      (gmii_txd    ),
        .rgmii_rxc     (phy1_rgmii_rx_clk     ),
        .rgmii_rx_ctl  (phy1_rgmii_rx_ctl  ),
        .rgmii_rxd     (phy1_rgmii_rx_data     ),
        .rgmii_txc     (phy1_rgmii_tx_clk     ),
        .rgmii_tx_ctl  (phy1_rgmii_tx_ctl  ),
        .rgmii_txd     (phy1_rgmii_tx_data     )
        );
    
    //ARP通信
    arp                                             
       #(
        .BOARD_MAC     (BOARD_MAC),      //参数例化
        .BOARD_IP      (BOARD_IP ),
        .DES_MAC       (DES_MAC  ),
        .DES_IP        (DES_IP   )
        )
       u_arp(
        .rst_n         (sys_rst_n  ),             
        .gmii_rx_clk   (gmii_rx_clk),
        .gmii_rx_dv    (gmii_rx_dv ),
        .gmii_rxd      (gmii_rxd   ),
        .gmii_tx_clk   (gmii_tx_clk),
        .gmii_tx_en    (arp_gmii_tx_en ),
        .gmii_txd      (arp_gmii_txd),              
        .arp_rx_done   (arp_rx_done),
        .arp_rx_type   (arp_rx_type),
        .src_mac       (src_mac    ),
        .src_ip        (src_ip     ),
        .arp_tx_en     (arp_tx_en  ),
        .arp_tx_type   (arp_tx_type),
        .des_mac       (des_mac    ),
        .des_ip        (des_ip     ),
        .tx_done       (arp_tx_done)
        );
    
    //UDP通信
    udp                                             
       #(
        .BOARD_MAC     (BOARD_MAC),      //参数例化
        .BOARD_IP      (BOARD_IP ),
        .DES_MAC       (DES_MAC  ),
        .DES_IP        (DES_IP   ),
    	.BOARD_POART     (BOARD_POART),
    	.DES_POART       (DES_POART  )	
        )
       u_udp(
        .rst_n         (sys_rst_n   ),  
        .gmii_rx_clk   (gmii_rx_clk ),           
        .gmii_rx_dv    (gmii_rx_dv  ),         
        .gmii_rxd      (gmii_rxd    ),                   
        .gmii_tx_clk   (gmii_tx_clk ), 
        .gmii_tx_en    (udp_gmii_tx_en),         
        .gmii_txd      (udp_gmii_txd),  
        .rec_pkt_done  (rec_pkt_done),    
        .rec_en        (rec_en      ),     
        .rec_data      (rec_data    ),         
        .rec_byte_num  (rec_byte_num),      
        .tx_start_en   (tx_start_en ),        
        .tx_data       (tx_data     ),         
        .tx_byte_num   (tx_byte_num ),  
        .des_mac       (des_mac     ),
        .des_ip        (des_ip      ),    
        .tx_done       (udp_tx_done ),        
        .tx_req        (tx_req      )           
        ); 
    
    //同步FIFO
    sync_fifo_2048x32b u_sync_fifo_2048x32b (
        .clk      (gmii_rx_clk),  // input wire clk
        .rst      (~sys_rst_n),  // input wire rst
        .din      (rec_data  ),  // input wire [31 : 0] din
        .wr_en    (rec_en    ),  // input wire wr_en
        .rd_en    (tx_req    ),  // input wire rd_en
        .dout     (tx_data   ),  // output wire [31 : 0] dout
        .full     (),            // output wire full
        .empty    ()             // output wire empty
        );    
    
    //以太网控制模块
    eth_ctrl u_eth_ctrl(
        .clk            (gmii_rx_clk),
        .rst_n          (sys_rst_n),
        .arp_rx_done    (arp_rx_done   ),
        .arp_rx_type    (arp_rx_type   ),
        .arp_tx_en      (arp_tx_en     ),
        .arp_tx_type    (arp_tx_type   ),
        .arp_tx_done    (arp_tx_done   ),
        .arp_gmii_tx_en (arp_gmii_tx_en),
        .arp_gmii_txd   (arp_gmii_txd  ),              
        .udp_gmii_tx_en (udp_gmii_tx_en),
        .udp_gmii_txd   (udp_gmii_txd  ),              
        .gmii_tx_en     (gmii_tx_en    ),
        .gmii_txd       (gmii_txd      )
        );
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185

    A7上的资源消耗和性能表现如下:
    在这里插入图片描述
    由于工程中使用到了PLL和fifo,实际UDP部分所占资源更小;
    代码架构如下:
    在这里插入图片描述

    5.上板调试验证

    工程1验证:
    开发板连接
    在这里插入图片描述
    工程2验证:
    开发板连接
    在这里插入图片描述
    上位机收发显示如下:
    在这里插入图片描述

    6.福利:工程代码的获取

    福利:工程代码的获取
    代码太大,无法邮箱发送,以某度网盘链接方式发送,
    获取方式:私,或者文章末尾的V名片
    资料如下:
    在这里插入图片描述

  • 相关阅读:
    C++ 提高编程
    C++工资管理系统
    深度学习技巧应用29-软件设计模式与神经网络巧妙结合,如何快速记忆软件设计模式
    企业数据共享机制的建立,是一次企业内部的重新梳理
    【视觉基础篇】14 # 如何使用片元着色器进行几何造型?
    年底了,我劝大家真别轻易离职...
    基于SSM的“阳光”养老院管理系统-计算机毕业设计源码
    swift类型属性及其注意点
    XML 解析技术:DOM4j
    集线器-交换机-路由器
  • 原文地址:https://blog.csdn.net/qq_41667729/article/details/127951617