概述
在使用ALTERA的高速串行接口時,GXB模塊里硬件實現了8B10B編碼,用戶只是“傻瓜”式的使用,筆者也一直沒有弄清楚。網上搜索了一些學習資料,結合參考文獻希望能夠對其進行消化。另外,ALTERA現在已經提供8B10B IP,用戶可以直接使用,不過有時候為了代碼可移植性需要自己寫代碼實現8B10B編解碼,筆者希望在這方面也做些實踐。
8B10B編碼概念
基本概念網上可以輕易找到答案,簡單的說就是將8bit數據轉換成10bit數據,顯然這個轉換過程有20%的開銷,大部分公開資料提出8B10B編碼的開銷是25%,我同意開銷大於20%,因為碼流中必然存在一些控制碼,但是為何是25%而不是24%或者26%呢?
為什么要使用8B10B編碼呢?是因為8B10B編碼的特性之一就是保證直流平衡,即編碼后二進制數據流中“0”和“1”的數量基本保持一致,因為我們知道當高速串行流的邏輯1和邏輯0有多個位沒有產生變化時(即所謂的長連0和長連1),信號的轉換就會因為電壓位階的關系而造成信號錯誤,直流平衡最大好處就是可以克服這個問題。
8B10B編碼是怎么做到DC平衡的呢?轉換的時候,連續的“0”或者“1”數量不超過5位,即每5個連續的“0”或者“1”后必須插入一位“1”或者“0”,從而保證信號DC平衡。這樣可以保證串行數據可以在接收端被正確復原,同時利用一些特殊代碼(K碼)也可以幫助接收端進行復原工作,且可以在早期發現數據位傳輸錯誤,抑制錯誤繼續發生。
通過以上解釋,那么一個8bit的二進制位流,變成10bit后,10B中0和1的位數只可能出現下面3種可能情況:
{C}l 有5個0和5個1
{C}l 有6個0和4個1
{C}l 有4個0和6個1
這樣就引出一個新的名詞“不均等性”,即Disparity。就是1的位數和0的位數的差值,根據上述3種情況,那么就有3種Disparity,即0、-2、+2。
8B10B編碼工作原理
圖1:8B10B編碼器邏輯設計原理框圖
如圖1所示,8bit(HGFEDCBA,H是MSB,A是LSB)原始數據會被分成兩部分,低5bit進行5B6B編碼,高3bit則進行3B4B編碼,這已成約定俗成的標准,所以8bit數據(0到255)也被表示為Dx.y的形式,其中x就是低5bit對應的十進制數值,而y就是高3bit對應的十進制數值。例如8bit數“101 10101”,即十進制數181,這時候按照上述划分原則x=10101(21),y=101(5),所示這個數被表示為D21.5。這叫Code Notation。
Running Disparity
Running Disparity縮寫成RD,有正和負之分,即RD+和RD-。有時候也認為RD- = -1,RD+ = +1,所以Running Disparity只有兩種狀態,而-1是其初始狀態。根據上述“不均等性”定義,8-Bit碼有3種Disparity,那么又是如何計算出Running Disparity呢?
根據參考[1]的描述,如果每個5B6B和3B4B碼中“1”和“0”的數目不相等,那么就有兩種碼流可能來進行傳輸,一種是“1”比“0”多2個,另外一種就是直接取反從而“1”比“0”少2個。到底采取哪一種,編碼原則根據當前的Running Disparity信號(也即圖1中的RD in)來選擇。很明顯,當5B6B和3B4B碼中“1”和“0”的數目相等的時候,由於Disparity沒有改變,所以這里似乎沒有選擇。但是這時候的編碼原則如下:
{C}l 如果6-Bit子塊為“000111”,那么6-Bit子塊結束RD為正
{C}l 如果4-Bit子塊為“0011”,那么4-Bit子塊結束RD為正
{C}l 如果6-Bit子塊為“111000”,那么6-Bit子塊結束RD為負
{C}l 如果4-Bit子塊為“1100”,那么4-Bit子塊結束RD為負
總的計算Running Disparity的原則如圖2所示:
圖2:計算Running Disparity規則
需要注意的是ALTERA高速接口里8B10B模塊的Running Disparity是基於10bit的子塊計算出來的。10B被分為2塊,一個6bit子塊(abcdei)和一個4bit子塊(fghj),如圖3所示。
圖3:10-Bit Grouping of 6-Bit & 4-Bit Sub-Blocks
6-Bit子塊的起始Running Disparity等於上一個10-Bit碼的結尾Running Disparity。而4-Bit子塊的Running Disparity等於6-Bit子塊結尾的Running Disparity。4-Bit子塊結尾的Running Disparity等於10-Bit碼的Running Disparity。如圖4所示。
圖4:Running Disparity between Sub-Blocks
ALTERA給出的計算Running Disparity規則如下所示(如果條件不符合,那么子塊結尾的Running Disparity與子塊開頭的一樣),與上述參考[1]的內容相符,注意和圖2比較。
{C}l 滿足下列條件,子塊結尾的當前Running Disparity為正
{C}n 子塊中“1”比“0”多
{C}n 6-Bit子塊為6’b000111
{C}n 4-Bit子塊為4’b0011
{C}l 滿足下列條件,子塊結尾的當前Running Disparity為負
{C}n 子塊中“1”比“0”少
{C}n 6-Bit子塊為6’b111000
{C}n 4-Bit子塊為4’b1100
數據編碼表
參考[1]將8B10B數據碼表分成兩部分,即5B6B碼和3B4B碼表。
圖5:5B6B數據碼表
圖6:3B4B數據碼表
D.x.7有兩種選擇(即初始碼D.x.P7或者可選碼D.x.A7),編碼器根據與5B6B編碼組合是否產生5個連續“1”或者“0”來選擇對應的碼。序列中如果出現5個相同的位,使用逗號碼(comma code)來進行同步。當RD=-1的時候,只有x=17、x=18和x=20時使用D.x.A7。當RD=+1的時候,只有x=11、x=13和x=14是才使用D.x.A7。當x=23、x=27、x=29和x=30時控制碼K.x.7也使用A7這個碼型。其他任何K碼都不能使用x.A7碼型,否則會有可能導致序列中逗號碼對不齊(即導致逗號碼漏檢)。
只有K.28.1、K.28.5和K.28.7可以作為“comma”碼,因為控制碼K.x.y的可選編碼使得其Disparity為0,而且數據bit流中找不到這種編碼。
控制碼表
圖7:控制碼
在控制代碼中,K.28.1 K.28.5 K.28.7 是逗號序列,逗號序列是用來同步的(即用來8B10B比特流字節對齊),如果K.28.7沒有被使用,序列0011111 或者 1100000 是不會出現在任何數據編碼中的。
如果K.28.7被用於實際編碼,一種比中提到的更復雜的同步碼型需要被定義使用。組合成K.28.7的碼與其它碼容易組合成其它的逗號碼,兩個相鄰碼就有可能變成相交碼,從而導致對齊錯誤。在任何情況下多個K.28.7序列不允許被同時使用,它將導致不可測的誤對齊逗號序列。
所謂控制碼,是比特流中的10B沒有對應的8B數據字節,通俗講就是這些碼不屬於上述圖5和圖6組合成的數據中。這些碼用於底層控制功能。ALTERA的GXB鏈接建立之前一般都要發IDLE碼,鏈接建立以后對了使得接收端能對齊數據字節邊界還要在發數據的同時發送一些控制碼,一般都是發送K28.5(即十六進制的BC)。
另外,下面這句話應該如何理解:
K.28.7 is the only comma symbol that cannot be the result of a single bit error in the data stream.
在FPGA中實現8B10B編解碼
ALTERA不但提供8B10B的IP,而且還提供Verilog編寫的8B10B源代碼。圖8是一個具體應用,將數據先進行8B10B編碼,然后並轉傳輸出。
圖8:應用實例
分析及結論
深入了解了什么8B10B編碼,解碼的過程與編碼相逆,通過ALTERA提供源代碼可以進一步學習解碼的具體過程。