// Copyright 2020 Intel Corporation. // // This software and the related documents are Intel copyrighted materials, // and your use of them is governed by the express license under which they // were provided to you ("License"). Unless the License provides otherwise, // you may not use, modify, copy, publish, distribute, disclose or transmit // this software or the related documents without Intel's prior written // permission. // // This software and the related documents are provided as is, with no express // or implied warranties, other than those that are expressly stated in the // License. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // ACL ECC DECODER // // This module decodes data using a single error correct, double error detect Hamming code. As the data width get large, // so will the xor network and that would limit fmax. To resolve this, we slice the data into smaller groups and decode // each independently. Essentially we trade off more memory overhead for parity bits in order to limit the fmax // degradation due to ECC. // // The user must specify the data width and the slicing size. From this, one can compute the number of parity bits and // total encoded bits (see the calculations in localparams below). // // Error reporting: for each decoder (after slicing), there are 2 status signals: single error corrected, and double // error detected. Each of these signal types are OR-ed together from all of the decoders (from slicing) before being // reported to the outside world. Beware that if there are two bit errors but they are in separate slicing groups, two // independent decoders can correct one bit each, so this will be reported as single error corrected. // // Reset: there is no reset. Pipeline stages are purely feed-forward, the intent is that reset will propagate through. // // This module is actually a wrapper around the actual ECC implementation in secded_decoder. Here is the architecture. // For example, suppose DATA_WIDTH is 70 and ECC_GROUP_SIZE is 32, then we will slice input data into 32 + 32 + 6, and // 3 encoders are used to produce 39 + 39 + 11 encoded bits. // // i_encoded[88:0] // | // +------------------------------------------------------------------------+ // | optional input pipeline stages | // +------------------------------------------------------------------------+ // | | | // encoded[88:78] encoded[77:39] encoded[38:0] // | | | // +----------------+ +----------------+ +----------------+ // | secded_decoder | | secded_decoder | | secded_decoder | // +----------------+ +----------------+ +----------------+ // | | | // data[69:64] data[63:32] data[31:0] // | | | // +------------------------------------------------------------------------+ // | optional output pipeline stages | // +------------------------------------------------------------------------+ // | // o_data[69:0] // // Everything decoder related is contained within this file. The related file that does the corresponding encoding is // dla_acl_ecc_encoder.sv. Note both encoder and decoder require dla_acl_ecc_pkg.sv. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// `default_nettype none //BEWARE: do not leave the "clock_enable" input port disconnected if any pipeline stages are used, it will default to 0 and nothing will go through module dla_acl_ecc_decoder import dla_acl_ecc_pkg::*; #( parameter int DATA_WIDTH, //number of bits in the decoded output data parameter int ECC_GROUP_SIZE, //how many bits of unencoded data to group into one ecc block, see description in header comments parameter int INPUT_PIPELINE_STAGES = 0, //number of pipeline stages between i_encoded and the ecc decoder parameter int OUTPUT_PIPELINE_STAGES = 0, //number of pipeline stages between the ecc decoder and o_data parameter int STATUS_PIPELINE_STAGES = 0 //number of pipeline stages between the ecc decoder and o_single_error_corrected/o_double_error_detected ) ( input wire clock, //clock is only needed if pipeline stages are nonzero input wire clock_enable, //set to 1 to sample i_encoded, intended for integration with altera_syncram, only needed if pipeline stages are nonzero input wire [getEncodedBitsEccGroup(DATA_WIDTH,ECC_GROUP_SIZE)-1:0] i_encoded, //encoded input data output logic [DATA_WIDTH-1:0] o_data, //decoded output data output logic o_single_error_corrected, //at least one ecc decoder corrected a single bit error within their ecc group output logic o_double_error_detected //at least one ecc decoder detected a double bit error within their ecc group ); //helper functions for determining number of bits are defined in dla_acl_ecc.svh localparam int ECC_NUM_GROUPS = getNumGroups(DATA_WIDTH,ECC_GROUP_SIZE); //how many groups to slice the data into localparam int LAST_GROUP_SIZE = getLastGroupSize(DATA_WIDTH,ECC_GROUP_SIZE); //all groups have size ECC_GROUP_SIZE except possibly the last group which may be smaller since it gets the remaining bits localparam int ENCODED_BITS = getEncodedBitsEccGroup(DATA_WIDTH,ECC_GROUP_SIZE); //internal signals genvar g; logic [ENCODED_BITS-1:0] encoded; logic [DATA_WIDTH-1:0] data; logic [2*ECC_NUM_GROUPS-1:0] error_status; logic [ECC_NUM_GROUPS-1:0] single_error_corrected; logic [ECC_NUM_GROUPS-1:0] double_error_detected; //input pipeline stages generate if (INPUT_PIPELINE_STAGES == 0) begin assign encoded = i_encoded; end else begin logic [ENCODED_BITS-1:0] encoded_pipe [INPUT_PIPELINE_STAGES-1:0]; always_ff @(posedge clock) begin //only the first pipeline stage needs a clock enable, the remaining pipeline stages will load the same data when the clock enable propagates there if (clock_enable) encoded_pipe[0] <= i_encoded; end for (g=1; g