Xilinx 7系列高速收发器GTX
说明:
FPGA:
TX端_zynq(7z035)
RX端_zynq(7z100)。
两个FPGA通过SFP(光纤)接口相连进行GTX的通信。
环境:Vivado2018.2。
IP核:7 Series FPGAs Transceivers Wizard(3.6)
工程代码下载
从原理图中标号①中看出发送端SFP1接口连接在FPGA的BANK111,发送端我们只需要MGTXTXP1与MGTXTXN1两个差分信号端(TX)。
(2).GTX时钟:
如原理图中标号②SFP接口在BANK111中使用了差分时钟MGTREFCLK1(MGTREFCLK1P、MGTREFCLK1N)。所谓差分时钟,看图,实测的。
gtx时钟为156.25M。
(1).GTX端口:
接收端SFP1接口连接在FPGA的BANK110,接收端差分信号为MGT_110_RX0_P、MGT_110_RX0_N。
(2).GTX时钟:
接收端的采用的MGT_110_CLK1(MGT_110_CLK1_P、MGT_110_CLK1_N)差分时钟,为156.25M。
TX发送端框图:
框图解析:
发送端由PMA(Physical Media Attachment,物理媒介适配层)PCS(PhysicalCoding Sublayer,物理编码子层)组成
PMA子层包含高速串并转换(Serdes)、预/后加重、接收均衡、时钟发生器及时钟恢复电路。
PCS 子层包含8B/10B编解码、缓冲区、通道绑定和时钟修正电路。
PISO 并转串
SIPO串转并
FPGA内部并行数据通过FPGATX Interface进入TX发送端,然后经过PCS和PMA子层的各个功能电路处理之后,最终从TX驱动器中以高速串行数据输出
TX发送端时钟:
框图解析:
Phase Adjust FIFO:即TX BUFF。
PMA和PCS在不同的时钟域PMA(XCLK)、PCS(TXUSRCLK),中间的Phase Adjust FIFO(FIFO具有隔离时钟的功能)连接着不同的时钟域XCLK和TXUSRCLK,为了数据发送的稳定,XCLK和TXUSRCLK必须是速率匹配,相位差可以消除的,TX Buffer主要用于匹配两时钟域的速率和消除两时钟域之间的相位差。Phase Adjust FIFO也可以被旁路,TX发送端提供了一个相位对齐电路,可以解决XCLK和TXUSRCLK时钟域之间的相位差,但是TX_XCLK_SEL需设置为“TXUSR”来保持XCLK时钟域和TXUSRCLK保持同频。
TXUSRCLK2: 是进入GTX端的所有信号的主要同步时钟,进入GTX收发器TX端的大多数信号都经过在TXUSRCLK2上升沿的采样。 TXUSRCLK和TXUSRCLK2基于TX_DATA_WIDTH 和TX_INT_DATAWIDTH的设置有固定的速率。如下图描述:
TXUSRCLK与TXUSRCLK2对应关系:
RX接收端框图:
框图解析:
每个GTX收发器都包括一个独立的接收器,该接收器由一个PCS(物理编码子层 )和PMA(物理媒介附加子层)。
PCS (物理编码子层 ):负责串化/解串化
PMA (物理媒介附加子层):负责数据流的编码解码
高速串行数据从板上的走线到GTX的PMA中,进入PCS,最后进入FPGA逻辑。
PISO并转串
SIPO串转并
RX CDR 图中三角形处,因为GTX传输不带随路时钟,因此在接收端必须自己做 时钟恢复和数据恢复。
LPM、DFE 为RX接收端的均衡器
LPM功耗较低,DFE能提供更精确的滤波参数,从而可以更好的补偿传输信道损失,因此性能更好。
Polarity :极性控制,解决PCB上TX/RX反转的问题。
FPGA RX接口包括两个并行时钟:RXUSRCLK and RXUSRCLK2
RXUSRCLK 是GTX发送器中PCS(负责串化/解串化)逻辑的内部时钟。
RXUSRCLK 所需的速率取决于内部数据路径宽度
RXUSRCLK = 线速/内部数据路径宽度
RXUSRCLK2是所有同步信号进入RX端信号的主要同步时钟。
进入GTX收发器RX端的大多数信号是在RXUSRCLK2的上升沿采样。
RXUSRCLK2和RXUSRCLK 有一个基于RX_DATA_WIDTH和RX_INT_DATAWIDTH的固定速率关系,线速大于6.6Gb/s通过RX_INT_DATAWIDTH设置为1 ,需要使用4字节内部数据路径。
熟悉FPGA原理图后进行IP核的配置。点击IP Catalog。
搜索并选择7 Series FPGAs Transceivers Wizard。
page1:
GT Type选择gtx,勾选example。
page2:
线速率为: 3.125Gbps。
参考时钟:选择REFCLK1 Q2 大小为156.25MHz(原理图中GTX采用了时钟MGTREFCLK1,大小为156.25MHz)。
page3:
数据宽度:16bit。
编码方式:8B/10B.
内部数据宽度:自动设置为20bit。
DRP时钟为50M(连接到系统时钟)。
系统时钟:
page4:
page5:
没采用协议,保持默认。
page6:
保持默认。
page7:
配置总结,在这里线速率为3.125Gbps,内部数据宽度为20bit,所以RXUSRCLK2=3125/20=156.25MHz。
page1:
GT Type选择gtx,勾选example。
page2:
线速率为: 3.125Gbps。
参考时钟:选择REFCLK1 Q1 大小为156.25MHz(原理图中GTX采用了时钟MGT_110_CLK1,大小为156.25MHz)。
page3:
数据宽度:16bit。
编码方式:8B/10B.
内部数据宽度:自动设置为20bit。
DRP时钟为100M(连接到系统时钟)。
系统时钟:
page4:
K码选择K28.5。
page5:
默认。
page6:
默认。
page7:
配置总结,在这里线速率为3.125Gbps,内部数据宽度为20bit,所以RXUSRCLK2=3125/20=156.25MHz。
在配置好GTX的IP核后,打开IP核的example工程,做一定的修改并加入ILA核进行调试。
配置IP核后,点击Open IP Example Design生成IP核的Example工程。
打开Example工程,包含以下模块。
●注:
1.GT_FRAME_GEN为数据获取模块,在此模块中将本地文件gt_rom_init_tx.dat中的数据读取FPGA内部进行数据的传输。数据如下:
在GT_FRAME_GEN模块中可以看出读入的数据长度为512。
2.数据中BC为K码:K28.5,当K码出现时charisk信号为1(具体的16bit数据和charisk怎么从如下数据中提取出来的详细看GT_FRAME_GEN中代码)。如下:
Example工程中需要修改的地方
1.gtx_tx_exdes中gt0_data_valid_in拉高。
括号内替换为1’b1。
2.DRP时钟
默认DRP时钟为差分时钟。
因为我们要连接到系统时钟为单端时钟,所以进行以下修改(如果板子上有多余的差分时钟也可以之间连接)。
将DRP时钟的输入改为单端。
在COMMON PORTS处屏蔽差分转单端原语(IBUFDS)。并将BUFG的输入改为我们的单端时钟DRP_CLK_IN(约束时只需要约束单端时钟)。
配置IP核后,点击Open IP Example Design生成IP核的Example代码。
接收端example工程更改:
1.在以下模块中gt0_data_valid_in拉高。
括号内替换为1’b1。
2.DRP时钟
因为接收端FPGA的系统时钟为差分时钟,所以源代码不用修改。
不具体写了
注意以下几点:
1.在Implementation中选择Floorplanning
可以看到我们约束好的GTX引脚,并且可以看到GTX位置为X0Y9,正好符合我们当时选择的通道。
时钟也一样可以看到
如果约束出问题了可以在这里查看一下。
2.多时钟域约束
设计中出现存在多个时钟,并且时钟域之间无数据交换,则需要给这些时钟之间设置假路径约束。
sys_clk(DRP时钟)
TXOUTCLK(GTX时钟)
set_false_path -from [get_clocks sys_clk] -to [get_clocks gtx_tx/gtx_tx_support_i/gtx_tx_init_i/inst/gtx_tx_i/gt0_gtx_tx_i/gtxe2_i/TXOUTCLK]
如果不约束会出现时序违例。
WNS 代表最差负时序裕量 (Worst Negative Slack)
TNS 代表总的负时序裕量 (Total Negative Slack),也就是负时序裕量路径之和。
WHS 代表最差保持时序裕量 (Worst Hold Slack)
THS 代表总的保持时序裕量 (Total Hold Slack),也就是负保持时序裕量路径之和。
这些值告诉设计者设计与时序要求相差多少。如果为正值,则说明能达到时序要求,若为负值,则说明时序达不到要求。
加ila核,还记不记得:
TXUSRCLK2:是进入GTX端的所有信号的主要同步时钟,进入GTX收发器TX端的大多数信号都经过在TXUSRCLK2上升沿的采样。
RXUSRCLK2是所有同步信号进入RX端信号的主要同步时钟。
进入GTX收发器RX端的大多数信号是在RXUSRCLK2的上升沿采样。
ila_0 ila_tx (
.clk(gt0_txusrclk2_out), // input wire clk
.probe0(gt0_txdata_in), // input wire [15:0] probe0
.probe1(gt0_txcharisk_in) // input wire [1:0] probe1
);
ila_0 ila_rx (
.clk(gt0_rxusrclk2_out), // input wire clk
.probe0(gt0_rxdata_out), // input wire [15:0] probe0
.probe1(gt0_rxcharisk_out) // input wire [1:0] probe1
);
★★★如有错误欢迎指导!!!