[aes] Add life cycle escalation signal

If the life cycle escalation signal is received, the main controller FSM
of the AES unit locks up in the terminal error state. A reset is required.

Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/hw/ip/aes/aes.core b/hw/ip/aes/aes.core
index 437aee3..1859017 100644
--- a/hw/ip/aes/aes.core
+++ b/hw/ip/aes/aes.core
@@ -8,8 +8,10 @@
   files_rtl:
     depend:
       - lowrisc:prim:all
+      - lowrisc:prim:lc_sync
       - lowrisc:prim:lfsr
       - lowrisc:ip:tlul
+      - lowrisc:ip:lc_ctrl_pkg
     files:
       - rtl/aes_pkg.sv
       - rtl/aes_reg_pkg.sv
diff --git a/hw/ip/aes/data/aes.hjson b/hw/ip/aes/data/aes.hjson
index 3d3cb88..592e739 100644
--- a/hw/ip/aes/data/aes.hjson
+++ b/hw/ip/aes/data/aes.hjson
@@ -128,6 +128,13 @@
       package: "",
       struct:  "logic",
       width:   "1"
+    },
+    { struct:  "lc_tx"
+      type:    "uni"
+      name:    "lc_escalate_en"
+      act:     "rcv"
+      default: "lc_ctrl_pkg::Off"
+      package: "lc_ctrl_pkg"
     }
   ],
   alert_list: [
@@ -149,7 +156,7 @@
     { name: "fatal_fault",
       desc: '''
         This fatal alert is triggered upon detecting a fatal fault inside the AES unit.
-        Examples for such faults include i) storage errors in the shadowed Control Register, ii) any internal FSM entering an invalid state, iii) any sparsely encoded signal taking on an invalid value, and iv) errors in the internal round counter.
+        Examples for such faults include i) storage errors in the shadowed Control Register, ii) any internal FSM entering an invalid state, iii) any sparsely encoded signal taking on an invalid value, iv) errors in the internal round counter, and v) escalations triggered by the life cycle controller.
         The AES unit cannot recover from such an error and needs to be reset.
       '''
     }
@@ -538,7 +545,7 @@
         desc:  '''
           No fatal fault has occurred inside the AES unit (0).
           A fatal fault has occurred and the AES unit needs to be reset (1).
-          Examples for fatal faults include i) storage errors in the Control Register, ii) if any internal FSM enters an invalid state, iii) if any sparsely encoded signal takes on an invalid value, and iv) errors in the internal round counter.
+          Examples for fatal faults include i) storage errors in the Control Register, ii) if any internal FSM enters an invalid state, iii) if any sparsely encoded signal takes on an invalid value, iv) errors in the internal round counter, and v) escalations triggered by the life cycle controller.
         '''
       }
     ]
diff --git a/hw/ip/aes/doc/_index.md b/hw/ip/aes/doc/_index.md
index 9a06143..e55ded5 100644
--- a/hw/ip/aes/doc/_index.md
+++ b/hw/ip/aes/doc/_index.md
@@ -123,6 +123,7 @@
 Signal             | Direction        | Type                   | Description
 -------------------|------------------|------------------------|---------------
 `idle_o`           | `output`         | `logic`                | Idle indication signal for clock manager.
+`lc_escalate_en_i` | `input`          | `lc_ctrl_pkg::lc_tx_t` | Life cycle escalation enable coming from life cycle controller. This signal moves the main controller FSM within the AES unit into the terminal error state. The AES unit needs to be reset.
 
 
 ## Design Details
diff --git a/hw/ip/aes/dv/tb/tb.sv b/hw/ip/aes/dv/tb/tb.sv
index 9c19219..2a78e85 100644
--- a/hw/ip/aes/dv/tb/tb.sv
+++ b/hw/ip/aes/dv/tb/tb.sv
@@ -32,6 +32,7 @@
     .rst_ni               (rst_n      ),
 
     .idle_o               (           ),
+    .lc_escalate_en_i     (lc_ctrl_pkg::Off),
 
     .tl_i                 (tl_if.h2d  ),
     .tl_o                 (tl_if.d2h  ),
diff --git a/hw/ip/aes/rtl/aes.sv b/hw/ip/aes/rtl/aes.sv
index f9b2e44..171ab3e 100644
--- a/hw/ip/aes/rtl/aes.sv
+++ b/hw/ip/aes/rtl/aes.sv
@@ -47,6 +47,9 @@
   // Idle indicator for clock manager
   output logic                                      idle_o,
 
+  // Life cycle
+  input  lc_ctrl_pkg::lc_tx_t                       lc_escalate_en_i,
+
   // Bus interface
   input  tlul_pkg::tl_h2d_t                         tl_i,
   output tlul_pkg::tl_d2h_t                         tl_o,
@@ -60,6 +63,7 @@
   aes_hw2reg_t hw2reg;
 
   logic [NumAlerts-1:0] alert;
+  lc_ctrl_pkg::lc_tx_t [0:0] lc_escalate_en; // Need a degenerate array for FPV tool.
 
   aes_reg_top u_reg (
     .clk_i,
@@ -71,6 +75,15 @@
     .devmode_i(1'b1)
   );
 
+  prim_lc_sync #(
+    .NumCopies (1)
+  ) u_prim_lc_sync (
+    .clk_i,
+    .rst_ni,
+    .lc_en_i ( lc_escalate_en_i ),
+    .lc_en_o ( lc_escalate_en   )
+  );
+
   aes_core #(
     .AES192Enable             ( AES192Enable             ),
     .Masking                  ( Masking                  ),
@@ -94,6 +107,8 @@
     .entropy_masking_ack_i  ( 1'b1                           ),
     .entropy_masking_i      ( RndCnstMaskingLfsrSeedDefault  ),
 
+    .lc_escalate_en_i       ( lc_escalate_en                 ),
+
     .alert_recov_o          ( alert[0]                       ),
     .alert_fatal_o          ( alert[1]                       ),
 
diff --git a/hw/ip/aes/rtl/aes_control.sv b/hw/ip/aes/rtl/aes_control.sv
index 59659a2..3984e09 100644
--- a/hw/ip/aes/rtl/aes_control.sv
+++ b/hw/ip/aes/rtl/aes_control.sv
@@ -29,6 +29,7 @@
   input  logic                    prng_reseed_i,
   input  logic                    mux_sel_err_i,
   input  logic                    sp_enc_err_i,
+  input  lc_ctrl_pkg::lc_tx_t     lc_escalate_en_i,
   input  logic                    alert_fatal_i,
   output logic                    alert_o,
 
@@ -587,8 +588,8 @@
     endcase
 
     // Unconditionally jump into the terminal error state in case a mux selector or a sparsely
-    // encoded signal becomes invalid
-    if (mux_sel_err_i || sp_enc_err) begin
+    // encoded signal becomes invalid, or if the life cycle controller triggers an escalation.
+    if (mux_sel_err_i || sp_enc_err || lc_escalate_en_i != lc_ctrl_pkg::Off) begin
       aes_ctrl_ns = ERROR;
     end
   end
diff --git a/hw/ip/aes/rtl/aes_core.sv b/hw/ip/aes/rtl/aes_core.sv
index ef27a18..fbfdfb0 100644
--- a/hw/ip/aes/rtl/aes_core.sv
+++ b/hw/ip/aes/rtl/aes_core.sv
@@ -34,6 +34,9 @@
   input  logic                        entropy_masking_ack_i,
   input  logic  [WidthPRDMasking-1:0] entropy_masking_i,
 
+  // Life cycle
+  input  lc_ctrl_pkg::lc_tx_t         lc_escalate_en_i,
+
   // Alerts
   output logic                        alert_recov_o,
   output logic                        alert_fatal_o,
@@ -525,6 +528,7 @@
     .prng_reseed_i             ( reg2hw.trigger.prng_reseed.q           ),
     .mux_sel_err_i             ( mux_sel_err                            ),
     .sp_enc_err_i              ( sp_enc_err_q                           ),
+    .lc_escalate_en_i          ( lc_escalate_en_i                       ),
     .alert_fatal_i             ( alert_fatal_o                          ),
     .alert_o                   ( ctrl_alert                             ),
 
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 4a2af0e..bec87bf 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -5711,6 +5711,18 @@
           index: 0
         }
         {
+          struct: lc_tx
+          type: uni
+          name: lc_escalate_en
+          act: rcv
+          default: lc_ctrl_pkg::Off
+          package: lc_ctrl_pkg
+          inst_name: aes
+          width: 1
+          top_signame: lc_ctrl_lc_escalate_en
+          index: -1
+        }
+        {
           struct: tl
           package: tlul_pkg
           type: req_rsp
@@ -7781,6 +7793,7 @@
       lc_ctrl.lc_cpu_en: []
       lc_ctrl.lc_escalate_en:
       [
+        aes.lc_escalate_en
         otp_ctrl.lc_escalate_en
         sram_ctrl_main.lc_escalate_en
         sram_ctrl_ret_aon.lc_escalate_en
@@ -14284,6 +14297,18 @@
         index: 0
       }
       {
+        struct: lc_tx
+        type: uni
+        name: lc_escalate_en
+        act: rcv
+        default: lc_ctrl_pkg::Off
+        package: lc_ctrl_pkg
+        inst_name: aes
+        width: 1
+        top_signame: lc_ctrl_lc_escalate_en
+        index: -1
+      }
+      {
         struct: tl
         package: tlul_pkg
         type: req_rsp
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index afe84cf..b9cca2d 100755
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -786,7 +786,8 @@
                                       'pinmux_aon.lc_hw_debug_en'],
       'lc_ctrl.lc_cpu_en'          : [],
       //'lc_ctrl.lc_keymgr_en'       : ['keymgr.lc_keymgr_en'],
-      'lc_ctrl.lc_escalate_en'     : ['otp_ctrl.lc_escalate_en',
+      'lc_ctrl.lc_escalate_en'     : ['aes.lc_escalate_en',
+                                      'otp_ctrl.lc_escalate_en',
                                       'sram_ctrl_main.lc_escalate_en',
                                       'sram_ctrl_ret_aon.lc_escalate_en'],
 
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index c0893a8..820ad82 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -1818,6 +1818,7 @@
 
       // Inter-module signals
       .idle_o(clkmgr_aon_idle[0]),
+      .lc_escalate_en_i(lc_ctrl_lc_escalate_en),
       .tl_i(aes_tl_req),
       .tl_o(aes_tl_rsp),