LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

Hamming Code

1 汉明码概要

汉明码的位宽和校验位组合是根据汉明码的设计原则来确定的,这些组合满足特定的数学关系,以确保能够检测并纠正单个位错误。

1.1 汉明码校验位宽和数据位宽关系

汉明不等式如下所示: \(2^k - 1 \geq n + k\)

  • n是数据位的数量。
  • k是校验位的数量。

不同校验位能够校验的数据位宽对应表如下:

 k  n
3 n=1
2 ≤ n ≤ 4
5 ≤ n ≤ 11
 12 ≤ n ≤ 26
 27 ≤ n ≤ 57
 58 ≤ n ≤ 120
 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);
}

 

posted on 2024-11-17 23:59  ArnoldLu  阅读(34)  评论(0编辑  收藏  举报

导航