blob: 8e599f77970eb34a22879329d248ddb77ea92fde [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// This module accumulates incoming alert triggers. Once the current accumulator
// value is greater or equal the accumulator threshold, the next occurence of
// class_trig_i will trigger escalation.
//
// Note that the accumulator is implemented using a saturation counter which
// does not wrap around.
//
`include "prim_assert.sv"
module alert_handler_accu import alert_pkg::*; (
input clk_i,
input rst_ni,
input class_en_i, // class enable
input clr_i, // clear the accumulator
input class_trig_i, // increments the accu
input [AccuCntDw-1:0] thresh_i, // escalation trigger threshold
output logic [AccuCntDw-1:0] accu_cnt_o, // output of current accu value
output logic accu_trig_o, // escalation trigger output
output logic accu_fail_o // asserted if the tandem accu counters are not equal
);
logic trig_gated_unbuf;
assign trig_gated_unbuf = class_trig_i & class_en_i;
// We employ two redundant counters to guard against FI attacks.
// If any of the two is glitched and the two counter states do not agree,
// the check_fail_o signal is asserted which will move the corresponding escalation
// FSM into a terminal error state where all escalation actions will be permanently asserted.
logic [1:0][AccuCntDw-1:0] accu_q;
for (genvar k = 0; k < 2; k++) begin : gen_double_accu
logic trig_gated_buf, clr_buf;
logic [AccuCntDw-1:0] accu_d;
// These size_only buffers are instantiated in order to prevent
// optimization / merging of the two counters.
prim_buf u_prim_buf_clr (
.in_i(clr_i),
.out_o(clr_buf)
);
prim_buf u_prim_buf_trig (
.in_i(trig_gated_unbuf),
.out_o(trig_gated_buf)
);
assign accu_d = (clr_buf) ? '0 : // clear
(trig_gated_buf && !(&accu_q[k])) ? accu_q[k] + 1'b1 : // saturate counter
accu_q[k];
prim_flop #(
.Width(AccuCntDw)
) u_prim_flop (
.clk_i,
.rst_ni,
.d_i(accu_d),
.q_o(accu_q[k])
);
end
assign accu_cnt_o = accu_q[0];
assign accu_trig_o = (accu_q[0] >= thresh_i) & trig_gated_unbuf;
assign accu_fail_o = accu_q[0] != accu_q[1];
////////////////
// Assertions //
////////////////
`ASSERT(DisabledNoTrigFwd_A, !class_en_i |-> !accu_trig_o)
`ASSERT(DisabledNoTrigBkwd_A, accu_trig_o |-> class_en_i)
`ASSERT(CheckFailFwd_A, accu_q[0] != accu_q[1] |-> accu_fail_o)
`ASSERT(CheckFailBkwd_A, accu_fail_o |-> accu_q[0] != accu_q[1])
endmodule : alert_handler_accu