高速接口----7系列收发器GTP(1)

1. 前言

  最近在做以太网相关的东西,其中一个其中想要使用MAC通过光电转换模块来完成数据的收发。在Artix7系列FPGA当中,有GTP这个高速收发器。我手上的板子上的核心芯片是ZYNQ7015,这是一个带一个QUAD的ZYNQ FPGA,上面的收发器是GTP。对于其他稍微高端一点的ZYNQ上带有收发器应该是GTH/GTX的。但是,只是实现一个千兆网,使用GTP应该是足够了。因此需要了解收发器的使用。
  本篇博客当中,我只介绍我在初次使用7 Serie FPGA Transceiver Wizard所进行的一些自认为比较重要的东西。

2. UG482

2.1 整体结构

  因为手上的ZYNQ芯片带有的收发器是GTP,因此需要参考的手册是ug482,对于GTH/GTX则需要参考ug476。其实GTP和GTX/GTH还是比较相似的,GTP内部的结构和GTX/GTH稍有不同。
在这里插入图片描述

  上面的图是手册上给出的100T内部的收发器分布图,可以看到对于Artix7系列FPGA的收发器,其是分布在上下两侧的,这与GTX/GTH单列放置是一个区别。

  下图是每个QUAD内部的结构:一个QUAD中包含4个channel和一个COMMON。GTPE2_COMMON 中包含两个PLL(PLL0/PLL1),使用到收发器时,COMMON原语必须被例化。每个CHANNEL中都包含一个接收器和一个发送器。
在这里插入图片描述
  下图是收发器每个CHANNEL中的结构:TX/RX都包含两部分,其中PCS是物理编码层,PMA是物理媒介层。
在这里插入图片描述

2.2参考时钟

  GTP中的参考时钟选项和GTX/GTH中略有不同,在GTH/GTX中,支持南北方向的时钟路由,在GTP当中支持东西方向的时钟路由。
  一个QUAD中包含4个GTPE2_CHANNEL原语,一个GTPE2_COMMON 原语,两个外部参考时钟引脚以及专用参考时钟的路由。
  在A7系列FPGA当中,位于上半部分的收发器可以进行时钟的共享,位于下半部分的收发器可以进行时钟的共享。
在下图中,COMMON原语的时钟输入可以有以下几种:两个参考时钟,来自另一个QUAD的参考时钟
在这里插入图片描述

2.2.1COMMON参考时钟

  GTP COMMON中时钟的选择:common中的每一个PLL时钟来源都包含7个分别为:一个用于测试的时钟,两个外部参考时钟,两个东向参考时钟,两个西向参考时钟,通过PLL0/1REFCLKSEL 来选择具体使用到的时钟参考源。
在这里插入图片描述

2.2.2 CHANNEL 参考时钟

  GTP CHANNEL的端口具体可以分为,用于选择RX/TX的参考时钟和数据的参考时钟,参考时钟可以来自PLL,也可以来自PLL的参考时钟。
在这里插入图片描述
  下图是包含了各种情况的时钟路由方式
在这里插入图片描述
  值得说明的是,这些端口和选项,在GTP的向导这个IP中,都不用可以去记,在向导里面只需设置就可以,IP会自动生成这些逻辑。
在这里插入图片描述

3 发送器TX

3.1 TX interface

 &esmp;TX interface 简单来说,就是位于FPGA逻辑侧和收发器发送这一侧的端口。从这里开始收发器会将FPGA中想要发送的数据进行发送。这里是收发器发送数据的第一步。TX Interface 是与用于逻辑联系最紧密的一个模块,该模块决定了FPGA侧数据的位宽和收发器传输的线速率,并且该模块还与数据的编码有关。

3.1.1 数据位宽

  GTP包含2字节的内部数据通道,TX 部分的Interface 的数据位宽通过TX_DATA_WIDTH 属性来配置。当8B/10B编码被使能的时候,TX_DATA_WIDTH必须被配置为20bit/bit。当不使能8B/10B编码的时候,TX_DATA_WIDTH 可以被配置为16,20,32,40。
  当不使用8B/10B编码的时候,必须使用TXCHARDISPMODE & TXCHARDISPVAL 来对位宽进行扩充,扩充位宽的方法是每1byte用户数据需要1bit 的TXCHARDISPMODE和 1bit 的TXCHARDISPVAL来对数据进行扩充。如图中的Table 3-2 所示。
在这里插入图片描述

3.1.2 用户时钟

  FPGA TX接口包含两个并行时钟:TXUSRCLK和TXUSRCLK2。TXUSRCLK是GTP内部PCS部分的内部时钟,TXUSRCLK所需要的速率取决于GTPE2_CHANNEL原语内部的数据路径宽度和TX 的线速率。
在这里插入图片描述
  TXUSRCLK2是所有进入到GTP TX接口的信号的主要的同步时钟。进入到TXUSRCLK的大多数数据在TXUSRCLK的上升沿进行采样。TXUSRCLK2和TXUSRCLK具有固定的频率关系。根据TX_DATA_WIDTH的值来确定:
在这里插入图片描述
  从上面的图中可以看出,TXUSRCLK2的时钟频率在不同的模式下可以为TXUSRCLK或者TXUSRCLK的一半,TXUSRCLK 和TXUSRCLK2一般都是由TX接口上的TXOUTCLK来生成的。下面的两幅图中,可以看到TXUSRCLK和TXUSRCLK在不同模式下的生成的示意图。
在这里插入图片描述
在这里插入图片描述
  在这之中,TXUSRCLK2一般都是给到用户侧逻辑来使用的,也就是说,用户在使用GTP发送数据时,一般都使用TXUSRCLK2来进行发送。

3.1.3 具体例子

  下图中设置了线速率为5GT,参考时钟时根据开发板上的参考时钟来指定的。
在这里插入图片描述

  在使用IP来配置端口将数据位宽设置为16bit,收发器发送通道内部的数据位宽为20bit。可以由线速率计算出发送时钟TXUSRCLK = 5Gbps/20bit = 250MHz。 因为用户数据位宽为16bit,是2byte mode,因此TXUSRCLK2 的频率也为250MHz
在这里插入图片描述
在这里插入图片描述

3.2 8B/10B编码器

  8B/10B编码器也是我认位在TX 通道中比较重要的一个模块。因为在该模块下,有一个比较重要的概念叫做
K Characters(K 字符),由于这些字符的添加,使得在数据传输的过程中,进行数据对齐提供了便利。
  在8B/10B编码器当中,还需要注意的是字节排序的顺序。当然如果使能了8B/10B编码,那么这个顺序就不用太关系,但是没有使用8B/10B编码也就是使用了8B/10B bypass这个模式,需要注意填充的字符1bit 的TXCHARDISPMODE和 1bit 的TXCHARDISPVAL在一个10bit数据中的位置。
   对于K 字符,在发送通道中是使用TXCHARISK[3:0]这个信号来指示的,通过拉高对应的bit位,来表示内部数据的哪一bit是K字符,不拉高的就是用户数据。
在这里插入图片描述

3.3 TX其他模块

在这里插入图片描述
  TX的其他模块,离用户逻辑较远,我在实验的时候没有太关心。简单来说:

模块作用
Gearbox传输速率控制,GTP支持不同类型的编码 (8B/10B, 64B/66B, 64B/67B)
使用这些编码的时候,由于在用户数据中插入数据后,数据需要在多个周期才能完整地传输。
因此需要速率控制来达到调节地作用
TxBuffer根据字面意思,就是一个Buffer,用于进行时钟域转换的,保证数据和时钟的对齐关系
TxbufferBypass不经过buffer也能使数据和时钟对齐,通过直接对时钟进行相位校正的方式
TX Pattern Generator产生伪随机数,来对收发器进行测试验证时使用
TX Polarity Control收发对的极性控制,感觉就是方便PCB布线,极性反了还可以补救
TX Fabric Clock Output Control收发器TX内部也能产生时钟,前面介绍的TXOUCLK就是在收发器内部产生的

  剩下的还有PCIE和SATA使用的一些资源,可以通过使用这些端口来完成PCIE和SATA协议的实现。

4 接收器RX

RX 与 TX就像是一个逆过程,RX实现的功能与TX基本相反,也就是RX完成数据接收,负责串行转并行并对串行数据进行解码,得到用户数据。我也只介绍其中我觉得比较重要的模块。
在这里插入图片描述

4.1 CDR模块

  高速串行接口在传输数据时,高速数据中包含了时钟信息,因此可以通过一定的方式,将时钟信息从串行数据中恢复出来。CDR模块所完成的功能就是恢复出串行时钟。在最终的用户接收模块中,可以看到接收模块用户侧时钟来源可以是TX模块,也可以是由CDR模块恢复出来的时钟。
在这里插入图片描述

4.2 字节对齐模块

  串行数据必须经过对齐后才能转换成并行数据给用户使用。为了能够识别这些编解,就需要使用到前面在TX模块中介绍到的K Characters(K 字符),这些字符也被叫做comma。接收器在输入数据中搜索comma。 当找到comma时,它将comma移至字节边界,以便接收到的并行字与发送的并行字匹配。
在这里插入图片描述
  只有接收到了comma后,数据才会被对齐,然后就可以按照10bit,10bit来排列数据,供解码模块使用,最终得到用户数据。
  在字节对齐模块,常用的用于对齐的字符有K28.3,K28.5。在UG482的附录里面也给出了K字符表。在设置IP的时候,就可以选择comma来确定用于对齐的comma。
在这里插入图片描述
在这里插入图片描述
  其他模块基本就是TX模块的逆过程。

4 官方demo验证

4.1 示例IP配置

  接下来就使用官方的demo来验证以下 收发器向导IP的功能。
首先配置出一个IP:

  • GT Selection
    选择收发器类型,选择GTP,包含共享逻辑到IP中,这样用户就不用去考虑收发器的复位初始化和参数配置这些事情了。
    在这里插入图片描述
  • LineRate Refclk选择
    在这里插入图片描述
  • 编解码和用户时钟
    在这里插入图片描述
  • 其他选项默认即可。

4.2 打开示例工程

  点击open IP example design就可以打开示例工程。
在这里插入图片描述

4.2.1 发送模块

  可以看到示例工程比较简单,一个产生数据的模块用于从ROM中读出数据,ROM中的数据是包含码字的递增数。
在这里插入图片描述
其实这个示例工程中的ROM的数据一开始难以理解,弄个80bit位宽的的rom,最后实际上有用的只有16bit数据加上2bit的comma指示信号。
在这里插入图片描述

4.2.2 接收校验模块

  接收校验模块主要是实现,对数据的接收和进行校验,在该模块中需要去检测comma,通过comma来完成数据的对齐。

4.2.3 下载验证

  对示例工程进行简单的更改后,综合,然后下载到FPGA当中,通过ila来观察得到的结果。由于手上没有光纤,因此使用两个板子来进行验证,一个板子发给另一个板子。

  • 发送模块
    在这里插入图片描述
     可以看到,在发送模块,进行数据的发送,其中发送的数据是00~1e的递增数据,需要注意的是第二个数据0x02bc,其中0xbc是一个K28.5 comma
    在这里插入图片描述

4.2.4 接收模块

  接收模块中负责接收数据,接收到0xbc的时候,说明检测到K28.5,之后就要进行数据的对齐。
在这里插入图片描述
可以看到使用K28.5 能够实现数据收发的对齐,那么在自己实现一个小协议的时候,就可以根据使用K28.5来进行突发的数据传输。
------THE FINE-------
参考:


UG482

  • 11
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
在 Golang 中给用户报文加上 GTP-C(GPRS Tunneling Protocol - Control Plane)头部,可以通过创建一个结构体来表示 GTP-C 头部,并使用字节切片(byte slice)将头部数据添加到用户报文之前。 下面是一个示例代码,演示如何添加 GTP-C 头部到用户报文: ```go package main import ( "encoding/binary" "fmt" ) type GTPCHeader struct { Version uint8 ProtocolType uint8 MessageType uint8 MessageLength uint16 // 添加其他字段 } func main() { // 假设用户报文为一个字节切片 userData := []byte{0x01, 0x02, 0x03, 0x04} // 创建 GTP-C 头部结构体并设置字段值 gtpcHeader := GTPCHeader{ Version: 2, ProtocolType: 1, MessageType: 10, MessageLength: uint16(len(userData) + 8), // 头部长度为8字节 } // 创建一个新的字节切片,用于存放 GTP-C 头部和用户报文数据 gtpcData := make([]byte, 0, len(userData)+8) // 将 GTP-C 头部字段逐个添加到 gtpcData 字节切片中 gtpcData = append(gtpcData, gtpcHeader.Version) gtpcData = append(gtpcData, gtpcHeader.ProtocolType) gtpcData = append(gtpcData, gtpcHeader.MessageType) // 将 MessageLength 字段以大端字节序添加到 gtpcData 字节切片中 lenBytes := make([]byte, 2) binary.BigEndian.PutUint16(lenBytes, gtpcHeader.MessageLength) gtpcData = append(gtpcData, lenBytes...) // 添加其他字段到 gtpcData 字节切片 // ... // 添加用户报文数据到 gtpcData 字节切片 gtpcData = append(gtpcData, userData...) // 打印包含 GTP-C 头部的完整报文 fmt.Printf("GTP-C Packet: %v\n", gtpcData) } ``` 上述代码中,我们创建了一个结构体 `GTPCHeader` 来表示 GTP-C 头部的字段。然后,我们假设用户报文数据为一个字节切片 `userData`。我们计算出头部的 `MessageLength` 字段,并逐个将头部字段添加到 `gtpcData` 字节切片中。最后,我们将用户报文数据添加到 `gtpcData` 中,得到包含 GTP-C 头部的完整报文。 请根据实际需求修改代码中的字段和数据,并根据 GTP-C 协议规范设置正确的字段值和字节顺序。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值