数值比较器与奇偶校验:谁大谁小,错没错
更新时间:2026-09-12。本文是「集成电路大类 · 芯片设计」入门层(beginner)数字逻辑基础第十八篇。加法器 解决了「两数相加」,这一篇解决两个同样高频的问题:两个数谁大谁小,以及一串 bit 在传输/存储后有没有出错。
本文要回答的问题
- 怎么用门判断两个一位数的大于/等于/小于?
- 多位比较为什么「从最高位比起、不等即定胜负」?怎么级联扩展位宽?
- 无符号比较和有符号(补码)比较在硬件上差在哪?为什么 RTL 里
>会综合出减法器? - 奇偶校验位是怎么用异或算出来的?接收端怎么发现错误?
- 奇偶校验能发现哪些错、为什么发现不了偶数个翻转,它和 CRC、汉明码是什么关系?
一、一位比较器:三个输出
先看最小情况,比较两个 1 位输入 A、B,结果只有三种:A>B、A=B、A<B。直接由 基本门 写出:
| A | B | A>B | A=B | A<B |
|---|---|---|---|---|
| 0 | 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 0 | 0 |
| 1 | 1 | 0 | 1 | 0 |
读出表达式:
- 相等:
A=B当且仅当两者同 0 或同 1,即(A·B) + (Ā·B̄),这正是同或(XNOR),记作A ⊙ B; - 大于:只有 A=1、B=0,
A>B = A·B̄; - 小于:只有 A=0、B=1,
A<B = Ā·B。
三者在任何输入下恰好一个为 1(互斥且完备),这个性质在多位级联时反复用到。
二、多位比较:从最高位逐位裁决
两个 n 位数 A、B 谁大,规则和人看十进制数完全一样:从最高位比起。最高位若不等,大小立刻确定,低位再大也翻不了盘(高位权重碾压一切低位之和);最高位相等,才退而比较次高位;如此逐位下降,任一位分出胜负即结束,全部相等才是 A=B。
以 4 位 A=A3A2A1A0、B=B3B2B1B0(A3 是最高位)为例,写出「A>B」的判据:
A>B = (A3>B3)
+ (A3=B3)·(A2>B2)
+ (A3=B3)·(A2=B2)·(A1>B1)
+ (A3=B3)·(A2=B2)·(A1=B1)·(A0>B0)读法很直白:要么最高位就 A 大;要么最高位相等且次高位 A 大;要么高两位都相等、第三位 A 大……每一项都要求「更高的所有位全部相等」作为前缀条件。A<B 对称,A=B 则要求每一位都相等,把四个同或相与即可:
A=B = (A3⊙B3)·(A2⊙B2)·(A1⊙B1)·(A0⊙B0)这是一种先行(并行)实现,速度快但高位宽时项数膨胀。更省器件的做法是逐位级联:给一位比较器增加三个级联输入(来自更高一位已经裁决出的 gt_in/eq_in/lt_in),从最高位向最低位像 行波进位加法器 一样把胜负关系传下去。商用的 74x85 四位比较器就是这种带级联端口的器件,多片首尾相接可比任意位宽,代价是比较结果要等「裁决波」从头传到尾,位宽越大越慢。工程上还会折中:把数分成若干组,组内先行、组间超前进位式地并行裁决,思想和超前进位加法器(CLA)如出一辙。
三、相等比较、无符号与有符号,RTL 里到底综合成什么
几种比较在硬件里的长相差别值得建立直觉:
| RTL 写法 | 综合出的结构 | 说明 |
|---|---|---|
a == b | n 个 XNOR + 一个多输入与(归约与) | 每位相等、再全相等;地址译码、寄存器表匹配到处都是 |
无符号 a > b | 减法器 a − b,看借位/零标志 | 够减则 a≥b;不产生借位即 a≥b |
有符号 a > b(补码) | 减法器 + 符号位、溢出与零标志联合判断 | 不能只看差的符号位,溢出时符号会反转 |
为什么比较常落到减法器上?因为 A − B 的结果符号和标志位一次性回答了三个问题:结果为 0 → 相等;无符号时无借位 → A≥B;有符号时要结合「差的符号 ⊕ 溢出标志 V」判断正负(溢出发生时符号位不可信),再配合零标志区分大于与等于。所以 ALU 里做比较并不需要专门一套电路,复用 加法器与补码减法、再补几个标志判断即可。
一个 RTL 细节:有符号比较必须保证两边位宽和 signed 语义一致。同样的位向量按无符号和按补码解释,大小关系可能完全颠倒(1111 无符号是 15 最大,补码却是 −1 最小)。写错 signed/unsigned,比较结果在「最高位为 1」的那些数据上整体翻车,且仿真不报错——这类问题在 定点数基础 里尤其常见。
四、奇偶校验:用一棵异或树算一个「指纹位」
转到第二个主题。一串 bit 在传输或存储中可能因干扰、单粒子翻转而某位变反。最简单的检错码是奇偶校验(parity check):在数据位之外额外附 1 个校验位,让「整组(数据位 + 校验位)中 1 的个数」凑成约定的奇数(奇校验 odd)或偶数(偶校验 even)。
这个校验位怎么算?回忆异或的性质:x ⊕ x = 0、x ⊕ 0 = x,把一个字的所有位连续异或(异或归约),结果正好等于「1 的个数是奇数还是偶数」——1 的个数为奇数结果是 1,偶数结果是 0。于是:
- 偶校验位
P = D3 ⊕ D2 ⊕ D1 ⊕ D0(使总 1 数为偶); - 奇校验位再整体取反即可。
多级异或门搭成**异或树(parity tree)**就能对任意位宽求奇偶:
检测时,接收端把收到的数据位重新异或一遍,再和收到的校验位异或:总结果(叫校验子 syndrome)为 0 表示「奇偶性没被破坏」,为 1 表示「一定有奇数个 bit 翻转了」。UART 串口的奇偶校验帧、老式总线的 parity、内存里的奇偶保护,都是这个套路。
五、奇偶校验的能力边界:能检什么、不能检什么
必须诚实地说清点破它的边界,否则会误以为加了校验就高枕无忧:
- 能发现奇数个 bit 翻转(1、3、5…个),因为奇数次翻转改变整组 1 个数的奇偶性;
- 发现不了偶数个 bit 翻转(2、4…个),偶数次翻转后奇偶性又绕回来了,校验子仍是 0;
- 只能检错、不能纠错:就算发现错了,也不知道是哪一位翻的,无法自动改正——通常只能要求重传(如 UART 丢帧)或标记数据无效;
- 连「到底错了几位」都区分不了,只知道奇偶性对不对。
因为这些局限,奇偶校验只用在「出错概率低、偶发多位错可接受、可重传」的场合。要求更高时换更强的码:
| 机制 | 检错 | 纠错 | 典型场景 |
|---|---|---|---|
| 奇偶校验 | 奇数个 bit 错 | 不能 | UART、简单总线、字节级保护 |
| CRC(循环冗余校验) | 突发性多位错,检错能力很强 | 不能 | 网络包、存储块、数据链路 |
| 汉明码 / ECC | 多位 | 单 bit 纠错、双 bit 检错(SEC-DED) | SRAM、DDR、片上存储 |
汉明码可以理解成「多个巧妙排列的奇偶校验」,每一位被若干个校验位交叉监视,根据哪些校验报警就能反推出是哪一位出错并翻转纠正——这正是内存 ECC(Error-Correcting Code,纠错码)的基础。理解了单棵异或树的奇偶校验,再看汉明码只是把树按矩阵排开;理解了「校验位是数据的函数、出错会让函数对不上」,再看 CRC 的多项式除法也不会觉得神秘。这一篇只需牢牢记住校验的第一性原理:发送端按数据算出冗余、接收端重算比对,对不上就说明中间被动过,至于用多强的码,是按出错模式和代价选的工程权衡。
与现有篇目的衔接
- 前置:逻辑门与晶体管(异或/同或)、加法器与算术电路(减法器与补码)
- 应用:寄存器表与地址解码(相等比较)、片上存储器(ECC)
- 有符号/无符号的坑:FPGA 定点数基础
- 更强检错:CRC 在数据链路与存储协议中展开,属后续协议/存储专题
总结
一句话总结:数值比较器从一位单元起步——相等就是同或 XNOR、大于为 A·B̄、小于为 Ā·B,三者互斥且完备;多位比较遵循「从最高位比起、不等即定胜负、相等才看下一位」,可写成高位相等作前缀的先行式,也可用带级联端口的比较芯片像行波进位那样逐位裁决、用面积换位宽;RTL 中相等比较综合为一串 XNOR 归约与,而大小比较常复用减法器,无符号看借位/零标志、有符号补码则必须结合差的符号位、溢出标志和零标志联合判断且要写对 signed 语义;奇偶校验则用一棵异或树把数据各位归约成 1 个校验位(偶校验为各位异或、奇校验再取反),接收端重算并与校验位异或得校验子,非 0 即检出奇数个 bit 翻转;它结构极简但发现不了偶数个错、只能检错不能纠错,要求高时换 CRC(强检错、不纠错)或汉明/ECC(可单 bit 纠错、双 bit 检错),而所有检错码共享同一个第一性原理——发送端按数据算冗余、接收端重算比对,对不上即知数据在中途被改变。