forked from pulp-platform/common_cells
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathecc_decode.sv
More file actions
130 lines (118 loc) · 5.46 KB
/
Copy pathecc_decode.sv
File metadata and controls
130 lines (118 loc) · 5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// 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 <zarubaf@iis.ee.ethz.ch>
//
/// # 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_o` 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::*;
#(
/// 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
);
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