FPGA学习笔记(7)以太网UDP数据报文发送电路设计(一)
参考资料:【正点原子】开拓者之FPGA开发指南 V3.2
一.协议栈
1.1 最小可用小协议栈(mini stack)
在网线上真正跑的是 以太网帧(Ethernet Frame)。UDP 只是帧里面的“内容的一部分”。
手册也用“逐层封装”的说法讲得很明确:
MAC 帧的数据段是 IP 数据报;IP 的数据段是 UDP 报文;UDP 的数据段才是用户数据。
所以做“以太网 UDP 数据报文发送电路”,本质是在 FPGA 里实现一个“最小可用小协议栈(mini stack)”:
做一个 “能和电脑互通的最小子集”:
-
L2(链路层):会收发以太网帧 + 生成正确 CRC32/FCS(不然网卡丢包)
-
ARP:至少能让电脑通过 ARP 得到你的 MAC(不然电脑发不了 IP/UDP 给你)
-
L3 IPv4(网络层):能解析/生成 IP 头 + 校验和(不然对方丢 IP 包)
-
L4 UDP(传输层):能正确组/拆 UDP 头和数据(校验和可先不做,后面再补)
1.2 ARP/ICMP 必要性
1)为什么 UDP 之前一定要先有 ARP
你在以太网上真正发出去的是 以太网帧(Ethernet Frame),帧头里必须有 目的 MAC 地址。
-
上位机应用(比如你写 UDP 调试助手)通常只知道“对方 IP”,但网卡转发帧必须靠“目的 MAC”。
-
ARP 的作用就是:根据目的 IP 自动获取目的 MAC,并把结果缓存起来(ARP 缓存表/ARP 映射),下次就不用再查了。手册也明确写了:ARP 是“根据 IP 获取 MAC”,且缓存会过期,静态绑定维护很麻烦。
所以你想做 UDP 工程时,如果没有 ARP,就只能:
-
方案 A:静态写死 MAC(很不通用,换电脑/换网卡 MAC 就变了)
-
方案 B:手动在电脑里静态绑 ARP 表(更麻烦,维护成本高)
结论:做 UDP 通信时,ARP 基本是“必选地基”。
2)为什么会在 UDP 前先做 ICMP(ping)
严格讲:UDP 不一定“必须”实现 ICMP 才能收发 UDP。
但教程一般会先做 ICMP 的原因很现实——ping 是最便宜、最直观的“网络连通性自检”:
-
ping 的请求/应答就是 ICMP Echo(ICMP Echo请求与应答):Type=0x08 请求,Type=0x00 应答,并且要匹配序列号等字段。
-
手册对 ICMP 实验任务写得很直白:电脑 ping FPGA,FPGA 收到后再回给电脑。
-
更关键的是:电脑在 ping 之前也会先 ARP。所以 ICMP 实验天然把“ARP + IP + ICMP”这条链路都验证了一遍:
-
ARP 不通 → ping 根本发不到 FPGA
-
IP 头/校验不对 → ping 会失败
-
ICMP 组包不对 → 也失败
这对你后续做 UDP 是非常好的“保命测试”。
-
另外,手册也说明了:ICMP 相比 ARP 工程,替换了控制模块并增加了 FIFO 和 ICMP 顶层。
这一步就是在为后续 UDP 的“多协议切换/复用”打基础。
1.3 把“协议栈”落到 FPGA 工程思路上(整体架构)

二 ARP 实验任务:
-
电脑发 ARP Request → FPGA 回 ARP Reply
-
按下开发板触摸按键 TPAD → FPGA 主动发 ARP Request → 电脑回 ARP Reply
结构:

三 顶层 eth_arp_test.v
3.1 端口:RGMII 物理口 + 复位 + 触摸按键
-
eth_rxc / eth_rx_ctl / eth_rxd[3:0]:RGMII 接收 -
eth_txc / eth_tx_ctl / eth_txd[3:0]:RGMII 发送 -
sys_rst_n:系统复位 -
touch_key:触摸按键(触发 FPGA 主动 ARP 请求) -
eth_rst_n:给以太网芯片的复位脚(顶层直接assign eth_rst_n = sys_rst_n;)
3.2 四个关键参数(决定你电脑怎么配 IP)
顶层写死了:
-
开发板 MAC:
00-11-22-33-44-55 -
开发板 IP:
192.168.1.10 -
默认目的 MAC:广播
ff:ff:ff:ff:ff:ff(用于 ARP Request) -
默认目的 IP:
192.168.1.102(一般设成你电脑 IP)
这和手册后面验证用的 IP 是一致的(比如 ping 192.168.1.10)
3.3 PLL:“相位偏移 eth_rxc”
顶层例化:
-
pll u_pll(.inclk0(eth_rxc), .c0(eth_rxc_deg))
含义:把 RGMII 接收时钟 eth_rxc 做相位偏移,再送进 gmii_to_rgmii 的 rgmii_rxc。
目的很实际:RGMII 是 DDR(上下沿采样),为了采样更稳,常会把采样时钟挪到数据眼图中间(工程里就叫 eth_rxc_deg)。
3.4 gmii_to_rgmii:DDR ↔ SDR 转换
-
RGMII:4bit DDR(上升沿+下降沿各 4bit)
-
GMII:8bit SDR(每个时钟上升沿 8bit)
“翻译器”:
-
PHY 过来的是 RGMII:
eth_rxd[3:0]+eth_rx_ctl+eth_rxc -
转成内部更好处理的 GMII:
gmii_rxd[7:0]+gmii_rx_dv+gmii_rx_clk -
发包时反过来:
gmii_txd/gmii_tx_en→eth_txd/eth_tx_ctl
gmii_to_rgmii 内部就是:
-
手册还给了实例:rgmii_rx:用ALTDDIO_IN把 DDR “拆成” 上升沿数据dataout_h和下降沿数据dataout_lddi_x4把rgmii_rxd[3:0]转成gmii_rxd[7:0],ddi_x1把rgmii_rx_ctl转成gmii_rx_dv -
rgmii_tx:用ALTDDIO_OUT把 GMII 的 8bit SDR “合成” 4bit DDR 输出到 RGMII(手册说这块用 ALTDDIO_OUT)



3.5 arp + arp_ctrl:谁负责协议,谁负责“什么时候发”
-
arp:负责解析 ARP、组 ARP 帧、发 Request/Reply。手册明确:ARP 顶层 =arp_rx+arp_tx+crc32_d8 -
arp_ctrl:负责“按键触发 / 收到对方 ARP 后触发应答”等控制流程
顶层还有一行非常关键:
-
assign des_mac = src_mac; -
assign des_ip = src_ip;
意思:收到谁的 ARP(对方 MAC/IP)就把它当成下一次发送的目的 MAC/IP。
所以你按 TPAD 主动发 ARP Request 时,目标就是“最近一次学到的对端”(或默认目的 IP/MAC 配合控制逻辑)。
四 下载后怎么验证
4.1 先让 FPGA 主动发 ARP(按 TPAD)
你按 TPAD 后,电脑 ARP 缓存表里会出现开发板的 IP/MAC 映射。手册也提示失败就检查:
-
网线是否连接开发板 PL 网口(GE_PL)
-
是否按下 TPAD 触发
-
电脑网口是否支持千兆(不支持可能失败)
4.2 再验证“电脑发 ARP → FPGA 回应答”(用 ping 间接触发 ARP)
手册给的步骤是:
-
先把 ARP 缓存删掉:
arp -d(最好管理员运行,否则可能删不掉) -
手册提醒:因为这个实验没做 ICMP,所以 ping 会超时,但 ARP 过程会发生,开发板会回 ARP Replyping 192.168.1.10让电脑发起 ARP 请求 -
再
arp -a查看是否学到了开发板 MAC
4.3 用 Wireshark 抓包(看到“真实数据包”你会瞬间通透)
手册步骤:
-
打开 Wireshark,选网卡开始抓包
-
然后按下 TPAD,就能在 Wireshark 里抓到开发板发出的包
五 路线 B:新建工程 + 自己生成 IP 核 + 自己约束
准备工作:
硬件:FPGA开发板(我的是正点原子开拓者FPGA),
PTD03下载器,
千兆USB转网口(有的笔记本没有网口),
千兆网线

B1. 新建 Quartus 工程
-
New Project Wizard → 选择工程目录→ 选芯片型号

B2. 添加源码
这里不自己编写源码了,用原子的ARP源码



开拓者FPGA开发板EP4CE10 — 正点原子资料下载中心 1.0.0 文档
加进工程:
-
rtl/eth_arp_test.v,arp_ctrl.v -
rtl/arp/*.v -
rtl/gmii_to_rgmii/*.v

B3. 生成/加入 IP 核
B3.1 这个工程里核心 IP 主要是两类:
① DDR 采样/输出用的 ALTDDIO
-
手册还解释了关键端口含义:ALTDDIO_IN(手册给了生成思路:RGMII 是 4 位输入所以 Width=4;也会用 1 位版本给rx_ctl)datain/inclock/dataout_h/dataout_l -
ALTDDIO_OUT:用于发送侧 SDR→DDR(手册说 rgmii_tx 用 ALTDDIO_OUT)
你需要生成四个变体(工程里也叫这些名字):
-
ddi_x4:4bit 输入 DDR -
ddi_x1:1bit 输入 DDR -
ddo_x4:4bit 输出 DDR -
ddo_x1:1bit 输出 DDR
说明:
关于RGMII,MII接口不再梳理,之前文章学习过,这里直接用IP核

② PLL(给 eth_rxc 做相位偏移)
-
顶层例化了
pll,输入eth_rxc,输出eth_rxc_deg(相位偏移后的时钟) -
IP 核就是“厂家已经实现好的硬件模块生成器”,你在 Quartus 里点几下配置,它就会吐出
.v/.qip等文件给你例化用。
B 3.2 生成5 个 IP 核(4 个 DDIO + 1 个 PLL)
0)先准备:建一个 ipcore 文件夹
在你新工程目录下建一个文件夹,比如:
-
...\your_project\ipcore\
后面所有 IP 都生成到这里,文件不会乱。
1)生成 DDR 输入 IP:ddi_x4(ALTDDIO_IN,宽度4)
用途:RGMII 的 rxd[3:0] DDR 采样成 dataout_h/dataout_l
① 打开向导
-
Quartus 顶部菜单:Tools → ip catalog
② 选 IP 类型
-
搜 ALTDDIO → ALTDDIO_IN
-
选中 ALTDDIO_IN → Next
③ 设置输出文件名 & 语言
-
“Name” 填:
ddi_x4 -
“Directory” 选你刚建的:
...\ipcore\ -
HDL 语言选:Verilog HDL
-
Next
④ 关键参数(Width)
-
找到 Width(数据位宽)设为:
4 -
其余选项保持默认(不要启用 reset/enable/oe 等)
-
Next → Finish(或一直 Next 到 Finish)
-
弹出窗口-确定加入工程
⑤ 生成完你应该看到这些文件(正常现象)
在 ipcore 文件夹里会出现:
-
ddi_x4.v -
ddi_x4.qip -
以及一些
.cmp/.inc/.bsf/.ppf等(可有可无)





说明:
很关键的“不要勾”的点(保证端口匹配源码)
向导里如果出现这些选项:
-
Output enable (oe) / Use oe:不要勾
-
Reset (aclr/aset/sclr/sset):不要勾
-
Clock enable:不要勾
因为源码里例化 ddo_x4 只连了这四个端口:datain_h, datain_l, outclock, dataout
如果你勾了 oe/reset,生成的模块端口会变多,源码就对不上了。
2)生成 DDR 输入 IP:ddi_x1(ALTDDIO_IN,宽度1)
用途:RGMII 的 rx_ctl 也是 DDR(1bit)
完全重复上面步骤,只改两处:
-
Name:
ddi_x1 -
Width:
1 -

3)生成 DDR 输出 IP:ddo_x4(ALTDDIO_OUT,宽度4)
用途:把 GMII txd[7:0] 拆成 datain_h[3:0] 和 datain_l[3:0] 输出到 RGMII txd[3:0]
4)生成 DDR 输出 IP:ddo_x1(ALTDDIO_OUT,宽度1)
用途:输出 tx_ctl,以及用它“拼”一个 rgmii_txc(源码里 ddo_x1_clk)
重复第3步,只改:
-
Name:
ddo_x1 -
Width:
1
5)生成 PLL:pll(ALTPLL)
用途:eth_rxc → 生成相位偏移的 eth_rxc_deg 给接收采样更稳
这里不自己生成了,因为原子手册里也没在本节介绍125MHZ pll生成步骤,但是前面有专门章节IP核之PLL实验,这里偷下懒不想复习自己整了



B4. 管脚/IO 约束(非常关键)
示例工程里给了 doc/eth_arp_test.tcl(里面是 pin 绑定 + IO_STANDARD)。你可以:
-
Quartus 里导入 tcl(或把内容复制到
.qsf) -
或者 Pin Planner 手动填引脚
这一步决定:
-
eth_rxc / eth_rxd[3:0] / eth_rx_ctl / eth_txc / eth_txd[3:0] / eth_tx_ctl / eth_rst_n / sys_rst_n / touch_key到底接到 FPGA 哪些管脚
说明:
输入、输出端口进行管脚分配,参考原理图来对引脚进行分配。三种方法,
Pin Planner界面,TCL文件,或把内容复制到 .qsf

这里用原子doc文档里TCL文件,运行TCL文件自动分配引脚


运行


B5. 编译 + 下载
-
Compile 全流程跑完
-
Programmer 选择硬件下载器(USB-Blaster)
-
选
.sof下载到板子



B6.验证现象(最短路径)
-
电脑网卡设置静态 IP:
192.168.1.102,掩码255.255.255.0 -
网线连开发板 GE_PL 口
-
CMD:
-
arp -d * -
ping 192.168.1.10(ping 可能超时没关系) -
arp -a看是否出现192.168.1.10 -> 00-11-22-33-44-55
-
-
Wireshark:过滤器输入
arp,按板子 TPAD,看是否有 ARP Request/Reply
0)连线下载
将下载器一端连接电脑,另一端与开发板上的JTAG下载口连接,将网线一端连接开发板的网口,另 一端连接电脑的网口,接下来连接电源线,并打开开发板的电源开关。下载
1)判断硬件

但是我的电脑下载成功但电脑没反应,排查:

发现是原因Windows 有时不会像手册截图那样明显弹“未识别网络”,



1)把电脑以太网改成静态 IP(否则后面 ARP 根本不一定发得对)
按工程默认参数,你电脑应设:
-
IP:
192.168.1.102 -
子网掩码:
255.255.255.0 -
网关:先留空都行
手册明确强调:必须手动设置电脑 IP,不能自动获取,并且就是设成 192.168.1.102。
这里忘记截图了,拿手册上的吧,以太网右键-属性-设置:

2)用命令验证
以管理员打开 CMD(手册也强调要管理员)。管理员身份运行应该不能快捷键了,

验证说明直接截图手册了,说的很清楚
任务一:电脑发 ARP Request → FPGA 回 ARP Reply


任务二:按下开发板触摸按键 TPAD → FPGA 主动发 ARP Request → 电脑回 ARP Reply

说明:ping是一个十分强大的TCP/IP工具,它可以用来检测网络的连通情况和分析网络速度。ping命令是一个固定格式的ICMP(Internet控制报文协议)请求数据包,之后会发起ARP请求命令,所以这里是通过ping命令来间接发起ARP请求。由于开发板并没有实现ICMP协议,因此在ping时会请求超时,但是在ping的过程中发起的ARP请求,开发板会响应并返回ARP应答数据。

我的验证:
说明,跟手册有点验证过程不一样是,我刚开始电脑没反应时候就按触摸按键了,然后开发板发ARP请求了,电脑获取MAC了,所有我的一开始查看ARP缓存表就有开发板MAC和IP.


3)Wireshark(以太网通信时经常使用的抓包软件):
按板子 TPAD,看是否有 ARP Request/Reply


更多推荐




所有评论(0)