概述
为什么要8B/10B编码呢?其实就是为了在高速串行通信中,把8bit的数据编码成10bit的数据发送出去,以达到直流平衡的目的。
那什么是直流平衡呢?就是在传输信号时确保直流分量(DC component)在一段时间内保持平衡或为零,也就是为了避免传输的数据出现长连“1”或者长连“0”的情况。
为什么要直流平衡呢?其实就是为了时钟恢复(CDR Clock Data Recovery)。
那为什么要时钟恢复呢?因为在高速通信中只有数据线,没有时钟线,时钟需要从数据中恢复出来以保证跟数据同步并且保证接受端数据采样的准确性。
那为什么不加个时钟线使用同步时钟呢?因为高速通信中,时钟频率很高,对于PCB布线的要求也很高,如果时钟线和数据线的长度有差异或者出现时钟抖动时,那么随着数据源源不断的传输就有可能产生数据无法满足建立时间与保持时间的要求从而发生数据采集错误。
基本原理
8B/10B编码也就是把一个8bit的数拆成高3bit+低5bit的形式,把3bit数编码成4bit数,把5bit数编码成6bit数,然后组成一个10bit(6bit+4bit)的数。然后从a到j串行依次发送出去。D码和K码的命名规则就是把高3bit的十进制数做为小数点后面的数,低5bit的十进制数做为小数点前面的数,如下图:
3bit数编码成4bit数,5bit数编码成6bit数都是通过查表得来的,在介绍3B/4B码表、5B/6B码表之前需要先介绍一下另外一个概念:运行偏差(Running Disparity,RD),也称极性偏差,就是拿数据中“0”的个数减去“1”的个数得来的,当RD = -1时,表示编码后“1”的个数比“0”的个数多2个;当RD = +1时,表示编码后“0”的个数比“1”的个数多2个;当RD = 0时,表示编码后“0”的个数和“1”的个数相等,也称为完美平衡。
编码后的数据“0”和“1”的个数差控制在+2,0,-2以内,为什么个数差是2呢?因为编码后的数据4b、6b都为偶数,所以“0”和“1”的个数差不可能是1。那为什么编码后的数据会有个数差呢,全部用完美平衡码不就行了吗?当然不行,因为编码后的4bit数,一共有16种编码,其中只有6 种是完美平衡的,而编码前的3bit数需要8种码值,而编码后的6bit数,一共有64种编码,其中只有20种是完美平衡的,而编码前的5bit数需要32种码值,所以仅依靠完美平衡码是不够的。
在编码中有K码,有D码,K码是逗号码,也就是comma,只作为控制字符出现,可以作为帧的开始和结束标志或者用于字节对齐,D码是8B/10B编码的数据码。下面看一些3B/4B,5B/6B的码表:
举几个例子,比如现在有个源码为0111_1000要进行8B/10B编码,那么用D码来表示:高三位011十进制作为小数点后面的数就是3,低五位11000十进制数作为小数点前面的数就是24,就是D24.3。数据编码时RD的初始值为-1,编码后的数据RD如果还为-1,那么下一个数据的RD为+1。查表可得D.24为110011,因为5B/6B的RD为-1,为了平衡,3B/4B的RD取+1,所以D.x.3为0011,所以编码后的10bit数就是1100110011。
紧接着又一个源码0101_1111进来了,用D码来表示就是D31.2,因为上一个10bit码RD为-1,所以这个码RD为+1,查表可得D.31为010100,因为5B/6B的RD为+1,所以3B/4B的RD取-1,所以D.x.2为0101(D.x.2为完美码型,只有这一种值),所以编码后的10bit数就是0101000101。
然后又一个源码1000_0010进来了,用D码来表示就是D2.4,因为上一个10bit码RD为+1,所以这个码RD取-1,查表可得D.02为101101,因为5B/6B的RD为-1,所以3B/4B的RD取+1,所以D.x.4为0010,所以编码后的10bit数就是1011010010。编码后的10bit数RD为0,所以下一个数据的RD仍取-1。
K码为什么作为逗号码呢?就是因为经过8B/10B编码以后,不会出现连续5bit的“0”或“1”,只有在使用comma时,才会出现连续5bit的“0”或“1”,有助于接收端更好的检测出逗号。