目前网上fpga实现udp协议的源码满天飞,我这里也有不少,但用FPGA纯源码实现TCP的项目却很少,能上板调试跑通的项目更是少之又少,甚至可以说是凤毛菱角,但很不巧,本人这儿就有一个;
本设采用纯VHDL实现了10G万兆网TCP/IP协议栈,该协议栈分为TCP服务器核客户端,没有使用IP核,而是用vhdl源码实现协议栈,为了适应大批量数据传输和匹配不同型号FPGA的源语,本例程调用10G Ethernet Subsystem IP核作为PHY的作用,完成PMA+PCS的功能,10G Ethernet Subsystem IP内部包含了GT资源,可以满足10G收发的线速率要求,10G Ethernet Subsystem的用户接口为适应高速数据流的AXI4-Stream,AXIS FIFO做数据缓冲后数据与10G TCP/IP 协议栈交互,完成数据的收发,而10G TCP/IP 协议栈内部则完成TCP/IP 协议的具体数据组包和拆包的工作,TCP/IP 协议栈包含动态ARP、NDP、PING、IGMP (for multicast UDP)、DHCP serve、DHCP client等功能模块;
TCP/IP协议栈用户接口分为UDP和TCP接口,这里只需要用到TCP接口,感兴趣的朋友可以试试UDP玩儿,将TCP的收发端口用FIFO连接起来形成数据回环,外部指定FPGA开发板的IP地址、MAC地址、端口号、目的IP地址、目的端口号等信息,即可完成TCP协议栈数据回环的工程搭建;TCP/IP协议栈目前速率固定为10G,用户侧数据接口为AXI4-Stream,通过10G Ethernet Subsystem IP核完成10G线速率的TCP数据收发,提供服务器和客户端2套vivado工程源码;
本设计提供服务器和客户端2套vivado工程源码,本设计经过反复大量测试稳定可靠,可在项目中直接移植使用,工程代码可综合编译上板调试,可直接项目移植,适用于在校学生、研究生项目开发,也适用于在职工程师做项目开发,可应用于医疗、军工等行业的数字通信领域;
提供完整的、跑通的工程源码和技术支持;
工程源码和技术支持的获取方式放在了文章末尾,请耐心看到最后;
本工程及其源码即有自己写的一部分,也有网络公开渠道获取的一部分(包括CSDN、Xilinx官网、Altera官网等等),若大佬们觉得有所冒犯,请私信批评教育;基于此,本工程及其源码仅限于读者或粉丝个人学习和研究,禁止用于商业用途,若由于读者或粉丝自身原因用于商业用途所导致的法律问题,与本博客及博主无关,请谨慎使用。。。
目前我这里有大量UDP协议的工程源码,包括UDP数据回环,视频传输,AD采集传输等,也有TCP协议的工程,还有RDMA的NIC 10G 25G 100G网卡工程源码,对网络通信有需求的兄弟可以去看看:直接点击前往
其中千兆TCP协议的工程博客如下:
直接点击前往
1:纯VHDL实现,没有用到任何一个IP核;
2:移植性天花板,该协议栈可在Xilinx、Altera、Lattice、国产FPGA等各大FPGA型号之间任意移植,因为是没有任何IP和源语的纯VHDL代码实现;但例如10G Ethernet Subsystem这样的PHY侧IP核目前用的Xilinx的;
3:功能齐全,包含了服务器和客户端,分为2套vivado工程源码;TCP/IP协议栈本身包含了动态ARP、NDP、PING、IGMP (for multicast UDP)、DHCP serve、DHCP client等功能模块;
4:代码符合标准的IEEE 802.3协议,支持IPv4和IPv6;
5:GT资源时钟要求:156.25 MHz;
6:时序收敛很到位,考虑到TCP协议的复杂性和时序的高要求,所以没有采用时序收敛不强的verilog,而是VHDL,虽然阅读性可能会低一些,但用户只需要知道用户接口即可,并不需要去看内部的复杂代码;
7:动态ARP功能;
8:带ping功能;
9:支持多播;
支持节点数是TCP里面最重要的性能指标之一,这里需要重点讲述:
TCP节点数最大支持255个,通过parameter NTCPSTREAMS参数设置,但前提是你的FPGA资源能满足;NTCPSTREAMS参数可以在代码中自由修改,含义和用法,在代码里有详细的注释,为了防止不同编译器下中文注释出现乱码,注释均由英文书写,英语较差的兄弟可以直接某度翻译,位置如下:
本例程只用到了1个节点;
FPGA资源消耗是TCP里面最重要的性能指标之一,这里需要重点讲述:
FPGA资源消耗很低;以下举例:
以Xilinx旗下资源较小的Artix7平台为例,下只运行UDP时的资源消耗如下:
只运行TCP IPv4时跑1个服务器的资源消耗如下:
只运行TCP IPv4时跑2个服务器的资源消耗如下:
同时运行UDP和TCP IPv6时跑1个服务器的资源消耗如下:
数据吞吐率是TCP里面最重要的性能指标之一,这里需要重点讲述:
数据吞吐率由代码中的TCP_TX_WINDOW_SIZE和TCP_RX_WINDOW_SIZE两个参数决定,可自由配置,TCP_TX_WINDOW_SIZE和TCP_RX_WINDOW_SIZE的值决定Buffers sizes的大小,Buffers sizes的大小决定数据吞吐率,他们之间的关系为:
Buffers sizes=2**n Bytes,其中n=TCP_RX/TX_WINDOW_SIZE;
例如:当TCP_RX_WINDOW_SIZE=15时,Buffers sizes=32KB;
Buffers sizes与数据吞吐率Throughput的关系如下:
下表的测试前提为:NIC+FPGA延时为90us,如果延时更低,则吞吐率更大;
TCP_TX_WINDOW_SIZE和TCP_RX_WINDOW_SIZE可在代码中任意修改,含义和用法,在代码里有详细的注释,为了防止不同编译器下中文注释出现乱码,注释均由英文书写,英语较差的兄弟可以直接某度翻译,位置如下:
本例程设置为17,也就是128KB,对应吞吐率至少为9.3G;
此外,数据吞吐率还与MTU(Maximum Transmission Unit: maximum number of payload Bytes)参数的设置有关,MTU的计算公式如下:
MTU = (buffer size/4) + 60 bytes (IP/TCP header);
MTU的含义和用法,在代码里有详细的注释,为了防止不同编译器下中文注释出现乱码,注释均由英文书写,英语较差的兄弟可以直接某度翻译,位置如下:
本例程设置为1500;
不同的MTU设置在不同应用中的数据吞吐率如下:
延时性能是TCP里面最重要的性能指标之一,这里需要重点讲述:
延时与TCP数据包长直接相关,如果你对延时性能性能要求很高,则可以减少包长来有效降低延时,假设你的载包为X bytes,那么你的收发延时关系如下:
发送延时=0.5 + 2X÷125 µs;
接收延时=0.5 + X÷125 µs;
当包长为2408 bytes,发送延时为1.734us,测试如下:
TCP/IP 协议栈代码架构如下:
所有模块均由vhdl源码实现,没有使用任何IP,可以移植到任何平台的FPGA上;模块的具体细节在后续章节讲述;
用户接口分为配置接口和用户接口,用户接口又分为跟应用程序对接的接口和跟MAC对接的用户接口;框图如下:
配置接口主要完成一些开关功能,例如使能IPv6、DHCP、IGMP等,具体看代码及注释;代码层面如下:
与MAC对接的用户接口不需要讲述,直接与MAC对接即可;
UDP协议的用户接口个人感觉不太重要,因为这里有价值的是TCP协议,所以直接介绍TCP协议的用户接口,TCP协议的用户接口分为接收和发送,都是可与AXI4-Stream对接的类AXI4-Stream接口,代码中有用法,你一看就懂,很简单;
代码的端口中,有一些缩写可能不好理解,下面给出解释:
顶层模块将各个分模块例化在一起,没什么可讲的,在代码中的位置如下:
PACKET_PARSING_10G模块功能是解析从MAC接收到的数据包,并有效地提取与多个协议相关的关键信息。解析是动态进行的,而不存储数据;在代码中的位置如下:
ARP_10G模块的作用是检测ARP请求,并组包一个ARP响应以太网数据包传输到MAC;在代码中的位置如下:
DHCP_SERVER_10G模块的作用是管理一个IPv4地址池,它会根据请求将它们动态地分配给DHCP客户端,服务器还提供子网掩码、网关地址和DNS地址等;
当选择动态寻址时,DHCP_CLIENT_10G模块从远程DHCP服务器请求IPv4地址,服务器还提供子网掩码、网关地址和DNS地址;
在代码中的位置如下:
IGMP_REPORT_10G模块的作用是以广播形式发送GMP成员身份报告,IGMP_QUERY.vhd模块响应成员资格查询。在代码中的位置如下:
ICMPV6_10G模块的作用是动态检测传入的IP/ICMPv6请求,并使用本地MAC地址信息进行响应。在代码中的位置如下:
PING_10G模块的作用是检测ICMP回波(ping)请求,并组装一个ping回波以太网数据包,以传输到MAC,Ping同时适用于IPv4和IPv6。
WHOIS2_10G模块的作用是生成一个ARP请求广播包(IPv4)或一个请求消息(IPv6),请求由其IP地址标识的目标用其MAC地址响应。
两个模块共同构成了我们经常用到的ping功能;
在代码中的位置如下:
ARP_CACHE2_10G模块是一个共享的路由表,它存储最多128个IP地址及其关联的48位MAC地址和一个“实时的”时间戳。此模块将确定目标IP地址是否为本地地址。在后一种情况下,将返回网关的MAC地址,只存储有关本地地址的记录(例如,不是WAN地址,因为这些地址通常指向路由器MAC地址);仲裁电路用于仲裁来自多个传输实例的路由请求。在代码中的位置如下:
UDP_TX_10G模块的作用是将一个数据包封装到一个UDP帧中,即从任何端口到任何端口/IP目标的地址。同时支持IPv4和IPv6。通常例化一次,而不管源或目标UDP端口的数量如何。然而,通过修改顶层代码(搜索TX_MUX_00x和RT_MUX_00x)可以很容易地实现例化多个,在代码中的位置如下:
UDP_RX_10G模块的作用是验证接收到的UDP帧,并提取其中的数据包。由于验证是在接收到的数据通过时动态执行的(没有存储),因此在数据包结束时提供了有效性确认信号。在代码中的位置如下:
TCP_SERVER_10G模块是TCP协议的核心。它可参数化配置,以支持ntcp流并发TCP连接。它本质上是处理TCP服务器的TCP状态机:首先监听来自远程TCP客户端的连接请求,建立和删除连接,并在建立连接时管理流控制和字节排序。由于这是一个服务器,它事先不预先知道协议是IPv4还是IPv6(它依赖于客户端),所以每个服务器有两个IP地址,每个IP版本一个。此模块在TCP服务器的vivado工程中才有,在代码中的位置如下:
TCP_CLIENTS_10G模块是TCP协议的核心。它可参数化配置,以支持ntcp流并发TCP连接。它本质上是处理TCP客户端的TCP状态机:它可以根据用户的请求启动与远程TCP服务器的连接。在建立连接时,它管理流控制和字节排序。此模块在TCP客户端的vivado工程中才有,在代码中的位置如下:
TCP_TX_10G模块的作用是格式化TCP tx帧,包括所有层:TCP,IP,MAC/以太网。它对所有并发流都是通用的,因此只实例化一次。在代码中的位置如下:
TCP_TXBUF_10G模块的作用是将TCP tx有效负载数据存储在单独的弹性缓冲区中,每个传输流对应一个。缓冲区大小是在合成之前通过ADDR_WIDTH通用参数配置的。在代码中的位置如下:
TCP_RXBUFNDEMUX_10G模块解复用了几个TCP rx流。该模块有两个目标: (1)暂时保持一个接收到的TCP帧,直到在帧结束时确认其有效性。如果无效则丢弃,如果无效则丢弃进一步处理。(2)基于目标端口号来分解多个TCP流。在代码中的位置如下:
工程代码中需要定义开发板的MAC、IP地址以及端口号等信息,包括服务器和客户端的;
服务器和客户端的定义修改在代码中的位置一样的,如下:
开发板本地 IP、MAC地址定义修改位置如下:
network_top.v
远端 IP、MAC地址定义修改位置如下:
top.v
详细设计方案如下:
为了测试需要,你得准备一张带SFP光口的10G网卡,某宝价格大概两三百块,10G网卡的PCIE连接器插在电脑主板上,装好驱动,10G网卡的SFP光口与FPGA开发板的SFP光口相连,数据进入FPGA后,首先经过10G Ethernet Subsystem IP核,该IP背部调用了GT资源,实现了PMA+PCS的功能,输出AXIS数据流的MAC数据,MAC数据经过AXIS FIFO缓冲后进入10GTCP/IP 协议栈,数据出来后再经过回环FIFO发送出去,形成回环;
由于TCP协议栈前面已经详细讲过了,这里重点讲讲10G Ethernet Subsystem这个IP,IP调用如下:
开发板:Xilinx–>KU–>xcku115-flvd1924-2-i;
开发环境:Vivado19.1;
输入\输出:10G TCP 网络通信;
测试项:TCP服务器测试;
工程代码架构如下:
FPGA资源消耗和功耗预估;
开发板:Xilinx–>KU–>xcku115-flvd1924-2-i;
开发环境:Vivado19.1;
输入\输出:10G TCP 网络通信;
测试项:TCP客户端测试;
工程代码架构如下:
FPGA资源消耗和功耗预估;
以server工程为例;
连接如下:
首先设置电脑端IP如下:
下载bit,如下:
打开cdm,输入 ping 192.168.2.10,如下:
打开网络调试助手并配置,单次发送数据测试结果如下:
循环发送数据测试结果如下,1秒时间间隔循环:
福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:私,或者文章末尾的V名片。
网盘资料如下: