diff --git a/.gitignore b/.gitignore index e349bbdd..098c484a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,6 @@ modelsim.ini /working_dir /work vsim.log +vsim.wlf vcom.log transcript diff --git a/Bender.yml b/Bender.yml index 4a3d3e71..22097191 100644 --- a/Bender.yml +++ b/Bender.yml @@ -1,7 +1,8 @@ package: name: redundancy_cells - authors: + authors: - "Michael Rogenmoser " + - "Luca Rufer " dependencies: tech_cells_generic: { git: "https://github.com/pulp-platform/tech_cells_generic.git", version: 0.2.3 } @@ -9,24 +10,64 @@ dependencies: register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.3.1 } common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.24.0 } +export_include_dirs: + - rtl/ECC_reg/include sources: # Source files grouped in levels. Files in level 0 have no dependencies on files in this # package. Files in level 1 only depend on files in level 0, files in level 2 on files in # levels 1 and 0, etc. Files within a level are ordered alphabetically. # Level 0 - rtl/ODRG_unit/odrg_manager_reg_pkg.sv + - rtl/dmr/DMR_handshake_fork.sv + - rtl/dmr/DMR_handshake_join.sv + - rtl/dmr/DMR_instr_join_fork.sv + - rtl/dmr/DMR_interrupt_fork.sv + - rtl/dmr/DMR_write_mux.sv + - rtl/ECC_reg/hamming.sv + - rtl/ECC_reg/tmr_reg.sv - rtl/ecc_wrap/ecc_manager_reg_pkg.sv - rtl/ecc_wrap/ecc_manager_2_reg_pkg.sv - rtl/ecc_wrap/ecc_manager_8_reg_pkg.sv - rtl/pulpissimo_tcls/tcls_manager_reg_pkg.sv + - rtl/lowrisc_ecc/prim_secded_4_1_cor.sv + - rtl/lowrisc_ecc/prim_secded_4_1_dec.svq + - rtl/lowrisc_ecc/prim_secded_4_1_enc.sv + - rtl/lowrisc_ecc/prim_secded_8_4_cor.sv + - rtl/lowrisc_ecc/prim_secded_8_4_dec.sv + - rtl/lowrisc_ecc/prim_secded_8_4_enc.sv + - rtl/lowrisc_ecc/prim_secded_13_8_cor.sv - rtl/lowrisc_ecc/prim_secded_13_8_dec.sv - rtl/lowrisc_ecc/prim_secded_13_8_enc.sv + - rtl/lowrisc_ecc/prim_secded_16_11_cor.sv + - rtl/lowrisc_ecc/prim_secded_16_11_dec.sv + - rtl/lowrisc_ecc/prim_secded_16_11_enc.sv + - rtl/lowrisc_ecc/prim_secded_22_16_cor.sv - rtl/lowrisc_ecc/prim_secded_22_16_dec.sv - rtl/lowrisc_ecc/prim_secded_22_16_enc.sv + - rtl/lowrisc_ecc/prim_secded_28_22_cor.sv + - rtl/lowrisc_ecc/prim_secded_28_22_dec.sv + - rtl/lowrisc_ecc/prim_secded_28_22_enc.sv + - rtl/lowrisc_ecc/prim_secded_32_26_cor.sv + - rtl/lowrisc_ecc/prim_secded_32_26_dec.sv + - rtl/lowrisc_ecc/prim_secded_32_26_enc.sv + - rtl/lowrisc_ecc/prim_secded_39_32_cor.sv - rtl/lowrisc_ecc/prim_secded_39_32_dec.sv - rtl/lowrisc_ecc/prim_secded_39_32_enc.sv + - rtl/lowrisc_ecc/prim_secded_64_57_cor.sv + - rtl/lowrisc_ecc/prim_secded_64_57_dec.sv + - rtl/lowrisc_ecc/prim_secded_64_57_enc.sv + - rtl/lowrisc_ecc/prim_secded_72_64_cor.sv - rtl/lowrisc_ecc/prim_secded_72_64_dec.sv - rtl/lowrisc_ecc/prim_secded_72_64_enc.sv + - rtl/lowrisc_ecc/prim_secded_128_120_cor.sv + - rtl/lowrisc_ecc/prim_secded_128_120_dec.sv + - rtl/lowrisc_ecc/prim_secded_128_120_enc.sv + - rtl/lowrisc_ecc/prim_secded_256_247_cor.sv + - rtl/lowrisc_ecc/prim_secded_256_247_dec.sv + - rtl/lowrisc_ecc/prim_secded_256_247_enc.sv + - rtl/lowrisc_ecc/prim_secded_512_502_cor.sv + - rtl/lowrisc_ecc/prim_secded_512_502_dec.sv + - rtl/lowrisc_ecc/prim_secded_512_502_enc.sv - rtl/lowrisc_ecc/prim_secded_pkg.sv - rtl/ODRG_unit/triple_core_barrier.sv - rtl/TMR_voter.sv @@ -57,14 +98,19 @@ sources: - rtl/BUS_enc_dec/TCDM_XBAR_bus_ecc_enc.sv - rtl/BUS_enc_dec/XBAR_DEMUX_BUS_ecc_dec.sv - rtl/BUS_enc_dec/XBAR_DEMUX_BUS_ecc_enc.sv + - rtl/ECC_reg/ecc_enc.sv + - rtl/ECC_reg/ecc_cor.sv - rtl/TMR_voter_detect.sv # Level 2 - rtl/bitwise_TMR_voter.sv + - rtl/ECC_reg/ecc_reg.sv - rtl/ecc_wrap/ecc_manager.sv - rtl/ecc_wrap/ecc_manager_2.sv - rtl/ecc_wrap/ecc_manager_8.sv - rtl/ecc_wrap/ecc_sram_wrap.sv # Level 3 + - rtl/ECC_reg/dmr_io_tmr_reg.sv + # Level 4 - include_dirs: - rtl/ODRG_unit files: @@ -75,11 +121,19 @@ sources: - rtl/pulpissimo_tcls/TCLS_unit.sv - target: test files: + # Level 0 + - test/dmr/dmr_handshake.sv + - test/tb_ecc_enc_cor.sv + - test/tb_ecc_reg.sv - test/tb_ecc_scrubber.sv - test/tb_ecc_secded.sv - test/tb_ecc_sram.sv + - test/tb_tmr_reg.sv - test/tb_tmr_voter.sv - test/tb_tmr_voter_detect.sv - test/tb_tmr_word_voter.sv - test/tb_bitwise_tmr_voter.sv - + # Level 1 + - test/tb_dmr_handshake_fork.sv + - test/tb_dmr_handshake_join.sv + - test/tb_dmr_handshake_fork_join_fork.sv diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a20c43..296402dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added +- Add secded ECC corrector +- Add encoder and corrector with parameterizable data width and code +- Add ECC protected register + +### Changed +- Update secded testbench to use correctors and fix error injection + ## 0.5.0 - 2022-12-21 ### Added diff --git a/rtl/ECC_reg/dmr_io_tmr_reg.sv b/rtl/ECC_reg/dmr_io_tmr_reg.sv new file mode 100644 index 00000000..048bc678 --- /dev/null +++ b/rtl/ECC_reg/dmr_io_tmr_reg.sv @@ -0,0 +1,121 @@ +// Copyright 2023 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. + +// Description: Flipflop with TMR state protection and integrated voter. +// The FF has two inputs that are to be used in DMR circuits to +// protect combinatorial logic. The 'dmr_err_o' signal indicates +// that the input signals don't match. The 'no_load_i' signal +// is used to prevent the new input from being loaded into the FF. +// it is advised to connect 'dmr_err_o' ORed with other signals +// to 'no_load_i' (this is NOT done internally). +// The 'voter_err_o' signal indicates a voter mismatch. It can +// be caused by an SEU in a Flip-Flop or an SET in an internal MUX +// or in the voter. +// The DMR checking can be disabled by setting 'no_load_i' to 0. +// However, loading new data when the inputs don't match will cause +// a voter mismatch one cycle later. Data input 1 takes priority +// over data input 2. +// Note: This implementation does not feature the LOAD-type FFs, as this can be +// controlled via the 'no_load_i' signal. +// Note: Special care has to be taken during layout that redundant parts of this +// module are not optimized away. + +// Hint: Use the macros in 'tmr_registers.svh' instead of using this module directly. + +`include "common_cells/registers.svh" + +module dmr_io_tmr_reg #( + // Data Settings + parameter int unsigned DataWidth = 0, + // FF Settings + parameter bit HasReset = 1, + parameter bit AsynchronousReset = 1, + parameter bit ActiveLowReset = 1 +) ( + // Clock and reset + input logic clk_i, + input logic rst_ni, + // Data Input + input logic[DataWidth-1:0] data_1_i, + input logic[DataWidth-1:0] data_2_i, + // Data Output + output logic[DataWidth-1:0] data_1_o, + output logic[DataWidth-1:0] data_2_o, + // Error and Control signals + output logic dmr_err_o, + input logic no_load_i, + output logic voter_err_o, + // FF ports + input logic[DataWidth-1:0] reset_value_i +); + +logic [3*DataWidth-1:0] data_d, data_q, reset_value; + +/***************************** + * Compare and Select Data * + *****************************/ + +assign dmr_err_o = (data_1_i != data_2_i); + +assign data_d = (no_load_i) ? data_q : {3{data_1_i}}; + +/***************** + * Flip-Flop * + *****************/ + +assign reset_value = {3{reset_value_i}}; + +logic rst; +assign rst = ~rst_ni; + +if ( HasReset && AsynchronousReset && ActiveLowReset) begin + `FF(data_q, data_d, reset_value, clk_i, rst_ni) +end else if ( HasReset && AsynchronousReset && ~ActiveLowReset) begin + `FFAR(data_q, data_d, reset_value, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ~ActiveLowReset) begin + `FFSR(data_q, data_d, reset_value, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ActiveLowReset) begin + `FFSRN(data_q, data_d, reset_value, clk_i, rst_ni) +end else if ( ~HasReset) begin + `FFNR(data_q, data_d, clk_i) +end + +/******************* + * Vote Data * + *******************/ + +logic [2:0] voter_err_1, voter_err_2; + +// Create two independent voters to prevent common-mode DMR faults +bitwise_TMR_voter #( + .DataWidth ( DataWidth ) +) i_voter_1 ( + .a_i ( data_q[0*DataWidth+:DataWidth] ), + .b_i ( data_q[1*DataWidth+:DataWidth] ), + .c_i ( data_q[2*DataWidth+:DataWidth] ), + .majority_o ( data_1_o ), + .error_o ( ), + .error_cba_o ( voter_err_1 ) +); + +bitwise_TMR_voter #( + .DataWidth ( DataWidth ) +) i_voter_2 ( + .a_i ( data_q[0*DataWidth+:DataWidth] ), + .b_i ( data_q[1*DataWidth+:DataWidth] ), + .c_i ( data_q[2*DataWidth+:DataWidth] ), + .majority_o ( data_2_o ), + .error_o ( ), + .error_cba_o ( voter_err_2 ) +); + +assign voter_err_o = |voter_err_1 | |voter_err_2; + +endmodule diff --git a/rtl/ECC_reg/ecc_cor.sv b/rtl/ECC_reg/ecc_cor.sv new file mode 100644 index 00000000..ae72d8b1 --- /dev/null +++ b/rtl/ECC_reg/ecc_cor.sv @@ -0,0 +1,237 @@ +// Copyright 2021 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: Luca Rufer (lrufer@student.ethz.ch) + +// Description: Module to correct Data with Error Correcting Codes (ECC). +// When using this module, make sure the data was encoded using the +// ecc_enc.sv module for compatibility. +// This Module can also be used as a decoder or detector +// For Decoding, only use the lower 'DataWidth' bits of the 'data_o' output. +// For Detecting, don't use the 'data_o' port. Especially for codes with large +// distances, the correction part of the module can become huge. +// Only certain data widths and codes are supported. Typically, at least +// 500 bits datawidth are supported per code. For longer data widths, there +// are other, better suited codes than the ones used here. +// The following codes are implemented: +// D = 1: No Encoding: No Detection possible +// D = 2: Even Parity: Single Error Detection (SED) +// D = 3: Hamming: Single Error Correction (SEC) or +// Double Error Detection (DED) +// D = 4: Even Parity: Single Error Correction (SEC) + Double Error Detection (DED) or +// Tripple Error Detection (TED) +// ECC can be disabled by setting both 'NumErrorDetect' and 'NumErrorCorrect'. +// In this case, the Module just outputs the input data again and sets the +// error signals to 0. + +// include ECC macros for calculations +`include "ECC_reg/ecc_calc.svh" + +module ecc_cor #( + // Data Settings + parameter int unsigned DataWidth = 0, + // ECC Settings + parameter int unsigned NumErrorDetect = 1, + parameter int unsigned NumErrorCorrect = 0, + // Dependent Parameters, do not change + parameter int unsigned EccDist = `ECC_DIST(NumErrorCorrect, NumErrorDetect), + parameter int EccWidth = `ECC_WIDTH(DataWidth, EccDist) +) ( + // Data ports + input logic[EccWidth+DataWidth-1:0] data_i, + output logic[EccWidth+DataWidth-1:0] data_o, + // ECC ports + output logic error_correctable_o, + output logic error_uncorrectable_o +); + +// Not all codes are implemented for all bit widths. For encoding and decoding, +// 0s are appended to the data to increase the width to the next supported size. +localparam int unsigned ZeroForcedWidth = + (EccDist == 1) ? 0 : // No ECC + (EccDist == 2) ? 0 : // Parity + (EccDist == 3) ? 0 : // Hamming Code + (EccDist == 4) ? ( // Hsiao Code + (DataWidth == 8) ? 0 : + (DataWidth == 16) ? 0 : + (DataWidth == 32) ? 0 : + (DataWidth == 64) ? 0 : + (DataWidth <= 1) ? ( 1 - DataWidth) : + (DataWidth <= 4) ? ( 4 - DataWidth) : + (DataWidth <= 11) ? ( 11 - DataWidth) : + (DataWidth <= 26) ? ( 26 - DataWidth) : + (DataWidth <= 57) ? ( 57 - DataWidth) : + (DataWidth <= 120) ? (120 - DataWidth) : + (DataWidth <= 247) ? (247 - DataWidth) : + (502 - DataWidth) + ) : 0; + +/**************** + * Correction * + ****************/ + +logic [EccWidth+DataWidth+ZeroForcedWidth-1:0] data_in_padded; +logic [EccWidth+DataWidth+ZeroForcedWidth-1:0] data_out_padded; + +logic [EccWidth-1:0] syndrome; +logic [EccWidth+DataWidth-1:0] data_corrected; + +assign data_in_padded = {data_i, {ZeroForcedWidth{1'b0}}}; + +if ( EccDist == 1) begin : dec_no_ecc + assign data_o = data_i; +end else if ( EccDist == 2 ) begin : dec_parity + assign syndrome = ^data_i; + assign data_o = data_i; +end else if ( EccDist == 3 ) begin : dec_hamming + prim_hamming_cor #( + .DataWidth (DataWidth) + ) i_cor ( + .data_i (data_i ), + .data_o (data_corrected), + .syndrome_o (syndrome ), + .error_o ( ) + ); +end else if ( EccDist == 4 ) begin : dec_hsiao + if(DataWidth == 8) begin + prim_secded_13_8_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth == 16) begin + prim_secded_22_16_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth == 32) begin + prim_secded_39_32_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth == 64) begin + prim_secded_72_64_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth <= 1) begin + prim_secded_4_1_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth <= 4) begin + prim_secded_8_4_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth <= 11) begin + prim_secded_16_11_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth <= 26) begin + prim_secded_32_26_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth <= 57) begin + prim_secded_64_57_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth <= 120) begin + prim_secded_128_120_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else if(DataWidth <= 247) begin + prim_secded_256_247_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end else begin + prim_secded_512_502_cor i_cor ( + .d_i (data_in_padded ), + .d_o (data_out_padded), + .syndrome_o (syndrome ), + .err_o ( ) + ); + end +end + +// Remove padding +if(EccDist == 4) begin + assign data_corrected = data_out_padded[EccWidth+DataWidth+ZeroForcedWidth-1:ZeroForcedWidth]; +end + +// Determine if correctable or uncorrectable +if (EccDist == 1) begin // no ECC + assign error_correctable_o = '0; + assign error_uncorrectable_o = '0; +end else if (EccDist == 2) begin // Parity + assign error_correctable_o = '0; + assign error_uncorrectable_o = syndrome; +end else if (EccDist == 3) begin // Hamming Code + if (NumErrorCorrect == 1) begin + assign error_correctable_o = |syndrome; + assign error_uncorrectable_o = '0; + assign data_o = data_corrected; + end else begin + assign error_correctable_o = '0; + assign error_uncorrectable_o = |syndrome; + assign data_o = data_i; + end +end else if (EccDist == 4) begin // Hsiao Code + if (NumErrorCorrect == 1) begin + assign error_correctable_o = ^syndrome; + assign error_uncorrectable_o = |syndrome & ~(^syndrome); + assign data_o = data_corrected; + end else begin + assign error_correctable_o = '0; + assign error_uncorrectable_o = |syndrome; + assign data_o = data_i; + end +end + +// pragma translate_off +if (DataWidth == 0) + $fatal(1, "[ECC Register] DataWidth was no specified"); + +if (EccDist > 4) + $fatal(1, "[ECC Register] Unsupported ECC type: NumErrorDetect = %d, NumErrorCorrect = %d.", + NumErrorDetect, NumErrorCorrect); + +if (EccWidth == -1) + $fatal(1, "[ECC Register] Unsupported DataWidth for ECC type: NumErrorDetect = %d, NumErrorCorrect = %d.", + NumErrorDetect, NumErrorCorrect); +// pragma translate_on + +endmodule diff --git a/rtl/ECC_reg/ecc_enc.sv b/rtl/ECC_reg/ecc_enc.sv new file mode 100644 index 00000000..8b30be80 --- /dev/null +++ b/rtl/ECC_reg/ecc_enc.sv @@ -0,0 +1,170 @@ +// Copyright 2021 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: Luca Rufer (lrufer@student.ethz.ch) + +// Description: Module to encode Data with Error Correcting Codes (ECC). +// Only certain data widths and codes are supported. Typically, at least +// 500 bits datawidth are supported per code. For longer data widths, there +// are other, better suited codes than the ones used here. +// The following codes are implemented: +// D = 1: No Encoding: No Detection possible +// D = 2: Even Parity: Single Error Detection (SED) +// D = 3: Hamming: Single Error Correction (SEC) or +// Double Error Detection (DED) +// D = 4: Even Parity: Single Error Correction (SEC) + Double Error Detection (DED) or +// Tripple Error Detection (TED) +// ECC can be disabled by setting both 'NumErrorDetect' and 'NumErrorCorrect'. +// In this case, the Module just outputs the input data again. + +// include ECC macros for calculations +`include "ECC_reg/ecc_calc.svh" + +module ecc_enc #( + // Data Settings + parameter int unsigned DataWidth = 0, + // ECC Settings + parameter int unsigned NumErrorDetect = 1, + parameter int unsigned NumErrorCorrect = 0, + // Dependent Parameters, do not change + parameter int unsigned EccDist = `ECC_DIST(NumErrorCorrect, NumErrorDetect), + parameter int EccWidth = `ECC_WIDTH(DataWidth, EccDist) +) ( + input logic[ DataWidth-1:0] data_i, + output logic[EccWidth+DataWidth-1:0] data_o +); + + // Not all codes are implemented for all bit widths. For encoding and decoding, + // 0s are appended to the data to increase the width to the next supported size. + localparam int unsigned ZeroForcedWidth = + (EccDist == 1) ? 0 : // No ECC + (EccDist == 2) ? 0 : // Parity + (EccDist == 3) ? 0 : // Hamming Code + (EccDist == 4) ? ( // Hsiao Code + (DataWidth == 8) ? 0 : + (DataWidth == 16) ? 0 : + (DataWidth == 32) ? 0 : + (DataWidth == 64) ? 0 : + (DataWidth <= 1) ? ( 1 - DataWidth) : + (DataWidth <= 4) ? ( 4 - DataWidth) : + (DataWidth <= 11) ? ( 11 - DataWidth) : + (DataWidth <= 26) ? ( 26 - DataWidth) : + (DataWidth <= 57) ? ( 57 - DataWidth) : + (DataWidth <= 120) ? (120 - DataWidth) : + (DataWidth <= 247) ? (247 - DataWidth) : + (502 - DataWidth) + ) : 0; + + /****************** + * Encode * + ******************/ + + // Additional nets for encodings that require padding + logic [ DataWidth+ZeroForcedWidth-1:0] data_in_padded; + logic [EccWidth+DataWidth+ZeroForcedWidth-1:0] data_out_padded; + + // Expand the data with zeros + assign data_in_padded = {data_i, {ZeroForcedWidth{1'b0}}}; + + if ( EccDist == 1 ) begin : noecc + assign data_o = data_i; + end else if ( EccDist == 2 ) begin : parity + assign data_o = {^data_i, data_i}; + end else if ( EccDist == 3 ) begin : hamming + prim_hamming_enc #( + .DataWidth (DataWidth) + ) i_enc ( + .data_i, + .data_o + ); + end else if ( EccDist == 4 ) begin : hsiao + if(DataWidth == 8) begin + prim_secded_13_8_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth == 16) begin + prim_secded_22_16_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth == 32) begin + prim_secded_39_32_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth == 64) begin + prim_secded_72_64_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth <= 1) begin + prim_secded_4_1_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth <= 4) begin + prim_secded_8_4_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth <= 11) begin + prim_secded_16_11_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth <= 26) begin + prim_secded_32_26_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth <= 57) begin + prim_secded_64_57_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth <= 120) begin + prim_secded_128_120_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else if(DataWidth <= 247) begin + prim_secded_256_247_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end else begin + prim_secded_512_502_enc i_enc ( + .in (data_in_padded ), + .out(data_out_padded) + ); + end + end + + // Remove the padded zeros again + // This can only be done for a linear systematic code. + if ( EccDist == 4 ) begin + assign data_o = data_out_padded[EccWidth+DataWidth+ZeroForcedWidth-1:ZeroForcedWidth]; + end + + // pragma translate_off + if (DataWidth == 0) + $fatal(1, "[ECC Encode] DataWidth was no specified"); + + if (EccDist > 4) + $fatal(1, "[ECC Encode] Unsupported ECC type: NumErrorDetect = %d, NumErrorCorrect = %d.", + NumErrorDetect, NumErrorCorrect); + + if (EccWidth == -1) + $fatal(1, "[ECC Encode] Unsupported DataWidth for ECC type: NumErrorDetect = %d, NumErrorCorrect = %d.", + NumErrorDetect, NumErrorCorrect); + // pragma translate_on + +endmodule diff --git a/rtl/ECC_reg/ecc_reg.sv b/rtl/ECC_reg/ecc_reg.sv new file mode 100644 index 00000000..0bf070b2 --- /dev/null +++ b/rtl/ECC_reg/ecc_reg.sv @@ -0,0 +1,217 @@ +// Copyright 2021 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: Luca Rufer (lrufer@student.ethz.ch) + +// Description: +// This module implements an ECC protected register with variable data width, +// multiple code options, optional encoding, decoding and correction capabilities, +// and many variants for the FF. All options can be seen below. +// DataWidth: The number of data bits to be stored in the ECC register +// NumErrorDetect: The number of errors the register should be able to detect. +// The EC Code will be selected according to this parameter. +// NumErrorCorrect: The number of errors the register should be able to correct. +// The EC Code will be selected according to this parameter. +// Encode: if enabled: The ECC register will use the unencoded data provided on +// the 'data_i' port and encode it before storing it. +// Encode: if disabled: The ECC register will directly store the data provided +// on 'data_i' and assume it was correctly encoded by the +// user. It is suggested to use the 'ecc_enc' module to +// encode the data for compatibility. +// Decode: if enabled: The data stored in the Register will be decoded before +// it is provided on 'data_o'. If the selected code has +// error correction capability, all possible errors will be +// corrected before the data is provided on the output. +// Note that this will introduce quite some latency to the +// Register. +// Decode: if disabled: The stored data will be directly provided on 'data_o', +// without correction. The user can use the error output +// signals to see if the output is valid or not. When decode +// is disabled, 'data_o' consists of both the data bits and +// the ecc bits. If the user is only interested in the data +// bits, the parameter 'OutputECCBits' can be set to 0. +// SelfCorrect: if enabled: The register will automatically correct the stored +// data according to the 'NumErrorCorrect' parameter. +// The correction will be done automatically in one +// clock cycle. During this time, the FF will not +// accept any new data on its input. The module +// indicates an ongoing correction by setting +// 'error_correctable_o' to '1' duriing the correction. +// This behaviour is only bypassed if the FF has a load +// and 'load_en_i' is '1' during the correction cycle. +// In this case, the new data on 'data_i' will be stored +// and the old, incorrect data will be disregarded. +// SelfCorrect: if disabled: Data in the FF will not be corrected. If the stored +// data contains errors, the corresponding error signals +// will indicate this. +// Note that error detection is always enabled and the 'error_correctable_o' and +// 'error_uncorrectable_o' will always be valid, independent of the parameters. + + +// register macros +`include "common_cells/registers.svh" +`include "ECC_reg/ecc_calc.svh" + +module ecc_reg #( + // Data Settings + parameter int unsigned DataWidth = 0, + // ECC Settings + parameter int unsigned NumErrorDetect = 1, + parameter int unsigned NumErrorCorrect = 0, + parameter bit Encode = 1, + parameter bit Decode = 1, + parameter bit SelfCorrect = 1, + parameter bit OutputECCBits = 1, + // FF Settings + parameter bit HasReset = 1, + parameter bit AsynchronousReset = 1, + parameter bit ActiveLowReset = 1, + parameter bit HasLoad = 0, + // Dependent Parameters, do not change + parameter int unsigned EccDist = `ECC_DIST(NumErrorCorrect, NumErrorDetect), + parameter int EccWidth = `ECC_WIDTH(DataWidth, EccDist), + parameter int unsigned InputWidth = DataWidth + (Encode ? 0 : EccWidth), + parameter int unsigned OutputWidth = DataWidth + ((Decode | !OutputECCBits) ? 0 : EccWidth) +) ( + // clock and reset inputs + input logic clk_i, + input logic rst_ni, + // data ports + input logic[ InputWidth-1:0] data_i, + input logic[ InputWidth-1:0] reset_value_i, + output logic[OutputWidth-1:0] data_o, + // ECC ports + output logic error_correctable_o, + output logic error_uncorrectable_o, + // FF ports + input logic load_en_i +); + +/****************** + * Encode * + ******************/ + +logic [EccWidth+DataWidth-1:0] data_encoded, reset_value_encoded; + +if ( Encode ) begin : enc + // Encode the incomming data + ecc_enc #( + .DataWidth ( DataWidth ), + .NumErrorDetect ( NumErrorDetect ), + .NumErrorCorrect ( NumErrorCorrect ) + ) i_enc ( + .data_i (data_i ), + .data_o (data_encoded) + ); + // Encode the reset value + ecc_enc #( + .DataWidth ( DataWidth ), + .NumErrorDetect ( NumErrorDetect ), + .NumErrorCorrect ( NumErrorCorrect ) + ) i_enc_rst_val ( + .data_i (reset_value_i ), + .data_o (reset_value_encoded) + ); +end else begin : no_enc + assign data_encoded = data_i; + assign reset_value_encoded = reset_value_i; +end + +/******************* + * FF input select * + *******************/ + +logic [EccWidth+DataWidth-1:0] data_d, data_q, data_corrected; + +if(HasLoad && SelfCorrect) begin + assign data_d = load_en_i ? data_encoded : data_corrected; +end else if(HasLoad && ~SelfCorrect) begin + assign data_d = load_en_i ? data_encoded : data_q; +end else if(~HasLoad && SelfCorrect) begin + assign data_d = error_correctable_o ? data_corrected : data_encoded; +end else begin + assign data_d = data_encoded; +end + +/***************** + * Flip-Flop * + *****************/ + +logic rst; +assign rst = ~rst_ni; + +if ( HasReset && AsynchronousReset && ActiveLowReset && ~HasLoad) begin + `FF(data_q, data_d, reset_value_encoded, clk_i, rst_ni) +end else if ( HasReset && AsynchronousReset && ~ActiveLowReset && ~HasLoad) begin + `FFAR(data_q, data_d, reset_value_encoded, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ~ActiveLowReset && ~HasLoad) begin + `FFSR(data_q, data_d, reset_value_encoded, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ActiveLowReset && ~HasLoad) begin + `FFSRN(data_q, data_d, reset_value_encoded, clk_i, rst_ni) +end else if ( ~HasReset && ~HasLoad) begin + `FFNR(data_q, data_d, clk_i) +end else if ( HasReset && AsynchronousReset && ActiveLowReset && HasLoad) begin + `FFL(data_q, data_d, load_en_i, reset_value_encoded, clk_i, rst_ni) +end else if ( HasReset && AsynchronousReset && ~ActiveLowReset && HasLoad) begin + `FFLAR(data_q, data_d, load_en_i, reset_value_encoded, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ~ActiveLowReset && HasLoad) begin + `FFLSR(data_q, data_d, load_en_i, reset_value_encoded, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ActiveLowReset && HasLoad) begin + `FFLSRN(data_q, data_d, load_en_i, reset_value_encoded, clk_i, rst_ni) +end else if ( ~HasReset && HasLoad) begin + `FFLNR(data_q, data_d, load_en_i, clk_i) +end + +/**************** + * Correction * + ****************/ + +// The 'correction' part is only used if Decode or SelfCorrect is enabled. +// When both are disabled, only the detection segment of the corrector is used. + +ecc_cor #( + .DataWidth (DataWidth ), + .NumErrorDetect (NumErrorDetect ), + .NumErrorCorrect(NumErrorCorrect) +) i_cor ( + .data_i (data_q ), + .data_o (data_corrected ), + .error_correctable_o (error_correctable_o ), + .error_uncorrectable_o (error_uncorrectable_o) +); + +/******************* + * Output Assign * + *******************/ + +if(Decode) begin + assign data_o = data_corrected; +end else begin + if(OutputECCBits) begin + assign data_o = data_q; + end else begin + assign data_o = data_q[DataWidth-1:0]; + end +end + +// pragma translate_off +if (DataWidth == 0) + $fatal(1, "[ECC Register] DataWidth was no specified"); + +if (EccDist > 4) + $fatal(1, "[ECC Register] Unsupported ECC type: NumErrorDetect = %d, NumErrorCorrect = %d.", + NumErrorDetect, NumErrorCorrect); + +if (EccWidth == -1) + $fatal(1, "[ECC Register] Unsupported DataWidth for ECC type: NumErrorDetect = %d, NumErrorCorrect = %d.", + NumErrorDetect, NumErrorCorrect); +// pragma translate_on + +endmodule diff --git a/rtl/ECC_reg/hamming.sv b/rtl/ECC_reg/hamming.sv new file mode 100644 index 00000000..aa387088 --- /dev/null +++ b/rtl/ECC_reg/hamming.sv @@ -0,0 +1,185 @@ +// Copyright 2022 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. +// +// Description: Encoding, Detection and Correction module for Hamming Code + +`include "ECC_reg/ecc_calc.svh" + +// TODO: re-order vectors to reduce xor-tree-height during encoding + +localparam MaxDataWidth = 502; +localparam MaxParityBits = 9; +localparam logic [MaxDataWidth-1:0][MaxParityBits-1:0] P = '{ + 9'h1FF, 9'h1FE, 9'h1FD, 9'h1FC, 9'h1FB, 9'h1FA, 9'h1F9, 9'h1F8, + 9'h1F7, 9'h1F6, 9'h1F5, 9'h1F4, 9'h1F3, 9'h1F2, 9'h1F1, 9'h1F0, + 9'h1EF, 9'h1EE, 9'h1ED, 9'h1EC, 9'h1EB, 9'h1EA, 9'h1E9, 9'h1E8, + 9'h1E7, 9'h1E6, 9'h1E5, 9'h1E4, 9'h1E3, 9'h1E2, 9'h1E1, 9'h1E0, + 9'h1DF, 9'h1DE, 9'h1DD, 9'h1DC, 9'h1DB, 9'h1DA, 9'h1D9, 9'h1D8, + 9'h1D7, 9'h1D6, 9'h1D5, 9'h1D4, 9'h1D3, 9'h1D2, 9'h1D1, 9'h1D0, + 9'h1CF, 9'h1CE, 9'h1CD, 9'h1CC, 9'h1CB, 9'h1CA, 9'h1C9, 9'h1C8, + 9'h1C7, 9'h1C6, 9'h1C5, 9'h1C4, 9'h1C3, 9'h1C2, 9'h1C1, 9'h1C0, + 9'h1BF, 9'h1BE, 9'h1BD, 9'h1BC, 9'h1BB, 9'h1BA, 9'h1B9, 9'h1B8, + 9'h1B7, 9'h1B6, 9'h1B5, 9'h1B4, 9'h1B3, 9'h1B2, 9'h1B1, 9'h1B0, + 9'h1AF, 9'h1AE, 9'h1AD, 9'h1AC, 9'h1AB, 9'h1AA, 9'h1A9, 9'h1A8, + 9'h1A7, 9'h1A6, 9'h1A5, 9'h1A4, 9'h1A3, 9'h1A2, 9'h1A1, 9'h1A0, + 9'h19F, 9'h19E, 9'h19D, 9'h19C, 9'h19B, 9'h19A, 9'h199, 9'h198, + 9'h197, 9'h196, 9'h195, 9'h194, 9'h193, 9'h192, 9'h191, 9'h190, + 9'h18F, 9'h18E, 9'h18D, 9'h18C, 9'h18B, 9'h18A, 9'h189, 9'h188, + 9'h187, 9'h186, 9'h185, 9'h184, 9'h183, 9'h182, 9'h181, 9'h180, + 9'h17F, 9'h17E, 9'h17D, 9'h17C, 9'h17B, 9'h17A, 9'h179, 9'h178, + 9'h177, 9'h176, 9'h175, 9'h174, 9'h173, 9'h172, 9'h171, 9'h170, + 9'h16F, 9'h16E, 9'h16D, 9'h16C, 9'h16B, 9'h16A, 9'h169, 9'h168, + 9'h167, 9'h166, 9'h165, 9'h164, 9'h163, 9'h162, 9'h161, 9'h160, + 9'h15F, 9'h15E, 9'h15D, 9'h15C, 9'h15B, 9'h15A, 9'h159, 9'h158, + 9'h157, 9'h156, 9'h155, 9'h154, 9'h153, 9'h152, 9'h151, 9'h150, + 9'h14F, 9'h14E, 9'h14D, 9'h14C, 9'h14B, 9'h14A, 9'h149, 9'h148, + 9'h147, 9'h146, 9'h145, 9'h144, 9'h143, 9'h142, 9'h141, 9'h140, + 9'h13F, 9'h13E, 9'h13D, 9'h13C, 9'h13B, 9'h13A, 9'h139, 9'h138, + 9'h137, 9'h136, 9'h135, 9'h134, 9'h133, 9'h132, 9'h131, 9'h130, + 9'h12F, 9'h12E, 9'h12D, 9'h12C, 9'h12B, 9'h12A, 9'h129, 9'h128, + 9'h127, 9'h126, 9'h125, 9'h124, 9'h123, 9'h122, 9'h121, 9'h120, + 9'h11F, 9'h11E, 9'h11D, 9'h11C, 9'h11B, 9'h11A, 9'h119, 9'h118, + 9'h117, 9'h116, 9'h115, 9'h114, 9'h113, 9'h112, 9'h111, 9'h110, + 9'h10F, 9'h10E, 9'h10D, 9'h10C, 9'h10B, 9'h10A, 9'h109, 9'h108, + 9'h107, 9'h106, 9'h105, 9'h104, 9'h103, 9'h102, 9'h101, 9'h0FF, + 9'h0FE, 9'h0FD, 9'h0FC, 9'h0FB, 9'h0FA, 9'h0F9, 9'h0F8, 9'h0F7, + 9'h0F6, 9'h0F5, 9'h0F4, 9'h0F3, 9'h0F2, 9'h0F1, 9'h0F0, 9'h0EF, + 9'h0EE, 9'h0ED, 9'h0EC, 9'h0EB, 9'h0EA, 9'h0E9, 9'h0E8, 9'h0E7, + 9'h0E6, 9'h0E5, 9'h0E4, 9'h0E3, 9'h0E2, 9'h0E1, 9'h0E0, 9'h0DF, + 9'h0DE, 9'h0DD, 9'h0DC, 9'h0DB, 9'h0DA, 9'h0D9, 9'h0D8, 9'h0D7, + 9'h0D6, 9'h0D5, 9'h0D4, 9'h0D3, 9'h0D2, 9'h0D1, 9'h0D0, 9'h0CF, + 9'h0CE, 9'h0CD, 9'h0CC, 9'h0CB, 9'h0CA, 9'h0C9, 9'h0C8, 9'h0C7, + 9'h0C6, 9'h0C5, 9'h0C4, 9'h0C3, 9'h0C2, 9'h0C1, 9'h0C0, 9'h0BF, + 9'h0BE, 9'h0BD, 9'h0BC, 9'h0BB, 9'h0BA, 9'h0B9, 9'h0B8, 9'h0B7, + 9'h0B6, 9'h0B5, 9'h0B4, 9'h0B3, 9'h0B2, 9'h0B1, 9'h0B0, 9'h0AF, + 9'h0AE, 9'h0AD, 9'h0AC, 9'h0AB, 9'h0AA, 9'h0A9, 9'h0A8, 9'h0A7, + 9'h0A6, 9'h0A5, 9'h0A4, 9'h0A3, 9'h0A2, 9'h0A1, 9'h0A0, 9'h09F, + 9'h09E, 9'h09D, 9'h09C, 9'h09B, 9'h09A, 9'h099, 9'h098, 9'h097, + 9'h096, 9'h095, 9'h094, 9'h093, 9'h092, 9'h091, 9'h090, 9'h08F, + 9'h08E, 9'h08D, 9'h08C, 9'h08B, 9'h08A, 9'h089, 9'h088, 9'h087, + 9'h086, 9'h085, 9'h084, 9'h083, 9'h082, 9'h081, 9'h07F, 9'h07E, + 9'h07D, 9'h07C, 9'h07B, 9'h07A, 9'h079, 9'h078, 9'h077, 9'h076, + 9'h075, 9'h074, 9'h073, 9'h072, 9'h071, 9'h070, 9'h06F, 9'h06E, + 9'h06D, 9'h06C, 9'h06B, 9'h06A, 9'h069, 9'h068, 9'h067, 9'h066, + 9'h065, 9'h064, 9'h063, 9'h062, 9'h061, 9'h060, 9'h05F, 9'h05E, + 9'h05D, 9'h05C, 9'h05B, 9'h05A, 9'h059, 9'h058, 9'h057, 9'h056, + 9'h055, 9'h054, 9'h053, 9'h052, 9'h051, 9'h050, 9'h04F, 9'h04E, + 9'h04D, 9'h04C, 9'h04B, 9'h04A, 9'h049, 9'h048, 9'h047, 9'h046, + 9'h045, 9'h044, 9'h043, 9'h042, 9'h041, 9'h03F, 9'h03E, 9'h03D, + 9'h03C, 9'h03B, 9'h03A, 9'h039, 9'h038, 9'h037, 9'h036, 9'h035, + 9'h034, 9'h033, 9'h032, 9'h031, 9'h030, 9'h02F, 9'h02E, 9'h02D, + 9'h02C, 9'h02B, 9'h02A, 9'h029, 9'h028, 9'h027, 9'h026, 9'h025, + 9'h024, 9'h023, 9'h022, 9'h021, 9'h01F, 9'h01E, 9'h01D, 9'h01C, + 9'h01B, 9'h01A, 9'h019, 9'h018, 9'h017, 9'h016, 9'h015, 9'h014, + 9'h013, 9'h012, 9'h011, 9'h00F, 9'h00E, 9'h00D, 9'h00C, 9'h00B, + 9'h00A, 9'h009, 9'h007, 9'h006, 9'h005, 9'h003 +}; + +localparam logic [MaxParityBits-1:0][MaxDataWidth-1:0] P_T = '{ + 502'h3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000000000000000000000, + 502'h3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000, + 502'h3FFFFFFFFFFFFFFFC0000000000000003FFFFFFFFFFFFFFFC0000000000000007FFFFFFFFFFFFFFF8000000000000000FFFFFFFFFFFFFFFE00000000000000, + 502'h3FFFFFFFC00000003FFFFFFFC00000003FFFFFFFC00000003FFFFFFFC00000007FFFFFFF800000007FFFFFFF80000000FFFFFFFF00000001FFFFFFFC000000, + 502'h3FFFC0003FFFC0003FFFC0003FFFC0003FFFC0003FFFC0003FFFC0003FFFC0007FFF80007FFF80007FFF80007FFF8000FFFF0000FFFF0001FFFE0003FFF800, + 502'h3FC03FC03FC03FC03FC03FC03FC03FC03FC03FC03FC03FC03FC03FC03FC03FC07F807F807F807F807F807F807F807F80FF00FF00FF00FF01FE01FE03FC07F0, + 502'h3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C78787878787878787878787878787878F0F0F0F0F0F0F0F1E1E1E1E3C3C78E, + 502'h333333333333333333333333333333333333333333333333333333333333333366666666666666666666666666666666CCCCCCCCCCCCCCCD9999999B33366D, + 502'h2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD5555555555555555555555555555555AAAAAAAAAAAAAAAB55555556AAAD5B +}; + +module prim_hamming_enc #( + parameter int unsigned DataWidth = 0, + /* Dependent parameter, do not change */ + parameter int EccWidth = `ECC_WIDTH(DataWidth, 3) +) ( + input logic [DataWidth-1:0] data_i, + output logic [DataWidth+EccWidth-1:0] data_o +); + + // A data word 'u' is encoded into a code word 'c' by matrix multiplication: + // c = u * G where G = [I P] + + // Encode the data + always_comb begin : enc + data_o[DataWidth-1:0] = data_i; + for (int unsigned i = 0; i < EccWidth; i++) begin + data_o[DataWidth+i] = ^(data_i & P_T[i][DataWidth-1:0]); + end + end +endmodule + +module prim_hamming_det #( + parameter int unsigned DataWidth = 0, + /* Dependent parameter, do not change */ + parameter int EccWidth = `ECC_WIDTH(DataWidth, 3) +) ( + input logic [DataWidth+EccWidth-1:0] data_i, + output logic [EccWidth-1:0] syndrome_o, + output logic error_o +); + + // The syndrome 'e' is calculated by multiplying the code word 'c' with the + // parity check matrix e = H * c = [P^T I] * c = P^T * c_data + I * c_ecc + + // Calculate the syndrome + always_comb begin : det + for (int unsigned i = 0; i < EccWidth; i++) begin + syndrome_o[i] = ^(data_i[DataWidth-1:0] & P_T[i]) ^ data_i[DataWidth+i]; + end + end + + // If the syndrome is not 0, an error has occured + assign error_o = |syndrome_o; +endmodule + +module prim_hamming_cor #( + parameter int unsigned DataWidth = 0, + /* Dependent parameter, do not change */ + parameter int EccWidth = `ECC_WIDTH(DataWidth, 3) +) ( + input logic [DataWidth+EccWidth-1:0] data_i, + output logic [DataWidth+EccWidth-1:0] data_o, + output logic [EccWidth-1:0] syndrome_o, + output logic error_o +); + + // The syndrome 'e' is calculated by multiplying the code word 'c' with the + // parity check matrix e = H * c = [P^T I] * c = P^T * c_data + I * c_ecc + + always_comb begin : cor + // calculate the syndrome + for (int unsigned i = 0; i < EccWidth; i++) begin + syndrome_o[i] = ^(data_i[DataWidth-1:0] & P_T[i]) ^ data_i[DataWidth+i]; + end + + data_o = data_i; + + // Errors in data bits can be detected by matching the calculated syndromes + // to given error patters. These error patterns correspond to the rows of P + // (colums of P_T). + + // Correct Data bits + for (int unsigned i = 0; i < DataWidth; i++) begin + if(syndrome_o == P[i]) data_o[i] = ~data_o[i]; + end + + // Errors in ECC bits result in a syndome with exacly one bit set. The + // position of the '1' bit in the syndrom corresponds to the flipped ECC bit + + // Correct ECC bits + for (int unsigned i = 0; i < EccWidth; i++) begin + if(syndrome_o == (1 << i)) data_o[DataWidth+i] = ~data_o[DataWidth+i]; + end + + end + + assign error_o = |syndrome_o; + +endmodule diff --git a/rtl/ECC_reg/include/ECC_reg/ecc_calc.svh b/rtl/ECC_reg/include/ECC_reg/ecc_calc.svh new file mode 100644 index 00000000..9acd3562 --- /dev/null +++ b/rtl/ECC_reg/include/ECC_reg/ecc_calc.svh @@ -0,0 +1,50 @@ +// Copyright 2021 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: Luca Rufer (lrufer@student.ethz.ch) + +`ifndef REDUNDANCY_CELLS_ECC_CALC_SVH_ +`define REDUNDANCY_CELLS_ECC_CALC_SVH_ + +// Calculate the ECC distance depending on the given parameters +`define ECC_DIST(NumErrorCorrect, NumErrorDetect) \ + (((NumErrorCorrect) >= (NumErrorDetect)) ? \ + (2 * (NumErrorCorrect) + 1) : \ + ((NumErrorCorrect) + (NumErrorDetect) + 1)) + +// Calcualte the the number of ECC bits required to encode a given amount +// of data bits with a given code distance +`define ECC_WIDTH(DATA_WIDTH, ECC_DIST) \ + ((ECC_DIST == 0) ? -1 : /* Invalid ECC distance */ \ + (ECC_DIST == 1) ? 0 : /* No Coding */ \ + (ECC_DIST == 2) ? 1 : /* Single Parity bit */ \ + (ECC_DIST == 3) ? ( /* Hamming Code: k <= 2^r - r - 1 */ \ + (DATA_WIDTH <= 0) ? 0 : \ + (DATA_WIDTH <= 4 - 2 - 1) ? 2 : \ + (DATA_WIDTH <= 8 - 3 - 1) ? 3 : \ + (DATA_WIDTH <= 16 - 4 - 1) ? 4 : \ + (DATA_WIDTH <= 32 - 5 - 1) ? 5 : \ + (DATA_WIDTH <= 64 - 6 - 1) ? 6 : \ + (DATA_WIDTH <= 128 - 7 - 1) ? 7 : \ + (DATA_WIDTH <= 256 - 8 - 1) ? 8 : \ + (DATA_WIDTH <= 512 - 9 - 1) ? 9 : -1) : \ + (ECC_DIST == 4) ? ( /* Hsiao Code: k <= 2^(r-1) - r */ \ + (DATA_WIDTH <= 0) ? 0 : \ + (DATA_WIDTH <= 4 - 3) ? 3 : \ + (DATA_WIDTH <= 8 - 4) ? 4 : \ + (DATA_WIDTH <= 16 - 5) ? 5 : \ + (DATA_WIDTH <= 32 - 6) ? 6 : \ + (DATA_WIDTH <= 64 - 7) ? 7 : \ + (DATA_WIDTH <= 128 - 8) ? 8 : \ + (DATA_WIDTH <= 256 - 9) ? 9 : \ + (DATA_WIDTH <= 512 - 10) ? 10 : -1) : \ + -1) /* Other Codes not supported */ + +`endif diff --git a/rtl/ECC_reg/include/ECC_reg/ecc_registers.svh b/rtl/ECC_reg/include/ECC_reg/ecc_registers.svh new file mode 100644 index 00000000..745ed309 --- /dev/null +++ b/rtl/ECC_reg/include/ECC_reg/ecc_registers.svh @@ -0,0 +1,2035 @@ +// Copyright 2021 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: Luca Rufer (lrufer@student.ethz.ch) + +`ifndef REDUNDANCY_CELLS_ECC_REGISTERS_SVH_ +`define REDUNDANCY_CELLS_ECC_REGISTERS_SVH_ + +`include "common_cells/registers.svh" + +/******************************************* + * Building Blocks for Macro definitions * + *******************************************/ + +// Basic module definitions +`define ECC_REGISTER_HEADER ecc_reg #( +`define ECC_REGISTER_BODY(__name) ) __name ( +`define ECC_REGISTER_FOOTER ); + +// Parameter definitions +`define ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC) \ + .DataWidth (__WIDTH), \ + .NumErrorDetect (__ND), \ + .NumErrorCorrect (__NC) +`define ECC_REGISTER_PARAM_MODE(__E, __D, __C) \ + .Encode (__E), \ + .Decode (__D), \ + .SelfCorrect (__C) +`define ECC_REGISTER_PARAM_MODE_NONE `ECC_REGISTER_PARAM_MODE(1'b0, 1'b0, 1'b0) +`define ECC_REGISTER_PARAM_MODE_C `ECC_REGISTER_PARAM_MODE(1'b0, 1'b0, 1'b1) +`define ECC_REGISTER_PARAM_MODE_D `ECC_REGISTER_PARAM_MODE(1'b0, 1'b1, 1'b0) +`define ECC_REGISTER_PARAM_MODE_DC `ECC_REGISTER_PARAM_MODE(1'b0, 1'b1, 1'b1) +`define ECC_REGISTER_PARAM_MODE_E `ECC_REGISTER_PARAM_MODE(1'b1, 1'b0, 1'b0) +`define ECC_REGISTER_PARAM_MODE_EC `ECC_REGISTER_PARAM_MODE(1'b1, 1'b0, 1'b1) +`define ECC_REGISTER_PARAM_MODE_ED `ECC_REGISTER_PARAM_MODE(1'b1, 1'b1, 1'b0) +`define ECC_REGISTER_PARAM_MODE_EDC `ECC_REGISTER_PARAM_MODE(1'b1, 1'b1, 1'b1) +`define ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o) \ + .OutputECCBits ($bits(__o) != __WIDTH) +`define ECC_REGISTER_PARAM_FF_TYPE(__HasReset, __Async, __ActiveLow, __HasLoad) \ + .HasReset (__HasReset ), \ + .AsynchronousReset (__Async ), \ + .ActiveLowReset (__ActiveLow), \ + .HasLoad (__HasLoad ) +`define ECC_REGISTER_PARAM_FF_TYPE_DEFAULT `ECC_REGISTER_PARAM_FF_TYPE(1'b1, 1'b1, 1'b1, 1'b0) +`define ECC_REGISTER_PARAM_FF_TYPE_AR `ECC_REGISTER_PARAM_FF_TYPE(1'b1, 1'b1, 1'b0, 1'b0) +`define ECC_REGISTER_PARAM_FF_TYPE_SR `ECC_REGISTER_PARAM_FF_TYPE(1'b1, 1'b0, 1'b0, 1'b0) +`define ECC_REGISTER_PARAM_FF_TYPE_SRN `ECC_REGISTER_PARAM_FF_TYPE(1'b1, 1'b0, 1'b1, 1'b0) +`define ECC_REGISTER_PARAM_FF_TYPE_NR `ECC_REGISTER_PARAM_FF_TYPE(1'b0, 1'b0, 1'b0, 1'b0) +`define ECC_REGISTER_PARAM_FF_TYPE_LARN `ECC_REGISTER_PARAM_FF_TYPE(1'b1, 1'b1, 1'b1, 1'b1) +`define ECC_REGISTER_PARAM_FF_TYPE_LAR `ECC_REGISTER_PARAM_FF_TYPE(1'b1, 1'b1, 1'b0, 1'b1) +`define ECC_REGISTER_PARAM_FF_TYPE_LSR `ECC_REGISTER_PARAM_FF_TYPE(1'b1, 1'b0, 1'b0, 1'b1) +`define ECC_REGISTER_PARAM_FF_TYPE_LSRN `ECC_REGISTER_PARAM_FF_TYPE(1'b1, 1'b0, 1'b1, 1'b1) +`define ECC_REGISTER_PARAM_FF_TYPE_LNR `ECC_REGISTER_PARAM_FF_TYPE(1'b0, 1'b0, 1'b0, 1'b1) + +`define ECC_REGISTER_PORTS_CLK_ARSTN(__clk,__arst_n) \ + .clk_i (__clk), \ + .rst_ni (__arst_n) +`define ECC_REGISTER_PORTS_CLK_ARST(__clk,__arst) \ + .clk_i (__clk), \ + .rst_ni (~__arst) +`define ECC_REGISTER_PORTS_CLK_SRSTN(__clk,__reset_n_clk) \ + .clk_i (__clk), \ + .rst_ni (__reset_n_clk) +`define ECC_REGISTER_PORTS_CLK_SRST(__clk,__reset_clk) \ + .clk_i (__clk), \ + .rst_ni (~__reset_clk) +`define ECC_REGISTER_PORTS_CLK(__clk) \ + .clk_i (__clk), \ + .rst_ni (1'b1) +`define ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc) \ + .data_i (__i), \ + .reset_value_i (__rst_val), \ + .data_o (__o), \ + .error_correctable_o (__ec), \ + .error_uncorrectable_o (__enc) +`define ECC_REGISTER_PORTS_LOAD(__load) \ + .load_en_i (__load) +`define ECC_REGISTER_PORTS_NOLOAD `ECC_REGISTER_PORTS_LOAD(1'b0) + +/*********************************************************************** + * ALL FF Types with no Encoding, no Decoding and no Self-Correction * + ***********************************************************************/ + +// ECC protected Flip-Flop with asynchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFECC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_DEFAULT \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + + +// ECC protected Flip-Flop with asynchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARECC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_AR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected Flip-Flop with synchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRECC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected Flip-Flop with synchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNECC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected Always-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +`define FFNRECC(__name, __WIDTH, __ND, __NC, __i, __o, __ec, __enc, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_NR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLECC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LARN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARECC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LAR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRECC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNECC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc,__load, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected Load-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +`define FFLNRECC(__name, __WIDTH, __ND, __NC, __i, __o, __ec, __enc, __load, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_NONE, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LNR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +/******************************************************************** + * ALL FF Types with Encoding, no Decoding and no Self-Correction * + ********************************************************************/ + +// ECC protected encoding Flip-Flop with asynchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFECCE(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_DEFAULT \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + + +// ECC protected encoding Flip-Flop with asynchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARECCE(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_AR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding Flip-Flop with synchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRECCE(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding Flip-Flop with synchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNECCE(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding Always-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +`define FFNRECCE(__name, __ND, __NC, __i, __o, __ec, __enc, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_NR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLECCE(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LARN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARECCE(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LAR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRECCE(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNECCE(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc,__load, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding Load-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +`define FFLNRECCE(__name, __ND, __NC, __i, __o, __ec, __enc, __load, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_E, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LNR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +/*********************************************************************** + * ALL FF Types with no Encoding, Decoding and no Self-Correction * + ***********************************************************************/ + +// ECC protected decoding Flip-Flop with asynchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFECCD(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_DEFAULT \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + + +// ECC protected decoding Flip-Flop with asynchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARECCD(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_AR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding Flip-Flop with synchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRECCD(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding Flip-Flop with synchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNECCD(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding Always-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +`define FFNRECCD(__name, __WIDTH, __ND, __NC, __i, __o, __ec, __enc, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_NR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLECCD(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LARN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARECCD(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LAR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRECCD(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNECCD(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc,__load, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding Load-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +`define FFLNRECCD(__name, __WIDTH, __ND, __NC, __i, __o, __ec, __enc, __load, __clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_D, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LNR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +/******************************************************************** + * ALL FF Types with Encoding, Decoding and no Self-Correction * + ********************************************************************/ + +// ECC protected encoding and decoding Flip-Flop with asynchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFECCED(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_DEFAULT \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + + +// ECC protected encoding and decoding Flip-Flop with asynchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARECCED(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_AR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and decoding Flip-Flop with synchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRECCED(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and decoding Flip-Flop with synchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNECCED(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and decoding Always-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +`define FFNRECCED(__name, __ND, __NC, __i, __o, __ec, __enc, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_NR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and decoding Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLECCED(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LARN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and decoding Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARECCED(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LAR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and decoding Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRECCED(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and decoding Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNECCED(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc,__load, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and decoding Load-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +`define FFLNRECCED(__name, __ND, __NC, __i, __o, __ec, __enc, __load, __clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_ED, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LNR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +/*********************************************************************** + * ALL FF Types with no Encoding, no Decoding and Self-Correction * + ***********************************************************************/ + +// ECC protected self-correcting Flip-Flop with asynchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFECCC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_DEFAULT \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + + +// ECC protected self-correcting Flip-Flop with asynchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARECCC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_AR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected self-correcting Flip-Flop with synchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRECCC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected self-correcting Flip-Flop with synchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNECCC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected self-correcting Always-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +`define FFNRECCC(__name, __WIDTH, __ND, __NC, __i, __o, __ec, __enc, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_NR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected self-correcting Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLECCC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LARN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected self-correcting Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARECCC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LAR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected self-correcting Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRECCC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected self-correcting Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNECCC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc,__load, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected self-correcting Load-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +`define FFLNRECCC(__name, __WIDTH, __ND, __NC, __i, __o, __ec, __enc, __load, __clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_C, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LNR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +/******************************************************************** + * ALL FF Types with Encoding, no Decoding and Self-Correction * + ********************************************************************/ + +// ECC protected encoding and self-correcting Flip-Flop with asynchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFECCEC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_DEFAULT \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + + +// ECC protected encoding and self-correcting Flip-Flop with asynchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARECCEC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_AR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and self-correcting Flip-Flop with synchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRECCEC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and self-correcting Flip-Flop with synchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNECCEC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and self-correcting Always-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +`define FFNRECCEC(__name, __ND, __NC, __i, __o, __ec, __enc, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_NR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and self-correcting Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLECCEC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst_n) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LARN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and self-correcting Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARECCEC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LAR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and self-correcting Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRECCEC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __reset_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and self-correcting Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNECCEC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc,__load, __clk, __reset_n_clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding and self-correcting Load-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is not corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +`define FFLNRECCEC(__name, __ND, __NC, __i, __o, __ec, __enc, __load, __clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LNR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +/*********************************************************************** + * ALL FF Types with no Encoding, Decoding and Self-Correction * + ***********************************************************************/ + +// ECC protected decoding and self-correcting Flip-Flop with asynchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFECCDC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst_n)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_DEFAULT \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + + +// ECC protected decoding and self-correcting Flip-Flop with asynchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARECCDC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_AR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding and self-correcting Flip-Flop with synchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRECCDC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding and self-correcting Flip-Flop with synchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNECCDC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_n_clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding and self-correcting Always-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +`define FFNRECCDC(__name, __WIDTH, __ND, __NC, __i, __o, __ec, __enc, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_NR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding and self-correcting Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLECCDC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst_n)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LARN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding and self-correcting Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARECCDC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LAR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding and self-correcting Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRECCDC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __reset_clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding and self-correcting Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __rst_val: Reset value of the FF. Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNECCDC(__name, __WIDTH, __ND, __NC, __i, __rst_val, __o, __ec, __enc,__load, __clk, __reset_n_clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected decoding and self-correcting Load-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __WIDTH: width of the data, in bits +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs). Data must already be ECC encoded. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: load __i value into FF +// __clk: clock input +`define FFLNRECCDC(__name, __WIDTH, __ND, __NC, __i, __o, __ec, __enc, __load, __clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC(__WIDTH, __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_DC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS(__WIDTH, __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LNR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +/******************************************************************** + * ALL FF Types with Encoding, Decoding and Self-Correction * + ********************************************************************/ + +// ECC protected encoding, decoding and self-correcting Flip-Flop with asynchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFECCEDC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst_n)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_DEFAULT \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + + +// ECC protected encoding, decoding and self-correcting Flip-Flop with asynchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARECCEDC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __arst) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_AR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding, decoding and self-correcting Flip-Flop with synchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRECCEDC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding, decoding and self-correcting Flip-Flop with synchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNECCEDC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __clk, __reset_n_clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_SRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding, decoding and self-correcting Always-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// Note: Input Data is not saved while FF is self-correcting (__ec high) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __clk: clock input +`define FFNRECCEDC(__name, __ND, __NC, __i, __o, __ec, __enc, __clk) \ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_NR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_NOLOAD \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding, decoding and self-correcting Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLECCEDC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst_n)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LARN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARSTN(__clk, __arst_n), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding, decoding and self-correcting Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARECCEDC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __arst)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LAR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_ARST(__clk, __arst), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding, decoding and self-correcting Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRECCEDC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc, __load, __clk, __reset_clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRST(__clk, __reset_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding, decoding and self-correcting Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNECCEDC(__name, __ND, __NC, __i, __rst_val, __o, __ec, __enc,__load, __clk, __reset_n_clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LSRN \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK_SRSTN(__clk, __reset_n_clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, __rst_val, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +// ECC protected encoding, decoding and self-correcting Load-enable Flip-Flop without reset +// __name: Name of the ECC FF instance +// __ND: Number of errors the used code can detect +// __NC: Number of errors the used code can correct +// __i: data input (replaces D input for normal FFs) +// __o: data output (replaces Q output for normal FFs). Contains ECC bits and is corrected. +// __ec: error correctable output. if 1, detection unit found a correctable error +// __enc: error not correctable output. if 1, detection unit found an uncorrrectable error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +`define FFLNRECCEDC(__name, __ND, __NC, __i, __o, __ec, __enc, __load, __clk)\ +`ECC_REGISTER_HEADER \ +`ECC_REGISTER_PARAM_ECC($bits(__i), __ND, __NC), \ +`ECC_REGISTER_PARAM_MODE_EDC, \ +`ECC_REGISTER_PARAM_OUTPUT_ECC_BITS($bits(__i), __o), \ +`ECC_REGISTER_PARAM_FF_TYPE_LNR \ +`ECC_REGISTER_BODY(__name) \ +`ECC_REGISTER_PORTS_CLK(__clk), \ +`ECC_REGISTER_PORTS_DATA_ERROR(__i, '0, __o, __ec, __enc), \ +`ECC_REGISTER_PORTS_LOAD(__load) \ +`ECC_REGISTER_FOOTER + +`endif \ No newline at end of file diff --git a/rtl/ECC_reg/include/ECC_reg/tmr_registers.svh b/rtl/ECC_reg/include/ECC_reg/tmr_registers.svh new file mode 100644 index 00000000..3a26f2fd --- /dev/null +++ b/rtl/ECC_reg/include/ECC_reg/tmr_registers.svh @@ -0,0 +1,431 @@ +// Copyright 2021 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: Luca Rufer (lrufer@student.ethz.ch) + +`ifndef REDUNDANCY_CELLS_TMR_REGISTERS_SVH_ +`define REDUNDANCY_CELLS_TMR_REGISTERS_SVH_ + +// TMR protected Flip-Flop with asynchronous active-low reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFTMR(__name, __i, __rst_val, __o, __error, __clk, __arst_n) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b1), \ + .HasLoad (1'b0) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (__arst_n), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i (__rst_val), \ + .load_en_i (1'b0) \ +); + + +// TMR protected Flip-Flop with asynchronous active-high reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFARTMR(__name, __i, __rst_val, __o, __error, __clk, __arst) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b0), \ + .HasLoad (1'b0) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (~__arst), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i (__rst_val), \ + .load_en_i (1'b0) \ +); + +// TMR protected Flip-Flop with synchronous active-high reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFSRTMR(__name, __i, __rst_val, __o, __error, __clk, __reset_clk) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b0), \ + .ActiveLowReset (1'b0), \ + .HasLoad (1'b0) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (~__reset_clk), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i (__rst_val), \ + .load_en_i (1'b0) \ +); + +// TMR protected Flip-Flop with synchronous active-low reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFSRNTMR(__name, __i, __rst_val, __o, __error, __clk, __reset_n_clk) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b0), \ + .ActiveLowReset (1'b1), \ + .HasLoad (1'b0) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (__reset_n_clk), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i (__rst_val), \ + .load_en_i (1'b0) \ +); + +// TMR protected Always-enable Flip-Flop without reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __clk: clock input +`define FFNRTMR(__name, __i, __o, __error, __clk) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b0), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b1), \ + .HasLoad (1'b0) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (1'b0), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i ('0), \ + .load_en_i (1'b0) \ +); + +// TMR protected Flip-Flop with load-enable and asynchronous active-low reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define FFLTMR(__name, __i, __rst_val, __o, __error, __load, __clk, __arst_n) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b1), \ + .HasLoad (1'b1) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (__arst_n), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i (__rst_val), \ + .load_en_i (__load) \ +); + +// TMR protected Flip-Flop with load-enable and asynchronous active-high reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __arst: asynchronous reset, active-high +`define FFLARTMR(__name, __i, __rst_val, __o, __error, __load, __clk, __arst) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b0), \ + .HasLoad (1'b1) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (~__arst), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i (__rst_val), \ + .load_en_i (__load) \ +); + +// TMR protected Flip-Flop with load-enable and synchronous active-high reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_clk: reset input, active-high +`define FFLSRTMR(__name, __i, __rst_val, __o, __error, __load, __clk, __reset_clk) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b0), \ + .ActiveLowReset (1'b0), \ + .HasLoad (1'b1) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (~__reset_clk), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i (__rst_val), \ + .load_en_i (__load) \ +); + +// TMR protected Flip-Flop with load-enable and synchronous active-low reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __rst_val: Reset value of the FF. +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define FFLSRNTMR(__name, __i, __rst_val, __o, __error, __load, __clk, __reset_n_clk) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b0), \ + .ActiveLowReset (1'b1), \ + .HasLoad (1'b1) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (__reset_n_clk), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i (__rst_val), \ + .load_en_i (__load) \ +); + +// TMR protected Load-enable Flip-Flop without reset +// __name: Name of the TMR FF instance +// __i: data input (replaces D input for normal FFs). +// __o: data output (replaces Q output for normal FFs). +// __error: error output. if 1, detection unit found and corrected an error +// __load: encode __i and load it into FF. Otherwise, the old value is kept. +// __clk: clock input +`define FFLNRTMR(__name, __i, __o, __error, __load, __clk) \ +tmr_reg #( \ + .DataWidth ($bits(__i)), \ + .HasReset (1'b0), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b1), \ + .HasLoad (1'b1) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (1'b0), \ + .data_i (__i), \ + .data_o (__o), \ + .err_o (__error), \ + .reset_value_i ('0), \ + .load_en_i (__load) \ +); + +/***************************************************************************** + * DMR input and output, TMR protected FF * + *****************************************************************************/ + +// DMR input, TMR protected Flip-Flop with asynchronous active-low reset +// __name: Name of the TMR FF instance +// __i_1: first data input. +// __i_2: second data input. +// __rst_val: Reset value of the FF. +// __o_1: first voted data output. +// __o_2: second voted data output (voter is independant from __o_1). +// __dmr_err: signal indicting if input signals don't match. +// __no_load: input signal to prevent loading the new value into the FF +// should be tied to __dmr_err and other error signals. +// __vote_err: voter detected and corrected an error. +// __clk: clock input +// __arst_n: asynchronous reset, active-low +`define DMRFFTMR(__name, __i_1, __i_2, __rst_val, __o_1, __o_2, __dmr_err, __no_load, __vote_err, __clk, __arst_n) \ +dmr_io_tmr_reg #( \ + .DataWidth ($bits(__i_1)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b1) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (__arst_n), \ + .data_1_i (__i_1), \ + .data_2_i (__i_2), \ + .data_1_o (__o_1), \ + .data_2_o (__o_2), \ + .dmr_err_o (__dmr_err), \ + .no_load_i (__no_load), \ + .voter_err_o (__vote_err), \ + .reset_value_i (__rst_val) \ +); + + +// DMR input, TMR protected Flip-Flop with asynchronous active-high reset +// __name: Name of the TMR FF instance +// __i_1: first data input. +// __i_2: second data input. +// __rst_val: Reset value of the FF. +// __o_1: first voted data output. +// __o_2: second voted data output (voter is independant from __o_1). +// __dmr_err: signal indicting if input signals don't match. +// __no_load: input signal to prevent loading the new value into the FF +// should be tied to __dmr_err and other error signals. +// __vote_err: voter detected and corrected an error. +// __clk: clock input +// __arst: asynchronous reset, active-high +`define DMRFFARTMR(__name, __i_1, __i_2, __rst_val, __o_1, __o_2, __dmr_err, __no_load, __vote_err, __clk, __arst) \ +dmr_io_tmr_reg #( \ + .DataWidth ($bits(__i_1)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b0) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (~__arst), \ + .data_1_i (__i_1), \ + .data_2_i (__i_2), \ + .data_1_o (__o_1), \ + .data_2_o (__o_2), \ + .dmr_err_o (__dmr_err), \ + .no_load_i (__no_load), \ + .voter_err_o (__vote_err), \ + .reset_value_i (__rst_val) \ +); + +// DMR input, TMR protected Flip-Flop with synchronous active-high reset +// __name: Name of the TMR FF instance +// __i_1: first data input. +// __i_2: second data input. +// __rst_val: Reset value of the FF. +// __o_1: first voted data output. +// __o_2: second voted data output (voter is independant from __o_1). +// __dmr_err: signal indicting if input signals don't match. +// __no_load: input signal to prevent loading the new value into the FF +// should be tied to __dmr_err and other error signals. +// __vote_err: voter detected and corrected an error. +// __clk: clock input +// __reset_clk: reset input, active-high +`define DMRFFSRTMR(__name, __i_1, __i_2, __rst_val, __o_1, __o_2, __dmr_err, __no_load, __vote_err, __clk, __reset_clk) \ +dmr_io_tmr_reg #( \ + .DataWidth ($bits(__i_1)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b0), \ + .ActiveLowReset (1'b0) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (~__reset_clk), \ + .data_1_i (__i_1), \ + .data_2_i (__i_2), \ + .data_1_o (__o_1), \ + .data_2_o (__o_2), \ + .dmr_err_o (__dmr_err), \ + .no_load_i (__no_load), \ + .voter_err_o (__vote_err), \ + .reset_value_i (__rst_val) \ +); + +// DMR input, TMR protected Flip-Flop with synchronous active-low reset +// __name: Name of the TMR FF instance +// __i_1: first data input. +// __i_2: second data input. +// __rst_val: Reset value of the FF. +// __o_1: first voted data output. +// __o_2: second voted data output (voter is independant from __o_1). +// __dmr_err: signal indicting if input signals don't match. +// __no_load: input signal to prevent loading the new value into the FF +// should be tied to __dmr_err and other error signals. +// __vote_err: voter detected and corrected an error. +// __clk: clock input +// __reset_n_clk: reset input, active-low +`define DMRFFSRNTMR(__name, __i_1, __i_2, __rst_val, __o_1, __o_2, __dmr_err, __no_load, __vote_err, __clk, __reset_n_clk) \ +dmr_io_tmr_reg #( \ + .DataWidth ($bits(__i_1)), \ + .HasReset (1'b1), \ + .AsynchronousReset (1'b0), \ + .ActiveLowReset (1'b1) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (__reset_n_clk), \ + .data_1_i (__i_1), \ + .data_2_i (__i_2), \ + .data_1_o (__o_1), \ + .data_2_o (__o_2), \ + .dmr_err_o (__dmr_err), \ + .no_load_i (__no_load), \ + .voter_err_o (__vote_err), \ + .reset_value_i (__rst_val) \ +); + +// DMR input, TMR protected Always-enable Flip-Flop without reset +// __name: Name of the TMR FF instance +// __i_1: first data input. +// __i_2: second data input. +// __o_1: first voted data output. +// __o_2: second voted data output (voter is independant from __o_1). +// __dmr_err: signal indicting if input signals don't match. +// __no_load: input signal to prevent loading the new value into the FF +// should be tied to __dmr_err and other error signals. +// __vote_err: voter detected and corrected an error. +// __clk: clock input +`define DMRFFNRTMR(__name, __i_1, __i_2, __o_1, __o_2, __dmr_err, __no_load, __vote_err, __clk) \ +dmr_io_tmr_reg #( \ + .DataWidth ($bits(__i_1)), \ + .HasReset (1'b0), \ + .AsynchronousReset (1'b1), \ + .ActiveLowReset (1'b1) \ +) __name ( \ + .clk_i (__clk), \ + .rst_ni (1'b0), \ + .data_1_i (__i_1), \ + .data_2_i (__i_2), \ + .data_1_o (__o_1), \ + .data_2_o (__o_2), \ + .dmr_err_o (__dmr_err), \ + .no_load_i (__no_load), \ + .voter_err_o (__vote_err), \ + .reset_value_i ('0) \ +); + +`endif diff --git a/rtl/ECC_reg/tmr_reg.sv b/rtl/ECC_reg/tmr_reg.sv new file mode 100644 index 00000000..1407abb4 --- /dev/null +++ b/rtl/ECC_reg/tmr_reg.sv @@ -0,0 +1,96 @@ +// 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. + +// Description: Flipflop with TMR protection and integrated voter +// Hint: Use the macros in 'tmr_registers.svh' instead of using this module directly. + +`include "common_cells/registers.svh" + +module tmr_reg #( + // Data Settings + parameter int unsigned DataWidth = 0, + // FF Settings + parameter bit HasReset = 1, + parameter bit AsynchronousReset = 1, + parameter bit ActiveLowReset = 1, + parameter bit HasLoad = 0 +) ( + // Clock and reset + input logic clk_i, + input logic rst_ni, + // Data + input logic[DataWidth-1:0] data_i, + output logic[DataWidth-1:0] data_o, + output logic err_o, + // FF ports + input logic[DataWidth-1:0] reset_value_i, + input logic load_en_i +); + +logic [3*DataWidth-1:0] data_d, data_q, reset_value; + +/******************* + * Encode Data * + *******************/ + +assign data_d = {3{data_i}}; +assign reset_value = {3{reset_value_i}}; + +/***************** + * Flip-Flop * + *****************/ + +logic rst; +assign rst = ~rst_ni; + +if ( HasReset && AsynchronousReset && ActiveLowReset && ~HasLoad) begin + `FF(data_q, data_d, reset_value, clk_i, rst_ni) +end else if ( HasReset && AsynchronousReset && ~ActiveLowReset && ~HasLoad) begin + `FFAR(data_q, data_d, reset_value, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ~ActiveLowReset && ~HasLoad) begin + `FFSR(data_q, data_d, reset_value, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ActiveLowReset && ~HasLoad) begin + `FFSRN(data_q, data_d, reset_value, clk_i, rst_ni) +end else if ( ~HasReset && ~HasLoad) begin + `FFNR(data_q, data_d, clk_i) +end else if ( HasReset && AsynchronousReset && ActiveLowReset && HasLoad) begin + `FFL(data_q, data_d, load_en_i, reset_value, clk_i, rst_ni) +end else if ( HasReset && AsynchronousReset && ~ActiveLowReset && HasLoad) begin + `FFLAR(data_q, data_d, load_en_i, reset_value, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ~ActiveLowReset && HasLoad) begin + `FFLSR(data_q, data_d, load_en_i, reset_value, clk_i, rst) +end else if ( HasReset && ~AsynchronousReset && ActiveLowReset && HasLoad) begin + `FFLSRN(data_q, data_d, load_en_i, reset_value, clk_i, rst_ni) +end else if ( ~HasReset && HasLoad) begin + `FFLNR(data_q, data_d, load_en_i, clk_i) +end + +/******************* + * Decode Data * + *******************/ + +logic [DataWidth-1:0] data_a, data_b, data_c, diff_ab, diff_bc, sel; + +assign data_a = data_q[0*DataWidth+:DataWidth]; +assign data_b = data_q[1*DataWidth+:DataWidth]; +assign data_c = data_q[2*DataWidth+:DataWidth]; + +assign diff_ab = data_a ^ data_b; +assign diff_bc = data_b ^ data_c; + +assign sel = diff_ab & ~diff_bc; + +for (genvar i = 0; i < DataWidth; i++) begin : sel_out + assign data_o[i] = sel[i] ? data_c[i] : data_a[i]; +end + +assign err_o = |(diff_ab | diff_bc); + +endmodule diff --git a/rtl/dmr/DMR_handshake_fork.sv b/rtl/dmr/DMR_handshake_fork.sv new file mode 100644 index 00000000..2679fbe5 --- /dev/null +++ b/rtl/dmr/DMR_handshake_fork.sv @@ -0,0 +1,196 @@ +// Copyright 2023 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: Luca Rufer + +/// Fork some handshaked data from a single source to multiple desinations. +/// All destinations must recieve the same output signals, but may provide +/// different input signals (only due to fault-induced errors, not by design). +/// This module makes sure all handshakes with the source are correctly handled, +/// and every transaction is completed exactly once without errors with every +/// destination. +/// +/// This module has three different error signals. Their effects are described +/// below: +/// - 'error_before_i': Error in the logic before the module (with respect to +/// the 'ready_i' signals of the destinations). +/// Some other logic block detected an error, which makes the 'ready_i' +/// signals (from the destination) that are supplied here unreliable. +/// The module will ignore the 'ready_i' signals from the destinations and +/// maintain the 'ready_o' signal (to the source) the from the previous cycle. +/// - 'error_o': The Module detected a mismatch in the 'ready_i' signals. +/// This has the same effect as an asserted 'error_before_i' signal. +/// - 'error_after_i': Some logic that depends on the destination output signals +/// of this module detected an error/mismatch, and the current cycle must be +/// repeated. When this signal is asserted and there was a completed handshake +/// on the destination side, this module will repeat the completed transaction +/// in the next clock cycle. +/// The 'error_after_i' signal does not affect the handshake signals, it only +/// effects the modules' internal state. This is done to prevent combinatorial +/// loops and reduce the critical timing path. +/// +/// If the 'enable_i' signal is high, the module behaves as described above. +/// If it is low, the checking features of the module are disabled: +/// - Incomming error signals are ignored +/// - The outgoing 'error_o' signal will always be 0 +/// - Handshakes will only be completed with destination 0. While all +/// desitinations still receive the same data via 'data_o', only the valid +/// signal of destination 0 is used, all other valid signals are set to 0. +/// Equally, only the ready signal of destination 0 is used to complete the +/// handshake, all other ready signals are ignored. +/// It is in the responsibility of the user to make sure a change in the +/// 'enable_i' signal will not violate any handshake rules. + +module dmr_handshake_fork #( + parameter type T = logic, + parameter int NUM_OUT = 2 +)( + // clock and reset + input logic clk_i, + input logic rst_ni, + // enable signal + input logic enable_i, + // error signals + input logic error_before_i, + input logic error_after_i, + output logic error_o, + // data source + input logic valid_i, + output logic ready_o, + input T data_i, + // data destination + output logic [NUM_OUT-1:0] valid_o, + input logic [NUM_OUT-1:0] ready_i, + output T [NUM_OUT-1:0] data_o +); + + // state signals + logic ready_d, ready_q; + logic data_latched_d, data_latched_q; + T data_d, data_q; + + // intermediate signals + logic source_hs_complete, dest_hs_complete; + + // check if handshakes completed + assign source_hs_complete = ready_o & valid_i; + assign dest_hs_complete = &(ready_i & valid_o) & ~error_after_i & ~error_before_i; + + // -------------------- + // Output signals + // -------------------- + + always_comb begin + // check if module is enabled + if(enable_i) begin + // Destination + for (int unsigned i = 0; i < NUM_OUT; i++) begin + valid_o[i] = valid_i | data_latched_q; + data_o[i] = (data_latched_q) ? data_q : data_i; + end + + // Source + ready_o = (ready_q | (&ready_i & ~error_before_i)) & ~data_latched_q; + + // Error + error_o = ~((&ready_i) | (ready_i == '0)); + + end else begin + // Destination + valid_o = '0; + valid_o[0] = valid_i; + data_o = {NUM_OUT{data_i}}; + + // Source + ready_o = ready_i[0]; + + // Error + error_o = 1'b0; + end + end + + // -------------------- + // Compute next state + // -------------------- + + // Ready signal (dest -> source) + always_comb begin + // default state + ready_d = ready_q; + // set ready signals if all destinations are ready, and no error + if (&ready_i & !error_before_i) begin + ready_d = 1'b1; + end + // clear ready signal if handshake is completed with source + if (source_hs_complete) begin + ready_d = 1'b0; + end + // Clear state if fork is disabled + if (!enable_i) begin + ready_d = 1'b0; + end + end + + // Data (source -> dest) + always_comb begin + // default state + data_latched_d = data_latched_q; + data_d = data_q; + // if handshake with source is complete, but destination is not, then latch data + if (source_hs_complete & ~dest_hs_complete) begin + data_latched_d = 1'b1; + data_d = data_i; + end + // if handshake with destination is complete, clear data + if (dest_hs_complete) begin + data_latched_d = 1'b0; + end + // Clear state if fork is disabled + if (!enable_i) begin + data_latched_d = 1'b0; + end + end + + // -------------------- + // State + // -------------------- + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + ready_q <= '0; + data_latched_q <= '0; + data_q <= '0; + end else begin + ready_q <= ready_d; + data_latched_q <= data_latched_d; + data_q <= data_d; + end + end + + // -------------------- + // Assertions + // -------------------- + + // pragma translate_off + `ifndef VERILATOR + // Source handshake assertions + source_valid: assert property( @(posedge clk_i) disable iff (~rst_ni) + (valid_i & ~ready_o |=> valid_i)) else + $fatal(1, "Deasserted valid before complete source handshake."); + source_data: assert property( @(posedge clk_i) disable iff (~rst_ni) + (valid_i & ~ready_o |=> $stable(data_i))) else + $fatal(1, "Unstable data before complete source handshake."); + dest_ready: assert property( @(posedge clk_i) disable iff (~rst_ni) + ((enable_i & error_after_i & ~error_before_i & ~error_o |=> $stable(ready_i)))) else + $warning("Ready signals were modified during a repetition cycle."); + `endif + // pragma translate_on + +endmodule diff --git a/rtl/dmr/DMR_handshake_join.sv b/rtl/dmr/DMR_handshake_join.sv new file mode 100644 index 00000000..f67650fa --- /dev/null +++ b/rtl/dmr/DMR_handshake_join.sv @@ -0,0 +1,239 @@ +// Copyright 2023 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: Luca Rufer + +/// Join handshaked data from multiple sources to a single desination. +/// All sources must recieve the same ready signal from the destination, but +/// may provide different input signals (only due to fault-induced errors, +/// not by design). +/// This module makes sure all handshakes with the destination are correctly +/// handled. Transaction with the source are only done when all sources agree +/// on the same data and valid signals, and every transaction is completed +/// exactly once. +/// +/// This module has three different error signals. Their effects are described +/// below: +/// - 'error_before_i': Error before the module. +/// Some other logic block detected an error, which makes the source signals +/// (data_i and valid_i) unreliable. +/// The module will ignore the 'valid_i' signals from the sources and maintain +/// the 'valid_o' and 'data_o' signals (to the destination) from the +/// previous cycle (except if the handshake on the destination side was +/// completed, in wich case the 'valid_o' signal is pulled low afterwards). +/// - 'error_o': The Module detected a mismatch in the 'valid_i' signals, or +/// a mismatch in the 'data_i' signals while all 'valid_i' signals were +/// active. +/// This has the same effect as an asserted 'error_before_i' signal. +/// - 'error_after_i': Some logic that depends on the destination output signals +/// of this module ('ready_o') detected an error/mismatch, and the current +/// cycle must be repeated to correctly handle the ready_o signals. +/// This module makes sure that if a transaction was completed in the same +/// cycle as the 'error_after_i' signal is active, no transaction will be +/// issued during the repetition cycle, so that the same transaction is not +/// issued twice. Note that completing a transaction during a cycle with an +/// 'after error' and trying to complete another transaction during the +/// repetition cycle will result in the second transaction not being +/// completed! +/// The 'error_after_i' signal does not affect the handshake signals, it only +/// effects the modules' internal state. This is done to prevent combinatorial +/// loops and reduce the critical timing path. +/// +/// If the 'enable_i' signal is high, the module behaves as described above. +/// If it is low, the checking features of the module are disabled: +/// - Incomming error signals are ignored +/// - The outgoing 'error_o' signal will always be 0 +/// - Handshakes will only be completed with source 0. 'data_o' and 'valid_o' +/// will only show the data and valid signals from source 0, regardless if +/// they match the data and valid signals from the other sources. Equally, +/// The ready signal from the destination will only be forwarded to source 0, +/// the 'ready_o' signals of all other sources are set to 0. +/// It is in the responsibility of the user to make sure a change in the +/// 'enable_i' signal will not violate any handshake rules. + +module dmr_handshake_join #( + parameter type T = logic, + parameter int NUM_IN = 2 +)( + // clock and reset + input logic clk_i, + input logic rst_ni, + // enable signal + input logic enable_i, + // error signals + input logic error_before_i, + input logic error_after_i, + output logic error_o, + // data source + input logic [NUM_IN-1:0] valid_i, + output logic [NUM_IN-1:0] ready_o, + input T [NUM_IN-1:0] data_i, + // data destination + output logic valid_o, + input logic ready_i, + output T data_o +); + + // state signals + logic valid_d, valid_q; + logic repeat_ready_d, repeat_ready_q; + logic error_after_d, error_after_q; + T data_d, data_q; + + // intermediate signals + logic source_hs_complete, dest_hs_complete; + + // check if handshakes complete + assign dest_hs_complete = ready_i & valid_o; + assign source_hs_complete = &(ready_o & valid_i) & ~error_after_i & ~error_o & ~error_before_i; + + // -------------------- + // Output signals + // -------------------- + + // Destination + always_comb begin + valid_o = valid_i[0]; + data_o = data_i[0]; + if(enable_i) begin + if (error_after_q) begin + valid_o = valid_i[0] | valid_q; + end + if (error_before_i | error_o) begin + valid_o = valid_q; + data_o = data_q; + end + if (repeat_ready_q) begin + valid_o = 1'b0; + end + end + end + + // Source + always_comb begin + if (enable_i) begin + for(int unsigned i = 0; i < NUM_IN; i++) begin + ready_o[i] = ready_i | repeat_ready_q; + end + end else begin + ready_o = '0; + ready_o[0] = ready_i; + end + end + + // Error + always_comb begin + error_o = error_before_i; + // check if all valid signals agree + if(~((&valid_i) | (valid_i == '0))) begin + error_o = 1'b1; + end + // check if valid signals were revoked + if(valid_q & ~(&valid_i)) begin + error_o = 1'b1; + end + // if valid, check if all data inputs match + if(&valid_i) begin + for(int unsigned i = 1; i < NUM_IN; i++) begin + if(data_i[i] != data_i[i-1]) begin + error_o = 1'b1; + end + end + end + // if module is disabled, no error is generated + if (!enable_i) begin + error_o = 1'b0; + end + end + + // -------------------- + // Compute next state + // -------------------- + + // Valid and Data signals (sources -> dest) + always_comb begin + // default state + valid_d = valid_o; + data_d = data_o; + // set valid signal if all sources are valid, and no error before or detected + if (&valid_i & !error_before_i & !error_o & !error_after_q) begin + valid_d = 1'b1; + data_d = data_i[0]; + end + // clear valid signal if handshake is completed with destination + if (dest_hs_complete | repeat_ready_q) begin + valid_d = 1'b0; + end + // Clear state if join is disabled + if (!enable_i) begin + valid_d = 1'b0; + end + end + + // Ready (dest -> sources) + always_comb begin + // default state + repeat_ready_d = repeat_ready_q; + // if handshake with source is complete, but destination is not, then latch data + if (dest_hs_complete & ~source_hs_complete) begin + repeat_ready_d = 1'b1; + end + // if handshake with destination is complete, clear data + if (source_hs_complete) begin + repeat_ready_d = 1'b0; + end + // Clear state if join is disabled + if (!enable_i) begin + repeat_ready_d = 1'b0; + end + end + + // Internal + always_comb begin + error_after_d = error_after_i & !(error_o | error_before_i); + + // Clear state if join is disabled + if (!enable_i) begin + error_after_d = 1'b0; + end + end + + // -------------------- + // State + // -------------------- + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + valid_q <= '0; + repeat_ready_q <= '0; + error_after_q <= '0; + data_q <= '0; + end else begin + valid_q <= valid_d; + repeat_ready_q <= repeat_ready_d; + error_after_q <= error_after_d; + data_q <= data_d; + end + end + + // -------------------- + // Assertions + // -------------------- + + // pragma translate_off + `ifndef VERILATOR + // Destination handshake assertions + dest_ready: assert property( @(posedge clk_i) disable iff (~rst_ni) + (ready_i & ~valid_o |=> ready_i)) else + $fatal(1, "Deasserted ready before complete destination handshake."); + `endif + // pragma translate_on + +endmodule diff --git a/rtl/dmr/DMR_instr_join_fork.sv b/rtl/dmr/DMR_instr_join_fork.sv new file mode 100644 index 00000000..6bf06b51 --- /dev/null +++ b/rtl/dmr/DMR_instr_join_fork.sv @@ -0,0 +1,82 @@ +// Copyright 2022 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. +// +// Luca Rufer + + +/// This module joins the instruction addresses of multiple sources. If they +/// match, then the requested instruction address is given to the output +/// (normally the ICache). The instruction data is distributed to all sources, +/// along with the ready signals 'ready_o' that indicate if the instruction +/// data is valid. +/// +/// This module assumes that the source is always ready to accept the +/// instruction data and thus there is no ready signal for the instuction data. +/// The valid signal for the instruction data is combined with the ready signal +/// for the instruction address. +/// +/// All instruction requests are processed if the addresses from the sources +/// match. If the addresses don't match while the valid signals are active, or +/// the valid signals of the sources don't agree, an error signal is generated. +/// This module dones not offer a way to repreat the request. The request +/// can simply be repeated by applying the same address in the next cycle. + +module dmr_instr_join_fork #( + parameter type addr_t = logic, + parameter type data_t = logic, + parameter int NUM_IN = 2 +)( + input logic clk_i, + input logic rst_ni, + output logic error_o, + input logic error_ext_i, + // address source + input logic [NUM_IN-1:0] valid_i, + output logic [NUM_IN-1:0] ready_o, + input addr_t [NUM_IN-1:0] addr_i, + output data_t [NUM_IN-1:0] data_o, + // data source + output logic valid_o, + input logic ready_i, + output addr_t addr_o, + input data_t data_i +); + + addr_t addr_q; + logic valid_q; + + assign addr_o = (error_o | error_ext_i) ? addr_q : addr_i[0]; + assign valid_o = (error_o | error_ext_i) ? valid_q : valid_i[0]; + assign data_o = {NUM_IN{data_i}}; + assign ready_o = {NUM_IN{ready_i}}; + + always_comb begin + error_o = 1'b0; + // output comparator logic + for(int i = 1; i < NUM_IN; i++) begin + if(addr_i[i] != addr_i[i-1] || valid_i[i] != valid_i[i-1]) begin + error_o = 1'b1; + end + end + end + + // addr store update + always_ff @(posedge (clk_i) or negedge (rst_ni)) begin + if (!rst_ni) begin + addr_q <= '0; + valid_q <= '0; + end else begin + addr_q <= addr_o; + valid_q <= valid_o; + end + end + +endmodule diff --git a/rtl/dmr/DMR_interrupt_fork.sv b/rtl/dmr/DMR_interrupt_fork.sv new file mode 100644 index 00000000..dfdc7e0c --- /dev/null +++ b/rtl/dmr/DMR_interrupt_fork.sv @@ -0,0 +1,90 @@ +// Copyright 2023 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: Luca Rufer + +/// Fork a interrupt signal from a single source to multiple desinations. +/// The interrupt signal is directly forwarded the to all destinations. If an +/// error happenes in the receiving circuit, and the interrupt signal cannot be +/// handled, the external circuit can raise the 'repeat_i' signal. If the +/// interrupt signal was high in the cycle where 'repeat_i' was asserted, then +/// the interrupt signal will be repeated in the next clock cycle. + +/// Interrupt signals are assumed to be active high and only asserted for a +/// single cycle. +/// This module can only handle a single outstanding interrupt at the time. + +/// The internal state is TMR-protected, so SEUs cannot trigger an interrupt +/// by accident. All outputs have individual voters to protect agaist common- +/// mode SETs + +module dmr_interrupt_fork #( + parameter int NUM_OUT = 2 +)( + // clock and reset + input logic clk_i, + input logic rst_ni, + // repeat signals + input logic repeat_i, + // interrupt signals + input logic interrupt_i, + output logic [NUM_OUT-1:0] interrupt_o +); + + // state signals (TMR protected) + logic [2:0] outstanding_interrupt_d, outstanding_interrupt_q; + + // Other signals + logic [NUM_OUT-1:0] outstanding_interrupt_voted; + + // Compute next state + always_comb begin + outstanding_interrupt_d = '0; + if (repeat_i) begin + outstanding_interrupt_d = {3{interrupt_i}} | outstanding_interrupt_q; + end + end + + // State + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + outstanding_interrupt_q <= '0; + end else begin + outstanding_interrupt_q <= outstanding_interrupt_d; + end + end + + for (genvar i = 0; i < NUM_OUT; i++) begin : gen_voters + TMR_voter i_vote ( + .a_i (outstanding_interrupt_q[0]), + .b_i (outstanding_interrupt_q[1]), + .c_i (outstanding_interrupt_q[2]), + .majority_o (outstanding_interrupt_voted[i]) + ); + end + + // Generate output signals + assign interrupt_o = {NUM_OUT{interrupt_i}} | outstanding_interrupt_voted; + + // -------------------- + // Warnings + // -------------------- + + // pragma translate_off + `ifndef VERILATOR + // Source handshake assertions + interrupt_overrun: assert property( @(posedge clk_i) disable iff (~rst_ni) + (~(interrupt_i & &outstanding_interrupt_q))) else + $warning("Interrupt Overrun."); + `endif + // pragma translate_on + +endmodule diff --git a/rtl/dmr/DMR_write_mux.sv b/rtl/dmr/DMR_write_mux.sv new file mode 100644 index 00000000..bf5fa8b7 --- /dev/null +++ b/rtl/dmr/DMR_write_mux.sv @@ -0,0 +1,81 @@ +// Copyright 2021 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. + +// Description: This module is used to apply DMR to the following circuit: +// A Table of N Elements of M bits each, where only one element +// can be written at the time. +// The DMR write protection uses two write-data (M bits each) and +// two write-enable inputs (N bits each). These signals are +// supposed to be generated independently (DMR). +// The 'dmr_error_o' signal indicates if there is a mismatch in the +// write-data or the write-enable data between the two inputs. +// The 'write_i' signal controls if the write is executed. This +// signal is supposed to be a combination of the 'dmr_error_o' +// signal and other error signals. It can also be used to force a +// write when DMR checking is to be disabled. When writing is +// forced, the data in we signals from port 1 are used. + +// Vulnerability to Single Event Transients (SETs): +// This module is designed to protect a design against single event transients. +// While this module is designed to protect agains SETs occuring in the +// combinatorial logic that generate the write-data and write-enable signals, +// it still has some internal vulnerabilities: +// - The AND gates that check the write-enable signals (including any buffers +// in the 'write_i' signal and at the output of the AND gates) are vulnerable +// to SETs. This cannot be prevented, as a single error signal needs to +// influence M*N MUX2 gates and this large fan-out requires buffers to be +// inserted, which in turn are vulnerable to SETs. +// - The MUXes that control the data flow (and all buffers on the incomming +// signals) are also vulnerable to SETs if the data is not encoded. +// Using Single Error Correction (SEC) encoded data (e.g. Hamming code or +// TMR) offers an easy way to protect the data path and the MUXes agains SETs. +// This module offers a trade-off between Area-overhead and vulnerability. +// The vulnerability could be reduced by applying TMR to the 'write_i' tree, +// and voting every single of the N*M MUX2 control signals. + +module DMR_write_mux #( + parameter type data_t = logic, + parameter int unsigned NumDataItems = 1 +) ( + // Data Ports + input data_t [NumDataItems-1:0] data_i, + output data_t [NumDataItems-1:0] data_o, + // Write Ports + input data_t wdata_1_i, + input data_t wdata_2_i, + input logic [NumDataItems-1:0] wen_1_i, + input logic [NumDataItems-1:0] wen_2_i, + // Error & Control Signals + output logic dmr_error_o, + input logic write_i +); + +// Internal signals +logic wdata_error, wen_error; +logic [NumDataItems-1:0] wen; +data_t [NumDataItems-1:0] wdata_expanded; + +// Error checking +assign wdata_error = (wdata_1_i != wdata_2_i); +assign wen_error = (wen_1_i != wen_2_i); +assign dmr_error_o = wdata_error | wen_error; + +// Write signal masking (Vulnerable) +assign wen = wen_1_i & {NumDataItems{write_i}}; + +// Input signal distribution (Vulnerable if not ECC protected) +assign wdata_expanded = {NumDataItems{wdata_1_i}}; + +// Write multiplexing (Vulnerable if not ECC protected) +for (genvar i = 0; i < NumDataItems; i++) begin + assign data_o[i] = wen[i] ? wdata_expanded[i] : data_i[i]; +end + +endmodule diff --git a/rtl/lowrisc_ecc/prim_secded_128_120_cor.sv b/rtl/lowrisc_ecc/prim_secded_128_120_cor.sv new file mode 100644 index 00000000..1a74c379 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_128_120_cor.sv @@ -0,0 +1,162 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 8 -k 120 -s 1592631616 -c hsiao + +module prim_secded_128_120_cor ( + input [127:0] d_i, + output logic [127:0] d_o, + output logic [7:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 128'h017F000007FFFFFFFF000000001FFFFF); + assign syndrome_o[1] = ^(d_i & 128'h02BF03FFF8000FFFFF00000FFFE0003F); + assign syndrome_o[2] = ^(d_i & 128'h04DF7C1FF83FF003FF003FF003E007C1); + assign syndrome_o[3] = ^(d_i & 128'h08EFBDE1FBC3F0FC0F0FC0F03C207842); + assign syndrome_o[4] = ^(d_i & 128'h10F7DEEE3DDC771C7171C711C4438884); + assign syndrome_o[5] = ^(d_i & 128'h20FBEF76CEED9B6592B65926488C9108); + assign syndrome_o[6] = ^(d_i & 128'h40FDF7BB5776ADAAA4DAAA4A91152210); + assign syndrome_o[7] = ^(d_i & 128'h80FEFBDDA7BB4ED348ED348D221A4420); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 8'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 8'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 8'h13) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 8'h23) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 8'h43) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 8'h83) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 8'hd) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 8'h15) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 8'h25) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 8'h45) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 8'h85) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 8'h19) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 8'h29) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 8'h49) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 8'h89) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 8'h31) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 8'h51) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 8'h91) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 8'h61) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 8'ha1) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 8'hc1) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 8'he) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 8'h16) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 8'h26) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 8'h46) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 8'h86) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 8'h1a) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 8'h2a) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 8'h4a) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 8'h8a) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 8'h32) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 8'h52) ^ d_i[31]; + assign d_o[32] = (syndrome_o == 8'h92) ^ d_i[32]; + assign d_o[33] = (syndrome_o == 8'h62) ^ d_i[33]; + assign d_o[34] = (syndrome_o == 8'ha2) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 8'hc2) ^ d_i[35]; + assign d_o[36] = (syndrome_o == 8'h1c) ^ d_i[36]; + assign d_o[37] = (syndrome_o == 8'h2c) ^ d_i[37]; + assign d_o[38] = (syndrome_o == 8'h4c) ^ d_i[38]; + assign d_o[39] = (syndrome_o == 8'h8c) ^ d_i[39]; + assign d_o[40] = (syndrome_o == 8'h34) ^ d_i[40]; + assign d_o[41] = (syndrome_o == 8'h54) ^ d_i[41]; + assign d_o[42] = (syndrome_o == 8'h94) ^ d_i[42]; + assign d_o[43] = (syndrome_o == 8'h64) ^ d_i[43]; + assign d_o[44] = (syndrome_o == 8'ha4) ^ d_i[44]; + assign d_o[45] = (syndrome_o == 8'hc4) ^ d_i[45]; + assign d_o[46] = (syndrome_o == 8'h38) ^ d_i[46]; + assign d_o[47] = (syndrome_o == 8'h58) ^ d_i[47]; + assign d_o[48] = (syndrome_o == 8'h98) ^ d_i[48]; + assign d_o[49] = (syndrome_o == 8'h68) ^ d_i[49]; + assign d_o[50] = (syndrome_o == 8'ha8) ^ d_i[50]; + assign d_o[51] = (syndrome_o == 8'hc8) ^ d_i[51]; + assign d_o[52] = (syndrome_o == 8'h70) ^ d_i[52]; + assign d_o[53] = (syndrome_o == 8'hb0) ^ d_i[53]; + assign d_o[54] = (syndrome_o == 8'hd0) ^ d_i[54]; + assign d_o[55] = (syndrome_o == 8'he0) ^ d_i[55]; + assign d_o[56] = (syndrome_o == 8'h1f) ^ d_i[56]; + assign d_o[57] = (syndrome_o == 8'h2f) ^ d_i[57]; + assign d_o[58] = (syndrome_o == 8'h4f) ^ d_i[58]; + assign d_o[59] = (syndrome_o == 8'h8f) ^ d_i[59]; + assign d_o[60] = (syndrome_o == 8'h37) ^ d_i[60]; + assign d_o[61] = (syndrome_o == 8'h57) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 8'h97) ^ d_i[62]; + assign d_o[63] = (syndrome_o == 8'h67) ^ d_i[63]; + assign d_o[64] = (syndrome_o == 8'ha7) ^ d_i[64]; + assign d_o[65] = (syndrome_o == 8'hc7) ^ d_i[65]; + assign d_o[66] = (syndrome_o == 8'h3b) ^ d_i[66]; + assign d_o[67] = (syndrome_o == 8'h5b) ^ d_i[67]; + assign d_o[68] = (syndrome_o == 8'h9b) ^ d_i[68]; + assign d_o[69] = (syndrome_o == 8'h6b) ^ d_i[69]; + assign d_o[70] = (syndrome_o == 8'hab) ^ d_i[70]; + assign d_o[71] = (syndrome_o == 8'hcb) ^ d_i[71]; + assign d_o[72] = (syndrome_o == 8'h73) ^ d_i[72]; + assign d_o[73] = (syndrome_o == 8'hb3) ^ d_i[73]; + assign d_o[74] = (syndrome_o == 8'hd3) ^ d_i[74]; + assign d_o[75] = (syndrome_o == 8'he3) ^ d_i[75]; + assign d_o[76] = (syndrome_o == 8'h3d) ^ d_i[76]; + assign d_o[77] = (syndrome_o == 8'h5d) ^ d_i[77]; + assign d_o[78] = (syndrome_o == 8'h9d) ^ d_i[78]; + assign d_o[79] = (syndrome_o == 8'h6d) ^ d_i[79]; + assign d_o[80] = (syndrome_o == 8'had) ^ d_i[80]; + assign d_o[81] = (syndrome_o == 8'hcd) ^ d_i[81]; + assign d_o[82] = (syndrome_o == 8'h75) ^ d_i[82]; + assign d_o[83] = (syndrome_o == 8'hb5) ^ d_i[83]; + assign d_o[84] = (syndrome_o == 8'hd5) ^ d_i[84]; + assign d_o[85] = (syndrome_o == 8'he5) ^ d_i[85]; + assign d_o[86] = (syndrome_o == 8'h79) ^ d_i[86]; + assign d_o[87] = (syndrome_o == 8'hb9) ^ d_i[87]; + assign d_o[88] = (syndrome_o == 8'hd9) ^ d_i[88]; + assign d_o[89] = (syndrome_o == 8'he9) ^ d_i[89]; + assign d_o[90] = (syndrome_o == 8'hf1) ^ d_i[90]; + assign d_o[91] = (syndrome_o == 8'h3e) ^ d_i[91]; + assign d_o[92] = (syndrome_o == 8'h5e) ^ d_i[92]; + assign d_o[93] = (syndrome_o == 8'h9e) ^ d_i[93]; + assign d_o[94] = (syndrome_o == 8'h6e) ^ d_i[94]; + assign d_o[95] = (syndrome_o == 8'hae) ^ d_i[95]; + assign d_o[96] = (syndrome_o == 8'hce) ^ d_i[96]; + assign d_o[97] = (syndrome_o == 8'h76) ^ d_i[97]; + assign d_o[98] = (syndrome_o == 8'hb6) ^ d_i[98]; + assign d_o[99] = (syndrome_o == 8'hd6) ^ d_i[99]; + assign d_o[100] = (syndrome_o == 8'he6) ^ d_i[100]; + assign d_o[101] = (syndrome_o == 8'h7a) ^ d_i[101]; + assign d_o[102] = (syndrome_o == 8'hba) ^ d_i[102]; + assign d_o[103] = (syndrome_o == 8'hda) ^ d_i[103]; + assign d_o[104] = (syndrome_o == 8'hea) ^ d_i[104]; + assign d_o[105] = (syndrome_o == 8'hf2) ^ d_i[105]; + assign d_o[106] = (syndrome_o == 8'h7c) ^ d_i[106]; + assign d_o[107] = (syndrome_o == 8'hbc) ^ d_i[107]; + assign d_o[108] = (syndrome_o == 8'hdc) ^ d_i[108]; + assign d_o[109] = (syndrome_o == 8'hec) ^ d_i[109]; + assign d_o[110] = (syndrome_o == 8'hf4) ^ d_i[110]; + assign d_o[111] = (syndrome_o == 8'hf8) ^ d_i[111]; + assign d_o[112] = (syndrome_o == 8'h7f) ^ d_i[112]; + assign d_o[113] = (syndrome_o == 8'hbf) ^ d_i[113]; + assign d_o[114] = (syndrome_o == 8'hdf) ^ d_i[114]; + assign d_o[115] = (syndrome_o == 8'hef) ^ d_i[115]; + assign d_o[116] = (syndrome_o == 8'hf7) ^ d_i[116]; + assign d_o[117] = (syndrome_o == 8'hfb) ^ d_i[117]; + assign d_o[118] = (syndrome_o == 8'hfd) ^ d_i[118]; + assign d_o[119] = (syndrome_o == 8'hfe) ^ d_i[119]; + assign d_o[120] = (syndrome_o == 8'h1) ^ d_i[120]; + assign d_o[121] = (syndrome_o == 8'h2) ^ d_i[121]; + assign d_o[122] = (syndrome_o == 8'h4) ^ d_i[122]; + assign d_o[123] = (syndrome_o == 8'h8) ^ d_i[123]; + assign d_o[124] = (syndrome_o == 8'h10) ^ d_i[124]; + assign d_o[125] = (syndrome_o == 8'h20) ^ d_i[125]; + assign d_o[126] = (syndrome_o == 8'h40) ^ d_i[126]; + assign d_o[127] = (syndrome_o == 8'h80) ^ d_i[127]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_128_120_cor diff --git a/rtl/lowrisc_ecc/prim_secded_128_120_dec.sv b/rtl/lowrisc_ecc/prim_secded_128_120_dec.sv new file mode 100644 index 00000000..8cbee310 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_128_120_dec.sv @@ -0,0 +1,154 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Decoder generated by +// util/design/secded_gen.py -m 8 -k 120 -s 1592631616 -c hsiao + +module prim_secded_128_120_dec ( + input [127:0] in, + output logic [119:0] d_o, + output logic [7:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(in & 128'h017F000007FFFFFFFF000000001FFFFF); + assign syndrome_o[1] = ^(in & 128'h02BF03FFF8000FFFFF00000FFFE0003F); + assign syndrome_o[2] = ^(in & 128'h04DF7C1FF83FF003FF003FF003E007C1); + assign syndrome_o[3] = ^(in & 128'h08EFBDE1FBC3F0FC0F0FC0F03C207842); + assign syndrome_o[4] = ^(in & 128'h10F7DEEE3DDC771C7171C711C4438884); + assign syndrome_o[5] = ^(in & 128'h20FBEF76CEED9B6592B65926488C9108); + assign syndrome_o[6] = ^(in & 128'h40FDF7BB5776ADAAA4DAAA4A91152210); + assign syndrome_o[7] = ^(in & 128'h80FEFBDDA7BB4ED348ED348D221A4420); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 8'h7) ^ in[0]; + assign d_o[1] = (syndrome_o == 8'hb) ^ in[1]; + assign d_o[2] = (syndrome_o == 8'h13) ^ in[2]; + assign d_o[3] = (syndrome_o == 8'h23) ^ in[3]; + assign d_o[4] = (syndrome_o == 8'h43) ^ in[4]; + assign d_o[5] = (syndrome_o == 8'h83) ^ in[5]; + assign d_o[6] = (syndrome_o == 8'hd) ^ in[6]; + assign d_o[7] = (syndrome_o == 8'h15) ^ in[7]; + assign d_o[8] = (syndrome_o == 8'h25) ^ in[8]; + assign d_o[9] = (syndrome_o == 8'h45) ^ in[9]; + assign d_o[10] = (syndrome_o == 8'h85) ^ in[10]; + assign d_o[11] = (syndrome_o == 8'h19) ^ in[11]; + assign d_o[12] = (syndrome_o == 8'h29) ^ in[12]; + assign d_o[13] = (syndrome_o == 8'h49) ^ in[13]; + assign d_o[14] = (syndrome_o == 8'h89) ^ in[14]; + assign d_o[15] = (syndrome_o == 8'h31) ^ in[15]; + assign d_o[16] = (syndrome_o == 8'h51) ^ in[16]; + assign d_o[17] = (syndrome_o == 8'h91) ^ in[17]; + assign d_o[18] = (syndrome_o == 8'h61) ^ in[18]; + assign d_o[19] = (syndrome_o == 8'ha1) ^ in[19]; + assign d_o[20] = (syndrome_o == 8'hc1) ^ in[20]; + assign d_o[21] = (syndrome_o == 8'he) ^ in[21]; + assign d_o[22] = (syndrome_o == 8'h16) ^ in[22]; + assign d_o[23] = (syndrome_o == 8'h26) ^ in[23]; + assign d_o[24] = (syndrome_o == 8'h46) ^ in[24]; + assign d_o[25] = (syndrome_o == 8'h86) ^ in[25]; + assign d_o[26] = (syndrome_o == 8'h1a) ^ in[26]; + assign d_o[27] = (syndrome_o == 8'h2a) ^ in[27]; + assign d_o[28] = (syndrome_o == 8'h4a) ^ in[28]; + assign d_o[29] = (syndrome_o == 8'h8a) ^ in[29]; + assign d_o[30] = (syndrome_o == 8'h32) ^ in[30]; + assign d_o[31] = (syndrome_o == 8'h52) ^ in[31]; + assign d_o[32] = (syndrome_o == 8'h92) ^ in[32]; + assign d_o[33] = (syndrome_o == 8'h62) ^ in[33]; + assign d_o[34] = (syndrome_o == 8'ha2) ^ in[34]; + assign d_o[35] = (syndrome_o == 8'hc2) ^ in[35]; + assign d_o[36] = (syndrome_o == 8'h1c) ^ in[36]; + assign d_o[37] = (syndrome_o == 8'h2c) ^ in[37]; + assign d_o[38] = (syndrome_o == 8'h4c) ^ in[38]; + assign d_o[39] = (syndrome_o == 8'h8c) ^ in[39]; + assign d_o[40] = (syndrome_o == 8'h34) ^ in[40]; + assign d_o[41] = (syndrome_o == 8'h54) ^ in[41]; + assign d_o[42] = (syndrome_o == 8'h94) ^ in[42]; + assign d_o[43] = (syndrome_o == 8'h64) ^ in[43]; + assign d_o[44] = (syndrome_o == 8'ha4) ^ in[44]; + assign d_o[45] = (syndrome_o == 8'hc4) ^ in[45]; + assign d_o[46] = (syndrome_o == 8'h38) ^ in[46]; + assign d_o[47] = (syndrome_o == 8'h58) ^ in[47]; + assign d_o[48] = (syndrome_o == 8'h98) ^ in[48]; + assign d_o[49] = (syndrome_o == 8'h68) ^ in[49]; + assign d_o[50] = (syndrome_o == 8'ha8) ^ in[50]; + assign d_o[51] = (syndrome_o == 8'hc8) ^ in[51]; + assign d_o[52] = (syndrome_o == 8'h70) ^ in[52]; + assign d_o[53] = (syndrome_o == 8'hb0) ^ in[53]; + assign d_o[54] = (syndrome_o == 8'hd0) ^ in[54]; + assign d_o[55] = (syndrome_o == 8'he0) ^ in[55]; + assign d_o[56] = (syndrome_o == 8'h1f) ^ in[56]; + assign d_o[57] = (syndrome_o == 8'h2f) ^ in[57]; + assign d_o[58] = (syndrome_o == 8'h4f) ^ in[58]; + assign d_o[59] = (syndrome_o == 8'h8f) ^ in[59]; + assign d_o[60] = (syndrome_o == 8'h37) ^ in[60]; + assign d_o[61] = (syndrome_o == 8'h57) ^ in[61]; + assign d_o[62] = (syndrome_o == 8'h97) ^ in[62]; + assign d_o[63] = (syndrome_o == 8'h67) ^ in[63]; + assign d_o[64] = (syndrome_o == 8'ha7) ^ in[64]; + assign d_o[65] = (syndrome_o == 8'hc7) ^ in[65]; + assign d_o[66] = (syndrome_o == 8'h3b) ^ in[66]; + assign d_o[67] = (syndrome_o == 8'h5b) ^ in[67]; + assign d_o[68] = (syndrome_o == 8'h9b) ^ in[68]; + assign d_o[69] = (syndrome_o == 8'h6b) ^ in[69]; + assign d_o[70] = (syndrome_o == 8'hab) ^ in[70]; + assign d_o[71] = (syndrome_o == 8'hcb) ^ in[71]; + assign d_o[72] = (syndrome_o == 8'h73) ^ in[72]; + assign d_o[73] = (syndrome_o == 8'hb3) ^ in[73]; + assign d_o[74] = (syndrome_o == 8'hd3) ^ in[74]; + assign d_o[75] = (syndrome_o == 8'he3) ^ in[75]; + assign d_o[76] = (syndrome_o == 8'h3d) ^ in[76]; + assign d_o[77] = (syndrome_o == 8'h5d) ^ in[77]; + assign d_o[78] = (syndrome_o == 8'h9d) ^ in[78]; + assign d_o[79] = (syndrome_o == 8'h6d) ^ in[79]; + assign d_o[80] = (syndrome_o == 8'had) ^ in[80]; + assign d_o[81] = (syndrome_o == 8'hcd) ^ in[81]; + assign d_o[82] = (syndrome_o == 8'h75) ^ in[82]; + assign d_o[83] = (syndrome_o == 8'hb5) ^ in[83]; + assign d_o[84] = (syndrome_o == 8'hd5) ^ in[84]; + assign d_o[85] = (syndrome_o == 8'he5) ^ in[85]; + assign d_o[86] = (syndrome_o == 8'h79) ^ in[86]; + assign d_o[87] = (syndrome_o == 8'hb9) ^ in[87]; + assign d_o[88] = (syndrome_o == 8'hd9) ^ in[88]; + assign d_o[89] = (syndrome_o == 8'he9) ^ in[89]; + assign d_o[90] = (syndrome_o == 8'hf1) ^ in[90]; + assign d_o[91] = (syndrome_o == 8'h3e) ^ in[91]; + assign d_o[92] = (syndrome_o == 8'h5e) ^ in[92]; + assign d_o[93] = (syndrome_o == 8'h9e) ^ in[93]; + assign d_o[94] = (syndrome_o == 8'h6e) ^ in[94]; + assign d_o[95] = (syndrome_o == 8'hae) ^ in[95]; + assign d_o[96] = (syndrome_o == 8'hce) ^ in[96]; + assign d_o[97] = (syndrome_o == 8'h76) ^ in[97]; + assign d_o[98] = (syndrome_o == 8'hb6) ^ in[98]; + assign d_o[99] = (syndrome_o == 8'hd6) ^ in[99]; + assign d_o[100] = (syndrome_o == 8'he6) ^ in[100]; + assign d_o[101] = (syndrome_o == 8'h7a) ^ in[101]; + assign d_o[102] = (syndrome_o == 8'hba) ^ in[102]; + assign d_o[103] = (syndrome_o == 8'hda) ^ in[103]; + assign d_o[104] = (syndrome_o == 8'hea) ^ in[104]; + assign d_o[105] = (syndrome_o == 8'hf2) ^ in[105]; + assign d_o[106] = (syndrome_o == 8'h7c) ^ in[106]; + assign d_o[107] = (syndrome_o == 8'hbc) ^ in[107]; + assign d_o[108] = (syndrome_o == 8'hdc) ^ in[108]; + assign d_o[109] = (syndrome_o == 8'hec) ^ in[109]; + assign d_o[110] = (syndrome_o == 8'hf4) ^ in[110]; + assign d_o[111] = (syndrome_o == 8'hf8) ^ in[111]; + assign d_o[112] = (syndrome_o == 8'h7f) ^ in[112]; + assign d_o[113] = (syndrome_o == 8'hbf) ^ in[113]; + assign d_o[114] = (syndrome_o == 8'hdf) ^ in[114]; + assign d_o[115] = (syndrome_o == 8'hef) ^ in[115]; + assign d_o[116] = (syndrome_o == 8'hf7) ^ in[116]; + assign d_o[117] = (syndrome_o == 8'hfb) ^ in[117]; + assign d_o[118] = (syndrome_o == 8'hfd) ^ in[118]; + assign d_o[119] = (syndrome_o == 8'hfe) ^ in[119]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_128_120_dec diff --git a/rtl/lowrisc_ecc/prim_secded_128_120_enc.sv b/rtl/lowrisc_ecc/prim_secded_128_120_enc.sv new file mode 100644 index 00000000..06d11fa3 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_128_120_enc.sv @@ -0,0 +1,25 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Encoder generated by +// util/design/secded_gen.py -m 8 -k 120 -s 1592631616 -c hsiao + +module prim_secded_128_120_enc ( + input [119:0] in, + output logic [127:0] out +); + + always_comb begin : p_encode + out[119:0] = in; + out[120] = ^(in & 120'h7F000007FFFFFFFF000000001FFFFF); + out[121] = ^(in & 120'hBF03FFF8000FFFFF00000FFFE0003F); + out[122] = ^(in & 120'hDF7C1FF83FF003FF003FF003E007C1); + out[123] = ^(in & 120'hEFBDE1FBC3F0FC0F0FC0F03C207842); + out[124] = ^(in & 120'hF7DEEE3DDC771C7171C711C4438884); + out[125] = ^(in & 120'hFBEF76CEED9B6592B65926488C9108); + out[126] = ^(in & 120'hFDF7BB5776ADAAA4DAAA4A91152210); + out[127] = ^(in & 120'hFEFBDDA7BB4ED348ED348D221A4420); + end + +endmodule : prim_secded_128_120_enc diff --git a/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv b/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv new file mode 100644 index 00000000..b1ba2ff0 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv @@ -0,0 +1,44 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 5 -k 8 -s 1592631616 -c hsiao + +module prim_secded_13_8_cor ( + input [12:0] d_i, + output logic [12:0] d_o, + output logic [4:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 13'h016B); + assign syndrome_o[1] = ^(d_i & 13'h02F8); + assign syndrome_o[2] = ^(d_i & 13'h04D5); + assign syndrome_o[3] = ^(d_i & 13'h08A7); + assign syndrome_o[4] = ^(d_i & 13'h101E); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 5'hd) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 5'h19) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 5'h1c) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 5'h13) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 5'h16) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 5'hb) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 5'h7) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 5'he) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 5'h1) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 5'h2) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 5'h4) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 5'h8) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 5'h10) ^ d_i[12]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_13_8_cor diff --git a/rtl/lowrisc_ecc/prim_secded_13_8_enc.sv b/rtl/lowrisc_ecc/prim_secded_13_8_enc.sv index d94b9de3..da3bf4b8 100644 --- a/rtl/lowrisc_ecc/prim_secded_13_8_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_13_8_enc.sv @@ -11,12 +11,12 @@ module prim_secded_13_8_enc ( ); always_comb begin : p_encode - out = 13'(in); - out[8] = ^(out & 13'h006B); - out[9] = ^(out & 13'h00F8); - out[10] = ^(out & 13'h00D5); - out[11] = ^(out & 13'h00A7); - out[12] = ^(out & 13'h001E); + out[7:0] = in; + out[8] = ^(in & 8'h6B); + out[9] = ^(in & 8'hF8); + out[10] = ^(in & 8'hD5); + out[11] = ^(in & 8'hA7); + out[12] = ^(in & 8'h1E); end endmodule : prim_secded_13_8_enc diff --git a/rtl/lowrisc_ecc/prim_secded_16_11_cor.sv b/rtl/lowrisc_ecc/prim_secded_16_11_cor.sv new file mode 100644 index 00000000..4f140493 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_16_11_cor.sv @@ -0,0 +1,47 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 5 -k 11 -s 1592631616 -c hsiao + +module prim_secded_16_11_cor ( + input [15:0] d_i, + output logic [15:0] d_o, + output logic [4:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 16'h0C3F); + assign syndrome_o[1] = ^(d_i & 16'h15C7); + assign syndrome_o[2] = ^(d_i & 16'h26D9); + assign syndrome_o[3] = ^(d_i & 16'h476A); + assign syndrome_o[4] = ^(d_i & 16'h87B4); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 5'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 5'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 5'h13) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 5'hd) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 5'h15) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 5'h19) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 5'he) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 5'h16) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 5'h1a) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 5'h1c) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 5'h1f) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 5'h1) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 5'h2) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 5'h4) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 5'h8) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 5'h10) ^ d_i[15]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_16_11_cor diff --git a/rtl/lowrisc_ecc/prim_secded_16_11_dec.sv b/rtl/lowrisc_ecc/prim_secded_16_11_dec.sv new file mode 100644 index 00000000..bf08adbc --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_16_11_dec.sv @@ -0,0 +1,42 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Decoder generated by +// util/design/secded_gen.py -m 5 -k 11 -s 1592631616 -c hsiao + +module prim_secded_16_11_dec ( + input [15:0] in, + output logic [10:0] d_o, + output logic [4:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(in & 16'h0C3F); + assign syndrome_o[1] = ^(in & 16'h15C7); + assign syndrome_o[2] = ^(in & 16'h26D9); + assign syndrome_o[3] = ^(in & 16'h476A); + assign syndrome_o[4] = ^(in & 16'h87B4); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 5'h7) ^ in[0]; + assign d_o[1] = (syndrome_o == 5'hb) ^ in[1]; + assign d_o[2] = (syndrome_o == 5'h13) ^ in[2]; + assign d_o[3] = (syndrome_o == 5'hd) ^ in[3]; + assign d_o[4] = (syndrome_o == 5'h15) ^ in[4]; + assign d_o[5] = (syndrome_o == 5'h19) ^ in[5]; + assign d_o[6] = (syndrome_o == 5'he) ^ in[6]; + assign d_o[7] = (syndrome_o == 5'h16) ^ in[7]; + assign d_o[8] = (syndrome_o == 5'h1a) ^ in[8]; + assign d_o[9] = (syndrome_o == 5'h1c) ^ in[9]; + assign d_o[10] = (syndrome_o == 5'h1f) ^ in[10]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_16_11_dec diff --git a/rtl/lowrisc_ecc/prim_secded_16_11_enc.sv b/rtl/lowrisc_ecc/prim_secded_16_11_enc.sv new file mode 100644 index 00000000..f2710125 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_16_11_enc.sv @@ -0,0 +1,22 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Encoder generated by +// util/design/secded_gen.py -m 5 -k 11 -s 1592631616 -c hsiao + +module prim_secded_16_11_enc ( + input [10:0] in, + output logic [15:0] out +); + + always_comb begin : p_encode + out[10:0] = in; + out[11] = ^(in & 11'h43F); + out[12] = ^(in & 11'h5C7); + out[13] = ^(in & 11'h6D9); + out[14] = ^(in & 11'h76A); + out[15] = ^(in & 11'h7B4); + end + +endmodule : prim_secded_16_11_enc diff --git a/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv b/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv new file mode 100644 index 00000000..b3fd2e4e --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv @@ -0,0 +1,54 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 6 -k 16 -s 1592631616 -c hsiao + +module prim_secded_22_16_cor ( + input [21:0] d_i, + output logic [21:0] d_o, + output logic [5:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 22'h017B48); + assign syndrome_o[1] = ^(d_i & 22'h0291AB); + assign syndrome_o[2] = ^(d_i & 22'h040E3D); + assign syndrome_o[3] = ^(d_i & 22'h087692); + assign syndrome_o[4] = ^(d_i & 22'h10A547); + assign syndrome_o[5] = ^(d_i & 22'h20C8F4); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 6'h16) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 6'h1a) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 6'h34) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 6'h7) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 6'h2c) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 6'h26) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 6'h31) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 6'h2a) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 6'h13) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 6'hd) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 6'h1c) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 6'h25) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 6'hb) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 6'h19) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 6'h29) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 6'h32) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 6'h1) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 6'h2) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 6'h4) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 6'h8) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 6'h10) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 6'h20) ^ d_i[21]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_22_16_cor diff --git a/rtl/lowrisc_ecc/prim_secded_22_16_enc.sv b/rtl/lowrisc_ecc/prim_secded_22_16_enc.sv index 897165d1..728afd51 100644 --- a/rtl/lowrisc_ecc/prim_secded_22_16_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_22_16_enc.sv @@ -11,13 +11,13 @@ module prim_secded_22_16_enc ( ); always_comb begin : p_encode - out = 22'(in); - out[16] = ^(out & 22'h007B48); - out[17] = ^(out & 22'h0091AB); - out[18] = ^(out & 22'h000E3D); - out[19] = ^(out & 22'h007692); - out[20] = ^(out & 22'h00A547); - out[21] = ^(out & 22'h00C8F4); + out[15:0] = in; + out[16] = ^(in & 16'h7B48); + out[17] = ^(in & 16'h91AB); + out[18] = ^(in & 16'h0E3D); + out[19] = ^(in & 16'h7692); + out[20] = ^(in & 16'hA547); + out[21] = ^(in & 16'hC8F4); end endmodule : prim_secded_22_16_enc diff --git a/rtl/lowrisc_ecc/prim_secded_256_247_cor.sv b/rtl/lowrisc_ecc/prim_secded_256_247_cor.sv new file mode 100644 index 00000000..34bb214e --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_256_247_cor.sv @@ -0,0 +1,291 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 9 -k 247 -s 1592631616 -c hsiao + +module prim_secded_256_247_cor ( + input [255:0] d_i, + output logic [255:0] d_o, + output logic [8:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 256'h00C03FFFFFFC00000000000003FFFFFFFFFFFFFFFFF00000000000000FFFFFFF); + assign syndrome_o[1] = ^(d_i & 256'h015FC07FFFFC00001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000007F); + assign syndrome_o[2] = ^(d_i & 256'h026FDF81FFFC0FFFE0003FFFFC0007FFFF800007FFF00000FFFE0003F0001F81); + assign syndrome_o[3] = ^(d_i & 256'h0477EFBE0FFDF07FE0FFC00FFC1FF801FF801FF801F003FF003E007C1003E082); + assign syndrome_o[4] = ^(d_i & 256'h087BF7DEF0FEF787EF0FC3F03DE1F87E0787E0781E10FC0F03C20784203C2104); + assign syndrome_o[5] = ^(d_i & 256'h107DFBEF771F7BB8F771DC71C6EE3B8E38B8E388E2271C711C44388841C44208); + assign syndrome_o[6] = ^(d_i & 256'h207EFDF7BB67BDDB3BB66D964B76CDB2C95B2C93244B65926488C91086488410); + assign syndrome_o[7] = ^(d_i & 256'h407F7EFBDDABDEED5DDAB6AA93BB56D5526D5525488DAAA4A91152210A910820); + assign syndrome_o[8] = ^(d_i & 256'h807FBF7DEED3EF769EED3B4D23DDA769A4769A46910ED348D221A4420D221040); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 9'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 9'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 9'h13) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 9'h23) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 9'h43) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 9'h83) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 9'h103) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 9'hd) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 9'h15) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 9'h25) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 9'h45) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 9'h85) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 9'h105) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 9'h19) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 9'h29) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 9'h49) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 9'h89) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 9'h109) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 9'h31) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 9'h51) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 9'h91) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 9'h111) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 9'h61) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 9'ha1) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 9'h121) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 9'hc1) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 9'h141) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 9'h181) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 9'he) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 9'h16) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 9'h26) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 9'h46) ^ d_i[31]; + assign d_o[32] = (syndrome_o == 9'h86) ^ d_i[32]; + assign d_o[33] = (syndrome_o == 9'h106) ^ d_i[33]; + assign d_o[34] = (syndrome_o == 9'h1a) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 9'h2a) ^ d_i[35]; + assign d_o[36] = (syndrome_o == 9'h4a) ^ d_i[36]; + assign d_o[37] = (syndrome_o == 9'h8a) ^ d_i[37]; + assign d_o[38] = (syndrome_o == 9'h10a) ^ d_i[38]; + assign d_o[39] = (syndrome_o == 9'h32) ^ d_i[39]; + assign d_o[40] = (syndrome_o == 9'h52) ^ d_i[40]; + assign d_o[41] = (syndrome_o == 9'h92) ^ d_i[41]; + assign d_o[42] = (syndrome_o == 9'h112) ^ d_i[42]; + assign d_o[43] = (syndrome_o == 9'h62) ^ d_i[43]; + assign d_o[44] = (syndrome_o == 9'ha2) ^ d_i[44]; + assign d_o[45] = (syndrome_o == 9'h122) ^ d_i[45]; + assign d_o[46] = (syndrome_o == 9'hc2) ^ d_i[46]; + assign d_o[47] = (syndrome_o == 9'h142) ^ d_i[47]; + assign d_o[48] = (syndrome_o == 9'h182) ^ d_i[48]; + assign d_o[49] = (syndrome_o == 9'h1c) ^ d_i[49]; + assign d_o[50] = (syndrome_o == 9'h2c) ^ d_i[50]; + assign d_o[51] = (syndrome_o == 9'h4c) ^ d_i[51]; + assign d_o[52] = (syndrome_o == 9'h8c) ^ d_i[52]; + assign d_o[53] = (syndrome_o == 9'h10c) ^ d_i[53]; + assign d_o[54] = (syndrome_o == 9'h34) ^ d_i[54]; + assign d_o[55] = (syndrome_o == 9'h54) ^ d_i[55]; + assign d_o[56] = (syndrome_o == 9'h94) ^ d_i[56]; + assign d_o[57] = (syndrome_o == 9'h114) ^ d_i[57]; + assign d_o[58] = (syndrome_o == 9'h64) ^ d_i[58]; + assign d_o[59] = (syndrome_o == 9'ha4) ^ d_i[59]; + assign d_o[60] = (syndrome_o == 9'h124) ^ d_i[60]; + assign d_o[61] = (syndrome_o == 9'hc4) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 9'h144) ^ d_i[62]; + assign d_o[63] = (syndrome_o == 9'h184) ^ d_i[63]; + assign d_o[64] = (syndrome_o == 9'h38) ^ d_i[64]; + assign d_o[65] = (syndrome_o == 9'h58) ^ d_i[65]; + assign d_o[66] = (syndrome_o == 9'h98) ^ d_i[66]; + assign d_o[67] = (syndrome_o == 9'h118) ^ d_i[67]; + assign d_o[68] = (syndrome_o == 9'h68) ^ d_i[68]; + assign d_o[69] = (syndrome_o == 9'ha8) ^ d_i[69]; + assign d_o[70] = (syndrome_o == 9'h128) ^ d_i[70]; + assign d_o[71] = (syndrome_o == 9'hc8) ^ d_i[71]; + assign d_o[72] = (syndrome_o == 9'h148) ^ d_i[72]; + assign d_o[73] = (syndrome_o == 9'h188) ^ d_i[73]; + assign d_o[74] = (syndrome_o == 9'h70) ^ d_i[74]; + assign d_o[75] = (syndrome_o == 9'hb0) ^ d_i[75]; + assign d_o[76] = (syndrome_o == 9'h130) ^ d_i[76]; + assign d_o[77] = (syndrome_o == 9'hd0) ^ d_i[77]; + assign d_o[78] = (syndrome_o == 9'h150) ^ d_i[78]; + assign d_o[79] = (syndrome_o == 9'h190) ^ d_i[79]; + assign d_o[80] = (syndrome_o == 9'he0) ^ d_i[80]; + assign d_o[81] = (syndrome_o == 9'h160) ^ d_i[81]; + assign d_o[82] = (syndrome_o == 9'h1a0) ^ d_i[82]; + assign d_o[83] = (syndrome_o == 9'h1c0) ^ d_i[83]; + assign d_o[84] = (syndrome_o == 9'h1f) ^ d_i[84]; + assign d_o[85] = (syndrome_o == 9'h2f) ^ d_i[85]; + assign d_o[86] = (syndrome_o == 9'h4f) ^ d_i[86]; + assign d_o[87] = (syndrome_o == 9'h8f) ^ d_i[87]; + assign d_o[88] = (syndrome_o == 9'h10f) ^ d_i[88]; + assign d_o[89] = (syndrome_o == 9'h37) ^ d_i[89]; + assign d_o[90] = (syndrome_o == 9'h57) ^ d_i[90]; + assign d_o[91] = (syndrome_o == 9'h97) ^ d_i[91]; + assign d_o[92] = (syndrome_o == 9'h117) ^ d_i[92]; + assign d_o[93] = (syndrome_o == 9'h67) ^ d_i[93]; + assign d_o[94] = (syndrome_o == 9'ha7) ^ d_i[94]; + assign d_o[95] = (syndrome_o == 9'h127) ^ d_i[95]; + assign d_o[96] = (syndrome_o == 9'hc7) ^ d_i[96]; + assign d_o[97] = (syndrome_o == 9'h147) ^ d_i[97]; + assign d_o[98] = (syndrome_o == 9'h187) ^ d_i[98]; + assign d_o[99] = (syndrome_o == 9'h3b) ^ d_i[99]; + assign d_o[100] = (syndrome_o == 9'h5b) ^ d_i[100]; + assign d_o[101] = (syndrome_o == 9'h9b) ^ d_i[101]; + assign d_o[102] = (syndrome_o == 9'h11b) ^ d_i[102]; + assign d_o[103] = (syndrome_o == 9'h6b) ^ d_i[103]; + assign d_o[104] = (syndrome_o == 9'hab) ^ d_i[104]; + assign d_o[105] = (syndrome_o == 9'h12b) ^ d_i[105]; + assign d_o[106] = (syndrome_o == 9'hcb) ^ d_i[106]; + assign d_o[107] = (syndrome_o == 9'h14b) ^ d_i[107]; + assign d_o[108] = (syndrome_o == 9'h18b) ^ d_i[108]; + assign d_o[109] = (syndrome_o == 9'h73) ^ d_i[109]; + assign d_o[110] = (syndrome_o == 9'hb3) ^ d_i[110]; + assign d_o[111] = (syndrome_o == 9'h133) ^ d_i[111]; + assign d_o[112] = (syndrome_o == 9'hd3) ^ d_i[112]; + assign d_o[113] = (syndrome_o == 9'h153) ^ d_i[113]; + assign d_o[114] = (syndrome_o == 9'h193) ^ d_i[114]; + assign d_o[115] = (syndrome_o == 9'he3) ^ d_i[115]; + assign d_o[116] = (syndrome_o == 9'h163) ^ d_i[116]; + assign d_o[117] = (syndrome_o == 9'h1a3) ^ d_i[117]; + assign d_o[118] = (syndrome_o == 9'h1c3) ^ d_i[118]; + assign d_o[119] = (syndrome_o == 9'h3d) ^ d_i[119]; + assign d_o[120] = (syndrome_o == 9'h5d) ^ d_i[120]; + assign d_o[121] = (syndrome_o == 9'h9d) ^ d_i[121]; + assign d_o[122] = (syndrome_o == 9'h11d) ^ d_i[122]; + assign d_o[123] = (syndrome_o == 9'h6d) ^ d_i[123]; + assign d_o[124] = (syndrome_o == 9'had) ^ d_i[124]; + assign d_o[125] = (syndrome_o == 9'h12d) ^ d_i[125]; + assign d_o[126] = (syndrome_o == 9'hcd) ^ d_i[126]; + assign d_o[127] = (syndrome_o == 9'h14d) ^ d_i[127]; + assign d_o[128] = (syndrome_o == 9'h18d) ^ d_i[128]; + assign d_o[129] = (syndrome_o == 9'h75) ^ d_i[129]; + assign d_o[130] = (syndrome_o == 9'hb5) ^ d_i[130]; + assign d_o[131] = (syndrome_o == 9'h135) ^ d_i[131]; + assign d_o[132] = (syndrome_o == 9'hd5) ^ d_i[132]; + assign d_o[133] = (syndrome_o == 9'h155) ^ d_i[133]; + assign d_o[134] = (syndrome_o == 9'h195) ^ d_i[134]; + assign d_o[135] = (syndrome_o == 9'he5) ^ d_i[135]; + assign d_o[136] = (syndrome_o == 9'h165) ^ d_i[136]; + assign d_o[137] = (syndrome_o == 9'h1a5) ^ d_i[137]; + assign d_o[138] = (syndrome_o == 9'h1c5) ^ d_i[138]; + assign d_o[139] = (syndrome_o == 9'h79) ^ d_i[139]; + assign d_o[140] = (syndrome_o == 9'hb9) ^ d_i[140]; + assign d_o[141] = (syndrome_o == 9'h139) ^ d_i[141]; + assign d_o[142] = (syndrome_o == 9'hd9) ^ d_i[142]; + assign d_o[143] = (syndrome_o == 9'h159) ^ d_i[143]; + assign d_o[144] = (syndrome_o == 9'h199) ^ d_i[144]; + assign d_o[145] = (syndrome_o == 9'he9) ^ d_i[145]; + assign d_o[146] = (syndrome_o == 9'h169) ^ d_i[146]; + assign d_o[147] = (syndrome_o == 9'h1a9) ^ d_i[147]; + assign d_o[148] = (syndrome_o == 9'h1c9) ^ d_i[148]; + assign d_o[149] = (syndrome_o == 9'hf1) ^ d_i[149]; + assign d_o[150] = (syndrome_o == 9'h171) ^ d_i[150]; + assign d_o[151] = (syndrome_o == 9'h1b1) ^ d_i[151]; + assign d_o[152] = (syndrome_o == 9'h1d1) ^ d_i[152]; + assign d_o[153] = (syndrome_o == 9'h1e1) ^ d_i[153]; + assign d_o[154] = (syndrome_o == 9'h3e) ^ d_i[154]; + assign d_o[155] = (syndrome_o == 9'h5e) ^ d_i[155]; + assign d_o[156] = (syndrome_o == 9'h9e) ^ d_i[156]; + assign d_o[157] = (syndrome_o == 9'h11e) ^ d_i[157]; + assign d_o[158] = (syndrome_o == 9'h6e) ^ d_i[158]; + assign d_o[159] = (syndrome_o == 9'hae) ^ d_i[159]; + assign d_o[160] = (syndrome_o == 9'h12e) ^ d_i[160]; + assign d_o[161] = (syndrome_o == 9'hce) ^ d_i[161]; + assign d_o[162] = (syndrome_o == 9'h14e) ^ d_i[162]; + assign d_o[163] = (syndrome_o == 9'h18e) ^ d_i[163]; + assign d_o[164] = (syndrome_o == 9'h76) ^ d_i[164]; + assign d_o[165] = (syndrome_o == 9'hb6) ^ d_i[165]; + assign d_o[166] = (syndrome_o == 9'h136) ^ d_i[166]; + assign d_o[167] = (syndrome_o == 9'hd6) ^ d_i[167]; + assign d_o[168] = (syndrome_o == 9'h156) ^ d_i[168]; + assign d_o[169] = (syndrome_o == 9'h196) ^ d_i[169]; + assign d_o[170] = (syndrome_o == 9'he6) ^ d_i[170]; + assign d_o[171] = (syndrome_o == 9'h166) ^ d_i[171]; + assign d_o[172] = (syndrome_o == 9'h1a6) ^ d_i[172]; + assign d_o[173] = (syndrome_o == 9'h1c6) ^ d_i[173]; + assign d_o[174] = (syndrome_o == 9'h7a) ^ d_i[174]; + assign d_o[175] = (syndrome_o == 9'hba) ^ d_i[175]; + assign d_o[176] = (syndrome_o == 9'h13a) ^ d_i[176]; + assign d_o[177] = (syndrome_o == 9'hda) ^ d_i[177]; + assign d_o[178] = (syndrome_o == 9'h15a) ^ d_i[178]; + assign d_o[179] = (syndrome_o == 9'h19a) ^ d_i[179]; + assign d_o[180] = (syndrome_o == 9'hea) ^ d_i[180]; + assign d_o[181] = (syndrome_o == 9'h16a) ^ d_i[181]; + assign d_o[182] = (syndrome_o == 9'h1aa) ^ d_i[182]; + assign d_o[183] = (syndrome_o == 9'h1ca) ^ d_i[183]; + assign d_o[184] = (syndrome_o == 9'hf2) ^ d_i[184]; + assign d_o[185] = (syndrome_o == 9'h172) ^ d_i[185]; + assign d_o[186] = (syndrome_o == 9'h1b2) ^ d_i[186]; + assign d_o[187] = (syndrome_o == 9'h1d2) ^ d_i[187]; + assign d_o[188] = (syndrome_o == 9'h1e2) ^ d_i[188]; + assign d_o[189] = (syndrome_o == 9'h7c) ^ d_i[189]; + assign d_o[190] = (syndrome_o == 9'hbc) ^ d_i[190]; + assign d_o[191] = (syndrome_o == 9'h13c) ^ d_i[191]; + assign d_o[192] = (syndrome_o == 9'hdc) ^ d_i[192]; + assign d_o[193] = (syndrome_o == 9'h15c) ^ d_i[193]; + assign d_o[194] = (syndrome_o == 9'h19c) ^ d_i[194]; + assign d_o[195] = (syndrome_o == 9'hec) ^ d_i[195]; + assign d_o[196] = (syndrome_o == 9'h16c) ^ d_i[196]; + assign d_o[197] = (syndrome_o == 9'h1ac) ^ d_i[197]; + assign d_o[198] = (syndrome_o == 9'h1cc) ^ d_i[198]; + assign d_o[199] = (syndrome_o == 9'hf4) ^ d_i[199]; + assign d_o[200] = (syndrome_o == 9'h174) ^ d_i[200]; + assign d_o[201] = (syndrome_o == 9'h1b4) ^ d_i[201]; + assign d_o[202] = (syndrome_o == 9'h1d4) ^ d_i[202]; + assign d_o[203] = (syndrome_o == 9'h1e4) ^ d_i[203]; + assign d_o[204] = (syndrome_o == 9'hf8) ^ d_i[204]; + assign d_o[205] = (syndrome_o == 9'h178) ^ d_i[205]; + assign d_o[206] = (syndrome_o == 9'h1b8) ^ d_i[206]; + assign d_o[207] = (syndrome_o == 9'h1d8) ^ d_i[207]; + assign d_o[208] = (syndrome_o == 9'h1e8) ^ d_i[208]; + assign d_o[209] = (syndrome_o == 9'h1f0) ^ d_i[209]; + assign d_o[210] = (syndrome_o == 9'h7f) ^ d_i[210]; + assign d_o[211] = (syndrome_o == 9'hbf) ^ d_i[211]; + assign d_o[212] = (syndrome_o == 9'h13f) ^ d_i[212]; + assign d_o[213] = (syndrome_o == 9'hdf) ^ d_i[213]; + assign d_o[214] = (syndrome_o == 9'h15f) ^ d_i[214]; + assign d_o[215] = (syndrome_o == 9'h19f) ^ d_i[215]; + assign d_o[216] = (syndrome_o == 9'hef) ^ d_i[216]; + assign d_o[217] = (syndrome_o == 9'h16f) ^ d_i[217]; + assign d_o[218] = (syndrome_o == 9'h1af) ^ d_i[218]; + assign d_o[219] = (syndrome_o == 9'h1cf) ^ d_i[219]; + assign d_o[220] = (syndrome_o == 9'hf7) ^ d_i[220]; + assign d_o[221] = (syndrome_o == 9'h177) ^ d_i[221]; + assign d_o[222] = (syndrome_o == 9'h1b7) ^ d_i[222]; + assign d_o[223] = (syndrome_o == 9'h1d7) ^ d_i[223]; + assign d_o[224] = (syndrome_o == 9'h1e7) ^ d_i[224]; + assign d_o[225] = (syndrome_o == 9'hfb) ^ d_i[225]; + assign d_o[226] = (syndrome_o == 9'h17b) ^ d_i[226]; + assign d_o[227] = (syndrome_o == 9'h1bb) ^ d_i[227]; + assign d_o[228] = (syndrome_o == 9'h1db) ^ d_i[228]; + assign d_o[229] = (syndrome_o == 9'h1eb) ^ d_i[229]; + assign d_o[230] = (syndrome_o == 9'h1f3) ^ d_i[230]; + assign d_o[231] = (syndrome_o == 9'hfd) ^ d_i[231]; + assign d_o[232] = (syndrome_o == 9'h17d) ^ d_i[232]; + assign d_o[233] = (syndrome_o == 9'h1bd) ^ d_i[233]; + assign d_o[234] = (syndrome_o == 9'h1dd) ^ d_i[234]; + assign d_o[235] = (syndrome_o == 9'h1ed) ^ d_i[235]; + assign d_o[236] = (syndrome_o == 9'h1f5) ^ d_i[236]; + assign d_o[237] = (syndrome_o == 9'h1f9) ^ d_i[237]; + assign d_o[238] = (syndrome_o == 9'hfe) ^ d_i[238]; + assign d_o[239] = (syndrome_o == 9'h17e) ^ d_i[239]; + assign d_o[240] = (syndrome_o == 9'h1be) ^ d_i[240]; + assign d_o[241] = (syndrome_o == 9'h1de) ^ d_i[241]; + assign d_o[242] = (syndrome_o == 9'h1ee) ^ d_i[242]; + assign d_o[243] = (syndrome_o == 9'h1f6) ^ d_i[243]; + assign d_o[244] = (syndrome_o == 9'h1fa) ^ d_i[244]; + assign d_o[245] = (syndrome_o == 9'h1fc) ^ d_i[245]; + assign d_o[246] = (syndrome_o == 9'h1ff) ^ d_i[246]; + assign d_o[247] = (syndrome_o == 9'h1) ^ d_i[247]; + assign d_o[248] = (syndrome_o == 9'h2) ^ d_i[248]; + assign d_o[249] = (syndrome_o == 9'h4) ^ d_i[249]; + assign d_o[250] = (syndrome_o == 9'h8) ^ d_i[250]; + assign d_o[251] = (syndrome_o == 9'h10) ^ d_i[251]; + assign d_o[252] = (syndrome_o == 9'h20) ^ d_i[252]; + assign d_o[253] = (syndrome_o == 9'h40) ^ d_i[253]; + assign d_o[254] = (syndrome_o == 9'h80) ^ d_i[254]; + assign d_o[255] = (syndrome_o == 9'h100) ^ d_i[255]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_256_247_cor diff --git a/rtl/lowrisc_ecc/prim_secded_256_247_dec.sv b/rtl/lowrisc_ecc/prim_secded_256_247_dec.sv new file mode 100644 index 00000000..94d72b41 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_256_247_dec.sv @@ -0,0 +1,282 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Decoder generated by +// util/design/secded_gen.py -m 9 -k 247 -s 1592631616 -c hsiao + +module prim_secded_256_247_dec ( + input [255:0] in, + output logic [246:0] d_o, + output logic [8:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(in & 256'h00C03FFFFFFC00000000000003FFFFFFFFFFFFFFFFF00000000000000FFFFFFF); + assign syndrome_o[1] = ^(in & 256'h015FC07FFFFC00001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000007F); + assign syndrome_o[2] = ^(in & 256'h026FDF81FFFC0FFFE0003FFFFC0007FFFF800007FFF00000FFFE0003F0001F81); + assign syndrome_o[3] = ^(in & 256'h0477EFBE0FFDF07FE0FFC00FFC1FF801FF801FF801F003FF003E007C1003E082); + assign syndrome_o[4] = ^(in & 256'h087BF7DEF0FEF787EF0FC3F03DE1F87E0787E0781E10FC0F03C20784203C2104); + assign syndrome_o[5] = ^(in & 256'h107DFBEF771F7BB8F771DC71C6EE3B8E38B8E388E2271C711C44388841C44208); + assign syndrome_o[6] = ^(in & 256'h207EFDF7BB67BDDB3BB66D964B76CDB2C95B2C93244B65926488C91086488410); + assign syndrome_o[7] = ^(in & 256'h407F7EFBDDABDEED5DDAB6AA93BB56D5526D5525488DAAA4A91152210A910820); + assign syndrome_o[8] = ^(in & 256'h807FBF7DEED3EF769EED3B4D23DDA769A4769A46910ED348D221A4420D221040); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 9'h7) ^ in[0]; + assign d_o[1] = (syndrome_o == 9'hb) ^ in[1]; + assign d_o[2] = (syndrome_o == 9'h13) ^ in[2]; + assign d_o[3] = (syndrome_o == 9'h23) ^ in[3]; + assign d_o[4] = (syndrome_o == 9'h43) ^ in[4]; + assign d_o[5] = (syndrome_o == 9'h83) ^ in[5]; + assign d_o[6] = (syndrome_o == 9'h103) ^ in[6]; + assign d_o[7] = (syndrome_o == 9'hd) ^ in[7]; + assign d_o[8] = (syndrome_o == 9'h15) ^ in[8]; + assign d_o[9] = (syndrome_o == 9'h25) ^ in[9]; + assign d_o[10] = (syndrome_o == 9'h45) ^ in[10]; + assign d_o[11] = (syndrome_o == 9'h85) ^ in[11]; + assign d_o[12] = (syndrome_o == 9'h105) ^ in[12]; + assign d_o[13] = (syndrome_o == 9'h19) ^ in[13]; + assign d_o[14] = (syndrome_o == 9'h29) ^ in[14]; + assign d_o[15] = (syndrome_o == 9'h49) ^ in[15]; + assign d_o[16] = (syndrome_o == 9'h89) ^ in[16]; + assign d_o[17] = (syndrome_o == 9'h109) ^ in[17]; + assign d_o[18] = (syndrome_o == 9'h31) ^ in[18]; + assign d_o[19] = (syndrome_o == 9'h51) ^ in[19]; + assign d_o[20] = (syndrome_o == 9'h91) ^ in[20]; + assign d_o[21] = (syndrome_o == 9'h111) ^ in[21]; + assign d_o[22] = (syndrome_o == 9'h61) ^ in[22]; + assign d_o[23] = (syndrome_o == 9'ha1) ^ in[23]; + assign d_o[24] = (syndrome_o == 9'h121) ^ in[24]; + assign d_o[25] = (syndrome_o == 9'hc1) ^ in[25]; + assign d_o[26] = (syndrome_o == 9'h141) ^ in[26]; + assign d_o[27] = (syndrome_o == 9'h181) ^ in[27]; + assign d_o[28] = (syndrome_o == 9'he) ^ in[28]; + assign d_o[29] = (syndrome_o == 9'h16) ^ in[29]; + assign d_o[30] = (syndrome_o == 9'h26) ^ in[30]; + assign d_o[31] = (syndrome_o == 9'h46) ^ in[31]; + assign d_o[32] = (syndrome_o == 9'h86) ^ in[32]; + assign d_o[33] = (syndrome_o == 9'h106) ^ in[33]; + assign d_o[34] = (syndrome_o == 9'h1a) ^ in[34]; + assign d_o[35] = (syndrome_o == 9'h2a) ^ in[35]; + assign d_o[36] = (syndrome_o == 9'h4a) ^ in[36]; + assign d_o[37] = (syndrome_o == 9'h8a) ^ in[37]; + assign d_o[38] = (syndrome_o == 9'h10a) ^ in[38]; + assign d_o[39] = (syndrome_o == 9'h32) ^ in[39]; + assign d_o[40] = (syndrome_o == 9'h52) ^ in[40]; + assign d_o[41] = (syndrome_o == 9'h92) ^ in[41]; + assign d_o[42] = (syndrome_o == 9'h112) ^ in[42]; + assign d_o[43] = (syndrome_o == 9'h62) ^ in[43]; + assign d_o[44] = (syndrome_o == 9'ha2) ^ in[44]; + assign d_o[45] = (syndrome_o == 9'h122) ^ in[45]; + assign d_o[46] = (syndrome_o == 9'hc2) ^ in[46]; + assign d_o[47] = (syndrome_o == 9'h142) ^ in[47]; + assign d_o[48] = (syndrome_o == 9'h182) ^ in[48]; + assign d_o[49] = (syndrome_o == 9'h1c) ^ in[49]; + assign d_o[50] = (syndrome_o == 9'h2c) ^ in[50]; + assign d_o[51] = (syndrome_o == 9'h4c) ^ in[51]; + assign d_o[52] = (syndrome_o == 9'h8c) ^ in[52]; + assign d_o[53] = (syndrome_o == 9'h10c) ^ in[53]; + assign d_o[54] = (syndrome_o == 9'h34) ^ in[54]; + assign d_o[55] = (syndrome_o == 9'h54) ^ in[55]; + assign d_o[56] = (syndrome_o == 9'h94) ^ in[56]; + assign d_o[57] = (syndrome_o == 9'h114) ^ in[57]; + assign d_o[58] = (syndrome_o == 9'h64) ^ in[58]; + assign d_o[59] = (syndrome_o == 9'ha4) ^ in[59]; + assign d_o[60] = (syndrome_o == 9'h124) ^ in[60]; + assign d_o[61] = (syndrome_o == 9'hc4) ^ in[61]; + assign d_o[62] = (syndrome_o == 9'h144) ^ in[62]; + assign d_o[63] = (syndrome_o == 9'h184) ^ in[63]; + assign d_o[64] = (syndrome_o == 9'h38) ^ in[64]; + assign d_o[65] = (syndrome_o == 9'h58) ^ in[65]; + assign d_o[66] = (syndrome_o == 9'h98) ^ in[66]; + assign d_o[67] = (syndrome_o == 9'h118) ^ in[67]; + assign d_o[68] = (syndrome_o == 9'h68) ^ in[68]; + assign d_o[69] = (syndrome_o == 9'ha8) ^ in[69]; + assign d_o[70] = (syndrome_o == 9'h128) ^ in[70]; + assign d_o[71] = (syndrome_o == 9'hc8) ^ in[71]; + assign d_o[72] = (syndrome_o == 9'h148) ^ in[72]; + assign d_o[73] = (syndrome_o == 9'h188) ^ in[73]; + assign d_o[74] = (syndrome_o == 9'h70) ^ in[74]; + assign d_o[75] = (syndrome_o == 9'hb0) ^ in[75]; + assign d_o[76] = (syndrome_o == 9'h130) ^ in[76]; + assign d_o[77] = (syndrome_o == 9'hd0) ^ in[77]; + assign d_o[78] = (syndrome_o == 9'h150) ^ in[78]; + assign d_o[79] = (syndrome_o == 9'h190) ^ in[79]; + assign d_o[80] = (syndrome_o == 9'he0) ^ in[80]; + assign d_o[81] = (syndrome_o == 9'h160) ^ in[81]; + assign d_o[82] = (syndrome_o == 9'h1a0) ^ in[82]; + assign d_o[83] = (syndrome_o == 9'h1c0) ^ in[83]; + assign d_o[84] = (syndrome_o == 9'h1f) ^ in[84]; + assign d_o[85] = (syndrome_o == 9'h2f) ^ in[85]; + assign d_o[86] = (syndrome_o == 9'h4f) ^ in[86]; + assign d_o[87] = (syndrome_o == 9'h8f) ^ in[87]; + assign d_o[88] = (syndrome_o == 9'h10f) ^ in[88]; + assign d_o[89] = (syndrome_o == 9'h37) ^ in[89]; + assign d_o[90] = (syndrome_o == 9'h57) ^ in[90]; + assign d_o[91] = (syndrome_o == 9'h97) ^ in[91]; + assign d_o[92] = (syndrome_o == 9'h117) ^ in[92]; + assign d_o[93] = (syndrome_o == 9'h67) ^ in[93]; + assign d_o[94] = (syndrome_o == 9'ha7) ^ in[94]; + assign d_o[95] = (syndrome_o == 9'h127) ^ in[95]; + assign d_o[96] = (syndrome_o == 9'hc7) ^ in[96]; + assign d_o[97] = (syndrome_o == 9'h147) ^ in[97]; + assign d_o[98] = (syndrome_o == 9'h187) ^ in[98]; + assign d_o[99] = (syndrome_o == 9'h3b) ^ in[99]; + assign d_o[100] = (syndrome_o == 9'h5b) ^ in[100]; + assign d_o[101] = (syndrome_o == 9'h9b) ^ in[101]; + assign d_o[102] = (syndrome_o == 9'h11b) ^ in[102]; + assign d_o[103] = (syndrome_o == 9'h6b) ^ in[103]; + assign d_o[104] = (syndrome_o == 9'hab) ^ in[104]; + assign d_o[105] = (syndrome_o == 9'h12b) ^ in[105]; + assign d_o[106] = (syndrome_o == 9'hcb) ^ in[106]; + assign d_o[107] = (syndrome_o == 9'h14b) ^ in[107]; + assign d_o[108] = (syndrome_o == 9'h18b) ^ in[108]; + assign d_o[109] = (syndrome_o == 9'h73) ^ in[109]; + assign d_o[110] = (syndrome_o == 9'hb3) ^ in[110]; + assign d_o[111] = (syndrome_o == 9'h133) ^ in[111]; + assign d_o[112] = (syndrome_o == 9'hd3) ^ in[112]; + assign d_o[113] = (syndrome_o == 9'h153) ^ in[113]; + assign d_o[114] = (syndrome_o == 9'h193) ^ in[114]; + assign d_o[115] = (syndrome_o == 9'he3) ^ in[115]; + assign d_o[116] = (syndrome_o == 9'h163) ^ in[116]; + assign d_o[117] = (syndrome_o == 9'h1a3) ^ in[117]; + assign d_o[118] = (syndrome_o == 9'h1c3) ^ in[118]; + assign d_o[119] = (syndrome_o == 9'h3d) ^ in[119]; + assign d_o[120] = (syndrome_o == 9'h5d) ^ in[120]; + assign d_o[121] = (syndrome_o == 9'h9d) ^ in[121]; + assign d_o[122] = (syndrome_o == 9'h11d) ^ in[122]; + assign d_o[123] = (syndrome_o == 9'h6d) ^ in[123]; + assign d_o[124] = (syndrome_o == 9'had) ^ in[124]; + assign d_o[125] = (syndrome_o == 9'h12d) ^ in[125]; + assign d_o[126] = (syndrome_o == 9'hcd) ^ in[126]; + assign d_o[127] = (syndrome_o == 9'h14d) ^ in[127]; + assign d_o[128] = (syndrome_o == 9'h18d) ^ in[128]; + assign d_o[129] = (syndrome_o == 9'h75) ^ in[129]; + assign d_o[130] = (syndrome_o == 9'hb5) ^ in[130]; + assign d_o[131] = (syndrome_o == 9'h135) ^ in[131]; + assign d_o[132] = (syndrome_o == 9'hd5) ^ in[132]; + assign d_o[133] = (syndrome_o == 9'h155) ^ in[133]; + assign d_o[134] = (syndrome_o == 9'h195) ^ in[134]; + assign d_o[135] = (syndrome_o == 9'he5) ^ in[135]; + assign d_o[136] = (syndrome_o == 9'h165) ^ in[136]; + assign d_o[137] = (syndrome_o == 9'h1a5) ^ in[137]; + assign d_o[138] = (syndrome_o == 9'h1c5) ^ in[138]; + assign d_o[139] = (syndrome_o == 9'h79) ^ in[139]; + assign d_o[140] = (syndrome_o == 9'hb9) ^ in[140]; + assign d_o[141] = (syndrome_o == 9'h139) ^ in[141]; + assign d_o[142] = (syndrome_o == 9'hd9) ^ in[142]; + assign d_o[143] = (syndrome_o == 9'h159) ^ in[143]; + assign d_o[144] = (syndrome_o == 9'h199) ^ in[144]; + assign d_o[145] = (syndrome_o == 9'he9) ^ in[145]; + assign d_o[146] = (syndrome_o == 9'h169) ^ in[146]; + assign d_o[147] = (syndrome_o == 9'h1a9) ^ in[147]; + assign d_o[148] = (syndrome_o == 9'h1c9) ^ in[148]; + assign d_o[149] = (syndrome_o == 9'hf1) ^ in[149]; + assign d_o[150] = (syndrome_o == 9'h171) ^ in[150]; + assign d_o[151] = (syndrome_o == 9'h1b1) ^ in[151]; + assign d_o[152] = (syndrome_o == 9'h1d1) ^ in[152]; + assign d_o[153] = (syndrome_o == 9'h1e1) ^ in[153]; + assign d_o[154] = (syndrome_o == 9'h3e) ^ in[154]; + assign d_o[155] = (syndrome_o == 9'h5e) ^ in[155]; + assign d_o[156] = (syndrome_o == 9'h9e) ^ in[156]; + assign d_o[157] = (syndrome_o == 9'h11e) ^ in[157]; + assign d_o[158] = (syndrome_o == 9'h6e) ^ in[158]; + assign d_o[159] = (syndrome_o == 9'hae) ^ in[159]; + assign d_o[160] = (syndrome_o == 9'h12e) ^ in[160]; + assign d_o[161] = (syndrome_o == 9'hce) ^ in[161]; + assign d_o[162] = (syndrome_o == 9'h14e) ^ in[162]; + assign d_o[163] = (syndrome_o == 9'h18e) ^ in[163]; + assign d_o[164] = (syndrome_o == 9'h76) ^ in[164]; + assign d_o[165] = (syndrome_o == 9'hb6) ^ in[165]; + assign d_o[166] = (syndrome_o == 9'h136) ^ in[166]; + assign d_o[167] = (syndrome_o == 9'hd6) ^ in[167]; + assign d_o[168] = (syndrome_o == 9'h156) ^ in[168]; + assign d_o[169] = (syndrome_o == 9'h196) ^ in[169]; + assign d_o[170] = (syndrome_o == 9'he6) ^ in[170]; + assign d_o[171] = (syndrome_o == 9'h166) ^ in[171]; + assign d_o[172] = (syndrome_o == 9'h1a6) ^ in[172]; + assign d_o[173] = (syndrome_o == 9'h1c6) ^ in[173]; + assign d_o[174] = (syndrome_o == 9'h7a) ^ in[174]; + assign d_o[175] = (syndrome_o == 9'hba) ^ in[175]; + assign d_o[176] = (syndrome_o == 9'h13a) ^ in[176]; + assign d_o[177] = (syndrome_o == 9'hda) ^ in[177]; + assign d_o[178] = (syndrome_o == 9'h15a) ^ in[178]; + assign d_o[179] = (syndrome_o == 9'h19a) ^ in[179]; + assign d_o[180] = (syndrome_o == 9'hea) ^ in[180]; + assign d_o[181] = (syndrome_o == 9'h16a) ^ in[181]; + assign d_o[182] = (syndrome_o == 9'h1aa) ^ in[182]; + assign d_o[183] = (syndrome_o == 9'h1ca) ^ in[183]; + assign d_o[184] = (syndrome_o == 9'hf2) ^ in[184]; + assign d_o[185] = (syndrome_o == 9'h172) ^ in[185]; + assign d_o[186] = (syndrome_o == 9'h1b2) ^ in[186]; + assign d_o[187] = (syndrome_o == 9'h1d2) ^ in[187]; + assign d_o[188] = (syndrome_o == 9'h1e2) ^ in[188]; + assign d_o[189] = (syndrome_o == 9'h7c) ^ in[189]; + assign d_o[190] = (syndrome_o == 9'hbc) ^ in[190]; + assign d_o[191] = (syndrome_o == 9'h13c) ^ in[191]; + assign d_o[192] = (syndrome_o == 9'hdc) ^ in[192]; + assign d_o[193] = (syndrome_o == 9'h15c) ^ in[193]; + assign d_o[194] = (syndrome_o == 9'h19c) ^ in[194]; + assign d_o[195] = (syndrome_o == 9'hec) ^ in[195]; + assign d_o[196] = (syndrome_o == 9'h16c) ^ in[196]; + assign d_o[197] = (syndrome_o == 9'h1ac) ^ in[197]; + assign d_o[198] = (syndrome_o == 9'h1cc) ^ in[198]; + assign d_o[199] = (syndrome_o == 9'hf4) ^ in[199]; + assign d_o[200] = (syndrome_o == 9'h174) ^ in[200]; + assign d_o[201] = (syndrome_o == 9'h1b4) ^ in[201]; + assign d_o[202] = (syndrome_o == 9'h1d4) ^ in[202]; + assign d_o[203] = (syndrome_o == 9'h1e4) ^ in[203]; + assign d_o[204] = (syndrome_o == 9'hf8) ^ in[204]; + assign d_o[205] = (syndrome_o == 9'h178) ^ in[205]; + assign d_o[206] = (syndrome_o == 9'h1b8) ^ in[206]; + assign d_o[207] = (syndrome_o == 9'h1d8) ^ in[207]; + assign d_o[208] = (syndrome_o == 9'h1e8) ^ in[208]; + assign d_o[209] = (syndrome_o == 9'h1f0) ^ in[209]; + assign d_o[210] = (syndrome_o == 9'h7f) ^ in[210]; + assign d_o[211] = (syndrome_o == 9'hbf) ^ in[211]; + assign d_o[212] = (syndrome_o == 9'h13f) ^ in[212]; + assign d_o[213] = (syndrome_o == 9'hdf) ^ in[213]; + assign d_o[214] = (syndrome_o == 9'h15f) ^ in[214]; + assign d_o[215] = (syndrome_o == 9'h19f) ^ in[215]; + assign d_o[216] = (syndrome_o == 9'hef) ^ in[216]; + assign d_o[217] = (syndrome_o == 9'h16f) ^ in[217]; + assign d_o[218] = (syndrome_o == 9'h1af) ^ in[218]; + assign d_o[219] = (syndrome_o == 9'h1cf) ^ in[219]; + assign d_o[220] = (syndrome_o == 9'hf7) ^ in[220]; + assign d_o[221] = (syndrome_o == 9'h177) ^ in[221]; + assign d_o[222] = (syndrome_o == 9'h1b7) ^ in[222]; + assign d_o[223] = (syndrome_o == 9'h1d7) ^ in[223]; + assign d_o[224] = (syndrome_o == 9'h1e7) ^ in[224]; + assign d_o[225] = (syndrome_o == 9'hfb) ^ in[225]; + assign d_o[226] = (syndrome_o == 9'h17b) ^ in[226]; + assign d_o[227] = (syndrome_o == 9'h1bb) ^ in[227]; + assign d_o[228] = (syndrome_o == 9'h1db) ^ in[228]; + assign d_o[229] = (syndrome_o == 9'h1eb) ^ in[229]; + assign d_o[230] = (syndrome_o == 9'h1f3) ^ in[230]; + assign d_o[231] = (syndrome_o == 9'hfd) ^ in[231]; + assign d_o[232] = (syndrome_o == 9'h17d) ^ in[232]; + assign d_o[233] = (syndrome_o == 9'h1bd) ^ in[233]; + assign d_o[234] = (syndrome_o == 9'h1dd) ^ in[234]; + assign d_o[235] = (syndrome_o == 9'h1ed) ^ in[235]; + assign d_o[236] = (syndrome_o == 9'h1f5) ^ in[236]; + assign d_o[237] = (syndrome_o == 9'h1f9) ^ in[237]; + assign d_o[238] = (syndrome_o == 9'hfe) ^ in[238]; + assign d_o[239] = (syndrome_o == 9'h17e) ^ in[239]; + assign d_o[240] = (syndrome_o == 9'h1be) ^ in[240]; + assign d_o[241] = (syndrome_o == 9'h1de) ^ in[241]; + assign d_o[242] = (syndrome_o == 9'h1ee) ^ in[242]; + assign d_o[243] = (syndrome_o == 9'h1f6) ^ in[243]; + assign d_o[244] = (syndrome_o == 9'h1fa) ^ in[244]; + assign d_o[245] = (syndrome_o == 9'h1fc) ^ in[245]; + assign d_o[246] = (syndrome_o == 9'h1ff) ^ in[246]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_256_247_dec diff --git a/rtl/lowrisc_ecc/prim_secded_256_247_enc.sv b/rtl/lowrisc_ecc/prim_secded_256_247_enc.sv new file mode 100644 index 00000000..e9758e7a --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_256_247_enc.sv @@ -0,0 +1,26 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Encoder generated by +// util/design/secded_gen.py -m 9 -k 247 -s 1592631616 -c hsiao + +module prim_secded_256_247_enc ( + input [246:0] in, + output logic [255:0] out +); + + always_comb begin : p_encode + out[246:0] = in; + out[247] = ^(in & 247'h403FFFFFFC00000000000003FFFFFFFFFFFFFFFFF00000000000000FFFFFFF); + out[248] = ^(in & 247'h5FC07FFFFC00001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000007F); + out[249] = ^(in & 247'h6FDF81FFFC0FFFE0003FFFFC0007FFFF800007FFF00000FFFE0003F0001F81); + out[250] = ^(in & 247'h77EFBE0FFDF07FE0FFC00FFC1FF801FF801FF801F003FF003E007C1003E082); + out[251] = ^(in & 247'h7BF7DEF0FEF787EF0FC3F03DE1F87E0787E0781E10FC0F03C20784203C2104); + out[252] = ^(in & 247'h7DFBEF771F7BB8F771DC71C6EE3B8E38B8E388E2271C711C44388841C44208); + out[253] = ^(in & 247'h7EFDF7BB67BDDB3BB66D964B76CDB2C95B2C93244B65926488C91086488410); + out[254] = ^(in & 247'h7F7EFBDDABDEED5DDAB6AA93BB56D5526D5525488DAAA4A91152210A910820); + out[255] = ^(in & 247'h7FBF7DEED3EF769EED3B4D23DDA769A4769A46910ED348D221A4420D221040); + end + +endmodule : prim_secded_256_247_enc diff --git a/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv b/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv new file mode 100644 index 00000000..12908105 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv @@ -0,0 +1,60 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 6 -k 22 -s 1592631616 -c hsiao + +module prim_secded_28_22_cor ( + input [27:0] d_i, + output logic [27:0] d_o, + output logic [5:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 28'h07003FF); + assign syndrome_o[1] = ^(d_i & 28'h0A0FC0F); + assign syndrome_o[2] = ^(d_i & 28'h1171C71); + assign syndrome_o[3] = ^(d_i & 28'h23B6592); + assign syndrome_o[4] = ^(d_i & 28'h43DAAA4); + assign syndrome_o[5] = ^(d_i & 28'h83ED348); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 6'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 6'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 6'h13) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 6'h23) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 6'hd) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 6'h15) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 6'h25) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 6'h19) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 6'h29) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 6'h31) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 6'he) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 6'h16) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 6'h26) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 6'h1a) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 6'h2a) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 6'h32) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 6'h1c) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 6'h2c) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 6'h34) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 6'h38) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 6'h3d) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 6'h3b) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 6'h1) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 6'h2) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 6'h4) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 6'h8) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 6'h10) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 6'h20) ^ d_i[27]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_28_22_cor diff --git a/rtl/lowrisc_ecc/prim_secded_28_22_enc.sv b/rtl/lowrisc_ecc/prim_secded_28_22_enc.sv index eeb56668..27bec95d 100644 --- a/rtl/lowrisc_ecc/prim_secded_28_22_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_28_22_enc.sv @@ -11,13 +11,13 @@ module prim_secded_28_22_enc ( ); always_comb begin : p_encode - out = 28'(in); - out[22] = ^(out & 28'h03003FF); - out[23] = ^(out & 28'h020FC0F); - out[24] = ^(out & 28'h0171C71); - out[25] = ^(out & 28'h03B6592); - out[26] = ^(out & 28'h03DAAA4); - out[27] = ^(out & 28'h03ED348); + out[21:0] = in; + out[22] = ^(in & 22'h3003FF); + out[23] = ^(in & 22'h20FC0F); + out[24] = ^(in & 22'h171C71); + out[25] = ^(in & 22'h3B6592); + out[26] = ^(in & 22'h3DAAA4); + out[27] = ^(in & 22'h3ED348); end endmodule : prim_secded_28_22_enc diff --git a/rtl/lowrisc_ecc/prim_secded_32_26_cor.sv b/rtl/lowrisc_ecc/prim_secded_32_26_cor.sv new file mode 100644 index 00000000..01b545e3 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_32_26_cor.sv @@ -0,0 +1,64 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 6 -k 26 -s 1592631616 -c hsiao + +module prim_secded_32_26_cor ( + input [31:0] d_i, + output logic [31:0] d_o, + output logic [5:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 32'h05F003FF); + assign syndrome_o[1] = ^(d_i & 32'h0AF0FC0F); + assign syndrome_o[2] = ^(d_i & 32'h13771C71); + assign syndrome_o[3] = ^(d_i & 32'h23BB6592); + assign syndrome_o[4] = ^(d_i & 32'h43DDAAA4); + assign syndrome_o[5] = ^(d_i & 32'h83EED348); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 6'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 6'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 6'h13) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 6'h23) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 6'hd) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 6'h15) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 6'h25) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 6'h19) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 6'h29) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 6'h31) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 6'he) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 6'h16) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 6'h26) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 6'h1a) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 6'h2a) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 6'h32) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 6'h1c) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 6'h2c) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 6'h34) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 6'h38) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 6'h1f) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 6'h2f) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 6'h37) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 6'h3b) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 6'h3d) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 6'h3e) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 6'h1) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 6'h2) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 6'h4) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 6'h8) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 6'h10) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 6'h20) ^ d_i[31]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_32_26_cor diff --git a/rtl/lowrisc_ecc/prim_secded_32_26_dec.sv b/rtl/lowrisc_ecc/prim_secded_32_26_dec.sv new file mode 100644 index 00000000..680e2ce8 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_32_26_dec.sv @@ -0,0 +1,58 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Decoder generated by +// util/design/secded_gen.py -m 6 -k 26 -s 1592631616 -c hsiao + +module prim_secded_32_26_dec ( + input [31:0] in, + output logic [25:0] d_o, + output logic [5:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(in & 32'h05F003FF); + assign syndrome_o[1] = ^(in & 32'h0AF0FC0F); + assign syndrome_o[2] = ^(in & 32'h13771C71); + assign syndrome_o[3] = ^(in & 32'h23BB6592); + assign syndrome_o[4] = ^(in & 32'h43DDAAA4); + assign syndrome_o[5] = ^(in & 32'h83EED348); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 6'h7) ^ in[0]; + assign d_o[1] = (syndrome_o == 6'hb) ^ in[1]; + assign d_o[2] = (syndrome_o == 6'h13) ^ in[2]; + assign d_o[3] = (syndrome_o == 6'h23) ^ in[3]; + assign d_o[4] = (syndrome_o == 6'hd) ^ in[4]; + assign d_o[5] = (syndrome_o == 6'h15) ^ in[5]; + assign d_o[6] = (syndrome_o == 6'h25) ^ in[6]; + assign d_o[7] = (syndrome_o == 6'h19) ^ in[7]; + assign d_o[8] = (syndrome_o == 6'h29) ^ in[8]; + assign d_o[9] = (syndrome_o == 6'h31) ^ in[9]; + assign d_o[10] = (syndrome_o == 6'he) ^ in[10]; + assign d_o[11] = (syndrome_o == 6'h16) ^ in[11]; + assign d_o[12] = (syndrome_o == 6'h26) ^ in[12]; + assign d_o[13] = (syndrome_o == 6'h1a) ^ in[13]; + assign d_o[14] = (syndrome_o == 6'h2a) ^ in[14]; + assign d_o[15] = (syndrome_o == 6'h32) ^ in[15]; + assign d_o[16] = (syndrome_o == 6'h1c) ^ in[16]; + assign d_o[17] = (syndrome_o == 6'h2c) ^ in[17]; + assign d_o[18] = (syndrome_o == 6'h34) ^ in[18]; + assign d_o[19] = (syndrome_o == 6'h38) ^ in[19]; + assign d_o[20] = (syndrome_o == 6'h1f) ^ in[20]; + assign d_o[21] = (syndrome_o == 6'h2f) ^ in[21]; + assign d_o[22] = (syndrome_o == 6'h37) ^ in[22]; + assign d_o[23] = (syndrome_o == 6'h3b) ^ in[23]; + assign d_o[24] = (syndrome_o == 6'h3d) ^ in[24]; + assign d_o[25] = (syndrome_o == 6'h3e) ^ in[25]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_32_26_dec diff --git a/rtl/lowrisc_ecc/prim_secded_32_26_enc.sv b/rtl/lowrisc_ecc/prim_secded_32_26_enc.sv new file mode 100644 index 00000000..f1d451de --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_32_26_enc.sv @@ -0,0 +1,23 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Encoder generated by +// util/design/secded_gen.py -m 6 -k 26 -s 1592631616 -c hsiao + +module prim_secded_32_26_enc ( + input [25:0] in, + output logic [31:0] out +); + + always_comb begin : p_encode + out[25:0] = in; + out[26] = ^(in & 26'h1F003FF); + out[27] = ^(in & 26'h2F0FC0F); + out[28] = ^(in & 26'h3771C71); + out[29] = ^(in & 26'h3BB6592); + out[30] = ^(in & 26'h3DDAAA4); + out[31] = ^(in & 26'h3EED348); + end + +endmodule : prim_secded_32_26_enc diff --git a/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv b/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv new file mode 100644 index 00000000..725b8b61 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv @@ -0,0 +1,72 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 7 -k 32 -s 1592631616 -c hsiao + +module prim_secded_39_32_cor ( + input [38:0] d_i, + output logic [38:0] d_o, + output logic [6:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 39'h013800CDBC); + assign syndrome_o[1] = ^(d_i & 39'h02C439C325); + assign syndrome_o[2] = ^(d_i & 39'h0452D82C63); + assign syndrome_o[3] = ^(d_i & 39'h08A4363856); + assign syndrome_o[4] = ^(d_i & 39'h109B833109); + assign syndrome_o[5] = ^(d_i & 39'h202DCF42C0); + assign syndrome_o[6] = ^(d_i & 39'h404364969A); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 7'h16) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 7'h4c) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 7'hb) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 7'h51) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 7'h49) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 7'h7) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 7'h2c) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 7'h61) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 7'h13) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 7'h62) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 7'h45) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 7'hd) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 7'h58) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 7'h1c) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 7'h23) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 7'h43) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 7'h32) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 7'h38) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 7'h68) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 7'h26) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 7'he) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 7'h4a) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 7'h64) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 7'h34) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 7'h70) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 7'h54) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 7'h2a) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 7'h31) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 7'h15) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 7'h29) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 7'h46) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 7'h1a) ^ d_i[31]; + assign d_o[32] = (syndrome_o == 7'h1) ^ d_i[32]; + assign d_o[33] = (syndrome_o == 7'h2) ^ d_i[33]; + assign d_o[34] = (syndrome_o == 7'h4) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 7'h8) ^ d_i[35]; + assign d_o[36] = (syndrome_o == 7'h10) ^ d_i[36]; + assign d_o[37] = (syndrome_o == 7'h20) ^ d_i[37]; + assign d_o[38] = (syndrome_o == 7'h40) ^ d_i[38]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_39_32_cor diff --git a/rtl/lowrisc_ecc/prim_secded_39_32_enc.sv b/rtl/lowrisc_ecc/prim_secded_39_32_enc.sv index 5401cc4c..888840c1 100644 --- a/rtl/lowrisc_ecc/prim_secded_39_32_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_39_32_enc.sv @@ -11,14 +11,14 @@ module prim_secded_39_32_enc ( ); always_comb begin : p_encode - out = 39'(in); - out[32] = ^(out & 39'h003800CDBC); - out[33] = ^(out & 39'h00C439C325); - out[34] = ^(out & 39'h0052D82C63); - out[35] = ^(out & 39'h00A4363856); - out[36] = ^(out & 39'h009B833109); - out[37] = ^(out & 39'h002DCF42C0); - out[38] = ^(out & 39'h004364969A); + out[31:0] = in; + out[32] = ^(in & 32'h3800CDBC); + out[33] = ^(in & 32'hC439C325); + out[34] = ^(in & 32'h52D82C63); + out[35] = ^(in & 32'hA4363856); + out[36] = ^(in & 32'h9B833109); + out[37] = ^(in & 32'h2DCF42C0); + out[38] = ^(in & 32'h4364969A); end endmodule : prim_secded_39_32_enc diff --git a/rtl/lowrisc_ecc/prim_secded_4_1_cor.sv b/rtl/lowrisc_ecc/prim_secded_4_1_cor.sv new file mode 100644 index 00000000..960563ec --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_4_1_cor.sv @@ -0,0 +1,33 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 3 -k 1 -s 1592631616 -c hsiao + +module prim_secded_4_1_cor ( + input [3:0] d_i, + output logic [3:0] d_o, + output logic [2:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 4'h3); + assign syndrome_o[1] = ^(d_i & 4'h5); + assign syndrome_o[2] = ^(d_i & 4'h9); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 3'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 3'h1) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 3'h2) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 3'h4) ^ d_i[3]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_4_1_cor diff --git a/rtl/lowrisc_ecc/prim_secded_4_1_dec.sv b/rtl/lowrisc_ecc/prim_secded_4_1_dec.sv new file mode 100644 index 00000000..6b13677c --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_4_1_dec.sv @@ -0,0 +1,30 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Decoder generated by +// util/design/secded_gen.py -m 3 -k 1 -s 1592631616 -c hsiao + +module prim_secded_4_1_dec ( + input [3:0] in, + output logic [0:0] d_o, + output logic [2:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(in & 4'h3); + assign syndrome_o[1] = ^(in & 4'h5); + assign syndrome_o[2] = ^(in & 4'h9); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 3'h7) ^ in[0]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_4_1_dec diff --git a/rtl/lowrisc_ecc/prim_secded_4_1_enc.sv b/rtl/lowrisc_ecc/prim_secded_4_1_enc.sv new file mode 100644 index 00000000..75cc2271 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_4_1_enc.sv @@ -0,0 +1,20 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Encoder generated by +// util/design/secded_gen.py -m 3 -k 1 -s 1592631616 -c hsiao + +module prim_secded_4_1_enc ( + input [0:0] in, + output logic [3:0] out +); + + always_comb begin : p_encode + out[0:0] = in; + out[1] = ^(in & 1'h1); + out[2] = ^(in & 1'h1); + out[3] = ^(in & 1'h1); + end + +endmodule : prim_secded_4_1_enc diff --git a/rtl/lowrisc_ecc/prim_secded_512_502_cor.sv b/rtl/lowrisc_ecc/prim_secded_512_502_cor.sv new file mode 100644 index 00000000..3e3662e1 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_512_502_cor.sv @@ -0,0 +1,548 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 10 -k 502 -s 1592631616 -c hsiao + +module prim_secded_512_502_cor ( + input [511:0] d_i, + output logic [511:0] d_o, + output logic [9:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 512'h005FF000000000FFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000FFFFFFFFF); + assign syndrome_o[1] = ^(d_i & 512'h00AFF00FFFFFFF0000000FFFFFFFFFFFFFF00000000000000FFFFFFFFFFFFFFFFFC00000000000000000FFFFFFFFFFFFFF00000000000000FFFFFFF0000000FF); + assign syndrome_o[2] = ^(d_i & 512'h0137F7F01FFFFF01FFFFF000007FFFFFFFF000007FFFFFFFF000000001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000000001FFFFF000007F000007F01); + assign syndrome_o[3] = ^(d_i & 512'h023BFBF7E07FFF7E07FFF03FFF8000FFFFF03FFF8000FFFFF0001FFFFE00001FFFC0007FFFF800007FFF00000FFFE0003F00000FFFE0003F0001F810001F8102); + assign syndrome_o[4] = ^(d_i & 512'h043DFDFBEF83FFBEF83FF7C1FF83FF003FF7C1FF83FF003FF07FE007FE007FE007C1FF801FF801FF801F003FF003E007C1003FF003E007C1003E082003E08204); + assign syndrome_o[5] = ^(d_i & 512'h083EFEFDF7BC3FDF7BC3FBDE1FBC3F0FC0FBDE1FBC3F0FC0F787E1F81E1F81E0785E1F87E0787E0781E10FC0F03C2078420FC0F03C20784203C210403C210408); + assign syndrome_o[6] = ^(d_i & 512'h103F7F7EFBDDC7EFBDDC7DEEE3DDC771C71DEEE3DDC771C71BB8EE38E2E38E2388AEE3B8E38B8E388E2271C711C443888471C711C44388841C442081C4420810); + assign syndrome_o[7] = ^(d_i & 512'h203FBFBF7DEED9F7DEED9EF76CEED9B6592EF76CEED9B6592DDB36CB256CB24C91376CDB2C95B2C93244B65926488C9108B65926488C91086488410648841020); + assign syndrome_o[8] = ^(d_i & 512'h403FDFDFBEF76AFBEF76AF7BB5776ADAAA4F7BB5776ADAAA4EED5B5549B55495223BB56D5526D5525488DAAA4A91152210DAAA4A91152210A910820A91082040); + assign syndrome_o[9] = ^(d_i & 512'h803FEFEFDF7BB4FDF7BB4FBDDA7BB4ED348FBDDA7BB4ED348F769DA691DA691A443DDA769A4769A46910ED348D221A4420ED348D221A4420D221040D22104080); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 10'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 10'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 10'h13) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 10'h23) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 10'h43) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 10'h83) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 10'h103) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 10'h203) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 10'hd) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 10'h15) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 10'h25) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 10'h45) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 10'h85) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 10'h105) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 10'h205) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 10'h19) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 10'h29) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 10'h49) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 10'h89) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 10'h109) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 10'h209) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 10'h31) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 10'h51) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 10'h91) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 10'h111) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 10'h211) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 10'h61) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 10'ha1) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 10'h121) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 10'h221) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 10'hc1) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 10'h141) ^ d_i[31]; + assign d_o[32] = (syndrome_o == 10'h241) ^ d_i[32]; + assign d_o[33] = (syndrome_o == 10'h181) ^ d_i[33]; + assign d_o[34] = (syndrome_o == 10'h281) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 10'h301) ^ d_i[35]; + assign d_o[36] = (syndrome_o == 10'he) ^ d_i[36]; + assign d_o[37] = (syndrome_o == 10'h16) ^ d_i[37]; + assign d_o[38] = (syndrome_o == 10'h26) ^ d_i[38]; + assign d_o[39] = (syndrome_o == 10'h46) ^ d_i[39]; + assign d_o[40] = (syndrome_o == 10'h86) ^ d_i[40]; + assign d_o[41] = (syndrome_o == 10'h106) ^ d_i[41]; + assign d_o[42] = (syndrome_o == 10'h206) ^ d_i[42]; + assign d_o[43] = (syndrome_o == 10'h1a) ^ d_i[43]; + assign d_o[44] = (syndrome_o == 10'h2a) ^ d_i[44]; + assign d_o[45] = (syndrome_o == 10'h4a) ^ d_i[45]; + assign d_o[46] = (syndrome_o == 10'h8a) ^ d_i[46]; + assign d_o[47] = (syndrome_o == 10'h10a) ^ d_i[47]; + assign d_o[48] = (syndrome_o == 10'h20a) ^ d_i[48]; + assign d_o[49] = (syndrome_o == 10'h32) ^ d_i[49]; + assign d_o[50] = (syndrome_o == 10'h52) ^ d_i[50]; + assign d_o[51] = (syndrome_o == 10'h92) ^ d_i[51]; + assign d_o[52] = (syndrome_o == 10'h112) ^ d_i[52]; + assign d_o[53] = (syndrome_o == 10'h212) ^ d_i[53]; + assign d_o[54] = (syndrome_o == 10'h62) ^ d_i[54]; + assign d_o[55] = (syndrome_o == 10'ha2) ^ d_i[55]; + assign d_o[56] = (syndrome_o == 10'h122) ^ d_i[56]; + assign d_o[57] = (syndrome_o == 10'h222) ^ d_i[57]; + assign d_o[58] = (syndrome_o == 10'hc2) ^ d_i[58]; + assign d_o[59] = (syndrome_o == 10'h142) ^ d_i[59]; + assign d_o[60] = (syndrome_o == 10'h242) ^ d_i[60]; + assign d_o[61] = (syndrome_o == 10'h182) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 10'h282) ^ d_i[62]; + assign d_o[63] = (syndrome_o == 10'h302) ^ d_i[63]; + assign d_o[64] = (syndrome_o == 10'h1c) ^ d_i[64]; + assign d_o[65] = (syndrome_o == 10'h2c) ^ d_i[65]; + assign d_o[66] = (syndrome_o == 10'h4c) ^ d_i[66]; + assign d_o[67] = (syndrome_o == 10'h8c) ^ d_i[67]; + assign d_o[68] = (syndrome_o == 10'h10c) ^ d_i[68]; + assign d_o[69] = (syndrome_o == 10'h20c) ^ d_i[69]; + assign d_o[70] = (syndrome_o == 10'h34) ^ d_i[70]; + assign d_o[71] = (syndrome_o == 10'h54) ^ d_i[71]; + assign d_o[72] = (syndrome_o == 10'h94) ^ d_i[72]; + assign d_o[73] = (syndrome_o == 10'h114) ^ d_i[73]; + assign d_o[74] = (syndrome_o == 10'h214) ^ d_i[74]; + assign d_o[75] = (syndrome_o == 10'h64) ^ d_i[75]; + assign d_o[76] = (syndrome_o == 10'ha4) ^ d_i[76]; + assign d_o[77] = (syndrome_o == 10'h124) ^ d_i[77]; + assign d_o[78] = (syndrome_o == 10'h224) ^ d_i[78]; + assign d_o[79] = (syndrome_o == 10'hc4) ^ d_i[79]; + assign d_o[80] = (syndrome_o == 10'h144) ^ d_i[80]; + assign d_o[81] = (syndrome_o == 10'h244) ^ d_i[81]; + assign d_o[82] = (syndrome_o == 10'h184) ^ d_i[82]; + assign d_o[83] = (syndrome_o == 10'h284) ^ d_i[83]; + assign d_o[84] = (syndrome_o == 10'h304) ^ d_i[84]; + assign d_o[85] = (syndrome_o == 10'h38) ^ d_i[85]; + assign d_o[86] = (syndrome_o == 10'h58) ^ d_i[86]; + assign d_o[87] = (syndrome_o == 10'h98) ^ d_i[87]; + assign d_o[88] = (syndrome_o == 10'h118) ^ d_i[88]; + assign d_o[89] = (syndrome_o == 10'h218) ^ d_i[89]; + assign d_o[90] = (syndrome_o == 10'h68) ^ d_i[90]; + assign d_o[91] = (syndrome_o == 10'ha8) ^ d_i[91]; + assign d_o[92] = (syndrome_o == 10'h128) ^ d_i[92]; + assign d_o[93] = (syndrome_o == 10'h228) ^ d_i[93]; + assign d_o[94] = (syndrome_o == 10'hc8) ^ d_i[94]; + assign d_o[95] = (syndrome_o == 10'h148) ^ d_i[95]; + assign d_o[96] = (syndrome_o == 10'h248) ^ d_i[96]; + assign d_o[97] = (syndrome_o == 10'h188) ^ d_i[97]; + assign d_o[98] = (syndrome_o == 10'h288) ^ d_i[98]; + assign d_o[99] = (syndrome_o == 10'h308) ^ d_i[99]; + assign d_o[100] = (syndrome_o == 10'h70) ^ d_i[100]; + assign d_o[101] = (syndrome_o == 10'hb0) ^ d_i[101]; + assign d_o[102] = (syndrome_o == 10'h130) ^ d_i[102]; + assign d_o[103] = (syndrome_o == 10'h230) ^ d_i[103]; + assign d_o[104] = (syndrome_o == 10'hd0) ^ d_i[104]; + assign d_o[105] = (syndrome_o == 10'h150) ^ d_i[105]; + assign d_o[106] = (syndrome_o == 10'h250) ^ d_i[106]; + assign d_o[107] = (syndrome_o == 10'h190) ^ d_i[107]; + assign d_o[108] = (syndrome_o == 10'h290) ^ d_i[108]; + assign d_o[109] = (syndrome_o == 10'h310) ^ d_i[109]; + assign d_o[110] = (syndrome_o == 10'he0) ^ d_i[110]; + assign d_o[111] = (syndrome_o == 10'h160) ^ d_i[111]; + assign d_o[112] = (syndrome_o == 10'h260) ^ d_i[112]; + assign d_o[113] = (syndrome_o == 10'h1a0) ^ d_i[113]; + assign d_o[114] = (syndrome_o == 10'h2a0) ^ d_i[114]; + assign d_o[115] = (syndrome_o == 10'h320) ^ d_i[115]; + assign d_o[116] = (syndrome_o == 10'h1c0) ^ d_i[116]; + assign d_o[117] = (syndrome_o == 10'h2c0) ^ d_i[117]; + assign d_o[118] = (syndrome_o == 10'h340) ^ d_i[118]; + assign d_o[119] = (syndrome_o == 10'h380) ^ d_i[119]; + assign d_o[120] = (syndrome_o == 10'h1f) ^ d_i[120]; + assign d_o[121] = (syndrome_o == 10'h2f) ^ d_i[121]; + assign d_o[122] = (syndrome_o == 10'h4f) ^ d_i[122]; + assign d_o[123] = (syndrome_o == 10'h8f) ^ d_i[123]; + assign d_o[124] = (syndrome_o == 10'h10f) ^ d_i[124]; + assign d_o[125] = (syndrome_o == 10'h20f) ^ d_i[125]; + assign d_o[126] = (syndrome_o == 10'h37) ^ d_i[126]; + assign d_o[127] = (syndrome_o == 10'h57) ^ d_i[127]; + assign d_o[128] = (syndrome_o == 10'h97) ^ d_i[128]; + assign d_o[129] = (syndrome_o == 10'h117) ^ d_i[129]; + assign d_o[130] = (syndrome_o == 10'h217) ^ d_i[130]; + assign d_o[131] = (syndrome_o == 10'h67) ^ d_i[131]; + assign d_o[132] = (syndrome_o == 10'ha7) ^ d_i[132]; + assign d_o[133] = (syndrome_o == 10'h127) ^ d_i[133]; + assign d_o[134] = (syndrome_o == 10'h227) ^ d_i[134]; + assign d_o[135] = (syndrome_o == 10'hc7) ^ d_i[135]; + assign d_o[136] = (syndrome_o == 10'h147) ^ d_i[136]; + assign d_o[137] = (syndrome_o == 10'h247) ^ d_i[137]; + assign d_o[138] = (syndrome_o == 10'h187) ^ d_i[138]; + assign d_o[139] = (syndrome_o == 10'h287) ^ d_i[139]; + assign d_o[140] = (syndrome_o == 10'h307) ^ d_i[140]; + assign d_o[141] = (syndrome_o == 10'h3b) ^ d_i[141]; + assign d_o[142] = (syndrome_o == 10'h5b) ^ d_i[142]; + assign d_o[143] = (syndrome_o == 10'h9b) ^ d_i[143]; + assign d_o[144] = (syndrome_o == 10'h11b) ^ d_i[144]; + assign d_o[145] = (syndrome_o == 10'h21b) ^ d_i[145]; + assign d_o[146] = (syndrome_o == 10'h6b) ^ d_i[146]; + assign d_o[147] = (syndrome_o == 10'hab) ^ d_i[147]; + assign d_o[148] = (syndrome_o == 10'h12b) ^ d_i[148]; + assign d_o[149] = (syndrome_o == 10'h22b) ^ d_i[149]; + assign d_o[150] = (syndrome_o == 10'hcb) ^ d_i[150]; + assign d_o[151] = (syndrome_o == 10'h14b) ^ d_i[151]; + assign d_o[152] = (syndrome_o == 10'h24b) ^ d_i[152]; + assign d_o[153] = (syndrome_o == 10'h18b) ^ d_i[153]; + assign d_o[154] = (syndrome_o == 10'h28b) ^ d_i[154]; + assign d_o[155] = (syndrome_o == 10'h30b) ^ d_i[155]; + assign d_o[156] = (syndrome_o == 10'h73) ^ d_i[156]; + assign d_o[157] = (syndrome_o == 10'hb3) ^ d_i[157]; + assign d_o[158] = (syndrome_o == 10'h133) ^ d_i[158]; + assign d_o[159] = (syndrome_o == 10'h233) ^ d_i[159]; + assign d_o[160] = (syndrome_o == 10'hd3) ^ d_i[160]; + assign d_o[161] = (syndrome_o == 10'h153) ^ d_i[161]; + assign d_o[162] = (syndrome_o == 10'h253) ^ d_i[162]; + assign d_o[163] = (syndrome_o == 10'h193) ^ d_i[163]; + assign d_o[164] = (syndrome_o == 10'h293) ^ d_i[164]; + assign d_o[165] = (syndrome_o == 10'h313) ^ d_i[165]; + assign d_o[166] = (syndrome_o == 10'he3) ^ d_i[166]; + assign d_o[167] = (syndrome_o == 10'h163) ^ d_i[167]; + assign d_o[168] = (syndrome_o == 10'h263) ^ d_i[168]; + assign d_o[169] = (syndrome_o == 10'h1a3) ^ d_i[169]; + assign d_o[170] = (syndrome_o == 10'h2a3) ^ d_i[170]; + assign d_o[171] = (syndrome_o == 10'h323) ^ d_i[171]; + assign d_o[172] = (syndrome_o == 10'h1c3) ^ d_i[172]; + assign d_o[173] = (syndrome_o == 10'h2c3) ^ d_i[173]; + assign d_o[174] = (syndrome_o == 10'h343) ^ d_i[174]; + assign d_o[175] = (syndrome_o == 10'h383) ^ d_i[175]; + assign d_o[176] = (syndrome_o == 10'h3d) ^ d_i[176]; + assign d_o[177] = (syndrome_o == 10'h5d) ^ d_i[177]; + assign d_o[178] = (syndrome_o == 10'h9d) ^ d_i[178]; + assign d_o[179] = (syndrome_o == 10'h11d) ^ d_i[179]; + assign d_o[180] = (syndrome_o == 10'h21d) ^ d_i[180]; + assign d_o[181] = (syndrome_o == 10'h6d) ^ d_i[181]; + assign d_o[182] = (syndrome_o == 10'had) ^ d_i[182]; + assign d_o[183] = (syndrome_o == 10'h12d) ^ d_i[183]; + assign d_o[184] = (syndrome_o == 10'h22d) ^ d_i[184]; + assign d_o[185] = (syndrome_o == 10'hcd) ^ d_i[185]; + assign d_o[186] = (syndrome_o == 10'h14d) ^ d_i[186]; + assign d_o[187] = (syndrome_o == 10'h24d) ^ d_i[187]; + assign d_o[188] = (syndrome_o == 10'h18d) ^ d_i[188]; + assign d_o[189] = (syndrome_o == 10'h28d) ^ d_i[189]; + assign d_o[190] = (syndrome_o == 10'h30d) ^ d_i[190]; + assign d_o[191] = (syndrome_o == 10'h75) ^ d_i[191]; + assign d_o[192] = (syndrome_o == 10'hb5) ^ d_i[192]; + assign d_o[193] = (syndrome_o == 10'h135) ^ d_i[193]; + assign d_o[194] = (syndrome_o == 10'h235) ^ d_i[194]; + assign d_o[195] = (syndrome_o == 10'hd5) ^ d_i[195]; + assign d_o[196] = (syndrome_o == 10'h155) ^ d_i[196]; + assign d_o[197] = (syndrome_o == 10'h255) ^ d_i[197]; + assign d_o[198] = (syndrome_o == 10'h195) ^ d_i[198]; + assign d_o[199] = (syndrome_o == 10'h295) ^ d_i[199]; + assign d_o[200] = (syndrome_o == 10'h315) ^ d_i[200]; + assign d_o[201] = (syndrome_o == 10'he5) ^ d_i[201]; + assign d_o[202] = (syndrome_o == 10'h165) ^ d_i[202]; + assign d_o[203] = (syndrome_o == 10'h265) ^ d_i[203]; + assign d_o[204] = (syndrome_o == 10'h1a5) ^ d_i[204]; + assign d_o[205] = (syndrome_o == 10'h2a5) ^ d_i[205]; + assign d_o[206] = (syndrome_o == 10'h325) ^ d_i[206]; + assign d_o[207] = (syndrome_o == 10'h1c5) ^ d_i[207]; + assign d_o[208] = (syndrome_o == 10'h2c5) ^ d_i[208]; + assign d_o[209] = (syndrome_o == 10'h345) ^ d_i[209]; + assign d_o[210] = (syndrome_o == 10'h385) ^ d_i[210]; + assign d_o[211] = (syndrome_o == 10'h79) ^ d_i[211]; + assign d_o[212] = (syndrome_o == 10'hb9) ^ d_i[212]; + assign d_o[213] = (syndrome_o == 10'h139) ^ d_i[213]; + assign d_o[214] = (syndrome_o == 10'h239) ^ d_i[214]; + assign d_o[215] = (syndrome_o == 10'hd9) ^ d_i[215]; + assign d_o[216] = (syndrome_o == 10'h159) ^ d_i[216]; + assign d_o[217] = (syndrome_o == 10'h259) ^ d_i[217]; + assign d_o[218] = (syndrome_o == 10'h199) ^ d_i[218]; + assign d_o[219] = (syndrome_o == 10'h299) ^ d_i[219]; + assign d_o[220] = (syndrome_o == 10'h319) ^ d_i[220]; + assign d_o[221] = (syndrome_o == 10'he9) ^ d_i[221]; + assign d_o[222] = (syndrome_o == 10'h169) ^ d_i[222]; + assign d_o[223] = (syndrome_o == 10'h269) ^ d_i[223]; + assign d_o[224] = (syndrome_o == 10'h1a9) ^ d_i[224]; + assign d_o[225] = (syndrome_o == 10'h2a9) ^ d_i[225]; + assign d_o[226] = (syndrome_o == 10'h329) ^ d_i[226]; + assign d_o[227] = (syndrome_o == 10'h1c9) ^ d_i[227]; + assign d_o[228] = (syndrome_o == 10'h2c9) ^ d_i[228]; + assign d_o[229] = (syndrome_o == 10'h349) ^ d_i[229]; + assign d_o[230] = (syndrome_o == 10'h389) ^ d_i[230]; + assign d_o[231] = (syndrome_o == 10'hf1) ^ d_i[231]; + assign d_o[232] = (syndrome_o == 10'h171) ^ d_i[232]; + assign d_o[233] = (syndrome_o == 10'h271) ^ d_i[233]; + assign d_o[234] = (syndrome_o == 10'h1b1) ^ d_i[234]; + assign d_o[235] = (syndrome_o == 10'h2b1) ^ d_i[235]; + assign d_o[236] = (syndrome_o == 10'h331) ^ d_i[236]; + assign d_o[237] = (syndrome_o == 10'h1d1) ^ d_i[237]; + assign d_o[238] = (syndrome_o == 10'h2d1) ^ d_i[238]; + assign d_o[239] = (syndrome_o == 10'h351) ^ d_i[239]; + assign d_o[240] = (syndrome_o == 10'h391) ^ d_i[240]; + assign d_o[241] = (syndrome_o == 10'h1e1) ^ d_i[241]; + assign d_o[242] = (syndrome_o == 10'h2e1) ^ d_i[242]; + assign d_o[243] = (syndrome_o == 10'h361) ^ d_i[243]; + assign d_o[244] = (syndrome_o == 10'h3a1) ^ d_i[244]; + assign d_o[245] = (syndrome_o == 10'h3c1) ^ d_i[245]; + assign d_o[246] = (syndrome_o == 10'h3e) ^ d_i[246]; + assign d_o[247] = (syndrome_o == 10'h5e) ^ d_i[247]; + assign d_o[248] = (syndrome_o == 10'h9e) ^ d_i[248]; + assign d_o[249] = (syndrome_o == 10'h11e) ^ d_i[249]; + assign d_o[250] = (syndrome_o == 10'h21e) ^ d_i[250]; + assign d_o[251] = (syndrome_o == 10'h6e) ^ d_i[251]; + assign d_o[252] = (syndrome_o == 10'hae) ^ d_i[252]; + assign d_o[253] = (syndrome_o == 10'h12e) ^ d_i[253]; + assign d_o[254] = (syndrome_o == 10'h22e) ^ d_i[254]; + assign d_o[255] = (syndrome_o == 10'hce) ^ d_i[255]; + assign d_o[256] = (syndrome_o == 10'h14e) ^ d_i[256]; + assign d_o[257] = (syndrome_o == 10'h24e) ^ d_i[257]; + assign d_o[258] = (syndrome_o == 10'h18e) ^ d_i[258]; + assign d_o[259] = (syndrome_o == 10'h28e) ^ d_i[259]; + assign d_o[260] = (syndrome_o == 10'h30e) ^ d_i[260]; + assign d_o[261] = (syndrome_o == 10'h76) ^ d_i[261]; + assign d_o[262] = (syndrome_o == 10'hb6) ^ d_i[262]; + assign d_o[263] = (syndrome_o == 10'h136) ^ d_i[263]; + assign d_o[264] = (syndrome_o == 10'h236) ^ d_i[264]; + assign d_o[265] = (syndrome_o == 10'hd6) ^ d_i[265]; + assign d_o[266] = (syndrome_o == 10'h156) ^ d_i[266]; + assign d_o[267] = (syndrome_o == 10'h256) ^ d_i[267]; + assign d_o[268] = (syndrome_o == 10'h196) ^ d_i[268]; + assign d_o[269] = (syndrome_o == 10'h296) ^ d_i[269]; + assign d_o[270] = (syndrome_o == 10'h316) ^ d_i[270]; + assign d_o[271] = (syndrome_o == 10'he6) ^ d_i[271]; + assign d_o[272] = (syndrome_o == 10'h166) ^ d_i[272]; + assign d_o[273] = (syndrome_o == 10'h266) ^ d_i[273]; + assign d_o[274] = (syndrome_o == 10'h1a6) ^ d_i[274]; + assign d_o[275] = (syndrome_o == 10'h2a6) ^ d_i[275]; + assign d_o[276] = (syndrome_o == 10'h326) ^ d_i[276]; + assign d_o[277] = (syndrome_o == 10'h1c6) ^ d_i[277]; + assign d_o[278] = (syndrome_o == 10'h2c6) ^ d_i[278]; + assign d_o[279] = (syndrome_o == 10'h346) ^ d_i[279]; + assign d_o[280] = (syndrome_o == 10'h386) ^ d_i[280]; + assign d_o[281] = (syndrome_o == 10'h7a) ^ d_i[281]; + assign d_o[282] = (syndrome_o == 10'hba) ^ d_i[282]; + assign d_o[283] = (syndrome_o == 10'h13a) ^ d_i[283]; + assign d_o[284] = (syndrome_o == 10'h23a) ^ d_i[284]; + assign d_o[285] = (syndrome_o == 10'hda) ^ d_i[285]; + assign d_o[286] = (syndrome_o == 10'h15a) ^ d_i[286]; + assign d_o[287] = (syndrome_o == 10'h25a) ^ d_i[287]; + assign d_o[288] = (syndrome_o == 10'h19a) ^ d_i[288]; + assign d_o[289] = (syndrome_o == 10'h29a) ^ d_i[289]; + assign d_o[290] = (syndrome_o == 10'h31a) ^ d_i[290]; + assign d_o[291] = (syndrome_o == 10'hea) ^ d_i[291]; + assign d_o[292] = (syndrome_o == 10'h16a) ^ d_i[292]; + assign d_o[293] = (syndrome_o == 10'h26a) ^ d_i[293]; + assign d_o[294] = (syndrome_o == 10'h1aa) ^ d_i[294]; + assign d_o[295] = (syndrome_o == 10'h2aa) ^ d_i[295]; + assign d_o[296] = (syndrome_o == 10'h32a) ^ d_i[296]; + assign d_o[297] = (syndrome_o == 10'h1ca) ^ d_i[297]; + assign d_o[298] = (syndrome_o == 10'h2ca) ^ d_i[298]; + assign d_o[299] = (syndrome_o == 10'h34a) ^ d_i[299]; + assign d_o[300] = (syndrome_o == 10'h38a) ^ d_i[300]; + assign d_o[301] = (syndrome_o == 10'hf2) ^ d_i[301]; + assign d_o[302] = (syndrome_o == 10'h172) ^ d_i[302]; + assign d_o[303] = (syndrome_o == 10'h272) ^ d_i[303]; + assign d_o[304] = (syndrome_o == 10'h1b2) ^ d_i[304]; + assign d_o[305] = (syndrome_o == 10'h2b2) ^ d_i[305]; + assign d_o[306] = (syndrome_o == 10'h332) ^ d_i[306]; + assign d_o[307] = (syndrome_o == 10'h1d2) ^ d_i[307]; + assign d_o[308] = (syndrome_o == 10'h2d2) ^ d_i[308]; + assign d_o[309] = (syndrome_o == 10'h352) ^ d_i[309]; + assign d_o[310] = (syndrome_o == 10'h392) ^ d_i[310]; + assign d_o[311] = (syndrome_o == 10'h1e2) ^ d_i[311]; + assign d_o[312] = (syndrome_o == 10'h2e2) ^ d_i[312]; + assign d_o[313] = (syndrome_o == 10'h362) ^ d_i[313]; + assign d_o[314] = (syndrome_o == 10'h3a2) ^ d_i[314]; + assign d_o[315] = (syndrome_o == 10'h3c2) ^ d_i[315]; + assign d_o[316] = (syndrome_o == 10'h7c) ^ d_i[316]; + assign d_o[317] = (syndrome_o == 10'hbc) ^ d_i[317]; + assign d_o[318] = (syndrome_o == 10'h13c) ^ d_i[318]; + assign d_o[319] = (syndrome_o == 10'h23c) ^ d_i[319]; + assign d_o[320] = (syndrome_o == 10'hdc) ^ d_i[320]; + assign d_o[321] = (syndrome_o == 10'h15c) ^ d_i[321]; + assign d_o[322] = (syndrome_o == 10'h25c) ^ d_i[322]; + assign d_o[323] = (syndrome_o == 10'h19c) ^ d_i[323]; + assign d_o[324] = (syndrome_o == 10'h29c) ^ d_i[324]; + assign d_o[325] = (syndrome_o == 10'h31c) ^ d_i[325]; + assign d_o[326] = (syndrome_o == 10'hec) ^ d_i[326]; + assign d_o[327] = (syndrome_o == 10'h16c) ^ d_i[327]; + assign d_o[328] = (syndrome_o == 10'h26c) ^ d_i[328]; + assign d_o[329] = (syndrome_o == 10'h1ac) ^ d_i[329]; + assign d_o[330] = (syndrome_o == 10'h2ac) ^ d_i[330]; + assign d_o[331] = (syndrome_o == 10'h32c) ^ d_i[331]; + assign d_o[332] = (syndrome_o == 10'h1cc) ^ d_i[332]; + assign d_o[333] = (syndrome_o == 10'h2cc) ^ d_i[333]; + assign d_o[334] = (syndrome_o == 10'h34c) ^ d_i[334]; + assign d_o[335] = (syndrome_o == 10'h38c) ^ d_i[335]; + assign d_o[336] = (syndrome_o == 10'hf4) ^ d_i[336]; + assign d_o[337] = (syndrome_o == 10'h174) ^ d_i[337]; + assign d_o[338] = (syndrome_o == 10'h274) ^ d_i[338]; + assign d_o[339] = (syndrome_o == 10'h1b4) ^ d_i[339]; + assign d_o[340] = (syndrome_o == 10'h2b4) ^ d_i[340]; + assign d_o[341] = (syndrome_o == 10'h334) ^ d_i[341]; + assign d_o[342] = (syndrome_o == 10'h1d4) ^ d_i[342]; + assign d_o[343] = (syndrome_o == 10'h2d4) ^ d_i[343]; + assign d_o[344] = (syndrome_o == 10'h354) ^ d_i[344]; + assign d_o[345] = (syndrome_o == 10'h394) ^ d_i[345]; + assign d_o[346] = (syndrome_o == 10'h1e4) ^ d_i[346]; + assign d_o[347] = (syndrome_o == 10'h2e4) ^ d_i[347]; + assign d_o[348] = (syndrome_o == 10'h364) ^ d_i[348]; + assign d_o[349] = (syndrome_o == 10'h3a4) ^ d_i[349]; + assign d_o[350] = (syndrome_o == 10'h3c4) ^ d_i[350]; + assign d_o[351] = (syndrome_o == 10'hf8) ^ d_i[351]; + assign d_o[352] = (syndrome_o == 10'h178) ^ d_i[352]; + assign d_o[353] = (syndrome_o == 10'h278) ^ d_i[353]; + assign d_o[354] = (syndrome_o == 10'h1b8) ^ d_i[354]; + assign d_o[355] = (syndrome_o == 10'h2b8) ^ d_i[355]; + assign d_o[356] = (syndrome_o == 10'h338) ^ d_i[356]; + assign d_o[357] = (syndrome_o == 10'h1d8) ^ d_i[357]; + assign d_o[358] = (syndrome_o == 10'h2d8) ^ d_i[358]; + assign d_o[359] = (syndrome_o == 10'h358) ^ d_i[359]; + assign d_o[360] = (syndrome_o == 10'h398) ^ d_i[360]; + assign d_o[361] = (syndrome_o == 10'h1e8) ^ d_i[361]; + assign d_o[362] = (syndrome_o == 10'h2e8) ^ d_i[362]; + assign d_o[363] = (syndrome_o == 10'h368) ^ d_i[363]; + assign d_o[364] = (syndrome_o == 10'h3a8) ^ d_i[364]; + assign d_o[365] = (syndrome_o == 10'h3c8) ^ d_i[365]; + assign d_o[366] = (syndrome_o == 10'h1f0) ^ d_i[366]; + assign d_o[367] = (syndrome_o == 10'h2f0) ^ d_i[367]; + assign d_o[368] = (syndrome_o == 10'h370) ^ d_i[368]; + assign d_o[369] = (syndrome_o == 10'h3b0) ^ d_i[369]; + assign d_o[370] = (syndrome_o == 10'h3d0) ^ d_i[370]; + assign d_o[371] = (syndrome_o == 10'h3e0) ^ d_i[371]; + assign d_o[372] = (syndrome_o == 10'h7f) ^ d_i[372]; + assign d_o[373] = (syndrome_o == 10'hbf) ^ d_i[373]; + assign d_o[374] = (syndrome_o == 10'h13f) ^ d_i[374]; + assign d_o[375] = (syndrome_o == 10'h23f) ^ d_i[375]; + assign d_o[376] = (syndrome_o == 10'hdf) ^ d_i[376]; + assign d_o[377] = (syndrome_o == 10'h15f) ^ d_i[377]; + assign d_o[378] = (syndrome_o == 10'h25f) ^ d_i[378]; + assign d_o[379] = (syndrome_o == 10'h19f) ^ d_i[379]; + assign d_o[380] = (syndrome_o == 10'h29f) ^ d_i[380]; + assign d_o[381] = (syndrome_o == 10'h31f) ^ d_i[381]; + assign d_o[382] = (syndrome_o == 10'hef) ^ d_i[382]; + assign d_o[383] = (syndrome_o == 10'h16f) ^ d_i[383]; + assign d_o[384] = (syndrome_o == 10'h26f) ^ d_i[384]; + assign d_o[385] = (syndrome_o == 10'h1af) ^ d_i[385]; + assign d_o[386] = (syndrome_o == 10'h2af) ^ d_i[386]; + assign d_o[387] = (syndrome_o == 10'h32f) ^ d_i[387]; + assign d_o[388] = (syndrome_o == 10'h1cf) ^ d_i[388]; + assign d_o[389] = (syndrome_o == 10'h2cf) ^ d_i[389]; + assign d_o[390] = (syndrome_o == 10'h34f) ^ d_i[390]; + assign d_o[391] = (syndrome_o == 10'h38f) ^ d_i[391]; + assign d_o[392] = (syndrome_o == 10'hf7) ^ d_i[392]; + assign d_o[393] = (syndrome_o == 10'h177) ^ d_i[393]; + assign d_o[394] = (syndrome_o == 10'h277) ^ d_i[394]; + assign d_o[395] = (syndrome_o == 10'h1b7) ^ d_i[395]; + assign d_o[396] = (syndrome_o == 10'h2b7) ^ d_i[396]; + assign d_o[397] = (syndrome_o == 10'h337) ^ d_i[397]; + assign d_o[398] = (syndrome_o == 10'h1d7) ^ d_i[398]; + assign d_o[399] = (syndrome_o == 10'h2d7) ^ d_i[399]; + assign d_o[400] = (syndrome_o == 10'h357) ^ d_i[400]; + assign d_o[401] = (syndrome_o == 10'h397) ^ d_i[401]; + assign d_o[402] = (syndrome_o == 10'h1e7) ^ d_i[402]; + assign d_o[403] = (syndrome_o == 10'h2e7) ^ d_i[403]; + assign d_o[404] = (syndrome_o == 10'h367) ^ d_i[404]; + assign d_o[405] = (syndrome_o == 10'h3a7) ^ d_i[405]; + assign d_o[406] = (syndrome_o == 10'h3c7) ^ d_i[406]; + assign d_o[407] = (syndrome_o == 10'hfb) ^ d_i[407]; + assign d_o[408] = (syndrome_o == 10'h17b) ^ d_i[408]; + assign d_o[409] = (syndrome_o == 10'h27b) ^ d_i[409]; + assign d_o[410] = (syndrome_o == 10'h1bb) ^ d_i[410]; + assign d_o[411] = (syndrome_o == 10'h2bb) ^ d_i[411]; + assign d_o[412] = (syndrome_o == 10'h33b) ^ d_i[412]; + assign d_o[413] = (syndrome_o == 10'h1db) ^ d_i[413]; + assign d_o[414] = (syndrome_o == 10'h2db) ^ d_i[414]; + assign d_o[415] = (syndrome_o == 10'h35b) ^ d_i[415]; + assign d_o[416] = (syndrome_o == 10'h39b) ^ d_i[416]; + assign d_o[417] = (syndrome_o == 10'h1eb) ^ d_i[417]; + assign d_o[418] = (syndrome_o == 10'h2eb) ^ d_i[418]; + assign d_o[419] = (syndrome_o == 10'h36b) ^ d_i[419]; + assign d_o[420] = (syndrome_o == 10'h3ab) ^ d_i[420]; + assign d_o[421] = (syndrome_o == 10'h3cb) ^ d_i[421]; + assign d_o[422] = (syndrome_o == 10'h1f3) ^ d_i[422]; + assign d_o[423] = (syndrome_o == 10'h2f3) ^ d_i[423]; + assign d_o[424] = (syndrome_o == 10'h373) ^ d_i[424]; + assign d_o[425] = (syndrome_o == 10'h3b3) ^ d_i[425]; + assign d_o[426] = (syndrome_o == 10'h3d3) ^ d_i[426]; + assign d_o[427] = (syndrome_o == 10'h3e3) ^ d_i[427]; + assign d_o[428] = (syndrome_o == 10'hfd) ^ d_i[428]; + assign d_o[429] = (syndrome_o == 10'h17d) ^ d_i[429]; + assign d_o[430] = (syndrome_o == 10'h27d) ^ d_i[430]; + assign d_o[431] = (syndrome_o == 10'h1bd) ^ d_i[431]; + assign d_o[432] = (syndrome_o == 10'h2bd) ^ d_i[432]; + assign d_o[433] = (syndrome_o == 10'h33d) ^ d_i[433]; + assign d_o[434] = (syndrome_o == 10'h1dd) ^ d_i[434]; + assign d_o[435] = (syndrome_o == 10'h2dd) ^ d_i[435]; + assign d_o[436] = (syndrome_o == 10'h35d) ^ d_i[436]; + assign d_o[437] = (syndrome_o == 10'h39d) ^ d_i[437]; + assign d_o[438] = (syndrome_o == 10'h1ed) ^ d_i[438]; + assign d_o[439] = (syndrome_o == 10'h2ed) ^ d_i[439]; + assign d_o[440] = (syndrome_o == 10'h36d) ^ d_i[440]; + assign d_o[441] = (syndrome_o == 10'h3ad) ^ d_i[441]; + assign d_o[442] = (syndrome_o == 10'h3cd) ^ d_i[442]; + assign d_o[443] = (syndrome_o == 10'h1f5) ^ d_i[443]; + assign d_o[444] = (syndrome_o == 10'h2f5) ^ d_i[444]; + assign d_o[445] = (syndrome_o == 10'h375) ^ d_i[445]; + assign d_o[446] = (syndrome_o == 10'h3b5) ^ d_i[446]; + assign d_o[447] = (syndrome_o == 10'h3d5) ^ d_i[447]; + assign d_o[448] = (syndrome_o == 10'h3e5) ^ d_i[448]; + assign d_o[449] = (syndrome_o == 10'h1f9) ^ d_i[449]; + assign d_o[450] = (syndrome_o == 10'h2f9) ^ d_i[450]; + assign d_o[451] = (syndrome_o == 10'h379) ^ d_i[451]; + assign d_o[452] = (syndrome_o == 10'h3b9) ^ d_i[452]; + assign d_o[453] = (syndrome_o == 10'h3d9) ^ d_i[453]; + assign d_o[454] = (syndrome_o == 10'h3e9) ^ d_i[454]; + assign d_o[455] = (syndrome_o == 10'h3f1) ^ d_i[455]; + assign d_o[456] = (syndrome_o == 10'hfe) ^ d_i[456]; + assign d_o[457] = (syndrome_o == 10'h17e) ^ d_i[457]; + assign d_o[458] = (syndrome_o == 10'h27e) ^ d_i[458]; + assign d_o[459] = (syndrome_o == 10'h1be) ^ d_i[459]; + assign d_o[460] = (syndrome_o == 10'h2be) ^ d_i[460]; + assign d_o[461] = (syndrome_o == 10'h33e) ^ d_i[461]; + assign d_o[462] = (syndrome_o == 10'h1de) ^ d_i[462]; + assign d_o[463] = (syndrome_o == 10'h2de) ^ d_i[463]; + assign d_o[464] = (syndrome_o == 10'h35e) ^ d_i[464]; + assign d_o[465] = (syndrome_o == 10'h39e) ^ d_i[465]; + assign d_o[466] = (syndrome_o == 10'h1ee) ^ d_i[466]; + assign d_o[467] = (syndrome_o == 10'h2ee) ^ d_i[467]; + assign d_o[468] = (syndrome_o == 10'h36e) ^ d_i[468]; + assign d_o[469] = (syndrome_o == 10'h3ae) ^ d_i[469]; + assign d_o[470] = (syndrome_o == 10'h3ce) ^ d_i[470]; + assign d_o[471] = (syndrome_o == 10'h1f6) ^ d_i[471]; + assign d_o[472] = (syndrome_o == 10'h2f6) ^ d_i[472]; + assign d_o[473] = (syndrome_o == 10'h376) ^ d_i[473]; + assign d_o[474] = (syndrome_o == 10'h3b6) ^ d_i[474]; + assign d_o[475] = (syndrome_o == 10'h3d6) ^ d_i[475]; + assign d_o[476] = (syndrome_o == 10'h3e6) ^ d_i[476]; + assign d_o[477] = (syndrome_o == 10'h1fa) ^ d_i[477]; + assign d_o[478] = (syndrome_o == 10'h2fa) ^ d_i[478]; + assign d_o[479] = (syndrome_o == 10'h37a) ^ d_i[479]; + assign d_o[480] = (syndrome_o == 10'h3ba) ^ d_i[480]; + assign d_o[481] = (syndrome_o == 10'h3da) ^ d_i[481]; + assign d_o[482] = (syndrome_o == 10'h3ea) ^ d_i[482]; + assign d_o[483] = (syndrome_o == 10'h3f2) ^ d_i[483]; + assign d_o[484] = (syndrome_o == 10'h1fc) ^ d_i[484]; + assign d_o[485] = (syndrome_o == 10'h2fc) ^ d_i[485]; + assign d_o[486] = (syndrome_o == 10'h37c) ^ d_i[486]; + assign d_o[487] = (syndrome_o == 10'h3bc) ^ d_i[487]; + assign d_o[488] = (syndrome_o == 10'h3dc) ^ d_i[488]; + assign d_o[489] = (syndrome_o == 10'h3ec) ^ d_i[489]; + assign d_o[490] = (syndrome_o == 10'h3f4) ^ d_i[490]; + assign d_o[491] = (syndrome_o == 10'h3f8) ^ d_i[491]; + assign d_o[492] = (syndrome_o == 10'h1ff) ^ d_i[492]; + assign d_o[493] = (syndrome_o == 10'h2ff) ^ d_i[493]; + assign d_o[494] = (syndrome_o == 10'h37f) ^ d_i[494]; + assign d_o[495] = (syndrome_o == 10'h3bf) ^ d_i[495]; + assign d_o[496] = (syndrome_o == 10'h3df) ^ d_i[496]; + assign d_o[497] = (syndrome_o == 10'h3ef) ^ d_i[497]; + assign d_o[498] = (syndrome_o == 10'h3f7) ^ d_i[498]; + assign d_o[499] = (syndrome_o == 10'h3fb) ^ d_i[499]; + assign d_o[500] = (syndrome_o == 10'h3fd) ^ d_i[500]; + assign d_o[501] = (syndrome_o == 10'h3fe) ^ d_i[501]; + assign d_o[502] = (syndrome_o == 10'h1) ^ d_i[502]; + assign d_o[503] = (syndrome_o == 10'h2) ^ d_i[503]; + assign d_o[504] = (syndrome_o == 10'h4) ^ d_i[504]; + assign d_o[505] = (syndrome_o == 10'h8) ^ d_i[505]; + assign d_o[506] = (syndrome_o == 10'h10) ^ d_i[506]; + assign d_o[507] = (syndrome_o == 10'h20) ^ d_i[507]; + assign d_o[508] = (syndrome_o == 10'h40) ^ d_i[508]; + assign d_o[509] = (syndrome_o == 10'h80) ^ d_i[509]; + assign d_o[510] = (syndrome_o == 10'h100) ^ d_i[510]; + assign d_o[511] = (syndrome_o == 10'h200) ^ d_i[511]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_512_502_cor diff --git a/rtl/lowrisc_ecc/prim_secded_512_502_dec.sv b/rtl/lowrisc_ecc/prim_secded_512_502_dec.sv new file mode 100644 index 00000000..bb5aeadf --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_512_502_dec.sv @@ -0,0 +1,538 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Decoder generated by +// util/design/secded_gen.py -m 10 -k 502 -s 1592631616 -c hsiao + +module prim_secded_512_502_dec ( + input [511:0] in, + output logic [501:0] d_o, + output logic [9:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(in & 512'h005FF000000000FFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000FFFFFFFFF); + assign syndrome_o[1] = ^(in & 512'h00AFF00FFFFFFF0000000FFFFFFFFFFFFFF00000000000000FFFFFFFFFFFFFFFFFC00000000000000000FFFFFFFFFFFFFF00000000000000FFFFFFF0000000FF); + assign syndrome_o[2] = ^(in & 512'h0137F7F01FFFFF01FFFFF000007FFFFFFFF000007FFFFFFFF000000001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000000001FFFFF000007F000007F01); + assign syndrome_o[3] = ^(in & 512'h023BFBF7E07FFF7E07FFF03FFF8000FFFFF03FFF8000FFFFF0001FFFFE00001FFFC0007FFFF800007FFF00000FFFE0003F00000FFFE0003F0001F810001F8102); + assign syndrome_o[4] = ^(in & 512'h043DFDFBEF83FFBEF83FF7C1FF83FF003FF7C1FF83FF003FF07FE007FE007FE007C1FF801FF801FF801F003FF003E007C1003FF003E007C1003E082003E08204); + assign syndrome_o[5] = ^(in & 512'h083EFEFDF7BC3FDF7BC3FBDE1FBC3F0FC0FBDE1FBC3F0FC0F787E1F81E1F81E0785E1F87E0787E0781E10FC0F03C2078420FC0F03C20784203C210403C210408); + assign syndrome_o[6] = ^(in & 512'h103F7F7EFBDDC7EFBDDC7DEEE3DDC771C71DEEE3DDC771C71BB8EE38E2E38E2388AEE3B8E38B8E388E2271C711C443888471C711C44388841C442081C4420810); + assign syndrome_o[7] = ^(in & 512'h203FBFBF7DEED9F7DEED9EF76CEED9B6592EF76CEED9B6592DDB36CB256CB24C91376CDB2C95B2C93244B65926488C9108B65926488C91086488410648841020); + assign syndrome_o[8] = ^(in & 512'h403FDFDFBEF76AFBEF76AF7BB5776ADAAA4F7BB5776ADAAA4EED5B5549B55495223BB56D5526D5525488DAAA4A91152210DAAA4A91152210A910820A91082040); + assign syndrome_o[9] = ^(in & 512'h803FEFEFDF7BB4FDF7BB4FBDDA7BB4ED348FBDDA7BB4ED348F769DA691DA691A443DDA769A4769A46910ED348D221A4420ED348D221A4420D221040D22104080); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 10'h7) ^ in[0]; + assign d_o[1] = (syndrome_o == 10'hb) ^ in[1]; + assign d_o[2] = (syndrome_o == 10'h13) ^ in[2]; + assign d_o[3] = (syndrome_o == 10'h23) ^ in[3]; + assign d_o[4] = (syndrome_o == 10'h43) ^ in[4]; + assign d_o[5] = (syndrome_o == 10'h83) ^ in[5]; + assign d_o[6] = (syndrome_o == 10'h103) ^ in[6]; + assign d_o[7] = (syndrome_o == 10'h203) ^ in[7]; + assign d_o[8] = (syndrome_o == 10'hd) ^ in[8]; + assign d_o[9] = (syndrome_o == 10'h15) ^ in[9]; + assign d_o[10] = (syndrome_o == 10'h25) ^ in[10]; + assign d_o[11] = (syndrome_o == 10'h45) ^ in[11]; + assign d_o[12] = (syndrome_o == 10'h85) ^ in[12]; + assign d_o[13] = (syndrome_o == 10'h105) ^ in[13]; + assign d_o[14] = (syndrome_o == 10'h205) ^ in[14]; + assign d_o[15] = (syndrome_o == 10'h19) ^ in[15]; + assign d_o[16] = (syndrome_o == 10'h29) ^ in[16]; + assign d_o[17] = (syndrome_o == 10'h49) ^ in[17]; + assign d_o[18] = (syndrome_o == 10'h89) ^ in[18]; + assign d_o[19] = (syndrome_o == 10'h109) ^ in[19]; + assign d_o[20] = (syndrome_o == 10'h209) ^ in[20]; + assign d_o[21] = (syndrome_o == 10'h31) ^ in[21]; + assign d_o[22] = (syndrome_o == 10'h51) ^ in[22]; + assign d_o[23] = (syndrome_o == 10'h91) ^ in[23]; + assign d_o[24] = (syndrome_o == 10'h111) ^ in[24]; + assign d_o[25] = (syndrome_o == 10'h211) ^ in[25]; + assign d_o[26] = (syndrome_o == 10'h61) ^ in[26]; + assign d_o[27] = (syndrome_o == 10'ha1) ^ in[27]; + assign d_o[28] = (syndrome_o == 10'h121) ^ in[28]; + assign d_o[29] = (syndrome_o == 10'h221) ^ in[29]; + assign d_o[30] = (syndrome_o == 10'hc1) ^ in[30]; + assign d_o[31] = (syndrome_o == 10'h141) ^ in[31]; + assign d_o[32] = (syndrome_o == 10'h241) ^ in[32]; + assign d_o[33] = (syndrome_o == 10'h181) ^ in[33]; + assign d_o[34] = (syndrome_o == 10'h281) ^ in[34]; + assign d_o[35] = (syndrome_o == 10'h301) ^ in[35]; + assign d_o[36] = (syndrome_o == 10'he) ^ in[36]; + assign d_o[37] = (syndrome_o == 10'h16) ^ in[37]; + assign d_o[38] = (syndrome_o == 10'h26) ^ in[38]; + assign d_o[39] = (syndrome_o == 10'h46) ^ in[39]; + assign d_o[40] = (syndrome_o == 10'h86) ^ in[40]; + assign d_o[41] = (syndrome_o == 10'h106) ^ in[41]; + assign d_o[42] = (syndrome_o == 10'h206) ^ in[42]; + assign d_o[43] = (syndrome_o == 10'h1a) ^ in[43]; + assign d_o[44] = (syndrome_o == 10'h2a) ^ in[44]; + assign d_o[45] = (syndrome_o == 10'h4a) ^ in[45]; + assign d_o[46] = (syndrome_o == 10'h8a) ^ in[46]; + assign d_o[47] = (syndrome_o == 10'h10a) ^ in[47]; + assign d_o[48] = (syndrome_o == 10'h20a) ^ in[48]; + assign d_o[49] = (syndrome_o == 10'h32) ^ in[49]; + assign d_o[50] = (syndrome_o == 10'h52) ^ in[50]; + assign d_o[51] = (syndrome_o == 10'h92) ^ in[51]; + assign d_o[52] = (syndrome_o == 10'h112) ^ in[52]; + assign d_o[53] = (syndrome_o == 10'h212) ^ in[53]; + assign d_o[54] = (syndrome_o == 10'h62) ^ in[54]; + assign d_o[55] = (syndrome_o == 10'ha2) ^ in[55]; + assign d_o[56] = (syndrome_o == 10'h122) ^ in[56]; + assign d_o[57] = (syndrome_o == 10'h222) ^ in[57]; + assign d_o[58] = (syndrome_o == 10'hc2) ^ in[58]; + assign d_o[59] = (syndrome_o == 10'h142) ^ in[59]; + assign d_o[60] = (syndrome_o == 10'h242) ^ in[60]; + assign d_o[61] = (syndrome_o == 10'h182) ^ in[61]; + assign d_o[62] = (syndrome_o == 10'h282) ^ in[62]; + assign d_o[63] = (syndrome_o == 10'h302) ^ in[63]; + assign d_o[64] = (syndrome_o == 10'h1c) ^ in[64]; + assign d_o[65] = (syndrome_o == 10'h2c) ^ in[65]; + assign d_o[66] = (syndrome_o == 10'h4c) ^ in[66]; + assign d_o[67] = (syndrome_o == 10'h8c) ^ in[67]; + assign d_o[68] = (syndrome_o == 10'h10c) ^ in[68]; + assign d_o[69] = (syndrome_o == 10'h20c) ^ in[69]; + assign d_o[70] = (syndrome_o == 10'h34) ^ in[70]; + assign d_o[71] = (syndrome_o == 10'h54) ^ in[71]; + assign d_o[72] = (syndrome_o == 10'h94) ^ in[72]; + assign d_o[73] = (syndrome_o == 10'h114) ^ in[73]; + assign d_o[74] = (syndrome_o == 10'h214) ^ in[74]; + assign d_o[75] = (syndrome_o == 10'h64) ^ in[75]; + assign d_o[76] = (syndrome_o == 10'ha4) ^ in[76]; + assign d_o[77] = (syndrome_o == 10'h124) ^ in[77]; + assign d_o[78] = (syndrome_o == 10'h224) ^ in[78]; + assign d_o[79] = (syndrome_o == 10'hc4) ^ in[79]; + assign d_o[80] = (syndrome_o == 10'h144) ^ in[80]; + assign d_o[81] = (syndrome_o == 10'h244) ^ in[81]; + assign d_o[82] = (syndrome_o == 10'h184) ^ in[82]; + assign d_o[83] = (syndrome_o == 10'h284) ^ in[83]; + assign d_o[84] = (syndrome_o == 10'h304) ^ in[84]; + assign d_o[85] = (syndrome_o == 10'h38) ^ in[85]; + assign d_o[86] = (syndrome_o == 10'h58) ^ in[86]; + assign d_o[87] = (syndrome_o == 10'h98) ^ in[87]; + assign d_o[88] = (syndrome_o == 10'h118) ^ in[88]; + assign d_o[89] = (syndrome_o == 10'h218) ^ in[89]; + assign d_o[90] = (syndrome_o == 10'h68) ^ in[90]; + assign d_o[91] = (syndrome_o == 10'ha8) ^ in[91]; + assign d_o[92] = (syndrome_o == 10'h128) ^ in[92]; + assign d_o[93] = (syndrome_o == 10'h228) ^ in[93]; + assign d_o[94] = (syndrome_o == 10'hc8) ^ in[94]; + assign d_o[95] = (syndrome_o == 10'h148) ^ in[95]; + assign d_o[96] = (syndrome_o == 10'h248) ^ in[96]; + assign d_o[97] = (syndrome_o == 10'h188) ^ in[97]; + assign d_o[98] = (syndrome_o == 10'h288) ^ in[98]; + assign d_o[99] = (syndrome_o == 10'h308) ^ in[99]; + assign d_o[100] = (syndrome_o == 10'h70) ^ in[100]; + assign d_o[101] = (syndrome_o == 10'hb0) ^ in[101]; + assign d_o[102] = (syndrome_o == 10'h130) ^ in[102]; + assign d_o[103] = (syndrome_o == 10'h230) ^ in[103]; + assign d_o[104] = (syndrome_o == 10'hd0) ^ in[104]; + assign d_o[105] = (syndrome_o == 10'h150) ^ in[105]; + assign d_o[106] = (syndrome_o == 10'h250) ^ in[106]; + assign d_o[107] = (syndrome_o == 10'h190) ^ in[107]; + assign d_o[108] = (syndrome_o == 10'h290) ^ in[108]; + assign d_o[109] = (syndrome_o == 10'h310) ^ in[109]; + assign d_o[110] = (syndrome_o == 10'he0) ^ in[110]; + assign d_o[111] = (syndrome_o == 10'h160) ^ in[111]; + assign d_o[112] = (syndrome_o == 10'h260) ^ in[112]; + assign d_o[113] = (syndrome_o == 10'h1a0) ^ in[113]; + assign d_o[114] = (syndrome_o == 10'h2a0) ^ in[114]; + assign d_o[115] = (syndrome_o == 10'h320) ^ in[115]; + assign d_o[116] = (syndrome_o == 10'h1c0) ^ in[116]; + assign d_o[117] = (syndrome_o == 10'h2c0) ^ in[117]; + assign d_o[118] = (syndrome_o == 10'h340) ^ in[118]; + assign d_o[119] = (syndrome_o == 10'h380) ^ in[119]; + assign d_o[120] = (syndrome_o == 10'h1f) ^ in[120]; + assign d_o[121] = (syndrome_o == 10'h2f) ^ in[121]; + assign d_o[122] = (syndrome_o == 10'h4f) ^ in[122]; + assign d_o[123] = (syndrome_o == 10'h8f) ^ in[123]; + assign d_o[124] = (syndrome_o == 10'h10f) ^ in[124]; + assign d_o[125] = (syndrome_o == 10'h20f) ^ in[125]; + assign d_o[126] = (syndrome_o == 10'h37) ^ in[126]; + assign d_o[127] = (syndrome_o == 10'h57) ^ in[127]; + assign d_o[128] = (syndrome_o == 10'h97) ^ in[128]; + assign d_o[129] = (syndrome_o == 10'h117) ^ in[129]; + assign d_o[130] = (syndrome_o == 10'h217) ^ in[130]; + assign d_o[131] = (syndrome_o == 10'h67) ^ in[131]; + assign d_o[132] = (syndrome_o == 10'ha7) ^ in[132]; + assign d_o[133] = (syndrome_o == 10'h127) ^ in[133]; + assign d_o[134] = (syndrome_o == 10'h227) ^ in[134]; + assign d_o[135] = (syndrome_o == 10'hc7) ^ in[135]; + assign d_o[136] = (syndrome_o == 10'h147) ^ in[136]; + assign d_o[137] = (syndrome_o == 10'h247) ^ in[137]; + assign d_o[138] = (syndrome_o == 10'h187) ^ in[138]; + assign d_o[139] = (syndrome_o == 10'h287) ^ in[139]; + assign d_o[140] = (syndrome_o == 10'h307) ^ in[140]; + assign d_o[141] = (syndrome_o == 10'h3b) ^ in[141]; + assign d_o[142] = (syndrome_o == 10'h5b) ^ in[142]; + assign d_o[143] = (syndrome_o == 10'h9b) ^ in[143]; + assign d_o[144] = (syndrome_o == 10'h11b) ^ in[144]; + assign d_o[145] = (syndrome_o == 10'h21b) ^ in[145]; + assign d_o[146] = (syndrome_o == 10'h6b) ^ in[146]; + assign d_o[147] = (syndrome_o == 10'hab) ^ in[147]; + assign d_o[148] = (syndrome_o == 10'h12b) ^ in[148]; + assign d_o[149] = (syndrome_o == 10'h22b) ^ in[149]; + assign d_o[150] = (syndrome_o == 10'hcb) ^ in[150]; + assign d_o[151] = (syndrome_o == 10'h14b) ^ in[151]; + assign d_o[152] = (syndrome_o == 10'h24b) ^ in[152]; + assign d_o[153] = (syndrome_o == 10'h18b) ^ in[153]; + assign d_o[154] = (syndrome_o == 10'h28b) ^ in[154]; + assign d_o[155] = (syndrome_o == 10'h30b) ^ in[155]; + assign d_o[156] = (syndrome_o == 10'h73) ^ in[156]; + assign d_o[157] = (syndrome_o == 10'hb3) ^ in[157]; + assign d_o[158] = (syndrome_o == 10'h133) ^ in[158]; + assign d_o[159] = (syndrome_o == 10'h233) ^ in[159]; + assign d_o[160] = (syndrome_o == 10'hd3) ^ in[160]; + assign d_o[161] = (syndrome_o == 10'h153) ^ in[161]; + assign d_o[162] = (syndrome_o == 10'h253) ^ in[162]; + assign d_o[163] = (syndrome_o == 10'h193) ^ in[163]; + assign d_o[164] = (syndrome_o == 10'h293) ^ in[164]; + assign d_o[165] = (syndrome_o == 10'h313) ^ in[165]; + assign d_o[166] = (syndrome_o == 10'he3) ^ in[166]; + assign d_o[167] = (syndrome_o == 10'h163) ^ in[167]; + assign d_o[168] = (syndrome_o == 10'h263) ^ in[168]; + assign d_o[169] = (syndrome_o == 10'h1a3) ^ in[169]; + assign d_o[170] = (syndrome_o == 10'h2a3) ^ in[170]; + assign d_o[171] = (syndrome_o == 10'h323) ^ in[171]; + assign d_o[172] = (syndrome_o == 10'h1c3) ^ in[172]; + assign d_o[173] = (syndrome_o == 10'h2c3) ^ in[173]; + assign d_o[174] = (syndrome_o == 10'h343) ^ in[174]; + assign d_o[175] = (syndrome_o == 10'h383) ^ in[175]; + assign d_o[176] = (syndrome_o == 10'h3d) ^ in[176]; + assign d_o[177] = (syndrome_o == 10'h5d) ^ in[177]; + assign d_o[178] = (syndrome_o == 10'h9d) ^ in[178]; + assign d_o[179] = (syndrome_o == 10'h11d) ^ in[179]; + assign d_o[180] = (syndrome_o == 10'h21d) ^ in[180]; + assign d_o[181] = (syndrome_o == 10'h6d) ^ in[181]; + assign d_o[182] = (syndrome_o == 10'had) ^ in[182]; + assign d_o[183] = (syndrome_o == 10'h12d) ^ in[183]; + assign d_o[184] = (syndrome_o == 10'h22d) ^ in[184]; + assign d_o[185] = (syndrome_o == 10'hcd) ^ in[185]; + assign d_o[186] = (syndrome_o == 10'h14d) ^ in[186]; + assign d_o[187] = (syndrome_o == 10'h24d) ^ in[187]; + assign d_o[188] = (syndrome_o == 10'h18d) ^ in[188]; + assign d_o[189] = (syndrome_o == 10'h28d) ^ in[189]; + assign d_o[190] = (syndrome_o == 10'h30d) ^ in[190]; + assign d_o[191] = (syndrome_o == 10'h75) ^ in[191]; + assign d_o[192] = (syndrome_o == 10'hb5) ^ in[192]; + assign d_o[193] = (syndrome_o == 10'h135) ^ in[193]; + assign d_o[194] = (syndrome_o == 10'h235) ^ in[194]; + assign d_o[195] = (syndrome_o == 10'hd5) ^ in[195]; + assign d_o[196] = (syndrome_o == 10'h155) ^ in[196]; + assign d_o[197] = (syndrome_o == 10'h255) ^ in[197]; + assign d_o[198] = (syndrome_o == 10'h195) ^ in[198]; + assign d_o[199] = (syndrome_o == 10'h295) ^ in[199]; + assign d_o[200] = (syndrome_o == 10'h315) ^ in[200]; + assign d_o[201] = (syndrome_o == 10'he5) ^ in[201]; + assign d_o[202] = (syndrome_o == 10'h165) ^ in[202]; + assign d_o[203] = (syndrome_o == 10'h265) ^ in[203]; + assign d_o[204] = (syndrome_o == 10'h1a5) ^ in[204]; + assign d_o[205] = (syndrome_o == 10'h2a5) ^ in[205]; + assign d_o[206] = (syndrome_o == 10'h325) ^ in[206]; + assign d_o[207] = (syndrome_o == 10'h1c5) ^ in[207]; + assign d_o[208] = (syndrome_o == 10'h2c5) ^ in[208]; + assign d_o[209] = (syndrome_o == 10'h345) ^ in[209]; + assign d_o[210] = (syndrome_o == 10'h385) ^ in[210]; + assign d_o[211] = (syndrome_o == 10'h79) ^ in[211]; + assign d_o[212] = (syndrome_o == 10'hb9) ^ in[212]; + assign d_o[213] = (syndrome_o == 10'h139) ^ in[213]; + assign d_o[214] = (syndrome_o == 10'h239) ^ in[214]; + assign d_o[215] = (syndrome_o == 10'hd9) ^ in[215]; + assign d_o[216] = (syndrome_o == 10'h159) ^ in[216]; + assign d_o[217] = (syndrome_o == 10'h259) ^ in[217]; + assign d_o[218] = (syndrome_o == 10'h199) ^ in[218]; + assign d_o[219] = (syndrome_o == 10'h299) ^ in[219]; + assign d_o[220] = (syndrome_o == 10'h319) ^ in[220]; + assign d_o[221] = (syndrome_o == 10'he9) ^ in[221]; + assign d_o[222] = (syndrome_o == 10'h169) ^ in[222]; + assign d_o[223] = (syndrome_o == 10'h269) ^ in[223]; + assign d_o[224] = (syndrome_o == 10'h1a9) ^ in[224]; + assign d_o[225] = (syndrome_o == 10'h2a9) ^ in[225]; + assign d_o[226] = (syndrome_o == 10'h329) ^ in[226]; + assign d_o[227] = (syndrome_o == 10'h1c9) ^ in[227]; + assign d_o[228] = (syndrome_o == 10'h2c9) ^ in[228]; + assign d_o[229] = (syndrome_o == 10'h349) ^ in[229]; + assign d_o[230] = (syndrome_o == 10'h389) ^ in[230]; + assign d_o[231] = (syndrome_o == 10'hf1) ^ in[231]; + assign d_o[232] = (syndrome_o == 10'h171) ^ in[232]; + assign d_o[233] = (syndrome_o == 10'h271) ^ in[233]; + assign d_o[234] = (syndrome_o == 10'h1b1) ^ in[234]; + assign d_o[235] = (syndrome_o == 10'h2b1) ^ in[235]; + assign d_o[236] = (syndrome_o == 10'h331) ^ in[236]; + assign d_o[237] = (syndrome_o == 10'h1d1) ^ in[237]; + assign d_o[238] = (syndrome_o == 10'h2d1) ^ in[238]; + assign d_o[239] = (syndrome_o == 10'h351) ^ in[239]; + assign d_o[240] = (syndrome_o == 10'h391) ^ in[240]; + assign d_o[241] = (syndrome_o == 10'h1e1) ^ in[241]; + assign d_o[242] = (syndrome_o == 10'h2e1) ^ in[242]; + assign d_o[243] = (syndrome_o == 10'h361) ^ in[243]; + assign d_o[244] = (syndrome_o == 10'h3a1) ^ in[244]; + assign d_o[245] = (syndrome_o == 10'h3c1) ^ in[245]; + assign d_o[246] = (syndrome_o == 10'h3e) ^ in[246]; + assign d_o[247] = (syndrome_o == 10'h5e) ^ in[247]; + assign d_o[248] = (syndrome_o == 10'h9e) ^ in[248]; + assign d_o[249] = (syndrome_o == 10'h11e) ^ in[249]; + assign d_o[250] = (syndrome_o == 10'h21e) ^ in[250]; + assign d_o[251] = (syndrome_o == 10'h6e) ^ in[251]; + assign d_o[252] = (syndrome_o == 10'hae) ^ in[252]; + assign d_o[253] = (syndrome_o == 10'h12e) ^ in[253]; + assign d_o[254] = (syndrome_o == 10'h22e) ^ in[254]; + assign d_o[255] = (syndrome_o == 10'hce) ^ in[255]; + assign d_o[256] = (syndrome_o == 10'h14e) ^ in[256]; + assign d_o[257] = (syndrome_o == 10'h24e) ^ in[257]; + assign d_o[258] = (syndrome_o == 10'h18e) ^ in[258]; + assign d_o[259] = (syndrome_o == 10'h28e) ^ in[259]; + assign d_o[260] = (syndrome_o == 10'h30e) ^ in[260]; + assign d_o[261] = (syndrome_o == 10'h76) ^ in[261]; + assign d_o[262] = (syndrome_o == 10'hb6) ^ in[262]; + assign d_o[263] = (syndrome_o == 10'h136) ^ in[263]; + assign d_o[264] = (syndrome_o == 10'h236) ^ in[264]; + assign d_o[265] = (syndrome_o == 10'hd6) ^ in[265]; + assign d_o[266] = (syndrome_o == 10'h156) ^ in[266]; + assign d_o[267] = (syndrome_o == 10'h256) ^ in[267]; + assign d_o[268] = (syndrome_o == 10'h196) ^ in[268]; + assign d_o[269] = (syndrome_o == 10'h296) ^ in[269]; + assign d_o[270] = (syndrome_o == 10'h316) ^ in[270]; + assign d_o[271] = (syndrome_o == 10'he6) ^ in[271]; + assign d_o[272] = (syndrome_o == 10'h166) ^ in[272]; + assign d_o[273] = (syndrome_o == 10'h266) ^ in[273]; + assign d_o[274] = (syndrome_o == 10'h1a6) ^ in[274]; + assign d_o[275] = (syndrome_o == 10'h2a6) ^ in[275]; + assign d_o[276] = (syndrome_o == 10'h326) ^ in[276]; + assign d_o[277] = (syndrome_o == 10'h1c6) ^ in[277]; + assign d_o[278] = (syndrome_o == 10'h2c6) ^ in[278]; + assign d_o[279] = (syndrome_o == 10'h346) ^ in[279]; + assign d_o[280] = (syndrome_o == 10'h386) ^ in[280]; + assign d_o[281] = (syndrome_o == 10'h7a) ^ in[281]; + assign d_o[282] = (syndrome_o == 10'hba) ^ in[282]; + assign d_o[283] = (syndrome_o == 10'h13a) ^ in[283]; + assign d_o[284] = (syndrome_o == 10'h23a) ^ in[284]; + assign d_o[285] = (syndrome_o == 10'hda) ^ in[285]; + assign d_o[286] = (syndrome_o == 10'h15a) ^ in[286]; + assign d_o[287] = (syndrome_o == 10'h25a) ^ in[287]; + assign d_o[288] = (syndrome_o == 10'h19a) ^ in[288]; + assign d_o[289] = (syndrome_o == 10'h29a) ^ in[289]; + assign d_o[290] = (syndrome_o == 10'h31a) ^ in[290]; + assign d_o[291] = (syndrome_o == 10'hea) ^ in[291]; + assign d_o[292] = (syndrome_o == 10'h16a) ^ in[292]; + assign d_o[293] = (syndrome_o == 10'h26a) ^ in[293]; + assign d_o[294] = (syndrome_o == 10'h1aa) ^ in[294]; + assign d_o[295] = (syndrome_o == 10'h2aa) ^ in[295]; + assign d_o[296] = (syndrome_o == 10'h32a) ^ in[296]; + assign d_o[297] = (syndrome_o == 10'h1ca) ^ in[297]; + assign d_o[298] = (syndrome_o == 10'h2ca) ^ in[298]; + assign d_o[299] = (syndrome_o == 10'h34a) ^ in[299]; + assign d_o[300] = (syndrome_o == 10'h38a) ^ in[300]; + assign d_o[301] = (syndrome_o == 10'hf2) ^ in[301]; + assign d_o[302] = (syndrome_o == 10'h172) ^ in[302]; + assign d_o[303] = (syndrome_o == 10'h272) ^ in[303]; + assign d_o[304] = (syndrome_o == 10'h1b2) ^ in[304]; + assign d_o[305] = (syndrome_o == 10'h2b2) ^ in[305]; + assign d_o[306] = (syndrome_o == 10'h332) ^ in[306]; + assign d_o[307] = (syndrome_o == 10'h1d2) ^ in[307]; + assign d_o[308] = (syndrome_o == 10'h2d2) ^ in[308]; + assign d_o[309] = (syndrome_o == 10'h352) ^ in[309]; + assign d_o[310] = (syndrome_o == 10'h392) ^ in[310]; + assign d_o[311] = (syndrome_o == 10'h1e2) ^ in[311]; + assign d_o[312] = (syndrome_o == 10'h2e2) ^ in[312]; + assign d_o[313] = (syndrome_o == 10'h362) ^ in[313]; + assign d_o[314] = (syndrome_o == 10'h3a2) ^ in[314]; + assign d_o[315] = (syndrome_o == 10'h3c2) ^ in[315]; + assign d_o[316] = (syndrome_o == 10'h7c) ^ in[316]; + assign d_o[317] = (syndrome_o == 10'hbc) ^ in[317]; + assign d_o[318] = (syndrome_o == 10'h13c) ^ in[318]; + assign d_o[319] = (syndrome_o == 10'h23c) ^ in[319]; + assign d_o[320] = (syndrome_o == 10'hdc) ^ in[320]; + assign d_o[321] = (syndrome_o == 10'h15c) ^ in[321]; + assign d_o[322] = (syndrome_o == 10'h25c) ^ in[322]; + assign d_o[323] = (syndrome_o == 10'h19c) ^ in[323]; + assign d_o[324] = (syndrome_o == 10'h29c) ^ in[324]; + assign d_o[325] = (syndrome_o == 10'h31c) ^ in[325]; + assign d_o[326] = (syndrome_o == 10'hec) ^ in[326]; + assign d_o[327] = (syndrome_o == 10'h16c) ^ in[327]; + assign d_o[328] = (syndrome_o == 10'h26c) ^ in[328]; + assign d_o[329] = (syndrome_o == 10'h1ac) ^ in[329]; + assign d_o[330] = (syndrome_o == 10'h2ac) ^ in[330]; + assign d_o[331] = (syndrome_o == 10'h32c) ^ in[331]; + assign d_o[332] = (syndrome_o == 10'h1cc) ^ in[332]; + assign d_o[333] = (syndrome_o == 10'h2cc) ^ in[333]; + assign d_o[334] = (syndrome_o == 10'h34c) ^ in[334]; + assign d_o[335] = (syndrome_o == 10'h38c) ^ in[335]; + assign d_o[336] = (syndrome_o == 10'hf4) ^ in[336]; + assign d_o[337] = (syndrome_o == 10'h174) ^ in[337]; + assign d_o[338] = (syndrome_o == 10'h274) ^ in[338]; + assign d_o[339] = (syndrome_o == 10'h1b4) ^ in[339]; + assign d_o[340] = (syndrome_o == 10'h2b4) ^ in[340]; + assign d_o[341] = (syndrome_o == 10'h334) ^ in[341]; + assign d_o[342] = (syndrome_o == 10'h1d4) ^ in[342]; + assign d_o[343] = (syndrome_o == 10'h2d4) ^ in[343]; + assign d_o[344] = (syndrome_o == 10'h354) ^ in[344]; + assign d_o[345] = (syndrome_o == 10'h394) ^ in[345]; + assign d_o[346] = (syndrome_o == 10'h1e4) ^ in[346]; + assign d_o[347] = (syndrome_o == 10'h2e4) ^ in[347]; + assign d_o[348] = (syndrome_o == 10'h364) ^ in[348]; + assign d_o[349] = (syndrome_o == 10'h3a4) ^ in[349]; + assign d_o[350] = (syndrome_o == 10'h3c4) ^ in[350]; + assign d_o[351] = (syndrome_o == 10'hf8) ^ in[351]; + assign d_o[352] = (syndrome_o == 10'h178) ^ in[352]; + assign d_o[353] = (syndrome_o == 10'h278) ^ in[353]; + assign d_o[354] = (syndrome_o == 10'h1b8) ^ in[354]; + assign d_o[355] = (syndrome_o == 10'h2b8) ^ in[355]; + assign d_o[356] = (syndrome_o == 10'h338) ^ in[356]; + assign d_o[357] = (syndrome_o == 10'h1d8) ^ in[357]; + assign d_o[358] = (syndrome_o == 10'h2d8) ^ in[358]; + assign d_o[359] = (syndrome_o == 10'h358) ^ in[359]; + assign d_o[360] = (syndrome_o == 10'h398) ^ in[360]; + assign d_o[361] = (syndrome_o == 10'h1e8) ^ in[361]; + assign d_o[362] = (syndrome_o == 10'h2e8) ^ in[362]; + assign d_o[363] = (syndrome_o == 10'h368) ^ in[363]; + assign d_o[364] = (syndrome_o == 10'h3a8) ^ in[364]; + assign d_o[365] = (syndrome_o == 10'h3c8) ^ in[365]; + assign d_o[366] = (syndrome_o == 10'h1f0) ^ in[366]; + assign d_o[367] = (syndrome_o == 10'h2f0) ^ in[367]; + assign d_o[368] = (syndrome_o == 10'h370) ^ in[368]; + assign d_o[369] = (syndrome_o == 10'h3b0) ^ in[369]; + assign d_o[370] = (syndrome_o == 10'h3d0) ^ in[370]; + assign d_o[371] = (syndrome_o == 10'h3e0) ^ in[371]; + assign d_o[372] = (syndrome_o == 10'h7f) ^ in[372]; + assign d_o[373] = (syndrome_o == 10'hbf) ^ in[373]; + assign d_o[374] = (syndrome_o == 10'h13f) ^ in[374]; + assign d_o[375] = (syndrome_o == 10'h23f) ^ in[375]; + assign d_o[376] = (syndrome_o == 10'hdf) ^ in[376]; + assign d_o[377] = (syndrome_o == 10'h15f) ^ in[377]; + assign d_o[378] = (syndrome_o == 10'h25f) ^ in[378]; + assign d_o[379] = (syndrome_o == 10'h19f) ^ in[379]; + assign d_o[380] = (syndrome_o == 10'h29f) ^ in[380]; + assign d_o[381] = (syndrome_o == 10'h31f) ^ in[381]; + assign d_o[382] = (syndrome_o == 10'hef) ^ in[382]; + assign d_o[383] = (syndrome_o == 10'h16f) ^ in[383]; + assign d_o[384] = (syndrome_o == 10'h26f) ^ in[384]; + assign d_o[385] = (syndrome_o == 10'h1af) ^ in[385]; + assign d_o[386] = (syndrome_o == 10'h2af) ^ in[386]; + assign d_o[387] = (syndrome_o == 10'h32f) ^ in[387]; + assign d_o[388] = (syndrome_o == 10'h1cf) ^ in[388]; + assign d_o[389] = (syndrome_o == 10'h2cf) ^ in[389]; + assign d_o[390] = (syndrome_o == 10'h34f) ^ in[390]; + assign d_o[391] = (syndrome_o == 10'h38f) ^ in[391]; + assign d_o[392] = (syndrome_o == 10'hf7) ^ in[392]; + assign d_o[393] = (syndrome_o == 10'h177) ^ in[393]; + assign d_o[394] = (syndrome_o == 10'h277) ^ in[394]; + assign d_o[395] = (syndrome_o == 10'h1b7) ^ in[395]; + assign d_o[396] = (syndrome_o == 10'h2b7) ^ in[396]; + assign d_o[397] = (syndrome_o == 10'h337) ^ in[397]; + assign d_o[398] = (syndrome_o == 10'h1d7) ^ in[398]; + assign d_o[399] = (syndrome_o == 10'h2d7) ^ in[399]; + assign d_o[400] = (syndrome_o == 10'h357) ^ in[400]; + assign d_o[401] = (syndrome_o == 10'h397) ^ in[401]; + assign d_o[402] = (syndrome_o == 10'h1e7) ^ in[402]; + assign d_o[403] = (syndrome_o == 10'h2e7) ^ in[403]; + assign d_o[404] = (syndrome_o == 10'h367) ^ in[404]; + assign d_o[405] = (syndrome_o == 10'h3a7) ^ in[405]; + assign d_o[406] = (syndrome_o == 10'h3c7) ^ in[406]; + assign d_o[407] = (syndrome_o == 10'hfb) ^ in[407]; + assign d_o[408] = (syndrome_o == 10'h17b) ^ in[408]; + assign d_o[409] = (syndrome_o == 10'h27b) ^ in[409]; + assign d_o[410] = (syndrome_o == 10'h1bb) ^ in[410]; + assign d_o[411] = (syndrome_o == 10'h2bb) ^ in[411]; + assign d_o[412] = (syndrome_o == 10'h33b) ^ in[412]; + assign d_o[413] = (syndrome_o == 10'h1db) ^ in[413]; + assign d_o[414] = (syndrome_o == 10'h2db) ^ in[414]; + assign d_o[415] = (syndrome_o == 10'h35b) ^ in[415]; + assign d_o[416] = (syndrome_o == 10'h39b) ^ in[416]; + assign d_o[417] = (syndrome_o == 10'h1eb) ^ in[417]; + assign d_o[418] = (syndrome_o == 10'h2eb) ^ in[418]; + assign d_o[419] = (syndrome_o == 10'h36b) ^ in[419]; + assign d_o[420] = (syndrome_o == 10'h3ab) ^ in[420]; + assign d_o[421] = (syndrome_o == 10'h3cb) ^ in[421]; + assign d_o[422] = (syndrome_o == 10'h1f3) ^ in[422]; + assign d_o[423] = (syndrome_o == 10'h2f3) ^ in[423]; + assign d_o[424] = (syndrome_o == 10'h373) ^ in[424]; + assign d_o[425] = (syndrome_o == 10'h3b3) ^ in[425]; + assign d_o[426] = (syndrome_o == 10'h3d3) ^ in[426]; + assign d_o[427] = (syndrome_o == 10'h3e3) ^ in[427]; + assign d_o[428] = (syndrome_o == 10'hfd) ^ in[428]; + assign d_o[429] = (syndrome_o == 10'h17d) ^ in[429]; + assign d_o[430] = (syndrome_o == 10'h27d) ^ in[430]; + assign d_o[431] = (syndrome_o == 10'h1bd) ^ in[431]; + assign d_o[432] = (syndrome_o == 10'h2bd) ^ in[432]; + assign d_o[433] = (syndrome_o == 10'h33d) ^ in[433]; + assign d_o[434] = (syndrome_o == 10'h1dd) ^ in[434]; + assign d_o[435] = (syndrome_o == 10'h2dd) ^ in[435]; + assign d_o[436] = (syndrome_o == 10'h35d) ^ in[436]; + assign d_o[437] = (syndrome_o == 10'h39d) ^ in[437]; + assign d_o[438] = (syndrome_o == 10'h1ed) ^ in[438]; + assign d_o[439] = (syndrome_o == 10'h2ed) ^ in[439]; + assign d_o[440] = (syndrome_o == 10'h36d) ^ in[440]; + assign d_o[441] = (syndrome_o == 10'h3ad) ^ in[441]; + assign d_o[442] = (syndrome_o == 10'h3cd) ^ in[442]; + assign d_o[443] = (syndrome_o == 10'h1f5) ^ in[443]; + assign d_o[444] = (syndrome_o == 10'h2f5) ^ in[444]; + assign d_o[445] = (syndrome_o == 10'h375) ^ in[445]; + assign d_o[446] = (syndrome_o == 10'h3b5) ^ in[446]; + assign d_o[447] = (syndrome_o == 10'h3d5) ^ in[447]; + assign d_o[448] = (syndrome_o == 10'h3e5) ^ in[448]; + assign d_o[449] = (syndrome_o == 10'h1f9) ^ in[449]; + assign d_o[450] = (syndrome_o == 10'h2f9) ^ in[450]; + assign d_o[451] = (syndrome_o == 10'h379) ^ in[451]; + assign d_o[452] = (syndrome_o == 10'h3b9) ^ in[452]; + assign d_o[453] = (syndrome_o == 10'h3d9) ^ in[453]; + assign d_o[454] = (syndrome_o == 10'h3e9) ^ in[454]; + assign d_o[455] = (syndrome_o == 10'h3f1) ^ in[455]; + assign d_o[456] = (syndrome_o == 10'hfe) ^ in[456]; + assign d_o[457] = (syndrome_o == 10'h17e) ^ in[457]; + assign d_o[458] = (syndrome_o == 10'h27e) ^ in[458]; + assign d_o[459] = (syndrome_o == 10'h1be) ^ in[459]; + assign d_o[460] = (syndrome_o == 10'h2be) ^ in[460]; + assign d_o[461] = (syndrome_o == 10'h33e) ^ in[461]; + assign d_o[462] = (syndrome_o == 10'h1de) ^ in[462]; + assign d_o[463] = (syndrome_o == 10'h2de) ^ in[463]; + assign d_o[464] = (syndrome_o == 10'h35e) ^ in[464]; + assign d_o[465] = (syndrome_o == 10'h39e) ^ in[465]; + assign d_o[466] = (syndrome_o == 10'h1ee) ^ in[466]; + assign d_o[467] = (syndrome_o == 10'h2ee) ^ in[467]; + assign d_o[468] = (syndrome_o == 10'h36e) ^ in[468]; + assign d_o[469] = (syndrome_o == 10'h3ae) ^ in[469]; + assign d_o[470] = (syndrome_o == 10'h3ce) ^ in[470]; + assign d_o[471] = (syndrome_o == 10'h1f6) ^ in[471]; + assign d_o[472] = (syndrome_o == 10'h2f6) ^ in[472]; + assign d_o[473] = (syndrome_o == 10'h376) ^ in[473]; + assign d_o[474] = (syndrome_o == 10'h3b6) ^ in[474]; + assign d_o[475] = (syndrome_o == 10'h3d6) ^ in[475]; + assign d_o[476] = (syndrome_o == 10'h3e6) ^ in[476]; + assign d_o[477] = (syndrome_o == 10'h1fa) ^ in[477]; + assign d_o[478] = (syndrome_o == 10'h2fa) ^ in[478]; + assign d_o[479] = (syndrome_o == 10'h37a) ^ in[479]; + assign d_o[480] = (syndrome_o == 10'h3ba) ^ in[480]; + assign d_o[481] = (syndrome_o == 10'h3da) ^ in[481]; + assign d_o[482] = (syndrome_o == 10'h3ea) ^ in[482]; + assign d_o[483] = (syndrome_o == 10'h3f2) ^ in[483]; + assign d_o[484] = (syndrome_o == 10'h1fc) ^ in[484]; + assign d_o[485] = (syndrome_o == 10'h2fc) ^ in[485]; + assign d_o[486] = (syndrome_o == 10'h37c) ^ in[486]; + assign d_o[487] = (syndrome_o == 10'h3bc) ^ in[487]; + assign d_o[488] = (syndrome_o == 10'h3dc) ^ in[488]; + assign d_o[489] = (syndrome_o == 10'h3ec) ^ in[489]; + assign d_o[490] = (syndrome_o == 10'h3f4) ^ in[490]; + assign d_o[491] = (syndrome_o == 10'h3f8) ^ in[491]; + assign d_o[492] = (syndrome_o == 10'h1ff) ^ in[492]; + assign d_o[493] = (syndrome_o == 10'h2ff) ^ in[493]; + assign d_o[494] = (syndrome_o == 10'h37f) ^ in[494]; + assign d_o[495] = (syndrome_o == 10'h3bf) ^ in[495]; + assign d_o[496] = (syndrome_o == 10'h3df) ^ in[496]; + assign d_o[497] = (syndrome_o == 10'h3ef) ^ in[497]; + assign d_o[498] = (syndrome_o == 10'h3f7) ^ in[498]; + assign d_o[499] = (syndrome_o == 10'h3fb) ^ in[499]; + assign d_o[500] = (syndrome_o == 10'h3fd) ^ in[500]; + assign d_o[501] = (syndrome_o == 10'h3fe) ^ in[501]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_512_502_dec diff --git a/rtl/lowrisc_ecc/prim_secded_512_502_enc.sv b/rtl/lowrisc_ecc/prim_secded_512_502_enc.sv new file mode 100644 index 00000000..051efede --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_512_502_enc.sv @@ -0,0 +1,27 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Encoder generated by +// util/design/secded_gen.py -m 10 -k 502 -s 1592631616 -c hsiao + +module prim_secded_512_502_enc ( + input [501:0] in, + output logic [511:0] out +); + + always_comb begin : p_encode + out[501:0] = in; + out[502] = ^(in & 502'h1FF000000000FFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000FFFFFFFFF); + out[503] = ^(in & 502'h2FF00FFFFFFF0000000FFFFFFFFFFFFFF00000000000000FFFFFFFFFFFFFFFFFC00000000000000000FFFFFFFFFFFFFF00000000000000FFFFFFF0000000FF); + out[504] = ^(in & 502'h37F7F01FFFFF01FFFFF000007FFFFFFFF000007FFFFFFFF000000001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000000001FFFFF000007F000007F01); + out[505] = ^(in & 502'h3BFBF7E07FFF7E07FFF03FFF8000FFFFF03FFF8000FFFFF0001FFFFE00001FFFC0007FFFF800007FFF00000FFFE0003F00000FFFE0003F0001F810001F8102); + out[506] = ^(in & 502'h3DFDFBEF83FFBEF83FF7C1FF83FF003FF7C1FF83FF003FF07FE007FE007FE007C1FF801FF801FF801F003FF003E007C1003FF003E007C1003E082003E08204); + out[507] = ^(in & 502'h3EFEFDF7BC3FDF7BC3FBDE1FBC3F0FC0FBDE1FBC3F0FC0F787E1F81E1F81E0785E1F87E0787E0781E10FC0F03C2078420FC0F03C20784203C210403C210408); + out[508] = ^(in & 502'h3F7F7EFBDDC7EFBDDC7DEEE3DDC771C71DEEE3DDC771C71BB8EE38E2E38E2388AEE3B8E38B8E388E2271C711C443888471C711C44388841C442081C4420810); + out[509] = ^(in & 502'h3FBFBF7DEED9F7DEED9EF76CEED9B6592EF76CEED9B6592DDB36CB256CB24C91376CDB2C95B2C93244B65926488C9108B65926488C91086488410648841020); + out[510] = ^(in & 502'h3FDFDFBEF76AFBEF76AF7BB5776ADAAA4F7BB5776ADAAA4EED5B5549B55495223BB56D5526D5525488DAAA4A91152210DAAA4A91152210A910820A91082040); + out[511] = ^(in & 502'h3FEFEFDF7BB4FDF7BB4FBDDA7BB4ED348FBDDA7BB4ED348F769DA691DA691A443DDA769A4769A46910ED348D221A4420ED348D221A4420D221040D22104080); + end + +endmodule : prim_secded_512_502_enc diff --git a/rtl/lowrisc_ecc/prim_secded_64_57_cor.sv b/rtl/lowrisc_ecc/prim_secded_64_57_cor.sv new file mode 100644 index 00000000..c6190039 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_64_57_cor.sv @@ -0,0 +1,97 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 7 -k 57 -s 1592631616 -c hsiao + +module prim_secded_64_57_cor ( + input [63:0] d_i, + output logic [63:0] d_o, + output logic [6:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 64'h0303FFF800007FFF); + assign syndrome_o[1] = ^(d_i & 64'h057C1FF801FF801F); + assign syndrome_o[2] = ^(d_i & 64'h09BDE1F87E0781E1); + assign syndrome_o[3] = ^(d_i & 64'h11DEEE3B8E388E22); + assign syndrome_o[4] = ^(d_i & 64'h21EF76CDB2C93244); + assign syndrome_o[5] = ^(d_i & 64'h41F7BB56D5525488); + assign syndrome_o[6] = ^(d_i & 64'h81FBDDA769A46910); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 7'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 7'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 7'h13) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 7'h23) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 7'h43) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 7'hd) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 7'h15) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 7'h25) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 7'h45) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 7'h19) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 7'h29) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 7'h49) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 7'h31) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 7'h51) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 7'h61) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 7'he) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 7'h16) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 7'h26) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 7'h46) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 7'h1a) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 7'h2a) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 7'h4a) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 7'h32) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 7'h52) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 7'h62) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 7'h1c) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 7'h2c) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 7'h4c) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 7'h34) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 7'h54) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 7'h64) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 7'h38) ^ d_i[31]; + assign d_o[32] = (syndrome_o == 7'h58) ^ d_i[32]; + assign d_o[33] = (syndrome_o == 7'h68) ^ d_i[33]; + assign d_o[34] = (syndrome_o == 7'h70) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 7'h1f) ^ d_i[35]; + assign d_o[36] = (syndrome_o == 7'h2f) ^ d_i[36]; + assign d_o[37] = (syndrome_o == 7'h4f) ^ d_i[37]; + assign d_o[38] = (syndrome_o == 7'h37) ^ d_i[38]; + assign d_o[39] = (syndrome_o == 7'h57) ^ d_i[39]; + assign d_o[40] = (syndrome_o == 7'h67) ^ d_i[40]; + assign d_o[41] = (syndrome_o == 7'h3b) ^ d_i[41]; + assign d_o[42] = (syndrome_o == 7'h5b) ^ d_i[42]; + assign d_o[43] = (syndrome_o == 7'h6b) ^ d_i[43]; + assign d_o[44] = (syndrome_o == 7'h73) ^ d_i[44]; + assign d_o[45] = (syndrome_o == 7'h3d) ^ d_i[45]; + assign d_o[46] = (syndrome_o == 7'h5d) ^ d_i[46]; + assign d_o[47] = (syndrome_o == 7'h6d) ^ d_i[47]; + assign d_o[48] = (syndrome_o == 7'h75) ^ d_i[48]; + assign d_o[49] = (syndrome_o == 7'h79) ^ d_i[49]; + assign d_o[50] = (syndrome_o == 7'h3e) ^ d_i[50]; + assign d_o[51] = (syndrome_o == 7'h5e) ^ d_i[51]; + assign d_o[52] = (syndrome_o == 7'h6e) ^ d_i[52]; + assign d_o[53] = (syndrome_o == 7'h76) ^ d_i[53]; + assign d_o[54] = (syndrome_o == 7'h7a) ^ d_i[54]; + assign d_o[55] = (syndrome_o == 7'h7c) ^ d_i[55]; + assign d_o[56] = (syndrome_o == 7'h7f) ^ d_i[56]; + assign d_o[57] = (syndrome_o == 7'h1) ^ d_i[57]; + assign d_o[58] = (syndrome_o == 7'h2) ^ d_i[58]; + assign d_o[59] = (syndrome_o == 7'h4) ^ d_i[59]; + assign d_o[60] = (syndrome_o == 7'h8) ^ d_i[60]; + assign d_o[61] = (syndrome_o == 7'h10) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 7'h20) ^ d_i[62]; + assign d_o[63] = (syndrome_o == 7'h40) ^ d_i[63]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_64_57_cor diff --git a/rtl/lowrisc_ecc/prim_secded_64_57_enc.sv b/rtl/lowrisc_ecc/prim_secded_64_57_enc.sv index e1ca422c..7da8dabc 100644 --- a/rtl/lowrisc_ecc/prim_secded_64_57_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_64_57_enc.sv @@ -11,14 +11,14 @@ module prim_secded_64_57_enc ( ); always_comb begin : p_encode - out = 64'(in); - out[57] = ^(out & 64'h0103FFF800007FFF); - out[58] = ^(out & 64'h017C1FF801FF801F); - out[59] = ^(out & 64'h01BDE1F87E0781E1); - out[60] = ^(out & 64'h01DEEE3B8E388E22); - out[61] = ^(out & 64'h01EF76CDB2C93244); - out[62] = ^(out & 64'h01F7BB56D5525488); - out[63] = ^(out & 64'h01FBDDA769A46910); + out[56:0] = in; + out[57] = ^(in & 57'h103FFF800007FFF); + out[58] = ^(in & 57'h17C1FF801FF801F); + out[59] = ^(in & 57'h1BDE1F87E0781E1); + out[60] = ^(in & 57'h1DEEE3B8E388E22); + out[61] = ^(in & 57'h1EF76CDB2C93244); + out[62] = ^(in & 57'h1F7BB56D5525488); + out[63] = ^(in & 57'h1FBDDA769A46910); end endmodule : prim_secded_64_57_enc diff --git a/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv b/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv new file mode 100644 index 00000000..72c85cf4 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv @@ -0,0 +1,106 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 8 -k 64 -s 1592631616 -c hsiao + +module prim_secded_72_64_cor ( + input [71:0] d_i, + output logic [71:0] d_o, + output logic [7:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 72'h01F8000000001FFFFF); + assign syndrome_o[1] = ^(d_i & 72'h029D00000FFFE0003F); + assign syndrome_o[2] = ^(d_i & 72'h048F003FF003E007C1); + assign syndrome_o[3] = ^(d_i & 72'h08F10FC0F03C207842); + assign syndrome_o[4] = ^(d_i & 72'h106E71C711C4438884); + assign syndrome_o[5] = ^(d_i & 72'h203EB65926488C9108); + assign syndrome_o[6] = ^(d_i & 72'h40D3DAAA4A91152210); + assign syndrome_o[7] = ^(d_i & 72'h8067ED348D221A4420); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 8'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 8'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 8'h13) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 8'h23) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 8'h43) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 8'h83) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 8'hd) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 8'h15) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 8'h25) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 8'h45) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 8'h85) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 8'h19) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 8'h29) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 8'h49) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 8'h89) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 8'h31) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 8'h51) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 8'h91) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 8'h61) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 8'ha1) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 8'hc1) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 8'he) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 8'h16) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 8'h26) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 8'h46) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 8'h86) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 8'h1a) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 8'h2a) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 8'h4a) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 8'h8a) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 8'h32) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 8'h52) ^ d_i[31]; + assign d_o[32] = (syndrome_o == 8'h92) ^ d_i[32]; + assign d_o[33] = (syndrome_o == 8'h62) ^ d_i[33]; + assign d_o[34] = (syndrome_o == 8'ha2) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 8'hc2) ^ d_i[35]; + assign d_o[36] = (syndrome_o == 8'h1c) ^ d_i[36]; + assign d_o[37] = (syndrome_o == 8'h2c) ^ d_i[37]; + assign d_o[38] = (syndrome_o == 8'h4c) ^ d_i[38]; + assign d_o[39] = (syndrome_o == 8'h8c) ^ d_i[39]; + assign d_o[40] = (syndrome_o == 8'h34) ^ d_i[40]; + assign d_o[41] = (syndrome_o == 8'h54) ^ d_i[41]; + assign d_o[42] = (syndrome_o == 8'h94) ^ d_i[42]; + assign d_o[43] = (syndrome_o == 8'h64) ^ d_i[43]; + assign d_o[44] = (syndrome_o == 8'ha4) ^ d_i[44]; + assign d_o[45] = (syndrome_o == 8'hc4) ^ d_i[45]; + assign d_o[46] = (syndrome_o == 8'h38) ^ d_i[46]; + assign d_o[47] = (syndrome_o == 8'h58) ^ d_i[47]; + assign d_o[48] = (syndrome_o == 8'h98) ^ d_i[48]; + assign d_o[49] = (syndrome_o == 8'h68) ^ d_i[49]; + assign d_o[50] = (syndrome_o == 8'ha8) ^ d_i[50]; + assign d_o[51] = (syndrome_o == 8'hc8) ^ d_i[51]; + assign d_o[52] = (syndrome_o == 8'h70) ^ d_i[52]; + assign d_o[53] = (syndrome_o == 8'hb0) ^ d_i[53]; + assign d_o[54] = (syndrome_o == 8'hd0) ^ d_i[54]; + assign d_o[55] = (syndrome_o == 8'he0) ^ d_i[55]; + assign d_o[56] = (syndrome_o == 8'hce) ^ d_i[56]; + assign d_o[57] = (syndrome_o == 8'hf4) ^ d_i[57]; + assign d_o[58] = (syndrome_o == 8'hb6) ^ d_i[58]; + assign d_o[59] = (syndrome_o == 8'h37) ^ d_i[59]; + assign d_o[60] = (syndrome_o == 8'h6b) ^ d_i[60]; + assign d_o[61] = (syndrome_o == 8'hb9) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 8'hd9) ^ d_i[62]; + assign d_o[63] = (syndrome_o == 8'h4f) ^ d_i[63]; + assign d_o[64] = (syndrome_o == 8'h1) ^ d_i[64]; + assign d_o[65] = (syndrome_o == 8'h2) ^ d_i[65]; + assign d_o[66] = (syndrome_o == 8'h4) ^ d_i[66]; + assign d_o[67] = (syndrome_o == 8'h8) ^ d_i[67]; + assign d_o[68] = (syndrome_o == 8'h10) ^ d_i[68]; + assign d_o[69] = (syndrome_o == 8'h20) ^ d_i[69]; + assign d_o[70] = (syndrome_o == 8'h40) ^ d_i[70]; + assign d_o[71] = (syndrome_o == 8'h80) ^ d_i[71]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_72_64_cor diff --git a/rtl/lowrisc_ecc/prim_secded_72_64_enc.sv b/rtl/lowrisc_ecc/prim_secded_72_64_enc.sv index 92b72941..ddf9943c 100644 --- a/rtl/lowrisc_ecc/prim_secded_72_64_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_72_64_enc.sv @@ -11,15 +11,15 @@ module prim_secded_72_64_enc ( ); always_comb begin : p_encode - out = 72'(in); - out[64] = ^(out & 72'h00F8000000001FFFFF); - out[65] = ^(out & 72'h009D00000FFFE0003F); - out[66] = ^(out & 72'h008F003FF003E007C1); - out[67] = ^(out & 72'h00F10FC0F03C207842); - out[68] = ^(out & 72'h006E71C711C4438884); - out[69] = ^(out & 72'h003EB65926488C9108); - out[70] = ^(out & 72'h00D3DAAA4A91152210); - out[71] = ^(out & 72'h0067ED348D221A4420); + out[63:0] = in; + out[64] = ^(in & 64'hF8000000001FFFFF); + out[65] = ^(in & 64'h9D00000FFFE0003F); + out[66] = ^(in & 64'h8F003FF003E007C1); + out[67] = ^(in & 64'hF10FC0F03C207842); + out[68] = ^(in & 64'h6E71C711C4438884); + out[69] = ^(in & 64'h3EB65926488C9108); + out[70] = ^(in & 64'hD3DAAA4A91152210); + out[71] = ^(in & 64'h67ED348D221A4420); end endmodule : prim_secded_72_64_enc diff --git a/rtl/lowrisc_ecc/prim_secded_8_4_cor.sv b/rtl/lowrisc_ecc/prim_secded_8_4_cor.sv new file mode 100644 index 00000000..6556f3bb --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_8_4_cor.sv @@ -0,0 +1,38 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 4 -k 4 -s 1592631616 -c hsiao + +module prim_secded_8_4_cor ( + input [7:0] d_i, + output logic [7:0] d_o, + output logic [3:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 8'h17); + assign syndrome_o[1] = ^(d_i & 8'h2B); + assign syndrome_o[2] = ^(d_i & 8'h4D); + assign syndrome_o[3] = ^(d_i & 8'h8E); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 4'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 4'hb) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 4'hd) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 4'he) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 4'h1) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 4'h2) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 4'h4) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 4'h8) ^ d_i[7]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_8_4_cor diff --git a/rtl/lowrisc_ecc/prim_secded_8_4_dec.sv b/rtl/lowrisc_ecc/prim_secded_8_4_dec.sv new file mode 100644 index 00000000..78e438de --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_8_4_dec.sv @@ -0,0 +1,34 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Decoder generated by +// util/design/secded_gen.py -m 4 -k 4 -s 1592631616 -c hsiao + +module prim_secded_8_4_dec ( + input [7:0] in, + output logic [3:0] d_o, + output logic [3:0] syndrome_o, + output logic [1:0] err_o +); + + logic single_error; + + // Syndrome calculation + assign syndrome_o[0] = ^(in & 8'h17); + assign syndrome_o[1] = ^(in & 8'h2B); + assign syndrome_o[2] = ^(in & 8'h4D); + assign syndrome_o[3] = ^(in & 8'h8E); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 4'h7) ^ in[0]; + assign d_o[1] = (syndrome_o == 4'hb) ^ in[1]; + assign d_o[2] = (syndrome_o == 4'hd) ^ in[2]; + assign d_o[3] = (syndrome_o == 4'he) ^ in[3]; + + // err_o calc. bit0: single error, bit1: double error + assign single_error = ^syndrome_o; + assign err_o[0] = single_error; + assign err_o[1] = ~single_error & (|syndrome_o); + +endmodule : prim_secded_8_4_dec diff --git a/rtl/lowrisc_ecc/prim_secded_8_4_enc.sv b/rtl/lowrisc_ecc/prim_secded_8_4_enc.sv new file mode 100644 index 00000000..3cbcffe7 --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_8_4_enc.sv @@ -0,0 +1,21 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Encoder generated by +// util/design/secded_gen.py -m 4 -k 4 -s 1592631616 -c hsiao + +module prim_secded_8_4_enc ( + input [3:0] in, + output logic [7:0] out +); + + always_comb begin : p_encode + out[3:0] = in; + out[4] = ^(in & 4'h7); + out[5] = ^(in & 4'hB); + out[6] = ^(in & 4'hD); + out[7] = ^(in & 4'hE); + end + +endmodule : prim_secded_8_4_enc diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv new file mode 100644 index 00000000..249a9e7f --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv @@ -0,0 +1,52 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 6 -k 16 -s 1592631616 -c hamming + +module prim_secded_hamming_22_16_cor ( + input [21:0] d_i, + output logic [21:0] d_o, + output logic [5:0] syndrome_o, + output logic [1:0] err_o +); + + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 22'h01AD5B); + assign syndrome_o[1] = ^(d_i & 22'h02366D); + assign syndrome_o[2] = ^(d_i & 22'h04C78E); + assign syndrome_o[3] = ^(d_i & 22'h0807F0); + assign syndrome_o[4] = ^(d_i & 22'h10F800); + assign syndrome_o[5] = ^(d_i & 22'h205CB7); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 6'h23) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 6'h25) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 6'h26) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 6'h7) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 6'h29) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 6'h2a) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 6'hb) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 6'h2c) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 6'hd) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 6'he) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 6'h2f) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 6'h31) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 6'h32) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 6'h13) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 6'h34) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 6'h15) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 6'h1) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 6'h2) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 6'h4) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 6'h8) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 6'h10) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 6'h20) ^ d_i[21]; + + // err_o calc. bit0: single error, bit1: double error + assign err_o[0] = syndrome_o[5]; + assign err_o[1] = |syndrome_o[4:0] & ~syndrome_o[5]; + +endmodule : prim_secded_hamming_22_16_cor diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_dec.sv b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_dec.sv index 34ce95c3..f47fe093 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_dec.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_dec.sv @@ -19,25 +19,25 @@ module prim_secded_hamming_22_16_dec ( assign syndrome_o[2] = ^(in & 22'h04C78E); assign syndrome_o[3] = ^(in & 22'h0807F0); assign syndrome_o[4] = ^(in & 22'h10F800); - assign syndrome_o[5] = ^(in & 22'h3FFFFF); + assign syndrome_o[5] = ^(in & 22'h205CB7); // Corrected output calculation assign d_o[0] = (syndrome_o == 6'h23) ^ in[0]; assign d_o[1] = (syndrome_o == 6'h25) ^ in[1]; assign d_o[2] = (syndrome_o == 6'h26) ^ in[2]; - assign d_o[3] = (syndrome_o == 6'h27) ^ in[3]; + assign d_o[3] = (syndrome_o == 6'h7) ^ in[3]; assign d_o[4] = (syndrome_o == 6'h29) ^ in[4]; assign d_o[5] = (syndrome_o == 6'h2a) ^ in[5]; - assign d_o[6] = (syndrome_o == 6'h2b) ^ in[6]; + assign d_o[6] = (syndrome_o == 6'hb) ^ in[6]; assign d_o[7] = (syndrome_o == 6'h2c) ^ in[7]; - assign d_o[8] = (syndrome_o == 6'h2d) ^ in[8]; - assign d_o[9] = (syndrome_o == 6'h2e) ^ in[9]; + assign d_o[8] = (syndrome_o == 6'hd) ^ in[8]; + assign d_o[9] = (syndrome_o == 6'he) ^ in[9]; assign d_o[10] = (syndrome_o == 6'h2f) ^ in[10]; assign d_o[11] = (syndrome_o == 6'h31) ^ in[11]; assign d_o[12] = (syndrome_o == 6'h32) ^ in[12]; - assign d_o[13] = (syndrome_o == 6'h33) ^ in[13]; + assign d_o[13] = (syndrome_o == 6'h13) ^ in[13]; assign d_o[14] = (syndrome_o == 6'h34) ^ in[14]; - assign d_o[15] = (syndrome_o == 6'h35) ^ in[15]; + assign d_o[15] = (syndrome_o == 6'h15) ^ in[15]; // err_o calc. bit0: single error, bit1: double error assign err_o[0] = syndrome_o[5]; diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_enc.sv b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_enc.sv index fd01413c..57d75e4f 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_enc.sv @@ -11,13 +11,13 @@ module prim_secded_hamming_22_16_enc ( ); always_comb begin : p_encode - out = 22'(in); - out[16] = ^(out & 22'h00AD5B); - out[17] = ^(out & 22'h00366D); - out[18] = ^(out & 22'h00C78E); - out[19] = ^(out & 22'h0007F0); - out[20] = ^(out & 22'h00F800); - out[21] = ^(out & 22'h1FFFFF); + out[15:0] = in; + out[16] = ^(in & 16'hAD5B); + out[17] = ^(in & 16'h366D); + out[18] = ^(in & 16'hC78E); + out[19] = ^(in & 16'h07F0); + out[20] = ^(in & 16'hF800); + out[21] = ^(in & 16'h5CB7); end endmodule : prim_secded_hamming_22_16_enc diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv new file mode 100644 index 00000000..c861663c --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv @@ -0,0 +1,70 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 7 -k 32 -s 1592631616 -c hamming + +module prim_secded_hamming_39_32_cor ( + input [38:0] d_i, + output logic [38:0] d_o, + output logic [6:0] syndrome_o, + output logic [1:0] err_o +); + + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 39'h0156AAAD5B); + assign syndrome_o[1] = ^(d_i & 39'h029B33366D); + assign syndrome_o[2] = ^(d_i & 39'h04E3C3C78E); + assign syndrome_o[3] = ^(d_i & 39'h0803FC07F0); + assign syndrome_o[4] = ^(d_i & 39'h1003FFF800); + assign syndrome_o[5] = ^(d_i & 39'h20FC000000); + assign syndrome_o[6] = ^(d_i & 39'h402DA65CB7); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 7'h43) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 7'h45) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 7'h46) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 7'h7) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 7'h49) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 7'h4a) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 7'hb) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 7'h4c) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 7'hd) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 7'he) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 7'h4f) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 7'h51) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 7'h52) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 7'h13) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 7'h54) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 7'h15) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 7'h16) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 7'h57) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 7'h58) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 7'h19) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 7'h1a) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 7'h5b) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 7'h1c) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 7'h5d) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 7'h5e) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 7'h1f) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 7'h61) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 7'h62) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 7'h23) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 7'h64) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 7'h25) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 7'h26) ^ d_i[31]; + assign d_o[32] = (syndrome_o == 7'h1) ^ d_i[32]; + assign d_o[33] = (syndrome_o == 7'h2) ^ d_i[33]; + assign d_o[34] = (syndrome_o == 7'h4) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 7'h8) ^ d_i[35]; + assign d_o[36] = (syndrome_o == 7'h10) ^ d_i[36]; + assign d_o[37] = (syndrome_o == 7'h20) ^ d_i[37]; + assign d_o[38] = (syndrome_o == 7'h40) ^ d_i[38]; + + // err_o calc. bit0: single error, bit1: double error + assign err_o[0] = syndrome_o[6]; + assign err_o[1] = |syndrome_o[5:0] & ~syndrome_o[6]; + +endmodule : prim_secded_hamming_39_32_cor diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_dec.sv b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_dec.sv index 9bcd7de2..f3c69fa1 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_dec.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_dec.sv @@ -20,41 +20,41 @@ module prim_secded_hamming_39_32_dec ( assign syndrome_o[3] = ^(in & 39'h0803FC07F0); assign syndrome_o[4] = ^(in & 39'h1003FFF800); assign syndrome_o[5] = ^(in & 39'h20FC000000); - assign syndrome_o[6] = ^(in & 39'h7FFFFFFFFF); + assign syndrome_o[6] = ^(in & 39'h402DA65CB7); // Corrected output calculation assign d_o[0] = (syndrome_o == 7'h43) ^ in[0]; assign d_o[1] = (syndrome_o == 7'h45) ^ in[1]; assign d_o[2] = (syndrome_o == 7'h46) ^ in[2]; - assign d_o[3] = (syndrome_o == 7'h47) ^ in[3]; + assign d_o[3] = (syndrome_o == 7'h7) ^ in[3]; assign d_o[4] = (syndrome_o == 7'h49) ^ in[4]; assign d_o[5] = (syndrome_o == 7'h4a) ^ in[5]; - assign d_o[6] = (syndrome_o == 7'h4b) ^ in[6]; + assign d_o[6] = (syndrome_o == 7'hb) ^ in[6]; assign d_o[7] = (syndrome_o == 7'h4c) ^ in[7]; - assign d_o[8] = (syndrome_o == 7'h4d) ^ in[8]; - assign d_o[9] = (syndrome_o == 7'h4e) ^ in[9]; + assign d_o[8] = (syndrome_o == 7'hd) ^ in[8]; + assign d_o[9] = (syndrome_o == 7'he) ^ in[9]; assign d_o[10] = (syndrome_o == 7'h4f) ^ in[10]; assign d_o[11] = (syndrome_o == 7'h51) ^ in[11]; assign d_o[12] = (syndrome_o == 7'h52) ^ in[12]; - assign d_o[13] = (syndrome_o == 7'h53) ^ in[13]; + assign d_o[13] = (syndrome_o == 7'h13) ^ in[13]; assign d_o[14] = (syndrome_o == 7'h54) ^ in[14]; - assign d_o[15] = (syndrome_o == 7'h55) ^ in[15]; - assign d_o[16] = (syndrome_o == 7'h56) ^ in[16]; + assign d_o[15] = (syndrome_o == 7'h15) ^ in[15]; + assign d_o[16] = (syndrome_o == 7'h16) ^ in[16]; assign d_o[17] = (syndrome_o == 7'h57) ^ in[17]; assign d_o[18] = (syndrome_o == 7'h58) ^ in[18]; - assign d_o[19] = (syndrome_o == 7'h59) ^ in[19]; - assign d_o[20] = (syndrome_o == 7'h5a) ^ in[20]; + assign d_o[19] = (syndrome_o == 7'h19) ^ in[19]; + assign d_o[20] = (syndrome_o == 7'h1a) ^ in[20]; assign d_o[21] = (syndrome_o == 7'h5b) ^ in[21]; - assign d_o[22] = (syndrome_o == 7'h5c) ^ in[22]; + assign d_o[22] = (syndrome_o == 7'h1c) ^ in[22]; assign d_o[23] = (syndrome_o == 7'h5d) ^ in[23]; assign d_o[24] = (syndrome_o == 7'h5e) ^ in[24]; - assign d_o[25] = (syndrome_o == 7'h5f) ^ in[25]; + assign d_o[25] = (syndrome_o == 7'h1f) ^ in[25]; assign d_o[26] = (syndrome_o == 7'h61) ^ in[26]; assign d_o[27] = (syndrome_o == 7'h62) ^ in[27]; - assign d_o[28] = (syndrome_o == 7'h63) ^ in[28]; + assign d_o[28] = (syndrome_o == 7'h23) ^ in[28]; assign d_o[29] = (syndrome_o == 7'h64) ^ in[29]; - assign d_o[30] = (syndrome_o == 7'h65) ^ in[30]; - assign d_o[31] = (syndrome_o == 7'h66) ^ in[31]; + assign d_o[30] = (syndrome_o == 7'h25) ^ in[30]; + assign d_o[31] = (syndrome_o == 7'h26) ^ in[31]; // err_o calc. bit0: single error, bit1: double error assign err_o[0] = syndrome_o[6]; diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_enc.sv b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_enc.sv index 222e31de..fdd9eb3e 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_enc.sv @@ -11,14 +11,14 @@ module prim_secded_hamming_39_32_enc ( ); always_comb begin : p_encode - out = 39'(in); - out[32] = ^(out & 39'h0056AAAD5B); - out[33] = ^(out & 39'h009B33366D); - out[34] = ^(out & 39'h00E3C3C78E); - out[35] = ^(out & 39'h0003FC07F0); - out[36] = ^(out & 39'h0003FFF800); - out[37] = ^(out & 39'h00FC000000); - out[38] = ^(out & 39'h3FFFFFFFFF); + out[31:0] = in; + out[32] = ^(in & 32'h56AAAD5B); + out[33] = ^(in & 32'h9B33366D); + out[34] = ^(in & 32'hE3C3C78E); + out[35] = ^(in & 32'h03FC07F0); + out[36] = ^(in & 32'h03FFF800); + out[37] = ^(in & 32'hFC000000); + out[38] = ^(in & 32'h2DA65CB7); end endmodule : prim_secded_hamming_39_32_enc diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv new file mode 100644 index 00000000..896f97ac --- /dev/null +++ b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv @@ -0,0 +1,104 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED Corrector generated by +// util/design/secded_gen.py -m 8 -k 64 -s 1592631616 -c hamming + +module prim_secded_hamming_72_64_cor ( + input [71:0] d_i, + output logic [71:0] d_o, + output logic [7:0] syndrome_o, + output logic [1:0] err_o +); + + + // Syndrome calculation + assign syndrome_o[0] = ^(d_i & 72'h01AB55555556AAAD5B); + assign syndrome_o[1] = ^(d_i & 72'h02CD9999999B33366D); + assign syndrome_o[2] = ^(d_i & 72'h04F1E1E1E1E3C3C78E); + assign syndrome_o[3] = ^(d_i & 72'h0801FE01FE03FC07F0); + assign syndrome_o[4] = ^(d_i & 72'h1001FFFE0003FFF800); + assign syndrome_o[5] = ^(d_i & 72'h2001FFFFFFFC000000); + assign syndrome_o[6] = ^(d_i & 72'h40FE00000000000000); + assign syndrome_o[7] = ^(d_i & 72'h80972CD2D32DA65CB7); + + // Corrected output calculation + assign d_o[0] = (syndrome_o == 8'h83) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 8'h85) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 8'h86) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 8'h7) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 8'h89) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 8'h8a) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 8'hb) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 8'h8c) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 8'hd) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 8'he) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 8'h8f) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 8'h91) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 8'h92) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 8'h13) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 8'h94) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 8'h15) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 8'h16) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 8'h97) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 8'h98) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 8'h19) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 8'h1a) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 8'h9b) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 8'h1c) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 8'h9d) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 8'h9e) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 8'h1f) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 8'ha1) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 8'ha2) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 8'h23) ^ d_i[28]; + assign d_o[29] = (syndrome_o == 8'ha4) ^ d_i[29]; + assign d_o[30] = (syndrome_o == 8'h25) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 8'h26) ^ d_i[31]; + assign d_o[32] = (syndrome_o == 8'ha7) ^ d_i[32]; + assign d_o[33] = (syndrome_o == 8'ha8) ^ d_i[33]; + assign d_o[34] = (syndrome_o == 8'h29) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 8'h2a) ^ d_i[35]; + assign d_o[36] = (syndrome_o == 8'hab) ^ d_i[36]; + assign d_o[37] = (syndrome_o == 8'h2c) ^ d_i[37]; + assign d_o[38] = (syndrome_o == 8'had) ^ d_i[38]; + assign d_o[39] = (syndrome_o == 8'hae) ^ d_i[39]; + assign d_o[40] = (syndrome_o == 8'h2f) ^ d_i[40]; + assign d_o[41] = (syndrome_o == 8'hb0) ^ d_i[41]; + assign d_o[42] = (syndrome_o == 8'h31) ^ d_i[42]; + assign d_o[43] = (syndrome_o == 8'h32) ^ d_i[43]; + assign d_o[44] = (syndrome_o == 8'hb3) ^ d_i[44]; + assign d_o[45] = (syndrome_o == 8'h34) ^ d_i[45]; + assign d_o[46] = (syndrome_o == 8'hb5) ^ d_i[46]; + assign d_o[47] = (syndrome_o == 8'hb6) ^ d_i[47]; + assign d_o[48] = (syndrome_o == 8'h37) ^ d_i[48]; + assign d_o[49] = (syndrome_o == 8'h38) ^ d_i[49]; + assign d_o[50] = (syndrome_o == 8'hb9) ^ d_i[50]; + assign d_o[51] = (syndrome_o == 8'hba) ^ d_i[51]; + assign d_o[52] = (syndrome_o == 8'h3b) ^ d_i[52]; + assign d_o[53] = (syndrome_o == 8'hbc) ^ d_i[53]; + assign d_o[54] = (syndrome_o == 8'h3d) ^ d_i[54]; + assign d_o[55] = (syndrome_o == 8'h3e) ^ d_i[55]; + assign d_o[56] = (syndrome_o == 8'hbf) ^ d_i[56]; + assign d_o[57] = (syndrome_o == 8'hc1) ^ d_i[57]; + assign d_o[58] = (syndrome_o == 8'hc2) ^ d_i[58]; + assign d_o[59] = (syndrome_o == 8'h43) ^ d_i[59]; + assign d_o[60] = (syndrome_o == 8'hc4) ^ d_i[60]; + assign d_o[61] = (syndrome_o == 8'h45) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 8'h46) ^ d_i[62]; + assign d_o[63] = (syndrome_o == 8'hc7) ^ d_i[63]; + assign d_o[64] = (syndrome_o == 8'h1) ^ d_i[64]; + assign d_o[65] = (syndrome_o == 8'h2) ^ d_i[65]; + assign d_o[66] = (syndrome_o == 8'h4) ^ d_i[66]; + assign d_o[67] = (syndrome_o == 8'h8) ^ d_i[67]; + assign d_o[68] = (syndrome_o == 8'h10) ^ d_i[68]; + assign d_o[69] = (syndrome_o == 8'h20) ^ d_i[69]; + assign d_o[70] = (syndrome_o == 8'h40) ^ d_i[70]; + assign d_o[71] = (syndrome_o == 8'h80) ^ d_i[71]; + + // err_o calc. bit0: single error, bit1: double error + assign err_o[0] = syndrome_o[7]; + assign err_o[1] = |syndrome_o[6:0] & ~syndrome_o[7]; + +endmodule : prim_secded_hamming_72_64_cor diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_dec.sv b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_dec.sv index e25de52e..cfb0fd06 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_dec.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_dec.sv @@ -21,72 +21,72 @@ module prim_secded_hamming_72_64_dec ( assign syndrome_o[4] = ^(in & 72'h1001FFFE0003FFF800); assign syndrome_o[5] = ^(in & 72'h2001FFFFFFFC000000); assign syndrome_o[6] = ^(in & 72'h40FE00000000000000); - assign syndrome_o[7] = ^(in & 72'hFFFFFFFFFFFFFFFFFF); + assign syndrome_o[7] = ^(in & 72'h80972CD2D32DA65CB7); // Corrected output calculation assign d_o[0] = (syndrome_o == 8'h83) ^ in[0]; assign d_o[1] = (syndrome_o == 8'h85) ^ in[1]; assign d_o[2] = (syndrome_o == 8'h86) ^ in[2]; - assign d_o[3] = (syndrome_o == 8'h87) ^ in[3]; + assign d_o[3] = (syndrome_o == 8'h7) ^ in[3]; assign d_o[4] = (syndrome_o == 8'h89) ^ in[4]; assign d_o[5] = (syndrome_o == 8'h8a) ^ in[5]; - assign d_o[6] = (syndrome_o == 8'h8b) ^ in[6]; + assign d_o[6] = (syndrome_o == 8'hb) ^ in[6]; assign d_o[7] = (syndrome_o == 8'h8c) ^ in[7]; - assign d_o[8] = (syndrome_o == 8'h8d) ^ in[8]; - assign d_o[9] = (syndrome_o == 8'h8e) ^ in[9]; + assign d_o[8] = (syndrome_o == 8'hd) ^ in[8]; + assign d_o[9] = (syndrome_o == 8'he) ^ in[9]; assign d_o[10] = (syndrome_o == 8'h8f) ^ in[10]; assign d_o[11] = (syndrome_o == 8'h91) ^ in[11]; assign d_o[12] = (syndrome_o == 8'h92) ^ in[12]; - assign d_o[13] = (syndrome_o == 8'h93) ^ in[13]; + assign d_o[13] = (syndrome_o == 8'h13) ^ in[13]; assign d_o[14] = (syndrome_o == 8'h94) ^ in[14]; - assign d_o[15] = (syndrome_o == 8'h95) ^ in[15]; - assign d_o[16] = (syndrome_o == 8'h96) ^ in[16]; + assign d_o[15] = (syndrome_o == 8'h15) ^ in[15]; + assign d_o[16] = (syndrome_o == 8'h16) ^ in[16]; assign d_o[17] = (syndrome_o == 8'h97) ^ in[17]; assign d_o[18] = (syndrome_o == 8'h98) ^ in[18]; - assign d_o[19] = (syndrome_o == 8'h99) ^ in[19]; - assign d_o[20] = (syndrome_o == 8'h9a) ^ in[20]; + assign d_o[19] = (syndrome_o == 8'h19) ^ in[19]; + assign d_o[20] = (syndrome_o == 8'h1a) ^ in[20]; assign d_o[21] = (syndrome_o == 8'h9b) ^ in[21]; - assign d_o[22] = (syndrome_o == 8'h9c) ^ in[22]; + assign d_o[22] = (syndrome_o == 8'h1c) ^ in[22]; assign d_o[23] = (syndrome_o == 8'h9d) ^ in[23]; assign d_o[24] = (syndrome_o == 8'h9e) ^ in[24]; - assign d_o[25] = (syndrome_o == 8'h9f) ^ in[25]; + assign d_o[25] = (syndrome_o == 8'h1f) ^ in[25]; assign d_o[26] = (syndrome_o == 8'ha1) ^ in[26]; assign d_o[27] = (syndrome_o == 8'ha2) ^ in[27]; - assign d_o[28] = (syndrome_o == 8'ha3) ^ in[28]; + assign d_o[28] = (syndrome_o == 8'h23) ^ in[28]; assign d_o[29] = (syndrome_o == 8'ha4) ^ in[29]; - assign d_o[30] = (syndrome_o == 8'ha5) ^ in[30]; - assign d_o[31] = (syndrome_o == 8'ha6) ^ in[31]; + assign d_o[30] = (syndrome_o == 8'h25) ^ in[30]; + assign d_o[31] = (syndrome_o == 8'h26) ^ in[31]; assign d_o[32] = (syndrome_o == 8'ha7) ^ in[32]; assign d_o[33] = (syndrome_o == 8'ha8) ^ in[33]; - assign d_o[34] = (syndrome_o == 8'ha9) ^ in[34]; - assign d_o[35] = (syndrome_o == 8'haa) ^ in[35]; + assign d_o[34] = (syndrome_o == 8'h29) ^ in[34]; + assign d_o[35] = (syndrome_o == 8'h2a) ^ in[35]; assign d_o[36] = (syndrome_o == 8'hab) ^ in[36]; - assign d_o[37] = (syndrome_o == 8'hac) ^ in[37]; + assign d_o[37] = (syndrome_o == 8'h2c) ^ in[37]; assign d_o[38] = (syndrome_o == 8'had) ^ in[38]; assign d_o[39] = (syndrome_o == 8'hae) ^ in[39]; - assign d_o[40] = (syndrome_o == 8'haf) ^ in[40]; + assign d_o[40] = (syndrome_o == 8'h2f) ^ in[40]; assign d_o[41] = (syndrome_o == 8'hb0) ^ in[41]; - assign d_o[42] = (syndrome_o == 8'hb1) ^ in[42]; - assign d_o[43] = (syndrome_o == 8'hb2) ^ in[43]; + assign d_o[42] = (syndrome_o == 8'h31) ^ in[42]; + assign d_o[43] = (syndrome_o == 8'h32) ^ in[43]; assign d_o[44] = (syndrome_o == 8'hb3) ^ in[44]; - assign d_o[45] = (syndrome_o == 8'hb4) ^ in[45]; + assign d_o[45] = (syndrome_o == 8'h34) ^ in[45]; assign d_o[46] = (syndrome_o == 8'hb5) ^ in[46]; assign d_o[47] = (syndrome_o == 8'hb6) ^ in[47]; - assign d_o[48] = (syndrome_o == 8'hb7) ^ in[48]; - assign d_o[49] = (syndrome_o == 8'hb8) ^ in[49]; + assign d_o[48] = (syndrome_o == 8'h37) ^ in[48]; + assign d_o[49] = (syndrome_o == 8'h38) ^ in[49]; assign d_o[50] = (syndrome_o == 8'hb9) ^ in[50]; assign d_o[51] = (syndrome_o == 8'hba) ^ in[51]; - assign d_o[52] = (syndrome_o == 8'hbb) ^ in[52]; + assign d_o[52] = (syndrome_o == 8'h3b) ^ in[52]; assign d_o[53] = (syndrome_o == 8'hbc) ^ in[53]; - assign d_o[54] = (syndrome_o == 8'hbd) ^ in[54]; - assign d_o[55] = (syndrome_o == 8'hbe) ^ in[55]; + assign d_o[54] = (syndrome_o == 8'h3d) ^ in[54]; + assign d_o[55] = (syndrome_o == 8'h3e) ^ in[55]; assign d_o[56] = (syndrome_o == 8'hbf) ^ in[56]; assign d_o[57] = (syndrome_o == 8'hc1) ^ in[57]; assign d_o[58] = (syndrome_o == 8'hc2) ^ in[58]; - assign d_o[59] = (syndrome_o == 8'hc3) ^ in[59]; + assign d_o[59] = (syndrome_o == 8'h43) ^ in[59]; assign d_o[60] = (syndrome_o == 8'hc4) ^ in[60]; - assign d_o[61] = (syndrome_o == 8'hc5) ^ in[61]; - assign d_o[62] = (syndrome_o == 8'hc6) ^ in[62]; + assign d_o[61] = (syndrome_o == 8'h45) ^ in[61]; + assign d_o[62] = (syndrome_o == 8'h46) ^ in[62]; assign d_o[63] = (syndrome_o == 8'hc7) ^ in[63]; // err_o calc. bit0: single error, bit1: double error diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_enc.sv b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_enc.sv index 1fd06ddb..a8e98f2b 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_enc.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_enc.sv @@ -11,15 +11,15 @@ module prim_secded_hamming_72_64_enc ( ); always_comb begin : p_encode - out = 72'(in); - out[64] = ^(out & 72'h00AB55555556AAAD5B); - out[65] = ^(out & 72'h00CD9999999B33366D); - out[66] = ^(out & 72'h00F1E1E1E1E3C3C78E); - out[67] = ^(out & 72'h0001FE01FE03FC07F0); - out[68] = ^(out & 72'h0001FFFE0003FFF800); - out[69] = ^(out & 72'h0001FFFFFFFC000000); - out[70] = ^(out & 72'h00FE00000000000000); - out[71] = ^(out & 72'h7FFFFFFFFFFFFFFFFF); + out[63:0] = in; + out[64] = ^(in & 64'hAB55555556AAAD5B); + out[65] = ^(in & 64'hCD9999999B33366D); + out[66] = ^(in & 64'hF1E1E1E1E3C3C78E); + out[67] = ^(in & 64'h01FE01FE03FC07F0); + out[68] = ^(in & 64'h01FFFE0003FFF800); + out[69] = ^(in & 64'h01FFFFFFFC000000); + out[70] = ^(in & 64'hFE00000000000000); + out[71] = ^(in & 64'h972CD2D32DA65CB7); end endmodule : prim_secded_hamming_72_64_enc diff --git a/rtl/lowrisc_ecc/prim_secded_pkg.sv b/rtl/lowrisc_ecc/prim_secded_pkg.sv index 0fc42ebd..bcc325d4 100644 --- a/rtl/lowrisc_ecc/prim_secded_pkg.sv +++ b/rtl/lowrisc_ecc/prim_secded_pkg.sv @@ -7,12 +7,30 @@ package prim_secded_pkg; + typedef struct packed { + logic [0:0] data; + logic [2:0] syndrome; + logic [1:0] err; + } secded_4_1_t; + + typedef struct packed { + logic [3:0] data; + logic [3:0] syndrome; + logic [1:0] err; + } secded_8_4_t; + typedef struct packed { logic [7:0] data; logic [4:0] syndrome; logic [1:0] err; } secded_13_8_t; + typedef struct packed { + logic [10:0] data; + logic [4:0] syndrome; + logic [1:0] err; + } secded_16_11_t; + typedef struct packed { logic [15:0] data; logic [5:0] syndrome; @@ -25,6 +43,12 @@ package prim_secded_pkg; logic [1:0] err; } secded_28_22_t; + typedef struct packed { + logic [25:0] data; + logic [5:0] syndrome; + logic [1:0] err; + } secded_32_26_t; + typedef struct packed { logic [31:0] data; logic [6:0] syndrome; @@ -43,6 +67,24 @@ package prim_secded_pkg; logic [1:0] err; } secded_72_64_t; + typedef struct packed { + logic [119:0] data; + logic [7:0] syndrome; + logic [1:0] err; + } secded_128_120_t; + + typedef struct packed { + logic [246:0] data; + logic [8:0] syndrome; + logic [1:0] err; + } secded_256_247_t; + + typedef struct packed { + logic [501:0] data; + logic [9:0] syndrome; + logic [1:0] err; + } secded_512_502_t; + typedef struct packed { logic [15:0] data; logic [5:0] syndrome; @@ -61,14 +103,95 @@ package prim_secded_pkg; logic [1:0] err; } secded_hamming_72_64_t; + function automatic logic [3:0] prim_secded_4_1_enc (logic [0:0] in); + logic [3:0] out; + out[0:0] = in; + out[1] = ^(in & 1'h1); + out[2] = ^(in & 1'h1); + out[3] = ^(in & 1'h1); + return out; + endfunction + + function automatic secded_4_1_t prim_secded_4_1_dec (logic [3:0] in); + logic [0:0] d_o; + logic [2:0] syndrome_o; + logic [1:0] err_o; + + secded_4_1_t dec; + + logic single_error; + + // Syndrome calculation + syndrome_o[0] = ^(in & 4'h3); + syndrome_o[1] = ^(in & 4'h5); + syndrome_o[2] = ^(in & 4'h9); + + // Corrected output calculation + d_o[0] = (syndrome_o == 3'h7) ^ in[0]; + + // err_o calc. bit0: single error, bit1: double error + single_error = ^syndrome_o; + err_o[0] = single_error; + err_o[1] = ~single_error & (|syndrome_o); + + dec.data = d_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [7:0] prim_secded_8_4_enc (logic [3:0] in); + logic [7:0] out; + out[3:0] = in; + out[4] = ^(in & 4'h7); + out[5] = ^(in & 4'hB); + out[6] = ^(in & 4'hD); + out[7] = ^(in & 4'hE); + return out; + endfunction + + function automatic secded_8_4_t prim_secded_8_4_dec (logic [7:0] in); + logic [3:0] d_o; + logic [3:0] syndrome_o; + logic [1:0] err_o; + + secded_8_4_t dec; + + logic single_error; + + // Syndrome calculation + syndrome_o[0] = ^(in & 8'h17); + syndrome_o[1] = ^(in & 8'h2B); + syndrome_o[2] = ^(in & 8'h4D); + syndrome_o[3] = ^(in & 8'h8E); + + // Corrected output calculation + d_o[0] = (syndrome_o == 4'h7) ^ in[0]; + d_o[1] = (syndrome_o == 4'hb) ^ in[1]; + d_o[2] = (syndrome_o == 4'hd) ^ in[2]; + d_o[3] = (syndrome_o == 4'he) ^ in[3]; + + // err_o calc. bit0: single error, bit1: double error + single_error = ^syndrome_o; + err_o[0] = single_error; + err_o[1] = ~single_error & (|syndrome_o); + + dec.data = d_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + function automatic logic [12:0] prim_secded_13_8_enc (logic [7:0] in); logic [12:0] out; - out = 13'(in); - out[8] = ^(out & 13'h006B); - out[9] = ^(out & 13'h00F8); - out[10] = ^(out & 13'h00D5); - out[11] = ^(out & 13'h00A7); - out[12] = ^(out & 13'h001E); + out[7:0] = in; + out[8] = ^(in & 8'h6B); + out[9] = ^(in & 8'hF8); + out[10] = ^(in & 8'hD5); + out[11] = ^(in & 8'hA7); + out[12] = ^(in & 8'h1E); return out; endfunction @@ -110,15 +233,67 @@ package prim_secded_pkg; endfunction + function automatic logic [15:0] prim_secded_16_11_enc (logic [10:0] in); + logic [15:0] out; + out[10:0] = in; + out[11] = ^(in & 11'h43F); + out[12] = ^(in & 11'h5C7); + out[13] = ^(in & 11'h6D9); + out[14] = ^(in & 11'h76A); + out[15] = ^(in & 11'h7B4); + return out; + endfunction + + function automatic secded_16_11_t prim_secded_16_11_dec (logic [15:0] in); + logic [10:0] d_o; + logic [4:0] syndrome_o; + logic [1:0] err_o; + + secded_16_11_t dec; + + logic single_error; + + // Syndrome calculation + syndrome_o[0] = ^(in & 16'h0C3F); + syndrome_o[1] = ^(in & 16'h15C7); + syndrome_o[2] = ^(in & 16'h26D9); + syndrome_o[3] = ^(in & 16'h476A); + syndrome_o[4] = ^(in & 16'h87B4); + + // Corrected output calculation + d_o[0] = (syndrome_o == 5'h7) ^ in[0]; + d_o[1] = (syndrome_o == 5'hb) ^ in[1]; + d_o[2] = (syndrome_o == 5'h13) ^ in[2]; + d_o[3] = (syndrome_o == 5'hd) ^ in[3]; + d_o[4] = (syndrome_o == 5'h15) ^ in[4]; + d_o[5] = (syndrome_o == 5'h19) ^ in[5]; + d_o[6] = (syndrome_o == 5'he) ^ in[6]; + d_o[7] = (syndrome_o == 5'h16) ^ in[7]; + d_o[8] = (syndrome_o == 5'h1a) ^ in[8]; + d_o[9] = (syndrome_o == 5'h1c) ^ in[9]; + d_o[10] = (syndrome_o == 5'h1f) ^ in[10]; + + // err_o calc. bit0: single error, bit1: double error + single_error = ^syndrome_o; + err_o[0] = single_error; + err_o[1] = ~single_error & (|syndrome_o); + + dec.data = d_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + function automatic logic [21:0] prim_secded_22_16_enc (logic [15:0] in); logic [21:0] out; - out = 22'(in); - out[16] = ^(out & 22'h007B48); - out[17] = ^(out & 22'h0091AB); - out[18] = ^(out & 22'h000E3D); - out[19] = ^(out & 22'h007692); - out[20] = ^(out & 22'h00A547); - out[21] = ^(out & 22'h00C8F4); + out[15:0] = in; + out[16] = ^(in & 16'h7B48); + out[17] = ^(in & 16'h91AB); + out[18] = ^(in & 16'h0E3D); + out[19] = ^(in & 16'h7692); + out[20] = ^(in & 16'hA547); + out[21] = ^(in & 16'hC8F4); return out; endfunction @@ -171,13 +346,13 @@ package prim_secded_pkg; function automatic logic [27:0] prim_secded_28_22_enc (logic [21:0] in); logic [27:0] out; - out = 28'(in); - out[22] = ^(out & 28'h03003FF); - out[23] = ^(out & 28'h020FC0F); - out[24] = ^(out & 28'h0171C71); - out[25] = ^(out & 28'h03B6592); - out[26] = ^(out & 28'h03DAAA4); - out[27] = ^(out & 28'h03ED348); + out[21:0] = in; + out[22] = ^(in & 22'h3003FF); + out[23] = ^(in & 22'h20FC0F); + out[24] = ^(in & 22'h171C71); + out[25] = ^(in & 22'h3B6592); + out[26] = ^(in & 22'h3DAAA4); + out[27] = ^(in & 22'h3ED348); return out; endfunction @@ -234,16 +409,85 @@ package prim_secded_pkg; endfunction + function automatic logic [31:0] prim_secded_32_26_enc (logic [25:0] in); + logic [31:0] out; + out[25:0] = in; + out[26] = ^(in & 26'h1F003FF); + out[27] = ^(in & 26'h2F0FC0F); + out[28] = ^(in & 26'h3771C71); + out[29] = ^(in & 26'h3BB6592); + out[30] = ^(in & 26'h3DDAAA4); + out[31] = ^(in & 26'h3EED348); + return out; + endfunction + + function automatic secded_32_26_t prim_secded_32_26_dec (logic [31:0] in); + logic [25:0] d_o; + logic [5:0] syndrome_o; + logic [1:0] err_o; + + secded_32_26_t dec; + + logic single_error; + + // Syndrome calculation + syndrome_o[0] = ^(in & 32'h05F003FF); + syndrome_o[1] = ^(in & 32'h0AF0FC0F); + syndrome_o[2] = ^(in & 32'h13771C71); + syndrome_o[3] = ^(in & 32'h23BB6592); + syndrome_o[4] = ^(in & 32'h43DDAAA4); + syndrome_o[5] = ^(in & 32'h83EED348); + + // Corrected output calculation + d_o[0] = (syndrome_o == 6'h7) ^ in[0]; + d_o[1] = (syndrome_o == 6'hb) ^ in[1]; + d_o[2] = (syndrome_o == 6'h13) ^ in[2]; + d_o[3] = (syndrome_o == 6'h23) ^ in[3]; + d_o[4] = (syndrome_o == 6'hd) ^ in[4]; + d_o[5] = (syndrome_o == 6'h15) ^ in[5]; + d_o[6] = (syndrome_o == 6'h25) ^ in[6]; + d_o[7] = (syndrome_o == 6'h19) ^ in[7]; + d_o[8] = (syndrome_o == 6'h29) ^ in[8]; + d_o[9] = (syndrome_o == 6'h31) ^ in[9]; + d_o[10] = (syndrome_o == 6'he) ^ in[10]; + d_o[11] = (syndrome_o == 6'h16) ^ in[11]; + d_o[12] = (syndrome_o == 6'h26) ^ in[12]; + d_o[13] = (syndrome_o == 6'h1a) ^ in[13]; + d_o[14] = (syndrome_o == 6'h2a) ^ in[14]; + d_o[15] = (syndrome_o == 6'h32) ^ in[15]; + d_o[16] = (syndrome_o == 6'h1c) ^ in[16]; + d_o[17] = (syndrome_o == 6'h2c) ^ in[17]; + d_o[18] = (syndrome_o == 6'h34) ^ in[18]; + d_o[19] = (syndrome_o == 6'h38) ^ in[19]; + d_o[20] = (syndrome_o == 6'h1f) ^ in[20]; + d_o[21] = (syndrome_o == 6'h2f) ^ in[21]; + d_o[22] = (syndrome_o == 6'h37) ^ in[22]; + d_o[23] = (syndrome_o == 6'h3b) ^ in[23]; + d_o[24] = (syndrome_o == 6'h3d) ^ in[24]; + d_o[25] = (syndrome_o == 6'h3e) ^ in[25]; + + // err_o calc. bit0: single error, bit1: double error + single_error = ^syndrome_o; + err_o[0] = single_error; + err_o[1] = ~single_error & (|syndrome_o); + + dec.data = d_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + function automatic logic [38:0] prim_secded_39_32_enc (logic [31:0] in); logic [38:0] out; - out = 39'(in); - out[32] = ^(out & 39'h003800CDBC); - out[33] = ^(out & 39'h00C439C325); - out[34] = ^(out & 39'h0052D82C63); - out[35] = ^(out & 39'h00A4363856); - out[36] = ^(out & 39'h009B833109); - out[37] = ^(out & 39'h002DCF42C0); - out[38] = ^(out & 39'h004364969A); + out[31:0] = in; + out[32] = ^(in & 32'h3800CDBC); + out[33] = ^(in & 32'hC439C325); + out[34] = ^(in & 32'h52D82C63); + out[35] = ^(in & 32'hA4363856); + out[36] = ^(in & 32'h9B833109); + out[37] = ^(in & 32'h2DCF42C0); + out[38] = ^(in & 32'h4364969A); return out; endfunction @@ -313,14 +557,14 @@ package prim_secded_pkg; function automatic logic [63:0] prim_secded_64_57_enc (logic [56:0] in); logic [63:0] out; - out = 64'(in); - out[57] = ^(out & 64'h0103FFF800007FFF); - out[58] = ^(out & 64'h017C1FF801FF801F); - out[59] = ^(out & 64'h01BDE1F87E0781E1); - out[60] = ^(out & 64'h01DEEE3B8E388E22); - out[61] = ^(out & 64'h01EF76CDB2C93244); - out[62] = ^(out & 64'h01F7BB56D5525488); - out[63] = ^(out & 64'h01FBDDA769A46910); + out[56:0] = in; + out[57] = ^(in & 57'h103FFF800007FFF); + out[58] = ^(in & 57'h17C1FF801FF801F); + out[59] = ^(in & 57'h1BDE1F87E0781E1); + out[60] = ^(in & 57'h1DEEE3B8E388E22); + out[61] = ^(in & 57'h1EF76CDB2C93244); + out[62] = ^(in & 57'h1F7BB56D5525488); + out[63] = ^(in & 57'h1FBDDA769A46910); return out; endfunction @@ -415,15 +659,15 @@ package prim_secded_pkg; function automatic logic [71:0] prim_secded_72_64_enc (logic [63:0] in); logic [71:0] out; - out = 72'(in); - out[64] = ^(out & 72'h00F8000000001FFFFF); - out[65] = ^(out & 72'h009D00000FFFE0003F); - out[66] = ^(out & 72'h008F003FF003E007C1); - out[67] = ^(out & 72'h00F10FC0F03C207842); - out[68] = ^(out & 72'h006E71C711C4438884); - out[69] = ^(out & 72'h003EB65926488C9108); - out[70] = ^(out & 72'h00D3DAAA4A91152210); - out[71] = ^(out & 72'h0067ED348D221A4420); + out[63:0] = in; + out[64] = ^(in & 64'hF8000000001FFFFF); + out[65] = ^(in & 64'h9D00000FFFE0003F); + out[66] = ^(in & 64'h8F003FF003E007C1); + out[67] = ^(in & 64'hF10FC0F03C207842); + out[68] = ^(in & 64'h6E71C711C4438884); + out[69] = ^(in & 64'h3EB65926488C9108); + out[70] = ^(in & 64'hD3DAAA4A91152210); + out[71] = ^(in & 64'h67ED348D221A4420); return out; endfunction @@ -524,15 +768,1031 @@ package prim_secded_pkg; endfunction + function automatic logic [127:0] prim_secded_128_120_enc (logic [119:0] in); + logic [127:0] out; + out[119:0] = in; + out[120] = ^(in & 120'h7F000007FFFFFFFF000000001FFFFF); + out[121] = ^(in & 120'hBF03FFF8000FFFFF00000FFFE0003F); + out[122] = ^(in & 120'hDF7C1FF83FF003FF003FF003E007C1); + out[123] = ^(in & 120'hEFBDE1FBC3F0FC0F0FC0F03C207842); + out[124] = ^(in & 120'hF7DEEE3DDC771C7171C711C4438884); + out[125] = ^(in & 120'hFBEF76CEED9B6592B65926488C9108); + out[126] = ^(in & 120'hFDF7BB5776ADAAA4DAAA4A91152210); + out[127] = ^(in & 120'hFEFBDDA7BB4ED348ED348D221A4420); + return out; + endfunction + + function automatic secded_128_120_t prim_secded_128_120_dec (logic [127:0] in); + logic [119:0] d_o; + logic [7:0] syndrome_o; + logic [1:0] err_o; + + secded_128_120_t dec; + + logic single_error; + + // Syndrome calculation + syndrome_o[0] = ^(in & 128'h017F000007FFFFFFFF000000001FFFFF); + syndrome_o[1] = ^(in & 128'h02BF03FFF8000FFFFF00000FFFE0003F); + syndrome_o[2] = ^(in & 128'h04DF7C1FF83FF003FF003FF003E007C1); + syndrome_o[3] = ^(in & 128'h08EFBDE1FBC3F0FC0F0FC0F03C207842); + syndrome_o[4] = ^(in & 128'h10F7DEEE3DDC771C7171C711C4438884); + syndrome_o[5] = ^(in & 128'h20FBEF76CEED9B6592B65926488C9108); + syndrome_o[6] = ^(in & 128'h40FDF7BB5776ADAAA4DAAA4A91152210); + syndrome_o[7] = ^(in & 128'h80FEFBDDA7BB4ED348ED348D221A4420); + + // Corrected output calculation + d_o[0] = (syndrome_o == 8'h7) ^ in[0]; + d_o[1] = (syndrome_o == 8'hb) ^ in[1]; + d_o[2] = (syndrome_o == 8'h13) ^ in[2]; + d_o[3] = (syndrome_o == 8'h23) ^ in[3]; + d_o[4] = (syndrome_o == 8'h43) ^ in[4]; + d_o[5] = (syndrome_o == 8'h83) ^ in[5]; + d_o[6] = (syndrome_o == 8'hd) ^ in[6]; + d_o[7] = (syndrome_o == 8'h15) ^ in[7]; + d_o[8] = (syndrome_o == 8'h25) ^ in[8]; + d_o[9] = (syndrome_o == 8'h45) ^ in[9]; + d_o[10] = (syndrome_o == 8'h85) ^ in[10]; + d_o[11] = (syndrome_o == 8'h19) ^ in[11]; + d_o[12] = (syndrome_o == 8'h29) ^ in[12]; + d_o[13] = (syndrome_o == 8'h49) ^ in[13]; + d_o[14] = (syndrome_o == 8'h89) ^ in[14]; + d_o[15] = (syndrome_o == 8'h31) ^ in[15]; + d_o[16] = (syndrome_o == 8'h51) ^ in[16]; + d_o[17] = (syndrome_o == 8'h91) ^ in[17]; + d_o[18] = (syndrome_o == 8'h61) ^ in[18]; + d_o[19] = (syndrome_o == 8'ha1) ^ in[19]; + d_o[20] = (syndrome_o == 8'hc1) ^ in[20]; + d_o[21] = (syndrome_o == 8'he) ^ in[21]; + d_o[22] = (syndrome_o == 8'h16) ^ in[22]; + d_o[23] = (syndrome_o == 8'h26) ^ in[23]; + d_o[24] = (syndrome_o == 8'h46) ^ in[24]; + d_o[25] = (syndrome_o == 8'h86) ^ in[25]; + d_o[26] = (syndrome_o == 8'h1a) ^ in[26]; + d_o[27] = (syndrome_o == 8'h2a) ^ in[27]; + d_o[28] = (syndrome_o == 8'h4a) ^ in[28]; + d_o[29] = (syndrome_o == 8'h8a) ^ in[29]; + d_o[30] = (syndrome_o == 8'h32) ^ in[30]; + d_o[31] = (syndrome_o == 8'h52) ^ in[31]; + d_o[32] = (syndrome_o == 8'h92) ^ in[32]; + d_o[33] = (syndrome_o == 8'h62) ^ in[33]; + d_o[34] = (syndrome_o == 8'ha2) ^ in[34]; + d_o[35] = (syndrome_o == 8'hc2) ^ in[35]; + d_o[36] = (syndrome_o == 8'h1c) ^ in[36]; + d_o[37] = (syndrome_o == 8'h2c) ^ in[37]; + d_o[38] = (syndrome_o == 8'h4c) ^ in[38]; + d_o[39] = (syndrome_o == 8'h8c) ^ in[39]; + d_o[40] = (syndrome_o == 8'h34) ^ in[40]; + d_o[41] = (syndrome_o == 8'h54) ^ in[41]; + d_o[42] = (syndrome_o == 8'h94) ^ in[42]; + d_o[43] = (syndrome_o == 8'h64) ^ in[43]; + d_o[44] = (syndrome_o == 8'ha4) ^ in[44]; + d_o[45] = (syndrome_o == 8'hc4) ^ in[45]; + d_o[46] = (syndrome_o == 8'h38) ^ in[46]; + d_o[47] = (syndrome_o == 8'h58) ^ in[47]; + d_o[48] = (syndrome_o == 8'h98) ^ in[48]; + d_o[49] = (syndrome_o == 8'h68) ^ in[49]; + d_o[50] = (syndrome_o == 8'ha8) ^ in[50]; + d_o[51] = (syndrome_o == 8'hc8) ^ in[51]; + d_o[52] = (syndrome_o == 8'h70) ^ in[52]; + d_o[53] = (syndrome_o == 8'hb0) ^ in[53]; + d_o[54] = (syndrome_o == 8'hd0) ^ in[54]; + d_o[55] = (syndrome_o == 8'he0) ^ in[55]; + d_o[56] = (syndrome_o == 8'h1f) ^ in[56]; + d_o[57] = (syndrome_o == 8'h2f) ^ in[57]; + d_o[58] = (syndrome_o == 8'h4f) ^ in[58]; + d_o[59] = (syndrome_o == 8'h8f) ^ in[59]; + d_o[60] = (syndrome_o == 8'h37) ^ in[60]; + d_o[61] = (syndrome_o == 8'h57) ^ in[61]; + d_o[62] = (syndrome_o == 8'h97) ^ in[62]; + d_o[63] = (syndrome_o == 8'h67) ^ in[63]; + d_o[64] = (syndrome_o == 8'ha7) ^ in[64]; + d_o[65] = (syndrome_o == 8'hc7) ^ in[65]; + d_o[66] = (syndrome_o == 8'h3b) ^ in[66]; + d_o[67] = (syndrome_o == 8'h5b) ^ in[67]; + d_o[68] = (syndrome_o == 8'h9b) ^ in[68]; + d_o[69] = (syndrome_o == 8'h6b) ^ in[69]; + d_o[70] = (syndrome_o == 8'hab) ^ in[70]; + d_o[71] = (syndrome_o == 8'hcb) ^ in[71]; + d_o[72] = (syndrome_o == 8'h73) ^ in[72]; + d_o[73] = (syndrome_o == 8'hb3) ^ in[73]; + d_o[74] = (syndrome_o == 8'hd3) ^ in[74]; + d_o[75] = (syndrome_o == 8'he3) ^ in[75]; + d_o[76] = (syndrome_o == 8'h3d) ^ in[76]; + d_o[77] = (syndrome_o == 8'h5d) ^ in[77]; + d_o[78] = (syndrome_o == 8'h9d) ^ in[78]; + d_o[79] = (syndrome_o == 8'h6d) ^ in[79]; + d_o[80] = (syndrome_o == 8'had) ^ in[80]; + d_o[81] = (syndrome_o == 8'hcd) ^ in[81]; + d_o[82] = (syndrome_o == 8'h75) ^ in[82]; + d_o[83] = (syndrome_o == 8'hb5) ^ in[83]; + d_o[84] = (syndrome_o == 8'hd5) ^ in[84]; + d_o[85] = (syndrome_o == 8'he5) ^ in[85]; + d_o[86] = (syndrome_o == 8'h79) ^ in[86]; + d_o[87] = (syndrome_o == 8'hb9) ^ in[87]; + d_o[88] = (syndrome_o == 8'hd9) ^ in[88]; + d_o[89] = (syndrome_o == 8'he9) ^ in[89]; + d_o[90] = (syndrome_o == 8'hf1) ^ in[90]; + d_o[91] = (syndrome_o == 8'h3e) ^ in[91]; + d_o[92] = (syndrome_o == 8'h5e) ^ in[92]; + d_o[93] = (syndrome_o == 8'h9e) ^ in[93]; + d_o[94] = (syndrome_o == 8'h6e) ^ in[94]; + d_o[95] = (syndrome_o == 8'hae) ^ in[95]; + d_o[96] = (syndrome_o == 8'hce) ^ in[96]; + d_o[97] = (syndrome_o == 8'h76) ^ in[97]; + d_o[98] = (syndrome_o == 8'hb6) ^ in[98]; + d_o[99] = (syndrome_o == 8'hd6) ^ in[99]; + d_o[100] = (syndrome_o == 8'he6) ^ in[100]; + d_o[101] = (syndrome_o == 8'h7a) ^ in[101]; + d_o[102] = (syndrome_o == 8'hba) ^ in[102]; + d_o[103] = (syndrome_o == 8'hda) ^ in[103]; + d_o[104] = (syndrome_o == 8'hea) ^ in[104]; + d_o[105] = (syndrome_o == 8'hf2) ^ in[105]; + d_o[106] = (syndrome_o == 8'h7c) ^ in[106]; + d_o[107] = (syndrome_o == 8'hbc) ^ in[107]; + d_o[108] = (syndrome_o == 8'hdc) ^ in[108]; + d_o[109] = (syndrome_o == 8'hec) ^ in[109]; + d_o[110] = (syndrome_o == 8'hf4) ^ in[110]; + d_o[111] = (syndrome_o == 8'hf8) ^ in[111]; + d_o[112] = (syndrome_o == 8'h7f) ^ in[112]; + d_o[113] = (syndrome_o == 8'hbf) ^ in[113]; + d_o[114] = (syndrome_o == 8'hdf) ^ in[114]; + d_o[115] = (syndrome_o == 8'hef) ^ in[115]; + d_o[116] = (syndrome_o == 8'hf7) ^ in[116]; + d_o[117] = (syndrome_o == 8'hfb) ^ in[117]; + d_o[118] = (syndrome_o == 8'hfd) ^ in[118]; + d_o[119] = (syndrome_o == 8'hfe) ^ in[119]; + + // err_o calc. bit0: single error, bit1: double error + single_error = ^syndrome_o; + err_o[0] = single_error; + err_o[1] = ~single_error & (|syndrome_o); + + dec.data = d_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [255:0] prim_secded_256_247_enc (logic [246:0] in); + logic [255:0] out; + out[246:0] = in; + out[247] = ^(in & 247'h403FFFFFFC00000000000003FFFFFFFFFFFFFFFFF00000000000000FFFFFFF); + out[248] = ^(in & 247'h5FC07FFFFC00001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000007F); + out[249] = ^(in & 247'h6FDF81FFFC0FFFE0003FFFFC0007FFFF800007FFF00000FFFE0003F0001F81); + out[250] = ^(in & 247'h77EFBE0FFDF07FE0FFC00FFC1FF801FF801FF801F003FF003E007C1003E082); + out[251] = ^(in & 247'h7BF7DEF0FEF787EF0FC3F03DE1F87E0787E0781E10FC0F03C20784203C2104); + out[252] = ^(in & 247'h7DFBEF771F7BB8F771DC71C6EE3B8E38B8E388E2271C711C44388841C44208); + out[253] = ^(in & 247'h7EFDF7BB67BDDB3BB66D964B76CDB2C95B2C93244B65926488C91086488410); + out[254] = ^(in & 247'h7F7EFBDDABDEED5DDAB6AA93BB56D5526D5525488DAAA4A91152210A910820); + out[255] = ^(in & 247'h7FBF7DEED3EF769EED3B4D23DDA769A4769A46910ED348D221A4420D221040); + return out; + endfunction + + function automatic secded_256_247_t prim_secded_256_247_dec (logic [255:0] in); + logic [246:0] d_o; + logic [8:0] syndrome_o; + logic [1:0] err_o; + + secded_256_247_t dec; + + logic single_error; + + // Syndrome calculation + syndrome_o[0] = ^(in & 256'h00C03FFFFFFC00000000000003FFFFFFFFFFFFFFFFF00000000000000FFFFFFF); + syndrome_o[1] = ^(in & 256'h015FC07FFFFC00001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000007F); + syndrome_o[2] = ^(in & 256'h026FDF81FFFC0FFFE0003FFFFC0007FFFF800007FFF00000FFFE0003F0001F81); + syndrome_o[3] = ^(in & 256'h0477EFBE0FFDF07FE0FFC00FFC1FF801FF801FF801F003FF003E007C1003E082); + syndrome_o[4] = ^(in & 256'h087BF7DEF0FEF787EF0FC3F03DE1F87E0787E0781E10FC0F03C20784203C2104); + syndrome_o[5] = ^(in & 256'h107DFBEF771F7BB8F771DC71C6EE3B8E38B8E388E2271C711C44388841C44208); + syndrome_o[6] = ^(in & 256'h207EFDF7BB67BDDB3BB66D964B76CDB2C95B2C93244B65926488C91086488410); + syndrome_o[7] = ^(in & 256'h407F7EFBDDABDEED5DDAB6AA93BB56D5526D5525488DAAA4A91152210A910820); + syndrome_o[8] = ^(in & 256'h807FBF7DEED3EF769EED3B4D23DDA769A4769A46910ED348D221A4420D221040); + + // Corrected output calculation + d_o[0] = (syndrome_o == 9'h7) ^ in[0]; + d_o[1] = (syndrome_o == 9'hb) ^ in[1]; + d_o[2] = (syndrome_o == 9'h13) ^ in[2]; + d_o[3] = (syndrome_o == 9'h23) ^ in[3]; + d_o[4] = (syndrome_o == 9'h43) ^ in[4]; + d_o[5] = (syndrome_o == 9'h83) ^ in[5]; + d_o[6] = (syndrome_o == 9'h103) ^ in[6]; + d_o[7] = (syndrome_o == 9'hd) ^ in[7]; + d_o[8] = (syndrome_o == 9'h15) ^ in[8]; + d_o[9] = (syndrome_o == 9'h25) ^ in[9]; + d_o[10] = (syndrome_o == 9'h45) ^ in[10]; + d_o[11] = (syndrome_o == 9'h85) ^ in[11]; + d_o[12] = (syndrome_o == 9'h105) ^ in[12]; + d_o[13] = (syndrome_o == 9'h19) ^ in[13]; + d_o[14] = (syndrome_o == 9'h29) ^ in[14]; + d_o[15] = (syndrome_o == 9'h49) ^ in[15]; + d_o[16] = (syndrome_o == 9'h89) ^ in[16]; + d_o[17] = (syndrome_o == 9'h109) ^ in[17]; + d_o[18] = (syndrome_o == 9'h31) ^ in[18]; + d_o[19] = (syndrome_o == 9'h51) ^ in[19]; + d_o[20] = (syndrome_o == 9'h91) ^ in[20]; + d_o[21] = (syndrome_o == 9'h111) ^ in[21]; + d_o[22] = (syndrome_o == 9'h61) ^ in[22]; + d_o[23] = (syndrome_o == 9'ha1) ^ in[23]; + d_o[24] = (syndrome_o == 9'h121) ^ in[24]; + d_o[25] = (syndrome_o == 9'hc1) ^ in[25]; + d_o[26] = (syndrome_o == 9'h141) ^ in[26]; + d_o[27] = (syndrome_o == 9'h181) ^ in[27]; + d_o[28] = (syndrome_o == 9'he) ^ in[28]; + d_o[29] = (syndrome_o == 9'h16) ^ in[29]; + d_o[30] = (syndrome_o == 9'h26) ^ in[30]; + d_o[31] = (syndrome_o == 9'h46) ^ in[31]; + d_o[32] = (syndrome_o == 9'h86) ^ in[32]; + d_o[33] = (syndrome_o == 9'h106) ^ in[33]; + d_o[34] = (syndrome_o == 9'h1a) ^ in[34]; + d_o[35] = (syndrome_o == 9'h2a) ^ in[35]; + d_o[36] = (syndrome_o == 9'h4a) ^ in[36]; + d_o[37] = (syndrome_o == 9'h8a) ^ in[37]; + d_o[38] = (syndrome_o == 9'h10a) ^ in[38]; + d_o[39] = (syndrome_o == 9'h32) ^ in[39]; + d_o[40] = (syndrome_o == 9'h52) ^ in[40]; + d_o[41] = (syndrome_o == 9'h92) ^ in[41]; + d_o[42] = (syndrome_o == 9'h112) ^ in[42]; + d_o[43] = (syndrome_o == 9'h62) ^ in[43]; + d_o[44] = (syndrome_o == 9'ha2) ^ in[44]; + d_o[45] = (syndrome_o == 9'h122) ^ in[45]; + d_o[46] = (syndrome_o == 9'hc2) ^ in[46]; + d_o[47] = (syndrome_o == 9'h142) ^ in[47]; + d_o[48] = (syndrome_o == 9'h182) ^ in[48]; + d_o[49] = (syndrome_o == 9'h1c) ^ in[49]; + d_o[50] = (syndrome_o == 9'h2c) ^ in[50]; + d_o[51] = (syndrome_o == 9'h4c) ^ in[51]; + d_o[52] = (syndrome_o == 9'h8c) ^ in[52]; + d_o[53] = (syndrome_o == 9'h10c) ^ in[53]; + d_o[54] = (syndrome_o == 9'h34) ^ in[54]; + d_o[55] = (syndrome_o == 9'h54) ^ in[55]; + d_o[56] = (syndrome_o == 9'h94) ^ in[56]; + d_o[57] = (syndrome_o == 9'h114) ^ in[57]; + d_o[58] = (syndrome_o == 9'h64) ^ in[58]; + d_o[59] = (syndrome_o == 9'ha4) ^ in[59]; + d_o[60] = (syndrome_o == 9'h124) ^ in[60]; + d_o[61] = (syndrome_o == 9'hc4) ^ in[61]; + d_o[62] = (syndrome_o == 9'h144) ^ in[62]; + d_o[63] = (syndrome_o == 9'h184) ^ in[63]; + d_o[64] = (syndrome_o == 9'h38) ^ in[64]; + d_o[65] = (syndrome_o == 9'h58) ^ in[65]; + d_o[66] = (syndrome_o == 9'h98) ^ in[66]; + d_o[67] = (syndrome_o == 9'h118) ^ in[67]; + d_o[68] = (syndrome_o == 9'h68) ^ in[68]; + d_o[69] = (syndrome_o == 9'ha8) ^ in[69]; + d_o[70] = (syndrome_o == 9'h128) ^ in[70]; + d_o[71] = (syndrome_o == 9'hc8) ^ in[71]; + d_o[72] = (syndrome_o == 9'h148) ^ in[72]; + d_o[73] = (syndrome_o == 9'h188) ^ in[73]; + d_o[74] = (syndrome_o == 9'h70) ^ in[74]; + d_o[75] = (syndrome_o == 9'hb0) ^ in[75]; + d_o[76] = (syndrome_o == 9'h130) ^ in[76]; + d_o[77] = (syndrome_o == 9'hd0) ^ in[77]; + d_o[78] = (syndrome_o == 9'h150) ^ in[78]; + d_o[79] = (syndrome_o == 9'h190) ^ in[79]; + d_o[80] = (syndrome_o == 9'he0) ^ in[80]; + d_o[81] = (syndrome_o == 9'h160) ^ in[81]; + d_o[82] = (syndrome_o == 9'h1a0) ^ in[82]; + d_o[83] = (syndrome_o == 9'h1c0) ^ in[83]; + d_o[84] = (syndrome_o == 9'h1f) ^ in[84]; + d_o[85] = (syndrome_o == 9'h2f) ^ in[85]; + d_o[86] = (syndrome_o == 9'h4f) ^ in[86]; + d_o[87] = (syndrome_o == 9'h8f) ^ in[87]; + d_o[88] = (syndrome_o == 9'h10f) ^ in[88]; + d_o[89] = (syndrome_o == 9'h37) ^ in[89]; + d_o[90] = (syndrome_o == 9'h57) ^ in[90]; + d_o[91] = (syndrome_o == 9'h97) ^ in[91]; + d_o[92] = (syndrome_o == 9'h117) ^ in[92]; + d_o[93] = (syndrome_o == 9'h67) ^ in[93]; + d_o[94] = (syndrome_o == 9'ha7) ^ in[94]; + d_o[95] = (syndrome_o == 9'h127) ^ in[95]; + d_o[96] = (syndrome_o == 9'hc7) ^ in[96]; + d_o[97] = (syndrome_o == 9'h147) ^ in[97]; + d_o[98] = (syndrome_o == 9'h187) ^ in[98]; + d_o[99] = (syndrome_o == 9'h3b) ^ in[99]; + d_o[100] = (syndrome_o == 9'h5b) ^ in[100]; + d_o[101] = (syndrome_o == 9'h9b) ^ in[101]; + d_o[102] = (syndrome_o == 9'h11b) ^ in[102]; + d_o[103] = (syndrome_o == 9'h6b) ^ in[103]; + d_o[104] = (syndrome_o == 9'hab) ^ in[104]; + d_o[105] = (syndrome_o == 9'h12b) ^ in[105]; + d_o[106] = (syndrome_o == 9'hcb) ^ in[106]; + d_o[107] = (syndrome_o == 9'h14b) ^ in[107]; + d_o[108] = (syndrome_o == 9'h18b) ^ in[108]; + d_o[109] = (syndrome_o == 9'h73) ^ in[109]; + d_o[110] = (syndrome_o == 9'hb3) ^ in[110]; + d_o[111] = (syndrome_o == 9'h133) ^ in[111]; + d_o[112] = (syndrome_o == 9'hd3) ^ in[112]; + d_o[113] = (syndrome_o == 9'h153) ^ in[113]; + d_o[114] = (syndrome_o == 9'h193) ^ in[114]; + d_o[115] = (syndrome_o == 9'he3) ^ in[115]; + d_o[116] = (syndrome_o == 9'h163) ^ in[116]; + d_o[117] = (syndrome_o == 9'h1a3) ^ in[117]; + d_o[118] = (syndrome_o == 9'h1c3) ^ in[118]; + d_o[119] = (syndrome_o == 9'h3d) ^ in[119]; + d_o[120] = (syndrome_o == 9'h5d) ^ in[120]; + d_o[121] = (syndrome_o == 9'h9d) ^ in[121]; + d_o[122] = (syndrome_o == 9'h11d) ^ in[122]; + d_o[123] = (syndrome_o == 9'h6d) ^ in[123]; + d_o[124] = (syndrome_o == 9'had) ^ in[124]; + d_o[125] = (syndrome_o == 9'h12d) ^ in[125]; + d_o[126] = (syndrome_o == 9'hcd) ^ in[126]; + d_o[127] = (syndrome_o == 9'h14d) ^ in[127]; + d_o[128] = (syndrome_o == 9'h18d) ^ in[128]; + d_o[129] = (syndrome_o == 9'h75) ^ in[129]; + d_o[130] = (syndrome_o == 9'hb5) ^ in[130]; + d_o[131] = (syndrome_o == 9'h135) ^ in[131]; + d_o[132] = (syndrome_o == 9'hd5) ^ in[132]; + d_o[133] = (syndrome_o == 9'h155) ^ in[133]; + d_o[134] = (syndrome_o == 9'h195) ^ in[134]; + d_o[135] = (syndrome_o == 9'he5) ^ in[135]; + d_o[136] = (syndrome_o == 9'h165) ^ in[136]; + d_o[137] = (syndrome_o == 9'h1a5) ^ in[137]; + d_o[138] = (syndrome_o == 9'h1c5) ^ in[138]; + d_o[139] = (syndrome_o == 9'h79) ^ in[139]; + d_o[140] = (syndrome_o == 9'hb9) ^ in[140]; + d_o[141] = (syndrome_o == 9'h139) ^ in[141]; + d_o[142] = (syndrome_o == 9'hd9) ^ in[142]; + d_o[143] = (syndrome_o == 9'h159) ^ in[143]; + d_o[144] = (syndrome_o == 9'h199) ^ in[144]; + d_o[145] = (syndrome_o == 9'he9) ^ in[145]; + d_o[146] = (syndrome_o == 9'h169) ^ in[146]; + d_o[147] = (syndrome_o == 9'h1a9) ^ in[147]; + d_o[148] = (syndrome_o == 9'h1c9) ^ in[148]; + d_o[149] = (syndrome_o == 9'hf1) ^ in[149]; + d_o[150] = (syndrome_o == 9'h171) ^ in[150]; + d_o[151] = (syndrome_o == 9'h1b1) ^ in[151]; + d_o[152] = (syndrome_o == 9'h1d1) ^ in[152]; + d_o[153] = (syndrome_o == 9'h1e1) ^ in[153]; + d_o[154] = (syndrome_o == 9'h3e) ^ in[154]; + d_o[155] = (syndrome_o == 9'h5e) ^ in[155]; + d_o[156] = (syndrome_o == 9'h9e) ^ in[156]; + d_o[157] = (syndrome_o == 9'h11e) ^ in[157]; + d_o[158] = (syndrome_o == 9'h6e) ^ in[158]; + d_o[159] = (syndrome_o == 9'hae) ^ in[159]; + d_o[160] = (syndrome_o == 9'h12e) ^ in[160]; + d_o[161] = (syndrome_o == 9'hce) ^ in[161]; + d_o[162] = (syndrome_o == 9'h14e) ^ in[162]; + d_o[163] = (syndrome_o == 9'h18e) ^ in[163]; + d_o[164] = (syndrome_o == 9'h76) ^ in[164]; + d_o[165] = (syndrome_o == 9'hb6) ^ in[165]; + d_o[166] = (syndrome_o == 9'h136) ^ in[166]; + d_o[167] = (syndrome_o == 9'hd6) ^ in[167]; + d_o[168] = (syndrome_o == 9'h156) ^ in[168]; + d_o[169] = (syndrome_o == 9'h196) ^ in[169]; + d_o[170] = (syndrome_o == 9'he6) ^ in[170]; + d_o[171] = (syndrome_o == 9'h166) ^ in[171]; + d_o[172] = (syndrome_o == 9'h1a6) ^ in[172]; + d_o[173] = (syndrome_o == 9'h1c6) ^ in[173]; + d_o[174] = (syndrome_o == 9'h7a) ^ in[174]; + d_o[175] = (syndrome_o == 9'hba) ^ in[175]; + d_o[176] = (syndrome_o == 9'h13a) ^ in[176]; + d_o[177] = (syndrome_o == 9'hda) ^ in[177]; + d_o[178] = (syndrome_o == 9'h15a) ^ in[178]; + d_o[179] = (syndrome_o == 9'h19a) ^ in[179]; + d_o[180] = (syndrome_o == 9'hea) ^ in[180]; + d_o[181] = (syndrome_o == 9'h16a) ^ in[181]; + d_o[182] = (syndrome_o == 9'h1aa) ^ in[182]; + d_o[183] = (syndrome_o == 9'h1ca) ^ in[183]; + d_o[184] = (syndrome_o == 9'hf2) ^ in[184]; + d_o[185] = (syndrome_o == 9'h172) ^ in[185]; + d_o[186] = (syndrome_o == 9'h1b2) ^ in[186]; + d_o[187] = (syndrome_o == 9'h1d2) ^ in[187]; + d_o[188] = (syndrome_o == 9'h1e2) ^ in[188]; + d_o[189] = (syndrome_o == 9'h7c) ^ in[189]; + d_o[190] = (syndrome_o == 9'hbc) ^ in[190]; + d_o[191] = (syndrome_o == 9'h13c) ^ in[191]; + d_o[192] = (syndrome_o == 9'hdc) ^ in[192]; + d_o[193] = (syndrome_o == 9'h15c) ^ in[193]; + d_o[194] = (syndrome_o == 9'h19c) ^ in[194]; + d_o[195] = (syndrome_o == 9'hec) ^ in[195]; + d_o[196] = (syndrome_o == 9'h16c) ^ in[196]; + d_o[197] = (syndrome_o == 9'h1ac) ^ in[197]; + d_o[198] = (syndrome_o == 9'h1cc) ^ in[198]; + d_o[199] = (syndrome_o == 9'hf4) ^ in[199]; + d_o[200] = (syndrome_o == 9'h174) ^ in[200]; + d_o[201] = (syndrome_o == 9'h1b4) ^ in[201]; + d_o[202] = (syndrome_o == 9'h1d4) ^ in[202]; + d_o[203] = (syndrome_o == 9'h1e4) ^ in[203]; + d_o[204] = (syndrome_o == 9'hf8) ^ in[204]; + d_o[205] = (syndrome_o == 9'h178) ^ in[205]; + d_o[206] = (syndrome_o == 9'h1b8) ^ in[206]; + d_o[207] = (syndrome_o == 9'h1d8) ^ in[207]; + d_o[208] = (syndrome_o == 9'h1e8) ^ in[208]; + d_o[209] = (syndrome_o == 9'h1f0) ^ in[209]; + d_o[210] = (syndrome_o == 9'h7f) ^ in[210]; + d_o[211] = (syndrome_o == 9'hbf) ^ in[211]; + d_o[212] = (syndrome_o == 9'h13f) ^ in[212]; + d_o[213] = (syndrome_o == 9'hdf) ^ in[213]; + d_o[214] = (syndrome_o == 9'h15f) ^ in[214]; + d_o[215] = (syndrome_o == 9'h19f) ^ in[215]; + d_o[216] = (syndrome_o == 9'hef) ^ in[216]; + d_o[217] = (syndrome_o == 9'h16f) ^ in[217]; + d_o[218] = (syndrome_o == 9'h1af) ^ in[218]; + d_o[219] = (syndrome_o == 9'h1cf) ^ in[219]; + d_o[220] = (syndrome_o == 9'hf7) ^ in[220]; + d_o[221] = (syndrome_o == 9'h177) ^ in[221]; + d_o[222] = (syndrome_o == 9'h1b7) ^ in[222]; + d_o[223] = (syndrome_o == 9'h1d7) ^ in[223]; + d_o[224] = (syndrome_o == 9'h1e7) ^ in[224]; + d_o[225] = (syndrome_o == 9'hfb) ^ in[225]; + d_o[226] = (syndrome_o == 9'h17b) ^ in[226]; + d_o[227] = (syndrome_o == 9'h1bb) ^ in[227]; + d_o[228] = (syndrome_o == 9'h1db) ^ in[228]; + d_o[229] = (syndrome_o == 9'h1eb) ^ in[229]; + d_o[230] = (syndrome_o == 9'h1f3) ^ in[230]; + d_o[231] = (syndrome_o == 9'hfd) ^ in[231]; + d_o[232] = (syndrome_o == 9'h17d) ^ in[232]; + d_o[233] = (syndrome_o == 9'h1bd) ^ in[233]; + d_o[234] = (syndrome_o == 9'h1dd) ^ in[234]; + d_o[235] = (syndrome_o == 9'h1ed) ^ in[235]; + d_o[236] = (syndrome_o == 9'h1f5) ^ in[236]; + d_o[237] = (syndrome_o == 9'h1f9) ^ in[237]; + d_o[238] = (syndrome_o == 9'hfe) ^ in[238]; + d_o[239] = (syndrome_o == 9'h17e) ^ in[239]; + d_o[240] = (syndrome_o == 9'h1be) ^ in[240]; + d_o[241] = (syndrome_o == 9'h1de) ^ in[241]; + d_o[242] = (syndrome_o == 9'h1ee) ^ in[242]; + d_o[243] = (syndrome_o == 9'h1f6) ^ in[243]; + d_o[244] = (syndrome_o == 9'h1fa) ^ in[244]; + d_o[245] = (syndrome_o == 9'h1fc) ^ in[245]; + d_o[246] = (syndrome_o == 9'h1ff) ^ in[246]; + + // err_o calc. bit0: single error, bit1: double error + single_error = ^syndrome_o; + err_o[0] = single_error; + err_o[1] = ~single_error & (|syndrome_o); + + dec.data = d_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [511:0] prim_secded_512_502_enc (logic [501:0] in); + logic [511:0] out; + out[501:0] = in; + out[502] = ^(in & 502'h1FF000000000FFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000FFFFFFFFF); + out[503] = ^(in & 502'h2FF00FFFFFFF0000000FFFFFFFFFFFFFF00000000000000FFFFFFFFFFFFFFFFFC00000000000000000FFFFFFFFFFFFFF00000000000000FFFFFFF0000000FF); + out[504] = ^(in & 502'h37F7F01FFFFF01FFFFF000007FFFFFFFF000007FFFFFFFF000000001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000000001FFFFF000007F000007F01); + out[505] = ^(in & 502'h3BFBF7E07FFF7E07FFF03FFF8000FFFFF03FFF8000FFFFF0001FFFFE00001FFFC0007FFFF800007FFF00000FFFE0003F00000FFFE0003F0001F810001F8102); + out[506] = ^(in & 502'h3DFDFBEF83FFBEF83FF7C1FF83FF003FF7C1FF83FF003FF07FE007FE007FE007C1FF801FF801FF801F003FF003E007C1003FF003E007C1003E082003E08204); + out[507] = ^(in & 502'h3EFEFDF7BC3FDF7BC3FBDE1FBC3F0FC0FBDE1FBC3F0FC0F787E1F81E1F81E0785E1F87E0787E0781E10FC0F03C2078420FC0F03C20784203C210403C210408); + out[508] = ^(in & 502'h3F7F7EFBDDC7EFBDDC7DEEE3DDC771C71DEEE3DDC771C71BB8EE38E2E38E2388AEE3B8E38B8E388E2271C711C443888471C711C44388841C442081C4420810); + out[509] = ^(in & 502'h3FBFBF7DEED9F7DEED9EF76CEED9B6592EF76CEED9B6592DDB36CB256CB24C91376CDB2C95B2C93244B65926488C9108B65926488C91086488410648841020); + out[510] = ^(in & 502'h3FDFDFBEF76AFBEF76AF7BB5776ADAAA4F7BB5776ADAAA4EED5B5549B55495223BB56D5526D5525488DAAA4A91152210DAAA4A91152210A910820A91082040); + out[511] = ^(in & 502'h3FEFEFDF7BB4FDF7BB4FBDDA7BB4ED348FBDDA7BB4ED348F769DA691DA691A443DDA769A4769A46910ED348D221A4420ED348D221A4420D221040D22104080); + return out; + endfunction + + function automatic secded_512_502_t prim_secded_512_502_dec (logic [511:0] in); + logic [501:0] d_o; + logic [9:0] syndrome_o; + logic [1:0] err_o; + + secded_512_502_t dec; + + logic single_error; + + // Syndrome calculation + syndrome_o[0] = ^(in & 512'h005FF000000000FFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000FFFFFFFFF); + syndrome_o[1] = ^(in & 512'h00AFF00FFFFFFF0000000FFFFFFFFFFFFFF00000000000000FFFFFFFFFFFFFFFFFC00000000000000000FFFFFFFFFFFFFF00000000000000FFFFFFF0000000FF); + syndrome_o[2] = ^(in & 512'h0137F7F01FFFFF01FFFFF000007FFFFFFFF000007FFFFFFFF000000001FFFFFFFFC000000007FFFFFFFF000000001FFFFF000000001FFFFF000007F000007F01); + syndrome_o[3] = ^(in & 512'h023BFBF7E07FFF7E07FFF03FFF8000FFFFF03FFF8000FFFFF0001FFFFE00001FFFC0007FFFF800007FFF00000FFFE0003F00000FFFE0003F0001F810001F8102); + syndrome_o[4] = ^(in & 512'h043DFDFBEF83FFBEF83FF7C1FF83FF003FF7C1FF83FF003FF07FE007FE007FE007C1FF801FF801FF801F003FF003E007C1003FF003E007C1003E082003E08204); + syndrome_o[5] = ^(in & 512'h083EFEFDF7BC3FDF7BC3FBDE1FBC3F0FC0FBDE1FBC3F0FC0F787E1F81E1F81E0785E1F87E0787E0781E10FC0F03C2078420FC0F03C20784203C210403C210408); + syndrome_o[6] = ^(in & 512'h103F7F7EFBDDC7EFBDDC7DEEE3DDC771C71DEEE3DDC771C71BB8EE38E2E38E2388AEE3B8E38B8E388E2271C711C443888471C711C44388841C442081C4420810); + syndrome_o[7] = ^(in & 512'h203FBFBF7DEED9F7DEED9EF76CEED9B6592EF76CEED9B6592DDB36CB256CB24C91376CDB2C95B2C93244B65926488C9108B65926488C91086488410648841020); + syndrome_o[8] = ^(in & 512'h403FDFDFBEF76AFBEF76AF7BB5776ADAAA4F7BB5776ADAAA4EED5B5549B55495223BB56D5526D5525488DAAA4A91152210DAAA4A91152210A910820A91082040); + syndrome_o[9] = ^(in & 512'h803FEFEFDF7BB4FDF7BB4FBDDA7BB4ED348FBDDA7BB4ED348F769DA691DA691A443DDA769A4769A46910ED348D221A4420ED348D221A4420D221040D22104080); + + // Corrected output calculation + d_o[0] = (syndrome_o == 10'h7) ^ in[0]; + d_o[1] = (syndrome_o == 10'hb) ^ in[1]; + d_o[2] = (syndrome_o == 10'h13) ^ in[2]; + d_o[3] = (syndrome_o == 10'h23) ^ in[3]; + d_o[4] = (syndrome_o == 10'h43) ^ in[4]; + d_o[5] = (syndrome_o == 10'h83) ^ in[5]; + d_o[6] = (syndrome_o == 10'h103) ^ in[6]; + d_o[7] = (syndrome_o == 10'h203) ^ in[7]; + d_o[8] = (syndrome_o == 10'hd) ^ in[8]; + d_o[9] = (syndrome_o == 10'h15) ^ in[9]; + d_o[10] = (syndrome_o == 10'h25) ^ in[10]; + d_o[11] = (syndrome_o == 10'h45) ^ in[11]; + d_o[12] = (syndrome_o == 10'h85) ^ in[12]; + d_o[13] = (syndrome_o == 10'h105) ^ in[13]; + d_o[14] = (syndrome_o == 10'h205) ^ in[14]; + d_o[15] = (syndrome_o == 10'h19) ^ in[15]; + d_o[16] = (syndrome_o == 10'h29) ^ in[16]; + d_o[17] = (syndrome_o == 10'h49) ^ in[17]; + d_o[18] = (syndrome_o == 10'h89) ^ in[18]; + d_o[19] = (syndrome_o == 10'h109) ^ in[19]; + d_o[20] = (syndrome_o == 10'h209) ^ in[20]; + d_o[21] = (syndrome_o == 10'h31) ^ in[21]; + d_o[22] = (syndrome_o == 10'h51) ^ in[22]; + d_o[23] = (syndrome_o == 10'h91) ^ in[23]; + d_o[24] = (syndrome_o == 10'h111) ^ in[24]; + d_o[25] = (syndrome_o == 10'h211) ^ in[25]; + d_o[26] = (syndrome_o == 10'h61) ^ in[26]; + d_o[27] = (syndrome_o == 10'ha1) ^ in[27]; + d_o[28] = (syndrome_o == 10'h121) ^ in[28]; + d_o[29] = (syndrome_o == 10'h221) ^ in[29]; + d_o[30] = (syndrome_o == 10'hc1) ^ in[30]; + d_o[31] = (syndrome_o == 10'h141) ^ in[31]; + d_o[32] = (syndrome_o == 10'h241) ^ in[32]; + d_o[33] = (syndrome_o == 10'h181) ^ in[33]; + d_o[34] = (syndrome_o == 10'h281) ^ in[34]; + d_o[35] = (syndrome_o == 10'h301) ^ in[35]; + d_o[36] = (syndrome_o == 10'he) ^ in[36]; + d_o[37] = (syndrome_o == 10'h16) ^ in[37]; + d_o[38] = (syndrome_o == 10'h26) ^ in[38]; + d_o[39] = (syndrome_o == 10'h46) ^ in[39]; + d_o[40] = (syndrome_o == 10'h86) ^ in[40]; + d_o[41] = (syndrome_o == 10'h106) ^ in[41]; + d_o[42] = (syndrome_o == 10'h206) ^ in[42]; + d_o[43] = (syndrome_o == 10'h1a) ^ in[43]; + d_o[44] = (syndrome_o == 10'h2a) ^ in[44]; + d_o[45] = (syndrome_o == 10'h4a) ^ in[45]; + d_o[46] = (syndrome_o == 10'h8a) ^ in[46]; + d_o[47] = (syndrome_o == 10'h10a) ^ in[47]; + d_o[48] = (syndrome_o == 10'h20a) ^ in[48]; + d_o[49] = (syndrome_o == 10'h32) ^ in[49]; + d_o[50] = (syndrome_o == 10'h52) ^ in[50]; + d_o[51] = (syndrome_o == 10'h92) ^ in[51]; + d_o[52] = (syndrome_o == 10'h112) ^ in[52]; + d_o[53] = (syndrome_o == 10'h212) ^ in[53]; + d_o[54] = (syndrome_o == 10'h62) ^ in[54]; + d_o[55] = (syndrome_o == 10'ha2) ^ in[55]; + d_o[56] = (syndrome_o == 10'h122) ^ in[56]; + d_o[57] = (syndrome_o == 10'h222) ^ in[57]; + d_o[58] = (syndrome_o == 10'hc2) ^ in[58]; + d_o[59] = (syndrome_o == 10'h142) ^ in[59]; + d_o[60] = (syndrome_o == 10'h242) ^ in[60]; + d_o[61] = (syndrome_o == 10'h182) ^ in[61]; + d_o[62] = (syndrome_o == 10'h282) ^ in[62]; + d_o[63] = (syndrome_o == 10'h302) ^ in[63]; + d_o[64] = (syndrome_o == 10'h1c) ^ in[64]; + d_o[65] = (syndrome_o == 10'h2c) ^ in[65]; + d_o[66] = (syndrome_o == 10'h4c) ^ in[66]; + d_o[67] = (syndrome_o == 10'h8c) ^ in[67]; + d_o[68] = (syndrome_o == 10'h10c) ^ in[68]; + d_o[69] = (syndrome_o == 10'h20c) ^ in[69]; + d_o[70] = (syndrome_o == 10'h34) ^ in[70]; + d_o[71] = (syndrome_o == 10'h54) ^ in[71]; + d_o[72] = (syndrome_o == 10'h94) ^ in[72]; + d_o[73] = (syndrome_o == 10'h114) ^ in[73]; + d_o[74] = (syndrome_o == 10'h214) ^ in[74]; + d_o[75] = (syndrome_o == 10'h64) ^ in[75]; + d_o[76] = (syndrome_o == 10'ha4) ^ in[76]; + d_o[77] = (syndrome_o == 10'h124) ^ in[77]; + d_o[78] = (syndrome_o == 10'h224) ^ in[78]; + d_o[79] = (syndrome_o == 10'hc4) ^ in[79]; + d_o[80] = (syndrome_o == 10'h144) ^ in[80]; + d_o[81] = (syndrome_o == 10'h244) ^ in[81]; + d_o[82] = (syndrome_o == 10'h184) ^ in[82]; + d_o[83] = (syndrome_o == 10'h284) ^ in[83]; + d_o[84] = (syndrome_o == 10'h304) ^ in[84]; + d_o[85] = (syndrome_o == 10'h38) ^ in[85]; + d_o[86] = (syndrome_o == 10'h58) ^ in[86]; + d_o[87] = (syndrome_o == 10'h98) ^ in[87]; + d_o[88] = (syndrome_o == 10'h118) ^ in[88]; + d_o[89] = (syndrome_o == 10'h218) ^ in[89]; + d_o[90] = (syndrome_o == 10'h68) ^ in[90]; + d_o[91] = (syndrome_o == 10'ha8) ^ in[91]; + d_o[92] = (syndrome_o == 10'h128) ^ in[92]; + d_o[93] = (syndrome_o == 10'h228) ^ in[93]; + d_o[94] = (syndrome_o == 10'hc8) ^ in[94]; + d_o[95] = (syndrome_o == 10'h148) ^ in[95]; + d_o[96] = (syndrome_o == 10'h248) ^ in[96]; + d_o[97] = (syndrome_o == 10'h188) ^ in[97]; + d_o[98] = (syndrome_o == 10'h288) ^ in[98]; + d_o[99] = (syndrome_o == 10'h308) ^ in[99]; + d_o[100] = (syndrome_o == 10'h70) ^ in[100]; + d_o[101] = (syndrome_o == 10'hb0) ^ in[101]; + d_o[102] = (syndrome_o == 10'h130) ^ in[102]; + d_o[103] = (syndrome_o == 10'h230) ^ in[103]; + d_o[104] = (syndrome_o == 10'hd0) ^ in[104]; + d_o[105] = (syndrome_o == 10'h150) ^ in[105]; + d_o[106] = (syndrome_o == 10'h250) ^ in[106]; + d_o[107] = (syndrome_o == 10'h190) ^ in[107]; + d_o[108] = (syndrome_o == 10'h290) ^ in[108]; + d_o[109] = (syndrome_o == 10'h310) ^ in[109]; + d_o[110] = (syndrome_o == 10'he0) ^ in[110]; + d_o[111] = (syndrome_o == 10'h160) ^ in[111]; + d_o[112] = (syndrome_o == 10'h260) ^ in[112]; + d_o[113] = (syndrome_o == 10'h1a0) ^ in[113]; + d_o[114] = (syndrome_o == 10'h2a0) ^ in[114]; + d_o[115] = (syndrome_o == 10'h320) ^ in[115]; + d_o[116] = (syndrome_o == 10'h1c0) ^ in[116]; + d_o[117] = (syndrome_o == 10'h2c0) ^ in[117]; + d_o[118] = (syndrome_o == 10'h340) ^ in[118]; + d_o[119] = (syndrome_o == 10'h380) ^ in[119]; + d_o[120] = (syndrome_o == 10'h1f) ^ in[120]; + d_o[121] = (syndrome_o == 10'h2f) ^ in[121]; + d_o[122] = (syndrome_o == 10'h4f) ^ in[122]; + d_o[123] = (syndrome_o == 10'h8f) ^ in[123]; + d_o[124] = (syndrome_o == 10'h10f) ^ in[124]; + d_o[125] = (syndrome_o == 10'h20f) ^ in[125]; + d_o[126] = (syndrome_o == 10'h37) ^ in[126]; + d_o[127] = (syndrome_o == 10'h57) ^ in[127]; + d_o[128] = (syndrome_o == 10'h97) ^ in[128]; + d_o[129] = (syndrome_o == 10'h117) ^ in[129]; + d_o[130] = (syndrome_o == 10'h217) ^ in[130]; + d_o[131] = (syndrome_o == 10'h67) ^ in[131]; + d_o[132] = (syndrome_o == 10'ha7) ^ in[132]; + d_o[133] = (syndrome_o == 10'h127) ^ in[133]; + d_o[134] = (syndrome_o == 10'h227) ^ in[134]; + d_o[135] = (syndrome_o == 10'hc7) ^ in[135]; + d_o[136] = (syndrome_o == 10'h147) ^ in[136]; + d_o[137] = (syndrome_o == 10'h247) ^ in[137]; + d_o[138] = (syndrome_o == 10'h187) ^ in[138]; + d_o[139] = (syndrome_o == 10'h287) ^ in[139]; + d_o[140] = (syndrome_o == 10'h307) ^ in[140]; + d_o[141] = (syndrome_o == 10'h3b) ^ in[141]; + d_o[142] = (syndrome_o == 10'h5b) ^ in[142]; + d_o[143] = (syndrome_o == 10'h9b) ^ in[143]; + d_o[144] = (syndrome_o == 10'h11b) ^ in[144]; + d_o[145] = (syndrome_o == 10'h21b) ^ in[145]; + d_o[146] = (syndrome_o == 10'h6b) ^ in[146]; + d_o[147] = (syndrome_o == 10'hab) ^ in[147]; + d_o[148] = (syndrome_o == 10'h12b) ^ in[148]; + d_o[149] = (syndrome_o == 10'h22b) ^ in[149]; + d_o[150] = (syndrome_o == 10'hcb) ^ in[150]; + d_o[151] = (syndrome_o == 10'h14b) ^ in[151]; + d_o[152] = (syndrome_o == 10'h24b) ^ in[152]; + d_o[153] = (syndrome_o == 10'h18b) ^ in[153]; + d_o[154] = (syndrome_o == 10'h28b) ^ in[154]; + d_o[155] = (syndrome_o == 10'h30b) ^ in[155]; + d_o[156] = (syndrome_o == 10'h73) ^ in[156]; + d_o[157] = (syndrome_o == 10'hb3) ^ in[157]; + d_o[158] = (syndrome_o == 10'h133) ^ in[158]; + d_o[159] = (syndrome_o == 10'h233) ^ in[159]; + d_o[160] = (syndrome_o == 10'hd3) ^ in[160]; + d_o[161] = (syndrome_o == 10'h153) ^ in[161]; + d_o[162] = (syndrome_o == 10'h253) ^ in[162]; + d_o[163] = (syndrome_o == 10'h193) ^ in[163]; + d_o[164] = (syndrome_o == 10'h293) ^ in[164]; + d_o[165] = (syndrome_o == 10'h313) ^ in[165]; + d_o[166] = (syndrome_o == 10'he3) ^ in[166]; + d_o[167] = (syndrome_o == 10'h163) ^ in[167]; + d_o[168] = (syndrome_o == 10'h263) ^ in[168]; + d_o[169] = (syndrome_o == 10'h1a3) ^ in[169]; + d_o[170] = (syndrome_o == 10'h2a3) ^ in[170]; + d_o[171] = (syndrome_o == 10'h323) ^ in[171]; + d_o[172] = (syndrome_o == 10'h1c3) ^ in[172]; + d_o[173] = (syndrome_o == 10'h2c3) ^ in[173]; + d_o[174] = (syndrome_o == 10'h343) ^ in[174]; + d_o[175] = (syndrome_o == 10'h383) ^ in[175]; + d_o[176] = (syndrome_o == 10'h3d) ^ in[176]; + d_o[177] = (syndrome_o == 10'h5d) ^ in[177]; + d_o[178] = (syndrome_o == 10'h9d) ^ in[178]; + d_o[179] = (syndrome_o == 10'h11d) ^ in[179]; + d_o[180] = (syndrome_o == 10'h21d) ^ in[180]; + d_o[181] = (syndrome_o == 10'h6d) ^ in[181]; + d_o[182] = (syndrome_o == 10'had) ^ in[182]; + d_o[183] = (syndrome_o == 10'h12d) ^ in[183]; + d_o[184] = (syndrome_o == 10'h22d) ^ in[184]; + d_o[185] = (syndrome_o == 10'hcd) ^ in[185]; + d_o[186] = (syndrome_o == 10'h14d) ^ in[186]; + d_o[187] = (syndrome_o == 10'h24d) ^ in[187]; + d_o[188] = (syndrome_o == 10'h18d) ^ in[188]; + d_o[189] = (syndrome_o == 10'h28d) ^ in[189]; + d_o[190] = (syndrome_o == 10'h30d) ^ in[190]; + d_o[191] = (syndrome_o == 10'h75) ^ in[191]; + d_o[192] = (syndrome_o == 10'hb5) ^ in[192]; + d_o[193] = (syndrome_o == 10'h135) ^ in[193]; + d_o[194] = (syndrome_o == 10'h235) ^ in[194]; + d_o[195] = (syndrome_o == 10'hd5) ^ in[195]; + d_o[196] = (syndrome_o == 10'h155) ^ in[196]; + d_o[197] = (syndrome_o == 10'h255) ^ in[197]; + d_o[198] = (syndrome_o == 10'h195) ^ in[198]; + d_o[199] = (syndrome_o == 10'h295) ^ in[199]; + d_o[200] = (syndrome_o == 10'h315) ^ in[200]; + d_o[201] = (syndrome_o == 10'he5) ^ in[201]; + d_o[202] = (syndrome_o == 10'h165) ^ in[202]; + d_o[203] = (syndrome_o == 10'h265) ^ in[203]; + d_o[204] = (syndrome_o == 10'h1a5) ^ in[204]; + d_o[205] = (syndrome_o == 10'h2a5) ^ in[205]; + d_o[206] = (syndrome_o == 10'h325) ^ in[206]; + d_o[207] = (syndrome_o == 10'h1c5) ^ in[207]; + d_o[208] = (syndrome_o == 10'h2c5) ^ in[208]; + d_o[209] = (syndrome_o == 10'h345) ^ in[209]; + d_o[210] = (syndrome_o == 10'h385) ^ in[210]; + d_o[211] = (syndrome_o == 10'h79) ^ in[211]; + d_o[212] = (syndrome_o == 10'hb9) ^ in[212]; + d_o[213] = (syndrome_o == 10'h139) ^ in[213]; + d_o[214] = (syndrome_o == 10'h239) ^ in[214]; + d_o[215] = (syndrome_o == 10'hd9) ^ in[215]; + d_o[216] = (syndrome_o == 10'h159) ^ in[216]; + d_o[217] = (syndrome_o == 10'h259) ^ in[217]; + d_o[218] = (syndrome_o == 10'h199) ^ in[218]; + d_o[219] = (syndrome_o == 10'h299) ^ in[219]; + d_o[220] = (syndrome_o == 10'h319) ^ in[220]; + d_o[221] = (syndrome_o == 10'he9) ^ in[221]; + d_o[222] = (syndrome_o == 10'h169) ^ in[222]; + d_o[223] = (syndrome_o == 10'h269) ^ in[223]; + d_o[224] = (syndrome_o == 10'h1a9) ^ in[224]; + d_o[225] = (syndrome_o == 10'h2a9) ^ in[225]; + d_o[226] = (syndrome_o == 10'h329) ^ in[226]; + d_o[227] = (syndrome_o == 10'h1c9) ^ in[227]; + d_o[228] = (syndrome_o == 10'h2c9) ^ in[228]; + d_o[229] = (syndrome_o == 10'h349) ^ in[229]; + d_o[230] = (syndrome_o == 10'h389) ^ in[230]; + d_o[231] = (syndrome_o == 10'hf1) ^ in[231]; + d_o[232] = (syndrome_o == 10'h171) ^ in[232]; + d_o[233] = (syndrome_o == 10'h271) ^ in[233]; + d_o[234] = (syndrome_o == 10'h1b1) ^ in[234]; + d_o[235] = (syndrome_o == 10'h2b1) ^ in[235]; + d_o[236] = (syndrome_o == 10'h331) ^ in[236]; + d_o[237] = (syndrome_o == 10'h1d1) ^ in[237]; + d_o[238] = (syndrome_o == 10'h2d1) ^ in[238]; + d_o[239] = (syndrome_o == 10'h351) ^ in[239]; + d_o[240] = (syndrome_o == 10'h391) ^ in[240]; + d_o[241] = (syndrome_o == 10'h1e1) ^ in[241]; + d_o[242] = (syndrome_o == 10'h2e1) ^ in[242]; + d_o[243] = (syndrome_o == 10'h361) ^ in[243]; + d_o[244] = (syndrome_o == 10'h3a1) ^ in[244]; + d_o[245] = (syndrome_o == 10'h3c1) ^ in[245]; + d_o[246] = (syndrome_o == 10'h3e) ^ in[246]; + d_o[247] = (syndrome_o == 10'h5e) ^ in[247]; + d_o[248] = (syndrome_o == 10'h9e) ^ in[248]; + d_o[249] = (syndrome_o == 10'h11e) ^ in[249]; + d_o[250] = (syndrome_o == 10'h21e) ^ in[250]; + d_o[251] = (syndrome_o == 10'h6e) ^ in[251]; + d_o[252] = (syndrome_o == 10'hae) ^ in[252]; + d_o[253] = (syndrome_o == 10'h12e) ^ in[253]; + d_o[254] = (syndrome_o == 10'h22e) ^ in[254]; + d_o[255] = (syndrome_o == 10'hce) ^ in[255]; + d_o[256] = (syndrome_o == 10'h14e) ^ in[256]; + d_o[257] = (syndrome_o == 10'h24e) ^ in[257]; + d_o[258] = (syndrome_o == 10'h18e) ^ in[258]; + d_o[259] = (syndrome_o == 10'h28e) ^ in[259]; + d_o[260] = (syndrome_o == 10'h30e) ^ in[260]; + d_o[261] = (syndrome_o == 10'h76) ^ in[261]; + d_o[262] = (syndrome_o == 10'hb6) ^ in[262]; + d_o[263] = (syndrome_o == 10'h136) ^ in[263]; + d_o[264] = (syndrome_o == 10'h236) ^ in[264]; + d_o[265] = (syndrome_o == 10'hd6) ^ in[265]; + d_o[266] = (syndrome_o == 10'h156) ^ in[266]; + d_o[267] = (syndrome_o == 10'h256) ^ in[267]; + d_o[268] = (syndrome_o == 10'h196) ^ in[268]; + d_o[269] = (syndrome_o == 10'h296) ^ in[269]; + d_o[270] = (syndrome_o == 10'h316) ^ in[270]; + d_o[271] = (syndrome_o == 10'he6) ^ in[271]; + d_o[272] = (syndrome_o == 10'h166) ^ in[272]; + d_o[273] = (syndrome_o == 10'h266) ^ in[273]; + d_o[274] = (syndrome_o == 10'h1a6) ^ in[274]; + d_o[275] = (syndrome_o == 10'h2a6) ^ in[275]; + d_o[276] = (syndrome_o == 10'h326) ^ in[276]; + d_o[277] = (syndrome_o == 10'h1c6) ^ in[277]; + d_o[278] = (syndrome_o == 10'h2c6) ^ in[278]; + d_o[279] = (syndrome_o == 10'h346) ^ in[279]; + d_o[280] = (syndrome_o == 10'h386) ^ in[280]; + d_o[281] = (syndrome_o == 10'h7a) ^ in[281]; + d_o[282] = (syndrome_o == 10'hba) ^ in[282]; + d_o[283] = (syndrome_o == 10'h13a) ^ in[283]; + d_o[284] = (syndrome_o == 10'h23a) ^ in[284]; + d_o[285] = (syndrome_o == 10'hda) ^ in[285]; + d_o[286] = (syndrome_o == 10'h15a) ^ in[286]; + d_o[287] = (syndrome_o == 10'h25a) ^ in[287]; + d_o[288] = (syndrome_o == 10'h19a) ^ in[288]; + d_o[289] = (syndrome_o == 10'h29a) ^ in[289]; + d_o[290] = (syndrome_o == 10'h31a) ^ in[290]; + d_o[291] = (syndrome_o == 10'hea) ^ in[291]; + d_o[292] = (syndrome_o == 10'h16a) ^ in[292]; + d_o[293] = (syndrome_o == 10'h26a) ^ in[293]; + d_o[294] = (syndrome_o == 10'h1aa) ^ in[294]; + d_o[295] = (syndrome_o == 10'h2aa) ^ in[295]; + d_o[296] = (syndrome_o == 10'h32a) ^ in[296]; + d_o[297] = (syndrome_o == 10'h1ca) ^ in[297]; + d_o[298] = (syndrome_o == 10'h2ca) ^ in[298]; + d_o[299] = (syndrome_o == 10'h34a) ^ in[299]; + d_o[300] = (syndrome_o == 10'h38a) ^ in[300]; + d_o[301] = (syndrome_o == 10'hf2) ^ in[301]; + d_o[302] = (syndrome_o == 10'h172) ^ in[302]; + d_o[303] = (syndrome_o == 10'h272) ^ in[303]; + d_o[304] = (syndrome_o == 10'h1b2) ^ in[304]; + d_o[305] = (syndrome_o == 10'h2b2) ^ in[305]; + d_o[306] = (syndrome_o == 10'h332) ^ in[306]; + d_o[307] = (syndrome_o == 10'h1d2) ^ in[307]; + d_o[308] = (syndrome_o == 10'h2d2) ^ in[308]; + d_o[309] = (syndrome_o == 10'h352) ^ in[309]; + d_o[310] = (syndrome_o == 10'h392) ^ in[310]; + d_o[311] = (syndrome_o == 10'h1e2) ^ in[311]; + d_o[312] = (syndrome_o == 10'h2e2) ^ in[312]; + d_o[313] = (syndrome_o == 10'h362) ^ in[313]; + d_o[314] = (syndrome_o == 10'h3a2) ^ in[314]; + d_o[315] = (syndrome_o == 10'h3c2) ^ in[315]; + d_o[316] = (syndrome_o == 10'h7c) ^ in[316]; + d_o[317] = (syndrome_o == 10'hbc) ^ in[317]; + d_o[318] = (syndrome_o == 10'h13c) ^ in[318]; + d_o[319] = (syndrome_o == 10'h23c) ^ in[319]; + d_o[320] = (syndrome_o == 10'hdc) ^ in[320]; + d_o[321] = (syndrome_o == 10'h15c) ^ in[321]; + d_o[322] = (syndrome_o == 10'h25c) ^ in[322]; + d_o[323] = (syndrome_o == 10'h19c) ^ in[323]; + d_o[324] = (syndrome_o == 10'h29c) ^ in[324]; + d_o[325] = (syndrome_o == 10'h31c) ^ in[325]; + d_o[326] = (syndrome_o == 10'hec) ^ in[326]; + d_o[327] = (syndrome_o == 10'h16c) ^ in[327]; + d_o[328] = (syndrome_o == 10'h26c) ^ in[328]; + d_o[329] = (syndrome_o == 10'h1ac) ^ in[329]; + d_o[330] = (syndrome_o == 10'h2ac) ^ in[330]; + d_o[331] = (syndrome_o == 10'h32c) ^ in[331]; + d_o[332] = (syndrome_o == 10'h1cc) ^ in[332]; + d_o[333] = (syndrome_o == 10'h2cc) ^ in[333]; + d_o[334] = (syndrome_o == 10'h34c) ^ in[334]; + d_o[335] = (syndrome_o == 10'h38c) ^ in[335]; + d_o[336] = (syndrome_o == 10'hf4) ^ in[336]; + d_o[337] = (syndrome_o == 10'h174) ^ in[337]; + d_o[338] = (syndrome_o == 10'h274) ^ in[338]; + d_o[339] = (syndrome_o == 10'h1b4) ^ in[339]; + d_o[340] = (syndrome_o == 10'h2b4) ^ in[340]; + d_o[341] = (syndrome_o == 10'h334) ^ in[341]; + d_o[342] = (syndrome_o == 10'h1d4) ^ in[342]; + d_o[343] = (syndrome_o == 10'h2d4) ^ in[343]; + d_o[344] = (syndrome_o == 10'h354) ^ in[344]; + d_o[345] = (syndrome_o == 10'h394) ^ in[345]; + d_o[346] = (syndrome_o == 10'h1e4) ^ in[346]; + d_o[347] = (syndrome_o == 10'h2e4) ^ in[347]; + d_o[348] = (syndrome_o == 10'h364) ^ in[348]; + d_o[349] = (syndrome_o == 10'h3a4) ^ in[349]; + d_o[350] = (syndrome_o == 10'h3c4) ^ in[350]; + d_o[351] = (syndrome_o == 10'hf8) ^ in[351]; + d_o[352] = (syndrome_o == 10'h178) ^ in[352]; + d_o[353] = (syndrome_o == 10'h278) ^ in[353]; + d_o[354] = (syndrome_o == 10'h1b8) ^ in[354]; + d_o[355] = (syndrome_o == 10'h2b8) ^ in[355]; + d_o[356] = (syndrome_o == 10'h338) ^ in[356]; + d_o[357] = (syndrome_o == 10'h1d8) ^ in[357]; + d_o[358] = (syndrome_o == 10'h2d8) ^ in[358]; + d_o[359] = (syndrome_o == 10'h358) ^ in[359]; + d_o[360] = (syndrome_o == 10'h398) ^ in[360]; + d_o[361] = (syndrome_o == 10'h1e8) ^ in[361]; + d_o[362] = (syndrome_o == 10'h2e8) ^ in[362]; + d_o[363] = (syndrome_o == 10'h368) ^ in[363]; + d_o[364] = (syndrome_o == 10'h3a8) ^ in[364]; + d_o[365] = (syndrome_o == 10'h3c8) ^ in[365]; + d_o[366] = (syndrome_o == 10'h1f0) ^ in[366]; + d_o[367] = (syndrome_o == 10'h2f0) ^ in[367]; + d_o[368] = (syndrome_o == 10'h370) ^ in[368]; + d_o[369] = (syndrome_o == 10'h3b0) ^ in[369]; + d_o[370] = (syndrome_o == 10'h3d0) ^ in[370]; + d_o[371] = (syndrome_o == 10'h3e0) ^ in[371]; + d_o[372] = (syndrome_o == 10'h7f) ^ in[372]; + d_o[373] = (syndrome_o == 10'hbf) ^ in[373]; + d_o[374] = (syndrome_o == 10'h13f) ^ in[374]; + d_o[375] = (syndrome_o == 10'h23f) ^ in[375]; + d_o[376] = (syndrome_o == 10'hdf) ^ in[376]; + d_o[377] = (syndrome_o == 10'h15f) ^ in[377]; + d_o[378] = (syndrome_o == 10'h25f) ^ in[378]; + d_o[379] = (syndrome_o == 10'h19f) ^ in[379]; + d_o[380] = (syndrome_o == 10'h29f) ^ in[380]; + d_o[381] = (syndrome_o == 10'h31f) ^ in[381]; + d_o[382] = (syndrome_o == 10'hef) ^ in[382]; + d_o[383] = (syndrome_o == 10'h16f) ^ in[383]; + d_o[384] = (syndrome_o == 10'h26f) ^ in[384]; + d_o[385] = (syndrome_o == 10'h1af) ^ in[385]; + d_o[386] = (syndrome_o == 10'h2af) ^ in[386]; + d_o[387] = (syndrome_o == 10'h32f) ^ in[387]; + d_o[388] = (syndrome_o == 10'h1cf) ^ in[388]; + d_o[389] = (syndrome_o == 10'h2cf) ^ in[389]; + d_o[390] = (syndrome_o == 10'h34f) ^ in[390]; + d_o[391] = (syndrome_o == 10'h38f) ^ in[391]; + d_o[392] = (syndrome_o == 10'hf7) ^ in[392]; + d_o[393] = (syndrome_o == 10'h177) ^ in[393]; + d_o[394] = (syndrome_o == 10'h277) ^ in[394]; + d_o[395] = (syndrome_o == 10'h1b7) ^ in[395]; + d_o[396] = (syndrome_o == 10'h2b7) ^ in[396]; + d_o[397] = (syndrome_o == 10'h337) ^ in[397]; + d_o[398] = (syndrome_o == 10'h1d7) ^ in[398]; + d_o[399] = (syndrome_o == 10'h2d7) ^ in[399]; + d_o[400] = (syndrome_o == 10'h357) ^ in[400]; + d_o[401] = (syndrome_o == 10'h397) ^ in[401]; + d_o[402] = (syndrome_o == 10'h1e7) ^ in[402]; + d_o[403] = (syndrome_o == 10'h2e7) ^ in[403]; + d_o[404] = (syndrome_o == 10'h367) ^ in[404]; + d_o[405] = (syndrome_o == 10'h3a7) ^ in[405]; + d_o[406] = (syndrome_o == 10'h3c7) ^ in[406]; + d_o[407] = (syndrome_o == 10'hfb) ^ in[407]; + d_o[408] = (syndrome_o == 10'h17b) ^ in[408]; + d_o[409] = (syndrome_o == 10'h27b) ^ in[409]; + d_o[410] = (syndrome_o == 10'h1bb) ^ in[410]; + d_o[411] = (syndrome_o == 10'h2bb) ^ in[411]; + d_o[412] = (syndrome_o == 10'h33b) ^ in[412]; + d_o[413] = (syndrome_o == 10'h1db) ^ in[413]; + d_o[414] = (syndrome_o == 10'h2db) ^ in[414]; + d_o[415] = (syndrome_o == 10'h35b) ^ in[415]; + d_o[416] = (syndrome_o == 10'h39b) ^ in[416]; + d_o[417] = (syndrome_o == 10'h1eb) ^ in[417]; + d_o[418] = (syndrome_o == 10'h2eb) ^ in[418]; + d_o[419] = (syndrome_o == 10'h36b) ^ in[419]; + d_o[420] = (syndrome_o == 10'h3ab) ^ in[420]; + d_o[421] = (syndrome_o == 10'h3cb) ^ in[421]; + d_o[422] = (syndrome_o == 10'h1f3) ^ in[422]; + d_o[423] = (syndrome_o == 10'h2f3) ^ in[423]; + d_o[424] = (syndrome_o == 10'h373) ^ in[424]; + d_o[425] = (syndrome_o == 10'h3b3) ^ in[425]; + d_o[426] = (syndrome_o == 10'h3d3) ^ in[426]; + d_o[427] = (syndrome_o == 10'h3e3) ^ in[427]; + d_o[428] = (syndrome_o == 10'hfd) ^ in[428]; + d_o[429] = (syndrome_o == 10'h17d) ^ in[429]; + d_o[430] = (syndrome_o == 10'h27d) ^ in[430]; + d_o[431] = (syndrome_o == 10'h1bd) ^ in[431]; + d_o[432] = (syndrome_o == 10'h2bd) ^ in[432]; + d_o[433] = (syndrome_o == 10'h33d) ^ in[433]; + d_o[434] = (syndrome_o == 10'h1dd) ^ in[434]; + d_o[435] = (syndrome_o == 10'h2dd) ^ in[435]; + d_o[436] = (syndrome_o == 10'h35d) ^ in[436]; + d_o[437] = (syndrome_o == 10'h39d) ^ in[437]; + d_o[438] = (syndrome_o == 10'h1ed) ^ in[438]; + d_o[439] = (syndrome_o == 10'h2ed) ^ in[439]; + d_o[440] = (syndrome_o == 10'h36d) ^ in[440]; + d_o[441] = (syndrome_o == 10'h3ad) ^ in[441]; + d_o[442] = (syndrome_o == 10'h3cd) ^ in[442]; + d_o[443] = (syndrome_o == 10'h1f5) ^ in[443]; + d_o[444] = (syndrome_o == 10'h2f5) ^ in[444]; + d_o[445] = (syndrome_o == 10'h375) ^ in[445]; + d_o[446] = (syndrome_o == 10'h3b5) ^ in[446]; + d_o[447] = (syndrome_o == 10'h3d5) ^ in[447]; + d_o[448] = (syndrome_o == 10'h3e5) ^ in[448]; + d_o[449] = (syndrome_o == 10'h1f9) ^ in[449]; + d_o[450] = (syndrome_o == 10'h2f9) ^ in[450]; + d_o[451] = (syndrome_o == 10'h379) ^ in[451]; + d_o[452] = (syndrome_o == 10'h3b9) ^ in[452]; + d_o[453] = (syndrome_o == 10'h3d9) ^ in[453]; + d_o[454] = (syndrome_o == 10'h3e9) ^ in[454]; + d_o[455] = (syndrome_o == 10'h3f1) ^ in[455]; + d_o[456] = (syndrome_o == 10'hfe) ^ in[456]; + d_o[457] = (syndrome_o == 10'h17e) ^ in[457]; + d_o[458] = (syndrome_o == 10'h27e) ^ in[458]; + d_o[459] = (syndrome_o == 10'h1be) ^ in[459]; + d_o[460] = (syndrome_o == 10'h2be) ^ in[460]; + d_o[461] = (syndrome_o == 10'h33e) ^ in[461]; + d_o[462] = (syndrome_o == 10'h1de) ^ in[462]; + d_o[463] = (syndrome_o == 10'h2de) ^ in[463]; + d_o[464] = (syndrome_o == 10'h35e) ^ in[464]; + d_o[465] = (syndrome_o == 10'h39e) ^ in[465]; + d_o[466] = (syndrome_o == 10'h1ee) ^ in[466]; + d_o[467] = (syndrome_o == 10'h2ee) ^ in[467]; + d_o[468] = (syndrome_o == 10'h36e) ^ in[468]; + d_o[469] = (syndrome_o == 10'h3ae) ^ in[469]; + d_o[470] = (syndrome_o == 10'h3ce) ^ in[470]; + d_o[471] = (syndrome_o == 10'h1f6) ^ in[471]; + d_o[472] = (syndrome_o == 10'h2f6) ^ in[472]; + d_o[473] = (syndrome_o == 10'h376) ^ in[473]; + d_o[474] = (syndrome_o == 10'h3b6) ^ in[474]; + d_o[475] = (syndrome_o == 10'h3d6) ^ in[475]; + d_o[476] = (syndrome_o == 10'h3e6) ^ in[476]; + d_o[477] = (syndrome_o == 10'h1fa) ^ in[477]; + d_o[478] = (syndrome_o == 10'h2fa) ^ in[478]; + d_o[479] = (syndrome_o == 10'h37a) ^ in[479]; + d_o[480] = (syndrome_o == 10'h3ba) ^ in[480]; + d_o[481] = (syndrome_o == 10'h3da) ^ in[481]; + d_o[482] = (syndrome_o == 10'h3ea) ^ in[482]; + d_o[483] = (syndrome_o == 10'h3f2) ^ in[483]; + d_o[484] = (syndrome_o == 10'h1fc) ^ in[484]; + d_o[485] = (syndrome_o == 10'h2fc) ^ in[485]; + d_o[486] = (syndrome_o == 10'h37c) ^ in[486]; + d_o[487] = (syndrome_o == 10'h3bc) ^ in[487]; + d_o[488] = (syndrome_o == 10'h3dc) ^ in[488]; + d_o[489] = (syndrome_o == 10'h3ec) ^ in[489]; + d_o[490] = (syndrome_o == 10'h3f4) ^ in[490]; + d_o[491] = (syndrome_o == 10'h3f8) ^ in[491]; + d_o[492] = (syndrome_o == 10'h1ff) ^ in[492]; + d_o[493] = (syndrome_o == 10'h2ff) ^ in[493]; + d_o[494] = (syndrome_o == 10'h37f) ^ in[494]; + d_o[495] = (syndrome_o == 10'h3bf) ^ in[495]; + d_o[496] = (syndrome_o == 10'h3df) ^ in[496]; + d_o[497] = (syndrome_o == 10'h3ef) ^ in[497]; + d_o[498] = (syndrome_o == 10'h3f7) ^ in[498]; + d_o[499] = (syndrome_o == 10'h3fb) ^ in[499]; + d_o[500] = (syndrome_o == 10'h3fd) ^ in[500]; + d_o[501] = (syndrome_o == 10'h3fe) ^ in[501]; + + // err_o calc. bit0: single error, bit1: double error + single_error = ^syndrome_o; + err_o[0] = single_error; + err_o[1] = ~single_error & (|syndrome_o); + + dec.data = d_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + function automatic logic [21:0] prim_secded_hamming_22_16_enc (logic [15:0] in); logic [21:0] out; - out = 22'(in); - out[16] = ^(out & 22'h00AD5B); - out[17] = ^(out & 22'h00366D); - out[18] = ^(out & 22'h00C78E); - out[19] = ^(out & 22'h0007F0); - out[20] = ^(out & 22'h00F800); - out[21] = ^(out & 22'h1FFFFF); + out[15:0] = in; + out[16] = ^(in & 16'hAD5B); + out[17] = ^(in & 16'h366D); + out[18] = ^(in & 16'hC78E); + out[19] = ^(in & 16'h07F0); + out[20] = ^(in & 16'hF800); + out[21] = ^(in & 16'h5CB7); return out; endfunction @@ -550,25 +1810,25 @@ package prim_secded_pkg; syndrome_o[2] = ^(in & 22'h04C78E); syndrome_o[3] = ^(in & 22'h0807F0); syndrome_o[4] = ^(in & 22'h10F800); - syndrome_o[5] = ^(in & 22'h3FFFFF); + syndrome_o[5] = ^(in & 22'h205CB7); // Corrected output calculation d_o[0] = (syndrome_o == 6'h23) ^ in[0]; d_o[1] = (syndrome_o == 6'h25) ^ in[1]; d_o[2] = (syndrome_o == 6'h26) ^ in[2]; - d_o[3] = (syndrome_o == 6'h27) ^ in[3]; + d_o[3] = (syndrome_o == 6'h7) ^ in[3]; d_o[4] = (syndrome_o == 6'h29) ^ in[4]; d_o[5] = (syndrome_o == 6'h2a) ^ in[5]; - d_o[6] = (syndrome_o == 6'h2b) ^ in[6]; + d_o[6] = (syndrome_o == 6'hb) ^ in[6]; d_o[7] = (syndrome_o == 6'h2c) ^ in[7]; - d_o[8] = (syndrome_o == 6'h2d) ^ in[8]; - d_o[9] = (syndrome_o == 6'h2e) ^ in[9]; + d_o[8] = (syndrome_o == 6'hd) ^ in[8]; + d_o[9] = (syndrome_o == 6'he) ^ in[9]; d_o[10] = (syndrome_o == 6'h2f) ^ in[10]; d_o[11] = (syndrome_o == 6'h31) ^ in[11]; d_o[12] = (syndrome_o == 6'h32) ^ in[12]; - d_o[13] = (syndrome_o == 6'h33) ^ in[13]; + d_o[13] = (syndrome_o == 6'h13) ^ in[13]; d_o[14] = (syndrome_o == 6'h34) ^ in[14]; - d_o[15] = (syndrome_o == 6'h35) ^ in[15]; + d_o[15] = (syndrome_o == 6'h15) ^ in[15]; // err_o calc. bit0: single error, bit1: double error err_o[0] = syndrome_o[5]; @@ -583,14 +1843,14 @@ package prim_secded_pkg; function automatic logic [38:0] prim_secded_hamming_39_32_enc (logic [31:0] in); logic [38:0] out; - out = 39'(in); - out[32] = ^(out & 39'h0056AAAD5B); - out[33] = ^(out & 39'h009B33366D); - out[34] = ^(out & 39'h00E3C3C78E); - out[35] = ^(out & 39'h0003FC07F0); - out[36] = ^(out & 39'h0003FFF800); - out[37] = ^(out & 39'h00FC000000); - out[38] = ^(out & 39'h3FFFFFFFFF); + out[31:0] = in; + out[32] = ^(in & 32'h56AAAD5B); + out[33] = ^(in & 32'h9B33366D); + out[34] = ^(in & 32'hE3C3C78E); + out[35] = ^(in & 32'h03FC07F0); + out[36] = ^(in & 32'h03FFF800); + out[37] = ^(in & 32'hFC000000); + out[38] = ^(in & 32'h2DA65CB7); return out; endfunction @@ -609,41 +1869,41 @@ package prim_secded_pkg; syndrome_o[3] = ^(in & 39'h0803FC07F0); syndrome_o[4] = ^(in & 39'h1003FFF800); syndrome_o[5] = ^(in & 39'h20FC000000); - syndrome_o[6] = ^(in & 39'h7FFFFFFFFF); + syndrome_o[6] = ^(in & 39'h402DA65CB7); // Corrected output calculation d_o[0] = (syndrome_o == 7'h43) ^ in[0]; d_o[1] = (syndrome_o == 7'h45) ^ in[1]; d_o[2] = (syndrome_o == 7'h46) ^ in[2]; - d_o[3] = (syndrome_o == 7'h47) ^ in[3]; + d_o[3] = (syndrome_o == 7'h7) ^ in[3]; d_o[4] = (syndrome_o == 7'h49) ^ in[4]; d_o[5] = (syndrome_o == 7'h4a) ^ in[5]; - d_o[6] = (syndrome_o == 7'h4b) ^ in[6]; + d_o[6] = (syndrome_o == 7'hb) ^ in[6]; d_o[7] = (syndrome_o == 7'h4c) ^ in[7]; - d_o[8] = (syndrome_o == 7'h4d) ^ in[8]; - d_o[9] = (syndrome_o == 7'h4e) ^ in[9]; + d_o[8] = (syndrome_o == 7'hd) ^ in[8]; + d_o[9] = (syndrome_o == 7'he) ^ in[9]; d_o[10] = (syndrome_o == 7'h4f) ^ in[10]; d_o[11] = (syndrome_o == 7'h51) ^ in[11]; d_o[12] = (syndrome_o == 7'h52) ^ in[12]; - d_o[13] = (syndrome_o == 7'h53) ^ in[13]; + d_o[13] = (syndrome_o == 7'h13) ^ in[13]; d_o[14] = (syndrome_o == 7'h54) ^ in[14]; - d_o[15] = (syndrome_o == 7'h55) ^ in[15]; - d_o[16] = (syndrome_o == 7'h56) ^ in[16]; + d_o[15] = (syndrome_o == 7'h15) ^ in[15]; + d_o[16] = (syndrome_o == 7'h16) ^ in[16]; d_o[17] = (syndrome_o == 7'h57) ^ in[17]; d_o[18] = (syndrome_o == 7'h58) ^ in[18]; - d_o[19] = (syndrome_o == 7'h59) ^ in[19]; - d_o[20] = (syndrome_o == 7'h5a) ^ in[20]; + d_o[19] = (syndrome_o == 7'h19) ^ in[19]; + d_o[20] = (syndrome_o == 7'h1a) ^ in[20]; d_o[21] = (syndrome_o == 7'h5b) ^ in[21]; - d_o[22] = (syndrome_o == 7'h5c) ^ in[22]; + d_o[22] = (syndrome_o == 7'h1c) ^ in[22]; d_o[23] = (syndrome_o == 7'h5d) ^ in[23]; d_o[24] = (syndrome_o == 7'h5e) ^ in[24]; - d_o[25] = (syndrome_o == 7'h5f) ^ in[25]; + d_o[25] = (syndrome_o == 7'h1f) ^ in[25]; d_o[26] = (syndrome_o == 7'h61) ^ in[26]; d_o[27] = (syndrome_o == 7'h62) ^ in[27]; - d_o[28] = (syndrome_o == 7'h63) ^ in[28]; + d_o[28] = (syndrome_o == 7'h23) ^ in[28]; d_o[29] = (syndrome_o == 7'h64) ^ in[29]; - d_o[30] = (syndrome_o == 7'h65) ^ in[30]; - d_o[31] = (syndrome_o == 7'h66) ^ in[31]; + d_o[30] = (syndrome_o == 7'h25) ^ in[30]; + d_o[31] = (syndrome_o == 7'h26) ^ in[31]; // err_o calc. bit0: single error, bit1: double error err_o[0] = syndrome_o[6]; @@ -658,15 +1918,15 @@ package prim_secded_pkg; function automatic logic [71:0] prim_secded_hamming_72_64_enc (logic [63:0] in); logic [71:0] out; - out = 72'(in); - out[64] = ^(out & 72'h00AB55555556AAAD5B); - out[65] = ^(out & 72'h00CD9999999B33366D); - out[66] = ^(out & 72'h00F1E1E1E1E3C3C78E); - out[67] = ^(out & 72'h0001FE01FE03FC07F0); - out[68] = ^(out & 72'h0001FFFE0003FFF800); - out[69] = ^(out & 72'h0001FFFFFFFC000000); - out[70] = ^(out & 72'h00FE00000000000000); - out[71] = ^(out & 72'h7FFFFFFFFFFFFFFFFF); + out[63:0] = in; + out[64] = ^(in & 64'hAB55555556AAAD5B); + out[65] = ^(in & 64'hCD9999999B33366D); + out[66] = ^(in & 64'hF1E1E1E1E3C3C78E); + out[67] = ^(in & 64'h01FE01FE03FC07F0); + out[68] = ^(in & 64'h01FFFE0003FFF800); + out[69] = ^(in & 64'h01FFFFFFFC000000); + out[70] = ^(in & 64'hFE00000000000000); + out[71] = ^(in & 64'h972CD2D32DA65CB7); return out; endfunction @@ -686,72 +1946,72 @@ package prim_secded_pkg; syndrome_o[4] = ^(in & 72'h1001FFFE0003FFF800); syndrome_o[5] = ^(in & 72'h2001FFFFFFFC000000); syndrome_o[6] = ^(in & 72'h40FE00000000000000); - syndrome_o[7] = ^(in & 72'hFFFFFFFFFFFFFFFFFF); + syndrome_o[7] = ^(in & 72'h80972CD2D32DA65CB7); // Corrected output calculation d_o[0] = (syndrome_o == 8'h83) ^ in[0]; d_o[1] = (syndrome_o == 8'h85) ^ in[1]; d_o[2] = (syndrome_o == 8'h86) ^ in[2]; - d_o[3] = (syndrome_o == 8'h87) ^ in[3]; + d_o[3] = (syndrome_o == 8'h7) ^ in[3]; d_o[4] = (syndrome_o == 8'h89) ^ in[4]; d_o[5] = (syndrome_o == 8'h8a) ^ in[5]; - d_o[6] = (syndrome_o == 8'h8b) ^ in[6]; + d_o[6] = (syndrome_o == 8'hb) ^ in[6]; d_o[7] = (syndrome_o == 8'h8c) ^ in[7]; - d_o[8] = (syndrome_o == 8'h8d) ^ in[8]; - d_o[9] = (syndrome_o == 8'h8e) ^ in[9]; + d_o[8] = (syndrome_o == 8'hd) ^ in[8]; + d_o[9] = (syndrome_o == 8'he) ^ in[9]; d_o[10] = (syndrome_o == 8'h8f) ^ in[10]; d_o[11] = (syndrome_o == 8'h91) ^ in[11]; d_o[12] = (syndrome_o == 8'h92) ^ in[12]; - d_o[13] = (syndrome_o == 8'h93) ^ in[13]; + d_o[13] = (syndrome_o == 8'h13) ^ in[13]; d_o[14] = (syndrome_o == 8'h94) ^ in[14]; - d_o[15] = (syndrome_o == 8'h95) ^ in[15]; - d_o[16] = (syndrome_o == 8'h96) ^ in[16]; + d_o[15] = (syndrome_o == 8'h15) ^ in[15]; + d_o[16] = (syndrome_o == 8'h16) ^ in[16]; d_o[17] = (syndrome_o == 8'h97) ^ in[17]; d_o[18] = (syndrome_o == 8'h98) ^ in[18]; - d_o[19] = (syndrome_o == 8'h99) ^ in[19]; - d_o[20] = (syndrome_o == 8'h9a) ^ in[20]; + d_o[19] = (syndrome_o == 8'h19) ^ in[19]; + d_o[20] = (syndrome_o == 8'h1a) ^ in[20]; d_o[21] = (syndrome_o == 8'h9b) ^ in[21]; - d_o[22] = (syndrome_o == 8'h9c) ^ in[22]; + d_o[22] = (syndrome_o == 8'h1c) ^ in[22]; d_o[23] = (syndrome_o == 8'h9d) ^ in[23]; d_o[24] = (syndrome_o == 8'h9e) ^ in[24]; - d_o[25] = (syndrome_o == 8'h9f) ^ in[25]; + d_o[25] = (syndrome_o == 8'h1f) ^ in[25]; d_o[26] = (syndrome_o == 8'ha1) ^ in[26]; d_o[27] = (syndrome_o == 8'ha2) ^ in[27]; - d_o[28] = (syndrome_o == 8'ha3) ^ in[28]; + d_o[28] = (syndrome_o == 8'h23) ^ in[28]; d_o[29] = (syndrome_o == 8'ha4) ^ in[29]; - d_o[30] = (syndrome_o == 8'ha5) ^ in[30]; - d_o[31] = (syndrome_o == 8'ha6) ^ in[31]; + d_o[30] = (syndrome_o == 8'h25) ^ in[30]; + d_o[31] = (syndrome_o == 8'h26) ^ in[31]; d_o[32] = (syndrome_o == 8'ha7) ^ in[32]; d_o[33] = (syndrome_o == 8'ha8) ^ in[33]; - d_o[34] = (syndrome_o == 8'ha9) ^ in[34]; - d_o[35] = (syndrome_o == 8'haa) ^ in[35]; + d_o[34] = (syndrome_o == 8'h29) ^ in[34]; + d_o[35] = (syndrome_o == 8'h2a) ^ in[35]; d_o[36] = (syndrome_o == 8'hab) ^ in[36]; - d_o[37] = (syndrome_o == 8'hac) ^ in[37]; + d_o[37] = (syndrome_o == 8'h2c) ^ in[37]; d_o[38] = (syndrome_o == 8'had) ^ in[38]; d_o[39] = (syndrome_o == 8'hae) ^ in[39]; - d_o[40] = (syndrome_o == 8'haf) ^ in[40]; + d_o[40] = (syndrome_o == 8'h2f) ^ in[40]; d_o[41] = (syndrome_o == 8'hb0) ^ in[41]; - d_o[42] = (syndrome_o == 8'hb1) ^ in[42]; - d_o[43] = (syndrome_o == 8'hb2) ^ in[43]; + d_o[42] = (syndrome_o == 8'h31) ^ in[42]; + d_o[43] = (syndrome_o == 8'h32) ^ in[43]; d_o[44] = (syndrome_o == 8'hb3) ^ in[44]; - d_o[45] = (syndrome_o == 8'hb4) ^ in[45]; + d_o[45] = (syndrome_o == 8'h34) ^ in[45]; d_o[46] = (syndrome_o == 8'hb5) ^ in[46]; d_o[47] = (syndrome_o == 8'hb6) ^ in[47]; - d_o[48] = (syndrome_o == 8'hb7) ^ in[48]; - d_o[49] = (syndrome_o == 8'hb8) ^ in[49]; + d_o[48] = (syndrome_o == 8'h37) ^ in[48]; + d_o[49] = (syndrome_o == 8'h38) ^ in[49]; d_o[50] = (syndrome_o == 8'hb9) ^ in[50]; d_o[51] = (syndrome_o == 8'hba) ^ in[51]; - d_o[52] = (syndrome_o == 8'hbb) ^ in[52]; + d_o[52] = (syndrome_o == 8'h3b) ^ in[52]; d_o[53] = (syndrome_o == 8'hbc) ^ in[53]; - d_o[54] = (syndrome_o == 8'hbd) ^ in[54]; - d_o[55] = (syndrome_o == 8'hbe) ^ in[55]; + d_o[54] = (syndrome_o == 8'h3d) ^ in[54]; + d_o[55] = (syndrome_o == 8'h3e) ^ in[55]; d_o[56] = (syndrome_o == 8'hbf) ^ in[56]; d_o[57] = (syndrome_o == 8'hc1) ^ in[57]; d_o[58] = (syndrome_o == 8'hc2) ^ in[58]; - d_o[59] = (syndrome_o == 8'hc3) ^ in[59]; + d_o[59] = (syndrome_o == 8'h43) ^ in[59]; d_o[60] = (syndrome_o == 8'hc4) ^ in[60]; - d_o[61] = (syndrome_o == 8'hc5) ^ in[61]; - d_o[62] = (syndrome_o == 8'hc6) ^ in[62]; + d_o[61] = (syndrome_o == 8'h45) ^ in[61]; + d_o[62] = (syndrome_o == 8'h46) ^ in[62]; d_o[63] = (syndrome_o == 8'hc7) ^ in[63]; // err_o calc. bit0: single error, bit1: double error diff --git a/run_ecc_tests.sh b/run_ecc_tests.sh new file mode 100755 index 00000000..a1acb912 --- /dev/null +++ b/run_ecc_tests.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 ETH Zurich, 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. +# +# Testing script for redundancy cells + +set -e + +[ ! -z "$VSIM" ] || VSIM=vsim + +# Test Settings +VSIM_LOGFILE=vsim.log +MAX_DATA_WIDTH=502 +RunCycles=100 +Codes=("0 0 NoECC" "0 1 SED-Parity" "1 0 SEC-Hamming" "0 2 DED-Hamming" "1 2 SECDED-Hsiao" "0 3 TED-Hsiao") +num_codes=${#Codes[@]} + +# Remove the old logfile +rm -f $VSIM_LOGFILE + +# Compile the Testbench +echo "Compiling Testbench..." +bender script vsim -t test -t rtl > compile.tcl +"$VSIM" -c -do 'source compile.tcl; quit' >> $VSIM_LOGFILE 2>&1 +tail -3 $VSIM_LOGFILE +echo "" + +# Test Encode and Decode +echo "Testing Encode and Decode" +test_nr=0 +num_tests=$num_codes + +for i in $(seq 0 $((num_codes-1))) +do + Code=${Codes[i]} + ECC_Params=( $Code ); + NumErrorCorrect=${ECC_Params[0]}; + NumErrorDetect=${ECC_Params[1]}; + CodeName=${ECC_Params[2]} + + ((++test_nr)) + echo "Testing Code: $CodeName ($test_nr of $num_tests)" + echo "run -all; quit" | vsim -voptargs=+acc -c -GMaxDataWidth=$MAX_DATA_WIDTH -GNumErrorCorrect=$NumErrorCorrect -GNumErrorDetect=$NumErrorDetect -GRunCycles=$RunCycles tb_ecc_enc_cor_multi >> $VSIM_LOGFILE 2>&1 + tail -4 $VSIM_LOGFILE + echo "" +done + +echo "Testing ECC protected FFs" +test_nr=0 +num_tests=$((2*2*2*num_codes)) +for SelfCorrect in 0 1 +do + for Encode in 0 1 + do + for Decode in 0 1 + do + for i in $(seq 0 $((num_codes-1))) + do + Code=${Codes[i]} + ECC_Params=( $Code ); + NumErrorCorrect=${ECC_Params[0]}; + NumErrorDetect=${ECC_Params[1]}; + CodeName=${ECC_Params[2]} + + ((++test_nr)) + echo "Testing Code: $CodeName, Decode=$Decode, Encode=$Encode, SelfCorrect=$SelfCorrect ($test_nr of $num_tests)" + vsim -c -voptargs=+acc -GMaxDataWidth=$MAX_DATA_WIDTH -GNumErrorCorrect=$NumErrorCorrect -GNumErrorDetect=$NumErrorDetect -GDecode=$Decode -GEncode=$Encode -GSelfCorrect=$SelfCorrect -GRunCycles=$RunCycles tb_ecc_reg_multi -do test_run.tcl >> $VSIM_LOGFILE 2>&1 + + echo "DataWidth=$DataWidth, Code=$CodeName, " + tail -4 $VSIM_LOGFILE + echo "" + done + done + done +done + +echo "Finished ECC testing" diff --git a/run_tests.sh b/run_tests.sh index 9deda23a..3c60127c 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -9,7 +9,7 @@ # 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. -# +# # Testing script for redundancy cells set -e @@ -45,4 +45,7 @@ call_vsim -GDataWidth=8 tb_ecc_secded call_vsim -GDataWidth=16 tb_ecc_secded call_vsim -GDataWidth=32 tb_ecc_secded call_vsim -GDataWidth=64 tb_ecc_secded +call_vsim tb_dmr_handshake_fork +call_vsim tb_dmr_handshake_join +call_vsim tb_dmr_handshake_fork_join_fork call_vsim tb_ecc_scrubber diff --git a/run_tmr_reg_tests.sh b/run_tmr_reg_tests.sh new file mode 100755 index 00000000..fcfba9b9 --- /dev/null +++ b/run_tmr_reg_tests.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 ETH Zurich, 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. +# +# Testing script for redundancy cells + +set -e + +[ ! -z "$VSIM" ] || VSIM=vsim + +# Test Settings +VSIM_LOGFILE=vsim.log +RunCycles=100 + +# Remove the old logfile +rm -f $VSIM_LOGFILE + +# Compile the Testbench +echo "Compiling Testbench..." +bender script vsim -t test -t rtl > compile.tcl +"$VSIM" -c -do 'source compile.tcl; quit' >> $VSIM_LOGFILE 2>&1 +tail -3 $VSIM_LOGFILE +echo "" + +echo "Testing TMR protected FFs" + +for data_width in 1 2 4 8 16 32 64 +do + echo "Testing Data Width $data_width" + vsim -voptargs=+acc -GDataWidth=$data_width tb_tmr_reg -do 'log -r /*; do test/tmr_reg_fault_injection.tcl; run -a; quit' >> $VSIM_LOGFILE 2>&1 + + echo "DataWidth=$data_width:" + tail -3 $VSIM_LOGFILE + echo "" +done + +echo "Finished TMR Reg testing" diff --git a/test/dmr/dmr_handshake.sv b/test/dmr/dmr_handshake.sv new file mode 100644 index 00000000..39312625 --- /dev/null +++ b/test/dmr/dmr_handshake.sv @@ -0,0 +1,204 @@ +// Copyright 2023 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: Luca Rufer + +// This file contains a handshaked data source and a handshaked data sink, +// that are designed to be used togehter in testbenches for DMR circuits. +// These modules are similar to the 'rand_stream' modules provided in the +// 'common verification' repo, with two main differences important for testing +// DMR circutis: +// 1. The data this source provides is deterministic and implemented as a +// counter starting at 0. This allows to quickly find dropped and repeated +// transactions, as well as out-of-order arrival. This is automatically +// checked at the sink. +// 2. The modules have an input to allow (and ignore) handshakes. This can be +// helpful in circuits (like DMR protected circuits) where a data +// transaction cannot be completed even tough the handshake was completed +// (due to errors in the state or somewhere else in the circuit). + +module handshake_source #( + parameter int unsigned DATA_BITS = 0, + parameter bit WARN_NEXT_ITEM_OVERRUN = 0 + ) ( + // clock and reset + input logic clk_i, + input logic rst_ni, + // control signals + input logic next_item_i, + input logic allow_handshake_i, + // data + output logic valid_o, + input logic ready_i, + output logic [DATA_BITS-1:0] data_o + ); + + // Signals + logic [DATA_BITS-1:0] data_d, data_q; + logic valid_d, valid_q; + logic handshake_complete; + + // assignments + assign data_o = data_q; + assign valid_o = valid_q; + assign handshake_complete = allow_handshake_i & valid_o & ready_i; + + always_comb begin + // default + data_d = data_q; + valid_d = valid_q; + + // check if handshake complete + if(handshake_complete) begin + valid_d = 1'b0; + data_d = data_q + 1; + end + + // Next item in the next cycle + if(next_item_i) begin + valid_d = 1'b1; + end + end + + // State + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + data_q <= '0; + valid_q <= '0; + end else begin + data_q <= data_d; + valid_q <= valid_d; + end + end + + `ifndef VERILATOR + // pragma translate_off + // Warnings + assert property (@(posedge clk_i) disable iff (~rst_ni) + ( data_q != 0 |-> data_d != 0)) else + $warning("[Handshake Source] data_o overflow!"); + if(WARN_NEXT_ITEM_OVERRUN) begin + assert property (@(posedge clk_i) disable iff (~rst_ni) + ( next_item_i |-> ((valid_o & ready_i) | ~valid_o))) else + $warning("[Handshake Source] next_item overrun!"); + end + + // Assertions (external checks) + assert property (@(posedge clk_i) disable iff (~rst_ni) + (( ready_i & ~valid_o ) |=> ready_i)) else + $error("[Handshake Source] ready revoked before handshake completed."); + + // Assertions (internal checks) + assert property (@(posedge clk_i) disable iff (~rst_ni) + (~ready_i & valid_o ) |=> valid_o) else + $error("[Handshake Source] valid revoked before handshake completed."); + assert property (@(posedge clk_i) disable iff (~rst_ni) + (~ready_i & valid_o ) |=> $stable(data_o)) else + $error("[Handshake Source] data changed before handshake completed."); + + // pragma translate_on + `endif + + endmodule + + module handshake_sink #( + parameter int unsigned DATA_BITS = 0 + ) ( + // clock and reset + input logic clk_i, + input logic rst_ni, + // control signals + input logic raise_ready_i, + input logic allow_sink_i, + // data + input logic valid_i, + output logic ready_o, + input logic [DATA_BITS-1:0] data_i, + // testbench + output logic [DATA_BITS-1:0] next_expected_o, + output logic [DATA_BITS-1:0] num_received_o + ); + + // Signals + logic ready_d, ready_q; + logic handshake_complete; + + // assignments + assign ready_o = ready_q; + assign handshake_complete = allow_sink_i & valid_i & ready_o; + + always_comb begin + // default + ready_d = ready_q; + + // check if handshake complete + if(handshake_complete) begin + ready_d = 1'b0; + end + + // Next item in the next cycle + if(raise_ready_i) begin + ready_d = 1'b1; + end + end + + // State + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + ready_q <= '0; + end else begin + ready_q <= ready_d; + end + end + + // testbench only + time last_consumed; + logic [DATA_BITS-1:0] data_expected; + logic [DATA_BITS-1:0] num_received; + + initial begin + last_consumed = 0; + data_expected = 0; + num_received = 0; + forever begin + @(posedge clk_i); + if(handshake_complete) begin + num_received++; + if(data_i > data_expected) begin + $error("[Handshake Sink] received %0d, expected %0d. %0d Data Items were skipped. Last item consumed at %0t", + data_i, data_expected, $signed(data_i)-$signed(data_expected), last_consumed); + end else if (data_i < data_expected) begin + $error("[Handshake Sink] received %0d, expected %0d. Data Item was repeated or out of order. Last item consumed at %0t", + data_i, data_expected, last_consumed); + end + last_consumed = $time; + data_expected = data_i + 1; + end + end + end + + assign next_expected_o = data_expected; + assign num_received_o = num_received; + + // Assertions (internal checks) + assert property (@(posedge clk_i) disable iff (~rst_ni) + ( ready_o & ~valid_i ) |=> ready_o) else + $error("[Handshake Sink] ready revoked before handshake completed."); + + // Assertions (external checks) + assert property (@(posedge clk_i) disable iff (~rst_ni) + ( ~ready_o & valid_i ) |=> valid_i) else + $error("[Handshake Sink] valid revoked before handshake completed."); + assert property (@(posedge clk_i) disable iff (~rst_ni) + ( ~ready_o & valid_i ) |=> $stable(data_i)) else + $error("[Handshake Sink] data changed before handshake completed."); + + endmodule diff --git a/test/ecc_reg_fault_injection.tcl b/test/ecc_reg_fault_injection.tcl new file mode 100644 index 00000000..70386c72 --- /dev/null +++ b/test/ecc_reg_fault_injection.tcl @@ -0,0 +1,11 @@ + +set MaxDataWidth [examine -radix dec sim:/tb_ecc_reg_multi/MaxDataWidth] + +when { sim:/tb_ecc_reg_multi/gen_dut[1]/i_dut/clk == 1'b0 } { + for {set dw 1} {$dw <= $MaxDataWidth} {incr dw} { + set val [examine sim:/tb_ecc_reg_multi/gen_dut[$dw]/i_dut/i_dut/data_q] + set inject_val [examine sim:/tb_ecc_reg_multi/gen_dut[$dw]/i_dut/inject_val] + force -deposit sim:/tb_ecc_reg_multi/gen_dut[$dw]/i_dut/i_dut/data_q $inject_val + #echo "Flipped $val to $inject_val" + } +} diff --git a/test/tb_dmr_handshake_fork.sv b/test/tb_dmr_handshake_fork.sv new file mode 100644 index 00000000..88ca395d --- /dev/null +++ b/test/tb_dmr_handshake_fork.sv @@ -0,0 +1,374 @@ +// Copyright 2023 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: Luca Rufer + +module tb_dmr_handshake_fork; + + // Time Settings + timeunit 1ns; + timeprecision 1ps; + + // Number of outputs + localparam int NUM_OUT = 2; + localparam int DATA_BITS = 16; + + /********************** + * Clock and Timing * + **********************/ + + // Timing parameters + localparam ClockPeriod = 1ns; + localparam TApply = 0.2ns; + localparam TTest = 0.8ns; + + // clock and reset + logic clk; + logic rst_n; + + // Clock + always #(ClockPeriod/2) clk = !clk; + + // Reset + initial begin + clk = 1'b1; + rst_n = 1'b0; + repeat (5) + #(ClockPeriod); + rst_n = 1'b1; + end + + /************************ + * Stimuli generation * + ************************/ + + // data type + typedef logic [DATA_BITS-1:0] data_t; + + class stimuli_t; + // Constants + static const bit [NUM_OUT-1:0] all_ones = {NUM_OUT{1'b1}}; + + // signals + rand bit error_before; + rand bit error_after; + + rand bit [NUM_OUT-1:0] ready_flip; + rand bit raise_valid; + + // fixed constraints + constraint save_flip { ready_flip == all_ones -> error_before == 1'b1;} + + // constraints disabled during tests + constraint no_error { error_before == 1'b0 && error_after == 1'b0 && ready_flip == '0;} + constraint synchronous { ready_flip inside {'0, all_ones};} + constraint always_ready { ready_flip == '0;} + constraint always_valid { raise_valid == 1'b1;} + + // distribution constraints + constraint ready_dist { ready_flip dist { '0 :/ 1, + [('b1):(all_ones-1)] :/ 1, + all_ones :/ 1};} + constraint error_dist { + error_before dist { 1'b0 := 3, 1'b1 := 1}; + error_after dist { 1'b0 := 3, 1'b1 := 1}; + } + + endclass + + // stimuli queue + stimuli_t stimuli_queue [$]; + + // result type + typedef struct packed { + bit error; + } expected_result_t; + + expected_result_t golden_queue [$]; + + stimuli_t all_ready_stimuli; + expected_result_t no_error_result; + + function automatic void generate_stimuli(); + // create default stimuli and results + // default stimuli to retrieve buffered items + all_ready_stimuli = new; + all_ready_stimuli.error_before = '0; + all_ready_stimuli.error_after = '0; + all_ready_stimuli.raise_valid = '0; + all_ready_stimuli.ready_flip = '0; + // default result to retrieve buffered items + no_error_result = '{ error: '0 }; + + // 1st phase: check maximum throughput with no errors & no repeats + for (int i = 0; i < 10; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{error: '0}); + + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_ready_stimuli); + golden_queue.push_back(no_error_result); + end + + // 2nd phase: do random testing, no errors, no repeats + for (int i = 0; i < 50; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // disable unused constraints + stimuli.always_ready.constraint_mode(0); + stimuli.always_valid.constraint_mode(0); + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{error: '0}); + + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_ready_stimuli); + golden_queue.push_back(no_error_result); + end + + // 3rd phase: do completely random testing + for (int i = 0; i < 1000; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // disable unused constraints + stimuli.no_error.constraint_mode(0); + stimuli.synchronous.constraint_mode(0); + stimuli.always_ready.constraint_mode(0); + stimuli.always_valid.constraint_mode(0); + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{error: !(~|ready_in | &ready_in)}); + + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_ready_stimuli); + golden_queue.push_back(no_error_result); + end + endfunction : generate_stimuli + + /******************* + * apply stimuli * + *******************/ + + // control signals + logic error_before, error_after, fork_error; + logic raise_valid; + logic no_error; + + // Data input side + data_t data_in; + logic valid_in, ready_out; + + // Data output side + data_t [NUM_OUT-1:0] data_out; + logic [NUM_OUT-1:0] ready_in, valid_out, ready_in_flip; + + // Testbench check signals + data_t [NUM_OUT-1:0] sink_expected, sink_received; + + task automatic apply_stimuli(); + automatic stimuli_t stimuli; + // get the next stimuli + wait (stimuli_queue.size() != '0); + stimuli = stimuli_queue.pop_front(); + // Wait for apply time + @(posedge clk); + #(TApply); + // apply stimuli + // only update ready in signals if the prev cycle had no error_after + if(error_after) begin + ready_in_flip = ready_in; + end else begin + ready_in_flip = ready_in ^ stimuli.ready_flip; + end + error_before = stimuli.error_before; + raise_valid = stimuli.raise_valid; + error_after = stimuli.error_after; + endtask : apply_stimuli + + assign no_error = !error_before & !error_after & !fork_error; + + /*********************** + * Device Under Test * + ***********************/ + + // source + handshake_source #( + .DATA_BITS ( DATA_BITS ) + ) i_source ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .next_item_i ( raise_valid ), + .allow_handshake_i ( 1'b1 ), + .valid_o ( valid_in ), + .ready_i ( ready_out ), + .data_o ( data_in ) + ); + + // dut + dmr_handshake_fork #( + .T ( data_t ), + .NUM_OUT ( NUM_OUT ) + ) i_dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .enable_i ( 1'b1 ), + .error_before_i ( error_before ), + .error_after_i ( error_after ), + .error_o ( fork_error ), + .valid_i ( valid_in ), + .ready_o ( ready_out ), + .data_i ( data_in ), + .valid_o ( valid_out ), + .ready_i ( ready_in_flip ), + .data_o ( data_out ) + ); + + // sinks + for(genvar i = 0; i < NUM_OUT; i++) begin : gen_sink + handshake_sink #( + .DATA_BITS ( DATA_BITS ) + ) i_sink ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .raise_ready_i ( 1'b1 ), + .allow_sink_i ( no_error ), + .valid_i ( valid_out[i] ), + .ready_o ( ready_in[i] ), + .data_i ( data_out[i] ), + .next_expected_o ( sink_expected[i] ), + .num_received_o ( sink_received[i] ) + ); + end + + /*********************** + * Output collection * + ***********************/ + + typedef struct packed { + bit error; + bit ready_out; + bit valid_out; + bit [NUM_OUT-1:0] received_data; + data_t [NUM_OUT-1:0] data; + } result_t; + + result_t result_queue [$]; + + task automatic collect_result; + result_t result; + // wait for test time + @(posedge clk) + #(TTest); + // collect the results + result.error = fork_error; + result.ready_out = ready_out; + result.valid_out = &valid_out; + result.received_data = valid_out & ready_in & {NUM_OUT{~(fork_error | error_before | error_after)}}; + result.data = data_out; + result_queue.push_back(result); + endtask : collect_result + + /************* + * Checker * + *************/ + + task automatic check_result; + automatic result_t result; + automatic expected_result_t golden; + + do begin + wait(result_queue.size() != 0); + + // extract the result + result = result_queue.pop_front(); + golden = golden_queue.pop_front(); + + // compare the results + if(golden.error & !result.error) + $error("[Error] Error injected in outgoing handshake not detected."); + end while (golden_queue.size() != 0); + + for(int unsigned i = 0; i < NUM_OUT; i++) begin + if(data_in != sink_received[i]) begin + $error("[Data Error] Sent %d items, sink %d, received %d items.", data_in, i, sink_received[i]); + end + end + endtask : check_result + + // Error assertions + assert property (@(posedge clk) disable iff (~rst_n) ((error_before | error_after) & &valid_out |=> $stable(data_out))) else begin + $error("[Data Repetition] Data was not repeated after error."); + end + + // make sure output signals are consitent over all outputs + for (genvar i = 0; i < NUM_OUT; i++) begin + assert property(@(posedge clk) disable iff (~rst_n) (data_out[i] == data_out[0])) else begin + $error("[Output Data Mismatch] [OUT%d] reads %d, [OUT0] reads %d", i, data_out[i], data_out[0]); + end + assert property(@(posedge clk) disable iff (~rst_n) (valid_out[i] == valid_out[0])) else begin + $error("[Output Valid Mismatch] [OUT%d] reads %b, [OUT0] reads %b", i, valid_out[i], valid_out[0]); + end + end + + task run_apply(); + forever begin + apply_stimuli(); + end + endtask : run_apply + + task run_collect(); + forever begin + collect_result(); + end + endtask : run_collect + + initial begin : tb + // Initialize variables + error_after = '0; + error_before = '0; + raise_valid = '0; + + @(posedge rst_n) + repeat(10) @(posedge clk); + + fork + run_apply(); + run_collect(); + fork + generate_stimuli(); + check_result(); + join + join_any + + $display("[Testbench] Transmitted %0d Data Items.", data_in); + $display("[Testbench] Done."); + $finish(0); + end : tb + +endmodule diff --git a/test/tb_dmr_handshake_fork_join_fork.sv b/test/tb_dmr_handshake_fork_join_fork.sv new file mode 100644 index 00000000..4026b3ad --- /dev/null +++ b/test/tb_dmr_handshake_fork_join_fork.sv @@ -0,0 +1,535 @@ +// Copyright 2023 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: Luca Rufer + +// Test a series combination of a fork, join and fork handshake module +// to check if the combination fork-join and join-fork are compatible. + +module tb_dmr_handshake_fork_join_fork; + + // Time Settings + timeunit 1ns; + timeprecision 1ps; + + // Number of outputs + localparam int NUM_IN_OUT = 2; + localparam int DATA_BITS = 16; + + /********************** + * Clock and Timing * + **********************/ + + // Timing parameters + localparam ClockPeriod = 1ns; + localparam TApply = 0.2ns; + localparam TTest = 0.8ns; + + // clock and reset + logic clk; + logic rst_n; + + // Clock + always #(ClockPeriod/2) clk = !clk; + + // Reset + initial begin + clk = 1'b1; + rst_n = 1'b0; + repeat (5) + #(ClockPeriod); + rst_n = 1'b1; + end + + /************************ + * Stimuli generation * + ************************/ + + // data type + typedef logic [DATA_BITS-1:0] data_t; + + class stimuli_t; + // constants + static const bit [NUM_IN_OUT-1:0] all_ones = {NUM_IN_OUT{1'b1}}; + + // non-random siganls + static stimuli_t prev = null; + bit any_error_injected; + + // signals + rand bit raise_valid; + rand bit flip_ready_0_F; + rand bit flip_ready_0_CB; + rand bit flip_valid_0_BC; + rand data_t flip_data_0_BC; + rand bit pretend_error_before; + rand bit pretend_error_BC; + rand bit pretend_error_F; + rand bit pretend_error_CB; + rand bit pretend_error_after; + + // constraints disabled during tests + constraint no_error { + !flip_ready_0_F & + !flip_ready_0_CB & + !flip_valid_0_BC & + (flip_data_0_BC == '0) & + !pretend_error_before & + !pretend_error_BC & + !pretend_error_F & + !pretend_error_CB & + !pretend_error_after; + } + constraint always_ready { + !flip_ready_0_F & + !flip_ready_0_CB & + !flip_valid_0_BC; + } + constraint always_valid { + raise_valid == 1'b1; + } + + // only allow errors to propagate forwards + // data flips are ignored as they do not always cause an error + constraint forward_prop_only { + if(prev != null && prev.any_error_injected) { + !prev.pretend_error_before -> !pretend_error_before; + !prev.pretend_error_before & + !prev.pretend_error_BC -> !pretend_error_BC; + !prev.pretend_error_before & + !prev.pretend_error_BC & + !prev.flip_valid_0_BC -> !flip_valid_0_BC; + !prev.pretend_error_before & + !prev.pretend_error_BC & + !prev.flip_valid_0_BC & + !prev.flip_data_0_BC -> !flip_data_0_BC; + !prev.pretend_error_before & + !prev.pretend_error_BC & + !prev.flip_valid_0_BC & + !prev.pretend_error_F -> !pretend_error_F; + !prev.pretend_error_before & + !prev.pretend_error_BC & + !prev.flip_valid_0_BC & + !prev.pretend_error_F & + !prev.flip_ready_0_F -> !flip_ready_0_F; + !prev.pretend_error_before & + !prev.pretend_error_BC & + !prev.flip_valid_0_BC & + !prev.pretend_error_F & + !prev.flip_ready_0_F & + !prev.pretend_error_CB -> !pretend_error_CB; + !prev.pretend_error_before & + !prev.pretend_error_BC & + !prev.flip_valid_0_BC & + !prev.pretend_error_F & + !prev.flip_ready_0_F & + !prev.pretend_error_CB & + !prev.flip_ready_0_CB -> !flip_ready_0_CB; + !prev.pretend_error_before & + !prev.pretend_error_BC & + !prev.flip_valid_0_BC & + !prev.pretend_error_F & + !prev.flip_ready_0_F & + !prev.pretend_error_CB & + !prev.flip_ready_0_CB & + !prev.pretend_error_after -> !pretend_error_after; + } + } + + // distribution constraints + constraint error_dist { + flip_ready_0_F dist { 1'b0 := 4, 1'b1 := 1}; + flip_ready_0_CB dist { 1'b0 := 4, 1'b1 := 1}; + flip_valid_0_BC dist { 1'b0 := 4, 1'b1 := 1}; + pretend_error_before dist { 1'b0 := 4, 1'b1 := 1}; + pretend_error_BC dist { 1'b0 := 4, 1'b1 := 1}; + pretend_error_F dist { 1'b0 := 4, 1'b1 := 1}; + pretend_error_CB dist { 1'b0 := 4, 1'b1 := 1}; + pretend_error_after dist { 1'b0 := 4, 1'b1 := 1}; + } + constraint d_error_dist { + flip_data_0_BC dist { '0 :/ 4, [('b1):all_ones] :/ 1}; + } + + function void post_randomize (); + any_error_injected = + flip_ready_0_F | + flip_ready_0_CB | + flip_valid_0_BC | + |flip_data_0_BC | + pretend_error_before | + pretend_error_BC | + pretend_error_F | + pretend_error_CB | + pretend_error_after; + + // override stimuli + prev = this; + endfunction + + endclass + + // stimuli queue + stimuli_t stimuli_queue [$]; + + // result type + typedef struct packed { + bit error; + } result_t; + + result_t golden_queue [$]; + + stimuli_t all_ready_stimuli; + result_t no_error_result; + + function automatic void generate_stimuli(); + // create default stimuli and results + // default stimuli to retrieve buffered items + all_ready_stimuli = new; + if (!all_ready_stimuli.randomize()) $error("Could not randomize."); + // default result to retrieve buffered items + no_error_result = '{ error: '0 }; + + // 1st phase: check maximum throughput with no errors & no repeats + for (int i = 0; i < 10; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{error: '0}); + + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_ready_stimuli); + golden_queue.push_back(no_error_result); + end + + // 2nd phase: do random testing, no errors, no repeats + for (int i = 0; i < 50; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // disable unused constraints + stimuli.always_ready.constraint_mode(0); + stimuli.always_valid.constraint_mode(0); + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{error: '0}); + + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_ready_stimuli); + golden_queue.push_back(no_error_result); + end + + // 3rd phase: do completely random testing + for (int i = 0; i < 1000; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // disable unused constraints + stimuli.no_error.constraint_mode(0); + stimuli.always_ready.constraint_mode(0); + stimuli.always_valid.constraint_mode(0); + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{error: stimuli.any_error_injected }); + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_ready_stimuli); + golden_queue.push_back(no_error_result); + end + endfunction : generate_stimuli + + /******************* + * apply stimuli * + *******************/ + + // Single-side signals + logic valid_A, valid_D, valid_E; + logic ready_A, ready_D, ready_E; + data_t data_A, data_D, data_E; + + // DMR-side signals + logic [NUM_IN_OUT-1:0] valid_B, valid_C, valid_F; + logic [NUM_IN_OUT-1:0] ready_B, ready_C, ready_F; + data_t [NUM_IN_OUT-1:0] data_B, data_C, data_F; + + // Injection signals + logic flip_valid_0_BC; + data_t flip_data_0_BC; + logic flip_ready_0_F; + logic flip_ready_0_CB; + + // Pretended Error signals + logic pretend_error_before; + logic pretend_error_BC; + logic pretend_error_F; + logic pretend_error_CB; + logic pretend_error_after; + + // Fork and join control signals + logic error_before_AB, error_before_CD, error_before_EF; + logic error_out_AB, error_out_CD, error_out_EF; + logic error_after_AB, error_after_CD, error_after_EF; + + // Source and sink signals + logic raise_valid; + logic [NUM_IN_OUT-1:0] raise_ready; + logic [NUM_IN_OUT-1:0] sink_ready; + logic no_error; + + // Testbench check signals + data_t [NUM_IN_OUT-1:0] sink_expected, sink_received; + + // initialize TB signals + initial begin + flip_ready_0_F = '0; + flip_ready_0_CB = '0; + raise_valid = '0; + flip_valid_0_BC = '0; + flip_data_0_BC = '0; + pretend_error_before = '0; + pretend_error_BC = '0; + pretend_error_F = '0; + pretend_error_CB = '0; + pretend_error_after = '0; + end + + task automatic apply_stimuli(); + automatic stimuli_t stimuli; + + // Get the next stimuli + wait (stimuli_queue.size() != '0); + stimuli = stimuli_queue.pop_front(); + + // Wait for apply time + @(posedge clk); + #(TApply); + + // apply stimuli + flip_ready_0_F = stimuli.flip_ready_0_F; + flip_ready_0_CB = stimuli.flip_ready_0_CB; + raise_valid = stimuli.raise_valid; + flip_valid_0_BC = stimuli.flip_valid_0_BC; + flip_data_0_BC = stimuli.flip_data_0_BC; + pretend_error_before = stimuli.pretend_error_before; + pretend_error_BC = stimuli.pretend_error_BC; + pretend_error_F = stimuli.pretend_error_F; + pretend_error_CB = stimuli.pretend_error_CB; + pretend_error_after = stimuli.pretend_error_after; + + endtask : apply_stimuli + + /*********************** + * Device Under Test * + ***********************/ + + // source + handshake_source #( + .DATA_BITS ( DATA_BITS ) + ) i_source ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .next_item_i ( raise_valid ), + .allow_handshake_i ( 1'b1 ), + .valid_o ( valid_A ), + .ready_i ( ready_A ), + .data_o ( data_A ) + ); + + // Fork AB + dmr_handshake_fork #( + .T ( data_t ), + .NUM_OUT ( NUM_IN_OUT ) + ) i_dut_fork_AB ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .enable_i ( 1'b1 ), + .error_before_i ( error_before_AB ), + .error_after_i ( error_after_AB ), + .error_o ( error_out_AB ), + .valid_i ( valid_A ), + .ready_o ( ready_A ), + .data_i ( data_A ), + .valid_o ( valid_B ), + .ready_i ( ready_B ), + .data_o ( data_B ) + ); + + // Fault injection BC + assign valid_C[0] = valid_B[0] ^ flip_valid_0_BC; + assign data_C[0] = data_B[0] ^ flip_data_0_BC; + assign ready_B[0] = ready_C[0] ^ flip_ready_0_CB; + // Assign unflipped signals + assign valid_C[NUM_IN_OUT-1:1] = valid_B[NUM_IN_OUT-1:1]; + assign data_C[NUM_IN_OUT-1:1] = data_B[NUM_IN_OUT-1:1]; + assign ready_B[NUM_IN_OUT-1:1] = ready_C[NUM_IN_OUT-1:1]; + + // Join CD + dmr_handshake_join #( + .T ( data_t ), + .NUM_IN ( NUM_IN_OUT ) + ) i_dut_join_CD ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .enable_i ( 1'b1 ), + .error_before_i ( error_before_CD ), + .error_after_i ( error_after_CD ), + .error_o ( error_out_CD ), + .valid_i ( valid_C ), + .ready_o ( ready_C ), + .data_i ( data_C ), + .valid_o ( valid_D ), + .ready_i ( ready_D ), + .data_o ( data_D ) + ); + + // assign unflipped signals DE + assign valid_E = valid_D; + assign data_E = data_D; + assign ready_D = ready_E; + + // Fork EF + dmr_handshake_fork #( + .T ( data_t ), + .NUM_OUT ( NUM_IN_OUT ) + ) i_dut_fork_EF ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .enable_i ( 1'b1 ), + .error_before_i ( error_before_EF ), + .error_after_i ( error_after_EF ), + .error_o ( error_out_EF ), + .valid_i ( valid_E ), + .ready_o ( ready_E ), + .data_i ( data_E ), + .valid_o ( valid_F ), + .ready_i ( ready_F ), + .data_o ( data_F ) + ); + + // make ready signal depend on valid + assign raise_ready = valid_F; + + assign ready_F[0] = sink_ready[0] ^ flip_ready_0_F; + assign ready_F[NUM_IN_OUT-1:1] = sink_ready[NUM_IN_OUT-1:1]; + + // Sinks + for(genvar i = 0; i < NUM_IN_OUT; i++) begin : gen_sink + handshake_sink #( + .DATA_BITS ( DATA_BITS ) + ) i_sink ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .raise_ready_i ( raise_ready[i] ), + .allow_sink_i ( no_error ), + .valid_i ( valid_F[i] ), + .ready_o ( sink_ready[i] ), + .data_i ( data_F[i] ), + .next_expected_o ( sink_expected[i] ), + .num_received_o ( sink_received[i] ) + ); + end + + // Error interconnect + assign no_error = ~(error_before_AB | error_before_CD | error_before_EF | error_out_AB | error_out_CD | error_out_EF | error_after_AB | error_after_CD | error_after_EF); + assign error_before_AB = pretend_error_before | pretend_error_BC | pretend_error_F | pretend_error_CB | error_out_CD | error_out_EF; + assign error_before_CD = pretend_error_before | pretend_error_BC; + assign error_before_EF = pretend_error_before | pretend_error_BC | pretend_error_F | error_out_CD; + assign error_after_AB = pretend_error_after; + assign error_after_CD = pretend_error_F | pretend_error_CB | error_out_EF | error_out_AB | pretend_error_after; + assign error_after_EF = pretend_error_CB | error_out_AB | pretend_error_after; + + /*********************** + * Output collection * + ***********************/ + + result_t result_queue [$]; + + task automatic collect_result; + result_t result; + // wait for test time + @(posedge clk) + #(TTest); + // collect the results (with manual flip data correction) + result.error = ~no_error | |flip_data_0_BC; + result_queue.push_back(result); + endtask : collect_result + + /************* + * Checker * + *************/ + + task automatic check_result; + automatic result_t result, golden; + + do begin + wait(result_queue.size() != 0); + + // extract the result + result = result_queue.pop_front(); + golden = golden_queue.pop_front(); + + // compare the results + if(golden != result) + $error("[Error] Injected Error not detected."); + end while (golden_queue.size() != 0); + + // Check if correct number of items received + for(int unsigned i = 0; i < NUM_IN_OUT; i++) begin + if(data_A != sink_received[i]) begin + $error("[Data Error] Sent %d items, sink %d, received %d items.", data_A, i, sink_received[i]); + end + end + endtask : check_result + + task run_apply(); + forever begin + apply_stimuli(); + end + endtask : run_apply + + task run_collect(); + forever begin + collect_result(); + end + endtask : run_collect + + initial begin : tb + + @(posedge rst_n) + repeat(10) @(posedge clk); + + fork + run_apply(); + run_collect(); + fork + generate_stimuli(); + check_result(); + join + join_any + + $display("[Testbench] Done. Transmitted %0d Data Items.", data_A); + $finish(0); + end : tb + +endmodule diff --git a/test/tb_dmr_handshake_join.sv b/test/tb_dmr_handshake_join.sv new file mode 100644 index 00000000..3aac1263 --- /dev/null +++ b/test/tb_dmr_handshake_join.sv @@ -0,0 +1,365 @@ +// Copyright 2023 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: Luca Rufer + +module tb_dmr_handshake_join; + + // Time Settings + timeunit 1ns; + timeprecision 1ps; + + // Number of outputs + localparam int NUM_IN = 2; + localparam int DATA_BITS = 16; + + /********************** + * Clock and Timing * + **********************/ + + // Timing parameters + localparam ClockPeriod = 1ns; + localparam TApply = 0.2ns; + localparam TTest = 0.8ns; + + // clock and reset + logic clk; + logic rst_n; + + // Clock + always #(ClockPeriod/2) clk = !clk; + + // Reset + initial begin + clk = 1'b1; + rst_n = 1'b0; + repeat (5) + #(ClockPeriod); + rst_n = 1'b1; + end + + /************************ + * Stimuli generation * + ************************/ + + logic sim_running; + + // data type + typedef logic [DATA_BITS-1:0] data_t; + + class stimuli_t; + // Constants + static const bit [NUM_IN-1:0] all_ones = {NUM_IN{1'b1}}; + + // signals + rand bit error_before; + rand bit error_after; + + rand bit gen_item; + rand bit [NUM_IN-1:0] valid_flip; + rand bit [NUM_IN-1:0] data_error; + rand data_t [NUM_IN-1:0] data_bitflips; + + rand bit raise_ready; + + // constraints disabled during tests + constraint no_error { error_before == 1'b0 && error_after == 1'b0 && valid_flip == '0;} + constraint no_data_error { data_error == '0;} + constraint synchronous { valid_flip inside {'0, all_ones};} + constraint always_ready { raise_ready == 1'b1;} + constraint always_valid { valid_flip == '0; gen_item == 1'b1; } + + // dependancy constraints + constraint correct_flip{ foreach(data_bitflips[i]) if(!data_error[i]) data_bitflips[i] == '0; + foreach(data_bitflips[i]) if( data_error[i]) data_bitflips[i] != '0;} + constraint not_all_flip{ error_before == '0 -> data_error != all_ones; + error_before == '0 -> valid_flip != all_ones;} + + // distribution constraints + constraint d_error_dist{ data_error dist { '0 :/ 4, [('b1):all_ones] :/ 1}; } + constraint valid_dist { valid_flip dist { '0 :/ 3, + [('b1):(all_ones-1)] :/ 1, + all_ones :/ 1}; + } + constraint error_dist { + error_before dist { 1'b0 := 3, 1'b1 := 1}; + error_after dist { 1'b0 := 3, 1'b1 := 1}; + } + constraint gen_item_dist {gen_item dist { 1'b0 := 3, 1'b1 := 1};} + endclass + + // stimuli queue + stimuli_t stimuli_queue [$]; + + stimuli_t all_valid_stimuli; + + function automatic void generate_stimuli(); + // create default stimuli and results + // default stimuli to retrieve buffered items + all_valid_stimuli = new; + all_valid_stimuli.error_before = '0; + all_valid_stimuli.error_after = '0; + all_valid_stimuli.gen_item = 1'b1; + all_valid_stimuli.valid_flip = '0; + all_valid_stimuli.data_error = '0; + all_valid_stimuli.data_bitflips = '0; + all_valid_stimuli.raise_ready = 1'b1; + + // 1st phase: check maximum throughput with no errors & no repeats + for (int i = 0; i < 10; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + stimuli_queue.push_back(stimuli); + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_valid_stimuli); + end + + // 2nd phase: do random testing, no errors, no repeats + for (int i = 0; i < 50; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // disable unused constraints + stimuli.always_ready.constraint_mode(0); + stimuli.always_valid.constraint_mode(0); + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + stimuli_queue.push_back(stimuli); + + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_valid_stimuli); + end + + // 3rd phase: do completely random testing + for (int i = 0; i < 1000; i++) begin + // new stimuli + automatic stimuli_t stimuli = new; + // disable unused constraints + stimuli.always_ready.constraint_mode(0); + stimuli.always_valid.constraint_mode(0); + stimuli.synchronous.constraint_mode(0); + stimuli.no_error.constraint_mode(0); + stimuli.no_data_error.constraint_mode(0); + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + stimuli_queue.push_back(stimuli); + end + + // clear remaining items + repeat (5) begin + stimuli_queue.push_back(all_valid_stimuli); + end + endfunction : generate_stimuli + + /******************* + * apply stimuli * + *******************/ + + // control signals + logic error_before, error_after, join_error; + logic gen_item; + logic no_error; + + // Data input side + data_t [NUM_IN-1:0] data_in, data_in_flipped, data_flip; + logic [NUM_IN-1:0] valid_in, valid_in_flipped, valid_flip; + logic [NUM_IN-1:0] ready_out; + + // Data output side + data_t data_out; + logic raise_ready, ready_in, valid_out; + + // Testbench check signals + data_t sink_expected, sink_received; + logic injected_error; + + task automatic apply_stimuli(); + automatic stimuli_t stimuli; + // get the next stimuli + wait (stimuli_queue.size() != '0); + stimuli = stimuli_queue.pop_front(); + // Wait for apply time + @(posedge clk); + #(TApply); + // apply stimuli + error_before = stimuli.error_before; + error_after = stimuli.error_after; + gen_item = stimuli.gen_item; + valid_flip = stimuli.valid_flip; + data_flip = stimuli.data_bitflips; + raise_ready = stimuli.raise_ready; + endtask : apply_stimuli + + /*********************** + * Device Under Test * + ***********************/ + + // source + for(genvar i = 0; i < NUM_IN; i++) begin : gen_sources + handshake_source #( + .DATA_BITS ( DATA_BITS ) + ) i_source ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .next_item_i ( gen_item ), + .allow_handshake_i ( no_error ), + .valid_o ( valid_in[i] ), + .ready_i ( ready_out[i] ), + .data_o ( data_in[i] ) + ); + end + + assign no_error = !error_before & !error_after & !join_error; + assign valid_in_flipped = valid_in ^ valid_flip; + assign data_in_flipped = data_in ^ data_flip; + + dmr_handshake_join #( + .T ( data_t ), + .NUM_IN ( NUM_IN ) + ) i_dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .enable_i ( 1'b1 ), + .error_before_i ( error_before ), + .error_after_i ( error_after ), + .error_o ( join_error ), + .valid_i ( valid_in_flipped ), + .ready_o ( ready_out ), + .data_i ( data_in_flipped ), + .valid_o ( valid_out ), + .ready_i ( ready_in ), + .data_o ( data_out ) + ); + + handshake_sink #( + .DATA_BITS ( DATA_BITS ) + ) i_sink ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .raise_ready_i ( raise_ready ), + .allow_sink_i ( 1'b1 ), + .valid_i ( valid_out ), + .ready_o ( ready_in ), + .data_i ( data_out ), + .next_expected_o ( sink_expected ), + .num_received_o ( sink_received ) + ); + + assign injected_error = error_before | |valid_flip | (&valid_in & |data_flip); + + /*********************** + * Output collection * + ***********************/ + + typedef struct packed { + bit injected_error; + bit detected_error; + } result_t; + + result_t result_queue [$]; + + task automatic collect_result; + result_t result; + // wait for test time + @(posedge clk) + #(TTest); + // collect the results + result.injected_error = injected_error; + result.detected_error = join_error; + result_queue.push_back(result); + // check if we're done + if(stimuli_queue.size() == 0) begin + sim_running = 1'b0; + end + endtask : collect_result + + /************* + * Checker * + *************/ + + time last_consumed = '0; + + task automatic check_result; + automatic result_t result; + + do begin + wait(result_queue.size() != 0); + + // extract the result + result = result_queue.pop_front(); + + // compare the results + if(result.injected_error != result.detected_error) + $error("[Data Error] Error injected in data not detected."); + end while (sim_running); + + if(data_in[0] != sink_received) begin + $error("[Data Error] Sent %d items, received %d items.", data_in[0], sink_received); + end else begin + $display("[Testbench] Received the correct number of items."); + end + endtask : check_result + + // Error assertions + assert property (@(posedge clk) disable iff (~rst_n) ((error_before | error_after) & &ready_out |=> &ready_out)) else begin + $error("[Ready Repetition] Ready was not repeated during a repeat cycle."); + end + + // make sure output signals are consitent over all sources + for (genvar i = 0; i < NUM_IN; i++) begin + assert property(@(posedge clk) disable iff (~rst_n) (ready_out[i] == ready_out[0])) else begin + $error("[Output Ready Mismatch] [OUT%d] reads %b, [OUT0] reads %b", i, ready_out[i], ready_out[0]); + end + end + + task run_apply(); + forever begin + apply_stimuli(); + end + endtask : run_apply + + task run_collect(); + forever begin + collect_result(); + end + endtask : run_collect + + initial begin : tb + // Initialize variables + error_after = '0; + error_before = '0; + gen_item = '0; + sim_running = 1'b1; + + @(posedge rst_n) + repeat(10) @(posedge clk); + + fork + run_apply(); + run_collect(); + fork + generate_stimuli(); + check_result(); + join + join_any + + $display("[Testbench] Done."); + $finish(0); + end : tb + +endmodule diff --git a/test/tb_ecc_enc_cor.sv b/test/tb_ecc_enc_cor.sv new file mode 100644 index 00000000..a662658c --- /dev/null +++ b/test/tb_ecc_enc_cor.sv @@ -0,0 +1,321 @@ +// Copyright 2021 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. +// +// Description: Testbench for ecc encode and decode modules +// Use the 'tb_ecc_enc_dec_multi' below to run multiple test simultaneously. + +`include "ECC_reg/ecc_calc.svh" + +module tb_ecc_enc_cor #( + parameter int unsigned DataWidth = 0, + // ECC Settings + parameter int unsigned NumErrorDetect = 2, + parameter int unsigned NumErrorCorrect = 1, + // Test settings + parameter int unsigned RunCycles = 100 +) ( + input logic enable_i, + output logic finished_o, + output logic[31:0] num_errors_o +); + + // ECC dist and width calculations + localparam int unsigned EccDist = `ECC_DIST(NumErrorCorrect, NumErrorDetect); + localparam int EccWidth = `ECC_WIDTH(DataWidth, EccDist); + + /****************** + * Helper tasks * + ******************/ + + localparam time TTest = 8ns; + localparam time TApply = 2ns; + + task cycle_start(); + #TApply; + endtask : cycle_start + + task cycle_end(); + #TTest; + endtask : cycle_end + + /********************** + * Helper variables * + **********************/ + + longint test_cnt; + longint error_cnt; + + /************************ + * Stimuli generation * + ************************/ + + class stimuli_t; + + // fixed stimuli inputs + int unsigned num_flips; + + // randomized inputs + rand logic [ DataWidth-1:0] in; + rand logic [EccWidth+DataWidth-1:0] inject; + + constraint error_bits {$countones(inject) == num_flips;} + + endclass : stimuli_t + + // Stimuli + stimuli_t stimuli_queue [$]; + + // Golden values + typedef struct packed { + logic[DataWidth+EccWidth-1:0] out; + logic e_cor, e_uncor, e_check; + } result_t; + + result_t golden_queue [$]; + + function automatic void generate_stimuli(); + + // Step 1: No injected errors + for (int i = 0; i < RunCycles; i++) begin + automatic stimuli_t stimuli = new; + + stimuli.num_flips = 0; + + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{out: stimuli.in, e_cor: 1'b0, e_uncor: 1'b0, e_check: 1'b0}); + end + + // Step 2: Correctable Errors + for (int c = 1; c <= NumErrorCorrect; c++) begin + for (int i = 0; i < RunCycles; i++) begin + // Stimuli with fault + automatic stimuli_t stimuli = new; + stimuli.num_flips = c; + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{out: stimuli.in, e_cor: 1'b1, e_uncor: 1'b0, e_check: 1'b0}); + end + end + + // Step 3: Uncorrectable, Detectable Errors + for (int c = NumErrorCorrect + 1; c <= NumErrorDetect; c++) begin + for (int i = 0; i < RunCycles; i++) begin + // Stimuli with fault + automatic stimuli_t stimuli = new; + stimuli.num_flips = c; + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{out: 'b?, e_cor: 1'b0, e_uncor: 1'b1, e_check: 1'b1}); + end + end + endfunction : generate_stimuli + + // Apply stimuli + logic[ DataWidth-1:0] in; + logic[EccWidth+DataWidth-1:0] inject; + + task automatic apply_stimuli(); + automatic stimuli_t stimuli; + + wait (stimuli_queue.size() != '0); + + stimuli = stimuli_queue.pop_front(); + in = stimuli.in; + inject = stimuli.inject; + endtask : apply_stimuli + + initial begin : init_stimuli + in = '0; + inject = '0; + end : init_stimuli + + /*********************** + * Device Under Test * + ***********************/ + + // __________ __________ __________ + // | | | | | | + // in -->| ENCODE |-->| Inject | -->| DECODE | --> out + // |__________| |__________| |__________| + // + + logic[EccWidth+DataWidth-1:0] protect, cor_protec; + logic[ DataWidth-1:0] out; + logic e_cor, e_uncor, e_cor_2, e_uncor_2, e_check; + + ecc_enc #( + .DataWidth (DataWidth ), + .NumErrorDetect (NumErrorDetect ), + .NumErrorCorrect (NumErrorCorrect) + ) i_dut_enc ( + .data_i (in ), + .data_o (protect) + ); + + ecc_cor #( + .DataWidth (DataWidth ), + .NumErrorDetect (NumErrorDetect ), + .NumErrorCorrect (NumErrorCorrect) + ) i_dut_cor ( + .data_i (protect ^ inject), + .data_o (cor_protec ), + .error_correctable_o (e_cor ), + .error_uncorrectable_o (e_uncor ) + ); + + ecc_cor #( + .DataWidth (DataWidth ), + .NumErrorDetect (NumErrorDetect ), + .NumErrorCorrect (NumErrorCorrect) + ) i_dut_cor_check ( + .data_i (cor_protec ), + .data_o ( ), + .error_correctable_o (e_cor_2 ), + .error_uncorrectable_o (e_uncor_2 ) + ); + + assign out = cor_protec[DataWidth-1:0]; + assign e_check = e_cor_2 | e_uncor_2; + + /*********************** + * Output collection * + ***********************/ + + result_t result_queue [$]; + + function automatic void collect_result; + result_queue.push_back('{out: out, e_cor: e_cor, e_uncor: e_uncor, e_check: e_check}); + endfunction: collect_result + + task automatic check_result; + automatic result_t result; + automatic result_t golden; + + do begin + wait(result_queue.size() != 0); + + // Capture the results + result = result_queue.pop_front(); + golden = golden_queue.pop_front(); + + // Account for this check + test_cnt++; + + if (result != golden) begin + $warning("ERROR! DataWidth %0d, Test %0d: expected %p, found %p.", DataWidth, test_cnt, golden, result); + error_cnt++; + end + end while (stimuli_queue.size() != 0); + endtask: check_result + + /**************** + * Test bench * + ****************/ + + task run(); + // Apply stimuli and collect results cycle + forever begin + if(enable_i) begin + cycle_start(); + apply_stimuli(); + cycle_end(); + collect_result(); + end + end + endtask : run + + assign num_errors_o = error_cnt; + + initial begin: tb + // Initialize variables + test_cnt = '0; + error_cnt = '0; + finished_o = '0; + + wait(enable_i); + + $display("Generating Stimuli for Datawidth %d", DataWidth); + + fork + // Run the TB + run(); + fork + // Generate stimuli + generate_stimuli(); + // Check result + check_result(); + join + join_any + + finished_o = 1'b1; + end: tb + +endmodule + +module tb_ecc_enc_cor_multi #( + parameter int unsigned MaxDataWidth = 0, + // ECC Settings + parameter int unsigned NumErrorDetect = 2, + parameter int unsigned NumErrorCorrect = 1, + // Testbench parameters + parameter int unsigned RunCycles = 500 +); + localparam int unsigned NumTests = RunCycles * MaxDataWidth * ((NumErrorDetect > NumErrorCorrect) ? NumErrorDetect : NumErrorCorrect); + + logic enable; + logic[MaxDataWidth-1:0] finished; + logic[MaxDataWidth-1:0][31:0] error_cnt; + + for(genvar datawidth = 1; datawidth <= MaxDataWidth; datawidth++) begin : gen_dut + tb_ecc_enc_cor #( + .DataWidth (datawidth ), + .NumErrorDetect (NumErrorDetect ), + .NumErrorCorrect (NumErrorCorrect), + .RunCycles (RunCycles ) + ) i_dut ( + .enable_i (enable ), + .finished_o (finished[datawidth-1] ), + .num_errors_o (error_cnt[datawidth-1]) + ); + end + + longint total_errors; + + initial begin + $display("Testing With Parameters:"); + $display(" - MaxDataWidth: %30d", MaxDataWidth); + $display(" - NumErrorDetect: %30d", NumErrorDetect); + $display(" - NumErrorCorrect: %30d", NumErrorCorrect); + + enable = 1'b1; + + wait( finished == {MaxDataWidth{1'b1}} ); + + total_errors = '0; + + $display("Testing Completed:"); + for(int i = 0; i < MaxDataWidth; i++) begin + $display("Datawidth %d: %d Errors.", i+1, error_cnt[i]); + total_errors += error_cnt[i]; + end + + $display("Finished Running %d tests over %d DataWidths", NumTests, MaxDataWidth); + $display("Errors: %d", total_errors); + + $finish(0); + + end + +endmodule diff --git a/test/tb_ecc_reg.sv b/test/tb_ecc_reg.sv new file mode 100644 index 00000000..b28e1244 --- /dev/null +++ b/test/tb_ecc_reg.sv @@ -0,0 +1,407 @@ +// Copyright 2021 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. +// +// Description: Testbench for the ecc register module +// Note: This testbench may only be run with the fault injection script running concurrently +// Use the 'tb_ecc_reg_multi' below to run multiple test simultaneously. + +`include "ECC_reg/ecc_calc.svh" + +module tb_ecc_reg #( + parameter int unsigned DataWidth = 32, + // ECC Settings + parameter int unsigned NumErrorDetect = 2, + parameter int unsigned NumErrorCorrect = 1, + parameter bit Decode = 1, + parameter bit Encode = 1, + parameter bit SelfCorrect = 1, + // FF Settings + parameter bit HasReset = 1, + parameter bit AsynchronousReset = 1, + parameter bit ActiveLowReset = 1, + parameter bit HasLoad = 0, + // Testbench Settings + parameter int unsigned RunCycles = 100 +) ( + input logic enable_i, + output logic finished_o, + output logic[31:0] num_errors_o +); + // ECC dist and width calculations + localparam int unsigned EccDist = `ECC_DIST(NumErrorCorrect, NumErrorDetect); + localparam int EccWidth = `ECC_WIDTH(DataWidth, EccDist); + localparam int unsigned InputWidth = DataWidth + (Encode ? 0 : EccWidth); + localparam int unsigned OutputWidth = DataWidth + (Decode ? 0 : EccWidth); + + /****************** + * Helper tasks * + ******************/ + + localparam time TTest = 8ns; + localparam time TApply = 2ns; + + task cycle_start(); + #TApply; + endtask : cycle_start + + task cycle_end(); + #TTest; + endtask : cycle_end + + /********************** + * Helper variables * + **********************/ + + longint test_cnt; + longint error_cnt; + + logic clk; + logic rst_n; + + clk_rst_gen #( + .ClkPeriod ( TTest + TApply ), + .RstClkCycles ( 5 ) + ) i_clk_gen ( + .clk_o ( clk ), + .rst_no ( rst_n ) + ); + + /************************ + * Stimuli generation * + ************************/ + + // Data type + typedef logic [ DataWidth-1:0] data_t; + typedef logic [ InputWidth-1:0] data_in_t; + typedef logic [OutputWidth-1:0] data_out_t; + typedef logic [DataWidth+EccWidth-1:0] prot_t; + + class stimuli_t; + // fixed stimuli inputs + int num_flips; + + // randomized inputs + rand data_t in; + rand prot_t inject; + + constraint error_bits {$countones(inject) == num_flips;} + + endclass : stimuli_t + + // Stimuli + stimuli_t stimuli_queue [$]; + + // Golden values + typedef struct packed { + data_t out; + logic e_cor, e_uncor; + } result_t; + result_t golden_queue[$]; + + function automatic void generate_stimuli(); + // No valid output in the first cycle + golden_queue.push_back('{out: {OutputWidth{1'b?}}, e_cor: 1'b?, e_uncor: 1'b?}); + + // Step 1: No injected errors + for (int i = 0; i < RunCycles; i++) begin + automatic stimuli_t stimuli = new; + + stimuli.num_flips = 0; + + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + if(Decode) begin + golden_queue.push_back('{out: stimuli.in, e_cor: 1'b0, e_uncor: 1'b0}); + end else begin + golden_queue.push_back('{out: {{EccWidth{1'b?}}, stimuli.in}, e_cor: 1'b0, e_uncor: 1'b0}); + end + end + + // Step 2: Correctable Errors + for (int c = 1; c <= NumErrorCorrect; c++) begin + for (int i = 0; i < RunCycles; i++) begin + // Stimuli with fault + automatic stimuli_t stimuli = new; + automatic stimuli_t stimuli2 = new; + stimuli.num_flips = c; + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + if(Decode) begin + golden_queue.push_back('{out: stimuli.in, e_cor: 1'b1, e_uncor: 1'b0}); + end else begin + if(stimuli.inject[DataWidth-1:0] == 0) begin + golden_queue.push_back('{out: {{EccWidth{1'b?}}, stimuli.in}, e_cor: 1'b1, e_uncor: 1'b0}); + end else begin + golden_queue.push_back('{out: {OutputWidth{1'b?}}, e_cor: 1'b1, e_uncor: 1'b0}); + end + end + + // For self-correction enabled: Second stimuli without fault while error is corrected + stimuli2.num_flips = 0; + if (!stimuli2.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli2); + if(Decode) begin + if(SelfCorrect) begin + golden_queue.push_back('{out: stimuli.in, e_cor: 1'b0, e_uncor: 1'b0}); + end else begin + golden_queue.push_back('{out: stimuli2.in, e_cor: 1'b0, e_uncor: 1'b0}); + end + end else begin + if(SelfCorrect) begin + golden_queue.push_back('{out: {{EccWidth{1'b?}}, stimuli.in}, e_cor: 1'b0, e_uncor: 1'b0}); + end else begin + golden_queue.push_back('{out: {OutputWidth{1'b?}}, e_cor: 1'b0, e_uncor: 1'b0}); + end + end + end + end + + // Step 3: Uncorrectable, Detectable Errors + for (int c = NumErrorCorrect + 1; c <= NumErrorDetect; c++) begin + for (int i = 0; i < RunCycles; i++) begin + // Stimuli with fault + automatic stimuli_t stimuli = new; + stimuli.num_flips = c; + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{out: {OutputWidth{1'b?}}, e_cor: 1'b0, e_uncor: 1'b1}); + end + end + endfunction : generate_stimuli + + // Apply stimuli + data_in_t in; + data_t in_uncoded; + prot_t fault_mask_next, fault_mask, inject_val; + + task automatic apply_stimuli(); + automatic stimuli_t stimuli; + + wait (stimuli_queue.size() != '0); + + stimuli = stimuli_queue.pop_front(); + in_uncoded = stimuli.in; + fault_mask_next = stimuli.inject; + endtask : apply_stimuli + + initial begin : init_stimuli + in_uncoded = '0; + fault_mask_next = '0; + end : init_stimuli + + if(!Encode) begin + ecc_enc #( + .DataWidth (DataWidth ), + .NumErrorDetect (NumErrorDetect ), + .NumErrorCorrect (NumErrorCorrect) + ) i_enc ( + .data_i (in_uncoded), + .data_o (in ) + ); + end else begin + assign in = in_uncoded; + end + + /*********************** + * Device Under Test * + ***********************/ + + data_out_t out; + logic e_cor, e_uncor; + + ecc_reg #( + .DataWidth (DataWidth), + .NumErrorDetect (NumErrorDetect), + .NumErrorCorrect (NumErrorCorrect), + .Encode (Encode), + .Decode (Decode), + .SelfCorrect (SelfCorrect), + .HasReset (HasReset), + .AsynchronousReset (AsynchronousReset), + .ActiveLowReset (ActiveLowReset), + .HasLoad (HasLoad) + ) i_dut ( + .clk_i (clk), + .rst_ni (rst_n), + .data_i (in), + .data_o (out), + .error_correctable_o (e_cor), + .error_uncorrectable_o (e_uncor), + .load_en_i ('0) + ); + + always_ff @( posedge clk or negedge rst_n) begin + if (!rst_n) begin + fault_mask <= '0; + end else begin + fault_mask <= fault_mask_next; + end + end + + assign inject_val = fault_mask ^ i_dut.data_q; + + /*********************** + * Output collection * + ***********************/ + + result_t result_queue [$]; + + function automatic void collect_result; + result_queue.push_back('{out: out,e_cor: e_cor, e_uncor: e_uncor}); + endfunction: collect_result + + task automatic check_result; + automatic result_t result; + automatic result_t golden; + + do begin + wait(result_queue.size() != 0); + + // Capture the results + result = result_queue.pop_front(); + golden = golden_queue.pop_front(); + + // Account for this check + test_cnt++; + + if (result != golden) begin + $warning("ERROR! Test %0d: expected %p, found %p.", test_cnt, golden, result); + error_cnt++; + end + end while (stimuli_queue.size() != 0); + endtask: check_result + + /**************** + * Test bench * + ****************/ + + task run(); + // Apply stimuli and collect results cycle + forever begin + if(enable_i) begin + cycle_start(); + apply_stimuli(); + cycle_end(); + collect_result(); + end + end + endtask : run + + assign num_errors_o = error_cnt; + + initial begin: tb + // Initialize variables + test_cnt = '0; + error_cnt = '0; + finished_o = '0; + + wait(enable_i); + + $display("Generating Stimuli for Datawidth %d", DataWidth); + + @(posedge rst_n) + + fork + // Run the TB + run(); + fork + // Generate stimuli + generate_stimuli(); + // Check result + check_result(); + join + join_any + + finished_o = 1'b1; + end: tb + +endmodule + +module tb_ecc_reg_multi #( + parameter int unsigned MaxDataWidth = 0, + // ECC Settings + parameter int unsigned NumErrorDetect = 2, + parameter int unsigned NumErrorCorrect = 1, + parameter bit Decode = 1, + parameter bit Encode = 1, + parameter bit SelfCorrect = 1, + // FF Settings + parameter bit HasReset = 1, + parameter bit AsynchronousReset = 1, + parameter bit ActiveLowReset = 1, + parameter bit HasLoad = 0, + // Testbench parameters + parameter int unsigned RunCycles = 50 +); + + logic enable; + logic[MaxDataWidth-1:0] finished; + logic[MaxDataWidth-1:0][31:0] error_cnt; + + for(genvar datawidth = 1; datawidth <= MaxDataWidth; datawidth++) begin : gen_dut + tb_ecc_reg #( + .DataWidth (datawidth ), + .NumErrorDetect (NumErrorDetect ), + .NumErrorCorrect (NumErrorCorrect ), + .Decode (Decode ), + .Encode (Encode ), + .SelfCorrect (SelfCorrect ), + .HasReset (HasReset ), + .AsynchronousReset (AsynchronousReset), + .ActiveLowReset (ActiveLowReset ), + .HasLoad (HasLoad ), + .RunCycles (RunCycles ) + ) i_dut ( + .enable_i (enable ), + .finished_o (finished[datawidth-1] ), + .num_errors_o (error_cnt[datawidth-1]) + ); + end + + longint total_errors; + + initial begin + $display("Testing With Parameters:"); + $display(" - MaxDataWidth: %30d", MaxDataWidth); + $display(" - NumErrorDetect: %30d", NumErrorDetect); + $display(" - NumErrorCorrect: %30d", NumErrorCorrect); + $display(" - Decode: %30d", Decode); + $display(" - Encode: %30d", Encode); + $display(" - SelfCorrect: %30d", SelfCorrect); + $display(" - HasReset: %30d", HasReset); + $display(" - AsynchronousReset: %30d", AsynchronousReset); + $display(" - ActiveLowReset: %30d", ActiveLowReset); + $display(" - HasLoad: %30d", HasLoad); + + enable = 1'b1; + + wait( finished == {MaxDataWidth{1'b1}} ); + + total_errors = '0; + + $display("Testing Completed:"); + for(int i = 0; i < MaxDataWidth; i++) begin + $display("Datawidth %d: %d Errors.", i+1, error_cnt[i]); + total_errors += error_cnt[i]; + end + + $display("Finished Running %d tests over %d DataWidths", MaxDataWidth * RunCycles, MaxDataWidth); + $display("Errors: %d", total_errors); + + $finish(0); + + end + +endmodule diff --git a/test/tb_ecc_secded.sv b/test/tb_ecc_secded.sv index 221a90ed..17cf733a 100644 --- a/test/tb_ecc_secded.sv +++ b/test/tb_ecc_secded.sv @@ -57,16 +57,16 @@ module tb_ecc_secded #( function prot_t get_inject; inject = '0; - if (error_pos_1 < DataWidth) + if (error_pos_1 < DataWidth+ProtectBits) inject[error_pos_1] = 1'b1; - if (error_pos_2 < DataWidth) + if (error_pos_2 < DataWidth+ProtectBits) inject[error_pos_2] = 1'b1; return inject; endfunction : get_inject - constraint no_error {error_pos_1 > DataWidth; error_pos_2 > DataWidth;} - constraint single_error {error_pos_1 < DataWidth; error_pos_2 > DataWidth;} - constraint double_error {error_pos_1 < DataWidth; error_pos_2 < DataWidth; error_pos_1 != error_pos_2;} + constraint no_error {error_pos_1 > DataWidth+ProtectBits; error_pos_2 > DataWidth+ProtectBits;} + constraint single_error {error_pos_1 < DataWidth+ProtectBits; error_pos_2 > DataWidth+ProtectBits;} + constraint double_error {error_pos_1 < DataWidth+ProtectBits; error_pos_2 < DataWidth+ProtectBits; error_pos_1 != error_pos_2;} endclass : stimuli_t // Stimuli @@ -75,8 +75,8 @@ module tb_ecc_secded #( // Golden values typedef struct packed { data_t out; - synd_t syndrome; - logic [1:0] error; + synd_t syndrome, syndrome_corrector, syndrome_corrector_decoder; + logic [1:0] error, error_corrector, error_correcter_decoder; } result_t; result_t golden_queue[$]; @@ -94,7 +94,10 @@ module tb_ecc_secded #( // Randomize if (stimuli.randomize()) begin stimuli_queue.push_back(stimuli); - golden_queue.push_back('{out: stimuli.in, syndrome: {ProtectBits{1'b0}}, error: 2'b00}); + golden_queue.push_back('{out: stimuli.in, + syndrome: {ProtectBits{1'b0}}, error: 2'b00, + syndrome_corrector: {ProtectBits{1'b0}}, error_corrector: 2'b00, + syndrome_corrector_decoder: {ProtectBits{1'b0}}, error_correcter_decoder: 2'b00}); end else begin $error("Could not randomize."); end @@ -113,7 +116,10 @@ module tb_ecc_secded #( // Randomize if (stimuli.randomize()) begin stimuli_queue.push_back(stimuli); - golden_queue.push_back('{out: stimuli.in, syndrome: {ProtectBits{1'b?}}, error: 2'b01}); + golden_queue.push_back('{out: stimuli.in, + syndrome: {ProtectBits{1'b?}}, error: 2'b01, + syndrome_corrector: {ProtectBits{1'b?}}, error_corrector: 2'b01, + syndrome_corrector_decoder: {ProtectBits{1'b0}}, error_correcter_decoder: 2'b00}); end else begin $error("Could not randomize."); end @@ -132,7 +138,10 @@ module tb_ecc_secded #( // Randomize if (stimuli.randomize()) begin stimuli_queue.push_back(stimuli); - golden_queue.push_back('{out: {DataWidth{1'b?}}, syndrome: {ProtectBits{1'b?}}, error: 2'b10}); + golden_queue.push_back('{out: {DataWidth{1'b?}}, + syndrome: {ProtectBits{1'b?}}, error: 2'b10, + syndrome_corrector: {ProtectBits{1'b?}}, error_corrector: 2'b10, + syndrome_corrector_decoder: {ProtectBits{1'b?}}, error_correcter_decoder: 2'b??}); end else begin $error("Could not randomize."); end @@ -141,7 +150,7 @@ module tb_ecc_secded #( // Apply stimuli data_t in; - data_t inject; + prot_t inject; task automatic apply_stimuli(); automatic stimuli_t stimuli; @@ -162,10 +171,21 @@ module tb_ecc_secded #( * Device Under Test * ***********************/ - data_t out; - synd_t syndrome; - prot_t prot_out, prot_in; - logic [1:0] error; + // __________ __________ __________ + // | | | | | | + // in -->| ENCODE |-->| Inject | -->| DECODE | --> out + // |__________| |__________| | |__________| + // | + // | ___________ __________ + // | | | | | + // ->| CORRECT | -->| DECODE | --> out_corrected + // |___________| |__________| + // + + data_t out, out_corrected; + synd_t syndrome, syndrome_corrector, syndrome_corrector_decoder; + prot_t prot_out, prot_in, prot_corrected; + logic [1:0] error, error_corrector, error_correcter_decoder; if (DataWidth == 8) begin prim_secded_13_8_enc i_dut_encode ( @@ -179,6 +199,18 @@ module tb_ecc_secded #( .syndrome_o(syndrome), .err_o (error) ); + prim_secded_13_8_cor i_dut_correct ( + .d_i (prot_in), + .d_o (prot_corrected), + .syndrome_o(syndrome_corrector), + .err_o (error_corrector) + ); + prim_secded_13_8_dec i_dut_correct_decode ( + .in (prot_corrected), + .d_o (out_corrected), + .syndrome_o(syndrome_corrector_decoder), + .err_o (error_correcter_decoder) + ); end else if (DataWidth == 16) begin prim_secded_22_16_enc i_dut_encode ( .in (in), @@ -191,6 +223,18 @@ module tb_ecc_secded #( .syndrome_o(syndrome), .err_o (error) ); + prim_secded_22_16_cor i_dut_correct ( + .d_i (prot_in), + .d_o (prot_corrected), + .syndrome_o(syndrome_corrector), + .err_o (error_corrector) + ); + prim_secded_22_16_dec i_dut_correct_decode ( + .in (prot_corrected), + .d_o (out_corrected), + .syndrome_o(syndrome_corrector_decoder), + .err_o (error_correcter_decoder) + ); end else if (DataWidth == 32) begin prim_secded_39_32_enc i_dut_encode ( .in (in), @@ -203,6 +247,18 @@ module tb_ecc_secded #( .syndrome_o(syndrome), .err_o (error) ); + prim_secded_39_32_cor i_dut_correct ( + .d_i (prot_in), + .d_o (prot_corrected), + .syndrome_o(syndrome_corrector), + .err_o (error_corrector) + ); + prim_secded_39_32_dec i_dut_correct_decode ( + .in (prot_corrected), + .d_o (out_corrected), + .syndrome_o(syndrome_corrector_decoder), + .err_o (error_correcter_decoder) + ); end else if (DataWidth == 64) begin prim_secded_72_64_enc i_dut_encode ( .in (in), @@ -215,6 +271,18 @@ module tb_ecc_secded #( .syndrome_o(syndrome), .err_o (error) ); + prim_secded_72_64_cor i_dut_correct ( + .d_i (prot_in), + .d_o (prot_corrected), + .syndrome_o(syndrome_corrector), + .err_o (error_corrector) + ); + prim_secded_72_64_dec i_dut_correct_decode ( + .in (prot_corrected), + .d_o (out_corrected), + .syndrome_o(syndrome_corrector_decoder), + .err_o (error_correcter_decoder) + ); end /*********************** @@ -224,7 +292,13 @@ module tb_ecc_secded #( result_t result_queue [$]; function automatic void collect_result; - result_queue.push_back('{out: out, syndrome: syndrome, error: error}); + result_queue.push_back('{out: out, + syndrome: syndrome, + error: error, + syndrome_corrector: syndrome_corrector, + error_corrector: error_corrector, + syndrome_corrector_decoder: syndrome_corrector_decoder, + error_correcter_decoder: error_correcter_decoder}); endfunction: collect_result task automatic check_result; diff --git a/test/tb_tmr_reg.sv b/test/tb_tmr_reg.sv new file mode 100644 index 00000000..f173d2f4 --- /dev/null +++ b/test/tb_tmr_reg.sv @@ -0,0 +1,259 @@ +// Copyright 2021 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. +// +// Description: Testbench for the tmr register module +// Note: This testbench may only be run with the fault injection script running concurrently + +module tb_tmr_reg #( + parameter int unsigned DataWidth = 32, + // FF Settings + parameter bit HasReset = 1, + parameter bit AsynchronousReset = 1, + parameter bit ActiveLowReset = 1, + parameter bit HasLoad = 0, + // Testbench Settings + parameter int unsigned RunCycles = 100 +) (); + + /****************** + * Helper tasks * + ******************/ + + localparam time TTest = 8ns; + localparam time TApply = 2ns; + + task cycle_start(); + #TApply; + endtask : cycle_start + + task cycle_end(); + #TTest; + endtask : cycle_end + + /********************** + * Helper variables * + **********************/ + + longint test_cnt; + longint error_cnt; + + logic clk; + logic rst_n; + + clk_rst_gen #( + .ClkPeriod ( TTest + TApply ), + .RstClkCycles ( 5 ) + ) i_clk_gen ( + .clk_o ( clk ), + .rst_no ( rst_n ) + ); + + /************************ + * Stimuli generation * + ************************/ + + // Data type + typedef logic [ DataWidth-1:0] data_t; + typedef logic [3*DataWidth-1:0] prot_t; + + class stimuli_t; + // stimuli settings + bit inject_fault; + + // randomized inputs + rand data_t in; + rand data_t flip; + rand int flip_pos [DataWidth]; + + // final injection + prot_t inject; + + constraint flip_bits { + if(inject_fault) { + flip != 0; + } else { + flip == 0; + } + }; + + constraint flip_position { foreach (flip_pos[i]) {flip_pos[i] inside {0, 1, 2};}} + + function void post_randomize(); + inject = '0; + foreach (flip_pos[i]) begin + inject[DataWidth*flip_pos[i]+i] = flip[i]; + end + endfunction + + endclass : stimuli_t + + // Stimuli + stimuli_t stimuli_queue [$]; + + // Golden values + typedef struct packed { + data_t out; + logic error; + } result_t; + result_t golden_queue[$]; + + function automatic void generate_stimuli(); + // No valid output in the first cycle + golden_queue.push_back('{out: {DataWidth{1'b?}}, error: 1'b?}); + + // Step 1: No injected errors + for (int i = 0; i < RunCycles; i++) begin + automatic stimuli_t stimuli = new; + stimuli.inject_fault = 1'b0; + + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{out: stimuli.in, error: 1'b0}); + end + + // Step 2: Correctable Error + for (int i = 0; i < RunCycles; i++) begin + // Stimuli with fault + automatic stimuli_t stimuli = new; + stimuli.inject_fault = 1'b1; + + // Randomize + if (!stimuli.randomize()) $error("Could not randomize."); + + stimuli_queue.push_back(stimuli); + golden_queue.push_back('{out: stimuli.in, error: 1'b1}); + end + endfunction : generate_stimuli + + // Apply stimuli + data_t in; + prot_t fault_mask_next, fault_mask, inject_val; + + task automatic apply_stimuli(); + automatic stimuli_t stimuli; + + wait (stimuli_queue.size() != '0); + + stimuli = stimuli_queue.pop_front(); + in = stimuli.in; + fault_mask_next = stimuli.inject; + endtask : apply_stimuli + + initial begin : init_stimuli + in = '0; + fault_mask_next = '0; + end : init_stimuli + + /*********************** + * Device Under Test * + ***********************/ + + data_t out; + logic error; + + tmr_reg #( + .DataWidth ( DataWidth ), + .HasReset ( HasReset ), + .AsynchronousReset ( AsynchronousReset ), + .ActiveLowReset ( ActiveLowReset ), + .HasLoad ( HasLoad ) + ) i_dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .data_i ( in ), + .data_o ( out ), + .err_o ( error ), + .reset_value_i ( '0 ), + .load_en_i ( '0 ) +); + + always_ff @( posedge clk or negedge rst_n) begin + if (!rst_n) begin + fault_mask <= '0; + end else begin + fault_mask <= fault_mask_next; + end + end + + // 'inject_val' is read by the fault injection script and is injected into 'i_dut.data_q' + assign inject_val = fault_mask ^ i_dut.data_q; + + /*********************** + * Output collection * + ***********************/ + + result_t result_queue [$]; + + function automatic void collect_result; + result_queue.push_back('{out: out, error: error}); + endfunction: collect_result + + task automatic check_result; + automatic result_t result; + automatic result_t golden; + + do begin + wait(result_queue.size() != 0); + + // Capture the results + result = result_queue.pop_front(); + golden = golden_queue.pop_front(); + + // Account for this check + test_cnt++; + + if (result != golden) begin + $warning("ERROR! Test %0d: expected %p, found %p.", test_cnt, golden, result); + error_cnt++; + end + end while (stimuli_queue.size() != 0); + endtask: check_result + + /**************** + * Test bench * + ****************/ + + task run(); + // Apply stimuli and collect results cycle + forever begin + cycle_start(); + apply_stimuli(); + cycle_end(); + collect_result(); + end + endtask : run + + assign num_errors_o = error_cnt; + + initial begin: tb + + $display("Generating Stimuli"); + + @(posedge rst_n) + + fork + // Run the TB + run(); + fork + // Generate stimuli + generate_stimuli(); + // Check result + check_result(); + join + join_any + + $display("Found %d Errors in %d tests.", error_cnt, test_cnt); + $finish(0); + + end: tb + +endmodule diff --git a/test/tmr_reg_fault_injection.tcl b/test/tmr_reg_fault_injection.tcl new file mode 100644 index 00000000..c1d96c14 --- /dev/null +++ b/test/tmr_reg_fault_injection.tcl @@ -0,0 +1,10 @@ +# Helper script for the testbench: +# The Testbench calcutales the value it wants to inject (inject_val), this script +# reads the value and injects in on the falling clock edge. + +when { sim:/tb_tmr_reg/clk == 1'b0 } { + set val [examine sim:/tb_tmr_reg/i_dut/data_q] + set inject_val [examine sim:/tb_tmr_reg/inject_val] + force -deposit sim:/tb_tmr_reg/i_dut/data_q $inject_val + #echo "Flipped $val to $inject_val" +} diff --git a/test_run.tcl b/test_run.tcl new file mode 100644 index 00000000..8279cbc0 --- /dev/null +++ b/test_run.tcl @@ -0,0 +1,3 @@ +log -r /* +do test/ecc_reg_fault_injection.tcl +run -a diff --git a/util/lowrisc_opentitan/util/design/data/secded_cfg.hjson b/util/lowrisc_opentitan/util/design/data/secded_cfg.hjson index 5de93ce7..b9e70bb8 100644 --- a/util/lowrisc_opentitan/util/design/data/secded_cfg.hjson +++ b/util/lowrisc_opentitan/util/design/data/secded_cfg.hjson @@ -2,12 +2,19 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 { cfgs: [ + {k: 1, m: 3, code_type: "hsiao" }, + {k: 4, m: 4, code_type: "hsiao" }, {k: 8, m: 5, code_type: "hsiao" }, + {k: 11, m: 5, code_type: "hsiao" }, {k: 16, m: 6, code_type: "hsiao" }, {k: 22, m: 6, code_type: "hsiao" }, + {k: 26, m: 6, code_type: "hsiao" }, {k: 32, m: 7, code_type: "hsiao" }, {k: 57, m: 7, code_type: "hsiao" }, {k: 64, m: 8, code_type: "hsiao" }, + {k: 120, m: 8, code_type: "hsiao" }, + {k: 247, m: 9, code_type: "hsiao" }, + {k: 502, m: 10, code_type: "hsiao" }, {k: 16, m: 6, code_type: "hamming"}, {k: 32, m: 7, code_type: "hamming"}, {k: 64, m: 8, code_type: "hamming"}, diff --git a/util/lowrisc_opentitan/util/design/secded_gen.py b/util/lowrisc_opentitan/util/design/secded_gen.py index 4a32f643..e6ec4dcc 100755 --- a/util/lowrisc_opentitan/util/design/secded_gen.py +++ b/util/lowrisc_opentitan/util/design/secded_gen.py @@ -128,9 +128,9 @@ def print_fn(n, k, m, codes, suffix, codetype): def print_enc(n, k, m, codes): - outstr = " out = {}'(in);\n".format(n) - format_str = " out[{}] = ^(out & " + str(n) + "'h{:0" + str( - (n + 3) // 4) + "X});\n" + outstr = " out[{}:0] = in;\n".format(k-1) + format_str = " out[{}] = ^(in & " + str(k) + "'h{:0" + str( + (k + 3) // 4) + "X});\n" # Print parity computation for j, mask in enumerate(calc_bitmasks(k, m, codes, False)): outstr += format_str.format(j + k, mask) @@ -180,6 +180,47 @@ def print_dec(n, k, m, codes, codetype, print_type="logic"): outstr += " {}".format(preamble) + "err_o[1] = ~single_error & (|syndrome_o);\n" return outstr +def print_cor(n, k, m, codes, codetype, print_type="logic"): + + preamble = PRINT_OPTIONS[print_type] + + outstr = "" + if codetype == "hsiao": + outstr += " {}logic single_error;\n".format( + preamble if print_type == "function" else "") + + outstr += "\n" + outstr += " {}// Syndrome calculation\n".format( + preamble if print_type == "function" else "") + format_str = " {}".format(preamble) + "syndrome_o[{}] = ^(d_i & " \ + + str(n) + "'h{:0" + str((n + 3) // 4) + "X});\n" + + # Print syndrome computation + for j, mask in enumerate(calc_bitmasks(k, m, codes, True)): + outstr += format_str.format(j, mask) + outstr += "\n" + outstr += " {}// Corrected output calculation\n".format( + preamble if print_type == "function" else "") + for i in range(k): + outstr += " {}".format(preamble) + "d_o[%d] = (syndrome_o == %d'h%x) ^ d_i[%d];\n" % ( + i, m, calc_syndrome(codes[i]), i) + for i in range(n-k): + outstr += " {}".format(preamble) + "d_o[%d] = (syndrome_o == %d'h%x) ^ d_i[%d];\n" % ( + i+k, m, 2**i, i+k) + outstr += "\n" + outstr += " {}// err_o calc. bit0: single error, bit1: double error\n".format( + preamble if print_type == "function" else "") + # The Hsiao and Hamming syndromes are interpreted slightly differently. + if codetype == "hamming": + outstr += " {}".format(preamble) + "err_o[0] = syndrome_o[%d];\n" % (m - 1) + outstr += " {}".format(preamble) + "err_o[1] = |syndrome_o[%d:0] & ~syndrome_o[%d];\n" % ( + m - 2, m - 1) + else: + outstr += " {}".format(preamble) + "single_error = ^syndrome_o;\n" + outstr += " {}".format(preamble) + "err_o[0] = single_error;\n" + outstr += " {}".format(preamble) + "err_o[1] = ~single_error & (|syndrome_o);\n" + return outstr + # return whether an integer is a power of 2 def is_pow2(n): @@ -199,7 +240,7 @@ def verify(cfgs): log.error("Seed {} must be a 32-bit integer".format(cfgs['seed'])) for cfg in cfgs['cfgs']: - if (cfg['k'] <= 1 or cfg['k'] > 120): + if (cfg['k'] < 1 or cfg['k'] > 502): error += 1 log.error("Current tool doesn't support the value k (%d)", cfg['k']) @@ -371,16 +412,12 @@ def hamming_code(k, m): pos, parity_pos, parity_chk)) # valid for inclusion or final parity bit that includes everything - if is_odd(parity_chk) or p == m - 1: + if is_odd(parity_chk) or (p == m - 1 and (len(code) % 2) == 0): code = code + (p, ) log.info("add {} to tuple {}".format(p, code)) codes.append(code) - # final parity bit includes all ECC bits - for p in range(m - 1): - codes.append((m - 1, )) - log.info("Hamming codes {}".format(codes)) return codes @@ -440,6 +477,25 @@ def write_enc_dec_files(n, k, m, s, codes, suffix, outdir, codetype): (m - 1), dec_out, module_name) f.write(outstr) + cor_out = print_cor(n, k, m, codes, codetype) + + with open(outdir + "/" + module_name + "_cor.sv", "w") as f: + outstr = '''{}// SECDED Corrector generated by +// util/design/secded_gen.py -m {} -k {} -s {} -c {} + +module {}_cor ( + input [{}:0] d_i, + output logic [{}:0] d_o, + output logic [{}:0] syndrome_o, + output logic [1:0] err_o +); + +{} +endmodule : {}_cor +'''.format(COPYRIGHT, m, k, s, codetype, module_name, (n - 1), (n - 1), + (m - 1), cor_out, module_name) + f.write(outstr) + def write_fpv_files(n, k, m, codes, suffix, outdir): module_name = "prim_secded%s_%d_%d" % (suffix, n, k) diff --git a/util/patches/lowrisc_opentitan/002-add_corrector.patch b/util/patches/lowrisc_opentitan/002-add_corrector.patch new file mode 100644 index 00000000..842b44c4 --- /dev/null +++ b/util/patches/lowrisc_opentitan/002-add_corrector.patch @@ -0,0 +1,78 @@ +diff --git a/util/lowrisc_opentitan/util/design/secded_gen.py b/util/lowrisc_opentitan/util/design/secded_gen.py +index 4a32f64..24056ce 100755 +--- a/util/lowrisc_opentitan/util/design/secded_gen.py ++++ b/util/lowrisc_opentitan/util/design/secded_gen.py +@@ -180,6 +180,47 @@ def print_dec(n, k, m, codes, codetype, print_type="logic"): + outstr += " {}".format(preamble) + "err_o[1] = ~single_error & (|syndrome_o);\n" + return outstr + ++def print_cor(n, k, m, codes, codetype, print_type="logic"): ++ ++ preamble = PRINT_OPTIONS[print_type] ++ ++ outstr = "" ++ if codetype == "hsiao": ++ outstr += " {}logic single_error;\n".format( ++ preamble if print_type == "function" else "") ++ ++ outstr += "\n" ++ outstr += " {}// Syndrome calculation\n".format( ++ preamble if print_type == "function" else "") ++ format_str = " {}".format(preamble) + "syndrome_o[{}] = ^(d_i & " \ ++ + str(n) + "'h{:0" + str((n + 3) // 4) + "X});\n" ++ ++ # Print syndrome computation ++ for j, mask in enumerate(calc_bitmasks(k, m, codes, True)): ++ outstr += format_str.format(j, mask) ++ outstr += "\n" ++ outstr += " {}// Corrected output calculation\n".format( ++ preamble if print_type == "function" else "") ++ for i in range(k): ++ outstr += " {}".format(preamble) + "d_o[%d] = (syndrome_o == %d'h%x) ^ d_i[%d];\n" % ( ++ i, m, calc_syndrome(codes[i]), i) ++ for i in range(n-k): ++ outstr += " {}".format(preamble) + "d_o[%d] = (syndrome_o == %d'h%x) ^ d_i[%d];\n" % ( ++ i+k, m, 2**i, i+k) ++ outstr += "\n" ++ outstr += " {}// err_o calc. bit0: single error, bit1: double error\n".format( ++ preamble if print_type == "function" else "") ++ # The Hsiao and Hamming syndromes are interpreted slightly differently. ++ if codetype == "hamming": ++ outstr += " {}".format(preamble) + "err_o[0] = syndrome_o[%d];\n" % (m - 1) ++ outstr += " {}".format(preamble) + "err_o[1] = |syndrome_o[%d:0] & ~syndrome_o[%d];\n" % ( ++ m - 2, m - 1) ++ else: ++ outstr += " {}".format(preamble) + "single_error = ^syndrome_o;\n" ++ outstr += " {}".format(preamble) + "err_o[0] = single_error;\n" ++ outstr += " {}".format(preamble) + "err_o[1] = ~single_error & (|syndrome_o);\n" ++ return outstr ++ + + # return whether an integer is a power of 2 + def is_pow2(n): +@@ -440,6 +481,25 @@ endmodule : {}_dec + (m - 1), dec_out, module_name) + f.write(outstr) + ++ cor_out = print_cor(n, k, m, codes, codetype) ++ ++ with open(outdir + "/" + module_name + "_cor.sv", "w") as f: ++ outstr = '''{}// SECDED Corrector generated by ++// util/design/secded_gen.py -m {} -k {} -s {} -c {} ++ ++module {}_cor ( ++ input [{}:0] d_i, ++ output logic [{}:0] d_o, ++ output logic [{}:0] syndrome_o, ++ output logic [1:0] err_o ++); ++ ++{} ++endmodule : {}_cor ++'''.format(COPYRIGHT, m, k, s, codetype, module_name, (n - 1), (n - 1), ++ (m - 1), cor_out, module_name) ++ f.write(outstr) ++ + + def write_fpv_files(n, k, m, codes, suffix, outdir): + module_name = "prim_secded%s_%d_%d" % (suffix, n, k) diff --git a/util/patches/lowrisc_opentitan/003-update_enc.patch b/util/patches/lowrisc_opentitan/003-update_enc.patch new file mode 100644 index 00000000..91d407c2 --- /dev/null +++ b/util/patches/lowrisc_opentitan/003-update_enc.patch @@ -0,0 +1,35 @@ +diff --git a/util/lowrisc_opentitan/util/design/secded_gen.py b/util/lowrisc_opentitan/util/design/secded_gen.py +index a0dca14..e6ec4dc 100755 +--- a/util/lowrisc_opentitan/util/design/secded_gen.py ++++ b/util/lowrisc_opentitan/util/design/secded_gen.py +@@ -128,9 +128,9 @@ def print_fn(n, k, m, codes, suffix, codetype): + + + def print_enc(n, k, m, codes): +- outstr = " out = {}'(in);\n".format(n) +- format_str = " out[{}] = ^(out & " + str(n) + "'h{:0" + str( +- (n + 3) // 4) + "X});\n" ++ outstr = " out[{}:0] = in;\n".format(k-1) ++ format_str = " out[{}] = ^(in & " + str(k) + "'h{:0" + str( ++ (k + 3) // 4) + "X});\n" + # Print parity computation + for j, mask in enumerate(calc_bitmasks(k, m, codes, False)): + outstr += format_str.format(j + k, mask) +@@ -412,16 +412,12 @@ def hamming_code(k, m): + pos, parity_pos, parity_chk)) + + # valid for inclusion or final parity bit that includes everything +- if is_odd(parity_chk) or p == m - 1: ++ if is_odd(parity_chk) or (p == m - 1 and (len(code) % 2) == 0): + code = code + (p, ) + log.info("add {} to tuple {}".format(p, code)) + + codes.append(code) + +- # final parity bit includes all ECC bits +- for p in range(m - 1): +- codes.append((m - 1, )) +- + log.info("Hamming codes {}".format(codes)) + return codes +