8b/10b编码方式(详细)总结附实例快速理解

8b/10b编码是一种用于高速串行通信的编码方式,旨在保证DC平衡,防止信号错误。编码过程包括8位拆分为3位和5位,分别进行3B/4B和5B/6B编码。转换规则确保连续的1或0不超过5位,利用运行不一致性(RD)统计码字的平衡性,以12个控制字符标识传输状态。

前言

本文主要通过图文方式介绍8b/10b编码,具体转换方式通过实例解析,方便读者快速掌握。

一、简介

8b/10b编码也叫做8字节/10字节,是目前高速串行通信中经常用到的一种编码方式,直观的理解就是把8bit数据编码成10bit来传输。该编码方式最初是由IBM公司在1983年发明并应用于ESCON[200M互联系统],由AI widmer和Peter Franaszek在IBM的刊物“研究与开发”上提出。

二、转换过程

2.1 背景

8b/10编码的特性就是保证DC平衡——直流平衡,其实就是串行数据中连续出现的1/0达到一个平衡均匀的状态,当高速串行流动逻辑1或逻辑0有多个位没有产生变化时,信号的转换就会因为电压位阶段关系而造成信号错误。
理想电容的阻抗公式在这里插入图片描述通过上面公式可以知道,频率f越高,阻抗越低,反之,频率越低,阻抗越高。因此上图中的情况,当码型是高频的时候,基本可以不损耗的传输过去,但是当码型为连续的0或者1的时候,电容的损耗就很大,导致幅度不断降低,最严重的后果就是无法识别到底是0还是1,因此8b/10b编码就是为了尽量把低频的码型优化成较高频率的码型,从而降低阻抗带来的损耗。
将8bit编码成10bit后,连续的1或者0不能超过5位,所以10b中0和1的位数只可能出现3中情况:
有5个0和5个1
有6个0和4个1
有4个0和6个1

在这里插入图片描述

2.2 具体转换过程

1、拆分转换
假设原始8位数据从高到低用HGFEDCBA表示,8B/10B编码将8位数据分成高3位HGF和低5位EDCBA两个子组。然后经过5B/6B编码,将低5位EDCBA映射成abcdei;高3位经过3B/4B编码,映射成fghj,最后合成abcdeifghj发送。发送时由于是小端模式,a先发送,相反,解码是将1组10位的输入数据经过变换得到8位数据位。在这里插入图片描述2、转换规则

将低5位EDCBA按其十进制数值记为x,将高3位按其十进制数值记为y,将原始8bit数据记为D.x.y,依次查表得到相应的转换结果。

5B/6B编码映射关系表
在这里插入图片描述在这里插入图片描述

举例说明:
例如8bit数“101 10101”,即十进制数181,按照按照3/5的划分原则x=10101(21),y=101(5),所示这个数被表示为D.21.5。此外在8B/10B编码中,还需用到12种控制字符,用来标识传输数据的开始和结束,传输空闲等状态,按照上述规则,将控制字符记为K.x.y。

3B/4B编码映射关系表
在这里插入图片描述RD:running disparity 直译“运行不一致性”,也翻译成“极性偏差”(running disparity,RD),RD是对编码后的数据流Disparity的一个统计,+1用来表示1比0多,-1用来表示0比1多,-1是它的初始化状态,编码中“1”和“0”数量相等的码字称为“完美平衡码”。

和5B/6B组合时D.x.m7和D.x.n7编码必须选择一个来避免连续的5个0或1。
具体怎么选择呢,是有规则的:

D.x.n7用在:x=17 x=18 x=20当RD=-1时;
x=11 x=13 x=14 当RD=+1时。
其他情况下x.n7码不能被使用

举例说明:
例1:
在编码时,RD的初始值为负,即RD-,根据当前的RD值,决定相应的编码输出。比如:在上表中,对于D.x.3(011),其对应的4B码字有两种:1100和0011,若此时RD为负,则取1100作为其对应的4B码字作为输出,同时检验此时的编码是否为完美编码,如果是完美编码,则保持RD的极性不变;否则改变RD的极性。通过控制RD的极性,同时在编码时根据RD的极性选择相对应的编码值,使得编码后的数据流有更好的直流平衡特性。

例2:
在上表中,对于D.x.4(100),其对应的4B码字有两种:1101和0010,若此时RD为负,则取1101作为其对应的4B码字作为输出,同时检验此时的编码是否为完美编码,如果是完美编码,则保持RD的极性不变;否则改变RD的极性。通过控制RD的极性,同时在编码时根据RD的极性选择相对应的编码值,使得编码后的数据流有更好的直流平衡特性,达到我们的缓解长“0”或长“1”的目的。

8B/10B编码映射关系表
在这里插入图片描述下图所示为RD状态转移图:
在这里插入图片描述
规划8B/10B编码机制的时候,使用了12个特殊的控制代码(Control Characters),他们能在数据中被发送,还可以组合成各种“原语”。由于控制字符只有12种,对其单独编码即可,可不按照上述方法对其编码。其编码映射关系如下:

在这里插入图片描述

三、其他相关链接

1、PCIe物理层总结-PCIE专题知识(一)

2、PCIe数据链路层图文总结-PCIe专题知识(二)

3、PCIe物理层链路训练和初始化总结-PCIe专题知识(三)

4、PCIe物理层弹性缓存机制解析-PCIe专题知识(四)

5、PCI总线及发展历程总结

<think>嗯,用户想要用Verilog实现一个32位并行的8b/10b编码器。首先,我需要回忆一下8b/10b编码的基本原理。这个编码方式8位数据转换成10位,确保直流平衡和足够的时钟恢复 transitions。通常每个字节(8位)独立编码10位,所以32位的话,应该是分成四个8位的部分,每个单独编码,然后合并成40位的输出。对吧? 接下来,用户需要的是并行处理,也就是同时处理这四个8位数据。这样设计的话,每个8b/10b编码器模块需要独立工作,互不干扰。Verilog里可以用generate语句来实例化四个这样的模块。每个模块处理输入的8位中的一部分,比如输入32位分成四个8位段,每个段连接到各自的编码实例。 然后,我需要考虑编码器的具体实现。8b/10b编码有数据符号(D.x.y)和控制符号(K.x.y)。编码过程涉及查找表,可能需要用case语句或者查找表LUT来实现。这里可能需要两个查找表:一个处理5b到6b的转换,另一个处理3b到4b的转换。同时,还需要维护一个不一致性(disparity)的状态,根据当前编码的差异来调整下一个符号的编码方式,以保持直流平衡。 需要注意的是,每个子模块在编码时,需要跟踪自己的不一致性状态,或者整个模块共享一个状态?这里可能需要每个子模块独立维护自己的状态,因为并行处理的情况下,各个部分的编码应该是相互独立的。否则,状态共享会导致时序问题,增加复杂度。 另外,输入的32位数据可能需要拆分成四个8位组。比如,输入data_in[31:0]可以分为data_in[31:24], data_in[23:16], data_in[15:8], data_in[7:0],分别对应四个编码器。每个编码器的输出是10位,那么四个编码器的输出合并成data_out[39:0]。 还需要考虑控制符号,用户可能需要指定某个字节是否为控制符号。因此,输入可能还需要一个4位的控制信号,比如ctrl[3:0],每位对应一个字节是否为控制符号。 在Verilog代码的结构上,顶层模块将实例化四个encoder_8b10b模块,并将输入数据和控制信号分配到各个子模块。每个子模块的输出拼接成最终的40位输出。 关于测试,用户可能需要验证代码的正确性,比如使用测试向量或仿真。这部分可能需要编写测试平台(testbench),输入不同的数据和控制信号,检查输出是否符合预期。 可能的问题点包括:状态机的正确性,尤其是disparity的处理;各个子模块的并行处理是否正确;输入输出的位宽是否正确分配;以及控制信号是否正确传递到每个子模块。 现在,我需要检查是否有现有的Verilog代码示例或开源项目可以参考。比如,OpenCores可能有相关的实现,但用户需要的是一个简洁的示例,而不是复杂的实现。因此,代码需要简化,可能使用查找表或case语句来实现编码逻辑,而不是复杂的算法。 最后,代码需要符合Verilog的语法规范,确保模块端口、信号连接正确,并且能够综合成实际的硬件。</think>以下是Verilog实现32位并行8b/10b编码器的基本架构和代码示例: ### 实现架构 1. **并行结构**:将32位输入拆分为4个8位数据块并行处理 2. **子模块复用**:每个8位数据使用标准8b/10b编码器模块 3. **差异控制**:每个子编码器独立维护运行差异(Running Disparity) 4. **输出组合**:将4个10编码结果拼接为40位输出 ```verilog module encoder_8b10b_32bit ( input wire clk, input wire rst, input wire [31:0] data_in, input wire [3:0] ctrl_in, // 每个bit控制对应字节是否为控制字符 output reg [39:0] data_out, output reg [3:0] rd_status ); // 8b10b子编码器声明 encoder_8b10b encoder[3:0] ( .clk(clk), .rst(rst), .data_in({data_in[31:24], data_in[23:16], data_in[15:8], data_in[7:0]}), .ctrl_in(ctrl_in), .data_out({data_out[39:30], data_out[29:20], data_out[19:10], data_out[9:0]}), .rd_out(rd_status) ); endmodule // 标准8b10b编码器模块 module encoder_8b10b ( input wire clk, input wire rst, input wire [7:0] data_in, input wire ctrl_in, output reg [9:0] data_out, output reg rd_out ); // 运行差异状态机 reg current_rd; always @(posedge clk or posedge rst) begin if (rst) begin current_rd <= 1'b0; end else begin current_rd <= next_rd; end end // 编码逻辑(实际实现需要完整LUT) always @(*) begin case({ctrl_in, data_in, current_rd}) // 这里应包含完整的编码查找表 // 示例:D0.0编码 10'b0_00000000_0: {data_out, next_rd} = {10'b100111_0100, 1'b1}; 10'b0_00000000_1: {data_out, next_rd} = {10'b011000_1011, 1'b0}; // ...其他编码模式 default: {data_out, next_rd} = 11'b0; endcase end endmodule ``` ### 关键特性 1. **并行吞吐**:每个时钟周期处理32位数据(4个独立编码通道) 2. **时钟域处理**:同步设计支持流水线实现 3. **差异控制**:每个子编码器独立维护运行差异状态[^1] 4. **控制符号支持**:通过ctrl_in选择数据/控制字符编码模式
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值