8B/10B码表及代码解读

8B/10B码表及代码解读

本文的目的在于能够读懂8B/10B码表,并能看懂赛灵思原厂8B/10B编解码代码,为日后的高速接口仿真打下基础。

读码表

前置概念

运行差异RD(RD,running disparity):
RD = -1 代表编码后1比0的个数多两个
RD = -1 代表编码后0比1的个数多两个
极性代表了编码中0与1的大小关系。初始极性为RD = -1
控制符号:
查找表中的K系列编码,用于检测字节边界。

5B/6B

如下所示,仅关注D即可
经过查表后5bit数据转换为了6bit
3bit数据转换为了4bit即可
在这里插入图片描述
本质上仍为映射关系。
5B最多能表示到31
当获取到5bit数据直接查表即可。
在这里插入图片描述

3B/4B

仅关注D即可
注意:
D.x.7具有P7与A7两套编码,其目的是为了避免出现连续的五个1或0
A7仅用于
x=17 x=18 x=20当RD=-1时;
x=11 x=13 x=14 当RD=+1时
其他情况的A7作为控制符号。
在这里插入图片描述

代码示例及注释

示例来源
详细过程见代码注释
赛灵思gmii转sgmii的IP核仿真示例
在这里插入图片描述
整体思路即
8B输入->5B/6B查表->计算RD->3B/4B查表->10输出
编码例程及相关注释如下

  //----------------------------------------------------------------------------
  // Procedure to perform 8B10B encoding
  //----------------------------------------------------------------------------

   task encode_8b10b;
      input [7:0] d8;
      input is_k;
      output [0:9] q10;
      input disparity_pos_in;
      output disparity_pos_out;
      reg [5:0] b6;
      reg [3:0] b4;
      reg k28, pdes6, a7, l13, l31, a, b, c, d, e;
      integer I;

      begin  // encode_8b10b
   // precalculate some common terms
   a = d8[0];
   b = d8[1];
   c = d8[2];
   d = d8[3];
   e = d8[4];

   k28 = is_k && d8[4:0] === 5'b11100;
/*-------------------
对应RD为-1时的备选情况
即:
a=1,b=0,c=0,d=0,e=1   d[4:0]=17   
a=0,b=1,c=0,d=0,e=1   d[4:0]=18
a=0,b=0,c=1,d=0,e=1   d[4:0]=20
注意大小端序
------------------------*/
   l13 = (((a ^ b) & !(c | d))
            | ((c ^ d) & !(a | b)));
/*-------------------
对应RD为+1时的备选情况
即:
a=1,b=0,c=1,d=1,e=0   d[4:0]=13   
a=0,b=1,c=1,d=1,e=0   d[4:0]=14
a=1,b=1,c=0,d=1,e=0   d[4:0]=11
注意大小端序
------------------------*/
   l31 = (((a ^ b) & (c & d))
    | ((c ^ d) & (a & b)));
/*---------------
选择A7时仅有三种情况
即:
1、特殊控制编码
2、x=17 x=18 x=20当RD=-1时;
3、x=11 x=13 x=14 当RD=+1时
-------------------*/
   a7 = is_k | ((l31 & d & !e & disparity_pos_in)
                   | (l13 & !d & e & !disparity_pos_in));
/*------------------
根据查找表进行对照即可
注意大小端序
-----------------*/
     // calculate the running disparity after the 5B6B block encode
   if (k28)                           //K.28
     if (!disparity_pos_in)
             b6 = 6'b111100;
     else
             b6 = 6'b000011;

   else
     case (d8[4:0])
             5'b00000 :                 //D.0
               if (disparity_pos_in)
     b6 = 6'b000110;
               else
     b6 = 6'b111001;
             5'b00001 :                 //D.1
               if (disparity_pos_in)
     b6 = 6'b010001;
               else
     b6 = 6'b101110;
             5'b00010 :                 //D.2
               if (disparity_pos_in)
     b6 = 6'b010010;
               else
     b6 = 6'b101101;
             5'b00011 :
         b6 = 6'b100011;              //D.3
             5'b00100 :                 //-D.4
               if (disparity_pos_in)
     b6 = 6'b010100;
               else
     b6 = 6'b101011;
             5'b00101 :
               b6 = 6'b100101;          //D.5
             5'b00110 :
               b6 = 6'b100110;          //D.6
             5'b00111 :                 //D.7
               if (!disparity_pos_in)
     b6 = 6'b000111;
               else
     b6 = 6'b111000;
             5'b01000 :                 //D.8
               if (disparity_pos_in)
     b6 = 6'b011000;
               else
     b6 = 6'b100111;
             5'b01001 :
               b6 = 6'b101001;          //D.9
             5'b01010 :
               b6 = 6'b101010;          //D.10
             5'b01011 :
               b6 = 6'b001011;          //D.11
             5'b01100 :
               b6 = 6'b101100;          //D.12
             5'b01101 :
               b6 = 6'b001101;          //D.13
             5'b01110 :
               b6 = 6'b001110;          //D.14
             5'b01111 :                 //D.15
               if (disparity_pos_in)
     b6 = 6'b000101;
               else
     b6 = 6'b111010;

             5'b10000 :                 //D.16
               if (!disparity_pos_in)
     b6 = 6'b110110;
               else
     b6 = 6'b001001;

             5'b10001 :
               b6 = 6'b110001;          //D.17
             5'b10010 :
               b6 = 6'b110010;          //D.18
             5'b10011 :
               b6 = 6'b010011;          //D.19
             5'b10100 :
               b6 = 6'b110100;          //D.20
             5'b10101 :
               b6 = 6'b010101;          //D.21
             5'b10110 :
               b6 = 6'b010110;          //D.22
             5'b10111 :                 //D/K.23
               if (!disparity_pos_in)
     b6 = 6'b010111;
               else
     b6 = 6'b101000;
             5'b11000 :                 //D.24
               if (disparity_pos_in)
     b6 = 6'b001100;
               else
     b6 = 6'b110011;
             5'b11001 :
               b6 = 6'b011001;          //D.25
             5'b11010 :
               b6 = 6'b011010;          //D.26
             5'b11011 :                 //D/K.27
               if (!disparity_pos_in)
     b6 = 6'b011011;
               else
     b6 = 6'b100100;
             5'b11100 :
               b6 = 6'b011100;          //D.28
             5'b11101 :                 //D/K.29
               if (!disparity_pos_in)
     b6 = 6'b011101;
               else
     b6 = 6'b100010;
             5'b11110 :                 //D/K.30
               if (!disparity_pos_in)
     b6 = 6'b011110;
               else
     b6 = 6'b100001;
             5'b11111 :                 //D.31
               if (!disparity_pos_in)
     b6 = 6'b110101;
               else
     b6 = 6'b001010;
             default :
               b6 = 6'bXXXXXX;
     endcase // case(d8[4:0])


   // reverse the bits
   for (I = 0; I < 6; I = I + 1)
     q10[I] = b6[I];
/*---------------------------
极性(RD)计算
当进行5B/6B编码后,可能会出现0与1的个数不一致的情况
例:5'b00000 : 对应的6B编码为100111   0011000
1与0的个数不相等,无论哪种情况,极性都会发生改变,此时需要取非进行反转。
5'b00011 : 对应的6B编码为11001仅有一种情况,1与0的个数相等,无需反转
------------------------------*/
   // calculate the running disparity after the 5B6B block encode
   if (k28)
     pdes6 = !disparity_pos_in;
   else
     case (d8[4:0])
             5'b00000 : pdes6 = !disparity_pos_in;
             5'b00001 : pdes6 = !disparity_pos_in;
             5'b00010 : pdes6 = !disparity_pos_in;
             5'b00011 : pdes6 = disparity_pos_in;
             5'b00100 : pdes6 = !disparity_pos_in;
             5'b00101 : pdes6 = disparity_pos_in;
             5'b00110 : pdes6 = disparity_pos_in;
             5'b00111 : pdes6 = disparity_pos_in;
             5'b01000 : pdes6 = !disparity_pos_in;
             5'b01001 : pdes6 = disparity_pos_in;
             5'b01010 : pdes6 = disparity_pos_in;
             5'b01011 : pdes6 = disparity_pos_in;
             5'b01100 : pdes6 = disparity_pos_in;
             5'b01101 : pdes6 = disparity_pos_in;
             5'b01110 : pdes6 = disparity_pos_in;
             5'b01111 : pdes6 = !disparity_pos_in;
             5'b10000 : pdes6 = !disparity_pos_in;
             5'b10001 : pdes6 = disparity_pos_in;
             5'b10010 : pdes6 = disparity_pos_in;
             5'b10011 : pdes6 = disparity_pos_in;
             5'b10100 : pdes6 = disparity_pos_in;
             5'b10101 : pdes6 = disparity_pos_in;
             5'b10110 : pdes6 = disparity_pos_in;
             5'b10111 : pdes6 = !disparity_pos_in;
             5'b11000 : pdes6 = !disparity_pos_in;
             5'b11001 : pdes6 = disparity_pos_in;
             5'b11010 : pdes6 = disparity_pos_in;
             5'b11011 : pdes6 = !disparity_pos_in;
             5'b11100 : pdes6 = disparity_pos_in;
             5'b11101 : pdes6 = !disparity_pos_in;
             5'b11110 : pdes6 = !disparity_pos_in;
             5'b11111 : pdes6 = !disparity_pos_in;
             default  : pdes6 = disparity_pos_in;
     endcase // case(d8[4:0])
/*------------------------
根据极性查表即可        
-------------------------*/
   case (d8[7:5])
     3'b000 :                     //D/K.x.0
             if (pdes6)
               b4 = 4'b0010;
       else
               b4 = 4'b1101;
     3'b001 :                     //D/K.x.1
             if (k28 && !pdes6)
               b4 = 4'b0110;
             else
               b4 = 4'b1001;
     3'b010 :                     //D/K.x.2
             if (k28 && !pdes6)
               b4 = 4'b0101;
             else
               b4 = 4'b1010;
     3'b011 :                     //D/K.x.3
             if (!pdes6)
               b4 = 4'b0011;
             else
               b4 = 4'b1100;
     3'b100 :                     //D/K.x.4
             if (pdes6)
               b4 = 4'b0100;
             else
               b4 = 4'b1011;
     3'b101 :                     //D/K.x.5
             if (k28 && !pdes6)
               b4 = 4'b1010;
             else
               b4 = 4'b0101;
     3'b110 :                     //D/K.x.6
             if (k28 && !pdes6)
               b4 = 4'b1001;
             else
               b4 = 4'b0110;
     3'b111 :                     //D.x.P7
             if (!a7)
               if (!pdes6)
     b4 = 4'b0111;
               else
     b4 = 4'b1000;
             else                   //D/K.y.A7
               if (!pdes6)
     b4 = 4'b1110;
               else
     b4 = 4'b0001;
     default :
             b4 = 4'bXXXX;
   endcase

   // Reverse the bits
   for (I = 0; I < 4; I = I + 1)
     q10[I+6] = b4[I];
/*----------------------
同pdes6的计算方式
注意:
3'b011  :对应的4B数据为1100 0011
1与0的个数相同,不发生反转。
--------------------------*/
   // Calculate the running disparity after the 4B group
   case (d8[7:5])
     3'b000  : disparity_pos_out = ~pdes6;
     3'b001  : disparity_pos_out = pdes6;
     3'b010  : disparity_pos_out = pdes6;
     3'b011  : disparity_pos_out = pdes6;
     3'b100  : disparity_pos_out = ~pdes6;
     3'b101  : disparity_pos_out = pdes6;
     3'b110  : disparity_pos_out = pdes6;
     3'b111  : disparity_pos_out = ~pdes6;
     default : disparity_pos_out = pdes6;
   endcase
      end
   endtask // encode_8b10b

番外

该部分仅列举8B10B编码实现方式,具体如何使用详见gig_ethernet_pcs_pma_0示例即可。
找了一圈教程,最后还是回原厂了TwT。
大部分工程都直接走gmii把这层仿真给绕过去了,毕竟是原厂的ip。而且即便是出了问题,直接ila抓信号即可。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值