Xilinx GTX/GTH 2D眼图扫描功能介绍

本文介绍Xilinx GT的一些概念,对GT没有概念但是有时间的童鞋推荐先看一下此文(Xilinx 7系列FPGA 高速收发器GTX/GTH的一些基本概念),补充一些基础概念。

随着高速数据传输的普及,Serdes已经成为FPGA上重要的I/O接口。而线速率也不断的提高。更高的线速率也就带来了更大的通道衰减影响。通常,Serdes接收端需要打开内部的均衡来对高速串行信号进行处理,保证内部的有效信号能够等到放大而噪声可以被抑制,并最终恢复出正确的数据。

通常,高速信号到达接收端的Pin位置,称为远端;进入Pin后,被接收端的均衡处理之后的信号,称为近端。在一些均衡能力比较优秀的Serdes上(例如Xilinx的GTX/GTH),远端处的眼图(可以通过高速示波器进行测量)无法睁开,但是近端处的眼图可以完全睁开。这就是均衡器无法忽视的重要作用。

这也带来一个问题,就是如何测量眼图。针对远端眼图,可以通过高速示波器来进行测量。但是这个测量在很多情况下并不容易,比如没有足够高速的示波器,或者由于FPGA多为BGA封装导致Serdes的RX Pin没有合适的测试点来进行测试。而近端眼图,由于近端的定义就是在Serdes的PMA内部,所以没有使用高速示波器直接测量眼图的可能。那么如何评价近端眼图,就成了一个问题。

Xilinx 7系列(及以后)的GTX/GTH中提供了2D眼图测量的功能,通常称呼为2D eye scan,可以用来测量近端眼图。Xilinx提供的GT测试工具ibert中,就是利用这个功能进行眼图的测量。

图片来自UG908

图片来自UG908

关于GT的基本结构和eye scan的具体原理,由于文档已经做了充分的描述,这里就不重复赘述了。下文将会用简单通俗的语言来描述2D eye scan的基本原理,出发点是易于理解。所以在准确性和严谨程度上肯定有所欠缺,这里先说一声抱歉。

从字面分析,2D eye scan的意思就是二维眼图扫描。二维的意思自然是横纵两个坐标。所以眼图扫描的基本原理就是将二维眼图的最大范围坐标化,将眼图整体变为一个二维矩阵区域。

眼图扫描的过程就是依次遍历眼图的二位矩阵区域,并和眼图扫描的正中间区域做对比,记录错误值,然后依据错误值,用不同的颜色来绘制当前二位矩阵中某个点,最终组成一个眼图。

用更通俗的话来解释,就是眼图被划分为一个分辨率是N*M的图片。测量眼图的时候会依次遍历N*M个点,并和中心点的数据做对比。多次对比后记录值不一样的次数,即误码率。当遍历完N*M个点之后,依据每个点记录的误码率来用不同的颜色绘制一副图,即为眼图。

图片来自UG476

图片来自UG476

从上图的左边可以看到,每一个点相对中心点都有一个水平偏移量和垂直偏移量,这就等价于每个点的坐标值(至于0,0点在左下角还是在中心点都只是简单的坐标变换而已)。

从图中的右边可以看到,最终眼图的颜色是依据误码率绘制的,结合前文来自UG908的截图,可以清楚的看到当误码率越低,颜色越偏向蓝色(深蓝色);当误码率越高,颜色越偏向红色。理论上,越接近中心的点,误码率越低,所以越偏蓝色,而越接近外围的点,误码率越高,所以越偏红色。所以实际获取的眼图样子,是中心蓝色,四周红色的眼图。

所以从原理上说,2D眼图的测量步骤其实是遍历整个N*M的点阵,计算每一个点与中心点数据值的误码率。当得到点阵误码率的数据之后,后面仅仅是绘图以便美观显示的事情。

具体的测量细节可以参考UG476的第四章。这里直接给出结论,内置的2D eye scan是逐个点进行测量的,所以每次测量只需一组坐标值。从微观看来,逐点测量由于是串行的,所以是比较慢的。但是从宏观来看,整体测量速度是比较快速的。

另外一个优点就是,眼图的测量不需要特殊的配置和数据,也不会对数据链路带来任何负面影响。由于是和中心点数据的对比,所以无论GT跑的是什么数据流,都可以进行测量,也没有影响。这就扩展了这一功能的使用范围。例如ibert的误码率只能统计PRBS,无法用于实际数据的统计/测试。而这一功能可以实时测试,不影响GT正常业务的运行。将这一功能集成到最终版本中,可以作为实时监控高速链路质量的一个参考标准。

如果GT无法正确回复出数据,则中心点的数据不会稳定。这样统计出来的结果也不会稳定的显示为一个眼睛的图案,而是一个奇怪的图案。如果GT能正确恢复出数据,那么中心点一定是稳定的数据,所以无论眼图是否睁开,张开多大,大体的形状还是一个眼睛的图案。进而,眼图张开的大小就代表信号质量的好坏。所以2D eye scan的结果对链路信号质量的判断,是非常有帮助的。

由于是逐点测试,所以这个过程相对来说更适合基于CPU/MCU的软件来实现。Xilinx提供了两个XAPP来实现该功能,其核心的控制都是交给MCU软核MicroBlaze来实现的。
https://www.xilinx.com/support/documentation/application_notes/xapp743-e...
https://www.xilinx.com/support/documentation/application_notes/xapp1198-...

下面介绍一下具体的操作步骤。

首先,eye scan的具体操作是需要使用DRP的端口,这一端口也是容易和CPU接口适配的。

使用DRP端口的优点是,主要步骤不占用FPGA可编程逻辑资源。代价是这个结构更适合MCU接口的实现,如果使用普通逻辑资源实现,会需要设计接口。

1.部分默认端口可以直接连接到地,例如:
EYESCANMODE
EYESCANTRIGGER

EYESCANRESET端口如果不需要使用,也是可以连接到地。

2.下面几个信号设置为1
ES_SCAN_EN
PMA_RSV2[5]
ES_ERRDET_EN
ES_QUAL_MASK=(80’b1)

3.根据位宽(RX_INT_DATAWIDTH)设置ES_SDATA_MASK
40-bit 位宽: ES_SDATA_MASK = (40'b1, 40'b0)
32-bit位宽: ES_SDATA_MASK = (40'b1, 32'b0, 8'b1)
20-bit位宽: ES_SDATA_MASK = (40'b1, 20'b0, 20'b1)
16-bit位宽: ES_SDATA_MASK = (40'b1, 16'b0, 24'b1)

4.根据误码率设置ES_PRESCALE,关于这个参数的值,可以暂时跳过,等看完下文,理解原理之后再选择合适的值写入。

上述设置只需要设置一次即可。其中要注意,ES_QUAL_MASK和ES_SDATA_MASK都是80bit数据,需要分多次才能写入。7系列的GTX/GTH,DRP数据位宽为16bit,所以需要5次才能完成80bit的写入。

开始遍历每一个点(即每一对横纵坐标)。横轴由ES_HORZ_OFFSET控制,纵轴由ES_VERT_OFFSET控制。

1.对每个点,将纵坐标写入ES_VERT_OFFSET

这里需要注意,ES_VERT_OFFSET和ES_PRESCALE的地址是一样的,高5bit是给ES_PRESCALE使用,低9位给ES_VERT_OFFSET使用。对于ES_VERT_OFFSET,0-7bit作为地址使用。第8位作为一个控制位,先填入0。DFE条件下后续还需要用到。

2.将横坐标写入ES_HORZ_OFFSET

3.将ES_CONTROL的低两位设置为2'b01

这里需要先读取出来,然后将低位设置位01,高位不变,再写入ES_CONTROL寄存器中。

4.循环查询es_control_status寄存器的值,如果发现最低位是1,表明采样/记错计数器溢出了,该点统计完毕(关于两个计数器的含义,下文在做讨论)。此时可以将ES_CONTROL的最低两位设置为2'd00,以便于下一个点的测量。

5.读取ES_ERROR_COUNT和ES_SAMPLE_COUNT寄存器的值,分别为记错寄存器和采样寄存器。

6.计算一下误码率

误码率的计算公式为,误码数目 / 采样数目。

误码数目即为ES_ERROR_COUNT的值,如果该值为0,则误码率直接为0。

采样数目的计算则相对负责。具体公式为:

SAMPLE\_COUNT=ES\_SAMPLE\_COUNT\times2^{(ES\_PRESCALE+1)}\times RX\_INT\_DATAWIDTH

可以看到,具体的采样数和ES_SAMPLE_COUNT的值是有一个非线性的计算关系。

通过上述公式可以计算出采样数的值,然后参与运算即可获取误码率这一数据。

7.当使用DFE的时候,需要将ES_VERT_OFFSET的第八位设置为1(前文描述设置为0),然后重新测试一边,计算出另一个误码率,和设置为0的误码率取一次平均才为最终的误码率。

这样就完成一个点的测试了。

所以测试的大体流程就是先设置好一些固定的参数,然后设置横纵坐标,开始测试。等测试结束后获取采样数和错误数两个值,计算误码率即可。DFE模式下需要将纵坐标的一位取反后重新测算一下,然后两个误码率取平均。

这里就能看出来测试的具体细节。内部测试提供了两个计数器,一个用于统计采样次数,另一个用于统计错误次数。测试过程其实就是进行多次的数据对比。对比一次,采样次数加1,如果数据不对,则错误次数也加1。等到两个计数器有一个溢出的时候就可以结束统计了。这样会有两种情况。
1.错误计数器溢出,采样计数器没有溢出,此时错误值比较大,可以保证精度。
2.采样计数器溢出,错误计数器没有溢出,此时采样值比较大,误码率往往比较低。
由于两个技术器溢出值相差非常大,所以不可能同时溢出。如果都没有溢出,那么测试就不会停止。
用这种方法,可以获取一个比较好的测试精度结果,也便于测试流程的控制。
另外,理解了这一流程,并观察采样值的计算公式,就能反推出ES_PRESCALE比较合适的值。
通过逐点的测量,就可以获取完整的眼图数据,然后进行绘图即可。

2D eye scan的原理就分析完了。

下面分析一下实际操作中的一些问题。

1.ES_PRESCALE:如果确定这个值

这个参数实际控制的是采样数的计算结果。通常情况下,通过公式反推,选区一个固定值就好。但是实际情况下,如果使用动态的控制,可以提高精度。关于这部分的讨论就非常深入了。有兴趣的童鞋可以再熟悉2D eye scan之后进行研究。

2.采样点的数量:一定要逐点吗

从手册中可以查询到ES_HORZ_OFFSET和ES_VERT_OFFSET的范围。实际操作中,其实并不需要逐点测试。从图片的角度触发,逐点(或者点间隔较小)的好处就是图片的分辨率较高。同时弊端就是花费的时间较长。通常使用中并不需要非常高的眼图分辨率,尤其是并不需要将眼图美观的绘制出来的条件下,适当加大间隔可以快速获取眼图的基本信息。依据基本信息再考虑是否提高精度,改变参数等操作,更为合适。ibert中也提供了调整采样点间隔的选项。

3.关于ibert眼图显示的美观性和眼图的显示

根据上述分析,眼图最终结果其实是一个颗粒感比较强的图片。ibert中较为平滑/美观的眼图其实是美化过的结果。右键点击眼图弹出的菜单中可以选择没有没画过的点阵图。

ibert绘制的平滑眼图

ibert绘制的平滑眼图

ibert的原始点阵眼图,每个点为细长的横条形状

ibert的原始点阵眼图,每个点为细长的横条形状

以上两张图为同一次测量后调整ibert显示参数获取的不同效果,可以看到ibert默认显示是经过了美化的。而原始图就是一个颗粒感很强的点阵图。

下图为自行设计/实现2D eye scan后自行绘制的眼图。

自行实现2D eye scan测量后绘制的眼图

自行实现2D eye scan测量后绘制的眼图

原始数据已经有了的情况下,眼图的绘制其实只是一个绘图的软件设计。考虑到大部分FPGA开发者可能并不擅长于图形界面的开发,所以推荐了解一下tk绘图。不过更好的方案是让专业的人做专业的事情。通过基本的数据,即使没有绘图,也能做很多事情了。

4.DRP如何控制

官方推荐的方案是利用MCU来进行控制,比如MicroBlaze的软核。

另外可以通过JTAG,由PC发起控制。原厂方案为AXI JTAG。

本人是通过TCL和JTAG来控制VIO接口,进而控制DRP端口的。关于这个方案,除了控制DRP端口,还可以控制BRAM。具体可以参考专栏文章:Vivado功能完善:如何用Tcl/VIO更新BRAM中的数据

5.寄存器的地址

上文的描述中最大的问题就是没有介绍寄存器和相关的地址。关于各个寄存器的名称再文章已经给出了。具体的地址可以参考UG476的附录D(通常都是最后一个附录)。
ES_QUAL_MASK 0x031~0x035
ES_SDATA_MASK 0x036~0x03A
PMA_RSV2 0x082
ES_ERRDET_EN 0x03D
ES_EYE_SCAN_EN 0x03D
ES_CONTROL 0x03D
ES_PRESCALE 0x03B
ES_VERT_OFFSET 0x03B
ES_HORZ_OFFSET 0x03C
es_control_status 0x151
ES_ERROR_COUNT 0x14F
ES_SAMPLE_COUNT 0X150

这里给出7系列GT的部分寄存器地址。

整套方案可以移植到UltraScale/UltraScale+的GT上,需要注意的是,寄存器地址需要重新核对一下。可以确定很多寄存器的地址/定义都不一样。

文章转载自: https://zhuanlan.zhihu.com/p/46238880

推荐阅读