Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
5f3bc83bcThis file is pinned to the selected release. Download the original to open it in your design tool.
// 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 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::*; #(
/// 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;
}
) (
/// Unencoded data in
input data_t data_i,
/// Encoded data out
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