Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Voter Macros #25

Merged
merged 8 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ dependencies:
common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.0 }
register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.4 }
common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.35.0 }

export_include_dirs:
- include

sources:
# Source files grouped in levels. Files in level 0 have no dependencies on files in this
Expand All @@ -23,6 +26,7 @@ sources:
- rtl/hsiao_ecc/hsiao_ecc_dec.sv
- rtl/hsiao_ecc/hsiao_ecc_cor.sv
- rtl/TMR_voter.sv
- rtl/TMR_voter_fail.sv
- rtl/TMR_word_voter.sv
# Level 1
- rtl/ODRG_unit/odrg_manager_reg_top.sv
Expand Down Expand Up @@ -68,6 +72,7 @@ sources:
- rtl/TMR_voter_detect.sv
# Level 2
- rtl/bitwise_TMR_voter.sv
- rtl/bitwise_TMR_voter_fail.sv
- rtl/ecc_wrap/ecc_manager.sv
- target: deprecated
files:
Expand All @@ -88,9 +93,12 @@ sources:
- test/tb_ecc_secded.sv
- test/tb_ecc_sram.sv
- test/tb_tmr_voter.sv
- test/tb_tmr_voter_fail.sv
- test/tb_tmr_voter_detect.sv
- test/tb_tmr_word_voter.sv
- test/tb_bitwise_tmr_voter.sv
- test/tb_bitwise_tmr_voter_fail.sv
- test/tb_voter_macros.sv

vendor_package:
- name: lowrisc_opentitan
Expand Down
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,42 @@ The `DropECC` parameter allows for a faster signal along the decode data path, n
## Triple Modular Redundancy majority voters
The `TMR_voter`s are Triple Modular Redundancy majority voters, based on research indicated in the corresponding files. To detect the failing module, additional signals are implemented in higher-level modules.

## Voting Macros
For quickly instantiating voters, the following macros might be useful. They can be used via bender with:
```
include "redundancy_cells/voters.svh"
```
All Macros use the following naming scheme:
`VOTE{Inputs}{Outputs}{Flags}`

For size `1` outputs can be arbitrarily sized arrays (denoted as size `K` below),
for size `3` inputs and outputs should be arrays of length 3 at the top level which at lower levels can again be arbitrarily (`K`) sized.
The size `X` allows for a parameter called `REP` to determine how many duplicates are used,
which allows to make designs which have parametric redundancy.
`REP` should be 1 (no redundancy), 2 (fault detection) or 3 (fault correction).

Available Flags are:
- `F` Fault Detection: Additional 1-bit output signal which is one if voting was not unanimous
- `W` Fault Location: Additional 3-bit output signal which specifies which input was different and 1-bit signal if all bits where different

Voters work with enumerated types, but there is no guarante when multiple faults occurr that the output is a valid enum entry.
For Enum simulation in Questasim `vsim-3999` and `vopt-8386` errors need to be supressed.

All availabe voters are:

| Macro | Arguments | Description |
|------------|-----------------------------------------------------------------------------------|--------------------------------------------------|
| `VOTE31` | `input_signal[2:0][K:0], output_signal[K:0]` | 3 -> 1 Voter |
| `VOTE31F` | `input_signal[2:0][K:0], output_signal[K:0], fault_any` | 3 -> 1 Voter with fault detection |
| `VOTE31W` | `input_signal[2:0][K:0], output_signal[K:0], fault_210[2:0], fault_multiple` | 3 -> 1 Voter with fault location |
| `VOTE33` | `input_signal[2:0][K:0], output_signal[2:0][K:0]` | 3 -> 3 Voters |
| `VOTE33F` | `input_signal[2:0][K:0], output_signal[2:0][K:0], fault_any` | 3 -> 3 Voters with fault detection |
| `VOTE33W` | `input_signal[2:0][K:0], output_signal[2:0][K:0], fault_210[2:0], fault_multiple` | 3 -> 3 Voters with fault location |
| `VOTEX1` | `input_signal[REP:0][K:0], output_signal[K:0]` | REP -> 1 Voter (REP is a parameter from 1 to 3) |
| `VOTEX1F` | `input_signal[REP:0][K:0], output_signal[K:0], fault_any` | REP -> 1 Voter with fault detection |
| `VOTEXX` | `input_signal[REP:0][K:0], output_signal[REP:0][K:0]` | REP -> REP Voters |
| `VOTEXXF` | `input_signal[REP:0][K:0], output_signal[REP:0][K:0], fault_any` | REP -> REP Voters with fault detection |

## Testing
To run tests, execute the following command:
```bash
Expand Down
104 changes: 104 additions & 0 deletions include/redundancy_cells/voters.svh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Macros to instantiate some kind of Voters
// If you want to use different kinds of Cells, you only have to change these
`define TMR_INSTANCE(input_signal, output_signal, instance_name) \
bitwise_TMR_voter_fail #(.DataWidth($bits(input_signal[0])), .VoterType(2)) instance_name ( \
.a_i(input_signal[0]), \
.b_i(input_signal[1]), \
.c_i(input_signal[2]), \
.majority_o(output_signal), \
.fault_detected_o() \
);

`define TMR_INSTANCE_F(input_signal, output_signal, fault_any, instance_name) \
bitwise_TMR_voter_fail #(.DataWidth($bits(input_signal[0])), .VoterType(1)) instance_name ( \
.a_i(input_signal[0]), \
.b_i(input_signal[1]), \
.c_i(input_signal[2]), \
.majority_o(output_signal), \
.fault_detected_o(fault_any) \
);

`define TMR_INSTANCE_W(input_signal, output_signal, fault_210, fault_multiple, instance_name) \
bitwise_TMR_voter #(.DataWidth($bits(input_signal[0])), .VoterType(2)) instance_name ( \
.a_i(input_signal[0]), \
.b_i(input_signal[1]), \
.c_i(input_signal[2]), \
.majority_o(output_signal), \
.error_o(fault_multiple), \
.error_cba_o(fault_210) \
);

// Macro to create a name based on the current line in the file
// Name looks like: base_name_L42
`define UNIQUE_NAME(base_name) ``base_name``_L```__LINE__

// 3 -> 1 Voters
`define VOTE31(input_signal, output_signal) \
`TMR_INSTANCE(input_signal, output_signal, `UNIQUE_NAME(i_bitwise_TMR_voter_fail));

`define VOTE31F(input_signal, output_signal, fault_any) \
`TMR_INSTANCE_F(input_signal, output_signal, fault_any, `UNIQUE_NAME(i_bitwise_TMR_voter_fail));

`define VOTE31W(input_signal, output_signal, fault_210, fault_multiple) \
`TMR_INSTANCE_W(input_signal, output_signal, fault_210, fault_multiple, `UNIQUE_NAME(i_bitwise_TMR_voter));


// 3 -> 3 Voters
`define VOTE33(input_signal, output_signal) \
`TMR_INSTANCE(input_signal, output_signal[0], `UNIQUE_NAME(i_bitwise_TMR_voter_fail_0)); \
`TMR_INSTANCE(input_signal, output_signal[1], `UNIQUE_NAME(i_bitwise_TMR_voter_fail_1)); \
`TMR_INSTANCE(input_signal, output_signal[2], `UNIQUE_NAME(i_bitwise_TMR_voter_fail_2));

`define VOTE33F(input_signal, output_signal, fault_any) \
`TMR_INSTANCE_F(input_signal, output_signal[0], fault_any, `UNIQUE_NAME(i_bitwise_TMR_voter_fail_0f)); \
`TMR_INSTANCE(input_signal, output_signal[1], `UNIQUE_NAME(i_bitwise_TMR_voter_fail_1)); \
`TMR_INSTANCE(input_signal, output_signal[2], `UNIQUE_NAME(i_bitwise_TMR_voter_fail_2));

`define VOTE33W(input_signal, output_signal, fault_210, fault_multiple) \
`TMR_INSTANCE_W(input_signal, output_signal[0], fault_210, fault_multiple, `UNIQUE_NAME(i_bitwise_TMR_voter_fail_0w)); \
`TMR_INSTANCE(input_signal, output_signal[1], `UNIQUE_NAME(i_bitwise_TMR_voter_fail_1)); \
`TMR_INSTANCE(input_signal, output_signal[2], `UNIQUE_NAME(i_bitwise_TMR_voter_fail_2));


// localparam REP -> 1 Voters
`define VOTEX1(input_signal, output_signal) \
if (REP == 3) begin \
`VOTE31(input_signal, output_signal); \
end else if (REP == 2) begin \
assign output_signal = input_signal[0]; \
end else begin \
assign output_signal = input_signal[0]; \
end

`define VOTEX1F(input_signal, output_signal, fault_any) \
if (REP == 3) begin \
`VOTE31F(input_signal, output_signal, fault_any); \
end else if (REP == 2) begin \
assign output_signal = input_signal[0]; \
assign fault_any = input_signal[0] != input_signal[1]; \
end else begin \
assign output_signal = input_signal[0]; \
assign fault_any = 1'b1; \
end


// localparam REP -> REP Voters
`define VOTEXX(input_signal, output_signal) \
if (REP == 3) begin \
`VOTE33(input_signal, output_signal); \
end else if (REP == 2) begin \
assign output_signal = input_signal; \
end else begin \
assign output_signal = input_signal; \
end

`define VOTEXXF(input_signal, output_signal, fault_any) \
if (REP == 3) begin \
`VOTE33F(input_signal, output_signal, fault_any); \
end else if (REP == 2) begin \
assign output_signal = input_signal; \
assign fault_any = input_signal[0] != input_signal[1]; \
end else begin \
assign output_signal = input_signal; \
assign fault_any = 1'b1; \
end
50 changes: 50 additions & 0 deletions rtl/TMR_voter_fail.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// 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.
//
// Triple Modular Redundancy Majority Voter (MV) for a single bit with a failure output
//
// Classical_MV: standard and & or gates
// KP_MV: Kshirsagar and Patrikar MV [https://doi.org/10.1016/j.microrel.2009.08.001]
// BN_MV: Ban and Naviner MV [https://doi.org/10.1109/NEWCAS.2010.5603933]
//
// Fault detection logic added on our own Ideas

module TMR_voter_fail #(
parameter int unsigned VoterType = 1 // 0: Classical_MV, 1: KP_MV, 2: BN_MV
) (
input logic a_i,
input logic b_i,
input logic c_i,
output logic majority_o,
output logic fault_detected_o
);

if (VoterType == 0) begin : gen_classical_mv
assign majority_o = (a_i & b_i) | (a_i & c_i) | (b_i & c_i);
assign fault_detected_o = (a_i ^ b_i) | (a_i ^ c_i); // 3 extra gates
end else if (VoterType == 1) begin : gen_kp_mv
logic n_1, n_2, p;
assign n_1 = a_i ^ b_i;
assign n_2 = b_i ^ c_i;
assign p = n_1 & ~n_2;
assign majority_o = p ? c_i : a_i;
assign fault_detected_o = n_1 | n_2; // 1 extra gate
end else if (VoterType == 2) begin : gen_bn_mv
logic n;
assign n = a_i ^ b_i;
assign majority_o = n ? c_i : b_i;
assign fault_detected_o = n | b_i ^ c_i; // 2 extra gates
end else begin : gen_unsupported
`ifndef TARGET_SYNTHESIS
$fatal(1, "Please select a valid VoterType.\n");
`endif
end

endmodule
40 changes: 40 additions & 0 deletions rtl/bitwise_TMR_voter_fail.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.
//
// Triple Modular Redundancy Majority Voter (MV) for a data word

module bitwise_TMR_voter_fail #(
parameter int unsigned DataWidth = 32,
parameter int unsigned VoterType = 1 // 0: Classical_MV, 1: KP_MV, 2: BN_MV
) (
input logic [DataWidth-1:0] a_i,
input logic [DataWidth-1:0] b_i,
input logic [DataWidth-1:0] c_i,
output logic [DataWidth-1:0] majority_o,
output logic fault_detected_o // Indicates any type of mismatch
);

logic [DataWidth-1:0] fault_detected;

for (genvar i = 0; i < DataWidth; i++) begin : gen_bit_voters
TMR_voter_fail #(
.VoterType ( VoterType )
) i_voter_fail (
.a_i ( a_i[i] ),
.b_i ( b_i[i] ),
.c_i ( c_i[i] ),
.majority_o ( majority_o[i] ),
.fault_detected_o ( fault_detected[i] )
);
end

assign fault_detected_o = |fault_detected;

endmodule
3 changes: 3 additions & 0 deletions run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,15 @@ call_vsim() {
}

call_vsim tb_tmr_voter
call_vsim tb_tmr_voter_fail
call_vsim tb_tmr_voter_detect
call_vsim tb_tmr_word_voter
call_vsim tb_bitwise_tmr_voter
call_vsim tb_bitwise_tmr_voter_fail
call_vsim tb_ecc_sram -voptargs="+acc=nr"
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_ecc_scrubber
call_vsim tb_voter_macros -suppress vsim-3999 -suppress vopt-8386
2 changes: 2 additions & 0 deletions src_files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ redundancy_cells:
lowrisc_ecc/prim_secded_72_64_dec.sv,
lowrisc_ecc/prim_secded_72_64_enc.sv,
rtl/TMR_voter.sv,
rtl/TMR_voter_fail.sv,
rtl/TMR_word_voter,
# Level 1
rtl/bitwise_TMR_voter_fail.sv
rtl/ecc_concat_32_64.sv,
rtl/ecc_sram_wrap.sv,
rtl/BUS_enc_dec/AXI_bus_ecc_dec.sv,
Expand Down
Loading
Loading