跳至内容
用户工具
登录
站点工具
搜索
工具
显示页面
修订记录
反向链接
最近更改
媒体管理器
网站地图
登录
>
最近更改
媒体管理器
网站地图
您的足迹:
千兆以太网实验
本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。
***银杏科技有限公司/Gingko Technology Co.,Ltd.** ***技术支持论坛:http://www.eeschool.org** ***旗舰店:http://icore.taobao.com** ***技术支持邮件:GINGKO@vip.163.com** ***电话:0379-69926675** ***更新日期:12/17/2019** ***版本号:v1.0** ***更新说明:无** ===== 实验三十二:千兆以太网传输 ===== === 一、实验目的与意义 === -了解以太网帧结构和IP协议以及UDP协议的定义。 -了解PHY芯片RTL8211EG的引脚设定和信号规范。 -学习千兆以太网传输原理和物理层接口GMII的时序控制方法。 -掌握GMII接口千兆以太网的UDP协议通信模块设计。 === 二、实验设备及平台 === $lang['target____extern'] -iCore3 双核心板( FPGA型号为EP4CE10F17)[[https://item.taobao.com/item.htm?id=524229438677|点击购买]] -千兆网传输模块[[https://item.taobao.com/item.htm?id=574787244706|点击购买]] -Blaster(或相同功能的)仿真器和USB线缆[[https://item.taobao.com/item.htm?id=554869837940|点击购买]] -Micro USB线缆和千兆速率网线。 -QuartusII开发软件(本实验中使用的是13.1版本)、TCP&UDP测试工具软件、wireshark抓包软件。 -一台带有千兆网卡的电脑。 {{ :icore3:图32-1_硬件连接实物图.jpg?direct&600 |图32-1_硬件连接实物图}} **注意事项1:** 注意FPC转接板和千兆网卡模块下边缘对齐连接,如图30-1红圈内标注所示。\\ **注意事项2:** 确认PC端网卡和网线是千兆速率,网线的水晶头连接紧密稳定。\\ **注意事项3:** 下载前请确认绑定的引脚或者加载的pin.tcl文件和千兆网与核心板之间的连接引脚相对应。\\ === 三、实验原理 === == 1、数据收发流程 == *首先确认实验目的,本次实验可以划分为实现两个目的: *1)FPGA接收PC发送的数据并实现数据包的解析。 *2)FPGA打包数据,并发送至PC。 = *具体细分的话,要实现FPGA单次收发数据的功能,和测试FPGA大量发送数据至PC端的极限速率。 {{ :icore3:图32-2_数据收发传输路径.png?direct&600 |图32-2_数据收发传输路径}} *围绕实验目的,构建本次实验的开发环境。上图是本次实验需要构建的一个开发环境。图中绿色箭头代表PC端的TCP&UDP测试工具软件,发送数据至FPGA内部千兆网数据接收模块的数据流路径,这是数据接收过程(相对于FPGA来说)。红色箭头代表FPGA的数据发送模块,将数据传送至PC端TCP&UDP测试工具软件的数据传送路径,这是FPGA的数据发送过程。其中千兆网模块和iCore3开发板之间是通过排针连接, PC和千兆网模块是通过网线连接。PHY芯片和FPGA之间的数据传输,采用的是GMII接口。 == 2、PHY芯片RTL8211EG == *本实验中千兆网模块上的PHY芯片是realtek(瑞昱半导体)公司的RTL8211EG,采用64引脚封装,引脚分布如下图所示: {{ :icore3:图32-3_rtl8211eg引脚示意图.png?direct&600 |图32-3_rtl8211eg引脚示意图}} *RTL8211EG作为高集成度的网络收发芯片,支持多种收发模式,支持GMII和RGMII两种接口。可以通过配置,使其工作在RGMII或者GMII模式。GMII接口使用引脚较多,采用时钟单边沿采样数据。而RGMII则在时钟的上升沿和下降沿都采样数据,节约引脚但增加了时序控制的复杂度。至于选用哪种接口,视需要而定。本实验的千兆网模块已经通过硬件配置使RTL8211EG工作在GMII模式,寄存器配置采用的是默认设置。因此,了解PHY芯片的硬件驱动原理和处理好数据的收发即可。 *通过阅读RTL8211EG芯片手册中GMII模式下对应引脚的介绍,可以知道各引脚的编号,输入输出类型以及功能描述等。包括数据收发对应的引脚以及模式配置引脚。 {{ :icore3:图32-4_gmii模式引脚命名及定义1.png?direct&600 |图32-4_gmii模式引脚命名及定义1}} {{ :icore3:图32-5_gmii模式引脚命名及定义2.png?direct&600 |图32-5_gmii模式引脚命名及定义2}} *从芯片手册的表格中可以看到,RGMII模式和GMII模式是通过配置31号引脚来控制的。如下图红框中所示,拉低31号引脚的电平,则表示选择GMII模式,拉高则表示选择RGMII模式。从表格下方的原理图可以看到31号引脚接地,接口模式为 GMII接口。 {{ :icore3:图32-6_phy芯片模式选择控制.png?direct&600 |图32-6_phy芯片模式选择控制}} {{ :icore3:图32-7_rtl8211eg电路原理图.png?direct&600 |图32-7_rtl8211eg电路原理图}} *图32-4和图32-5中也包含了其他的配置信号,包括PHY地址和工作电压配置等,这些信号在千兆网模块上通过硬件电路已经配置完成,这里不再详解。有兴趣的同学可以结合手册和原理图,看一下是如何配置的。 **3、GMII接口** *GMII接口采用8位数据通道,125MHz的工作时钟,可达1000Mbps的传输速率。符合IEEE802.3-2000标准以太网协议。在实际应用中,绝大多数GMII接口都是兼容MII接口的,所以,一般的GMII接口都有两个发送参考时钟:TX_CLK和GTX_CLK。本次实验是千兆网实验,使用的是GTX_CLK。 *TXCLK也是发射参考时钟,跟PHY芯片的传输速率有关。这个时钟是由PHY芯片提供,指向MAC侧的。100Mbps速率下,TXCLK的频率为25MHz,10Mbps速率下,TXCLK频率为2.5MHz。 *RXC也是PHY芯片提供的连续接收参考时钟。100Mbps速率下,时钟频率为25MHz,10Mbps速率下,时钟频率为2.5MHz。把FPGA看成MAC端,千兆网模块看成PHY端,他们之间的信号关联如下图所示: {{ :icore3:图32-8_gmii接口的相关信号.png?direct&600 |图32-8_gmii接口的相关信号}} *关于GMII接口的信号定义,RTL8211EG的手册里有相关介绍,可以详参阅。 *在GMII接口信号中,125Mhz的GTX_CLK作为发射参考时钟,由MCA侧提供给PHY芯片,即由FPGA内部PLL输出,提供给PHY芯片用于采集FPGA发送的数据。GTX_CLK上升沿要保证在数据的稳定期以确保采集数据的准确性。RTL8211EG的芯片手册中关于此信号和数据的规范如下图: {{ :icore3:图32-9_gmii接口时序定义.png?direct&600 |图32-9_gmii接口时序定义}} *图中可以看出,tGCC即RXCLK时钟周期,典型值是8ns,因为时钟频率是125MHz。tGSUR到时钟上升沿的最小值是2ns,也就是TXD的跳变沿要比GTXCLK的上升沿最少要早2ns。我们代码中命名为GTX_CLK(tGCC)的时钟,由PLL IP核输出。在PLL IP核关于此时钟的设定中我们设置了时钟沿延后2ns。如下图红框中所示: {{ :icore3:图32-10_时钟gtx_clk相位偏移量设置.png?direct&600 |图32-10_时钟gtx_clk相位偏移量设置}} === 四、以太网 === *本实验所使用的千兆网模块基于PHY芯片RTL8211EG。作为物理层芯片,只负责数据的收发,不能对MAC层数据进行处理以及对协议的解析。这里就可以通过FPGA实现MAC层功能,按照互联网协议,解析出帧结构的数据部分,提取IP数据包。然后对IP数据包进行解析,读取IP数据包的数据部分,提取UDP数据包。再然后对UDP数据包进行解析,取出UDP包中的数据,也就是帧结构中的有效数据。从而实现FPGA解析以太网帧结构,解析IP协议,解析UDP数据包,以获取帧结构中的有效数据。 == 1、以太网帧结构 == *本实验是基于UDP协议的千兆网传输实验,因此需要对以太网帧结构和IP数据包、UDP数据包的定义和格式有所了解。在IEEE802.3中规定,数据是以帧的形式,在节点之间传输。如下表所示,数据按照下表中从左到右的字段顺序构成以太网帧结构: ^ 前导码 ^ SFD ^ 目标地址 ^ 源地址 ^ 类型 ^ 数据(IP数据包) ^ CRC ^ | 7byte | 1byte | 6byte | 6byte| 2byte | 46-1500byte | 4byte | ^ 字段名称 ^ 字段含义 ^ | 前导码 | 7个字节的0x55,用于以太网前导 | | SFD | 1个字节的帧起始符,0xD5,表示以太网数据帧的开始 | | 目标地址 | 接收方MAC地址,6字节 | | 源地址 | 发送方MAC地址,6字节 | | 类型 | 网络协议类型,0x0800表示为IP协议,0x0806表示是ARP协议 | | 数据 | 46-1500字节,不够最少字节的用0x00填充。 | | CRC | CRC-32 校验,从目标地址到数据结束都为需校验内容 | *上面两个表格,是对帧结构以及帧结构中各字段含义的讲解。可以这么理解,一帧数据就是依次由7个字节的0x55,一个字节的0xd5,12个字节的MAC地址,2个字节的IP协议类型值,一串长度不定的数据,和4个字节的CRC校验位组成。 *接收端首先接收到的是由7个字节的0x55构成的前导码,然后收到一个0xD5作为帧起始符。起始符之后收到目标MAC地址,源MAC地址,然后是网络协议类型。本实验采用的是IPv 4网络协议,这个协议类型字段的值就应该是0x0800。然后是数据长度以及CRC-32的校验数据。 *发送端与此类似,先发送7个字节的0x55,接着发送一个字节的0xd5,然后按顺序发送MCA地址协议类型以及数据和CRC校验值。 *标准以太网帧长度最小值为64 字节,最大值1518字节,有兴趣的可以查一下这两个数是怎么算的。这里的64和1518都是从目标地址开始算起的,不包括前导码和SFD,这也是为什么帧数据除了头部和校验以外的长度范围是46字节到1500字节。 == 2、IP协议 == *IP数据包在以太网帧结构中是以帧数据的形式存在的。所以解析完以太网的帧结构,得到的以太网帧的数据部分,便是IP协议的数据包。按照IP协议的头部格式,对帧的数据部分依次进行比对判断。识别完IP首部,接下来读取的便是IP数据包的数据部分。那么,IP数据包以什么样的结构在以太网帧中存在的呢?请看下表: | 版本(4bit) | 首部长度(4 bit) | 服务类型(1 byte) | 总长度(2 byte) || \\ | 标识(2 byte) ||| 标识(3 bit) | 片偏移(13 bit) |\\ | 生存时间(1 byte) || 协议(1 byte) | 首部校验和(2byte) ||\\\ | 源IP地址(4 byte) |||||\\ | 目标IP地址(4 byte) |||||\\ | 选项(如果有) |||||\\ | 数据 |||||\\ *IP数据包就是上表中各字段的值按照从左到右,从上到下的顺序排列,作为头部。加上数据部分,构成一个完整的IP数据包。注意上表中bit和byte的区别。那么,上表中各字段分别代表什么含义呢,这里也做了简单的解释: ^ 字段名称 ^ 字段含义 ^ | 版本 | IP协议版本,IPv 4 的协议版本号为4 | | 首部长度 | IP包头的长度,单位为4byte,即首部长度字段的值为5时,包头长度为20byte | | 服务类型 | 只有在使区分服务时,本字段才起作用 | | 总长度 | IP包的总长度,包括包头和数据 | | 标识 | 用于分包/拼包 | | 标志 | 用于分包/拼包 | | 片偏移 | 用于分包/拼包 | | 生存时间 | 数据在网络中的寿命,每经过一个路由器 -1,减到0时数据无效 | | 协议 | 指明数据字段中的数据包协议类型,UDP(17),TCP(6) | | 首部校验和 | IP包头部检验,只检验数据报的首部,不包括数据部分 | | 源IP地址 | 发送方IP地址 | | 目标IP地址 | 接收方IP地址 | | 选项 | 可选字段(长度可变) | | 数据 | IP数据包的数据部分(既UDP包) | == 3、UDP协议 == *UDP协议,即用户数据报协议,在消息的分发上有着独到优势。IP包的数据部分便是UDP数据包。包头很短,只有8byte,包含了发送方和接收方的端口,以及数据包长度和头部检验。下表是UDP包首部的字段及其含义。 | 源端口号(2 byte) | 目标端口号(2 byte) | | UDP长度(2 byte) | UDP长度(2 byte) | | 数据(x byte) (如果有) || ^ 字段名称 ^ 字段含义 ^ | 源端口号(2 byte) | 发送方端口 | | 目标端口号(2 byte) | 接收方端口 | | UDP长度(2 byte) | UDP数据包长度,包括包头和数据| | UDP长度(2 byte) | UDP包头部检验,只检验数据报的首部,不包括数据部分 | | 数据(x byte) | UDP数据包中的数据(也是帧结构的有效数据) | *至此,FPGA作为MAC端先解析帧数据包,然后提取出IP协议包,再从IP协议包里取出UDP协议包,最后从UDP协议包中读取出有效数据。 == 4、CRC校验 == *CRC校验是数据通信领域中常用的一种数据传输检错功能,通过对数据进行多项式计算,并将得到的结果附在帧的后面。接收设备采用类似算法检验接收数据的正确性和完整性。CRC校验的基本思想是将从目的MAC地址到有效数据的最后一位当成一个数,用这个数除以另一个数,得到的余数作为校验值附着在帧有效数据的后面,构成一个完整的帧格式。即是CRC校验。 === 五、代码讲解 === *首先来看一下这张图: {{ :icore3:图32-11_数据接收流程图.png?direct&300 |图32-11_数据接收流程图}} *这是数据接收时,FPGA内部接收模块数据做处理的流程。FPGA作为接收方,要判断接收的数据是否为一个帧数据包,就要按照帧结构,依次对接收的数据进行判断。只有数据符合帧结构,且MAC地址、IP地址、以及端口信息均和预期的吻合,才开始接收有效数据并缓存到寄存器组变量buffer中。否则就返回到初始状态继续等待数据的到来。 {{ :icore3:图32-12_数据发送流程图.png?direct&400 |图32-12_数据发送流程图}} *上图是帧数据发送流程图。一旦SD_EN为高的时候,进入帧数据发送流程。发送数据的时候要按照协议协议规定,以125MHz时钟信号做参考,将数据依次发送出去。按照顺序发送的思想,这里使用case语句控制状态的跳转,并通过计数对帧头部数据的发送进行控制。发送完UDP首部以后判断flag信号电平的高低。控制state是进入单次发送状态(send_data)还是连续发送状态(send_data1)。 *有了上面的思路就可以构思代码逻辑了。 == 1、数据接收模块 == *首先定义一些寄存器,用于存储接收到的头部信息。然后进行寄存器的初始化。由于数据是顺序接收和判断的,这里采用了case语句,并嵌入if判断语句控制case语句的跳转。只要图中的判断语句任意处出现否,则跳回数据接收模块的PRE_R状态。 *接下来再来看一下代码部分。结合前面的学习,理解起来就比较容易了。首先来看一下数据接收模块,其功能是判断数据包是否符合协议规范,并解析出数据包中的数据。数据接收部分首先是对状态机的状态跳转控进行赋值,其次是对寄存器的定义,如代码注释所示: <code verilog> //-------------------接收数据-------------------// parameter PRE_R = 4'd0, SFD_R = 4'd1, DA_R = 4'd2, SA_R = 4'd3, TYPE_R = 4'd4, ARP_R = 4'd5, IP_R = 4'd6, UDP_R = 4'd7, APP_R = 4'd8, END_R = 4'd9; reg [3:0] STATE_R;//接收状态 reg [7:0] cnt_R;//接收使用的计数器 reg [47:0]dest_mac;//目标MAC地址 reg [47:0]source_mac;//源MAC地址 reg [15:0]type;//接收数据的协议类型 reg [223:0]arp_data;//ARP中的数据 reg [159:0]ip_head;//IP报头 reg [63:0]udp_head;//UDP数据报头 reg [7:0]buffer[63:0];//数据缓存区 reg [15:0]data_lenght;//数据长度 reg [11:0] i;//数据计数器 reg [7:0]data1; reg UDP_SD_EN; </code> *这里有个寄存器变量data1,它的作用就像我们过安检时用的托盘。将物品放入托盘中,经过安检,取走物品后的托盘再次放入物品,过安检。于此类似,依次接收的数据,先放到变量data1中,然后对变量data1的值进行判断,是否符合帧格式,符合的话则用下一个输入值覆盖当前data1中的值,继续进行判断。 *数据接收模块的主要部分是一个case语句,在case语句的不同分支中,实现对帧结构的解析和数据的读取。首先是对寄存器变量的初始化,使其在复位之后处于一个确定的状态。然后是对帧的起始标志的判断,就在PRE_R的状态判断七次存入data1中的值,如果是7个0x55,那么说明输入的前七个数值符合帧起始符,就跳转到下一个状态,判断存入data1中的值是否为帧起始符0xd5。如果是0xd5,继续判断,否则调出判断,返回初始状态。如果发送过来的是一个完整的帧数据包,则可以解析出帧数据的MAC地址,协议类型,IP地址,端口类型以及数据长度,校验码等信息。 *UDP协议中,在UDP数据包里定义了数据部分的长度。那么,当我们解析出UDP数据包后,也就知道了这次发送的有效数据的长度。有了这个数据长度值,就可以在缓存接收到的数据时只存输入进来的有效数据了。 *在解析UDP包头的时候,也对目标端口进行了判断。要保证TCP&UDP测试软件设置的时候的端口值和此处代码中的端口值保持一致,否则会导致数据接收失败。 <code verilog> UDP_R:// 接收UDP包头 8 byte begin if(cnt_R == 8'd7) begin udp_head <= {udp_head[55:0],data1}; cnt_R <= 8'd0; if(udp_head[39:24] == 16'h7530)//16进制的7530是十进制的30000,即设定的端口号 begin data_lenght <= udp_head[23:8] - 16'd8;//提取数据长度,udp_head的[23:8]定义了UDP包的数据长度,包括了UDP头部,所以这里要减去UDP头部的数据长度8 STATE_R <= APP_R; end else begin STATE_R <= PRE_R; //如果端口不匹配,则返回PRE_R状态 end end else begin udp_head <= {udp_head[55:0],data1}; cnt_R <= cnt_R +1'd1; end end </code> *在这个状态机中还有个标志信号UDP_SD_EN,在存取有效数据完毕的同时,拉高UDP_SD_EN这个信号,在帧结束状态拉低这个信号,如果感兴趣,可以用SignalTap II Logic Anlyzer(quartus II 自带的逻辑分析仪)查看一下这个信号持续了几个时钟周期。这个标志位的作用是表示一个完整的帧数据包接收完成了。在发送数据的时候,以这个信号判断数据是否接收完毕。 == 2、数据发送模块 == *看代码部分,先定义帧头部标志位寄存器,并对case语句中的状态控制字赋初值,跟数据接收部分类似。因为有个连续发送模式,所以这里对数据的发送做个控制,这个控制信号就是发送模块代码中的flag。 <code verilog> reg flag;//连发模式标志位 reg flag_h;//连发开始位标志 reg flag_l;//连发停止位标志 always@(posedge RX_CLK or negedge rst_N ) if(rst_N==1'b0) flag_h<=1'b0; else if((buffer[0]==8'h33)&&(STATE_UT==APP_R))//连发开始位标志3 flag_h<=1'b1; else flag_h<=1'b0; always@(posedge RX_CLK or negedge rst_N ) if(rst_N==1'b0) flag_l<=1'b0; else if((buffer[0]==8'h73)&&(STATE_UT==APP_R))//连发停止位标志s flag_l<=1'b1; else flag_l<=1'b0; always@(posedge RX_CLK or negedge rst_N ) if(rst_N==1'b0) flag<=1'b0; else if(flag_l) //连发状态停止 flag<=1'b0; else if(flag_h==1'b1)//连发状态开始 flag<=1'b1; </code> *看这段代码,定义了另外两个寄存器变量,用于控制flag信号,那么控制flag变量的flag_h和flag_l又是如何产生的呢?在代码中,通过对数据接收模块状态和接收的第一个字符的值进行综合判断,当接收模块处于接收有效数据,且第一个接受到的数值为“3”的时候,拉高一个时钟周期的flag_h信号。flag_l则根据接收数据的第一个字符为“s”的时候拉高一个时钟周期。这里大家应该有注意到,当我们对数据接收缓存器的第一个值buffer[0]进行判断时,对比值是8’h33和8’h73。这里的8’h33和8’h73分别是ASCII码“3”和“s”对应的16进制数。这是因为我们使用TCP&UDP测试工具给FPGA发送数据的时候选择的是ASCII格式。 *那什么时候开始进入数据发送的流程呢?首先要对帧结构头部寄存器进行初始化,设定MCA地址,协议类型,版本号和端口号等信息。然后进入IDEL状态,等待SD_EN信号为高,则进行数据长度的初始化并进入发送状态。 *那么这里控制IDEL跳转到下一状态的SD_EN信号是什么作用呢?看下面这段代码就能知道,这个信号相当于一个选择器,当接收到的第一个字符为“3”的时候,flag信号为高,则SD_EN就一直为高电平了。SD_EN为高的时候,数据发送模就一直处于发送使能状态。而flag为低的时候,它的状态和UDP_SD_EN的状态就一样了,也就是FPGA每接收完一帧数据,便发送出一帧数据,并等待下一帧数据发送进来。 <code verilog> reg SD_EN; always@(posedge clk_125M or negedge rst_N) if(!rst_N) SD_EN<=1'b0; else if(flag) SD_EN<=1'b1; else if(!flag) SD_EN<=UDP_SD_EN; </code> *进入发送状态以后,是将帧头部和IP头部以及校验和的值存入对应的寄存器。准备工作做好之后,开始进入发送状态。在发送数据之前,先进行IP首部校验和的运算。IP校验的目的是为了保证IP首部的完整性。算法也比较简单,反码求和。反码求和的意思是先将IP首部的数据每两个字节拼成一个16位数,并对这些16位数求和。将求和的结果存入一个32位寄存器中,然后将寄存器的高16位和低16位求和取反即可得到IP首部校验和。代码如下: <code verilog> check1: begin if(cnt == 8'd6) begin//IP计算首部校验和:以16位相加方式加到32位校验和中 ip_check_sum <= {ip_send[0],ip_send[1]} + {ip_send[2],ip_send[3]}+{ip_send[4],ip_send[5]} + {ip_send[6],ip_send[7]} + {ip_send[8],ip_send[9]}+{ip_send[12],ip_send[13]}+{ip_send[14],ip_send[15]}+{ip_send[16],ip_send[17]}+{ip_send[18],ip_send[19]}; crc_reset <= 1'd1; cnt <= 8'd0; STATE_UT <= check2; end else begin cnt <= cnt + 1'd1; end end check2: begin//IP计算首部校验和:16位相加取反 {ip_send[10],ip_send[11]} = ~(ip_check_sum[15:0] + ip_check_sum[31:16]); STATE_UT <= send55; end </code> *然后正式进入数据发送阶段。首先是发送7个0x55和一个0xd5。作为帧数据开始标志,告诉接收设备,做好接收准备。之后就是发送源端和目标端MAC地址,以及协议类型,构成完整的数据帧头部。这里也要注意MAC地址的值和我们软件设置里相互对应。然后是IP数据包头和UDP数据包头部。 *在发送完UDP头部之后,将要发送的就是帧内的有效数据了,这里也用flag信号控制了一下状态的跳转。当flag为高的时候,跳转到send_data1状态,否则跳转到send_data状态。 <code verilog> send_udp://发送UDP包头 begin if(cnt == 8'd7) begin data_out <= udp_send[cnt]; cnt <= 8'd0; data_counter <= 16'd0; if(flag) //控制发送状态跳转至send_data1 STATE_UT<=send_data1; else STATE_UT <= send_data; end else begin data_out <= udp_send[cnt]; cnt <= cnt +1'd1; end end </code> *那么这两个状态有什么不同呢,我们首先来看一下代码: <code verilog> send_data://发送数据 begin if(data_lenght < 16'd19) begin if(data_counter == 16'd20) begin data_out <= buffer[data_counter]; data_counter <= 16'd0; STATE_UT <= send_crc; end else begin data_out <= buffer[data_counter]; data_counter <= data_counter + 1'd1; end end else begin if(data_counter == data_lenght - 16'd1) begin data_out <= buffer[data_counter]; data_counter <= 16'd0; STATE_UT <= send_crc; end else begin data_out <= buffer[data_counter]; data_counter <= data_counter + 1'd1; end end end send_data1: begin if(cnt_l==1200) begin STATE_UT <=send_crc; cnt_l<=12'd0; end else begin data_out<=8'h38;//输出数值随便定义,这里设定的“8” cnt_l<=cnt_l+1'b1; end end </code> *通过对比这两段代码可以知道,send_data和send_data1均是实现数据发送的。 *send_data是按照协议流程,进行最小帧长度的判断,并处理,然后将接收数据缓冲寄存器buffer中存储的接收数据依次发送出去。 *前面我们有提到,帧数据的长度为46字节到1500字节,这个长度是包括IP协议头部和UDP协议头部的,因此,一帧数据除了IP协议头部和UDP协议头部,携带的有效数据长度在19字节至1400多个字节之间。所以在发送数据的时候我们这里对需要发送的数据的长度做个判断,当发送的数据的长度不够19个字节的时候,就对其进行填充,避免被当成非法帧而丢包。 *send_data1则是直接将ASCII码“8”的16进制数值连续1200次发送出去。这里的data_out的值大家给定什么,在TCP&UDP的接收区就可以收到什么。连续发送的次数只要在帧数据长度的最大值和最小值以内都可以。 *回过头看一下,大概流程就是,如果接收数据的第一个字符是“3”,则flag信号为高电平。相应的SD_EN信号也为高电平,一直处于发送使能状态。同时由于flag为高,case语句中有效数据发送一直进入send_data1,即连续发送内容为1200个“8”的帧到PC端。数据发送完之后接着发送CRC校验的值,就完成了一帧数据的发送。 === 六、操作流程和测试结果 === == 1、操作步骤: == *1)确认电脑网卡为千兆网卡,并设置成千兆网模式,至于如何查看和设置,大家可以网上搜一下。 *2)修改电脑IP为192.168.0.3 子网掩码改为 255.255.255.0。 *以WIN10系统为例: *点击【设置】选项,在弹出窗口中的以太网界面点击①处【更改适配器】选项。弹出网络连接界面,右键单击②处【以太网】,选择【属性】。在弹出界面点击③处的【协议版本4】,点击【属性】。弹出界面后在④处选择使【用下面的IP地址】,并设置IP地址和子网掩码,完成后点击【OK】并退出。如图中①②③④所示: * {{ :icore3:图32-13_设置ip地址.png?direct&600 |图32-13_设置ip地址}} *3)连接好网线和调试工具,供电并编译下载。 *4)打开wireshark抓包软件,双击以太网那行,进入抓数据包界面。 {{ :icore3:图32-14_wireshark界面.png?direct&600 |图32-14_wireshark界面}} *5)打开PC端的任务管理器,在性能界面点击【以太网】,在此界面可以实时动态显示PC端以太网接口发送和接收数据的速率。 *6)打开TCP&UDP测试软件,步骤如下: *(1)打开软件,点击客户端模式,创建连接。 {{ :icore3:图32-15_tcp_udp测试工具创建连接.png?direct&600 |图32-15 TCP&UDP测试工具创建连接}} *(2)配置为UDP格式,并指定目标IP和端口号,注意此处IP和端口号要跟代码中的相互对应。点击【创建】按钮。 {{ :icore3:图32-16_tcp_udp测试工具参数设置.png?direct&600 |图32-16 TCP&UDP测试工具参数设置}} *出现下图界面,从界面中红框处可以看到IP、端口、类型等信息,点击蓝色框中的【创建】创立连接。如果打开软件后发送区为灰色,可以点击绿色框中的【√】,取消发送文件选项(本实验暂不支持文件的传输)。这时会看到TCP&UDP测试工具软件的发送区可以输入内容了。在发送区输入任意内容,点击发送或者自动发送(此处自动发送为PC端持续向iCore3发送数据,iCore3接收并返回数据到PC端),即可实现PC端向FPGA发送数据。 {{ :icore3:图32-17_tcp_udp测试工具测试界面.png?direct&600 |图32-17 TCP&UDP测试工具测试界面}} *本实验中使用3和s(小写)作为高速发送模式的标识符,即当PC发送的内容第一个字符为3这个数字时,FPGA开始连续大量发送数字8到PC,此时可以测试FPGA的千兆网模块发送数据的能力。 *FPGA大量发送数据的过程中,如果PC端通过TCP&UDP测试软件给千兆网模块发送的内容第一个字符为s(小写),则FPGA停止发送数字8,返回到普通模式。 == 2、测试结果: == *不勾选【自动发送】选项,则点击发送的时候,发送的内容可以在接收区看到。这里以数字“4”为例,在TCP&UDP测试工具的发送区输入数字“4”,并点击发送。可以在接收区看到数字“4”,表示FPGA接收到数字4,并将其返回至PC端。同时可以在wireshark界面看到PC端网口抓到的本次发送和接收的数据包信息。如下图红框中所示,是本次发送和接收的IP地址信息和数据包格式信息,点击任意一行,会深色显示,表示选中,在界面的中间窗口有源端口和目标端口的显示,对照TCP&UDP测试工具软件的蓝色框内信息可以确认我们的端口信息。底端窗口橙色框中所示,是数字“4”的16进制和ASCII码格式。 {{ :icore3:图32-18_tcp_udp测试工具和wireshark软件联合调试.png?direct&600 |图32-18 TCP&UDP测试工具和wireshark软件联合调试}} *勾选【连续发送】后可以看到接收区不断的接收和发送区相同的内容。这是TCP&UDP测试软件持续将发送区内容发送至FPGA、FPGA再把接收到的内容发送至PC端的过程。 *此时在TCP&UDP测试工具的发送区输入第一个字符为3的内容,并点击发送。在任务管理器界面可以看到接收速率达980 Mbps。同时可以在TCP&UDP测试工具软件的接收区看到连续的数字“8”接收进来,说明成功实现了FPGA向PC端以接近千兆的速率传输数据。 {{ :icore3:图32-19_测试结果.png?direct&600 |图32-19 测试结果}} *在FPGA高速发送数据模式下,如果在TCP&UDP测试工具软件的发送区输入第一个字符为“s” (小写)的内容并点击发送,可以在任务管理器界面看到数据接收变为0Kbps。由于TCP&UDP测试工具软件会缓存接收的数据并显示,等待一会儿之后可以看到接收区停止显示数字“8”,并且结尾显示有我们发送的字符“s”。如果有丢包现象,可以多点击两次【发送】按钮。目前千兆以太网已经很常见了,理论网速可达1000Mbit/s,实际传输时接近该值,但几乎达不到该值。本次例程中传输速率实测可达980Mbit/s。至此,本实验实现了基于FPGA的千兆网实验,包括数据的单次收发,连续收发以及接近千兆的发送能力测试。 === 七、拓展实验: === *1、换成其他字符,实现和“3”、“s”同样的功能。 *2、改变send_data1状态的发送内容。
千兆以太网实验.1577259894.txt.gz
· 最后更改: 2019/12/25 15:44 由
xiaomagee
页面工具
显示页面
修订记录
反向链接
回到顶部