导言:
8b/10b编码是由IBM公司的Widmer和Franaszek于1993年提出并于1994年申请专利。其在以太网,光线通信,PCIe,SATA,USB3.0等高速串行接口领域得到了广泛的应用。8b/10b编码通过将8b数据编码为10b数据,避免连续出现0或者1,来保证DC平衡,并拥有足够的位转换密度来保证时钟恢复。这种编码方式使数据传输不再需要分布时钟,避免并行传输的一些缺点,可以实现更高数据速率的串行传输,本文就将展开讲解该编码的基本原理。
编码目的
-
在数据中嵌入时钟
8b/10b编码确保数据流中具有足够的边沿让接收端恢复时钟,从而不再需要分配时钟(传输过程不需要通用参考时钟),让传输实现更高的速率(串行)。避免了并行总线的一些缺点,比如飞行时间的限制,时钟偏斜的影响。同样避免了分配高频时钟可能带来的EMI和布线困难的影响。这里请注意,串行总线是当前高速接口的主流方案,但并不意味着串行方案能完全避免例如“偏斜”问题的影响,如果传输都是一个lane那当然没影响,但为了提高带宽,一般都不会是一个lane。比如PCIe中的X1,X4,X16,X32这些各个lane仍然会存在偏斜的问题,但收发器本身会处理这些偏斜,当然这不在本文讨论范围。
如上图的并行传输,需要通用时钟作为参考,面临的问题除了时钟偏斜,数据偏斜,还有飞行时间,也就是发射端到接收端信号需要的时间,该模式下必然要求飞行时间小于时钟频率,但随着传输速率需求提升,通用时钟频率会更大,从而飞行时间的影响也越大,除此以外的EMI和时钟布线的问题也会变得更严峻。
-
保持DC平衡
以PCIe为例,链路使用AC耦合,链路中放置电容,当频率越高,阻抗越低,反之频率越低,阻抗越高,当码型的0和1交替频繁,那么信号很容易传输过去,但如果出现连续的0或者1,意味着频率降低,可能无法识别0和1。这里有个概念叫“极性偏差”,就是10位数据中1的个数多于0称正极性偏差(+1),0的个数多于1称为副极性偏差(-1)。还有一种0和1相等,则无偏差(neutral disparity)。通过控制极性偏差实现10位数中不出现5个连续的0,也不会出现5个连续的1,且0和1的个数相差不会超过2,即要么相等,要么6个0,4个1,要么6个1,4个0。
-
加强错误检测
8b/10b编码方案同样加强了错误检测机制,8bit数据有256个编码,而10bit数据有1024个编码,如果1对1进行映射,那么这1024个编码中只需要找出256个编码来对应原始的8bit数据。由于数据的极性偏差要变化来保持DC平衡,所以一些数据映射到10位数据是存在两个数值的,即一个8位数据对应2个10bit的编码后值,分别为为正极性偏差和负极性偏差。那么数据应该映射了512个编码,考虑到有些编码后的10bit数据还存在“无偏差”(0和1个数相等),所以对于数据而言(不包含控制符)实际8bit数据映射到10bit数据需要的编码数小于512。即使加上控制符号编码,这个数字也是远小于1024个编码的,那么哪些不被映射的数据,就属于非法字符,接收端也可以依靠判断数据是否在合法来检测错误。
编码的基本原理
并非说8b/10b编码就没有缺点,影响最大的应该是产生了巨大开销,由8bit编码为10bit数据,其中2个数据为非用户数据,引入了20%的额外开销,当然有些协议也使用例如64b/66b,128b/130b的编码方式(例如PCIe3.0),这样能大大减少开销。
对于8b/10b编码,这里可能和大家想的不太一样,它并非是把8bit数据直接映射到10bit数据里,因为直接映射的话,对编码效率会有影响,也会增加对芯片面积的占用。所以这里把8bit分为2部分,低5位和高3位,对低5位进行5b/6b编码,对低三位进行3b/4b编码,最后再合并起来,提高效率。
8b/10b规定了256种数据映射(从8bit映射到10bit)和12个特殊控制字符编码,分别用Dx.y和Kx.y表示,其中Dx.y种x表示高3位,y表示低5位。对于特殊控制字符编码一般用于帧的起始终止符号以及逗号的检测,以PCIe2.0为例,K27.7是TLP的开始,K28.2是DLLP的开始等等不详细讲解了,可以参考相关手册。8位数据的低5位为EDCBA被编码为iedcba,高3位的HGF被编码为ihgf,最后组合一起为10位的ihgfiedcba。
5B/6B编码映射表(部分)
RD=+1表示1比0多,RD=-1表示0比1多。
输入 | 输出abcdei | ||
信号 | EDCBA | RD=-1 | RD=+1 |
D0 | 00000 | 100111 | 011000 |
D1 | 00001 | 011101 | 100010 |
D2 | 00010 | 101101 | 010010 |
D3 | 00011 | 110001 | |
D4 | 00100 | 110101 | 001010 |
D5 | 00101 | 101001 | |
D6 | 00110 | 011001 | |
D7 | 00111 | 111000 | 000111 |
3B/4B编码映射表
输入 | 输出fghj | ||
信号 | HGF | RD=-1 | RD=+1 |
Dx.0 | 000 | 1011 | 0100 |
Dx.1 | 001 | 1001 | |
Dx.2 | 010 | 0101 | |
Dx.3 | 011 | 1100 | 0011 |
Dx.4 | 100 | 1101 | 0010 |
Dx.5 | 101 | 1010 | |
Dx.6 | 110 | 0110 | |
Dx.P7 | 111 | 1110 | 0001 |
Dx.A7 | 111 | 0111 | 1000 |
8B/10B编码映射表(部分)
信号名 | HGF EDCBA | abcdei fghj(RD-) | abcdei fghj(RD+) |
---|---|---|---|
D0.0 | 000 00000 | 100111 0100 | 011000 1011 |
D1.0 | 000 00001 | 011101 0100 | 100010 1011 |
D2.0 | 000 00010 | 101101 0100 | 010010 1011 |
D3.0 | 000 00011 | 110001 1011 | 110001 0100 |
D4.0 | 000 00100 | 110101 0100 | 001010 1011 |
D5.0 | 000 00101 | 101001 1011 | 101001 0100 |
D6.0 | 000 00110 | 011001 1011 | 011001 0100 |
D7.0 | 000 00111 | 111000 1011 | 000111 0100 |
特殊控制符号编码映射表
信号名 | HGF EDCBA | abcdei fghj(RD-) | abcdei fghj(RD+) |
---|---|---|---|
K28.0 | 000 11100 | 001111 0100 | 110000 1011 |
K28.1 | 001 11100 | 001111 1001 | 110000 0110 |
K28.2 | 010 11100 | 001111 0101 | 110000 1010 |
K28.3 | 011 11100 | 001111 0011 | 110000 1100 |
K28.4 | 100 11100 | 001111 0010 | 110000 1101 |
K28.5 | 101 11100 | 001111 1010 | 110000 0101 |
K28.6 | 110 11100 | 001111 0110 | 110000 1001 |
K28.7 | 111 11100 | 001111 1000 | 110000 0111 |
K23.7 | 111 10111 | 111010 1000 | 000101 0111 |
K27.7 | 111 11011 | 110110 1000 | 001001 0111 |
K29.7 | 111 11101 | 101110 1000 | 010001 0111 |
K30.7 | 111 11110 | 011110 1000 | 100001 0111 |
总结
本篇主要介绍一些基本的概念,下一篇讲编码的方式,以及给出一个参考的代码。