1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-301505-1-1.html 4)对正点原子FPGA感兴趣的同学可以加群讨论:994244016 5)关注正点原子公众号,获取最新资料更新
UDP是一种面向无连接的传输层协议,属于TCP/IP协议簇的一种。UDP具有消耗资源少、通信效率高等优点,通常用来传输音频、视频等对实时性要求高的场合。本章我们来学习如何通过领航者ZYNQ开发板实现UDP通信的功能。 本章分为以下几个章节: 1.1 简介 1.2 实验任务 1.3 硬件设计 1.4 程序设计 1.5 下载验证 1.1 简介 UDP概述 UDP(User Datagram Protocol),即用户数据报协议,是一种面向无连接的传输层协议。无连接是指在传输数据时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输(如视频会议等)都会采用UDP协议进行传输,这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。 UDP和TCP是传输层中非常重要的两个协议,位于OSI(Open System Interconnection,开放式系统互联)参考模型中的第四层(传输层),是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,位于IP协议层(网络层)之上。OSI将计算机网络体系结构分为七层:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,OSI参考模型如下图所示。
图 7.5.13.1 OSI参考模型 以太网UDP传输单包数据的格式由图 7.5.13.2所示。从图中可以看出,以太网的数据包就是对各层协议的逐层封装来实现数据的传输。用户数据打包在UDP协议中,UDP协议又是基于IP协议之上的,IP协议又是走MAC层发送的,即从包含关系来说:MAC帧中的数据段为IP数据报,IP报文中的数据段为UDP报文,UDP报文中的数据段为用户希望传输的数据内容。接下来我们逐个来向大家介绍不同层的数据格式。
图 7.5.13.2 以太网UDP传输数据包格式 其中以太网的帧格式在“以太网ARP测试实验”中已经向大家作了详细的介绍,如果对以太网帧格式不熟悉的话,可以参考“以太网ARP测试实验”。IP协议(互联网分组交换协议)是TCP/IP协议簇中非常重要的一个协议,下面我们来熟悉下IP协议。 IP协议 IP协议是TCP/IP协议簇中的核心协议,也是TCP/IP协议的载体,IP协议规定了数据传输时的基本单元和格式。从前面介绍的图 7.5.13.2中可以看出,IP协议位于以太网MAC帧格式的数据段,IP协议内容由IP首部和数据字段组成。所有的TCP、UDP及ICMP数据都以IP数据报格式传输,IP数据包格式如图 7.5.13.3所示。
图 7.5.13.3 IP数据报格式 前20个字节和紧跟其后的可选字段是IP数据报的首部,前20个字节是固定的,后面可选字段是可有可无的,首部的每一行以32位(4个字节)为单位。 版本:4位IP版本号(Version),这个值设置为二进制的0100时表示IPv4,设置为0110时表示IPv6,目前使用比较多的IP协议版本号是4。 首部长度:4位首部长度(IHL,Internet Header Length),表示IP首部一共有多少个32位(4个字节)。在没有可选字段时,IP首部长度为20个字节,因此首部长度的值为5。 服务类型:8位服务类型(TOS,Type of service),该字段被划分成两个子字段:3位优先级字段(现在已经基本忽略掉了)和4位TOS字段,最后一位固定为0。服务类型为0时表示一般服务。 总长度:16位IP数据报总长度(Total Length),包括IP首部和IP数据部分,以字节为单位。我们利用IP首部长度和IP数据报总长度,就可以知道IP数据报中数据内容的起始位置和长度。由于该字段长16bit,所以IP数据报最长可达65535字节。尽管理论上可以传输长达65535字节的IP数据报,但实际上还要考虑网络的最大承载能力等因素。 标识字段:16位标识(Identification)字段,用来标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1。 标志字段:3位标志(Flags)字段,第1位为保留位;第2位表示禁止分片(1表示不分片 0:允许分片);第3位标识更多分片(除了数据报的最后一个分片外,其它分片都为1)。 片偏移:13位片偏移(Fragment Offset),在接收方进行数据报重组时用来标识分片的顺序。 生存时间:8位生存时间字段,TTL(Time To Live)域防止丢失的数据包在无休止的传播,一般被设置为64或者128。 协议:8位协议(Protocol)类型,表示此数据报所携带上层数据使用的协议类型,ICMP为1,TCP为6,UDP为17。 首部校验和:16位首部校验和(Header Checksum),该字段只校验数据报的首部,不包含数据部分;校验IP数据报头部是否被破坏、篡改和丢失等。 源IP地址:32位源IP地址(Source Address),即发送端的IP地址,如192.168.1.123。 目的IP地址:32位目的IP地址(Destination Address),即接收端的IP地址,如192.168.1.102。 可选字段:是数据报中的一个可变长度的可选信息,选项字段以32bit为界,不足时插入值为0的填充字节,保证IP首部始终是32bit的整数倍。 以上内容是对IP首部格式的详细阐述,还需要补充的内容是IP首部校验和的计算方法,其计算步骤如下: 将16位检验和字段置为0,然后将IP首部按照16位分成多个单元; 对各个单元采用反码加法运算(即高位溢出位会加到低位,通常的补码运算是直接丢掉溢出的高位); 此时仍然可能出现进位的情况,将得到的和再次分成高16位和低16位进行累加; 最后将得到的和的反码填入校验和字段。 例如,我们使用IP协议发送一个IP数据报总长度为50个字节(有效数据为30个字节)的数据包,发送端IP地址为192.168.1.123,接收端IP地址为192.168.102,则IP首部数据如下:
图 7.5.13.4 IP首部数据 按照上述提到的 IP 首部校验和的方法计算 IP 首部校验和,即: 0x4500 + 0x0032 + 0x0000 + 0x4000 + 0x4011 + 0x0000(计算时强制置0) + 0xc0a8 + 0x017b + 0xc0a8 + 0x0166 = 0x24974 0x0002 + 0x4974 = 0x4976 0x0000 + 0x4976 = 0x4976(此种情况并未出现进位) check_sum = ~0x4976(按位取反) = 0xb689 到此为止IP协议内容已经介绍完了,我们从前面介绍的图 7.5.13.2可以知道,UDP的首部和数据位于IP协议的数据段。既然已经有IP协议了,为什么还需要UDP协议呢?为什么我们选择的是UDP还不是传输更可靠的TCP呢?带着这些疑问我们继续往下看。 UDP协议 首先回答为什么还需要UDP协议?事实上数据是可以直接封装在IP协议里而不使用TCP、UDP或者其它上层协议的。然而在网络传输中同一IP服务器需要提供各种不同的服务,各种不同的服务类型是使用端口号来区分的,例如用于浏览网页服务的80端口,用于FTP(文件传输协议)服务的21端口等。TCP和UDP都使用两个字节的端口号,理论上可以表示的范围为0~65535,足够满足各种不同的服务类型。 然后是为什么不选择传输更可靠的TCP协议,而是UDP协议呢?TCP协议与UDP协议作为传输层最常用的两种传输协议,这两种协议都是使用IP作为网络层协议进行传输。下面是TCP协议与UDP协议的区别: 1、TCP协议面向连接,是流传输协议,通过连接发送数据,而UDP协议传输不需要连接,是数据报协议; 2、TCP为可靠传输协议,而UDP为不可靠传输协议。即TCP协议可以保证数据的完整和有序,而UDP不能保证; 3、UDP由于不需要连接,故传输速度比TCP快,且占用资源比TCP少; 4、应用场合:TCP协议常用在对数据文件完整性较高的一些场景中,如文件传输等。UDP常用于对通讯速度有较高要求或者传输数据较少时,比如对速度要求较高的视频直播和传输数据较少的QQ等。 首先可以肯定的告诉大家,使用FPGA实现TCP协议是完全没有问题的,但是,FPGA发展到现在,却鲜有成功商用的RTL级的TCP协议设计,大部分以太网传输都是基于比较简单的UDP协议。TCP协议设计之初是根据软件灵活性设计的,如果使用硬件逻辑实现,工程量会十分巨大,而且功能和性能无法得到保证,因此,TCP协议设计并不适合使用硬件逻辑实现。UDP协议是一种不可靠传输,发送方只负责数据发送出去,而不管接收方是否正确的接收。在很多场合,是可以接受这种潜在的不可靠性的,例如视频实时传输显示等。 UDP数据格式如图 7.5.13.5所示:
图 7.5.13.5 UDP数据格式 UDP首部共8个字节,同IP首部一样,也是一行以32位(4个字节)为单位。 源端口号:16位发送端端口号,用于区分不同服务的端口,端口号的范围从0到65535。 目的端口号:16位接收端端口号。 UDP长度:16位UDP长度,包含UDP首部长度+数据长度,单位是字节(byte)。 UDP校验和:16位UDP校验和。UDP计算校验和的方法和计算IP数据报首部校验和的方法相似,但不同的是IP数据报的校验和只检验IP数据报的首部,而UDP校验和包含三个部分:UDP伪首部,UDP首部和UDP的数据部分。伪首部的数据是从IP数据报头和UDP数据报头获取的,包括源IP地址,目的IP地址,协议类型和UDP长度,其目的是让UDP两次检查数据是否已经正确到达目的地,只是单纯为了做校验用的。在大多数使用场景中接收端并不检测UDP校验和,因此这里不做过多介绍。 以太网的帧格式、IP数据报协议以及UDP协议到这里已经全部介绍完了,关于用户数据、UDP、IP、MAC四个报文的关系如下图所示:
图 7.5.13.6 以太网包数据格式 用户数据打包在UDP协议中,UDP协议又是基于IP协议之上的,IP协议又是走MAC层发送的,即从包含关系来说:MAC帧中的数据段为IP数据报,IP报文中的数据段为UDP报文,UDP报文中的数据段为用户希望传输的数据内容。现在再回过头看图 7.5.13.6的内容就非常容易理解了。 1.2 实验任务 本节实验任务是上位机通过网口调试助手发送数据给FPGA,FPGA通过PL端以太网接口接收数据并将接收到的数据发送给上位机,完成以太网UDP数据的环回。 1.3 硬件设计 PL端千兆以太网接口部分的硬件设计原理及本实验中各端口信号的管脚分配,和“以太网ARP测试实验”完全相同,请参考“以太网ARP读写测试实验”中的硬件设计部分。 1.4 程序设计 图 7.5.13.1是根据本章实验任务画出的系统框图。和“以太网ARP测试实验”相比,将ARP控制模块替换成了以太网控制模块,并增加了一个同步FIFO和UDP顶层模块。本次实验虽然实现的是UDP通信,但保留了ARP顶层模块,这是由于上位机应用程序只知道接收端的目的IP地址和端口号,却不知道接收端的MAC地址,因此这里通过ARP协议来获取接收端的MAC地址,否则需要在发送端手动绑定接收端MAC地址,而手动绑定的方法较为繁琐,因此这里保留了ARP协议。 本次实验同时实现了ARP协议和UDP协议,GMII接收侧的引脚同时连接至ARP顶层模块和UDP顶层模块,这个两个模块会分别根据ARP协议和UDP协议解析数据。而GMII发送侧引脚只能和ARP顶层模块和UDP顶层模块的其中一个连接,因此以太网控制模块会根据当前接收到的协议类型,选择切换GMII发送侧引脚和ARP顶层模块或者UDP顶层模块连接。除此之外,以太网控制模块根据输入的ARP接收的类型,控制ARP顶层模块返回ARP应答信号。以太网单次会接收到大量数据,因此本次实验需要一个FIFO模块用来缓存数据,由于本次实验所使用的GMII接收时钟和GMII发送时钟实际上为同一个时钟,因此这里使用的是同步FIFO。
图 7.5.13.1 以太网UDP测试系统框图 系统时钟经过PLL时钟模块后,输出200Mhz的时钟,用于IDELAYCTRL原语的参考时钟;GMII TO RGMII模块负责将双沿(DDR)数据和单沿(SDR)数据之间的转换;ARP顶层模块解析ARP请求命令,并返回开发板的MAC地址;以太网控制模块根据输入的ARP接收完成信号类型,控制ARP顶层模块返回ARP应答信号,并根据当前接收到的协议类型,选择切换ARP顶层模块和UDP顶层模块的GMII发送侧引脚;UDP顶层模块实现了以太网UDP数据包的接收、发送以及CRC校验的功能。同步FIFO模块是由Vivado软件自带的FIFO IP核生成的,FIFO的大小为2048个32bit,为了能够满足单包数据量较大的情况(尽管通常情况下,以太网帧有效数据不超过1500个字节),所以FIFO的深度最好设置的大一点,这里把深度设置为2048,宽度为32位。 各模块端口及信号连接如下图所示:
图 7.5.13.2 顶层模块原理图 由上图可知,FPGA顶层模块例化了以下六个模块,PLL时钟模块(clk_wiz)、GMII TO RGMII模块(gmii_to_rgmii)、ARP顶层模块(arp)、UDP顶层模块(udp)、同步FIFO模块(sync_fifo_2048x32b)和以太网控制模块(eth_ctrl),实现了各模块之间的数据交互。 其中GMII TO RGMII(gmii_to_rgmii)模块和ARP顶层模块(arp)在“以太网ARP测试实验”中已经向大家作了详细的介绍,如果大家对这部分内容不熟悉的话,可以参考“以太网ARP测试实验”。 本章我们重点介绍UDP顶层模块(udp)。 UDP顶层模块实现了整个以太网帧格式与UDP协议的功能,其模块端口及信号连接如下图所示:
图 7.5.13.3 UDP模块原理图 由上图可知,UDP顶层模块例化了UDP接收模块(udp_rx)、UDP发送模块(udp_tx)和CRC校验模块(crc32_d8)。 UDP接收模块(udp_rx):UDP接收模块较为简单,因为我们不需要对数据做IP首部校验也不需要做CRC循环冗余校验,只需要判断目的MAC地址与开发板MAC地址、目的IP地址与开发板IP地址是否一致即可。接收模块的解析顺序是:前导码+帧起始界定符→以太网帧头→IP首部→UDP首部→UDP数据(有效数据)→接收结束。IP数据报一般以32bit为单位,为了和IP数据报格式保持一致,所以要把8位数据转成32位数据,因此接收模块实际上是完成了8位数据转32位数据的功能。 UDP发送模块(udp_tx):UDP发送模块和接收模块比较类似,但是多了IP首部校验和和CRC循环冗余校验的计算。CRC的校验并不是在发送模块完成,而是在CRC校验模块(crc32_d8)里完成的。发送模块的发送顺序是前导码+帧起始界定符→以太网帧头→IP首部→UDP首部→UDP数据(有效数据)→CRC校验。输入的有效数据为32位数据,GMII接口为8位数据接口,因此发送模块实际上完成的是32位数据转8位数据的功能。 CRC校验模块(crc32_d8):CRC校验模块是对UDP发送模块的数据(不包括前导码和帧起始界定符)做校验,把校验结果值拼在以太网帧格式的FCS字段,如果CRC校验值计算错误或者没有的话,那么电脑网卡会直接丢弃该帧导致收不到数据(有些网卡是可以设置不做校验的)。CRC32校验在FPGA实现的原理是LFSR(Linear Feedback Shift Register,线性反馈移位寄存器),其思想是各个寄存器储存着上一次CRC32运算的结果,寄存器的输出即为CRC32的值。 其中CRC校验模块和ARP模块例化的校验模块完全相同,这里我们重点介绍UDP接收模块和UDP发送模块。 UDP接收模块按照UDP的数据格式解析数据,并实现将8位用户数据转成32位数据的功能。由UDP的数据格式可知,解析UDP数据很适合使用状态机来实现,下图为UDP接收模块的状态跳转图。
图 7.5.13.4 UDP接收模块的状态跳转图 接收模块使用三段式状态机来解析以太网包,从上图可以比较直观的看到每个状态实现的功能以及跳转到下一个状态的条件。这里需要注意的一点是,在中间状态如前导码错误、MAC地址错误以及IP地址错误时跳转到st_rx_end状态而不是跳转到st_idle状态。因为中间状态在解析到数据错误时,单包数据的接收还没有结束,如果此时跳转到st_idle状态会误把有效数据当成前导码来解析,所以状态跳转到st_rx_end。而eth_rxdv信号为0时,单包数据才算接收结束,所以st_rx_end跳转到st_idle的条件是eth_rxdv=0,准备接收下一包数据。因为代码较长,只粘贴了第三段状态机的接收数据状态和接收结束状态源代码,代码如下:
249 st_rx_data : begin
250 //接收数据,转换成32bit
251 if(gmii_rx_dv) begin
252 data_cnt
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?