[控场AI]
· 8 分钟阅读· 4,164 字

用AI辅助实现FPGA上的TCP协议栈:Cursor实战全记录

用AI辅助实现FPGA上的TCP协议栈:Cursor实战全记录

在开源千兆以太网FPGA工程上,借助AI工具补全TCP客户端与ICMP模块,并验证实测吞吐与协议权衡。

本文介绍了一个基于开源千兆以太网FPGA工程的升级项目:在原有UDP基础上,通过"ICMP/TCP Hub"分发模块,将ICMP和TCP客户端作为独立模块接入IPv4层,以协议号区分三种上层协议。TCP客户端实现了三次握手、按字节递增的序列号、滑动窗口、慢启动、超时重传、零窗口探测等完整可靠传输机制。该项目的核心亮点在于开发方式:状态机代码、PPT与教学文档均借助Cursor等AI工具完成,并配置了时序优化Skill自动处理时序违例。实测验证了TCP/UDP回环无丢包及巨型帧支持,同时揭示了ACK响应延迟对吞吐的实质影响,并指出AI降低的是实现门槛而非理解门槛。

从UDP到TCP:给开源千兆以太网补上传输层

这个项目的起点是一个已经相对成熟的开源千兆以太网工程。原作者在此前的版本中已经完成了IP层和UDP功能,但缺少完整的传输层能力。这次的升级目标很明确:在原有工程基础上,把ICMP功能从IP核里独立出来,并新增一个完整的TCP客户端模块。

值得关注的不是TCP本身——这是一个几十年历史的协议——而是整个开发方式。作者坦言,TCP客户端的核心逻辑、状态机代码,乃至演示用的PPT和教学文档,都是借助AI(主要是Cursor)协助完成的。这代表了FPGA/硬件开发领域一个正在发生的变化:原本需要深厚协议理解才能手写的复杂状态机,现在可以通过与AI协作的方式快速落地。

整个工程基于LwIP风格的开源协议栈思路,利用协议栈预留的原始IP层接口,向上扩展出ICMP、TCP两套独立功能。作者还专门做了一个"ICMP/TCP Hub"模块,负责在IP层接口之上做分发——ICMP走协议号1,TCP走协议号6,UDP走协议号17,通过协议号区分数据流向。

然后TCP的话

模块架构:Hub分发 + 三个实验历程

从整体框图看,这套协议栈的层次是:以太网层 → IPv4 → 上层的ICMP / TCP / UDP。各协议的职责划分清晰:

  • ICMP:实现简单的Ping回复功能,主机Ping本机IP后返回Echo Reply包。这部分作者认为不需要过多性能测试,能通即可。
  • TCP:实现单连接的客户端角色,主动发起三次握手,支持按序交付、滑动窗口、超时重传等机制。
  • UDP:沿用原工程本身就有的端口回环功能。

需要留意一个设计细节:TCP和UDP都使用了相同的端口号1234,但因为IP层通过协议号进行区分,二者并不会冲突。这是协议栈设计中一个常见但容易被初学者忽略的点。

在新增历程方面,作者做了三个演示工程:一个TCP回环的FIFO历程、一个TCP测速DEMO(持续向PC发送压力数据包测吞吐),以及顶层的ICMP回复示例。测速思路与此前的万兆网项目一致。

服务端的IP地址配置

协议号(Protocol Number)是IPv4报头中的一个8位字段,由IANA统一分配,用于标识上层协议类型,使IP层能够正确地将数据包交付给对应的传输层或控制层模块。ICMP的协议号为1,TCP为6,UDP为17。在FPGA实现的协议栈中,"Hub"模块本质上是一个多路分发器(demultiplexer):它解析每个入站IP数据包报头中的Protocol字段,再根据该字段的值将载荷路由到对应的处理子模块。这种设计使各协议模块可以相互独立开发和测试,也与LwIP等软件协议栈中"raw API + protocol callback"的架构思路一脉相承。正因为分发发生在IP层而非端口层,TCP和UDP即便使用相同端口号1234也不会产生冲突——端口号只在各自协议内部具有意义。

TCP客户端实现的关键机制

作者在设计说明中梳理了TCP客户端实现的几个核心点,这也是TCP区别于UDP的难点所在。

序号以字节为单位递增

TCP序列号的计算是一个典型的理解盲区。作者特别强调:不管是发送4个字节作为一个报文,还是把这4个字节拆成4个单字节报文包,序列号都是加4——因为序列号以字节为单位递增,而非以报文包为单位。如果发送的是四段各4字节的报文,序列号就加16。这个细节直接决定了ACK确认和重传逻辑的正确性。

三次握手与连接维持

连接建立采用标准三次握手:IP核上电后,每隔约1毫秒(演示中主机侧约1秒)发送SYN包,主机侧若端口打开则应答,IP核再确认,完成连接。断开则走四次挥手流程。作者在演示中展示了连接断开后,IP核会以固定间隔持续发送SYN尝试重连的行为。

流控与可靠传输

K7平台上为了保证测速速率,配置了256的发送缓存。实现涵盖了慢启动、通知窗口、MSS选项协商、超时重传(SYN超时1秒、数据超时200毫秒)、按未确认指针重发、三次重复ACK触发快速重传、零窗口探测与保活等机制。这套机制基本覆盖了TCP可靠传输的核心要素。

AI生成的状态机代码

作者对AI生成代码的态度比较务实:状态机写得偏长,没有刻意让AI做优化,也没有加中文注释(因为中文注释容易导致代码乱码)。他建议学习者在使用时可以让AI补充注释,这样更便于理解。

慢启动(Slow Start)是TCP拥塞控制的初始阶段:连接建立后,发送方不会立即以最大窗口满速发送,而是将拥塞窗口(cwnd)初始化为1个MSS,每收到一个ACK就将cwnd加倍,直到触及慢启动阈值(ssthresh)后转入线性增长的拥塞避免阶段。MSS(Maximum Segment Size,最大报文段大小)则是在TCP三次握手期间通过选项字段协商的单次可传输的最大数据量,通常由链路MTU减去IP与TCP报头长度得出,标准以太网场景下典型值为1460字节,而启用巨型帧(Jumbo Frame)时MTU可达9000字节,MSS相应增大。零窗口探测(Zero Window Probe)用于解决接收方通告窗口为零后的死锁问题:发送方每隔一段时间发送1字节的探测包,等待接收方窗口重新打开后恢复正常传输。这些机制共同构成TCP在有损、变速网络环境下维持可靠高效传输的基础。

用Cursor做硬件开发的工作流

这个项目最有参考价值的部分,是作者对AI工具链的使用方式。他用的是Cursor,并配置了多种Skill和自定义功能包:

  • 时序优化Skill:当工程出现时序违例(timing violation)时,AI能找出违例路径,针对同一驱动做打拍(register retiming)处理,最终让工程实现无时序违例。
  • 持续优化Skill:从网上找来的现成技能脚本。
  • 自定义功能包:作者自己添加了写文档、注意事项提醒等能力,让AI自动生成教学GPT和设计说明文档。

作者给出的入门建议很接地气:如果不熟悉Cursor,可以先用豆包或DeepSeek广告这类工具,对工程做简单介绍,再一步步深入。核心能力不是写代码,而是"正确地去指挥AI"——比如要做TCP服务端,只要你会做客户端、懂得如何描述需求,让AI建立完整的测试仿真流程即可。

时序违例(Timing Violation)是FPGA综合与布局布线后的常见问题,指某条数据路径的传播延迟超过了目标时钟周期,导致触发器无法在时钟沿到来时稳定采样到正确数据。打拍(Pipeline Register / Register Retiming)是解决时序违例的标准手段之一:在过长的组合逻辑路径中插入额外的寄存器级,将原本一拍内完成的运算分散到多个时钟周期,以换取更高的可运行频率,代价是引入额外的流水线延迟。Cursor在此场景中的作用是:解析EDA工具(如Vivado)输出的时序报告,定位违例的起点与终点,自动在RTL代码中对应位置插入寄存器,然后重新触发综合验证。这类"分析报告→修改代码→验证"的迭代闭环,正是AI辅助硬件开发能显著节省时间的典型场景。

实测验证:吞吐与ACK响应的权衡

演示环节揭示了一个真实的工程权衡。

回环与巨型帧测试:TCP连接建立后,作者发送450包、接收450包,无丢包;UDP发送1194、接收1194也无丢包,且都支持巨型帧(演示中收发均为3695字节)。

测速结果:直接用网络调试助手做TCP测速时,速率只有约31兆——原因是调试助手回复ACK不够快,拖累了整体性能。为此作者让AI做了一个只回复ACK、不存储数据的轻量测试APP,速率随即接近满速。

这里暴露了TCP性能的本质瓶颈:作者观察到IP核发送4包后,主机侧才回复一次ACK(通过序列号差值验证——4包×各自载荷恰好对应4896字节的总和)。这种"累积确认"减少了ACK频率、降低卡顿,但也意味着实际TCP服务器若需要对数据做处理,ACK响应不可能这么快,吞吐会明显下降。换句话说,纯测速场景下接近满速的数字,并不能等同于真实业务场景的性能。

IP核向主机发送数据

TCP的累积确认(Cumulative ACK)机制允许接收方不必对每个数据段单独回复ACK,而是用一个ACK确认"到此为止所有字节均已收到",从而减少ACK报文数量、降低网络开销。然而这也意味着发送方在收到ACK之前,可发出的未确认数据量受制于接收窗口(rwnd)和拥塞窗口(cwnd)的较小值。当接收方处理能力有限、ACK回复较慢时,发送方会频繁触及窗口上限而被迫等待,吞吐量因此大幅下降。作者观察到"发送4包才收到1次ACK"的现象,正是接收端(网络调试助手)采用延迟确认(Delayed ACK)策略的体现——该策略通常等待最多40~200毫秒或积累到一定数据量再回复ACK,以减少小ACK包的发送频率。这在低速或交互场景下有益,但在高吞吐测速场景中反而成为瓶颈,作者因此专门编写了一个只回ACK不处理数据的轻量测试程序来规避此问题。

对硬件开发者的启示

这个项目本身规模不大,但它示范了一条正在成形的路径:在FPGA这类传统上高度依赖专家经验的领域,AI正在成为可用的协作者。TCP状态机、时序收敛、文档生成这些原本耗时的环节,都能在AI辅助下显著加速。

当然,前提依然是开发者自己理解TCP协议原理——AI能写出代码,但判断序列号逻辑是否正确、理解ACK响应对吞吐的影响、识别时序违例的根因,仍然需要人的专业判断。正如作者反复强调的,想真正学会TCP,还是要回去看协议文档。AI降低的是实现门槛,而非理解门槛。

分享:

相关推荐