// 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. //see dla_hld_ram.sv for a description of the parameters, ports, and general functionality of all the dla_hld_ram layers //this layer is adds error correction codes, specifically single error correct double error detect hamming codes `default_nettype none `include "dla_acl_parameter_assert.svh" module dla_hld_ram_ecc import dla_acl_ecc_pkg::*; #( //geometry configuration parameter int DEPTH, parameter int WIDTH, parameter int BE_WIDTH, //geometry constants parameter bit MINIMIZE_MEMORY_USAGE, parameter int MIN_PHYSICAL_DEPTH, //memory initialization parameter bit USE_MEM_INIT_FILE, parameter bit ZERO_INITIALIZE_MEM, parameter MEM_INIT_NAME, //error correction codes -- these parameters are consumed at this layer, layers below do not have them parameter bit ENABLE_ECC, parameter bit ECC_STATUS_TIME_STRETCH, parameter bit ASYNC_RESET, parameter bit SYNCHRONIZE_RESET, //memory configuration parameter RAM_BLOCK_TYPE, parameter RAM_OPERATION_MODE, parameter DEVICE_FAMILY, parameter READ_DURING_WRITE, parameter bit REGISTER_A_READDATA, parameter bit REGISTER_B_ADDRESS, parameter bit REGISTER_B_READDATA, //try to use memory hardened logic parameter bit USE_ENABLE, parameter bit COMMON_IN_CLOCK_EN, parameter bit COMMON_OUT_CLOCK_EN, //derived parameters localparam int ADDR = $clog2(DEPTH) ) ( input wire clock, //port a input wire [ADDR-1:0] a_address, input wire a_write, input wire [WIDTH-1:0] a_writedata, input wire [BE_WIDTH-1:0] a_byteenable, output logic [WIDTH-1:0] a_readdata, input wire a_in_clock_en, input wire a_out_clock_en, input wire a_read_enable, //port b input wire [ADDR-1:0] b_address, input wire b_write, input wire [WIDTH-1:0] b_writedata, input wire [BE_WIDTH-1:0] b_byteenable, output logic [WIDTH-1:0] b_readdata, input wire b_in_clock_en, input wire b_out_clock_en, input wire b_read_enable, //error correction code -- these signals are consumed at this layer, layers below do not have them input wire resetn, output logic [1:0] ecc_err_status ); /////////////////////// // Legality checks // /////////////////////// generate //width / be_width must divide evenly with no remainder `DLA_ACL_PARAMETER_ASSERT(WIDTH % BE_WIDTH == 0) endgenerate ////////////////////////// // Derived parameters // ////////////////////////// //note: the max group size of 32 has been deliberately chosen, after encoding this expands to 39 bits which maps nicely to the physical width of m20k and mlab localparam int BITS_PER_ENABLE = WIDTH / BE_WIDTH; //how many bits of data are controlled by each byte enable signal, typically we think of this as 8 but really can be any value localparam int MAX_ECC_GROUP_SIZE = 32; //if data is wide, slice into smaller sections and encode each section independently, limit the xor network size to maintain high fmax localparam int ECC_GROUP_SIZE = (BITS_PER_ENABLE > MAX_ECC_GROUP_SIZE) ? MAX_ECC_GROUP_SIZE : BITS_PER_ENABLE; //cannot jointly encode data from different byte enable groups localparam int ENCODED_BITS_PER_ENABLE = (ENABLE_ECC) ? getEncodedBitsEccGroup(BITS_PER_ENABLE, ECC_GROUP_SIZE) : BITS_PER_ENABLE; //how many encoded bits of data are controlled by each byte enable signal localparam int ENCODED_WIDTH = ENCODED_BITS_PER_ENABLE * BE_WIDTH; //total data width after encoding //////////////////////////////////////////////////////////////// // Encode the write data, respecting byte enable boundaries // //////////////////////////////////////////////////////////////// genvar g; logic [ENCODED_WIDTH-1:0] encoded_a_writedata, encoded_b_writedata; logic [ENCODED_WIDTH-1:0] encoded_a_readdata, encoded_b_readdata; logic [ENCODED_WIDTH-1:0] encoded_a_readdata_raw, encoded_b_readdata_raw; generate if (ENABLE_ECC) begin : ECC_ENCODE //each byte enable signal controls BITS_PER_ENABLE bits of the data path, to respect this boundary never ecc encode across different groups //it is possible that the group could be large, so we would want multiple ecc encoders within that group to limit the size of the xor network //dla_acl_ecc_encoder already does that for us, however we may need non-uniform slicing, so we still have to deal with that here //example scenario, suppose WIDTH = 98 and BE_WIDTH = 2, therefore BITS_PER_ENABLE = 49 //given that MAX_ECC_GROUP_SIZE = 32, this is how the data should be sliced up: //dla_acl_ecc_encoder instance 0 -- ecc instance 0 handles bits 31:0, ecc instance 1 handles bits 48:32 //dla_acl_ecc_encoder instance 1 -- ecc instance 0 handles bits 80:49, ecc instance 1 handles bits 97:81 //the above layout cannot be achieved with only one instance of dla_acl_ecc_encoder, there is no way to alternate between slicing 32 and 17 bits for (g=0; g