Skip to content

Commit

Permalink
SECDED: Add encoder, decoder and testbench
Browse files Browse the repository at this point in the history
  • Loading branch information
zarubaf committed Apr 15, 2020
1 parent 95da1fb commit 34567e3
Show file tree
Hide file tree
Showing 13 changed files with 548 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ formal/fifo_v3
formal/counter
formal/fall_through_register
*.check
*.vcd
obj_dir/
3 changes: 3 additions & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ sources:
- src/cf_math_pkg.sv
- src/clk_div.sv
- src/delta_counter.sv
- src/ecc_pkg.sv
- src/edge_propagator_tx.sv
- src/exp_backoff.sv
- src/fifo_v3.sv
Expand Down Expand Up @@ -57,6 +58,8 @@ sources:
- src/cdc_fifo_2phase.sv
- src/cdc_fifo_gray.sv
- src/counter.sv
- src/ecc_decode.sv
- src/ecc_encode.sv
- src/edge_detect.sv
- src/id_queue.sv
- src/max_counter.sv
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- stream_fork_dynamic: Wrapper around `stream_fork` for partial forking.
- stream_join: Join multiple Ready/Valid handshakes to one common handshake.
- SECDED (Single Error Correction, Double Error Detection) encoder and decoder
- SECDED Verilator-based testbench

## 1.17.0 - 2020-04-09
### Added
Expand Down
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: Apache-2.0

VERILATOR ?= verilator

all: ecc_encode ecc_decode

ecc_%: test/ecc/ecc_%.cpp test/ecc/ecc.cpp src/ecc_pkg.sv src/ecc_%.sv
$(VERILATOR) --cc $^ --top-module $@ --trace --exe
cd obj_dir && make -f V$@.mk > /dev/zero
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Please note that cells with status *deprecated* are not to be used for new desig
| Name | Description | Status | Superseded By |
| :--------------------------- | :----------------------------------------------------------------------------- | :------------- | :------------ |
| `addr_decode ` | Address map decoder | active | |
| `ecc_decode` | SECDED Decoder (Single Error Correction, Double Error Detection) | active | |
| `ecc_encode` | SECDED Encoder (Single Error Correction, Double Error Detection) | active | |
| `binary_to_gray` | Binary to gray code converter | active | |
| `find_first_one` | Leading-one finder / leading-zero counter | *deprecated* | `lzc` |
| `gray_to_binary` | Gray code to binary converter | active | |
Expand Down
121 changes: 121 additions & 0 deletions src/ecc_decode.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright 2020 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
// Author: Florian Zaruba <[email protected]>
//
// ECC Decoder
//
// Implements SECDED (Single Error Correction, Double Error Detection) Hamming Code
// with extended parity bit [1].
// The module receives a data word including parity bit and decodes it according to the
// number of data and parity bit.
//
// 1. If no error has been detected the syndrome will be zero and all flags will be zero.
// 2. If a single error has been detected, the syndrome is non-zero, and `single-error` will be
// asserted. The output word contains the corrected data.
// 3. If the parity bit contained an error, the module will assert `parity_error_o`.
// 4. In case of a double fault the syndrome is non-zero, `double_error_o` will be asserted.
// All other status flags will be de-asserted.
//
// [1] https://en.wikipedia.org/wiki/Hamming_code

module ecc_decode import ecc_pkg::*; #(
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;
}
) (
input encoded_data_t data_i,
output data_t data_o,
output parity_t syndrome_o, // indicates the erroneous bit position
output logic single_error_o,
output logic parity_error_o, // error received in parity bit (MSB)
output logic double_error_o
);

logic parity;
data_t data_wo_parity;
parity_t syndrome;
logic syndrome_not_zero;
code_word_t correct_data;

// Check parity bit. 0 = parity equal, 1 = different parity
assign parity = data_i.parity ^ (^data_i.code_word);

// | 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.
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

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

// 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;

// 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;

endmodule
75 changes: 75 additions & 0 deletions src/ecc_encode.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2020 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
// Author: Florian Zaruba <[email protected]>
// ECC Encoder
//
// Implements SECDED (Single Error Correction, Double Error Detection) Hamming Code
// with extended parity bit [1].
// The module receives a data word and encodes it using above mentioned error
// detection and correction code. The corresponding decode module
// can be found in `ecc_decode.sv`
//
// [1] https://en.wikipedia.org/wiki/Hamming_code

module ecc_encode import ecc_pkg::*; #(
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;
}
) (
input data_t data_i,
output encoded_data_t data_o
);

parity_t parity_code_word;
code_word_t data, codeword;

// Expand incoming data to codeword width
always_comb begin : expand_data
automatic int unsigned idx;
data = '0;
idx = 0;
for (int unsigned i = 1; i < unsigned'($bits(code_word_t)) + 1; i++) begin
// if it is not a power of two word it is a normal data index
if (unsigned'(2**$clog2(i)) != i) begin
data[i - 1] = data_i[idx];
idx++;
end
end
end

// calculate code word
always_comb begin : calculate_syndrome
parity_code_word = 0;
for (int unsigned i = 0; i < unsigned'($bits(parity_t)); i++) begin
for (int unsigned j = 1; j < unsigned'($bits(code_word_t)) + 1; j++) begin
if (|(unsigned'(2**i) & j)) parity_code_word[i] = parity_code_word[i] ^ data[j - 1];
end
end
end

// fuse the final codeword
always_comb begin : generate_codeword
codeword = data;
for (int unsigned i = 0; i < unsigned'($bits(parity_t)); i++) begin
codeword[2**i-1] = parity_code_word[i];
end
end

assign data_o.code_word = codeword;
assign data_o.parity = ^codeword;

endmodule
31 changes: 31 additions & 0 deletions src/ecc_pkg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2020 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
// Author: Florian Zaruba <[email protected]>
//
// Description: Contains common ECC definitions and helper functions.

package ecc_pkg;

// Calculate required ECC parity width:
function automatic int unsigned get_parity_width (input int unsigned data_width);
// data_width + cw_width + 1 <= 2**cw_width
int unsigned cw_width = 2;
while (unsigned'(2**cw_width) < cw_width + data_width + 1) cw_width++;
return cw_width;
endfunction

// Calculate required ECC codeword width:
function automatic int unsigned get_cw_width (input int unsigned data_width);
// data width + parity width + one additional parity bit (for double error detection)
return data_width + get_parity_width(data_width);
endfunction

endpackage
3 changes: 3 additions & 0 deletions src_files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ common_cells_all:
- src/cf_math_pkg.sv
- src/clk_div.sv
- src/delta_counter.sv
- src/ecc_pkg.sv
- src/edge_propagator_tx.sv
- src/exp_backoff.sv
- src/fifo_v3.sv
Expand Down Expand Up @@ -41,6 +42,8 @@ common_cells_all:
- src/cdc_fifo_2phase.sv
- src/cdc_fifo_gray.sv
- src/counter.sv
- src/ecc_decode.sv
- src/ecc_encode.sv
- src/edge_detect.sv
- src/id_queue.sv
- src/max_counter.sv
Expand Down
Loading

0 comments on commit 34567e3

Please sign in to comment.