FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Common CellsのECCデコーダの実装詳細解析:ecc_decodesv の実装詳細

ecc_encode.sv の実装調査を行ったので、今度は ecc_decode.sv の実装調査をしてみる。

基本的には ecc_encode.sv の逆を行っており、問題があればエラーを通知することになる。

module ecc_decode import ecc_pkg::*; #(
  /// Data width of unencoded word.
  parameter  int unsigned DataWidth   = 64,
  // Do not change
  parameter type data_t         = logic [DataWidth-1:0],
  parameter type parity_t       = logic [get_parity_width(DataWidth)-1:0],
  parameter type code_word_t    = logic [get_cw_width(DataWidth)-1:0],
  parameter type encoded_data_t = struct packed {
                                    logic parity;
                                    code_word_t code_word;
                                  }
  ) (
  /// Encoded data in
  input  encoded_data_t data_i,
  /// Corrected data out
  output data_t         data_o,
  /// Error syndrome indicates the erroneous bit position
  output parity_t       syndrome_o,
  /// A single error occurred
  output logic          single_error_o,
  /// Error received in parity bit (MSB)
  output logic          parity_error_o,
  /// A double error occurred
  output logic          double_error_o
);
  • data_i : encoded_data_t エンコード済みのデータが入っている
  • data_o : data_t デコード後の値を出力する
  • syndrome_o : parity_t エラーが発生した場合のビット位置の情報を出力する。
  • single_error_o : 単一ビットエラーが発生した場合にアサートされる
  • parity_error_o : 全体としてパリティエラーが発生した場合にアサートされる
  • double_error_o : 2ビット以上のエラーが発生した場合にアサートされる

実装の詳細についてだが、コード内にコメントがある:

  ///!    | 0  1  2  3  4  5  6  7  8  9 10 11 12  13  14
  ///!    |p1 p2 d1 p4 d2 d3 d4 p8 d5 d6 d7 d8 d9 d10 d11
  ///! ---|----------------------------------------------
  ///! p1 | x     x     x     x     x     x     x       x
  ///! p2 |    x  x        x  x        x  x         x   x
  ///! p4 |          x  x  x  x              x  x   x   x
  ///! p8 |                      x  x  x  x  x  x   x   x

  ///! 1. Parity bit 1 covers all bit positions which have the least significant bit
  ///!    set: bit 1 (the parity bit itself), 3, 5, 7, 9, etc.
  ///! 2. Parity bit 2 covers all bit positions which have the second least
  ///!    significant bit set: bit 2 (the parity bit itself), 3, 6, 7, 10, 11, etc.
  ///! 3. Parity bit 4 covers all bit positions which have the third least
  ///!    significant bit set: bits 4–7, 12–15, 20–23, etc.
  ///! 4. Parity bit 8 covers all bit positions which have the fourth least
  ///!    significant bit set: bits 8–15, 24–31, 40–47, etc.
  ///! 5. In general each parity bit covers all bits where the bitwise AND of the
  ///!    parity position and the bit position is non-zero.
  1. パリティビット1は最下位ビット=1(つまり奇数インデックスのビット)のパリティを含んでいる
  2. パリティビット2は2番目に低いビット=1(つまり、2,3,6,7,10,11…) のパリティを含んでいる
  3. パリティビット4は3番目に低いビット=1(つまり、4-7, 12-15, 20-23, ….) のパリティを含んでいる
  4. パリティビット8は4番目に低いビット=!(つまり、8-15, 24-31, 40-47, … )のパリティを含んでいる

シンドロームの計算

それぞれのパリティを検算するために、各対象となるビットのXORを生成する。

  always_comb begin : calculate_syndrome
    syndrome = 0;
    for (int unsigned i = 0; i < unsigned'($bits(parity_t)); i++) begin
      for (int unsigned j = 0; j < unsigned'($bits(code_word_t)); j++) begin
        if (|(unsigned'(2**i) & (j + 1))) syndrome[i] = syndrome[i] ^ data_i.code_word[j];
      end
    end
  end

すべてのシンドロームがゼロであれば問題ないが、1つでも問題があれば訂正または通知を試みる:

シンドロームが誤っているデータの位置を示しているので、そのビット位置を反転させるということになる。

  assign syndrome_not_zero = |syndrome;

  // correct the data word if the syndrome is non-zero
  always_comb begin
    correct_data = data_i.code_word;
    if (syndrome_not_zero) begin
      correct_data[syndrome - 1] = ~data_i.code_word[syndrome - 1];
    end
  end
  • single bit errorの条件: 全体パリティビットエラー & シンドロームが検出された
  • parity bit errorの条件: 全体パリティビットエラー & シンドロームが検出されない
  • double bit error: 全体パリティビットエラーなし (2ビット反転しているので) & シンドロームが検出された
    • シンドロームだけでは、single error と double error の違いが分からないので、double error では 2ビット反転によりparityビットエラーが発生しないことを理由に、切り分けを行っている。
  ///! Syndrome | Overall Parity (MSB) | Error Type   | Notes
  ///! --------------------------------------------------------
  ///! 0        | 0                    | No Error     |
  ///! /=0      | 1                    | Single Error | Correctable. Syndrome holds incorrect bit position.
  ///! 0        | 1                    | Parity Error | Overall parity, MSB is in error and can be corrected.
  ///! /=0      | 0                    | Double Error | Not correctable.
  assign single_error_o = parity & syndrome_not_zero;
  assign parity_error_o = parity & ~syndrome_not_zero;
  assign double_error_o = ~parity & syndrome_not_zero;

データの抽出

2の累乗のビット位置にはパリティの情報が入っているので、それらを取り除いていく。

  // Extract data vector
  always_comb begin
    automatic int unsigned idx; // bit index
    data_wo_parity = '0;
    idx = 0;

    for (int unsigned i = 1; i < unsigned'($bits(code_word_t)) + 1; i++) begin
      // if i is a power of two we are indexing a parity bit
      if (unsigned'(2**$clog2(i)) != i) begin
        data_wo_parity[idx] = correct_data[i - 1];
        idx++;
      end
    end
  end

  assign data_o = data_wo_parity;