詳解FPGA實現8b10b編碼原理(含VHDL及verilog源碼)


首發自https://hifpga.com/%E9%97%AE%E9%A2%98/37599

為什么要推出8b/10b編碼?
8b/10b最常見的是應用於光纖通訊和LVDS信號的。由於光模塊光模塊只能發送亮或者不亮,也就是0或者1這兩種狀態這種單極性碼,那么這會存在一個問題,如果傳輸中出現較長的連0或者連1(例如111111100000000),那么接收端將沒有辦法正確的采樣識別信號,另外還會由於單極性碼含有直流分量,這種直流成分會隨數據中1和0的隨機變化也呈現隨機性,這會引起接收端的基線漂移導致接收端誤判。LVDS信號一樣會存在這個問題,隨着線路上的信號頻率越來越高,如果線路上的0和1數量不均衡(直流不平衡)那么線路上的基電壓會出現偏移,一樣會導致解碼錯誤。

總之一句話,8b/10b是為了解決直流平衡而推出的。

什么是直流平衡
下面這段引自知乎

高速串行總線通常會使用AC耦合電容,而通過編碼技術使得DC平衡的原理可以從電容“隔直流、通交流”的角度理解。 如下圖所示,DC平衡時,位流中的1和0交替出現,可認為是交流信號,可以順利的通過電容;DC不平衡時,位流中出現多個連續的1或者0,可認為該時間段內的信號是直流,通過電容時會因為電壓位階的關系導致傳輸后的編碼錯誤。高速串行總線采用編碼技術的目的是平衡位流中的1和0,從而達到DC平衡。大多數串行電路都是ac coupling,就是會在tx端有串電容。電容是隔直通交的,如果不做dc balance,會把直流信號濾除,信號會畸變。但並不是所有的串行電路標准都是ac coupling,比如HDMI就是dc coupling,也就是說HDMI標准電氣編碼並不是dc balance的。

 

8b/10b編碼的發展歷史及應用范圍
8b/10b編碼是由IBM的 Al Widmer 與 Peter Franaszek在1983年提出的,【
Widmer, A. X.; Franaszek, P. A., “A DC-Balanced, Partitioned-Block, 8B/ 10B Transmission Code”, IBM Journal of Research. Development, VOL. 27, NO. 5, September 1983.pdf
】 。8B/10B編碼是加擾二進制碼的一種,在此之前這種技術已得到應用,只是沒有像8B10B那么普遍。目前采用8b/10b編碼的串行高速接口總線有IEEE 1394b、SATA、PCI Express、Infini-band、Fiber Channel、RapidIO、USB3.0、MIPI M-phy 等。

8b10b編碼方式詳解
8b10b編碼的位域映射關系
編碼前的原始數據以字節為單位,每字節數據從高到低位用HGFEDCBA表示,首先將8b拆為高3位HGF,低5位EDCBA,然后將HGF從3bit編碼成4bit,編碼后的4bit用jhgf表示,將EDCBA從5bit編碼為6bit, 編碼后后的6bit為iedcba, 將編碼的4bit和6bit拼在一起即為10bit jhgfiedcba,發送時由於是小端模式,因為表示為abcdeifghj,如圖下:

 

通常人們會將編碼前低位的5bit EDCBA按其十進字數值計為X,高位的3bit HGF按其十進制數值為計Y,把這8bit數據計為D.x.y。在進行傳輸時我們除了傳輸數據本身,我們還需要嵌入一些控制信號,控制信號則依上面的規則計為K.x.y(稱之為“comma”)。這里會有一個疑問,D.x.y中的x最多到D.31.y,y最多到D.x.7,xy都被數據占完了,還用什么表示控制碼的K.x,y,下面一一道來。

3b/4b和5b/6b碼表
8bit原始數據有256個碼,而編碼后的10b數據有1024碼,這里面肯定有很多是用不着的,那么具體到一個8bit的數據編碼到什么樣的10bit數據能夠盡可能的做到直流平衡?這個可以自己去推導,也可以直接查表。

 

 

symbol列表示可讀命名, EDCBA是原始5b,abcdei是編碼后的6b, HGF是原始3b, fghj是編碼后4b。這個表中Symbol列以D開頭的行是數據的編碼,以k開頭的是控制符號的編碼。看到這里應該就明白了用什么表示k.x.y,因為5b6b碼表中除了K28.y外其它幾個碼值的K和D的x碼值是共用的,如D.K/23,這種情況下用以區分數據和控制符的其實是在3b4b碼表的D.x.7,D.x.7有兩個編碼一個是主編碼D.x.P7,另一個是D.x.A7。關於控制碼也有一個專門的碼表,如下:

 

從控制符碼表可以看到k.28.y本身的K.28跟D.28是不同的碼值。K27.y, K29.y,K30.y的編碼由於y=7存在兩種編碼,也不沖突。
但上面的碼表有個疑問表上的RD表示什么呢?從碼表上可以看到在4bit的子分組中,16種編碼中只有6 種是完美平衡(0,1個數相等)的,這對於3bit的8種編碼值是不夠的。 同時,在6bit的子分組中也只有20種編碼是完美平衡的,對於5bit的32種編碼值也是不夠的。RD( running disparity)極性偏差就是用來表示0,1的不平衡性的,

編碼時,數據不斷地進入8b10b編碼器生成10b數據,前面所有已編碼的10b數據不一致性累積產生的狀態就是運行不一致性(Runing Disparity)就是RD。RD僅會出現+1與-1兩種狀態,分別代表位”1”比位”0”多或位”0”比位”1”多,其初始值是-1。根據Current RD的值來決定5B/4B和 3B/4B編碼映射。

這樣,經過8B/10B編碼以后,連續的“1”和“0”基本上不會超過5bit,只有在使用comma時,才會出現連續的5個0或1。接收端的數據解碼示意如下圖所示:

 

8b10b編碼優缺點
優點是可以實現DC平衡、控制符嵌入、時鍾嵌入、在線錯誤檢測等,缺點是帶寬損失較大,只有80%的有效帶寬,為了克服這個問題后面又出現了64B66B。我將在之后的文章中來介紹這種編碼,這種編碼的一個典型應用是萬兆網(10GBase-R)。

關於8b10b的更多資料還可以參考下面的文檔

8B10B詳解&綜述.pdf

FPGA實現
FPGA實現主要有兩種思路:

通過ROM查表實現,這個受限於ROM的尋址速度。
通過邏輯實現
大體思路如下:


細化一下如下:


VHDL版本的opencore上有兩個,
8b10b_encdec
async_8b10b_encoder_decoder

verilog 版本的如下:

【8b10_encoder.v】

module encode (datain, dispin, dataout, dispout) ;
input [8:0] datain ;
input dispin ; // 0 = neg disp; 1 = pos disp
output [9:0] dataout ;
output dispout ;


wire ai = datain[0] ;
wire bi = datain[1] ;
wire ci = datain[2] ;
wire di = datain[3] ;
wire ei = datain[4] ;
wire fi = datain[5] ;
wire gi = datain[6] ;
wire hi = datain[7] ;
wire ki = datain[8] ;

wire aeqb = (ai & bi) | (!ai & !bi) ;
wire ceqd = (ci & di) | (!ci & !di) ;
wire l22 = (ai & bi & !ci & !di) |
(ci & di & !ai & !bi) |
( !aeqb & !ceqd) ;
wire l40 = ai & bi & ci & di ;
wire l04 = !ai & !bi & !ci & !di ;
wire l13 = ( !aeqb & !ci & !di) |
( !ceqd & !ai & !bi) ;
wire l31 = ( !aeqb & ci & di) |
( !ceqd & ai & bi) ;

// The 5B/6B encoding

wire ao = ai ;
wire bo = (bi & !l40) | l04 ;
wire co = l04 | ci | (ei & di & !ci & !bi & !ai) ;
wire do = di & ! (ai & bi & ci) ;
wire eo = (ei | l13) & ! (ei & di & !ci & !bi & !ai) ;
wire io = (l22 & !ei) |
(ei & !di & !ci & !(ai&bi)) | // D16, D17, D18
(ei & l40) |
(ki & ei & di & ci & !bi & !ai) | // K.28
(ei & !di & ci & !bi & !ai) ;

// pds16 indicates cases where d-1 is assumed + to get our encoded value
wire pd1s6 = (ei & di & !ci & !bi & !ai) | (!ei & !l22 & !l31) ;
// nds16 indicates cases where d-1 is assumed - to get our encoded value
wire nd1s6 = ki | (ei & !l22 & !l13) | (!ei & !di & ci & bi & ai) ;

// ndos6 is pds16 cases where d-1 is + yields - disp out - all of them
wire ndos6 = pd1s6 ;
// pdos6 is nds16 cases where d-1 is - yields + disp out - all but one
wire pdos6 = ki | (ei & !l22 & !l13) ;


// some Dx.7 and all Kx.7 cases result in run length of 5 case unless
// an alternate coding is used (referred to as Dx.A7, normal is Dx.P7)
// specifically, D11, D13, D14, D17, D18, D19.
wire alt7 = fi & gi & hi & (ki |
(dispin ? (!ei & di & l31) : (ei & !di & l13))) ;


wire fo = fi & ! alt7 ;
wire go = gi | (!fi & !gi & !hi) ;
wire ho = hi ;
wire jo = (!hi & (gi ^ fi)) | alt7 ;

// nd1s4 is cases where d-1 is assumed - to get our encoded value
wire nd1s4 = fi & gi ;
// pd1s4 is cases where d-1 is assumed + to get our encoded value
wire pd1s4 = (!fi & !gi) | (ki & ((fi & !gi) | (!fi & gi))) ;

// ndos4 is pd1s4 cases where d-1 is + yields - disp out - just some
wire ndos4 = (!fi & !gi) ;
// pdos4 is nd1s4 cases where d-1 is - yields + disp out
wire pdos4 = fi & gi & hi ;

// only legal K codes are K28.0->.7, K23/27/29/30.7
// K28.0->7 is ei=di=ci=1,bi=ai=0
// K23 is 10111
// K27 is 11011
// K29 is 11101
// K30 is 11110 - so K23/27/29/30 are ei & l31
wire illegalk = ki &
(ai | bi | !ci | !di | !ei) & // not K28.0->7
(!fi | !gi | !hi | !ei | !l31) ; // not K23/27/29/30.7

// now determine whether to do the complementing
// complement if prev disp is - and pd1s6 is set, or + and nd1s6 is set
wire compls6 = (pd1s6 & !dispin) | (nd1s6 & dispin) ;

// disparity out of 5b6b is disp in with pdso6 and ndso6
// pds16 indicates cases where d-1 is assumed + to get our encoded value
// ndos6 is cases where d-1 is + yields - disp out
// nds16 indicates cases where d-1 is assumed - to get our encoded value
// pdos6 is cases where d-1 is - yields + disp out
// disp toggles in all ndis16 cases, and all but that 1 nds16 case

wire disp6 = dispin ^ (ndos6 | pdos6) ;

wire compls4 = (pd1s4 & !disp6) | (nd1s4 & disp6) ;
assign dispout = disp6 ^ (ndos4 | pdos4) ;

assign dataout = {(jo ^ compls4), (ho ^ compls4),
(go ^ compls4), (fo ^ compls4),
(io ^ compls6), (eo ^ compls6),
(do ^ compls6), (co ^ compls6),
(bo ^ compls6), (ao ^ compls6)} ;

endmodule
【8b10b_decoder】

module decode (datain, dispin, dataout, dispout, code_err, disp_err) ;
input [9:0] datain ;
input dispin ;
output [8:0] dataout ;
output dispout ;
output code_err ;
output disp_err ;

wire ai = datain[0] ;
wire bi = datain[1] ;
wire ci = datain[2] ;
wire di = datain[3] ;
wire ei = datain[4] ;
wire ii = datain[5] ;
wire fi = datain[6] ;
wire gi = datain[7] ;
wire hi = datain[8] ;
wire ji = datain[9] ;

wire aeqb = (ai & bi) | (!ai & !bi) ;
wire ceqd = (ci & di) | (!ci & !di) ;
wire p22 = (ai & bi & !ci & !di) |
(ci & di & !ai & !bi) |
( !aeqb & !ceqd) ;
wire p13 = ( !aeqb & !ci & !di) |
( !ceqd & !ai & !bi) ;
wire p31 = ( !aeqb & ci & di) |
( !ceqd & ai & bi) ;

wire p40 = ai & bi & ci & di ;
wire p04 = !ai & !bi & !ci & !di ;

wire disp6a = p31 | (p22 & dispin) ; // pos disp if p22 and was pos, or p31.
wire disp6a2 = p31 & dispin ; // disp is ++ after 4 bits
wire disp6a0 = p13 & ! dispin ; // -- disp after 4 bits
wire disp6b = (((ei & ii & ! disp6a0) | (disp6a & (ei | ii)) | disp6a2 |
(ei & ii & di)) & (ei | ii | di)) ;
// The 5B/6B decoding special cases where ABCDE != abcde
wire p22bceeqi = p22 & bi & ci & (ei == ii) ;
wire p22bncneeqi = p22 & !bi & !ci & (ei == ii) ;
wire p13in = p13 & !ii ;
wire p31i = p31 & ii ;
wire p13dei = p13 & di & ei & ii ;
wire p22aceeqi = p22 & ai & ci & (ei == ii) ;
wire p22ancneeqi = p22 & !ai & !ci & (ei == ii) ;
wire p13en = p13 & !ei ;
wire anbnenin = !ai & !bi & !ei & !ii ;
wire abei = ai & bi & ei & ii ;
wire cdei = ci & di & ei & ii ;
wire cndnenin = !ci & !di & !ei & !ii ;
// non-zero disparity cases:
wire p22enin = p22 & !ei & !ii ;
wire p22ei = p22 & ei & ii ;
//wire p13in = p12 & !ii ;
//wire p31i = p31 & ii ;
wire p31dnenin = p31 & !di & !ei & !ii ;
//wire p13dei = p13 & di & ei & ii ;
wire p31e = p31 & ei ;
wire compa = p22bncneeqi | p31i | p13dei | p22ancneeqi |
p13en | abei | cndnenin ;
wire compb = p22bceeqi | p31i | p13dei | p22aceeqi |
p13en | abei | cndnenin ;
wire compc = p22bceeqi | p31i | p13dei | p22ancneeqi |
p13en | anbnenin | cndnenin ;
wire compd = p22bncneeqi | p31i | p13dei | p22aceeqi |
p13en | abei | cndnenin ;
wire compe = p22bncneeqi | p13in | p13dei | p22ancneeqi |
p13en | anbnenin | cndnenin ;
wire ao = ai ^ compa ;
wire bo = bi ^ compb ;
wire co = ci ^ compc ;
wire do = di ^ compd ;
wire eo = ei ^ compe ;
wire feqg = (fi & gi) | (!fi & !gi) ;
wire heqj = (hi & ji) | (!hi & !ji) ;
wire fghj22 = (fi & gi & !hi & !ji) |
(!fi & !gi & hi & ji) |
( !feqg & !heqj) ;
wire fghjp13 = ( !feqg & !hi & !ji) |
( !heqj & !fi & !gi) ;
wire fghjp31 = ( (!feqg) & hi & ji) |
( !heqj & fi & gi) ;
wire dispout = (fghjp31 | (disp6b & fghj22) | (hi & ji)) & (hi | ji) ;

wire ko = ( (ci & di & ei & ii) | ( !ci & !di & !ei & !ii) |
(p13 & !ei & ii & gi & hi & ji) |
(p31 & ei & !ii & !gi & !hi & !ji)) ;
wire alt7 = (fi & !gi & !hi & // 1000 cases, where disp6b is 1
((dispin & ci & di & !ei & !ii) | ko |
(dispin & !ci & di & !ei & !ii))) |
(!fi & gi & hi & // 0111 cases, where disp6b is 0
(( !dispin & !ci & !di & ei & ii) | ko |
( !dispin & ci & !di & ei & ii))) ;

wire k28 = (ci & di & ei & ii) | ! (ci | di | ei | ii) ;
// k28 with positive disp into fghi - .1, .2, .5, and .6 special cases
wire k28p = ! (ci | di | ei | ii) ;
wire fo = (ji & !fi & (hi | !gi | k28p)) |
(fi & !ji & (!hi | gi | !k28p)) |
(k28p & gi & hi) |
(!k28p & !gi & !hi) ;
wire go = (ji & !fi & (hi | !gi | !k28p)) |
(fi & !ji & (!hi | gi |k28p)) |
(!k28p & gi & hi) |
(k28p & !gi & !hi) ;
wire ho = ((ji ^ hi) & ! ((!fi & gi & !hi & ji & !k28p) | (!fi & gi & hi & !ji & k28p) |
(fi & !gi & !hi & ji & !k28p) | (fi & !gi & hi & !ji & k28p))) |
(!fi & gi & hi & ji) | (fi & !gi & !hi & !ji) ;

wire disp6p = (p31 & (ei | ii)) | (p22 & ei & ii) ;
wire disp6n = (p13 & ! (ei & ii)) | (p22 & !ei & !ii) ;
wire disp4p = fghjp31 ;
wire disp4n = fghjp13 ;
assign code_err = p40 | p04 | (fi & gi & hi & ji) | (!fi & !gi & !hi & !ji) |
(p13 & !ei & !ii) | (p31 & ei & ii) |
(ei & ii & fi & gi & hi) | (!ei & !ii & !fi & !gi & !hi) |
(ei & !ii & gi & hi & ji) | (!ei & ii & !gi & !hi & !ji) |
(!p31 & ei & !ii & !gi & !hi & !ji) |
(!p13 & !ei & ii & gi & hi & ji) |
(((ei & ii & !gi & !hi & !ji) |
(!ei & !ii & gi & hi & ji)) &
! ((ci & di & ei) | (!ci & !di & !ei))) |
(disp6p & disp4p) | (disp6n & disp4n) |
(ai & bi & ci & !ei & !ii & ((!fi & !gi) | fghjp13)) |
(!ai & !bi & !ci & ei & ii & ((fi & gi) | fghjp31)) |
(fi & gi & !hi & !ji & disp6p) |
(!fi & !gi & hi & ji & disp6n) |
(ci & di & ei & ii & !fi & !gi & !hi) |
(!ci & !di & !ei & !ii & fi & gi & hi) ;
assign dataout = {ko, ho, go, fo, eo, do, co, bo, ao} ;
// my disp err fires for any legal codes that violate disparity, may fire for illegal codes
assign disp_err = ((dispin & disp6p) | (disp6n & !dispin) |
(dispin & !disp6n & fi & gi) |
(dispin & ai & bi & ci) |
(dispin & !disp6n & disp4p) |
(!dispin & !disp6p & !fi & !gi) |
(!dispin & !ai & !bi & !ci) |
(!dispin & !disp6p & disp4n) |
(disp6p & disp4p) | (disp6n & disp4n)) ;

endmodule
【testbench.v】

`timescale 1ns / 1ns
module test_8b10b ;
reg [29:0] code8b10b [0:267] ;
reg [8:0] testin ;
reg dispin ;
reg [10:0] i ;
wire [9:0] testout ;
wire dispout, decodedisp, decodeerr, disperr ;
wire [8:0] decodeout ;
// My data file is 30 columns. Column 1 becomes [29], 2 becomes [28], etc..
// code[0] is last Column (30)
// First column, [29] is K indication
// columns 2:9, [28:21], are data byte, aka 'm' and 'n' of Dm.n
// columns 10:19, [20:11] are 10b symbol if starting disparity was negative, 0
// columns 20:29, [10:1] are 10b symbol if starting disparity was positive, 1
// column 30, [0], is a 1 if symbol results in a disparity flip
// 0 for a balanced symbol (5 '1's, 5 '0's).

wire [29:0] code = code8b10b[i] ;
wire [9:0] expect_0_disp = {code[11], code[12], code[13], code[14], code[15],
code[16], code[17], code[18], code[19], code[20]} ;
wire [9:0] expect_1_disp = {code[1], code[2], code[3], code[4], code[5],
code[6], code[7], code[8], code[9], code[10]} ;

reg [1023:0] legal ; // mark every used 10b symbol as legal, leave rest marked as not
reg [2047:0] okdisp ; // now mark every used combination of symbol and starting disparity
reg [8:0] mapcode [1023:0] ;
reg [10:0] codedisp0, codedisp1 ;
reg [9:0] decodein ;
reg decdispin ;
integer errors ;

encode DUTE (testin, dispin, testout, dispout) ;
decode DUTD (decodein, decdispin, decodeout, decodedisp, decodeerr, disperr) ;

always @ (code) testin = code[29:21] ;

initial begin
errors = 0 ;
$readmemb ("8b10b_a.mem", code8b10b) ;
//$vcdpluson ;
$dumpvars (0);
$display ("\n\nFirst, test by trying all 268 (256 Dx.y and 12 Kx.y)") ;
$display ("valid inputs, with both + and - starting disparity.");
$display ("We check that the encoder output and ending disparity is correct.");
$display ("We also check that the decoder matches.");
for (i = 0 ; i < 268 ; i = i + 1) begin
// testin = code[29:21] ;
dispin = 0 ;
#1
decodein = testout ;
decdispin = dispin ;
#1
// $display ("%b %b %b %b *%b*", dispin, testin, testout, {dispout, DUTD.disp6a, DUTD.disp6a2, DUTD.disp6a0, DUTD.disp6a2}, decodeout,, decodedisp,, DUTD.k28,, DUTD.disp6b) ;
if (testout != expect_0_disp)
$display ("bad code0 %b %b %b %b %b", dispin, testin, dispout, testout, expect_0_disp) ;
if (dispout != (dispin ^ code[0]))
$display ("bad disp0 %b %b %b %b %b", dispin, testin, dispout, testout, (dispin ^ code[0])) ;
if (0 != (9'b1_1111_1111 & (testin ^ decodeout)))
$display ("diff in abcdefghk decode, %b %b %b %b %b", dispin, testin, dispout, testout, decodeout) ;
if (decodedisp != dispout)
$display ("diff in decoder disp out, %b %b %b %b %b", dispin, testin, dispout, testout, decodeout) ;
if (decodeerr) $display ("decode error asserted improperly, %b %b %b %b %b", dispin, testin, dispout, testout, decodeout) ;
if ((testout != expect_0_disp) | decodeerr |
(dispout != (dispin ^ code[0])) | (decodedisp != dispout))
errors = errors + 1 ;

dispin = 1 ;
#1
decodein = testout ;
decdispin = dispin ;
#1
// $display ("%b %b %b %b *%b*", dispin, testin, testout, {dispout, DUTD.disp6a, DUTD.disp6a2, DUTD.disp6a0, DUTD.disp6a2, DUTD.fghjp31, DUTD.feqg, DUTD.heqj, DUTD.fghj22, DUTD.fi, DUTD.gi, DUTD.hi, DUTD.ji, DUTD.dispout}, decodeout,, decodedisp,, DUTD.k28,, DUTD.disp6b) ;
if (testout != expect_1_disp)
$display ("bad code1 %b %b %b %b %b", dispin, testin, dispout, testout, expect_1_disp) ;
if (dispout != (dispin ^ code[0]))
$display ("bad disp1 %b %b %b %b %b", dispin, testin, dispout, testout, (dispin ^ code[0])) ;
if (0 != (9'b1_1111_1111 & (testin ^ decodeout)))
$display ("diff in abcdefghk decode, %b %b %b %b %b", dispin, testin, dispout, testout, decodeout) ;
if (decodedisp != dispout)
$display ("diff in decoder disp out, %b %b %b %b %b", dispin, testin, dispout, testout, decodeout) ;
if (decodeerr) $display ("decode error asserted improperly, %b %b %b %b %b", dispin, testin, dispout, testout, decodeout) ;
if ((testout != expect_1_disp) | decodeerr |
(dispout != (dispin ^ code[0])) | (decodedisp != dispout))
errors = errors + 1 ;
end
$display ("%d errors in that testing.\n", errors) ;

// Now, having verified all legal codes, lets run some illegal codes
// at the decoder... how to figure illegal codes ? 2048 possible cases,
// lets mark the OK ones...
legal = 0 ;
okdisp = 0 ;
for (i = 0 ; i < 268 ; i = i + 1) begin
#1
// $display ("i=%d: %b %b %d %d %x %x", i, expect_0_disp, expect_1_disp, expect_0_disp, expect_1_disp, expect_0_disp, expect_1_disp) ;
legal[expect_0_disp] = 1 ;
legal[expect_1_disp] = 1 ;
codedisp0 = expect_0_disp ;
codedisp1 = {1'b1, expect_1_disp} ;
okdisp[codedisp0] = 1 ;
okdisp[codedisp1] = 1 ;
mapcode[expect_0_disp] = code[29:21] ;
mapcode[expect_1_disp] = code[29:21] ;
end

$display ("Now lets test all (legal and illegal) codes into the decoder.");
$display ("checking all possible decode inputs") ;
for (i = 0 ; i < 1024 ; i = i + 1) begin
decodein = i ;
decdispin = 0 ;
codedisp1 = 1024 | i ;
#1
if (((legal[i] == 0) & (decodeerr != 1)) |
(legal[i] & (mapcode[i] != decodeout)) |
(legal[i] & (disperr != !okdisp[i])))
$display ("10b:%b start disp:%b 8b:%b end disp:%b codevio:%b dispvio:%b known code:%b used disp:",
decodein, decdispin, decodeout, decodedisp, decodeerr, disperr, legal[i], okdisp[i]) ;
if ((legal[i] == 0) & (decodeerr != 1)) $display ("ERR: decoderr should be 1") ;
if (legal[i] & (mapcode[i] != decodeout)) $display ("ERR: decode output incorrect") ;
if (legal[i] & (disperr != 1) & !okdisp[i]) $display ("ERR: disp err should be asserted") ;
else if (legal[i] & (disperr != 0) & okdisp[i])
$display ("ERR: disp err should not be asserted") ;

if (((legal[i] == 0) & (decodeerr != 1)) |
(legal[i] & !disperr & !okdisp[i]) |
(legal[i] & (mapcode[i] != decodeout)) |
(legal[i] & disperr & okdisp[i]))
errors = errors + 1 ;

decdispin = 1 ;
#1
if (((legal[i] == 0) & (decodeerr != 1)) |
(legal[i] & (mapcode[i] != decodeout)) |
(legal[i] & (disperr != !okdisp[i|1024])))
$display ("10b:%b start disp:%b 8b:%b end disp:%b codevio:%b dispvio:%b known code:%b used disp:",
decodein, decdispin, decodeout, decodedisp, decodeerr, disperr, legal[i], okdisp[i|1024]) ;
if ((legal[i] == 0) & (decodeerr != 1)) $display ("ERR: decoderr should be 1") ;
if (legal[i] & (mapcode[i] != decodeout)) $display ("ERR: decode output incorrect") ;
if (legal[i] & (disperr != 1) & !okdisp[i|1024]) $display ("ERR: disp err should be asserted") ;
else if (legal[i] & (disperr != 0) & okdisp[i|1024])
$display ("ERR: disp err should not be asserted") ;
if (((legal[i] == 0) & (decodeerr != 1)) |
(legal[i] & !disperr & !okdisp[i|1024]) |
(legal[i] & (mapcode[i] != decodeout)) |
(legal[i] & disperr & okdisp[i|1024]))
errors = errors + 1 ;
end // for (i = 0 ; i < 1024 ; i = i + 1)

$display ("\nDone testing decoder.\n") ;
$display ("Total error count: %d", errors);
if (errors == 0) $display ("Congratulations!\n");
$finish ;
end // initial begin

endmodule
用於testbench的測試數據表
【8b10b_a.mem】

000000000100111010001100010110
000000001011101010010001010110
000000010101101010001001010110
000000011110001101111000101001
000000100110101010000101010110
000000101101001101110100101001
000000110011001101101100101001
000000111111000101100011101001
000001000111001010000011010110
000001001100101101110010101001
000001010010101101101010101001
000001011110100101111010001001
000001100001101101100110101001
000001101101100101110110001001
000001110011100101101110001001
000001111010111010010100010110
000010000011011010010010010110
000010001100011101110001101001
000010010010011101101001101001
000010011110010101111001001001
000010100001011101100101101001
000010101101010101110101001001
000010110011010101101101001001
000010111111010010000010110110
000011000110011010000110010110
000011001100110101110011001001
000011010010110101101011001001
000011011110110010000100110110
000011100001110101100111001001
000011101101110010001000110110
000011110011110010010000110110
000011111101011010001010010110
000100000100111100101100010011
000100001011101100110001010011
000100010101101100101001010011
000100011110001100111000110010
000100100110101100100101010011
000100101101001100110100110010
000100110011001100101100110010
000100111111000100100011110010
000101000111001100100011010011
000101001100101100110010110010
000101010010101100101010110010
000101011110100100111010010010
000101100001101100100110110010
000101101101100100110110010010
000101110011100100101110010010
000101111010111100110100010011
000110000011011100110010010011
000110001100011100110001110010
000110010010011100101001110010
000110011110010100111001010010
000110100001011100100101110010
000110101101010100110101010010
000110110011010100101101010010
000110111111010100100010110011
000111000110011100100110010011
000111001100110100110011010010
000111010010110100101011010010
000111011110110100100100110011
000111100001110100100111010010
000111101101110100101000110011
000111110011110100110000110011
000111111101011100101010010011
001000000100111010101100001011
001000001011101010110001001011
001000010101101010101001001011
001000011110001010111000101010
001000100110101010100101001011
001000101101001010110100101010
001000110011001010101100101010
001000111111000010100011101010
001001000111001010100011001011
001001001100101010110010101010
001001010010101010101010101010
001001011110100010111010001010
001001100001101010100110101010
001001101101100010110110001010
001001110011100010101110001010
001001111010111010110100001011
001010000011011010110010001011
001010001100011010110001101010
001010010010011010101001101010
001010011110010010111001001010
001010100001011010100101101010
001010101101010010110101001010
001010110011010010101101001010
001010111111010010100010101011
001011000110011010100110001011
001011001100110010110011001010
001011010010110010101011001010
001011011110110010100100101011
001011100001110010100111001010
001011101101110010101000101011
001011110011110010110000101011
001011111101011010101010001011
001100000100111001101100011001
001100001011101001110001011001
001100010101101001101001011001
001100011110001110011000100110
001100100110101001100101011001
001100101101001110010100100110
001100110011001110001100100110
001100111111000110000011100110
001101000111001001100011011001
001101001100101110010010100110
001101010010101110001010100110
001101011110100110011010000110
001101100001101110000110100110
001101101101100110010110000110
001101110011100110001110000110
001101111010111001110100011001
001110000011011001110010011001
001110001100011110010001100110
001110010010011110001001100110
001110011110010110011001000110
001110100001011110000101100110
001110101101010110010101000110
001110110011010110001101000110
001110111111010001100010111001
001111000110011001100110011001
001111001100110110010011000110
001111010010110110001011000110
001111011110110001100100111001
001111100001110110000111000110
001111101101110001101000111001
001111110011110001110000111001
001111111101011001101010011001
010000000100111001001100011010
010000001011101001010001011010
010000010101101001001001011010
010000011110001110111000100101
010000100110101001000101011010
010000101101001110110100100101
010000110011001110101100100101
010000111111000110100011100101
010001000111001001000011011010
010001001100101110110010100101
010001010010101110101010100101
010001011110100110111010000101
010001100001101110100110100101
010001101101100110110110000101
010001110011100110101110000101
010001111010111001010100011010
010010000011011001010010011010
010010001100011110110001100101
010010010010011110101001100101
010010011110010110111001000101
010010100001011110100101100101
010010101101010110110101000101
010010110011010110101101000101
010010111111010001000010111010
010011000110011001000110011010
010011001100110110110011000101
010011010010110110101011000101
010011011110110001000100111010
010011100001110110100111000101
010011101101110001001000111010
010011110011110001010000111010
010011111101011001001010011010
010100000100111101001100010101
010100001011101101010001010101
010100010101101101001001010101
010100011110001101011000110100
010100100110101101000101010101
010100101101001101010100110100
010100110011001101001100110100
010100111111000101000011110100
010101000111001101000011010101
010101001100101101010010110100
010101010010101101001010110100
010101011110100101011010010100
010101100001101101000110110100
010101101101100101010110010100
010101110011100101001110010100
010101111010111101010100010101
010110000011011101010010010101
010110001100011101010001110100
010110010010011101001001110100
010110011110010101011001010100
010110100001011101000101110100
010110101101010101010101010100
010110110011010101001101010100
010110111111010101000010110101
010111000110011101000110010101
010111001100110101010011010100
010111010010110101001011010100
010111011110110101000100110101
010111100001110101000111010100
010111101101110101001000110101
010111110011110101010000110101
010111111101011101001010010101
011000000100111011001100001101
011000001011101011010001001101
011000010101101011001001001101
011000011110001011011000101100
011000100110101011000101001101
011000101101001011010100101100
011000110011001011001100101100
011000111111000011000011101100
011001000111001011000011001101
011001001100101011010010101100
011001010010101011001010101100
011001011110100011011010001100
011001100001101011000110101100
011001101101100011010110001100
011001110011100011001110001100
011001111010111011010100001101
011010000011011011010010001101
011010001100011011010001101100
011010010010011011001001101100
011010011110010011011001001100
011010100001011011000101101100
011010101101010011010101001100
011010110011010011001101001100
011010111111010011000010101101
011011000110011011000110001101
011011001100110011010011001100
011011010010110011001011001100
011011011110110011000100101101
011011100001110011000111001100
011011101101110011001000101101
011011110011110011010000101101
011011111101011011001010001101
011100000100111000101100011100
011100001011101000110001011100
011100010101101000101001011100
011100011110001111011000100011
011100100110101000100101011100
011100101101001111010100100011
011100110011001111001100100011
011100111111000111000011100011
011101000111001000100011011100
011101001100101111010010100011
011101010010101111001010100011
011101011110100111011010010001
011101100001101111000110100011
011101101101100111010110010001
011101110011100111001110010001
011101111010111000110100011100
011110000011011000110010011100
011110001100011011110001100011
011110010010011011101001100011
011110011110010111011001000011
011110100001011011100101100011
011110101101010111010101000011
011110110011010111001101000011
011110111111010000100010111100
011111000110011000100110011100
011111001100110111010011000011
011111010010110111001011000011
011111011110110000100100111100
011111100001110111000111000011
011111101101110000101000111100
011111110011110000110000111100
011111111101011000101010011100
100011100001111010011000010110
100111100001111100111000001101
101011100001111010111000010101
101111100001111001111000011001
110011100001111001011000011010
110111100001111101011000001011
111011100001111011011000010011
111111100001111100011000001110
111110111111010100000010101110
111111011110110100000100101110
111111101101110100001000101110
111111110011110100010000101110
 
————————————————
版權聲明:本文為CSDN博主「Shawge」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/Shawge/article/details/107426788


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM