汉明码与 ECC:定位并纠正出错的那一位
更新时间:2026-09-12。本文是「集成电路大类 · 芯片设计」进阶层(intermediate)数字逻辑第四十一篇。数值比较器与奇偶校验里单棵异或树只能喊「出错了」,这一篇讲怎么进一步说出是哪一位错并自动翻回来——汉明码,它是 SRAM/DDR/Cache ECC 的基石。
本文要回答的问题
- 加几个校验位、怎么排列,才能从「报警组合」反推出出错位编号?
- 为什么校验子 syndrome 的数值正好等于出错位位置?
- SEC(单纠)和 SEC-DED(单纠双检)差在哪?为什么还要一个总奇偶位?
- 编码、检错、纠错在读写路径上各是什么电路?代价多大?
- 汉明码管不了哪些错?BCH、Reed-Solomon 能力强在哪?
一、核心思想:让每个校验位交叉「看」一片位
简单奇偶只有 1 个校验位,报警只能回答「有没有错」(1 bit 信息)。要在 k 个数据位里指出「第几位错」,答案要能区分 k+1 种情况(没错 / 错在第 1..k 位),因此需要约 ⌈log₂(k+1)⌉ bit 的报警信息。汉明码设 r 个校验位,让 2^r ≥ k + r + 1(含校验位自己也可能错)。
排法的关键约定:
- 校验位放在编号为 2 的幂的位置:P1 在位 1、P2 在位 2、P4 在位 4、P8 在位 8……(位置从 1 起);
- 每个校验位 P(2ⁱ) 覆盖「位置编号的二进制里第 i 位为 1」的所有位(含它自己);
- 于是位置 3(二进制 011)被 P1、P2 一起覆盖,位置 5(101)被 P1、P4 覆盖,依此类推。
二、校验子为什么直接等于出错位号
发送时按覆盖关系让每组奇偶为偶。接收端重算每组奇偶,r 个结果组成一个 r 位二进制数 syndrome。若第 j 位翻转,那么恰好覆盖 j 的那些校验会报警——而「哪些校验覆盖 j」正由 j 的二进制编码决定,所以报警组合拼出来的二进制数就是 j。syndrome=0 表示无错,非 0 直接指出位置,把该位取反即纠正。
以 4 数据位 + 3 校验位(Hamming(7,4))为例,排布为:
| 位置 | 1(P1) | 2(P2) | 3(D1) | 4(P4) | 5(D2) | 6(D3) | 7(D4) |
|---|---|---|---|---|---|---|---|
| 谁覆盖 | P1 | P2 | P1,P2 | P4 | P1,P4 | P2,P4 | P1,P2,P4 |
若 D2(位置 5)翻转,报警的是 P1、P4,syndrome=101=5,正好定位到第 5 位。
编码与校验子都是异或网络:
// Hamming(7,4) 编码:数据放 3,5,6,7,校验放 1,2,4(位置从 1 起)
p1 = d1 ^ d2 ^ d4; // 覆盖位置 3,5,7
p2 = d1 ^ d3 ^ d4; // 覆盖位置 3,6,7
p4 = d2 ^ d3 ^ d4; // 覆盖位置 5,6,7
// 接收端重算,syndrome 非零即为出错位置,对该位取反
syndrome = {s4, s2, s1};
if (syndrome != 0) code[syndrome-1] ^= 1'b1;三、SEC-DED:再加一位,单 bit 纠正 + 双 bit 检错
普通汉明码有个漏洞:若同时翻 2 bit,syndrome 非零并会「纠正」到一个错误位置(越纠越错)。加一个覆盖整个码字的总体奇偶位 P0 即可区分:
- 无错:syndrome=0 且总体奇偶正确;
- 单 bit 错:syndrome≠0 且 总体奇偶报错——按 syndrome 纠正;
- 双 bit 错:syndrome≠0 但 总体奇偶正确(翻 2 位不改变总奇偶)——知道出错但无法定位,报不可纠正错误(DUE)。
这就是存储 ECC 最常见的 SEC-DED(64 位数据通常配 8 位 ECC)。它把最频发的单粒子单 bit 翻转自动修正、双 bit 至少能报警,是 Cache/DDR 可靠性的底线。
四、代价、能力阶梯与存储工程组织
- 码率/开销:r≈⌈log₂k⌉ 个校验位,数据越宽开销比例越小;代价是写路径上的异或树编码延迟、读路径上「算校验子+定位+条件翻转」的读出延迟,以及额外存储位。
- 更强的码:汉明只保证单纠双检;BCH 可设计成纠多 bit(t-bit correction),用于 NAND Flash;Reed-Solomon 对突发连续位错误强,用于光存储/通信;它们共享「校验矩阵 H、校验子定位」的线性码框架,只是码字在 GF(2ᵐ) 上构造。纯检多 bit 突发的轻量选择是 CRC。
- 存储侧组织:ECC 通常按可寻址字(如 64+8)独立编解码,写时生成、读时校验;配合 scrubbing(后台定期读出-纠正-写回)把潜伏单错在下一次访问前清掉,避免两个单错累积成不可纠的双错。多 bit 错误上报中断/RAS 机制。
与现有篇目的衔接
- 前置:数值比较器与奇偶校验(异或树/检错边界)
- 配套:CRC 与 LFSR(强突发检错)、SRAM 单元
- 应用:片上存储器、Cache/DDR 可靠性、DFT
总结
一句话总结:汉明码把校验位放在 2 的幂位置(P1/P2/P4…),每个校验位覆盖「位置编号二进制对应位为 1」的全部位,使校验位数量满足 2^r ≥ k+r+1;接收端重算各组奇偶得到 syndrome,其非零二进制值恰好等于出错位编号,从而定位并取反纠正(SEC),编码和校验都是异或树;再加一个覆盖全字的总体奇偶位即可区分单错(syndrome 非零且总奇偶错,可纠)与双错(syndrome 非零但总奇偶对,只报不可纠),构成 SEC-DED,是 SRAM/DDR/Cache 的标准配置;代价是 log 级校验位和读写路径的异或/定位延迟,更强需求用 BCH(纠多位)、Reed-Solomon(抗突发),纯检多位突发用 CRC,存储侧再配合按字 ECC 与后台 scrubbing 防止单错累积成双错。