ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)

1)摘自【正点原子】领航者 ZYNQ 之FPGA开发指南

2)实验平台:正点原子领航者ZYNQ开发板
3)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
4)全套实验源码+手册+视频下载:http://www.openedv.com/docs/boards/fpga/zdyz_linhanz.html
5)对正点原子FPGA感兴趣的同学可以加群讨论:876744900
6)正点原子资料更新和新品发布,请加正点原子公众号:正点原子
关注方法:微信→添加好友→公众号→输入:正点原子

第二十五章以太网ARP测试实验


在以太网中,一个主机和另一个主机进行通信,必须要知道目的主机的MAC地址(物理地址),而目的MAC地址的获取由ARP协议完成。本章我们来学习如何通过领航者ZYNQ开发板实现ARP协议的功能。
本章分为以下几个章节:
2525.1简介
25.2实验任务
25.3硬件设计
25.4程序设计
25.5下载验证
25.1简介
ARP概述
ARP(Address Resolution Protocol),即地址解析协议,是根据IP地址(逻辑地址)获取MAC地址的一种TCP/IP协议。在以太网通信中,数据是以“帧”的格式进行传输的,帧格式里面包含目的主机的MAC地址。源主机的应用程序知道目的主机的IP地址,却不知道目的主机的MAC地址。而目的主机的MAC地址直接被网卡接收和解析,当解析到目的MAC地址非本地MAC地址时,则直接丢弃该包数据,因此在通信前需要先获得目的的MAC地址,而ARP协议正是实现了此功能。
ARP协议的基本功能是通过目的设备的IP地址,查询目的设备的MAC地址,以保证通信的顺利进行。MAC地址在网络中表示网卡的ID,每个网卡都需要并有且仅有一个MAC地址。在获取到目的MAC地址之后,将目的MAC地址更新至ARP缓存表中,称为ARP映射,下次通信时,可以直接从ARP缓存表中获取,而不用重新通过ARP获取MAC地址。但一般ARP缓存表会有过期时间,过期后需要重新通过ARP协议进行获取。
ARP映射是指将IP地址和MAC地址映射起来,分为静态映射和动态映射。
静态映射指手动创建一张ARP表,把IP地址和MAC地址关联起来。手动绑定之后,源主机在通信之前,就可以直接从ARP表中直接找到IP地址对应的MAC地址,但这样做有一定的局限性,因为MAC地址可能会变化,比如:
1)机器可能更换NIC(网络适配器),结果变成一个新的物理地址;
2)在某些局域网中,每当计算机加电时,他的物理地址都要改变一次。
3)移动电脑可以从一个物理网络转移到另一个物理网络,这样会改变物理地址。
要避免这些问题出现,必须定期维护更新ARP表,此类比较麻烦而且会影响网络性能。
动态映射指使用协议来获取相对应的物理地址,之所以用动态这个词是因为这个过程是自动完成的,一般应用程序的用户或系统管理员不必关心。已经设计出用于实现动态映射协议的有ARP和RARP(逆地址解析协议)两种,如下图所示。

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第1张图片

图 25.1.1 地址解析协议:RAP和RRAP


ARP把IP地址映射为物理地址,RARP把物理地址映射为IP地址。RRAP是被那些没有磁盘驱动器的系统使用(一般是无盘工作站或 X终端),此类应用较少,本章不做讨论。
ARP协议分为ARP请求和ARP应答,源主机发起查询目的MAC地址的报文称为ARP请求,目的主机响应源主机并发送包含本地MAC地址的报文称为ARP应答。
当主机需要找出这个网络中的另一个主机的物理地址时,它就可以发送一个ARP请求报文,这个报文包含了发送方的MAC地址和IP地址以及接收方的IP地址。因为发送方不知道接收方的物理地址,所以这个查询分组会在网络层中进行广播,即ARP请求时发送的接收方物理地址为广播地址,用48’hff_ff_ff_ff_ff_ff表示。ARP请求的示意图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第2张图片

图 25.1.2 ARP请求示意图


上图中的主机A发起ARP请求,由于发送的目的MAC地址为广播地址,所以此时局域网中的所有主机都会进行接收并处理这个ARP请求报文,然后进行验证,查看接收方的IP地址是不是自己的地址。是则返回ARP应答报文,不是则不响应。
只有验证成功的主机才会返回一个ARP应答报文,这个应答报文包含接收方的IP地址和物理地址。ARP应答的示意图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第3张图片

图 25.1.3 ARP应答示意图


主机B利用收到的ARP请求报文中的请求方物理地址,以单播的方式直接发送给主机A,主机A将收到的ARP应答报文中的目的MAC地址解析出来,将目的MAC地址和目的IP地址更新至ARP缓存表中。当再次和主机A通信时,可以直接从ARP缓存表中获取,而不用重新发起ARP请求报文。需要说明的是,ARP缓存表中的表项有过期时间(一般为20分钟),过期之后,需要重新发起ARP请求以获取目的MAC地址。
ARP协议通过以太网进行传输,那么必须也要按照以太网所规定的格式进行传输,我们先来介绍下以太网的帧格式,随后再来向大家详细介绍ARP协议的具体格式。
以太网是目前应用最广泛的局域网通讯方式,同时也是一种协议。以太网协议定义了一系列软件和硬件标准,从而将不同的计算机设备连接在一起。我们知道串口通信单次只传输一个字节,而以太网通信是以数据包的形式传输,其单包数据量达到几十,甚至成百上千个字节。下图为以太网通过ARP传输单包数据的格式,从图中可以看出,以太网的数据包就是对协议的封装来实现数据的传输,即ARP数据位于以太网帧格式的数据段。这里只是让大家了解下以太网数据包的格式,后面会逐个展开来讲。

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第4张图片

图 25.1.4 以太网ARP数据包格式


以太网MAC帧格式
以太网技术的正式标准是IEEE 802.3,它规定了以太网传输数据的帧结构,我们可以把以太网MAC层理解成高速公路,我们必须遵循它的规则才能在上面通行,以太网MAC层帧格式如图 25.1.5所示。

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第5张图片

图 25.1.5 以太网帧格式


以太网传输数据时按照上面的顺序从头到尾依次被发送和接收,我们下面进一步解释各个区域。
前导码(Preamble):为了实现底层数据的正确阐述,物理层使用7个字节同步码(0和1交替(55-55-55-55-55-55-55))实现数据的同步。
帧起始界定符(SFD,Start Frame Delimiter):使用1个字节的SFD(固定值为0xd5)来表示一帧的开始,即后面紧跟着传输的就是以太网的帧头。
目的MAC地址:即接收端物理MAC地址,占用6个字节。MAC地址从应用上可分为单播地址、组播地址和广播地址。单播地址:第一个字节的最低位为0,比如00-00-00-11-11-11,一般用于标志唯一的设备;组播地址:第一个字节的最低位为1,比如01-00-00-11-11-11,一般用于标志同属一组的多个设备;广播地址:所有48bit全为1,即FF-FF-FF-FF-FF-FF,它用于标志同一网段中的所有设备。
源MAC地址:即发送端物理MAC地址,占用6个字节。
长度/类型:上图中的长度/类型具有两个意义,当这两个字节的值小于1536(十六进制为 0x0600)时,代表该以太网中数据段的长度;如果这两个字节的值大于1536,则表示该以太网中的数据属于哪个上层协议,例如0x0800代表IP协议(网际协议)、0x0806代表ARP协议(地址解析协议)等。
数据:以太网中的数据段长度最小46个字节,最大1500个字节。最大值1500称为以太网的最大传输单元(MTU,Maximum Transmission Unit),之所以限制最大传输单元是因为在多个计算机的数据帧排队等待传输时,如果某个数据帧太大的话,那么其它数据帧等待的时间就会加长,导致体验变差,这就像一个十字路口的红绿灯,你可以让绿灯持续亮一小时,但是等红灯的人一定不愿意的。另外还要考虑网络I/O控制器缓存区资源以及网络最大的承载能力等因素,因此最大传输单元是由各种综合因素决定的。为了避免增加额外的配置,通常以太网的有效数据字段小于1500个字节。
帧检验序列(FCS,Frame Check Sequence):为了确保数据的正确传输,在数据的尾部加入了4个字节的循环冗余校验码(CRC校验)来检测数据是否传输错误。CRC数据校验从以太网帧头开始即不包含前导码和帧起始界定符。通用的CRC标准有CRC-8、CRC-16、CRC-32、CRC-CCIT,其中在网络通信系统中应用最广泛的是CRC-32标准。
在这里还有一个要注意的地方就是以太网相邻两帧之间的时间间隔,即帧间隙(IFG,Interpacket Gap)。帧间隙的时间就是网络设备和组件在接收一帧之后,需要短暂的时间来恢复并为接收下一帧做准备的时间,IFG的最小值是96 bit time,即在媒介中发送96位原始数据所需要的时间,在不同媒介中IFG的最小值是不一样的。不管10M/100M/1000M的以太网,两帧之间最少要有96bit time,IFG的最少间隔时间计算方法如下:
10Mbit/s最小时间为:96*100ns = 9600ns;
100Mbit/s最小时间为:96*10ns = 960ns;
1000Mbit/s最小时间为:96*1ns = 96ns。
接下来我们介绍ARP协议以及它和以太网MAC层的关系。在介绍ARP协议之前,我们先了解下TCP(传输控制协议)/IP(网际协议)协议簇。TCP/IP是网络使用中最基本的通信协议,虽然从名字看上去TCP/IP包括两个协议,TCP和IP,但TCP/IP实际上是一组协议,它包括上百个各种功能的协议,如:TCP、IP、ARP、UDP等。而TCP协议和IP协议是保证数据完整传输的两个重要的协议,因此TCP/IP协议用来表示Internet协议簇。
TCP/IP协议不仅可以运行在以太网上,也可以运行在FDDI(光纤分布式数据接口)和WLAN(无线局域网)上。反过来,以太网的高层协议不仅可以是TCP/IP协议,也可以是IPX协议(互联网分组交换协议)等,只不过以太网+TCP/IP成为IT行业中应用最普遍的技术。下面我们来熟悉下ARP协议。
ARP协议
ARP协议属于TCP/IP协议簇的一种,从前面介绍的图 25.1.4可以看出,ARP协议位于以太网MAC帧格式的数据段,ARP数据包格式如下图所示。

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第6张图片

图 25.1.6 ARP数据包格式


硬件类型(Hardware type):硬件地址的类型,1表示以太网地址。
协议类型(Protocol type):要映射的协议地址类型,ARP协议的上层协议为IP协议,因此该协议类型为IP协议,其值为0x0800。
硬件地址长度(Hardware size):硬件地址(MAC地址)的长度,以字节为单位。对于以太网上IP地址的ARP请求或者应答来说,该值为6。
协议地址长度(Protocol size):IP地址的长度,以字节为单位。对于以太网上IP地址的ARP请求或者应答来说,该值为4。
OP(Opcode):操作码,用于表示该数据包为ARP请求或者ARP应答。1表示ARP请求,2表示ARP应答。
源MAC地址:发送端的硬件地址。
源IP地址:发送端的协议(IP)地址,如192.168.1.102。
目的MAC地址:接收端的硬件地址,在ARP请求时由于不知道接收端MAC地址,因此该字段为广播地址,即48’hff_ff_ff_ff_ff_ff。
目的IP地址:接收端的协议(IP)地址,如192.168.1.10。
以太网的帧格式、ARP数据格式到这里已经全部介绍完了,关于通过以太网传输ARP报文的格式如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第7张图片

图 25.1.7 以太网ARP数据包格式


由上图可知,28字节的ARP数据位于以太网帧格式的数据段。由于以太网数据段最少为46个字节,而ARP数据包总长度为28个字节,因此在ARP数据段后面需要填充18个字节的数据,以满足以太网传输格式的要求。这个填充的过程称为Padding(填充),填充的数据可以为任意值,但一般为0。
RGMII接口介绍
以太网的通信离不开物理层PHY芯片的支持,以太网MAC和PHY之间有一个接口,常用的接口有MII、RMII、GMII、RGMII等。
MII(Medium Independent Interface,媒体独立接口):MII支持10Mbps和100Mbps的操作,数据位宽为4位,在100Mbps传输速率下,时钟频率为25Mhz。
RMII(Reduced MII):RMII是MII的简化版,数据位宽为2位,在100Mbps传输速率下,时钟频率为50Mhz。
GMII(Gigabit MII):GMII接口向下兼容MII接口,支持10Mbps、100Mbps和1000Mbps的操作,数据位宽为8位,在1000Mbps传输速率下,时钟频率为125Mhz。
RGMII(Reduced GMII):RGMII是GMII的简化版,数据位宽为4位,在1000Mbps传输速率下,时钟频率为125Mhz,在时钟的上下沿同时采样数据。在100Mbps和10Mbps通信速率下,为单个时钟沿采样。
在千兆以太网中,常用的接口为RGMII和GMII接口。RGMII接口的优势是同时适用于10M/100M/1000Mbps通信速率,同时占用的引脚数较少。但RGMII接口也有其缺点,就是在PCB布线时需要尽可能对时钟、控制和数据线进行等长处理,且时序约束相对也更为严格。
为了节省引脚,领航者ZYNQ开发板板载的PHY芯片采用的接口为RGMII接口,下图是MAC侧与PHY侧接口的连接。

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第8张图片

图 25.1.8 MAC侧与PHY侧接口连接


ETH_RXC:接收数据参考时钟,1000Mbps速率下,时钟频率为125MHz,时钟为上下沿同时采样;100Mbps速率下,时钟频率为25MHz;10Mbps速率下,时钟频率为2.5MHz,ETH_RXC由PHY侧提供。
ETH_RXCTL(ETH_RX_DV):接收数据控制信号。
ETH_RXD:四位并行的接收数据线。
ETH_TXC:发送参考时钟,1000Mbps速率下,时钟频率为125MHz,时钟为上下沿同时采样;100Mbps速率下,时钟频率为25MHz;10Mbps速率下,时钟频率为2.5MHz,ETH_TXC由MAC侧提供。
ETH_TXCTL(ETH_TXEN):发送数据控制信号。
ETH_TXD:四位并行的发送数据线。
ETH_RESET_N:芯片复位信号,低电平有效。
ETH_MDC:数据管理时钟(Management Data Clock),该引脚对ETH_MDIO信号提供了一个同步的时钟。
ETH_MDIO:数据输入/输出管理(Management Data Input/Output),该引脚提供了一个双向信号用于传递管理信息。
其中ETH_RXC、ETH_RXCTL和ETH_RXD为MAC接收侧引脚;ETH_TXC、ETH_TXCTL和ETH_TXD为MAC发送侧引脚;ETH_MDC和ETH_MDIO为MDIO接口引脚,用于配置PHY芯片内部寄存器;ETH_RST_N为PHY芯片硬件复位信号。由于PHY芯片的内部寄存器在默认配置下也可以正常工作,因此本次实验没有对MDIO接口进行读写操作,只用到了以太网的RGMII接口信号和复位信号。
RGMII使用4bit数据接口,在1000Mbps通信速率下,ETH_TXC和ETH_RXC的时钟频率为125Mhz,采用上下沿DDR(Double Data Rate)的方式在一个时钟周期内传输8位数据信号,即上升沿发送/接收低4位数据,上升沿发送/接收高4位数据。ETH_TXCTL和ETH_RXCTL控制信号同样采用DDR的方式在一个时钟周期内传输两位控制信号,即上升沿发送/接收数据使能(TX_EN/RX_ DV)信号,下降沿发送/接收使能信号与错误信号的异或值(TX_ERR xor TX_EN、RX_ERR xor RX_DV)。当RX_DV为高电平(表示数据有效),RX_ERR为低电平(表示数据无错误),则异或的结果值为高电平,因此只有当ETH_RXCTL和ETH_TXCTL信号的上下沿同时为高电平时,发送和接收的数据有效且正确。
当RGMII工作在100Mbps时,ETH_TXC和ETH_RXC的时钟频率为25Mhz,采用上升沿SDR的方式在一个周期内传输4位数据。不过此时ETH_TXCTL和ETH_RXCTL控制信号仍采用上下沿DDR的传输方式。
当RGMII工作在10Mbps时,ETH_TXC和ETH_RXC的时钟频率为2.5Mhz,采用上升沿SDR的方式在一个周期内传输4位数据。ETH_TXCTL和ETH_RXCTL控制信号也采用SDR的传输方式。
RGMII接口时序
PHY芯片一般支持两种RGMII接口传输模式,正常模式和延时模式,两种模式的区别在于时钟、控制信号和数据对齐方式不同,其传输模式由MDIO接口或者硬件上的特殊引脚配置。
RGMII发送端口正常模式时序图如下:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第9张图片

图 25.1.9 RGMII发送端口正常模式


由上图可知,RGMII发送端口正常模式下,需要满足TXC的上下边沿与TXD和TX_CTL信号的中间位置对齐,TXC的时钟周期为8ns,单个高电平或者低电平为4ns,TXC相对于TXD和TX_CTL延时约2ns。
RGMII发送端口延时模式时序图如下:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第10张图片

图 25.1.10 RGMII发送端口延时模式


由上图可知,RGMII发送端口延时模式下,需要满足TXC的上下边沿与TXD和TX_CTL信号对齐,相位相同。B50610 RGMII发送端口默认采用延时模式,其模式由MDIO接口进行配置,如下图 25.1.11所示。其中寄存器地址0x1C的Bit[9]用于配置发送端口的延时模式,默认配置为1,即采用延时模式。

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第11张图片

图 25.1.11 RGMII发送端口模式配置


RGMII接收端口正常模式时序图如下:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第12张图片

图 25.1.12 RGMII接收端口正常模式


RGMII接收端口正常模式下,RXC的上下边沿与RXD和RX_CTL信号对齐,相位相同。
RGMII接收端口延时模式时序图如下:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第13张图片

图 25.1.13 RGMII接收端口延时模式


RGMII接收端口延时模式下,RXC的上下边沿与RXD和RX_CTL信号的中间位置对齐,RXC的时钟周期为8ns,单个高电平或者低电平为4ns,RXC相对于RXD和RX_CTL延时约2ns。B50610 RGMII接收端口默认采用延时模式,其模式由MDIO接口进行配置,如下图 25.1.14所示。其中寄存器地址0x18的Bit[8]用于配置发送端口的延时模式,默认配置为1,即采用延时模式。

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第14张图片

图 25.1.14 RGMII接收端口模式配置


由RGMII的接口时序可知,RGMII发送端口在TXC时钟的上升沿传输TXD的高4位和TX_CTL的使能信号;下降沿传输TXD的低4位和TX_CTL的错误信号(实际上是使能信号和错误信号的异或值);RGMII接收端口在RXC时钟的上升沿传输RXD的高4位和RX_CTL的使能信号;下降沿传输RXD的低4位和RX_CTL的错误信号(实际上是使能信号和错误信号的异或值)。因此为了便于正确接收数据以及解析数据,需要将这种双沿采集4位数据的端口转换成常规的单沿采集8位数据的端口,即RGMII接口到GMII接口的转换。这个需要借助于Xilinx提供的原语进行转换,接下来我们介绍下本次实验所用到的Xilinx的原语。
Xilinx原语
原语是Xilinx器件底层硬件中的功能模块,它使用专用的资源来实现一系列的功能。相比于IP核,原语的调用方法更简单,但是一般只用于实现一些简单的功能。本章主要用到了BUFG、BUFIO、IDDR、ODDR、IDELAYE2和IDELAYCTRL。
BUFG:全局缓冲,BUFG的输出到达FPGA内部的IOB、CLB、块RAM的时钟延迟和抖动最小。BUFG原语模板如下:

  1. BUFG BUFG_inst (
  2. .O(O), // 1-bit output: Clock output
  3. .I(I) // 1-bit input: Clock input
  4. );


除了BUFG外,常用的还有BUFR,BUFR是regional时钟网络,它的驱动范围只能局限在一个clock region的逻辑。BUFR相比BUFG的最大优势是偏斜和功耗都比较小。
BUFIO:BUFIO是IO时钟网络,其独立于全局时钟资源,适合采集源同步数据。它只能驱动IO Block里面的逻辑,不能驱动CLB里面的LUT,REG等逻辑。BUFIO原语模板如下:

  1. BUFIO BUFIO_inst (
  2. .O(O), // 1-bit output: Clock output (connect to I/O clock loads).
  3. .I(I) // 1-bit input: Clock input (connect to an IBUF or BUFMR).
  4. );


BUFIO在采集源同步IO数据时,提供非常小的延时,因此非常适合采集比如RGMII接收侧的数据,但是由于其不能驱动FPGA的内部逻辑,因此需要BUFIO和BUFG配合使用,以达到最佳性能。如ETH_RXC的时钟经过BUFIO,用来采集端口数据;ETH_RXC经过BUFG,用来作为除端口采集外的其他模块的操作时钟。
IDDR:在7系列设备的ILOGIC block中有专属的registers来实现input double-data-rate(IDDR) registers,将输入的上下边沿DDR信号,转换成两位单边沿SDR信号。IDDR的原语结构图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第15张图片

图 25.1.15 IDDR原语结构图


C:输入的同步时钟;
D:输入的1位DDR数据;
Q1和Q2:分别是“C”时钟上升沿和下降沿同步输出的SDR数据。
CE:时钟使能信号;
S/R:置位/复位信号,这两个信号不能同时拉高。
IDDR原语模板如下:

  1. IDDR #(
  2. .DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE", "SAME_EDGE"
  3. // or "SAME_EDGE_PIPELINED"
  4. .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
  5. .INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
  6. .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
  7. ) IDDR_inst (
  8. .Q1(Q1), // 1-bit output for positive edge of clock
  9. .Q2(Q2), // 1-bit output for negative edge of clock
  10. .C(C), // 1-bit clock input
  11. .CE(CE), // 1-bit clock enable input
  12. .D(D), // 1-bit DDR data input
  13. .R(R), // 1-bit reset
  14. .S(S) // 1-bit set
  15. );


DDR_CLK_EDGE参数为IDDR的三种采集模式,分别为“OPPOSITE_EDGE”、“SAME_EDGE”和“SAME_EDGE_PIPELINED”模式。
OPPOSITE_EDGE模式的时序图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第16张图片

图 25.1.16 IDDR“OPPOSITE_EDGE”模式时序图


OPPOSITE_EDGE模式下,在时钟的上升沿输出的Q1,时钟的下降沿输出Q2。
SAME_EDGE模式的时序图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第17张图片

图 25.1.17 IDDR“SAME_EDGE”模式时序图


SAME_EDGE模式下,在时钟的上升沿输出Q1和Q2,但Q1和Q2不在同一个cycle输出。
SAME_EDGE_PIPELINED模式的时序图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第18张图片

图 25.1.18 IDDR“SAME_EDGE_PIPELINED”模式时序图


SAME_EDGE_PIPELINED模式下,在时钟的上升沿输出Q1和Q2,Q1和Q2虽然在同一个cycle输出,但整体延时了一个时钟周期。在使用IDDR时,一般采用此种模式。
ODDR:通过ODDR把两路单端的数据合并到一路上输出,上下沿同时输出数据,上升沿输出a路,下降沿输出b路;如果两路输入信号一路固定为1,另外一路固定为0,那么输出的信号实际上是时钟信号。
ODDR的原语结构图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第19张图片

图 25.1.19 ODDR原语结构图


C:输入的同步时钟;
Q:输出的1位DDR数据;
D1和D2:分别是“C”时钟上升沿和下降沿同步输入的SDR数据。
CE:时钟使能信号;
S/R:置位/复位信号,这两个信号不能同时拉高。
ODDR原语模板如下:

  1. ODDR #(
  2. .DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE"
  3. .INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1
  4. .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
  5. ) ODDR_inst (
  6. .Q(Q), // 1-bit DDR output
  7. .C(C), // 1-bit clock input
  8. .CE(CE), // 1-bit clock enable input
  9. .D1(D1), // 1-bit data input (positive edge)
  10. .D2(D2), // 1-bit data input (negative edge)
  11. .R(R), // 1-bit reset
  12. .S(S) // 1-bit set
  13. );


DDR_CLK_EDGE参数为ODDR的两种输出模式,分别为“OPPOSITE_EDGE”和“SAME_EDGE”模式。
OPPOSITE_EDGE模式的时序图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第20张图片

图 25.1.20 ODDR OPPOSITE_EDGE模式时序图


此种模式下,在FPGA内部需要两个反相时钟来同步D1和D2,此种模式使用较少。
SAME_EDGE模式的时序图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第21张图片

图 25.1.21 ODDR SAME_EDGE模式时序图


此种模式下,数据可以在相同的时钟边沿输出到Q,一般采用此种模式。
IDELAYE2:IO延时原语,用于在信号通过引脚进入芯片内部之前,进行延时调节,一般高速端口信号由于走线延时等原因,需要通过IDELAYE2原语对数据做微调。IDELAYE2原语模板如下:

  1. IDELAYE2 #(
  2. .CINVCTRL_SEL("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE)
  3. .DELAY_SRC("IDATAIN"), // Delay input (IDATAIN, DATAIN)
  4. .HIGH_PERFORMANCE_MODE("FALSE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")
  5. .IDELAY_TYPE("FIXED"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
  6. .IDELAY_VALUE(0), // Input delay tap setting (0-31)
  7. .PIPE_SEL("FALSE"), // Select pipelined mode, FALSE, TRUE
  8. .REFCLK_FREQUENCY(200.0), // IDELAYCTRL clock input frequency in MHz
  9. .SIGNAL_PATTERN("DATA") // DATA, CLOCK input signal
  10. )
  11. IDELAYE2_inst (
  12. .CNTVALUEOUT(CNTVALUEOUT), // 5-bit output: Counter value output
  13. .DATAOUT(DATAOUT), // 1-bit output: Delayed data output
  14. .C(C), // 1-bit input: Clock input
  15. .CE(CE), // 1-bit input: Active high enable increment/decrement input
  16. .CINVCTRL(CINVCTRL), // 1-bit input: Dynamic clock inversion input
  17. .CNTVALUEIN(CNTVALUEIN), // 5-bit input: Counter value input
  18. .DATAIN(DATAIN), // 1-bit input: Internal delay data input
  19. .IDATAIN(IDATAIN), // 1-bit input: Data input from the I/O
  20. .INC(INC), // 1-bit input: Increment / Decrement tap delay input
  21. .LD(LD), // 1-bit input: Load IDELAY_VALUE input
  22. .LDPIPEEN(LDPIPEEN), // 1-bit input: Enable PIPELINE register to load data input
  23. .REGRST(REGRST) // 1-bit input: Active-high reset tap-delay input
  24. );


IDATAIN为延时前的输入信号,DATAOUT为延时后的输出信号。
REFCLK_FREQUENCY参数为IDELAYCTRL原语的参考时钟频率,一般为200Mhz; IDELAY_VALUE参数用来设置延时的tap数,范围为1~31,每个tap数的延时时间和参考时钟频率有关。
和IDELAYE2对应的还有ODELAYE2,由于A7系列没有ODELAYE2原语,故此处不做讨论。
IDELAYCTRL:IDELAYCTRL和IDELAYE2一般同时使用,IDELAYCTRL对IDELAYE2延时进行校准。IDELAYE2原语如下:

  1. (* IODELAY_GROUP = *)
  2. IDELAYCTRL IDELAYCTRL_inst (
  3. .RDY(RDY), // 1-bit output: Ready output
  4. .REFCLK(REFCLK), // 1-bit input: Reference clock input
  5. .RST(RST) // 1-bit input: Active high reset input
  6. );


IODELAY_GROUP为延时IO分组,一般数据接口位于多个BANK时,才需要分组。
IDELAYCTRL通过参考时钟REFCLK来校准IDELAY2每个tap的延时值,可用的REFCLK频率为190Mhz~210Mhz或者290Mhz~310Mhz。时钟频率越高对应的tap延时平均值越小,即延时调节精度越高。当参考时钟为200Mhz时,一个tap为78ps。
25.2实验任务
本节实验任务是使用领航者ZYNQ开发板上的PL端以太网接口,和上位机实现ARP请求和应答的功能。当上位机发送ARP请求时,开发板返回ARP应答数据。当按下开发板的触摸按键时,开发板发送ARP请求,此时上位机返回应答数据。
25.3硬件设计
PL端千兆以太网接口部分的硬件设计原理和“MDIO接口读写测试实验” 完全相同,请参考“MDIO接口读写测试实验”中的硬件设计部分。
本实验中,各端口信号的管脚分配如下表所示:
表 25.3.1 以太网ARP测试实验管脚分配

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第22张图片


对应的XDC约束语句如下所示:

  1. create_clock -period 20.000 -name sys_clk [get_ports sys_clk]
  2. create_clock -period 8.000 -name eth_rxc [get_ports eth_rxc]
  3. set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
  4. set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
  5. set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports touch_key]
  6. #GE_PL
  7. set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS33} [get_ports eth_rst_n]
  8. set_property -dict {PACKAGE_PIN K17 IOSTANDARD LVCMOS33} [get_ports eth_rxc]
  9. set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports eth_rx_ctl]
  10. set_property -dict {PACKAGE_PIN F19 IOSTANDARD LVCMOS33} [get_ports {eth_rxd[0]}]
  11. set_property -dict {PACKAGE_PIN F20 IOSTANDARD LVCMOS33} [get_ports {eth_rxd[1]}]
  12. set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS33} [get_ports {eth_rxd[2]}]
  13. set_property -dict {PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports {eth_rxd[3]}]
  14. set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS33} [get_ports eth_txc]
  15. set_property -dict {PACKAGE_PIN E19 IOSTANDARD LVCMOS33} [get_ports eth_tx_ctl]
  16. set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS33} [get_ports {eth_txd[0]}]
  17. set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports {eth_txd[1]}]
  18. set_property -dict {PACKAGE_PIN F17 IOSTANDARD LVCMOS33} [get_ports {eth_txd[2]}]
  19. set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS33} [get_ports {eth_txd[3]}]


25.4程序设计
根据实验任务,我们可以大致规划出系统的控制流程:首先我们需要完成RGMII接口数据和GMII接口数据的转换,以方便数据的采集和解析,在数据采集过程中所用到的延时原语参考时钟由锁相环输出的时钟提供;其次整个以太网帧格式与ARP协议的实现由ARP顶层模块完成;ARP控制模块负责检测输入的触摸按键是否被按下,控制ARP顶层模块发起请求与产生应答等操作。由此画出系统的功能框图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第23张图片

图 25.4.1 以太网ARP测试系统框图


系统时钟经过PLL时钟模块后,输出200Mhz的时钟,用于IDELAYCTRL原语的参考时钟;GMII TO RGMII模块负责将双沿(DDR)数据和单沿(SDR)数据之间的转换;ARP顶层模块实现了以太网ARP数据包的接收、发送以及CRC校验的功能;ARP控制模块根据输入的按键触摸信号和接收到的ARP请求信号,控制ARP顶层模块发送ARP请求或者ARP应答。
各模块端口及信号连接如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第24张图片

图 25.4.2 顶层模块原理图


由上图可知,FPGA顶层模块例化了以下四个模块,PLL时钟模块(clk_wiz)、GMII TO RGMII模块(gmii_to_rgmii)、ARP顶层模块(arp)和ARP控制模块(arp_ctrl),实现了各模块之间的数据交互。
其中ARP顶层模块和GMII TO RGMII模块内部也例化了多个其它模块,这样设计的目的是为了方便模块的重用。
顶层模块的代码如下:

  1. 1 module eth_arp_test(
  2. 2 input sys_clk , //系统时钟
  3. 3 input sys_rst_n , //系统复位信号,低电平有效
  4. 4 input touch_key , //触摸按键,用于触发开发板发出ARP请求
  5. 5 //PL以太网RGMII接口
  6. 6 input eth_rxc , //RGMII接收数据时钟
  7. 7 input eth_rx_ctl, //RGMII输入数据有效信号
  8. 8 input [3:0] eth_rxd , //RGMII输入数据
  9. 9 output eth_txc , //RGMII发送数据时钟
  10. 10 output eth_tx_ctl, //RGMII输出数据有效信号
  11. 11 output [3:0] eth_txd , //RGMII输出数据
  12. 12 output eth_rst_n //以太网芯片复位信号,低电平有效
  13. 13 );
  14. 14
  15. 15 //parameter define
  16. 16 //开发板MAC地址 00-11-22-33-44-55
  17. 17 parameter BOARD_MAC = 48'h00_11_22_33_44_55;
  18. 18 //开发板IP地址 192.168.1.10
  19. 19 parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd10};
  20. 20 //目的MAC地址 ff_ff_ff_ff_ff_ff
  21. 21 parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;
  22. 22 //目的IP地址 192.168.1.102
  23. 23 parameter DES_IP = {8'd192,8'd168,8'd1,8'd102};
  24. 24 //输入数据IO延时(如果为n,表示延时n*78ps)
  25. 25 parameter IDELAY_VALUE = 16;
  26. 26
  27. 27 //wire define
  28. 28 wire clk_200m ; //用于IO延时的时钟
  29. 29
  30. 30 wire gmii_rx_clk; //GMII接收时钟
  31. 31 wire gmii_rx_dv ; //GMII接收数据有效信号
  32. 32 wire [7:0] gmii_rxd ; //GMII接收数据
  33. 33 wire gmii_tx_clk; //GMII发送时钟
  34. 34 wire gmii_tx_en ; //GMII发送数据使能信号
  35. 35 wire [7:0] gmii_txd ; //GMII发送数据
  36. 36
  37. 37 wire arp_rx_done; //ARP接收完成信号
  38. 38 wire arp_rx_type; //ARP接收类型 0:请求 1:应答
  39. 39 wire [47:0] src_mac ; //接收到目的MAC地址
  40. 40 wire [31:0] src_ip ; //接收到目的IP地址
  41. 41 wire arp_tx_en ; //ARP发送使能信号
  42. 42 wire arp_tx_type; //ARP发送类型 0:请求 1:应答
  43. 43 wire tx_done ; //发送的目标MAC地址
  44. 44 wire [47:0] des_mac ; //发送的目标IP地址
  45. 45 wire [31:0] des_ip ; //以太网发送完成信号
  46. 46
  47. 47 //*****************************************************
  48. 48 //** main code
  49. 49 //*****************************************************
  50. 50
  51. 51 assign des_mac = src_mac;
  52. 52 assign des_ip = src_ip;
  53. 53 assign eth_rst_n = sys_rst_n;
  54. 54
  55. 55 //MMCM/PLL
  56. 56 clk_wiz u_clk_wiz
  57. 57 (
  58. 58 .clk_in1 (sys_clk ),
  59. 59 .clk_out1 (clk_200m ),
  60. 60 .reset (~sys_rst_n),
  61. 61 .locked (locked)
  62. 62 );
  63. 63
  64. 64 //GMII接口转RGMII接口
  65. 65 gmii_to_rgmii
  66. 66 #(
  67. 67 .IDELAY_VALUE (IDELAY_VALUE)
  68. 68 )
  69. 69 u_gmii_to_rgmii(
  70. 70 .idelay_clk (clk_200m ),
  71. 71
  72. 72 .gmii_rx_clk (gmii_rx_clk ),
  73. 73 .gmii_rx_dv (gmii_rx_dv ),
  74. 74 .gmii_rxd (gmii_rxd ),
  75. 75 .gmii_tx_clk (gmii_tx_clk ),
  76. 76 .gmii_tx_en (gmii_tx_en ),
  77. 77 .gmii_txd (gmii_txd ),
  78. 78
  79. 79 .rgmii_rxc (eth_rxc ),
  80. 80 .rgmii_rx_ctl (eth_rx_ctl ),
  81. 81 .rgmii_rxd (eth_rxd ),
  82. 82 .rgmii_txc (eth_txc ),
  83. 83 .rgmii_tx_ctl (eth_tx_ctl ),
  84. 84 .rgmii_txd (eth_txd )
  85. 85 );
  86. 86
  87. 87 //ARP通信
  88. 88 arp
  89. 89 #(
  90. 90 .BOARD_MAC (BOARD_MAC), //参数例化
  91. 91 .BOARD_IP (BOARD_IP ),
  92. 92 .DES_MAC (DES_MAC ),
  93. 93 .DES_IP (DES_IP )
  94. 94 )
  95. 95 u_arp(
  96. 96 .rst_n (sys_rst_n ),
  97. 97
  98. 98 .gmii_rx_clk (gmii_rx_clk),
  99. 99 .gmii_rx_dv (gmii_rx_dv ),
  100. 100 .gmii_rxd (gmii_rxd ),
  101. 101 .gmii_tx_clk (gmii_tx_clk),
  102. 102 .gmii_tx_en (gmii_tx_en ),
  103. 103 .gmii_txd (gmii_txd ),
  104. 104
  105. 105 .arp_rx_done (arp_rx_done),
  106. 106 .arp_rx_type (arp_rx_type),
  107. 107 .src_mac (src_mac ),
  108. 108 .src_ip (src_ip ),
  109. 109 .arp_tx_en (arp_tx_en ),
  110. 110 .arp_tx_type (arp_tx_type),
  111. 111 .des_mac (des_mac ),
  112. 112 .des_ip (des_ip ),
  113. 113 .tx_done (tx_done )
  114. 114 );
  115. 115
  116. 116 //ARP控制
  117. 117 arp_ctrl u_arp_ctrl(
  118. 118 .clk (gmii_rx_clk),
  119. 119 .rst_n (sys_rst_n),
  120. 120
  121. 121 .touch_key (touch_key),
  122. 122 .arp_rx_done (arp_rx_done),
  123. 123 .arp_rx_type (arp_rx_type),
  124. 124 .arp_tx_en (arp_tx_en),
  125. 125 .arp_tx_type (arp_tx_type)
  126. 126 );
  127. 127
  128. 128 endmodule


顶层模块主要完成对其余模块的例化。在程序的第16行至第23行代码定义了开发板的MAC地址、IP地址、默认的目的MAC地址和目的IP地址。开发板的MAC地址为00:11:22:33:44:55;可开发板的IP地址为192.168.1.10;默认目的MAC地址为ff:ff:ff:ff:ff:ff,这是一个广播MAC地址,在收到上位机的请求或者应答之后,ARP模块会替换成实际的目的MAC地址。目的IP地址这里设置为192.168.1.102,因此大家在做本次实验时,需要把电脑的以太网的IP地址改成192.168.1.102,或者将代码中定义的DES_IP改成电脑的IP地址。
程序的第25行设置IDELAY_VALUE的值为8,由于IDELAYCTRL原语的参考时钟为200Mhz,对应每个tap的延时时间为78ps,RGMII输入数据和控制信号相对于RXC时钟共延时了16*78ps=1248ps,这也是我们实测非常稳定的一个值。
程序的第52行和53行代码将收到的对端设备MAC地址和目的IP地址,作为开发板发送时的目的MAC地址和IP地址。
gmii_to_rgmii模块代码如下:

  1. 1 module gmii_to_rgmii(
  2. 2 input idelay_clk , //IDELAY时钟
  3. 3 //以太网GMII接口
  4. 4 output gmii_rx_clk , //GMII接收时钟
  5. 5 output gmii_rx_dv , //GMII接收数据有效信号
  6. 6 output [7:0] gmii_rxd , //GMII接收数据
  7. 7 output gmii_tx_clk , //GMII发送时钟
  8. 8 input gmii_tx_en , //GMII发送数据使能信号
  9. 9 input [7:0] gmii_txd , //GMII发送数据
  10. 10 //以太网RGMII接口
  11. 11 input rgmii_rxc , //RGMII接收时钟
  12. 12 input rgmii_rx_ctl, //RGMII接收数据控制信号
  13. 13 input [3:0] rgmii_rxd , //RGMII接收数据
  14. 14 output rgmii_txc , //RGMII发送时钟
  15. 15 output rgmii_tx_ctl, //RGMII发送数据控制信号
  16. 16 output [3:0] rgmii_txd //RGMII发送数据
  17. 17 );
  18. 18
  19. 19 //parameter define
  20. 20 parameter IDELAY_VALUE = 0; //输入数据IO延时(如果为n,表示延时n*78ps)
  21. 21
  22. 22 //*****************************************************
  23. 23 //** main code
  24. 24 //*****************************************************
  25. 25
  26. 26 assign gmii_tx_clk = gmii_rx_clk;
  27. 27
  28. 28 //RGMII接收
  29. 29 rgmii_rx
  30. 30 #(
  31. 31 .IDELAY_VALUE (IDELAY_VALUE)
  32. 32 )
  33. 33 u_rgmii_rx(
  34. 34 .idelay_clk (idelay_clk),
  35. 35 .gmii_rx_clk (gmii_rx_clk),
  36. 36 .rgmii_rxc (rgmii_rxc ),
  37. 37 .rgmii_rx_ctl (rgmii_rx_ctl),
  38. 38 .rgmii_rxd (rgmii_rxd ),
  39. 39
  40. 40 .gmii_rx_dv (gmii_rx_dv ),
  41. 41 .gmii_rxd (gmii_rxd )
  42. 42 );
  43. 43
  44. 44 //RGMII发送
  45. 45 rgmii_tx u_rgmii_tx(
  46. 46 .gmii_tx_clk (gmii_tx_clk ),
  47. 47 .gmii_tx_en (gmii_tx_en ),
  48. 48 .gmii_txd (gmii_txd ),
  49. 49
  50. 50 .rgmii_txc (rgmii_txc ),
  51. 51 .rgmii_tx_ctl (rgmii_tx_ctl),
  52. 52 .rgmii_txd (rgmii_txd )
  53. 53 );
  54. 54
  55. 55 endmodule


由该模块的端口可知,该模块实现了双沿(DDR)数据和单沿(SDR)数据之间的转换。程序中第26行将GMII接收时钟赋值给GMII发送时钟,因此GMII的发送时钟和接收时钟实际上为同一个时钟。GMII TO RGMII模块例化了rgmii_rx模块和rgmii_tx模块。
rgmii_rx模块代码如下所示:

  1. 1 module rgmii_rx(
  2. 2 input idelay_clk , //200Mhz时钟,IDELAY时钟
  3. 3
  4. 4 //以太网RGMII接口
  5. 5 input rgmii_rxc , //RGMII接收时钟
  6. 6 input rgmii_rx_ctl, //RGMII接收数据控制信号
  7. 7 input [3:0] rgmii_rxd , //RGMII接收数据
  8. 8
  9. 9 //以太网GMII接口
  10. 10 output gmii_rx_clk , //GMII接收时钟
  11. 11 output gmii_rx_dv , //GMII接收数据有效信号
  12. 12 output [7:0] gmii_rxd //GMII接收数据
  13. 13 );
  14. 14
  15. 15 //parameter define
  16. 16 parameter IDELAY_VALUE = 0;
  17. 17
  18. 18 //wire define
  19. 19 wire rgmii_rxc_bufg; //全局时钟缓存
  20. 20 wire rgmii_rxc_bufio; //全局时钟IO缓存
  21. 21 wire [3:0] rgmii_rxd_delay; //rgmii_rxd输入延时
  22. 22 wire rgmii_rx_ctl_delay; //rgmii_rx_ctl输入延时
  23. 23 wire [1:0] gmii_rxdv_t; //两位GMII接收有效信号
  24. 24
  25. 25 //*****************************************************
  26. 26 //** main code
  27. 27 //*****************************************************
  28. 28
  29. 29 assign gmii_rx_clk = rgmii_rxc_bufg;
  30. 30 assign gmii_rx_dv = gmii_rxdv_t[0] & gmii_rxdv_t[1];
  31. 31
  32. 32 //全局时钟缓存
  33. 33 BUFG BUFG_inst (
  34. 34 .I (rgmii_rxc), // 1-bit input: Clock input
  35. 35 .O (rgmii_rxc_bufg) // 1-bit output: Clock output
  36. 36 );
  37. 37
  38. 38 //全局时钟IO缓存
  39. 39 BUFIO BUFIO_inst (
  40. 40 .I (rgmii_rxc), // 1-bit input: Clock input
  41. 41 .O (rgmii_rxc_bufio) // 1-bit output: Clock output
  42. 42 );
  43. 43
  44. 44 //输入延时控制
  45. 45 // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
  46. 46 (* IODELAY_GROUP = "rgmii_rx_delay" *)
  47. 47 IDELAYCTRL IDELAYCTRL_inst (
  48. 48 .RDY(), // 1-bit output: Ready output
  49. 49 .REFCLK(idelay_clk), // 1-bit input: Reference clock input
  50. 50 .RST(1'b0) // 1-bit input: Active high reset input
  51. 51 );
  52. 52
  53. 53 //rgmii_rx_ctl输入延时与双沿采样
  54. 54 (* IODELAY_GROUP = "rgmii_rx_delay" *)
  55. 55 IDELAYE2 #(
  56. 56 .IDELAY_TYPE ("FIXED"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
  57. 57 .IDELAY_VALUE (IDELAY_VALUE), // Input delay tap setting (0-31)
  58. 58 .REFCLK_FREQUENCY(200.0) // IDELAYCTRL clock input frequency in MHz
  59. 59 )
  60. 60 u_delay_rx_ctrl (
  61. 61 .CNTVALUEOUT (), // 5-bit output: Counter value output
  62. 62 .DATAOUT (rgmii_rx_ctl_delay),// 1-bit output: Delayed data output
  63. 63 .C (1'b0), // 1-bit input: Clock input
  64. 64 .CE (1'b0), // 1-bit input: enable increment/decrement
  65. 65 .CINVCTRL (1'b0), // 1-bit input: Dynamic clock inversion input
  66. 66 .CNTVALUEIN (5'b0), // 5-bit input: Counter value input
  67. 67 .DATAIN (1'b0), // 1-bit input: Internal delay data input
  68. 68 .IDATAIN (rgmii_rx_ctl), // 1-bit input: Data input from the I/O
  69. 69 .INC (1'b0), // 1-bit input: Increment / Decrement tap delay
  70. 70 .LD (1'b0), // 1-bit input: Load IDELAY_VALUE input
  71. 71 .LDPIPEEN (1'b0), // 1-bit input: Enable PIPELINE register
  72. 72 .REGRST (1'b0) // 1-bit input: Active-high reset tap-delay input
  73. 73 );
  74. 74
  75. 75 //输入双沿采样寄存器
  76. 76 IDDR #(
  77. 77 .DDR_CLK_EDGE("SAME_EDGE_PIPELINED"),// "OPPOSITE_EDGE", "SAME_EDGE"
  78. 78 // or "SAME_EDGE_PIPELINED"
  79. 79 .INIT_Q1 (1'b0), // Initial value of Q1: 1'b0 or 1'b1
  80. 80 .INIT_Q2 (1'b0), // Initial value of Q2: 1'b0 or 1'b1
  81. 81 .SRTYPE ("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
  82. 82 ) u_iddr_rx_ctl (
  83. 83 .Q1 (gmii_rxdv_t[0]), // 1-bit output for positive edge of clock
  84. 84 .Q2 (gmii_rxdv_t[1]), // 1-bit output for negative edge of clock
  85. 85 .C (rgmii_rxc_bufio), // 1-bit clock input
  86. 86 .CE (1'b1), // 1-bit clock enable input
  87. 87 .D (rgmii_rx_ctl_delay), // 1-bit DDR data input
  88. 88 .R (1'b0), // 1-bit reset
  89. 89 .S (1'b0) // 1-bit set
  90. 90 );
  91. 91
  92. 92 //rgmii_rxd输入延时与双沿采样
  93. 93 genvar i;
  94. 94 generate for (i=0; i<4; i=i+1)
  95. 95 (* IODELAY_GROUP = "rgmii_rx_delay" *)
  96. 96 begin : rxdata_bus
  97. 97 //输入延时
  98. 98 (* IODELAY_GROUP = "rgmii_rx_delay" *)
  99. 99 IDELAYE2 #(
  100. 100 .IDELAY_TYPE ("FIXED"), // FIXED,VARIABLE,VAR_LOAD,VAR_LOAD_PIPE
  101. 101 .IDELAY_VALUE (IDELAY_VALUE), // Input delay tap setting (0-31)
  102. 102 .REFCLK_FREQUENCY(200.0) // IDELAYCTRL clock input frequency in MHz
  103. 103 )
  104. 104 u_delay_rxd (
  105. 105 .CNTVALUEOUT (), // 5-bit output: Counter value output
  106. 106 .DATAOUT (rgmii_rxd_delay),// 1-bit output: Delayed data output
  107. 107 .C (1'b0), // 1-bit input: Clock input
  108. 108 .CE (1'b0), // 1-bit input: enable increment/decrement
  109. 109 .CINVCTRL (1'b0), // 1-bit input: Dynamic clock inversion
  110. 110 .CNTVALUEIN (5'b0), // 5-bit input: Counter value input
  111. 111 .DATAIN (1'b0), // 1-bit input: Internal delay data input
  112. 112 .IDATAIN (rgmii_rxd), // 1-bit input: Data input from the I/O
  113. 113 .INC (1'b0), // 1-bit input: Inc/Decrement tap delay
  114. 114 .LD (1'b0), // 1-bit input: Load IDELAY_VALUE input
  115. 115 .LDPIPEEN (1'b0), // 1-bit input: Enable PIPELINE register
  116. 116 .REGRST (1'b0) // 1-bit input: Active-high reset tap-delay
  117. 117 );
  118. 118
  119. 119 //输入双沿采样寄存器
  120. 120 IDDR #(
  121. 121 .DDR_CLK_EDGE("SAME_EDGE_PIPELINED"),// "OPPOSITE_EDGE", "SAME_EDGE"
  122. 122 // or "SAME_EDGE_PIPELINED"
  123. 123 .INIT_Q1 (1'b0), // Initial value of Q1: 1'b0 or 1'b1
  124. 124 .INIT_Q2 (1'b0), // Initial value of Q2: 1'b0 or 1'b1
  125. 125 .SRTYPE ("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
  126. 126 ) u_iddr_rxd (
  127. 127 .Q1 (gmii_rxd), // 1-bit output for positive edge of clock
  128. 128 .Q2 (gmii_rxd[4+i]), // 1-bit output for negative edge of clock
  129. 129 .C (rgmii_rxc_bufio), // 1-bit clock input rgmii_rxc_bufio
  130. 130 .CE (1'b1), // 1-bit clock enable input
  131. 131 .D (rgmii_rxd_delay), // 1-bit DDR data input
  132. 132 .R (1'b0), // 1-bit reset
  133. 133 .S (1'b0) // 1-bit set
  134. 134 );
  135. 135 end
  136. 136 endgenerate
  137. 137
  138. 138 endmodule


该模块通过调用BUFG、BUFIO、IDDR、IDELAYCTRL和IDELAY2原语,实现了RGMII接口输入的DDR数据到SDR数据的转换,输入的rgmii_rx_ctl控制信号的转换方法同样类似。rgmii_rx模块信号转换示意图如下图所示:

ec20 以太网_「正点原子FPGA连载」第二十五章以太网ARP测试实验(一)_第25张图片

图 25.4.3 rgmii_rx模块信号转换示意图

你可能感兴趣的:(ec20,以太网,韦东山,IMX6ULL和正点原子)