PCIe/USB3.0中的Elastic buffer/store

  1. 背景
    这个模块又叫时钟补偿模块,顾名思义就是用于补偿时钟的失配,是PCIe/Ethernet/USB3.0及以上版本中必备的一个模块。
    在这些通信协议中,都包含发送模块和接收模块。其中,接收模块的时钟通常是CDR模块从接收到的串行数据流中恢复出来的,此外,本地还有一个时钟,这两个时钟频率上理论上是一样的,但在实际应用中,这两个时钟的频率往往存在一定范围的偏差。
    送过来的数据处于恢复出的时钟域之中,而数据的处理需要在本地时钟域进行。这样就需要一个缓存器对这个数据进行同步,但由于读写时钟存在偏差,而且数据会源源不断的进入和读出(不能简单地反压),如果用普通的异步FIFO势必会造成缓存的上溢和下溢,造成数据的丢失,此时就需要这种特殊的buffer。
  2. 工作原理
    Elastic Buffer,弹性缓存。这个buffer并不是说可以动态改变buffer的深度,而是通过插入或者删除一些dummy symbol,SoS(Skip Order Set),在采用8b/10b编码的PCIe1.0/2.0/USB3.0协议中,有个专门的symbol,即SKP。SoS由COMMA(K28.5)+3SKP(K28.0)组成。Elastic Buffer并没有传统FIFO的空满信号,它正常的工作状态是半满(half-full)状态。
    PCIe/USB3.0中的Elastic buffer/store_第1张图片
    2.1 当本地(读)时钟比恢复(写)时钟快
    当读时钟比写时钟快,意味着buffer会有下溢的风险,需要根据buffer中的数据量来判断buffer是否处于normal(half-full)状态,如果不是,并且当检测即将写入的数据是SoS, 则需要插入额外的SKP使buffer的容量回到half-full的状态;写地址指针在该周期内增加2~3,写入二外1 ~2 个SKP symbol。
    PCIe/USB3.0中的Elastic buffer/store_第2张图片
    2.2 当本地(读)时钟比恢复(写)时钟慢
    同理,当读时钟比写时钟慢,意味着buffer会有上溢的风险,需要根据buffer中的数据量来判断buffer是否处于normal(half-full)状态,如果不是,并且当检测即将写入的数据是SoS, 则需要"删除"SKP使buffer的容量回到half-full的状态;所谓‘删除’就是不将到来的SKP写入到buffer,写地址保持不变,直接跳过1~2个SKP symbol。

PCIe/USB3.0中的Elastic buffer/store_第3张图片
3. 硬件实现
SKP的“插入”和“删除”都可在写时钟域实现,通过操控buffer的写指针来使buffer的一直处于half-full状态;
其中,有几个关键点需要注意:
3.1 buffer的深度;
buffer的深度应该cover最worst case,这部分主要由max-payload size和读写时钟的最大差异(用ppm表示)决定;因为SKP的插入和删除操作只能在报文的间隙进行,不能在发送报文中间,因此需要考虑到max-payload size及其发包的开销;
对于PCIe协议来讲,容许的最大的时钟偏差为600ppm,这意味着每100 0000/600=1666个cycle(symbol time)有一个时钟周期漂移;另外,还需要考虑发送SKP的最大间隔1180~1538 symbol time和lane的数量Link_Width。
因此worst-case的周期漂移个数计算如下:
在这里插入图片描述
其中TLP_Overhead为包开销:
a. 帧起始字符(1);
b. 包序列号(2);
c. Header(16);
d.ECRC(4);
e.LCRC(4);
f.帧结束字符(1);
总共1+2+16+4+4+1=28 symbols
Max_payload_size最大可为4096;Link_width worst-case下为1.

Max_Symbol_Shifted =4096+28+1538)/1666 = 3.4

Max_Symbol_Shifted向上取整为4.考虑到两个方向的时钟漂移,需要将这个结果翻倍,即为8,这就是对于max payload size 为4096所需的buffer深度。
下图是max_payload_size与Max_Symbol_Shifted的关系:
PCIe/USB3.0中的Elastic buffer/store_第4张图片
注意,将这个结果向上取整,考虑到两个方向的时钟漂移,需要将这个结果翻倍,即为所需的buffer深度。
对于USB3.0来讲,每隔354个symbol time就会发送一次SoS,与PCIe不同,USB3.0的SoS是没有COMMA字符打头的,而是每次都是连续的两个SKP(K28.1)字符
USB3.0需要能容忍的时钟漂移是300+300+5000=5600ppm(300+300包含两个方向,5000ppm是考虑到展频SSC)。
USB3.0 的buffer 深度计算如下:
Max_Payload_Size = 1024B
Packet Overhead = Header(20B)+ CRC32(4B)=24B

Max_Symbol_Shifted =1024+24+354)/(100 0000/5600) = 7.8

向上取整为8。

3.2 判断buffer half-full的依据
知道了SKP如何被"插入"或者被"删除"后,接下来就是如何去计算何时"插入"或者"删除"SKP,即判断buffer是否处于half-full状态。
最直接的办法就是利用读写指针去计算,因为elastic buffer是一个处理异步的器件,读写的时钟是异步的,因此需要将读指针同步之后再计算,这时需要将二进制转换成格雷码,然后同步到写时钟域,然后再转换为二进制编码,之后与写指针做比较。需要注意的是,因为经过了两级同步器,因此有同步过来的写指针有两拍的延时,这意味着同步过来的读指针落后了两个地址,这部分应该考虑进去;因而,buffer中存在的数据量可以表示为:

fillcount_w = w_ptr - (r_ptr_b_sync + 2)

其中,r_ptr_b_sync是同步到写时钟域的读指针的二进制码。
4. Elastic buffer 与8b/10b解码模块的位置关系
考虑一个问题,Elastic buffer 是放在8b/10b解码模块之前还是之后好呢?
假如放在8b/10b解码模块之后,则会有如下好处:

  1. 数据位宽可以为8b,而不是10b;
  2. 不用考虑RD(Running Disparity);
    但是需要考虑一点,那就是协议规定的device 作为loopback slave的情形;协议要求作为LoopBack slave的device 在进行时钟补偿时(经过elastic buffer),必须原封不动地返回接收到的10b数据,这就意味着不能对接收到的10b数据进行编解码后返回。这一点要求了Elastic buffer必须放在8b/10b解码模块之前
    另外,Elastic buffer放在8b/10b解码模块之前还有一个好处就是多lane情况下的de-skew的问题。
    PCIe/USB3.0中的Elastic buffer/store_第5张图片
    将Elastic buffer放在8b/10b解码模块之前可以解决一半的de-skew的工作量。

参考文献:
https://www.mindshare.com/files/resources/mindshare_pcie_elastic_buffer.pdf

你可能感兴趣的:(信息与通信)