打印
[VHDL]

玩转VHDL020-8B10B编码器

[复制链接]
1545|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ucx|  楼主 | 2018-3-19 21:03 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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为系统时钟,d8B8位信源码D[7:0]q10B为并行10位线路码Q[0:9],实际应用中通常需要串行化,按照Q[0], Q[1],.. ,Q[9]的顺序发送。en10b是编码使能脉冲,如果串行化时钟就是clock,那么en10b应为每10clock周期一次。q10Ben10b有效下一周期输出。在en10b有效时刻,如果K28_5 为高则输出K28.5,否则若K28_1为高输出K28.1,其他输出D码。为适应绝大部分应用,此编码模块中K码部分只使用K28.1K28.5。例如可用K28.5作为界定一帧的起始,K28.1用来表征信道空闲。

上一帖说到8B10B可以拆分为5B6B3B4B,它们的线路码字都可以分成正码和负码两组,负码与正码相同或相反。5B部分x=D[4:0]对应6B线路用Dx表示;3B部分y=D[7:5]对应4BDy表示。那么先定义一个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位表示,第6LSB=Dx_T[6]用来表示该码字的极性变化规律。LSB不是用’0’’1’来表示,而是用’X’’U’’-‘来表示,是为了明显和前面6位的线路码字区分开来。’X’代表码字的输入极性和和输出极性不同且正码字与负码字不同,’U’代表输入输出极性相同但正负码字不同,’-‘代表输入输出极性相同且正负码字相同。极性变化只有这三种情况。数组中前32个元素分别一一对应x031映射的Dx值。最后一个元素用来表示K28 == 001111。那么x的范围是032

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.1yDy_T[10]表示K28.5y
使用A7码的条件是d8B[7:5]==7,且,x=11,1314RD为正时)或x=17,1820RD为负时),那么定义选择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);

@clock if(en10b){
         q10B = {abcdei , fghj};
         RD ^= Dx[6] ^ Dy[4];
}
至此,8B10B编码完毕。enc8B_10B结构体全部代码如下图所示。



本例中使用Dx_T[0:32][0:6]是为了便于把代码与编码表对应理解,实际上,若不考虑可读性,可直接定义常量Dx_TableDy_Table,这样代码中可略去33行到38行的循环赋值。
附件中给出8B10B5B6B3B4B各种形式的编码表,并在压缩包里给出编码器的完整VHDL代码,有兴趣者可查看。

相关帖子

沙发
xyz549040622| | 2018-3-20 06:35 | 只看该作者
支持下!

使用特权

评论回复
评论
ucx 2018-3-20 08:07 回复TA
我才发现,文本[ i ]若没有空格被解释成斜体,在页面上显示不出来了。 
板凳
Echo000| | 2018-4-16 17:10 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

ucx

29

主题

89

帖子

5

粉丝