Hamming Code
1 汉明码概要
汉明码的位宽和校验位组合是根据汉明码的设计原则来确定的,这些组合满足特定的数学关系,以确保能够检测并纠正单个位错误。
1.1 汉明码校验位宽和数据位宽关系
汉明不等式如下所示: \(2^k - 1 \geq n + k\)。
- n是数据位的数量。
- k是校验位的数量。
不同校验位能够校验的数据位宽对应表如下:
k | n |
3 | n=1 |
4 | 2 ≤ n ≤ 4 |
5 | 5 ≤ n ≤ 11 |
6 | 12 ≤ n ≤ 26 |
7 | 27 ≤ n ≤ 57 |
8 | 58 ≤ n ≤ 120 |
9 | 121 ≤ n ≤ 247 |
10 | 248 ≤ n ≤ 502 |
11 | 503 ≤ n ≤ 1013 |
12 | 1014 ≤ n ≤ 2036 |
13 | 2037 ≤ n ≤ 4083 |
14 | 4084 ≤ n ≤ 8178 |
1.2 根据数据位宽选择校验位
如果要对一个ROW单元为32位的eFuse使用Hamming Code进行校验,如何选择k呢?
- k必须大于等于7。
- k=7,n=32时,校验代价为7/32=21.9%。
- k=8,n=64时,校验代价为8/64=12.5%。
- k=8,n=96时,校验代价为8/96=8.3%。
- k=9,n=128时,校验代价为9/128=7.0%。
- k=9,n=160时,校验代价为9/160=5.6%。
- k=14,n=8160,校验代价为14/8160=0.2%。
当k越高,可以获得更低的校验代价。但是丧失了写的灵活性,n+k位必须一次性写入。
结合校验开销和灵活性选择k=8,一次写入64bit数据,和对应8bit校验位。所以Hamming Code(72, 64)是最优解。
1.3 汉明码计算和纠错、错误检测
汉明码(Hamming Code)是一种线性错误检测和纠正码,它通过在数据位中插入校验位来实现错误检测和纠正。汉明码的编码规则基于以下几个原则:
1. 校验位的位置:
校验位被放置在2的幂次方的位置,即第1位、第2位、第4位、第8位等。这些位置的索引从1开始计算。
2. 校验位的计算:
每个校验位负责一组特定的数据位,这组数据位的索引是2的幂次方减1的倍数。例如,第一个校验位(P1)负责第1、3、5、7...位,第二个校验位(P2)负责第2、3、6、7...位,以此类推。
3. 校验位的值:
每个校验位的值是通过计算其所覆盖的数据位的异或(XOR)得到的。如果覆盖的数据位中1的个数为奇数,则校验位设为1;如果为偶数,则校验位设为0。
4. 编码过程:
- 首先,确定需要的校验位数(k),使得 \(2^k - 1 \geq n + k\),其中n是数据位数。
- 然后,将数据位填充到非校验位的位置。
- 接着,计算每个校验位的值,并将其放置在校验位的位置。
5. 错误检测和纠正:
- 在接收端,通过重新计算校验位并比较接收到的校验位值来检测错误。
- 如果发现错误,可以通过Syndrome来确定错误位的位置,并进行纠正。
6. Syndrome的计算:
Syndrome是通过将接收到的编码与校验矩阵的转置进行模2运算得到的。如果Syndrome非零,则表示有错误发生,且Syndrome值对应于错误位的位置。
7. 错误位置的确定:
- 将接收到的编码与校验矩阵相乘,得到Syndrome向量。
- Syndrome向量中的每一位表示一个校验位,如果该位为1,则表示对应的校验位检测到错误。
- Syndrome向量实际上是错误位位置的二进制表示。
通过遵循这些规则,汉明码能够有效地检测和纠正单个位错误,并检测双位错误。这些规则确保了汉明码的可靠性和有效性。
2 汉明码在eFuse中应用
为了增强eFuse中内容正确性,增加Hamming Code模块,对eFuse中内容进行1bit错误纠正,2bit及以上错误报错功能。
3 软件生成Hamming Code(72, 64)
Hamming Code(72, 64)生成如下:
#include <stdio.h> typedef unsigned char uint8; struct DATA_IN { uint8 data_00:1; uint8 data_01:1; uint8 data_02:1; uint8 data_03:1; uint8 data_04:1; uint8 data_05:1; uint8 data_06:1; uint8 data_07:1; uint8 data_08:1; uint8 data_09:1; uint8 data_10:1; uint8 data_11:1; uint8 data_12:1; uint8 data_13:1; uint8 data_14:1; uint8 data_15:1; uint8 data_16:1; uint8 data_17:1; uint8 data_18:1; uint8 data_19:1; uint8 data_20:1; uint8 data_21:1; uint8 data_22:1; uint8 data_23:1; uint8 data_24:1; uint8 data_25:1; uint8 data_26:1; uint8 data_27:1; uint8 data_28:1; uint8 data_29:1; uint8 data_30:1; uint8 data_31:1; uint8 data_32:1; uint8 data_33:1; uint8 data_34:1; uint8 data_35:1; uint8 data_36:1; uint8 data_37:1; uint8 data_38:1; uint8 data_39:1; uint8 data_40:1; uint8 data_41:1; uint8 data_42:1; uint8 data_43:1; uint8 data_44:1; uint8 data_45:1; uint8 data_46:1; uint8 data_47:1; uint8 data_48:1; uint8 data_49:1; uint8 data_50:1; uint8 data_51:1; uint8 data_52:1; uint8 data_53:1; uint8 data_54:1; uint8 data_55:1; uint8 data_56:1; uint8 data_57:1; uint8 data_58:1; uint8 data_59:1; uint8 data_60:1; uint8 data_61:1; uint8 data_62:1; uint8 data_63:1; }; union DATA_IN_UNION { struct DATA_IN data_in; long unsigned int data_in_long; }; struct DATA_IN_ECC { uint8 data_00:1; uint8 data_01:1; uint8 data_02:1; uint8 data_03:1; uint8 data_04:1; uint8 data_05:1; uint8 data_06:1; uint8 data_07:1; uint8 data_08:1; uint8 data_09:1; uint8 data_10:1; uint8 data_11:1; uint8 data_12:1; uint8 data_13:1; uint8 data_14:1; uint8 data_15:1; uint8 data_16:1; uint8 data_17:1; uint8 data_18:1; uint8 data_19:1; uint8 data_20:1; uint8 data_21:1; uint8 data_22:1; uint8 data_23:1; uint8 data_24:1; uint8 data_25:1; uint8 data_26:1; uint8 data_27:1; uint8 data_28:1; uint8 data_29:1; uint8 data_30:1; uint8 data_31:1; uint8 data_32:1; uint8 data_33:1; uint8 data_34:1; uint8 data_35:1; uint8 data_36:1; uint8 data_37:1; uint8 data_38:1; uint8 data_39:1; uint8 data_40:1; uint8 data_41:1; uint8 data_42:1; uint8 data_43:1; uint8 data_44:1; uint8 data_45:1; uint8 data_46:1; uint8 data_47:1; uint8 data_48:1; uint8 data_49:1; uint8 data_50:1; uint8 data_51:1; uint8 data_52:1; uint8 data_53:1; uint8 data_54:1; uint8 data_55:1; uint8 data_56:1; uint8 data_57:1; uint8 data_58:1; uint8 data_59:1; uint8 data_60:1; uint8 data_61:1; uint8 data_62:1; uint8 data_63:1; uint8 data_64:1; uint8 data_65:1; uint8 data_66:1; uint8 data_67:1; uint8 data_68:1; uint8 data_69:1; uint8 data_70:1; uint8 data_71:1; }; struct ECC_VAL { uint8 ecc0:1; uint8 ecc1:1; uint8 ecc2:1; uint8 ecc3:1; uint8 ecc4:1; uint8 ecc5:1; uint8 ecc6:1; uint8 ecc7:1; }; void hamming_cal(long unsigned int data_in_long) { union DATA_IN_UNION data_in_union; data_in_union.data_in_long = data_in_long; struct DATA_IN_ECC data_in_ecc = {0}; char col1, col2, col3, col4, col5, col6, col7, row1, row2, row3, row4, row5, row6, row7, row8; struct ECC_VAL ecc_val; data_in_ecc.data_03 = data_in_union.data_in.data_00; data_in_ecc.data_05 = data_in_union.data_in.data_01; data_in_ecc.data_06 = data_in_union.data_in.data_02; data_in_ecc.data_07 = data_in_union.data_in.data_03; data_in_ecc.data_09 = data_in_union.data_in.data_04; data_in_ecc.data_10 = data_in_union.data_in.data_05; data_in_ecc.data_11 = data_in_union.data_in.data_06; data_in_ecc.data_12 = data_in_union.data_in.data_07; data_in_ecc.data_13 = data_in_union.data_in.data_08; data_in_ecc.data_14 = data_in_union.data_in.data_09; data_in_ecc.data_15 = data_in_union.data_in.data_10; data_in_ecc.data_17 = data_in_union.data_in.data_11; data_in_ecc.data_18 = data_in_union.data_in.data_12; data_in_ecc.data_19 = data_in_union.data_in.data_13; data_in_ecc.data_20 = data_in_union.data_in.data_14; data_in_ecc.data_21 = data_in_union.data_in.data_15; data_in_ecc.data_22 = data_in_union.data_in.data_16; data_in_ecc.data_23 = data_in_union.data_in.data_17; data_in_ecc.data_24 = data_in_union.data_in.data_18; data_in_ecc.data_25 = data_in_union.data_in.data_19; data_in_ecc.data_26 = data_in_union.data_in.data_20; data_in_ecc.data_27 = data_in_union.data_in.data_21; data_in_ecc.data_28 = data_in_union.data_in.data_22; data_in_ecc.data_29 = data_in_union.data_in.data_23; data_in_ecc.data_30 = data_in_union.data_in.data_24; data_in_ecc.data_31 = data_in_union.data_in.data_25; data_in_ecc.data_33 = data_in_union.data_in.data_26; data_in_ecc.data_34 = data_in_union.data_in.data_27; data_in_ecc.data_35 = data_in_union.data_in.data_28; data_in_ecc.data_36 = data_in_union.data_in.data_29; data_in_ecc.data_37 = data_in_union.data_in.data_30; data_in_ecc.data_38 = data_in_union.data_in.data_31; data_in_ecc.data_39 = data_in_union.data_in.data_32; data_in_ecc.data_40 = data_in_union.data_in.data_33; data_in_ecc.data_41 = data_in_union.data_in.data_34; data_in_ecc.data_42 = data_in_union.data_in.data_35; data_in_ecc.data_43 = data_in_union.data_in.data_36; data_in_ecc.data_44 = data_in_union.data_in.data_37; data_in_ecc.data_45 = data_in_union.data_in.data_38; data_in_ecc.data_46 = data_in_union.data_in.data_39; data_in_ecc.data_47 = data_in_union.data_in.data_40; data_in_ecc.data_48 = data_in_union.data_in.data_41; data_in_ecc.data_49 = data_in_union.data_in.data_42; data_in_ecc.data_50 = data_in_union.data_in.data_43; data_in_ecc.data_51 = data_in_union.data_in.data_44; data_in_ecc.data_52 = data_in_union.data_in.data_45; data_in_ecc.data_53 = data_in_union.data_in.data_46; data_in_ecc.data_54 = data_in_union.data_in.data_47; data_in_ecc.data_55 = data_in_union.data_in.data_48; data_in_ecc.data_56 = data_in_union.data_in.data_49; data_in_ecc.data_57 = data_in_union.data_in.data_50; data_in_ecc.data_58 = data_in_union.data_in.data_51; data_in_ecc.data_59 = data_in_union.data_in.data_52; data_in_ecc.data_60 = data_in_union.data_in.data_53; data_in_ecc.data_61 = data_in_union.data_in.data_54; data_in_ecc.data_62 = data_in_union.data_in.data_55; data_in_ecc.data_63 = data_in_union.data_in.data_56; data_in_ecc.data_65 = data_in_union.data_in.data_57; data_in_ecc.data_66 = data_in_union.data_in.data_58; data_in_ecc.data_67 = data_in_union.data_in.data_59; data_in_ecc.data_68 = data_in_union.data_in.data_60; data_in_ecc.data_69 = data_in_union.data_in.data_61; data_in_ecc.data_70 = data_in_union.data_in.data_62; data_in_ecc.data_71 = data_in_union.data_in.data_63; col1 = data_in_ecc.data_01\ ^data_in_ecc.data_09\ ^data_in_ecc.data_17\ ^data_in_ecc.data_25\ ^data_in_ecc.data_33\ ^data_in_ecc.data_41\ ^data_in_ecc.data_49\ ^data_in_ecc.data_57\ ^data_in_ecc.data_65; col2 = data_in_ecc.data_02\ ^data_in_ecc.data_10\ ^data_in_ecc.data_18\ ^data_in_ecc.data_26\ ^data_in_ecc.data_34\ ^data_in_ecc.data_42\ ^data_in_ecc.data_50\ ^data_in_ecc.data_58\ ^data_in_ecc.data_66; col3 = data_in_ecc.data_03\ ^data_in_ecc.data_11\ ^data_in_ecc.data_19\ ^data_in_ecc.data_27\ ^data_in_ecc.data_35\ ^data_in_ecc.data_43\ ^data_in_ecc.data_51\ ^data_in_ecc.data_59\ ^data_in_ecc.data_67; col4 = data_in_ecc.data_04\ ^data_in_ecc.data_12\ ^data_in_ecc.data_20\ ^data_in_ecc.data_28\ ^data_in_ecc.data_36\ ^data_in_ecc.data_44\ ^data_in_ecc.data_52\ ^data_in_ecc.data_60\ ^data_in_ecc.data_68; col5 = data_in_ecc.data_05\ ^data_in_ecc.data_13\ ^data_in_ecc.data_21\ ^data_in_ecc.data_29\ ^data_in_ecc.data_37\ ^data_in_ecc.data_45\ ^data_in_ecc.data_53\ ^data_in_ecc.data_61\ ^data_in_ecc.data_69; col6 = data_in_ecc.data_06\ ^data_in_ecc.data_14\ ^data_in_ecc.data_22\ ^data_in_ecc.data_30\ ^data_in_ecc.data_38\ ^data_in_ecc.data_46\ ^data_in_ecc.data_54\ ^data_in_ecc.data_62\ ^data_in_ecc.data_70; col7 = data_in_ecc.data_07\ ^data_in_ecc.data_15\ ^data_in_ecc.data_23\ ^data_in_ecc.data_31\ ^data_in_ecc.data_39\ ^data_in_ecc.data_47\ ^data_in_ecc.data_55\ ^data_in_ecc.data_63\ ^data_in_ecc.data_71; row1 = data_in_ecc.data_08\ ^data_in_ecc.data_09\ ^data_in_ecc.data_10\ ^data_in_ecc.data_11\ ^data_in_ecc.data_12\ ^data_in_ecc.data_13\ ^data_in_ecc.data_14\ ^data_in_ecc.data_15; row2 = data_in_ecc.data_16\ ^data_in_ecc.data_17\ ^data_in_ecc.data_18\ ^data_in_ecc.data_19\ ^data_in_ecc.data_20\ ^data_in_ecc.data_21\ ^data_in_ecc.data_22\ ^data_in_ecc.data_23; row3 = data_in_ecc.data_24\ ^data_in_ecc.data_25\ ^data_in_ecc.data_26\ ^data_in_ecc.data_27\ ^data_in_ecc.data_28\ ^data_in_ecc.data_29\ ^data_in_ecc.data_30\ ^data_in_ecc.data_31; row4 = data_in_ecc.data_32\ ^data_in_ecc.data_33\ ^data_in_ecc.data_34\ ^data_in_ecc.data_35\ ^data_in_ecc.data_36\ ^data_in_ecc.data_37\ ^data_in_ecc.data_38\ ^data_in_ecc.data_39; row5 = data_in_ecc.data_40\ ^data_in_ecc.data_41\ ^data_in_ecc.data_42\ ^data_in_ecc.data_43\ ^data_in_ecc.data_44\ ^data_in_ecc.data_45\ ^data_in_ecc.data_46\ ^data_in_ecc.data_47; row6 = data_in_ecc.data_48\ ^data_in_ecc.data_49\ ^data_in_ecc.data_50\ ^data_in_ecc.data_51\ ^data_in_ecc.data_52\ ^data_in_ecc.data_53\ ^data_in_ecc.data_54\ ^data_in_ecc.data_55; row7 = data_in_ecc.data_56\ ^data_in_ecc.data_57\ ^data_in_ecc.data_58\ ^data_in_ecc.data_59\ ^data_in_ecc.data_60\ ^data_in_ecc.data_61\ ^data_in_ecc.data_62\ ^data_in_ecc.data_63; row8 = data_in_ecc.data_64\ ^data_in_ecc.data_65\ ^data_in_ecc.data_66\ ^data_in_ecc.data_67\ ^data_in_ecc.data_68\ ^data_in_ecc.data_69\ ^data_in_ecc.data_70\ ^data_in_ecc.data_71; ecc_val.ecc0 = data_in_ecc.data_01 = col1 ^ col3 ^ col5 ^ col7; ecc_val.ecc1 = data_in_ecc.data_02 = col2 ^ col3 ^ col6 ^ col7; ecc_val.ecc2 = data_in_ecc.data_04 = col4 ^ col5 ^ col6 ^ col7; ecc_val.ecc3 = data_in_ecc.data_08 = row1 ^ row3 ^ row5 ^ row7; ecc_val.ecc4 = data_in_ecc.data_16 = row2 ^ row3 ^ row6 ^ row7; ecc_val.ecc5 = data_in_ecc.data_32 = row4 ^ row5 ^ row6 ^ row7; ecc_val.ecc6 = data_in_ecc.data_64 = row8; ecc_val.ecc7 = data_in_ecc.data_00 = \ data_in_ecc.data_01\ ^data_in_ecc.data_02\ ^data_in_ecc.data_03\ ^data_in_ecc.data_04\ ^data_in_ecc.data_05\ ^data_in_ecc.data_06\ ^data_in_ecc.data_07\ ^data_in_ecc.data_08\ ^data_in_ecc.data_09\ ^data_in_ecc.data_10\ ^data_in_ecc.data_11\ ^data_in_ecc.data_12\ ^data_in_ecc.data_13\ ^data_in_ecc.data_14\ ^data_in_ecc.data_15\ ^data_in_ecc.data_16\ ^data_in_ecc.data_17\ ^data_in_ecc.data_18\ ^data_in_ecc.data_19\ ^data_in_ecc.data_20\ ^data_in_ecc.data_21\ ^data_in_ecc.data_22\ ^data_in_ecc.data_23\ ^data_in_ecc.data_24\ ^data_in_ecc.data_25\ ^data_in_ecc.data_26\ ^data_in_ecc.data_27\ ^data_in_ecc.data_28\ ^data_in_ecc.data_29\ ^data_in_ecc.data_30\ ^data_in_ecc.data_31\ ^data_in_ecc.data_32\ ^data_in_ecc.data_33\ ^data_in_ecc.data_34\ ^data_in_ecc.data_35\ ^data_in_ecc.data_36\ ^data_in_ecc.data_37\ ^data_in_ecc.data_38\ ^data_in_ecc.data_39\ ^data_in_ecc.data_40\ ^data_in_ecc.data_41\ ^data_in_ecc.data_42\ ^data_in_ecc.data_43\ ^data_in_ecc.data_44\ ^data_in_ecc.data_45\ ^data_in_ecc.data_46\ ^data_in_ecc.data_47\ ^data_in_ecc.data_48\ ^data_in_ecc.data_49\ ^data_in_ecc.data_50\ ^data_in_ecc.data_51\ ^data_in_ecc.data_52\ ^data_in_ecc.data_53\ ^data_in_ecc.data_54\ ^data_in_ecc.data_55\ ^data_in_ecc.data_56\ ^data_in_ecc.data_57\ ^data_in_ecc.data_58\ ^data_in_ecc.data_59\ ^data_in_ecc.data_60\ ^data_in_ecc.data_61\ ^data_in_ecc.data_62\ ^data_in_ecc.data_63\ ^data_in_ecc.data_64\ ^data_in_ecc.data_65\ ^data_in_ecc.data_66\ ^data_in_ecc.data_67\ ^data_in_ecc.data_68\ ^data_in_ecc.data_69\ ^data_in_ecc.data_70\ ^data_in_ecc.data_71; printf("Data In:0x%016lx, ECC:0x%02x\n", data_in_union.data_in_long, ecc_val); } void main(void) { hamming_cal(0xec85637d783ae78e); hamming_cal(0x07b93e7aff523216); hamming_cal(0x5da80c14c85e1de6); hamming_cal(0x2e143a22820e3301); }