[aes] Add second alert signal

This commit adds a second alert signal to AES in order to distinguish
between
- minor/recoverable update errors, and
- major/fatal storage errors that require the module to be reset.

Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/hw/ip/aes/data/aes.hjson b/hw/ip/aes/data/aes.hjson
index 1c41834..24e5ac3 100644
--- a/hw/ip/aes/data/aes.hjson
+++ b/hw/ip/aes/data/aes.hjson
@@ -39,8 +39,19 @@
     }
   ],
   alert_list: [
-    { name: "ctrl_err",
-      desc: "This alert is triggered upon detecting an error in the Control Register",
+    { name: "ctrl_err_update",
+      desc: '''
+        This minor alert is triggered upon detecting an update error in the Control Register.
+        The AES unit recovers from such a condition automatically.
+        No further action needs to be taken but this should be monitored by the system.
+      '''
+    }
+    { name: "ctrl_err_storage",
+      desc: '''
+        This major alert is triggered upon detecting a storage error in the Control Register.
+        It is fatal.
+        The AES unit cannot recover from such an error and needs to be reset.
+      '''
     }
   ],
   regwidth: "32",
@@ -358,7 +369,7 @@
     # Tag info (CSR test exclusions):
     #  Updated by the HW.
     #  Updates based on writes to other regs.
-    #  -> Exclude all fields from init and write-read checks.
+    #  -> Exclude all fields (except CTRL_STORAGE_ERROR) from init and write-read checks.
     #  Upon reset, internal operations are triggered that temporarily change the IDLE field.
     #  -> Exclude IDLE field from init and write-read checks (also in reset test).
     fields: [
@@ -399,6 +410,14 @@
         '''
         tags: ["excl:CsrNonInitTests:CsrExclCheck"]
       }
+      { bits: "4",
+        name: "CTRL_ERR_STORAGE",
+        resval: "0",
+        desc:  '''
+          No storage error detected in the Control Register (0).
+          A storage error has been detected in the Control Register and the AES unit needs to be reset (1).
+        '''
+      }
     ]
   },
   ],
diff --git a/hw/ip/aes/dv/tb/tb.sv b/hw/ip/aes/dv/tb/tb.sv
index a08972b..c4713fc 100644
--- a/hw/ip/aes/dv/tb/tb.sv
+++ b/hw/ip/aes/dv/tb/tb.sv
@@ -18,6 +18,7 @@
   wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
   prim_alert_pkg::alert_rx_t [aes_pkg::NumAlerts-1:0] alert_rx;
   assign alert_rx[0] = 4'b0101;
+  assign alert_rx[1] = 4'b0101;
 
   // interfaces
   clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n));
diff --git a/hw/ip/aes/rtl/aes.sv b/hw/ip/aes/rtl/aes.sv
index 3c238b0..9440dd2 100644
--- a/hw/ip/aes/rtl/aes.sv
+++ b/hw/ip/aes/rtl/aes.sv
@@ -15,10 +15,11 @@
                                                          // Note: currently, constant masks are
                                                          // used, this is of course not secure.
   parameter sbox_impl_e  SBoxImpl                   = SBoxImplLut, // See aes_pkg.sv
-  parameter int unsigned NumDelayCyclesStartTrigger = 0 // Manual start trigger delay, useful for
-                                                        // SCA measurements. A value of e.g. 40
-                                                        // allows the processor to go into sleep
-                                                        // before AES starts operation.
+  parameter int unsigned NumDelayCyclesStartTrigger = 0, // Manual start trigger delay, useful for
+                                                         // SCA measurements. A value of e.g. 40
+                                                         // allows the processor to go into sleep
+                                                         // before AES starts operation.
+  parameter logic [NumAlerts-1:0] AlertAsyncOn      = {NumAlerts{1'b1}}
 ) (
   input                     clk_i,
   input                     rst_ni,
@@ -74,13 +75,14 @@
     .clk_i,
     .rst_ni,
 
-    .prng_data_req_o   ( prng_data_req   ),
-    .prng_data_ack_i   ( prng_data_ack   ),
-    .prng_data_i       ( prng_data       ),
-    .prng_reseed_req_o ( prng_reseed_req ),
-    .prng_reseed_ack_i ( prng_reseed_ack ),
+    .prng_data_req_o    ( prng_data_req   ),
+    .prng_data_ack_i    ( prng_data_ack   ),
+    .prng_data_i        ( prng_data       ),
+    .prng_reseed_req_o  ( prng_reseed_req ),
+    .prng_reseed_ack_i  ( prng_reseed_ack ),
 
-    .ctrl_err_o        ( alert[0]        ),
+    .ctrl_err_update_o  ( alert[0]        ),
+    .ctrl_err_storage_o ( alert[1]        ),
 
     .reg2hw,
     .hw2reg
diff --git a/hw/ip/aes/rtl/aes_control.sv b/hw/ip/aes/rtl/aes_control.sv
index 760c9f6..1c9dd43 100644
--- a/hw/ip/aes/rtl/aes_control.sv
+++ b/hw/ip/aes/rtl/aes_control.sv
@@ -18,7 +18,7 @@
   // Main control signals
   input  logic                    ctrl_qe_i,
   output logic                    ctrl_we_o,
-  input  logic                    ctrl_err_i,
+  input  logic                    ctrl_err_storage_i,
   input  aes_pkg::aes_op_e        op_i,
   input  aes_pkg::aes_mode_e      mode_i,
   input  aes_pkg::ciph_op_e       cipher_op_i,
@@ -176,7 +176,7 @@
 
   // The cipher core is only ever allowed to start or finish if the control register holds a valid
   // configuration.
-  assign cfg_valid = ~((mode_i == AES_NONE) | ctrl_err_i);
+  assign cfg_valid = ~((mode_i == AES_NONE) | ctrl_err_storage_i);
 
   // If set to start manually, we just wait for the trigger. Otherwise, we start once we have valid
   // data available. If the IV (and counter) is needed, we only start if also the IV (and counter)
@@ -284,8 +284,9 @@
           key_init_we_o  = key_init_qe_i;
           iv_we_o        = iv_qe;
 
-          // Control register updates are only allowed if we are idle.
-          ctrl_we_o      = ctrl_qe_i;
+          // Updates to the control register are only allowed if we are idle and we don't have a
+          // storage error. A storage error is unrecoverable and requires a reset.
+          ctrl_we_o      = !ctrl_err_storage_i ? ctrl_qe_i : 1'b0;
 
           // Control register updates clear all register status trackers.
           key_init_clear = ctrl_we_o;
diff --git a/hw/ip/aes/rtl/aes_core.sv b/hw/ip/aes/rtl/aes_core.sv
index cc3794f..fe19049 100644
--- a/hw/ip/aes/rtl/aes_core.sv
+++ b/hw/ip/aes/rtl/aes_core.sv
@@ -27,7 +27,8 @@
   input  logic                     prng_reseed_ack_i,
 
   // Alerts
-  output logic                     ctrl_err_o,
+  output logic                     ctrl_err_update_o,
+  output logic                     ctrl_err_storage_o,
 
   // Bus Interface
   input  aes_reg_pkg::aes_reg2hw_t reg2hw,
@@ -48,7 +49,6 @@
   key_len_e             key_len_q;
   logic                 manual_operation_q;
   ctrl_reg_t            ctrl_d, ctrl_q;
-  logic                 ctrl_err_update, ctrl_err_storage;
 
   logic [3:0][3:0][7:0] state_in;
   si_sel_e              state_in_sel;
@@ -376,21 +376,23 @@
     .SWACCESS ( "WO"              ),
     .RESVAL   ( CTRL_RESET        )
   ) u_ctrl_reg_shadowed (
-    .clk_i       ( clk_i            ),
-    .rst_ni      ( rst_ni           ),
-    .re          ( ctrl_re          ),
-    .we          ( ctrl_we          ),
-    .wd          ( ctrl_d           ),
-    .de          ( 1'b0             ),
-    .d           ( '0               ),
-    .qe          (                  ),
-    .q           ( ctrl_q           ),
-    .qs          (                  ),
-    .err_update  ( ctrl_err_update  ),
-    .err_storage ( ctrl_err_storage )
+    .clk_i       ( clk_i              ),
+    .rst_ni      ( rst_ni             ),
+    .re          ( ctrl_re            ),
+    .we          ( ctrl_we            ),
+    .wd          ( ctrl_d             ),
+    .de          ( 1'b0               ),
+    .d           ( '0                 ),
+    .qe          (                    ),
+    .q           ( ctrl_q             ),
+    .qs          (                    ),
+    .err_update  ( ctrl_err_update_o  ),
+    .err_storage ( ctrl_err_storage_o )
   );
 
-  assign ctrl_err_o = ctrl_err_update | ctrl_err_storage;
+  // Make sure the storage error is observable via status register.
+  assign hw2reg.status.ctrl_err_storage.d  = ctrl_err_storage_o;
+  assign hw2reg.status.ctrl_err_storage.de = ctrl_err_storage_o;
 
   // Get shorter references.
   assign aes_op_q           = ctrl_q.operation;
@@ -411,7 +413,7 @@
 
     .ctrl_qe_i               ( ctrl_qe                          ),
     .ctrl_we_o               ( ctrl_we                          ),
-    .ctrl_err_i              ( ctrl_err_storage                 ),
+    .ctrl_err_storage_i      ( ctrl_err_storage_o               ),
     .op_i                    ( aes_op_q                         ),
     .mode_i                  ( aes_mode_q                       ),
     .cipher_op_i             ( cipher_op                        ),
diff --git a/hw/ip/aes/rtl/aes_pkg.sv b/hw/ip/aes/rtl/aes_pkg.sv
index 2f855e2..9540c52 100644
--- a/hw/ip/aes/rtl/aes_pkg.sv
+++ b/hw/ip/aes/rtl/aes_pkg.sv
@@ -6,8 +6,7 @@
 
 package aes_pkg;
 
-parameter int NumAlerts = 1;
-parameter logic [NumAlerts-1:0] AlertAsyncOn = NumAlerts'(1'b1);
+parameter int NumAlerts = 2;
 
 typedef enum integer {
   SBoxImplLut,                  // Unmasked LUT-based S-Box
diff --git a/hw/ip/aes/rtl/aes_reg_pkg.sv b/hw/ip/aes/rtl/aes_reg_pkg.sv
index db9a1b2..5a9dcfc 100644
--- a/hw/ip/aes/rtl/aes_reg_pkg.sv
+++ b/hw/ip/aes/rtl/aes_reg_pkg.sv
@@ -164,6 +164,10 @@
       logic        d;
       logic        de;
     } input_ready;
+    struct packed {
+      logic        d;
+      logic        de;
+    } ctrl_err_storage;
   } aes_hw2reg_status_reg_t;
 
 
@@ -184,14 +188,14 @@
   // Internal design logic to register //
   ///////////////////////////////////////
   typedef struct packed {
-    aes_hw2reg_key_share0_mreg_t [7:0] key_share0; // [930:675]
-    aes_hw2reg_key_share1_mreg_t [7:0] key_share1; // [674:419]
-    aes_hw2reg_iv_mreg_t [3:0] iv; // [418:291]
-    aes_hw2reg_data_in_mreg_t [3:0] data_in; // [290:159]
-    aes_hw2reg_data_out_mreg_t [3:0] data_out; // [158:31]
-    aes_hw2reg_ctrl_shadowed_reg_t ctrl_shadowed; // [30:16]
-    aes_hw2reg_trigger_reg_t trigger; // [15:10]
-    aes_hw2reg_status_reg_t status; // [9:10]
+    aes_hw2reg_key_share0_mreg_t [7:0] key_share0; // [932:677]
+    aes_hw2reg_key_share1_mreg_t [7:0] key_share1; // [676:421]
+    aes_hw2reg_iv_mreg_t [3:0] iv; // [420:293]
+    aes_hw2reg_data_in_mreg_t [3:0] data_in; // [292:161]
+    aes_hw2reg_data_out_mreg_t [3:0] data_out; // [160:33]
+    aes_hw2reg_ctrl_shadowed_reg_t ctrl_shadowed; // [32:18]
+    aes_hw2reg_trigger_reg_t trigger; // [17:12]
+    aes_hw2reg_status_reg_t status; // [11:12]
   } aes_hw2reg_t;
 
   // Register Address
diff --git a/hw/ip/aes/rtl/aes_reg_top.sv b/hw/ip/aes/rtl/aes_reg_top.sv
index 96fe46c..58f53c6 100644
--- a/hw/ip/aes/rtl/aes_reg_top.sv
+++ b/hw/ip/aes/rtl/aes_reg_top.sv
@@ -159,6 +159,7 @@
   logic status_stall_qs;
   logic status_output_valid_qs;
   logic status_input_ready_qs;
+  logic status_ctrl_err_storage_qs;
 
   // Register instances
 
@@ -975,6 +976,31 @@
   );
 
 
+  //   F[ctrl_err_storage]: 4:4
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RO"),
+    .RESVAL  (1'h0)
+  ) u_status_ctrl_err_storage (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    .we     (1'b0),
+    .wd     ('0  ),
+
+    // from internal hardware
+    .de     (hw2reg.status.ctrl_err_storage.de),
+    .d      (hw2reg.status.ctrl_err_storage.d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (status_ctrl_err_storage_qs)
+  );
+
+
 
 
   logic [30:0] addr_hit;
@@ -1169,6 +1195,7 @@
 
 
 
+
   // Read data return
   always_comb begin
     reg_rdata_next = '0;
@@ -1306,6 +1333,7 @@
         reg_rdata_next[1] = status_stall_qs;
         reg_rdata_next[2] = status_output_valid_qs;
         reg_rdata_next[3] = status_input_ready_qs;
+        reg_rdata_next[4] = status_ctrl_err_storage_qs;
       end
 
       default: begin
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 0677413..9934dc8 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -798,7 +798,13 @@
       alert_list:
       [
         {
-          name: ctrl_err
+          name: ctrl_err_update
+          width: 1
+          type: alert
+          async: 0
+        }
+        {
+          name: ctrl_err_storage
           width: 1
           type: alert
           async: 0
@@ -4106,7 +4112,14 @@
   alert:
   [
     {
-      name: aes_ctrl_err
+      name: aes_ctrl_err_update
+      width: 1
+      type: alert
+      async: 0
+      module_name: aes
+    }
+    {
+      name: aes_ctrl_err_storage
       width: 1
       type: alert
       async: 0
diff --git a/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson b/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson
index 8388f0b..5a1e996 100644
--- a/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson
+++ b/hw/top_earlgrey/ip/alert_handler/data/autogen/alert_handler.hjson
@@ -30,7 +30,7 @@
     { name: "NAlerts",
       desc: "Number of peripheral inputs",
       type: "int",
-      default: "12",
+      default: "13",
       local: "true"
     },
     { name: "EscCntDw",
@@ -54,7 +54,7 @@
     { name: "AsyncOn",
       desc: "Number of peripheral outputs",
       type: "logic [NAlerts-1:0]",
-      default: "12'b111111100000",
+      default: "13'b1111111000000",
       local: "true"
     },
     { name: "N_CLASSES",
diff --git a/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_env_pkg__params.sv b/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_env_pkg__params.sv
index 28bc9be..d5abde7 100644
--- a/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_env_pkg__params.sv
+++ b/hw/top_earlgrey/ip/alert_handler/dv/alert_handler_env_pkg__params.sv
@@ -10,5 +10,5 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-parameter uint NUM_ALERTS = 12;
-parameter bit [NUM_ALERTS-1:0] ASYNC_ON = 12'b111111100000;
+parameter uint NUM_ALERTS = 13;
+parameter bit [NUM_ALERTS-1:0] ASYNC_ON = 13'b1111111000000;
diff --git a/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv b/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv
index 4082f61..2135bc2 100644
--- a/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv
+++ b/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_pkg.sv
@@ -7,11 +7,11 @@
 package alert_handler_reg_pkg;
 
   // Param list
-  parameter int NAlerts = 12;
+  parameter int NAlerts = 13;
   parameter int EscCntDw = 32;
   parameter int AccuCntDw = 16;
   parameter int LfsrSeed = 2147483647;
-  parameter logic [NAlerts-1:0] AsyncOn = 12'b111111100000;
+  parameter logic [NAlerts-1:0] AsyncOn = 13'b1111111000000;
   parameter int N_CLASSES = 4;
   parameter int N_ESC_SEV = 4;
   parameter int N_PHASES = 4;
@@ -455,14 +455,14 @@
   // Register to internal design logic //
   ///////////////////////////////////////
   typedef struct packed {
-    alert_handler_reg2hw_intr_state_reg_t intr_state; // [872:869]
-    alert_handler_reg2hw_intr_enable_reg_t intr_enable; // [868:865]
-    alert_handler_reg2hw_intr_test_reg_t intr_test; // [864:857]
-    alert_handler_reg2hw_regen_reg_t regen; // [856:856]
-    alert_handler_reg2hw_ping_timeout_cyc_reg_t ping_timeout_cyc; // [855:832]
-    alert_handler_reg2hw_alert_en_mreg_t [11:0] alert_en; // [831:820]
-    alert_handler_reg2hw_alert_class_mreg_t [11:0] alert_class; // [819:796]
-    alert_handler_reg2hw_alert_cause_mreg_t [11:0] alert_cause; // [795:784]
+    alert_handler_reg2hw_intr_state_reg_t intr_state; // [876:873]
+    alert_handler_reg2hw_intr_enable_reg_t intr_enable; // [872:869]
+    alert_handler_reg2hw_intr_test_reg_t intr_test; // [868:861]
+    alert_handler_reg2hw_regen_reg_t regen; // [860:860]
+    alert_handler_reg2hw_ping_timeout_cyc_reg_t ping_timeout_cyc; // [859:836]
+    alert_handler_reg2hw_alert_en_mreg_t [12:0] alert_en; // [835:823]
+    alert_handler_reg2hw_alert_class_mreg_t [12:0] alert_class; // [822:797]
+    alert_handler_reg2hw_alert_cause_mreg_t [12:0] alert_cause; // [796:784]
     alert_handler_reg2hw_loc_alert_en_mreg_t [3:0] loc_alert_en; // [783:780]
     alert_handler_reg2hw_loc_alert_class_mreg_t [3:0] loc_alert_class; // [779:772]
     alert_handler_reg2hw_loc_alert_cause_mreg_t [3:0] loc_alert_cause; // [771:768]
@@ -504,8 +504,8 @@
   // Internal design logic to register //
   ///////////////////////////////////////
   typedef struct packed {
-    alert_handler_hw2reg_intr_state_reg_t intr_state; // [251:248]
-    alert_handler_hw2reg_alert_cause_mreg_t [11:0] alert_cause; // [247:224]
+    alert_handler_hw2reg_intr_state_reg_t intr_state; // [253:250]
+    alert_handler_hw2reg_alert_cause_mreg_t [12:0] alert_cause; // [249:224]
     alert_handler_hw2reg_loc_alert_cause_mreg_t [3:0] loc_alert_cause; // [223:216]
     alert_handler_hw2reg_classa_clren_reg_t classa_clren; // [215:216]
     alert_handler_hw2reg_classa_accum_cnt_reg_t classa_accum_cnt; // [215:216]
@@ -658,7 +658,7 @@
     4'b 0001, // index[ 3] ALERT_HANDLER_REGEN
     4'b 0111, // index[ 4] ALERT_HANDLER_PING_TIMEOUT_CYC
     4'b 0011, // index[ 5] ALERT_HANDLER_ALERT_EN
-    4'b 0111, // index[ 6] ALERT_HANDLER_ALERT_CLASS
+    4'b 1111, // index[ 6] ALERT_HANDLER_ALERT_CLASS
     4'b 0011, // index[ 7] ALERT_HANDLER_ALERT_CAUSE
     4'b 0001, // index[ 8] ALERT_HANDLER_LOC_ALERT_EN
     4'b 0001, // index[ 9] ALERT_HANDLER_LOC_ALERT_CLASS
diff --git a/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_top.sv b/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_top.sv
index 781f7ca..32496b9 100644
--- a/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_top.sv
+++ b/hw/top_earlgrey/ip/alert_handler/rtl/autogen/alert_handler_reg_top.sv
@@ -145,6 +145,9 @@
   logic alert_en_en_a_11_qs;
   logic alert_en_en_a_11_wd;
   logic alert_en_en_a_11_we;
+  logic alert_en_en_a_12_qs;
+  logic alert_en_en_a_12_wd;
+  logic alert_en_en_a_12_we;
   logic [1:0] alert_class_class_a_0_qs;
   logic [1:0] alert_class_class_a_0_wd;
   logic alert_class_class_a_0_we;
@@ -181,6 +184,9 @@
   logic [1:0] alert_class_class_a_11_qs;
   logic [1:0] alert_class_class_a_11_wd;
   logic alert_class_class_a_11_we;
+  logic [1:0] alert_class_class_a_12_qs;
+  logic [1:0] alert_class_class_a_12_wd;
+  logic alert_class_class_a_12_we;
   logic alert_cause_a_0_qs;
   logic alert_cause_a_0_wd;
   logic alert_cause_a_0_we;
@@ -217,6 +223,9 @@
   logic alert_cause_a_11_qs;
   logic alert_cause_a_11_wd;
   logic alert_cause_a_11_we;
+  logic alert_cause_a_12_qs;
+  logic alert_cause_a_12_wd;
+  logic alert_cause_a_12_we;
   logic loc_alert_en_en_la_0_qs;
   logic loc_alert_en_en_la_0_wd;
   logic loc_alert_en_en_la_0_we;
@@ -1135,6 +1144,32 @@
   );
 
 
+  // F[en_a_12]: 12:12
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_alert_en_en_a_12 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (alert_en_en_a_12_we & regen_qs),
+    .wd     (alert_en_en_a_12_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.alert_en[12].q ),
+
+    // to register interface (read)
+    .qs     (alert_en_en_a_12_qs)
+  );
+
+
 
 
   // Subregister 0 of Multireg alert_class
@@ -1452,6 +1487,32 @@
   );
 
 
+  // F[class_a_12]: 25:24
+  prim_subreg #(
+    .DW      (2),
+    .SWACCESS("RW"),
+    .RESVAL  (2'h0)
+  ) u_alert_class_class_a_12 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (alert_class_class_a_12_we & regen_qs),
+    .wd     (alert_class_class_a_12_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.alert_class[12].q ),
+
+    // to register interface (read)
+    .qs     (alert_class_class_a_12_qs)
+  );
+
+
 
 
   // Subregister 0 of Multireg alert_cause
@@ -1769,6 +1830,32 @@
   );
 
 
+  // F[a_12]: 12:12
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("W1C"),
+    .RESVAL  (1'h0)
+  ) u_alert_cause_a_12 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (alert_cause_a_12_we),
+    .wd     (alert_cause_a_12_wd),
+
+    // from internal hardware
+    .de     (hw2reg.alert_cause[12].de),
+    .d      (hw2reg.alert_cause[12].d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.alert_cause[12].q ),
+
+    // to register interface (read)
+    .qs     (alert_cause_a_12_qs)
+  );
+
+
 
 
   // Subregister 0 of Multireg loc_alert_en
@@ -4407,6 +4494,9 @@
   assign alert_en_en_a_11_we = addr_hit[5] & reg_we & ~wr_err;
   assign alert_en_en_a_11_wd = reg_wdata[11];
 
+  assign alert_en_en_a_12_we = addr_hit[5] & reg_we & ~wr_err;
+  assign alert_en_en_a_12_wd = reg_wdata[12];
+
   assign alert_class_class_a_0_we = addr_hit[6] & reg_we & ~wr_err;
   assign alert_class_class_a_0_wd = reg_wdata[1:0];
 
@@ -4443,6 +4533,9 @@
   assign alert_class_class_a_11_we = addr_hit[6] & reg_we & ~wr_err;
   assign alert_class_class_a_11_wd = reg_wdata[23:22];
 
+  assign alert_class_class_a_12_we = addr_hit[6] & reg_we & ~wr_err;
+  assign alert_class_class_a_12_wd = reg_wdata[25:24];
+
   assign alert_cause_a_0_we = addr_hit[7] & reg_we & ~wr_err;
   assign alert_cause_a_0_wd = reg_wdata[0];
 
@@ -4479,6 +4572,9 @@
   assign alert_cause_a_11_we = addr_hit[7] & reg_we & ~wr_err;
   assign alert_cause_a_11_wd = reg_wdata[11];
 
+  assign alert_cause_a_12_we = addr_hit[7] & reg_we & ~wr_err;
+  assign alert_cause_a_12_wd = reg_wdata[12];
+
   assign loc_alert_en_en_la_0_we = addr_hit[8] & reg_we & ~wr_err;
   assign loc_alert_en_en_la_0_wd = reg_wdata[0];
 
@@ -4801,6 +4897,7 @@
         reg_rdata_next[9] = alert_en_en_a_9_qs;
         reg_rdata_next[10] = alert_en_en_a_10_qs;
         reg_rdata_next[11] = alert_en_en_a_11_qs;
+        reg_rdata_next[12] = alert_en_en_a_12_qs;
       end
 
       addr_hit[6]: begin
@@ -4816,6 +4913,7 @@
         reg_rdata_next[19:18] = alert_class_class_a_9_qs;
         reg_rdata_next[21:20] = alert_class_class_a_10_qs;
         reg_rdata_next[23:22] = alert_class_class_a_11_qs;
+        reg_rdata_next[25:24] = alert_class_class_a_12_qs;
       end
 
       addr_hit[7]: begin
@@ -4831,6 +4929,7 @@
         reg_rdata_next[9] = alert_cause_a_9_qs;
         reg_rdata_next[10] = alert_cause_a_10_qs;
         reg_rdata_next[11] = alert_cause_a_11_qs;
+        reg_rdata_next[12] = alert_cause_a_12_qs;
       end
 
       addr_hit[8]: begin
diff --git a/hw/top_earlgrey/ip/rv_plic/fpv/autogen/rv_plic_csr_assert_fpv.sv b/hw/top_earlgrey/ip/rv_plic/fpv/autogen/rv_plic_csr_assert_fpv.sv
new file mode 100644
index 0000000..67aa2a3
--- /dev/null
+++ b/hw/top_earlgrey/ip/rv_plic/fpv/autogen/rv_plic_csr_assert_fpv.sv
@@ -0,0 +1,505 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// FPV CSR read and write assertions auto-generated by `reggen` containing data structure
+// Do Not Edit directly
+// TODO: This automation does not support: shadow reg and regwen reg
+// This automation assumes that W1C and W0C are registers with 1 bit per field
+
+`include "prim_assert.sv"
+
+// Block: rv_plic
+module rv_plic_csr_assert_fpv import tlul_pkg::*; import rv_plic_reg_pkg::*; (
+  input clk_i,
+  input rst_ni,
+
+  // tile link ports
+  input tl_h2d_t h2d,
+  input tl_d2h_t d2h,
+
+  // reg and hw ports
+  input rv_plic_reg2hw_t reg2hw,
+  input rv_plic_hw2reg_t hw2reg
+);
+
+  parameter int DWidth = 32;
+  // mask register to convert byte to bit
+  logic [DWidth-1:0] a_mask_bit;
+
+  assign a_mask_bit[7:0]   = h2d.a_mask[0] ? '1 : '0;
+  assign a_mask_bit[15:8]  = h2d.a_mask[1] ? '1 : '0;
+  assign a_mask_bit[23:16] = h2d.a_mask[2] ? '1 : '0;
+  assign a_mask_bit[31:24] = h2d.a_mask[3] ? '1 : '0;
+
+  // declare common read and write sequences
+  sequence device_wr_S(logic [9:0] addr);
+    h2d.a_address == addr && h2d.a_opcode inside {PutFullData, PutPartialData} &&
+        h2d.a_valid && h2d.d_ready && !d2h.d_valid;
+  endsequence
+
+  sequence device_rd_S(logic [9:0] addr);
+    h2d.a_address == addr && h2d.a_opcode inside {Get} && h2d.a_valid && h2d.d_ready &&
+        !d2h.d_valid;
+  endsequence
+
+  // declare common read and write properties
+  // for homog registers, we check by a reg; for non-homog regs, we check by field.
+  // `mask` is used for checking by field. It masks out any act_data that are not within the field
+  // `lsb` is used to check non-homog multi_reg. Because we are using a local copy `_fpv` variable
+  // to store all the multi-reg within one basefield, we need to shift the `_fpv` value to the
+  // correct bits, then compare with read/write exp_data.
+
+  property wr_P(bit [9:0] addr, bit [DWidth-1:0] act_data, bit regen,
+                bit [DWidth-1:0] mask, int lsb);
+    logic [DWidth-1:0] id, exp_data;
+    (device_wr_S(addr), id = h2d.a_source, exp_data = h2d.a_data & a_mask_bit & mask) ##1
+        first_match(##[0:$] d2h.d_valid && d2h.d_source == id) |->
+        (d2h.d_error || (act_data << lsb) == exp_data || !regen);
+  endproperty
+
+  // external reg will use one clk cycle to update act_data from external
+  property wr_ext_P(bit [9:0] addr, bit [DWidth-1:0] act_data, bit regen,
+                    bit [DWidth-1:0] mask, int lsb);
+    logic [DWidth-1:0] id, exp_data;
+    (device_wr_S(addr), id = h2d.a_source, exp_data = h2d.a_data & a_mask_bit & mask) ##1
+        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
+        (d2h.d_error || ($past(act_data) << lsb) == exp_data || !regen);
+  endproperty
+
+  property w1c_P(bit [9:0] addr, bit [DWidth-1:0] act_data, bit regen,
+                bit [DWidth-1:0] mask, int lsb);
+    logic [DWidth-1:0] id, exp_data;
+    (device_wr_S(addr), id = h2d.a_source, exp_data = h2d.a_data & a_mask_bit & mask & '0) ##1
+        first_match(##[0:$] d2h.d_valid && d2h.d_source == id) |->
+        (d2h.d_error || (act_data << lsb) == exp_data || !regen);
+  endproperty
+
+  property w1c_ext_P(bit [9:0] addr, bit [DWidth-1:0] act_data, bit regen,
+                    bit [DWidth-1:0] mask, int lsb);
+    logic [DWidth-1:0] id, exp_data;
+    (device_wr_S(addr), id = h2d.a_source, exp_data = h2d.a_data & a_mask_bit & mask & '0) ##1
+        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
+        (d2h.d_error || ($past(act_data) << lsb) == exp_data || !regen);
+  endproperty
+
+  property rd_P(bit [9:0] addr, bit [DWidth-1:0] act_data, bit [DWidth-1:0] mask, int lsb);
+    logic [DWidth-1:0] id, exp_data;
+    (device_rd_S(addr), id = h2d.a_source, exp_data = $past(act_data)) ##1
+        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
+        (d2h.d_error || (d2h.d_data & mask) >> lsb == exp_data);
+  endproperty
+
+  property rd_ext_P(bit [9:0] addr, bit [DWidth-1:0] act_data, bit [DWidth-1:0] mask,
+      int lsb);
+    logic [DWidth-1:0] id, exp_data;
+    (device_rd_S(addr), id = h2d.a_source, exp_data = act_data) ##1
+        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
+        (d2h.d_error || (d2h.d_data & mask) >> lsb == exp_data);
+  endproperty
+
+  // read a WO register, always return 0
+  property r_wo_P(bit [9:0] addr);
+    logic [DWidth-1:0] id;
+    (device_rd_S(addr), id = h2d.a_source) ##1
+        first_match(##[0:$] (d2h.d_valid && d2h.d_source == id)) |->
+        (d2h.d_error || d2h.d_data == 0);
+  endproperty
+
+  // TODO: currently not used, will use once support regwen reg
+  property wr_regen_stable_P(bit regen, bit [DWidth-1:0] exp_data);
+    (!regen && $stable(regen)) |-> $stable(exp_data);
+  endproperty
+
+
+  // define local fpv variable for multi-reg
+  logic [82:0] ip_d_fpv;
+  for (genvar s = 0; s < 83; s++) begin : gen_ip_q
+    assign ip_d_fpv[((s+1)*1-1):s*1] = hw2reg.ip[s].d;
+  end
+
+  // assertions for register: ip0
+  `ASSERT(ip0_rd_A, rd_P(10'h0, ip_d_fpv[31:0], 'hffffffff, 0))
+  // assertions for register: ip1
+  `ASSERT(ip1_rd_A, rd_P(10'h4, ip_d_fpv[63:32], 'hffffffff, 0))
+  // assertions for register: ip2
+  `ASSERT(ip2_rd_A, rd_P(10'h8, ip_d_fpv[82:64], 'h7ffff, 0))
+
+  // define local fpv variable for multi-reg
+  logic [82:0] le_q_fpv;
+  for (genvar s = 0; s < 83; s++) begin : gen_le_q
+    assign le_q_fpv[((s+1)*1-1):s*1] = reg2hw.le[s].q;
+  end
+
+  // assertions for register: le0
+  `ASSERT(le0_wr_A, wr_P(10'hc, le_q_fpv[31:0], 1, 'hffffffff, 0))
+  `ASSERT(le0_rd_A, rd_P(10'hc, le_q_fpv[31:0], 'hffffffff, 0))
+  // assertions for register: le1
+  `ASSERT(le1_wr_A, wr_P(10'h10, le_q_fpv[63:32], 1, 'hffffffff, 0))
+  `ASSERT(le1_rd_A, rd_P(10'h10, le_q_fpv[63:32], 'hffffffff, 0))
+  // assertions for register: le2
+  `ASSERT(le2_wr_A, wr_P(10'h14, le_q_fpv[82:64], 1, 'h7ffff, 0))
+  `ASSERT(le2_rd_A, rd_P(10'h14, le_q_fpv[82:64], 'h7ffff, 0))
+
+  // assertions for register: prio0
+  `ASSERT(prio0_wr_A, wr_P(10'h18, reg2hw.prio0.q, 1, 'h3, 0))
+  `ASSERT(prio0_rd_A, rd_P(10'h18, reg2hw.prio0.q, 'hffffffff, 0))
+
+  // assertions for register: prio1
+  `ASSERT(prio1_wr_A, wr_P(10'h1c, reg2hw.prio1.q, 1, 'h3, 0))
+  `ASSERT(prio1_rd_A, rd_P(10'h1c, reg2hw.prio1.q, 'hffffffff, 0))
+
+  // assertions for register: prio2
+  `ASSERT(prio2_wr_A, wr_P(10'h20, reg2hw.prio2.q, 1, 'h3, 0))
+  `ASSERT(prio2_rd_A, rd_P(10'h20, reg2hw.prio2.q, 'hffffffff, 0))
+
+  // assertions for register: prio3
+  `ASSERT(prio3_wr_A, wr_P(10'h24, reg2hw.prio3.q, 1, 'h3, 0))
+  `ASSERT(prio3_rd_A, rd_P(10'h24, reg2hw.prio3.q, 'hffffffff, 0))
+
+  // assertions for register: prio4
+  `ASSERT(prio4_wr_A, wr_P(10'h28, reg2hw.prio4.q, 1, 'h3, 0))
+  `ASSERT(prio4_rd_A, rd_P(10'h28, reg2hw.prio4.q, 'hffffffff, 0))
+
+  // assertions for register: prio5
+  `ASSERT(prio5_wr_A, wr_P(10'h2c, reg2hw.prio5.q, 1, 'h3, 0))
+  `ASSERT(prio5_rd_A, rd_P(10'h2c, reg2hw.prio5.q, 'hffffffff, 0))
+
+  // assertions for register: prio6
+  `ASSERT(prio6_wr_A, wr_P(10'h30, reg2hw.prio6.q, 1, 'h3, 0))
+  `ASSERT(prio6_rd_A, rd_P(10'h30, reg2hw.prio6.q, 'hffffffff, 0))
+
+  // assertions for register: prio7
+  `ASSERT(prio7_wr_A, wr_P(10'h34, reg2hw.prio7.q, 1, 'h3, 0))
+  `ASSERT(prio7_rd_A, rd_P(10'h34, reg2hw.prio7.q, 'hffffffff, 0))
+
+  // assertions for register: prio8
+  `ASSERT(prio8_wr_A, wr_P(10'h38, reg2hw.prio8.q, 1, 'h3, 0))
+  `ASSERT(prio8_rd_A, rd_P(10'h38, reg2hw.prio8.q, 'hffffffff, 0))
+
+  // assertions for register: prio9
+  `ASSERT(prio9_wr_A, wr_P(10'h3c, reg2hw.prio9.q, 1, 'h3, 0))
+  `ASSERT(prio9_rd_A, rd_P(10'h3c, reg2hw.prio9.q, 'hffffffff, 0))
+
+  // assertions for register: prio10
+  `ASSERT(prio10_wr_A, wr_P(10'h40, reg2hw.prio10.q, 1, 'h3, 0))
+  `ASSERT(prio10_rd_A, rd_P(10'h40, reg2hw.prio10.q, 'hffffffff, 0))
+
+  // assertions for register: prio11
+  `ASSERT(prio11_wr_A, wr_P(10'h44, reg2hw.prio11.q, 1, 'h3, 0))
+  `ASSERT(prio11_rd_A, rd_P(10'h44, reg2hw.prio11.q, 'hffffffff, 0))
+
+  // assertions for register: prio12
+  `ASSERT(prio12_wr_A, wr_P(10'h48, reg2hw.prio12.q, 1, 'h3, 0))
+  `ASSERT(prio12_rd_A, rd_P(10'h48, reg2hw.prio12.q, 'hffffffff, 0))
+
+  // assertions for register: prio13
+  `ASSERT(prio13_wr_A, wr_P(10'h4c, reg2hw.prio13.q, 1, 'h3, 0))
+  `ASSERT(prio13_rd_A, rd_P(10'h4c, reg2hw.prio13.q, 'hffffffff, 0))
+
+  // assertions for register: prio14
+  `ASSERT(prio14_wr_A, wr_P(10'h50, reg2hw.prio14.q, 1, 'h3, 0))
+  `ASSERT(prio14_rd_A, rd_P(10'h50, reg2hw.prio14.q, 'hffffffff, 0))
+
+  // assertions for register: prio15
+  `ASSERT(prio15_wr_A, wr_P(10'h54, reg2hw.prio15.q, 1, 'h3, 0))
+  `ASSERT(prio15_rd_A, rd_P(10'h54, reg2hw.prio15.q, 'hffffffff, 0))
+
+  // assertions for register: prio16
+  `ASSERT(prio16_wr_A, wr_P(10'h58, reg2hw.prio16.q, 1, 'h3, 0))
+  `ASSERT(prio16_rd_A, rd_P(10'h58, reg2hw.prio16.q, 'hffffffff, 0))
+
+  // assertions for register: prio17
+  `ASSERT(prio17_wr_A, wr_P(10'h5c, reg2hw.prio17.q, 1, 'h3, 0))
+  `ASSERT(prio17_rd_A, rd_P(10'h5c, reg2hw.prio17.q, 'hffffffff, 0))
+
+  // assertions for register: prio18
+  `ASSERT(prio18_wr_A, wr_P(10'h60, reg2hw.prio18.q, 1, 'h3, 0))
+  `ASSERT(prio18_rd_A, rd_P(10'h60, reg2hw.prio18.q, 'hffffffff, 0))
+
+  // assertions for register: prio19
+  `ASSERT(prio19_wr_A, wr_P(10'h64, reg2hw.prio19.q, 1, 'h3, 0))
+  `ASSERT(prio19_rd_A, rd_P(10'h64, reg2hw.prio19.q, 'hffffffff, 0))
+
+  // assertions for register: prio20
+  `ASSERT(prio20_wr_A, wr_P(10'h68, reg2hw.prio20.q, 1, 'h3, 0))
+  `ASSERT(prio20_rd_A, rd_P(10'h68, reg2hw.prio20.q, 'hffffffff, 0))
+
+  // assertions for register: prio21
+  `ASSERT(prio21_wr_A, wr_P(10'h6c, reg2hw.prio21.q, 1, 'h3, 0))
+  `ASSERT(prio21_rd_A, rd_P(10'h6c, reg2hw.prio21.q, 'hffffffff, 0))
+
+  // assertions for register: prio22
+  `ASSERT(prio22_wr_A, wr_P(10'h70, reg2hw.prio22.q, 1, 'h3, 0))
+  `ASSERT(prio22_rd_A, rd_P(10'h70, reg2hw.prio22.q, 'hffffffff, 0))
+
+  // assertions for register: prio23
+  `ASSERT(prio23_wr_A, wr_P(10'h74, reg2hw.prio23.q, 1, 'h3, 0))
+  `ASSERT(prio23_rd_A, rd_P(10'h74, reg2hw.prio23.q, 'hffffffff, 0))
+
+  // assertions for register: prio24
+  `ASSERT(prio24_wr_A, wr_P(10'h78, reg2hw.prio24.q, 1, 'h3, 0))
+  `ASSERT(prio24_rd_A, rd_P(10'h78, reg2hw.prio24.q, 'hffffffff, 0))
+
+  // assertions for register: prio25
+  `ASSERT(prio25_wr_A, wr_P(10'h7c, reg2hw.prio25.q, 1, 'h3, 0))
+  `ASSERT(prio25_rd_A, rd_P(10'h7c, reg2hw.prio25.q, 'hffffffff, 0))
+
+  // assertions for register: prio26
+  `ASSERT(prio26_wr_A, wr_P(10'h80, reg2hw.prio26.q, 1, 'h3, 0))
+  `ASSERT(prio26_rd_A, rd_P(10'h80, reg2hw.prio26.q, 'hffffffff, 0))
+
+  // assertions for register: prio27
+  `ASSERT(prio27_wr_A, wr_P(10'h84, reg2hw.prio27.q, 1, 'h3, 0))
+  `ASSERT(prio27_rd_A, rd_P(10'h84, reg2hw.prio27.q, 'hffffffff, 0))
+
+  // assertions for register: prio28
+  `ASSERT(prio28_wr_A, wr_P(10'h88, reg2hw.prio28.q, 1, 'h3, 0))
+  `ASSERT(prio28_rd_A, rd_P(10'h88, reg2hw.prio28.q, 'hffffffff, 0))
+
+  // assertions for register: prio29
+  `ASSERT(prio29_wr_A, wr_P(10'h8c, reg2hw.prio29.q, 1, 'h3, 0))
+  `ASSERT(prio29_rd_A, rd_P(10'h8c, reg2hw.prio29.q, 'hffffffff, 0))
+
+  // assertions for register: prio30
+  `ASSERT(prio30_wr_A, wr_P(10'h90, reg2hw.prio30.q, 1, 'h3, 0))
+  `ASSERT(prio30_rd_A, rd_P(10'h90, reg2hw.prio30.q, 'hffffffff, 0))
+
+  // assertions for register: prio31
+  `ASSERT(prio31_wr_A, wr_P(10'h94, reg2hw.prio31.q, 1, 'h3, 0))
+  `ASSERT(prio31_rd_A, rd_P(10'h94, reg2hw.prio31.q, 'hffffffff, 0))
+
+  // assertions for register: prio32
+  `ASSERT(prio32_wr_A, wr_P(10'h98, reg2hw.prio32.q, 1, 'h3, 0))
+  `ASSERT(prio32_rd_A, rd_P(10'h98, reg2hw.prio32.q, 'hffffffff, 0))
+
+  // assertions for register: prio33
+  `ASSERT(prio33_wr_A, wr_P(10'h9c, reg2hw.prio33.q, 1, 'h3, 0))
+  `ASSERT(prio33_rd_A, rd_P(10'h9c, reg2hw.prio33.q, 'hffffffff, 0))
+
+  // assertions for register: prio34
+  `ASSERT(prio34_wr_A, wr_P(10'ha0, reg2hw.prio34.q, 1, 'h3, 0))
+  `ASSERT(prio34_rd_A, rd_P(10'ha0, reg2hw.prio34.q, 'hffffffff, 0))
+
+  // assertions for register: prio35
+  `ASSERT(prio35_wr_A, wr_P(10'ha4, reg2hw.prio35.q, 1, 'h3, 0))
+  `ASSERT(prio35_rd_A, rd_P(10'ha4, reg2hw.prio35.q, 'hffffffff, 0))
+
+  // assertions for register: prio36
+  `ASSERT(prio36_wr_A, wr_P(10'ha8, reg2hw.prio36.q, 1, 'h3, 0))
+  `ASSERT(prio36_rd_A, rd_P(10'ha8, reg2hw.prio36.q, 'hffffffff, 0))
+
+  // assertions for register: prio37
+  `ASSERT(prio37_wr_A, wr_P(10'hac, reg2hw.prio37.q, 1, 'h3, 0))
+  `ASSERT(prio37_rd_A, rd_P(10'hac, reg2hw.prio37.q, 'hffffffff, 0))
+
+  // assertions for register: prio38
+  `ASSERT(prio38_wr_A, wr_P(10'hb0, reg2hw.prio38.q, 1, 'h3, 0))
+  `ASSERT(prio38_rd_A, rd_P(10'hb0, reg2hw.prio38.q, 'hffffffff, 0))
+
+  // assertions for register: prio39
+  `ASSERT(prio39_wr_A, wr_P(10'hb4, reg2hw.prio39.q, 1, 'h3, 0))
+  `ASSERT(prio39_rd_A, rd_P(10'hb4, reg2hw.prio39.q, 'hffffffff, 0))
+
+  // assertions for register: prio40
+  `ASSERT(prio40_wr_A, wr_P(10'hb8, reg2hw.prio40.q, 1, 'h3, 0))
+  `ASSERT(prio40_rd_A, rd_P(10'hb8, reg2hw.prio40.q, 'hffffffff, 0))
+
+  // assertions for register: prio41
+  `ASSERT(prio41_wr_A, wr_P(10'hbc, reg2hw.prio41.q, 1, 'h3, 0))
+  `ASSERT(prio41_rd_A, rd_P(10'hbc, reg2hw.prio41.q, 'hffffffff, 0))
+
+  // assertions for register: prio42
+  `ASSERT(prio42_wr_A, wr_P(10'hc0, reg2hw.prio42.q, 1, 'h3, 0))
+  `ASSERT(prio42_rd_A, rd_P(10'hc0, reg2hw.prio42.q, 'hffffffff, 0))
+
+  // assertions for register: prio43
+  `ASSERT(prio43_wr_A, wr_P(10'hc4, reg2hw.prio43.q, 1, 'h3, 0))
+  `ASSERT(prio43_rd_A, rd_P(10'hc4, reg2hw.prio43.q, 'hffffffff, 0))
+
+  // assertions for register: prio44
+  `ASSERT(prio44_wr_A, wr_P(10'hc8, reg2hw.prio44.q, 1, 'h3, 0))
+  `ASSERT(prio44_rd_A, rd_P(10'hc8, reg2hw.prio44.q, 'hffffffff, 0))
+
+  // assertions for register: prio45
+  `ASSERT(prio45_wr_A, wr_P(10'hcc, reg2hw.prio45.q, 1, 'h3, 0))
+  `ASSERT(prio45_rd_A, rd_P(10'hcc, reg2hw.prio45.q, 'hffffffff, 0))
+
+  // assertions for register: prio46
+  `ASSERT(prio46_wr_A, wr_P(10'hd0, reg2hw.prio46.q, 1, 'h3, 0))
+  `ASSERT(prio46_rd_A, rd_P(10'hd0, reg2hw.prio46.q, 'hffffffff, 0))
+
+  // assertions for register: prio47
+  `ASSERT(prio47_wr_A, wr_P(10'hd4, reg2hw.prio47.q, 1, 'h3, 0))
+  `ASSERT(prio47_rd_A, rd_P(10'hd4, reg2hw.prio47.q, 'hffffffff, 0))
+
+  // assertions for register: prio48
+  `ASSERT(prio48_wr_A, wr_P(10'hd8, reg2hw.prio48.q, 1, 'h3, 0))
+  `ASSERT(prio48_rd_A, rd_P(10'hd8, reg2hw.prio48.q, 'hffffffff, 0))
+
+  // assertions for register: prio49
+  `ASSERT(prio49_wr_A, wr_P(10'hdc, reg2hw.prio49.q, 1, 'h3, 0))
+  `ASSERT(prio49_rd_A, rd_P(10'hdc, reg2hw.prio49.q, 'hffffffff, 0))
+
+  // assertions for register: prio50
+  `ASSERT(prio50_wr_A, wr_P(10'he0, reg2hw.prio50.q, 1, 'h3, 0))
+  `ASSERT(prio50_rd_A, rd_P(10'he0, reg2hw.prio50.q, 'hffffffff, 0))
+
+  // assertions for register: prio51
+  `ASSERT(prio51_wr_A, wr_P(10'he4, reg2hw.prio51.q, 1, 'h3, 0))
+  `ASSERT(prio51_rd_A, rd_P(10'he4, reg2hw.prio51.q, 'hffffffff, 0))
+
+  // assertions for register: prio52
+  `ASSERT(prio52_wr_A, wr_P(10'he8, reg2hw.prio52.q, 1, 'h3, 0))
+  `ASSERT(prio52_rd_A, rd_P(10'he8, reg2hw.prio52.q, 'hffffffff, 0))
+
+  // assertions for register: prio53
+  `ASSERT(prio53_wr_A, wr_P(10'hec, reg2hw.prio53.q, 1, 'h3, 0))
+  `ASSERT(prio53_rd_A, rd_P(10'hec, reg2hw.prio53.q, 'hffffffff, 0))
+
+  // assertions for register: prio54
+  `ASSERT(prio54_wr_A, wr_P(10'hf0, reg2hw.prio54.q, 1, 'h3, 0))
+  `ASSERT(prio54_rd_A, rd_P(10'hf0, reg2hw.prio54.q, 'hffffffff, 0))
+
+  // assertions for register: prio55
+  `ASSERT(prio55_wr_A, wr_P(10'hf4, reg2hw.prio55.q, 1, 'h3, 0))
+  `ASSERT(prio55_rd_A, rd_P(10'hf4, reg2hw.prio55.q, 'hffffffff, 0))
+
+  // assertions for register: prio56
+  `ASSERT(prio56_wr_A, wr_P(10'hf8, reg2hw.prio56.q, 1, 'h3, 0))
+  `ASSERT(prio56_rd_A, rd_P(10'hf8, reg2hw.prio56.q, 'hffffffff, 0))
+
+  // assertions for register: prio57
+  `ASSERT(prio57_wr_A, wr_P(10'hfc, reg2hw.prio57.q, 1, 'h3, 0))
+  `ASSERT(prio57_rd_A, rd_P(10'hfc, reg2hw.prio57.q, 'hffffffff, 0))
+
+  // assertions for register: prio58
+  `ASSERT(prio58_wr_A, wr_P(10'h100, reg2hw.prio58.q, 1, 'h3, 0))
+  `ASSERT(prio58_rd_A, rd_P(10'h100, reg2hw.prio58.q, 'hffffffff, 0))
+
+  // assertions for register: prio59
+  `ASSERT(prio59_wr_A, wr_P(10'h104, reg2hw.prio59.q, 1, 'h3, 0))
+  `ASSERT(prio59_rd_A, rd_P(10'h104, reg2hw.prio59.q, 'hffffffff, 0))
+
+  // assertions for register: prio60
+  `ASSERT(prio60_wr_A, wr_P(10'h108, reg2hw.prio60.q, 1, 'h3, 0))
+  `ASSERT(prio60_rd_A, rd_P(10'h108, reg2hw.prio60.q, 'hffffffff, 0))
+
+  // assertions for register: prio61
+  `ASSERT(prio61_wr_A, wr_P(10'h10c, reg2hw.prio61.q, 1, 'h3, 0))
+  `ASSERT(prio61_rd_A, rd_P(10'h10c, reg2hw.prio61.q, 'hffffffff, 0))
+
+  // assertions for register: prio62
+  `ASSERT(prio62_wr_A, wr_P(10'h110, reg2hw.prio62.q, 1, 'h3, 0))
+  `ASSERT(prio62_rd_A, rd_P(10'h110, reg2hw.prio62.q, 'hffffffff, 0))
+
+  // assertions for register: prio63
+  `ASSERT(prio63_wr_A, wr_P(10'h114, reg2hw.prio63.q, 1, 'h3, 0))
+  `ASSERT(prio63_rd_A, rd_P(10'h114, reg2hw.prio63.q, 'hffffffff, 0))
+
+  // assertions for register: prio64
+  `ASSERT(prio64_wr_A, wr_P(10'h118, reg2hw.prio64.q, 1, 'h3, 0))
+  `ASSERT(prio64_rd_A, rd_P(10'h118, reg2hw.prio64.q, 'hffffffff, 0))
+
+  // assertions for register: prio65
+  `ASSERT(prio65_wr_A, wr_P(10'h11c, reg2hw.prio65.q, 1, 'h3, 0))
+  `ASSERT(prio65_rd_A, rd_P(10'h11c, reg2hw.prio65.q, 'hffffffff, 0))
+
+  // assertions for register: prio66
+  `ASSERT(prio66_wr_A, wr_P(10'h120, reg2hw.prio66.q, 1, 'h3, 0))
+  `ASSERT(prio66_rd_A, rd_P(10'h120, reg2hw.prio66.q, 'hffffffff, 0))
+
+  // assertions for register: prio67
+  `ASSERT(prio67_wr_A, wr_P(10'h124, reg2hw.prio67.q, 1, 'h3, 0))
+  `ASSERT(prio67_rd_A, rd_P(10'h124, reg2hw.prio67.q, 'hffffffff, 0))
+
+  // assertions for register: prio68
+  `ASSERT(prio68_wr_A, wr_P(10'h128, reg2hw.prio68.q, 1, 'h3, 0))
+  `ASSERT(prio68_rd_A, rd_P(10'h128, reg2hw.prio68.q, 'hffffffff, 0))
+
+  // assertions for register: prio69
+  `ASSERT(prio69_wr_A, wr_P(10'h12c, reg2hw.prio69.q, 1, 'h3, 0))
+  `ASSERT(prio69_rd_A, rd_P(10'h12c, reg2hw.prio69.q, 'hffffffff, 0))
+
+  // assertions for register: prio70
+  `ASSERT(prio70_wr_A, wr_P(10'h130, reg2hw.prio70.q, 1, 'h3, 0))
+  `ASSERT(prio70_rd_A, rd_P(10'h130, reg2hw.prio70.q, 'hffffffff, 0))
+
+  // assertions for register: prio71
+  `ASSERT(prio71_wr_A, wr_P(10'h134, reg2hw.prio71.q, 1, 'h3, 0))
+  `ASSERT(prio71_rd_A, rd_P(10'h134, reg2hw.prio71.q, 'hffffffff, 0))
+
+  // assertions for register: prio72
+  `ASSERT(prio72_wr_A, wr_P(10'h138, reg2hw.prio72.q, 1, 'h3, 0))
+  `ASSERT(prio72_rd_A, rd_P(10'h138, reg2hw.prio72.q, 'hffffffff, 0))
+
+  // assertions for register: prio73
+  `ASSERT(prio73_wr_A, wr_P(10'h13c, reg2hw.prio73.q, 1, 'h3, 0))
+  `ASSERT(prio73_rd_A, rd_P(10'h13c, reg2hw.prio73.q, 'hffffffff, 0))
+
+  // assertions for register: prio74
+  `ASSERT(prio74_wr_A, wr_P(10'h140, reg2hw.prio74.q, 1, 'h3, 0))
+  `ASSERT(prio74_rd_A, rd_P(10'h140, reg2hw.prio74.q, 'hffffffff, 0))
+
+  // assertions for register: prio75
+  `ASSERT(prio75_wr_A, wr_P(10'h144, reg2hw.prio75.q, 1, 'h3, 0))
+  `ASSERT(prio75_rd_A, rd_P(10'h144, reg2hw.prio75.q, 'hffffffff, 0))
+
+  // assertions for register: prio76
+  `ASSERT(prio76_wr_A, wr_P(10'h148, reg2hw.prio76.q, 1, 'h3, 0))
+  `ASSERT(prio76_rd_A, rd_P(10'h148, reg2hw.prio76.q, 'hffffffff, 0))
+
+  // assertions for register: prio77
+  `ASSERT(prio77_wr_A, wr_P(10'h14c, reg2hw.prio77.q, 1, 'h3, 0))
+  `ASSERT(prio77_rd_A, rd_P(10'h14c, reg2hw.prio77.q, 'hffffffff, 0))
+
+  // assertions for register: prio78
+  `ASSERT(prio78_wr_A, wr_P(10'h150, reg2hw.prio78.q, 1, 'h3, 0))
+  `ASSERT(prio78_rd_A, rd_P(10'h150, reg2hw.prio78.q, 'hffffffff, 0))
+
+  // assertions for register: prio79
+  `ASSERT(prio79_wr_A, wr_P(10'h154, reg2hw.prio79.q, 1, 'h3, 0))
+  `ASSERT(prio79_rd_A, rd_P(10'h154, reg2hw.prio79.q, 'hffffffff, 0))
+
+  // assertions for register: prio80
+  `ASSERT(prio80_wr_A, wr_P(10'h158, reg2hw.prio80.q, 1, 'h3, 0))
+  `ASSERT(prio80_rd_A, rd_P(10'h158, reg2hw.prio80.q, 'hffffffff, 0))
+
+  // assertions for register: prio81
+  `ASSERT(prio81_wr_A, wr_P(10'h15c, reg2hw.prio81.q, 1, 'h3, 0))
+  `ASSERT(prio81_rd_A, rd_P(10'h15c, reg2hw.prio81.q, 'hffffffff, 0))
+
+  // assertions for register: prio82
+  `ASSERT(prio82_wr_A, wr_P(10'h160, reg2hw.prio82.q, 1, 'h3, 0))
+  `ASSERT(prio82_rd_A, rd_P(10'h160, reg2hw.prio82.q, 'hffffffff, 0))
+
+  // define local fpv variable for multi-reg
+  logic [82:0] ie0_q_fpv;
+  for (genvar s = 0; s < 83; s++) begin : gen_ie0_q
+    assign ie0_q_fpv[((s+1)*1-1):s*1] = reg2hw.ie0[s].q;
+  end
+
+  // assertions for register: ie00
+  `ASSERT(ie00_wr_A, wr_P(10'h200, ie0_q_fpv[31:0], 1, 'hffffffff, 0))
+  `ASSERT(ie00_rd_A, rd_P(10'h200, ie0_q_fpv[31:0], 'hffffffff, 0))
+  // assertions for register: ie01
+  `ASSERT(ie01_wr_A, wr_P(10'h204, ie0_q_fpv[63:32], 1, 'hffffffff, 0))
+  `ASSERT(ie01_rd_A, rd_P(10'h204, ie0_q_fpv[63:32], 'hffffffff, 0))
+  // assertions for register: ie02
+  `ASSERT(ie02_wr_A, wr_P(10'h208, ie0_q_fpv[82:64], 1, 'h7ffff, 0))
+  `ASSERT(ie02_rd_A, rd_P(10'h208, ie0_q_fpv[82:64], 'h7ffff, 0))
+
+  // assertions for register: threshold0
+  `ASSERT(threshold0_wr_A, wr_P(10'h20c, reg2hw.threshold0.q, 1, 'h3, 0))
+  `ASSERT(threshold0_rd_A, rd_P(10'h20c, reg2hw.threshold0.q, 'hffffffff, 0))
+
+  // assertions for register: cc0
+  `ASSERT(cc0_wr_A, wr_ext_P(10'h210, reg2hw.cc0.q, 1, 'h7f, 0))
+  `ASSERT(cc0_rd_A, rd_ext_P(10'h210, hw2reg.cc0.d, 'hffffffff, 0))
+
+  // assertions for register: msip0
+  `ASSERT(msip0_wr_A, wr_P(10'h214, reg2hw.msip0.q, 1, 'h1, 0))
+  `ASSERT(msip0_rd_A, rd_P(10'h214, reg2hw.msip0.q, 'hffffffff, 0))
+
+
+endmodule
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index f5cbc53..08a3383 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -656,9 +656,10 @@
 
   aes u_aes (
 
-      // [0]: ctrl_err
-      .alert_tx_o  ( alert_tx[0:0] ),
-      .alert_rx_i  ( alert_rx[0:0] ),
+      // [0]: ctrl_err_update
+      // [1]: ctrl_err_storage
+      .alert_tx_o  ( alert_tx[1:0] ),
+      .alert_rx_i  ( alert_rx[1:0] ),
 
       // Inter-module signals
       .idle_o(aes_idle),
@@ -675,9 +676,9 @@
       .intr_fifo_empty_o (intr_hmac_fifo_empty),
       .intr_hmac_err_o   (intr_hmac_hmac_err),
 
-      // [1]: msg_push_sha_disabled
-      .alert_tx_o  ( alert_tx[1:1] ),
-      .alert_rx_i  ( alert_rx[1:1] ),
+      // [2]: msg_push_sha_disabled
+      .alert_tx_o  ( alert_tx[2:2] ),
+      .alert_rx_i  ( alert_rx[2:2] ),
 
       // Inter-module signals
       .tl_i(hmac_tl_req),
@@ -916,15 +917,15 @@
 
   sensor_ctrl u_sensor_ctrl (
 
-      // [2]: ast_alerts
       // [3]: ast_alerts
       // [4]: ast_alerts
       // [5]: ast_alerts
       // [6]: ast_alerts
       // [7]: ast_alerts
       // [8]: ast_alerts
-      .alert_tx_o  ( alert_tx[8:2] ),
-      .alert_rx_i  ( alert_rx[8:2] ),
+      // [9]: ast_alerts
+      .alert_tx_o  ( alert_tx[9:3] ),
+      .alert_rx_i  ( alert_rx[9:3] ),
 
       // Inter-module signals
       .ast_alert_i(sensor_ctrl_ast_alert_req_i),
@@ -942,11 +943,11 @@
       .intr_done_o (intr_otbn_done),
       .intr_err_o  (intr_otbn_err),
 
-      // [9]: imem_uncorrectable
-      // [10]: dmem_uncorrectable
-      // [11]: reg_uncorrectable
-      .alert_tx_o  ( alert_tx[11:9] ),
-      .alert_rx_i  ( alert_rx[11:9] ),
+      // [10]: imem_uncorrectable
+      // [11]: dmem_uncorrectable
+      // [12]: reg_uncorrectable
+      .alert_tx_o  ( alert_tx[12:10] ),
+      .alert_rx_i  ( alert_rx[12:10] ),
 
       // Inter-module signals
       .idle_o(),