码制转换器:BCD、格雷码、七段码之间怎么互转
更新时间:2026-09-12。本文是「集成电路大类 · 芯片设计」**入门层(beginner)**数字逻辑基础第二十二篇。数制与编码建立了补码、BCD、格雷码的基本词汇,这一篇把「各种编码之间怎么转换、用什么电路实现」系统化——这是显示、总线、跨时钟域里反复出现的实际问题。
本文要回答的问题
- BCD 有哪些常见变体(8421、余三码、2421)?为什么需要不止一种?
- 格雷码「相邻只差 1 bit」是怎么构造出来的?二进制怎么直接异或成格雷码、格雷又怎么还原?
- 二进制 ↔ BCD 为什么不能简单取余,double-dabble「移位加 3」算法在干什么?
- 七段显示译码器怎么把 BCD 译成 a~g?共阴/共阳、灭零、消隐是怎么回事?
- 哪类转换用门直接算、哪类必须查表或走时序算法?
一、先分清两类 BCD:有权码与无权码
**BCD(Binary-Coded Decimal,二—十进制编码)**用 4 个 bit 表示一位十进制数字 0~9,剩下的 1010~1111 是非法/无关项(化简时可当 don't care,见 卡诺图)。同样 4 bit 有多种分配方案:
| 编码 | 各位权 | 0~9 表示特点 | 用途/性质 |
|---|---|---|---|
| 8421(自然 BCD) | 8,4,2,1 | 就是二进制 0000~1001 | 最常用,时钟/显示默认 |
| 2421 码 | 2,4,2,1 | 5~9 在高位取 1 | 自补码:数字 N 的码按位取反恰是 9−N,利于十进制减法 |
| 余三码(excess-3) | 无权 | 每个数字 = 8421 码 +3(0011) | 也是自补码;相加后用修正规则容易处理进位 |
余三码是无权码的代表:你不能用位权加权求和还原数字,但它有个好性质——两数按二进制相加后,结果「正好比余三表示多/少一个 3」,配合固定的 ±3 修正就能正确处理十进制进位,早年用加法器做十进制运算时很省事。2421、余三这类自补码在做十进制求补(9 减)时只需按位取反,省逻辑。这些编码今天主要出现在数字钟、仪表显示、老式十进制运算单元里;现代通用计算内部一律用二进制补码,BCD 只在「必须逐位对应十进制」的显示、财务、RTC(实时时钟)场景保留。
二、格雷码:反射构造与异或互转
格雷码(Gray code)最重要的性质是相邻两个码之间只有 1 bit 不同,首尾(0 和最大码)也只差 1 bit(循环码)。普通二进制从 0111(7) 变 1000(8) 要同时翻 4 位,各位若有先有后,中间会瞬间闪过 1111、1001 等错误码;格雷码把每次变化限制为 1 bit,就从根上避免了「多位同时变、却不同步」造成的中间错误值。
它能用一个极简的反射法构造:从 1 位 0,1 开始,每增加一位,就把已有的序列镜像复制一份,原序列前面补 0、镜像序列前面补 1:
1 位: 0 1
2 位: 00 01 | 11 10 (后两个是 01 00 的镜像加 1)
3 位: 000 001 011 010 | 110 111 101 100工程上更有用的是直接换算公式。设二进制 B = bₙ₋₁…b₁b₀,格雷 G = gₙ₋₁…g₀:
- 二进制 → 格雷:最高位不变,其余每位 = 相邻两位二进制异或:
gₙ₋₁ = bₙ₋₁,gᵢ = bᵢ₊₁ ⊕ bᵢ; - 格雷 → 二进制:最高位不变,从高到低用已求出的二进制位与下一位格雷异或:
bᵢ = bᵢ₊₁ ⊕ gᵢ。
// n 位二进制 ↔ 格雷,纯异或,一拍组合逻辑即可
assign gray = bin ^ (bin >> 1); // B→G:右移一位与自身异或
// G→B:逐位「前缀异或」
always @(*) begin
bin_v[N-1] = gray[N-1];
for (int i=N-2; i>=0; i--) bin_v[i] = bin_v[i+1] ^ gray[i];
end这个「相邻只变 1 bit」让格雷码在四个地方极有用:①卡诺图的行列按格雷排列,几何相邻才对应只差一个变量(见 布尔代数与卡诺图);②低功耗/低串扰总线——同时翻转的 bit 少,动态功耗和地弹噪声小;③异步 FIFO 读写指针跨时钟域——指针连续变化时每次只变 1 bit,打两拍同步也不会采到非法中间值(见 异步 FIFO 与 CDC);④机械旋转编码器、旋钮挡位——多位触点不会因微小抖动同时跳变产生错误挡位。也正因为只变 1 bit,格雷码不适合做算术运算(没有位权、不能直接相加),所以惯例是「计数/运算用二进制,只在需要跨域或位置采样的边界转成格雷传过去」。
三、二进制 ↔ BCD:移位加 3(double-dabble)
二进制与格雷之间是纯异或、一块组合逻辑就够;但二进制 ↔ BCD 是非线性的(十进制逢十进位、二进制逢二进位,进位边界对不齐),没法用一个简单位运算表达。两种主流实现:
查表法(LUT/ROM):位宽不大时,把每个二进制数对应的 BCD 预先算好存进 ROM,输入当地址查——最省事,正是 MUX/LUT 实现任意函数的应用。
double-dabble(移位加 3)算法:要把多位二进制在线转 BCD(如 FPGA 里 16 位二进制送数码管),常用这个逐拍/逐位算法:
- 准备一个左宽(放 BCD 各十进制位)右窄(放原二进制)的移位空间;
- 从最高位开始,每次左移 1 bit进 BCD 区;
- 每次移位之前检查每个已形成的 BCD 半字节:若它
≥5,先 +3 再移位;否则直接移位; - 重复到所有二进制位移完,左边各半字节就是各位 BCD。
「为什么是加 3」值得理解:左移一位等于 ×2,而 BCD 半字节要逢 10 进位。若当前值 ≥5,×2 后会 ≥10,本应向高一位进 1、本位留余;先 +3(即 0011)再随移位翻倍,等价于在 4 bit 空间里提前把十进制进位「挤」到上一个半字节(数学上 (x+3)×2 = 2x+6,正好实现逢十进一后本位取余的效果)。它是一个规整的、可用比较器(判 ≥5)+ 加法器(+3)+ 移位寄存器流水线实现的时序过程,是 时序部件和加法器的综合练手项目。
四、七段显示译码器
最常见的码制转换器之一。七段数码管用 a~g 七个发光段拼出 0~9(有的加小数点 dp),七段译码器输入 1 位 BCD,输出 7 个段控信号:
aaa
f b
f b
ggg
e c
e c
ddd例如显示「0」要点亮 a,b,c,d,e,f、熄灭 g。实现上就是一张以 BCD 为输入、7 个段为输出的真值表(10 个有效输入 + 6 个无关项),可用卡诺图化简成门,更常直接 case 查表(见 组合逻辑的 case)。两个必须分清的硬件约定:
- 共阴(common cathode):各段公共端接地,段控给高电平点亮(高有效段码);
- 共阳(common anode):公共端接 VDD,段控给低电平点亮(低有效,段码按位取反)。
同一张字符表,共阴共阳的段码正好互为反相,接错管子会出现「该亮的不亮、该灭的全亮」。多位数码管还常用动态扫描:所有位共用一组段线,靠位选信号快速轮流点亮每一位,利用视觉暂留让人眼看到稳定数字(见 FPGA 数码管与 LED 动态扫描)。控制端还常见:**灭灯 BI(blanking)**强制全灭、灯测试 LT 全亮自检、灭零 RBI/RBO 在数字是 0 且处于整数前导位时自动熄灭多余的「000」——这些使能端很多就是带使能的译码器/三态选择。
五、什么时候用门、什么时候查表/走时序
收束成一张选择表,这也是码制转换类设计的通用判断:
| 转换类型 | 数学性质 | 典型实现 |
|---|---|---|
| 二进制 ↔ 格雷 | 线性(纯异或) | 一块异或组合逻辑,极快 |
| BCD → 七段码 | 小规模真值表 | case/ROM 查表(10 行) |
| 二进制 → BCD | 非线性、逢十进位 | double-dabble 时序算法,或宽位查表 |
| 补码 ↔ 绝对值/反码 | 取反加一 | 加法器 |
| 任意 ≤6 输入函数 | 任意真值表 | FPGA 一个 LUT / 一块 ROM |
判据:有规整算术关系的,用加法器/异或门等运算结构;输入少、关系任意的,用查找表;输入宽又非线性的,用时序迭代算法摊到多拍。想清楚「这个映射有没有算术结构、输入位宽多大」,实现方式基本就定了。
与现有篇目的衔接
- 编码基础:数制与编码(补码、BCD、奇偶)、布尔代数与卡诺图(无关项)
- 实现手段:组合与时序逻辑(case 查表)、组合数据通路/LUT/ROM、加法器
- 典型应用:异步 FIFO 与 Gray 码、FPGA 数码管动态扫描
总结
一句话总结:同一数值有多种编码,转换方式取决于映射有没有算术结构——BCD 用 4 bit 表一位十进制,8421 是自然有权码、2421 和余三码是便于十进制求补/进位修正的自补码,通用运算仍用补码、BCD 只留给显示与财务等逐位十进制场景;格雷码用反射法构造、相邻码只差 1 bit,二进制↔格雷是纯异或(B→G 为 gᵢ=bᵢ₊₁⊕bᵢ、G→B 高位起逐位前缀异或),一块组合逻辑即可,正因为每次只变一位,它广泛用于卡诺图排序、低翻转总线、异步 FIFO 跨域指针和旋转编码器,但因无位权不能直接算术;二进制↔BCD 是非线性的,窄位宽用 ROM/LUT 查表,宽位宽用 double-dabble 移位加 3 算法(≥5 先加 3 再左移以提前实现逢十进一)逐拍转换;七段译码器是 BCD→a~g 的小真值表,用 case 查表,并须区分共阴高有效与共阳低有效(段码互反),多位显示走动态扫描并配灭灯/灯测试/灭零等使能;总的判据是有规整算术关系用加法器/异或结构、输入少且任意用查找表、宽而非线性用时序迭代。