Error Detection

TMRX can aggregate error signals from all voters to a single output port for monitoring.

Defining an Error Sink

There are three ways to designate an error sink port.

Verilog Attribute

Mark an output port directly in the source with the tmrx_error_sink attribute:

module my_module (
    input  wire clk_i,
    input  wire rst_ni,
    input  wire [7:0] data_i,
    output wire [7:0] data_o,
    (* tmrx_error_sink *)
    output wire err_o
);
    // ...
endmodule

Configuration Option

Specify the error sink port by name in the TOML configuration using error_port_name. This is useful when you cannot or do not want to modify the Verilog source:

[module.my_module]
error_port_name = "err_o"

The equivalent Verilog attribute is tmrx_error_port_name:

(* tmrx_error_port_name = "err_o" *)
module my_module ( ... );

Automatic Error Port Creation

When no explicit error sink is present, TMRX can create one automatically. Enable this with auto_error_port:

[global]
auto_error_port = true

When enabled and voter errors exist, TMRX adds a new 1-bit output port named tmrx_err_o to the module and connects all aggregated voter errors to it. If there are no voter errors in a module, no port is created.

The equivalent Verilog attribute is tmrx_auto_error_port:

(* tmrx_auto_error_port = "1" *)
module my_module ( ... );

auto_error_port defaults to false. Enabling it globally is the simplest way to ensure every TMR-processed module exposes its errors without modifying Verilog source.

How It Works

  1. Each voter generates a 1-bit error signal when its inputs do not all agree.

  2. All voter error signals within the module are OR’d together into a single aggregate error.

  3. The aggregate error is driven onto the error sink port — whether defined by attribute, error_port_name, or auto-created.

Implicit Upward Propagation

TMRX automatically propagates error signals up the module hierarchy. When a submodule has an error sink port (by any method above), the parent module collects that port’s output as an additional error signal alongside its own voter errors. This collected child error is then aggregated into the parent’s own error sink.

This means a single top-level error port can capture voter disagreements from the entire design hierarchy without any manual wiring.

// Child module — error exposed via attribute
module alu (
    input  wire [7:0] a_i,
    input  wire [7:0] b_i,
    output wire [7:0] result_o,
    (* tmrx_error_sink *)
    output wire err_o      // collected by parent automatically
);

// Parent module — receives child error implicitly
module cpu (
    input  wire clk_i,
    input  wire rst_ni,
    (* tmrx_error_sink *)
    output wire err_o      // aggregates its own voters + alu.err_o
);
    alu u_alu ( ... );

Behavior Without an Error Sink

If no error sink is defined and auto_error_port = false:

  • Voters still generate error signals internally.

  • Error signals are left unconnected.

  • No warning is generated.

For production designs, either mark an error sink port in every TMR module or enable auto_error_port = true globally to ensure all voter errors are observable.