> 技术文档 > FPGA UDP 回环实验全解析:从协议原理到工程实现_fpga以太网回环

FPGA UDP 回环实验全解析:从协议原理到工程实现_fpga以太网回环


FPGA UDP 回环实验全解析:从协议原理到工程实现

  • 实现任务
  • 一、UDP 协议与以太网通信基础
  • 二、以太网 UDP 数据回环实验
    • 2.1 系统架构设计
    • 2.2 时钟管理模块
    • 2.3 RGMII→GMII 转换模块
    • 2.4 ARP协议处理模块
    • 2.5 UDP协议处理模块
      • 2.5.1UDP接收模块:
      • 2.5.2UDP发送模块
    • 2.6 以太网控制模块

在 FPGA 开发中,以太网通信是实现设备联网与数据交互的核心能力,而 UDP 协议凭借 “无连接、低延迟” 的特性,在工业控制、实时数据采集等场景中被广泛应用。本文以正点原子UDP回环工程为基础,从理论原理到实验细节,完整讲解 FPGA UDP 回环实验的设计思路、模块架构与验证方法,帮助初学者快速掌握 FPGA 以太网开发的核心逻辑。

实现任务

本节实验任务是上位机通过网口调试助手发送数据给FPGA,FPGA通过PL端以太网接口接收数据并将接收到的数据发送给上位机,完成以太网UDP数据的环回

一、UDP 协议与以太网通信基础

UDP(User Datagram Protocol,用户数据报协议)是一个简单的面向消息的传输层协议,尽管UDP提供标头和有效负载的完整性验证(通过校验和),但它不保证向上层协议提供消息传递,并且UDP层在发送后不会保留UDP 消息的状态。因此,UDP有时被称为不可靠的数据报协议。如果需要传输可靠性,则必须在用户应用程序中实现,其核心特点如下:

  1. 无连接性:通信前无需建立连接,通信后无需断开连接,减少协议开销;
  2. 低开销:头部仅 8 字节(远小于 TCP 的 20 字节),包含源端口、目的端口、数据长度和校验和四个字段;;
  3. 高效性:无确认、重传、流量控制机制,适用于实时性要求高的场景(如视频流、工业控制指令);
  4. 不可靠性:不保证数据按序到达或不丢失,需上层应用按需处理可靠性问题。

UDP数据表格式

二、以太网 UDP 数据回环实验

2.1 系统架构设计

本实验的顶层模块包含以下主要组成部分:

  • 时钟管理模块:生成200MHz时钟用于IO延时控制
  • GMII转RGMII模块:实现GMII与RGMII接口协议转换
  • ARP处理模块:处理地址解析协议
  • UDP处理模块:实现UDP数据包处理
  • FIFO缓存:数据缓冲和时钟域转换
  • 以太网控制模块:协调ARP和UDP模块的工作

系统框图
在这里插入图片描述

2.2 时钟管理模块

将统主时钟(50MHz)通过 MMCM/PLL 生成用于 RGMII 接收数据的 IO 延时补偿(IDELAY)
代码片

//MMCM/PLLclk_wiz_0 u_clk_wiz_0 ( .clk_out1(clk_200m), // output clk_out1 .reset(~sys_rst_n), // input reset .locked(locked), // output locked .clk_in1(sys_clk) ); 

2.3 RGMII→GMII 转换模块

实现物理层信号转换 —— 将 PHY 的 RGMII(4 位,双边沿采样)信号转换为 FPGA 内部易于处理的 GMII(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发送数据  );

2.4 ARP协议处理模块

ARP(Address Resolution Protocol,地址解析协议)是一种用于将网络层地址(如 IP 地址)解析为数据链路层地址(如 MAC 地址)的协议。(因为以太网帧传输需要 MAC 地址,而非 IP 地址)。
主要包含三个模块,ARP接收模块arp_rx,ARP发送模块arp_tx,CRC校验模块。
在这里插入图片描述

2.5 UDP协议处理模块

UDP顶层模块例化了UDP接收模块(udp_rx)、UDP发送模块(udp_tx)和CRC校验模块(crc32_d8)

2.5.1UDP接收模块:

以太网帧的结构(从 PHY 接收的顺序)为:前导码(7字节) + 帧起始符(1字节) + 目的MAC(6字节) + 源MAC(6字节) + 帧类型(2字节) + IP包(≥20字节) + UDP包(≥8字节) + 数据(用户数据) + CRC(4字节)。
采用7 个状态的三段式状态机,状态机的每个状态对应 “解析流程的一个阶段”。
在这里插入图片描述这里需要注意的一点是,在中间状态如前导码错误、MAC地址错误以及IP地址错误时跳转到st_rx_end状态而不是跳转到st_idle状态。因为中间状态在解析到数据错误时,单包数据的接收还没有结束,如果此时跳转到st_idle状态会误把有效数据当成前导码来解析,所以状态跳转到st_rx_end。而eth_rxdv信号为0时,单包数据才算接收结束,所以st_rx_end跳转到st_idle的条件是eth_rxdv=0,准备接收下一包数据。
代码片

//(三段式状态机)同步时序描述状态转移always @(posedge clk or negedge rst_n) begin if(!rst_n) cur_state <= st_idle; else cur_state <= next_state;end//组合逻辑判断状态转移条件always @(*) begin next_state = st_idle; case(cur_state) st_idle : begin  //等待接收前导码 if(skip_en)  next_state = st_preamble; else next_state = st_idle; end st_preamble : begin  //接收前导码 if(skip_en)  next_state = st_eth_head; else if(error_en)  next_state = st_rx_end; else next_state = st_preamble; end st_eth_head : begin  //接收以太网帧头 if(skip_en)  next_state = st_ip_head; else if(error_en)  next_state = st_rx_end; else next_state = st_eth_head;  end st_ip_head : begin //接收IP首部 if(skip_en) next_state = st_udp_head; else if(error_en) next_state = st_rx_end; else next_state = st_ip_head;  end st_udp_head : begin  //接收UDP首部 if(skip_en) next_state = st_rx_data; else next_state = st_udp_head; end st_rx_data : begin //接收有效数据 if(skip_en) next_state = st_rx_end; else next_state = st_rx_data; end st_rx_end : begin //接收结束 if(skip_en) next_state = st_idle; else next_state = st_rx_end;  end default : next_state = st_idle; endcase  end 

2.5.2UDP发送模块

UDP发送模块按照UDP的数据格式发送数据,并将32位用户数据转成8位数据的功能,也就是接收模块的逆过程。同样也非常适合使用状态机来完成发送数据的功能。发送模块和接收模块有很多相似之处,同样使用三段式状态机来发送以太网包,从下图可以比较直观的看到每个状态实现的功能以及跳转到下一个状态的条件。
在这里插入图片描述

2.6 以太网控制模块

如果输入的arp_rx_done(ARP接收完成信号)为高电平,且arp_rx_type为低电平(ARP接收类型为请求)时,表示接收到ARP请求数据包,此时拉高arp_rx_flag信号;当arp_rx_flag为高电平,且udp_tx_busy(当前UDP发送模块处于空闲状态)信号为低电平时,此时拉高arp_tx_en信号,开始控制ARP顶层模块发送ARP应答数据包,并拉低protocol_sw信号,此时GMII发送端口信号和ARP顶层模块的发送端口信号相连。
代码片

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_tx_start_en(tx_start_en ), .udp_tx_done (udp_tx_done ), .udp_gmii_tx_en (udp_gmii_tx_en), .udp_gmii_txd (udp_gmii_txd ), .gmii_tx_en (gmii_tx_en ), .gmii_txd (gmii_txd ) );