第二章 基于FPGA的HDMA驱动——8B10B编码
文章目录
研究意义
1、串行电路通常采用交流耦合的方式(串接电容);
2、理想电容的阻抗公式Z=1/2Πf ,频率f越高,阻抗越低,反之,频率越低,阻抗越高。电容损耗大,导致幅度不断降低,最严重的后果就是无法识别到底是0还是1;
3、因此直流平衡(使0/1尽可能相等的方式)可以通过降低电容阻抗的方式增加通信可靠性。
8B10B转换概念图
最上面为8B并行码,最下面为编码后的10B串行码,中间为编码方式。3B/4B为高3bit的编码方式,5B/6B为低5bit的编码方式,注意fgh≠FGH,abcde≠ABCDE,具体转换后的值要参考下面的转换表。

8B/10B转化表



看图很抽象,举个例子:
5B/6B编码
输入:EDCBA = 01010
查表得:
RD-时:010110 (差异0,RD保持-)
RD+时:010110 (差异0,RD保持+)
输入:HGF = 010 (十进制2)
查表得:
RD-时:0101 (差异-2,RD变为+)
RD+时:0101 (差异-2,RD变为+)
名词解释
1、D.x.y:低5位EDCBA按其十进制数值记为x,高3位按其十进制数值记为y,例如:D1.2是8’b010_00001;
2、K.x.y:逗号码,比如常见的K28.5,用于同步数据,和上一章中的H_SYNC有异曲同工之妙;
3、RD:极性偏差(running disparity),+1用来表示1比0多,-1用来表示0比1,另外规定RD初始态为-1;
4、D.x.P7/D.x.A7:D.x.7是个特例,当和5B/6B组合时D.x.P7和D.x.A7编码必须选择一个来避免连续的5个0或1。
其中x=17 x=18 x=20当RD=-1时或 x=11 x=13 x=14 当RD=+1时,使用D.x.A7编码,其余情况使用D.x.P7编码。
例如:D.17.7若以D.17.P7的方式编码,则原码为111_10001,RD为-1,编码后应该为100011_1110,此时出现5个连续的1,因此D.17.7只能以D.x.A7方式编码。其实原因很简单,D.x.7时会出现连续的三个0或1,上述六种情况下ei为11或者00,应避开;
5、D.23/27/.29/30 † :当KD共用x码值(23,27,29,30)时,通过高3位区分,D码使用备用P7编码,K码使用A7编码
代码实现思路
1、查找表,逻辑简单,但是编解码电路的工作速度受到FPGA内部存储器读取时间的限制,同时不可避免地增加了芯片的面积和功耗。
2、逻辑运算直接完成编解码功能对,该方法的优点是可以明显减小内部使用面积,难点在于逻辑关系复杂。如果采用卡诺图直接化简则会产生大扇入逻辑表达式,大大限制电路的最高工作速度,同时对逻辑电路的驱动也将加大电路功耗。
3、8B/10B编码模块化实现,较好地反映了8B/10B编码的特点,资源消耗居中。
逻辑核心
注意!!!网上绝大多数文章认为上次8B10B编码结果的RD会作为下次5B6B和3B4B编码的起始RD,这是错误的。以Xilinx文档中的8B/10B编码举例,用上述方法可以得到,当前RD+时,D23.4应该为000101_0010,和手册不符。

正确的判决逻辑为:将上次8B10B编码结果的RD数值用作本次5B6B编码的起始RD,而3B4B编码的起始RD等于5B6B编码结果的RD,3B4B编码结果的RD作为本次8B10B编码的RD。还以D23.4举例,当前RD如下图:

关于这点在网上搜的代码运行结果一直达不到预期要求,百思不得其解, 看了一篇文章后,茅塞顿开,索性自己把代码写了。
详解8B10B编码(高速收发器五) by 电路_fpga
代码细节
`timescale 1ns /1ps //////////////////////////////////////////////////////////////////////////////////// Design Name: LSF // Project Name:// Target Devices:// Tool Versions:// Description: 无K码,若使用K码可以增加K码标识符,和数据码区分 //////////////////////////////////////////////////////////////////////////////////// module Encoder_8B_10B( input clk , input rst_n , input [7:0] data_8b , output [9:0] data_10b );//************************************************************************////*********************** Constant and Variable **************************////************************************************************************////------------------------------Constant---------------------------////--------------------------Inter_Variable-------------------------// wire [4:0] data_5b ; assign data_5b = data_8b[4:0]; reg [6:0] data_5b_6b ; wire rd_5b_6b ; assign rd_5b_6b = data_5b_6b[6];//1代表不平衡,0代表平衡 wire [2:0] data_3b ; assign data_3b = data_8b[7:5]; reg [4:0] data_3b_4b ; wire rd_3b_4b ; assign rd_3b_4b = data_3b_4b[4];//1代表不平衡,0代表平衡 reg [3:0] data_4b ; reg [5:0] data_6b ; assign data_10b ={data_6b,data_4b};//--------------------------Intra_Variable-------------------------// reg rd =1'b0 ;//当前极性值(初始值为RD-),0代表RD-,1代表RD+//************************************************************************////****************************** Main Code *******************************////************************************************************************////5b_6b编码查找表(RD-),由于同一个数的两种编码互补,为了减少代码量只写RD-的情况 //RD-编码:data_3b_4b(RD-) //RD+编码:若极性平衡(即6b中1和0数量相同),则data_3b_4b(RD-);若极性失衡(即6b中1和0数量不同),则data_3b_4b(RD-)取反 //RD+编码有一个特例,D.07在RD极性不同时有两种编码, always@(*)begin case(data_5b)5'h00: data_5b_6b <=7'b1100111;5'h01: data_5b_6b <=7'b1011101;5'h02: data_5b_6b <=7'b1101101;5'h03: data_5b_6b <=7'b0110001;5'h04: data_5b_6b <=7'b1110101;5'h05: data_5b_6b <=7'b0101001;5'h06: data_5b_6b <=7'b0011001;5'h07: data_5b_6b <=7'b0111000;5'h08: data_5b_6b <=7'b1111001;5'h09: data_5b_6b <=7'b0100101;5'h0a: data_5b_6b <=7'b0010101;5'h0b: data_5b_6b <=7'b0110100;5'h0c: data_5b_6b <=7'b0001101;5'h0d: data_5b_6b <=7'b0101100;5'h0e: data_5b_6b <=7'b0011100;5'h0f: data_5b_6b <=7'b1010111;5'h10: data_5b_6b <=7'b1011011;5'h11: data_5b_6b <=7'b0100011;5'h12: data_5b_6b <=7'b0010011;5'h13: data_5b_6b <=7'b0110010;5'h14: data_5b_6b <=7'b0001011;5'h15: data_5b_6b <=7'b0101010;5'h16: data_5b_6b <=7'b0011010;5'h17: data_5b_6b <=7'b1111010;5'h18: data_5b_6b <=7'b1110011;5'h19: data_5b_6b <=7'b0100110;5'h1a: data_5b_6b <=7'b0010110;5'h1b: data_5b_6b <=7'b1110110;5'h1c: data_5b_6b <=7'b0001110;5'h1d: data_5b_6b <=7'b1101110;5'h1e: data_5b_6b <=7'b1011110;5'h1f: data_5b_6b <=7'b1101011; endcase end//3b_4b编码查找表(RD-) //RD-编码:data_3b_4b(RD-) //RD+编码:若极性平衡,则data_3b_4b(RD-);若极性失衡,则data_3b_4b(RD-)取反 always@(*)begin case(data_3b)3'b000: data_3b_4b <=5'b11011;3'b001: data_3b_4b <=5'b01001;3'b010: data_3b_4b <=5'b00101;3'b011: data_3b_4b <=5'b01100;3'b100: data_3b_4b <=5'b11101;3'b101: data_3b_4b <=5'b01010;3'b110: data_3b_4b <=5'b00110;3'b111: begin if(!data_5b_6b[6]&&(data_5b_6b[0]==data_5b_6b[1]))//筛选出D11,13,14,17,18,20 data_3b_4b <=5'b10111;//A7码,防止出现5个连续的1或0else data_3b_4b <=5'b11110;//P7码 end endcase end//6B→4B→6B...→4B极性切换 always@(*)begin case({rd_5b_6b,data_3b_4b,rd})3'b000:begin //全体平衡,保持RD-编码 rd <= rd; data_4b <= data_3b_4b[3:0]; data_6b <= data_5b_6b[5:0];end3'b001:begin //全体平衡,保持RD+编码 rd <= rd; data_4b <= data_3b_4b[3:0];if(data_5b_6b ==7'b0111000)data_6b <=~data_5b_6b[5:0];else data_6b <= data_5b_6b[5:0];end3'b010:begin rd <=~rd;//4b失衡,编码后变成RD+ data_4b <= data_3b_4b[3:0];//由于6b平衡,编码后保持RD-,所以4b按照RD-编码 data_6b <= data_5b_6b[5:0];//当前RD-,所以6b按照RD-编码 end3'b011:begin rd <=~rd;//4b失衡,编码后变成RD- data_4b <=~data_3b_4b[3:0];//由于6b平衡,编码后保持RD+,所以4b按照RD+编码 if(data_5b_6b ==7'b0111000)data_6b <=~data_5b_6b[5:0];//当前RD+,所以6b按照RD+编码 else data_6b <= data_5b_6b[5:0];end3'b100:begin rd <=~rd;//4b平衡,编码后保持RD+ data_4b <=~data_3b_4b[3:0];//由于6b失衡,编码后变为RD+,所以4b按照RD+编码 data_6b <= data_5b_6b[5:0];//当前RD-,所以6b按照RD-编码 end3'b101:begin rd <=~rd;//4b平衡,编码后保持RD- data_4b <= data_3b_4b[3:0];//由于6b失衡,编码后变为RD-,所以4b按照RD-编码 data_6b <=~data_5b_6b[5:0];//当前RD+,所以6b按照RD+编码 end3'b110:begin rd <= rd;//4b失衡,编码后变为RD- data_4b <=~data_3b_4b[3:0];//由于6b失衡,编码后变为RD+,所以4b按照RD+编码 data_6b <= data_5b_6b[5:0];//当前RD-,所以6b按照RD-编码 end3'b111:begin rd <= rd;//4b失衡,编码后变为RD+ data_4b <= data_3b_4b[3:0];//由于6b失衡,编码后变为RD-,所以4b按照RD-编码 data_6b <=~data_5b_6b[5:0];//当前RD+,所以6b按照RD+编码 end endcase end//************************************************************************////*************************** DETECT & DEBUG *****************************////************************************************************************// endmodule