本帖最后由 ucx 于 2018-3-20 08:09 编辑
enc8B_10B.rar
(1.03 KB)
编码表.pdf
(488.68 KB)
8B10B编码模块enc8B_10B( input clock, input[7:0] d8B, input en10b, K28_1,K28_5, output[0:9] q10B ); 其中clock为系统时钟,d8B为8位信源码D[7:0],q10B为并行10位线路码Q[0:9],实际应用中通常需要串行化,按照Q[0], Q[1],.. ,Q[9]的顺序发送。en10b是编码使能脉冲,如果串行化时钟就是clock,那么en10b应为每10个clock周期一次。q10B在en10b有效下一周期输出。在en10b有效时刻,如果K28_5 为高则输出K28.5,否则若K28_1为高输出K28.1,其他输出D码。为适应绝大部分应用,此编码模块中K码部分只使用K28.1和K28.5。例如可用K28.5作为界定一帧的起始,K28.1用来表征信道空闲。
上一帖说到8B10B可以拆分为5B6B和3B4B,它们的线路码字都可以分成正码和负码两组,负码与正码相同或相反。5B部分x=D[4:0]对应6B线路用Dx表示;3B部分y=D[7:5]对应4B用Dy表示。那么先定义一个5B6B的正码表如下:
constant Dx_T[0:32][0:6] = { "100111X","011101X","101101X","110001-", "110101X","101001-","011001-","111000U", "111001X","100101-","010101-","110100-", "001101-","101100-","011100-","010111X", "011011X","100011-","010011-","110010-", "001011-","101010-","011010-","111010X", "110011X","100110-","010110-","110110X", "001110-","101110X","011110X","101011X", "001111X"};
上表中任一数组元素用7位表示,第6位LSB=Dx_T[6]用来表示该码字的极性变化规律。LSB不是用’0’或’1’来表示,而是用’X’、’U’或’-‘来表示,是为了明显和前面6位的线路码字区分开来。’X’代表码字的输入极性和和输出极性不同且正码字与负码字不同,’U’代表输入输出极性相同但正负码字不同,’-‘代表输入输出极性相同且正负码字相同。极性变化只有这三种情况。数组中前32个元素分别一一对应x从0到31映射的Dx值。最后一个元素用来表示K28 == 001111。那么x的范围是0到32。
x = K28_1 ||K28_5 ? 32 : d8B[4:0];
常量中的’X’、’U’或’-‘在VHDL中是可以区分的,但在变量中被忽略(verilog中的情况我没有去尝试)。如果直接定义使用Dx[0:6]=Dx_T[x]; 那么Dx就是变量,Dx[6]将不能够区分’X’、’U’或’-‘这些值。所以重新定义一个元素为8位数的数组Dx_Table[0:32][0:7]。
i = 0 : 32; Dx_Table[ i ] ={ Dx_T[ i ][0:5], Dx_T[ i ][6]==’X’, Dx_T[ i ][6]!=’-’};
Dx[0:7]=Dx_Table[x]; 那么Dx[6]==1表示输入输出极性不同,Dx[7]==1表示正负码字不同。 5B6B编码后的极性输出,也即3B4B编码的输入yiRD =RD ^ Dx[6]。其中RD表示当前码字的极性(’1’表示+),也是5B6B编码的输入极性。RD ^ Dx[7]用来选取正码还是负码: abcdei = RD ^Dx[7] ? Dx[0:5] : ~ Dx[0:5];
类似地3B4B部分
constant Dy_T [0:10][0:4] = { "1011X", "1001-","0101-", "1100U", "1101X","1010-", "0110-", "1110X", "0111X", "0110U","0101U"};
Dy_T[8]表示A7码,Dy_T[9]表示K28.1y,Dy_T[10]表示K28.5y, 使用A7码的条件是d8B[7:5]==7,且,x=11,13或14(RD为正时)或x=17,18或20(RD为负时),那么定义选择A7的条件 sA7 = d8B[7:5]==7&& ( RD ? x==11||x==13||x==14 : x==17||x==18 ||x==20);
再定义3B4B表的元素索引,并最终输出一气呵成。 y = K28_5 ? 10: K28_1 ? 9 : sA7 ?8: d8B[7:5]; i = 0 : 10; Dy_Table[ i ] = { Dx_T[ i ][0:3], Dx_T[ i ][4]==’X’, Dx_T[ i ][4]!=’-’}; Dy[0:5]=Dy_Table[y]; fghj = Dy(5)&& yiRD ? Dy(0 to 3) : ~Dy(0 to 3);
q10B = {abcdei , fghj}; RD ^= Dx[6] ^ Dy[4]; } 至此,8B10B编码完毕。enc8B_10B结构体全部代码如下图所示。
本例中使用Dx_T[0:32][0:6]是为了便于把代码与编码表对应理解,实际上,若不考虑可读性,可直接定义常量Dx_Table和Dy_Table,这样代码中可略去33行到38行的循环赋值。 附件中给出8B10B,5B6B,3B4B各种形式的编码表,并在压缩包里给出编码器的完整VHDL代码,有兴趣者可查看。 |