[top_earlgrey] Instantiate LC controller in toplevel

Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/ip/lc_ctrl/data/lc_ctrl.hjson b/hw/ip/lc_ctrl/data/lc_ctrl.hjson
index 2bb0e12..61cbbba 100644
--- a/hw/ip/lc_ctrl/data/lc_ctrl.hjson
+++ b/hw/ip/lc_ctrl/data/lc_ctrl.hjson
@@ -89,33 +89,40 @@
       type:    "req_rsp"
       name:    "jtag"
       act:     "rsp"
-      package: "rv_dm_pkg"
+      package: "jtag_pkg"
     }
     // Escalation inputs from alert handler
     { struct:  "esc_tx"
       type:    "uni"
-      name:    "esc1_tx"
+      name:    "esc_wipe_secrets_tx"
       act:     "rcv"
       package: "prim_esc_pkg"
     }
     { struct:  "esc_rx"
       type:    "uni"
-      name:    "esc1_rx"
+      name:    "esc_wipe_secrets_rx"
       act:     "req"
       package: "prim_esc_pkg"
     }
     { struct:  "esc_tx"
       type:    "uni"
-      name:    "esc2_tx"
+      name:    "esc_scrap_state_tx"
       act:     "rcv"
       package: "prim_esc_pkg"
     }
     { struct:  "esc_rx"
       type:    "uni"
-      name:    "esc2_rx"
+      name:    "esc_scrap_state_rx"
       act:     "req"
       package: "prim_esc_pkg"
     }
+    // Init request from power manager
+    { struct:  "pwr_lc",
+      type:    "req_rsp",
+      name:    "pwr_lc",
+      act:     "rsp",
+      package: "pwrmgr_pkg",
+    },
     // life cycle state broadcast from OTP
     { struct:  "otp_lc_data"
       type:    "uni"
@@ -171,49 +178,7 @@
     }
     { struct:  "lc_tx"
       type:    "uni"
-      name:    "lc_cpu_en"
-      act:     "req"
-      default: "lc_ctrl_pkg::Off"
-      package: "lc_ctrl_pkg"
-    }
-    { struct:  "lc_tx"
-      type:    "uni"
-      name:    "lc_cpu_en"
-      act:     "req"
-      default: "lc_ctrl_pkg::Off"
-      package: "lc_ctrl_pkg"
-    }
-    { struct:  "lc_tx"
-      type:    "uni"
-      name:    "lc_creator_seed_sw_rw_en"
-      act:     "req"
-      default: "lc_ctrl_pkg::Off"
-      package: "lc_ctrl_pkg"
-    }
-    { struct:  "lc_tx"
-      type:    "uni"
-      name:    "lc_owner_seed_sw_rw_en"
-      act:     "req"
-      default: "lc_ctrl_pkg::Off"
-      package: "lc_ctrl_pkg"
-    }
-    { struct:  "lc_tx"
-      type:    "uni"
-      name:    "lc_iso_part_sw_rd_en"
-      act:     "req"
-      default: "lc_ctrl_pkg::Off"
-      package: "lc_ctrl_pkg"
-    }
-    { struct:  "lc_tx"
-      type:    "uni"
-      name:    "lc_iso_part_sw_wr_en"
-      act:     "req"
-      default: "lc_ctrl_pkg::Off"
-      package: "lc_ctrl_pkg"
-    }
-    { struct:  "lc_tx"
-      type:    "uni"
-      name:    "lc_seed_hw_rd_en"
+      name:    "lc_keymgr_en"
       act:     "req"
       default: "lc_ctrl_pkg::Off"
       package: "lc_ctrl_pkg"
@@ -260,6 +225,41 @@
       default: "lc_ctrl_pkg::Off"
       package: "lc_ctrl_pkg"
     }
+    { struct:  "lc_tx"
+      type:    "uni"
+      name:    "lc_creator_seed_sw_rw_en"
+      act:     "req"
+      default: "lc_ctrl_pkg::Off"
+      package: "lc_ctrl_pkg"
+    }
+    { struct:  "lc_tx"
+      type:    "uni"
+      name:    "lc_owner_seed_sw_rw_en"
+      act:     "req"
+      default: "lc_ctrl_pkg::Off"
+      package: "lc_ctrl_pkg"
+    }
+    { struct:  "lc_tx"
+      type:    "uni"
+      name:    "lc_iso_part_sw_rd_en"
+      act:     "req"
+      default: "lc_ctrl_pkg::Off"
+      package: "lc_ctrl_pkg"
+    }
+    { struct:  "lc_tx"
+      type:    "uni"
+      name:    "lc_iso_part_sw_wr_en"
+      act:     "req"
+      default: "lc_ctrl_pkg::Off"
+      package: "lc_ctrl_pkg"
+    }
+    { struct:  "lc_tx"
+      type:    "uni"
+      name:    "lc_seed_hw_rd_en"
+      act:     "req"
+      default: "lc_ctrl_pkg::Off"
+      package: "lc_ctrl_pkg"
+    }
     // LC state diversification value for keymgr
     { struct:  "lc_keymgr_div"
       type:    "uni"
@@ -268,6 +268,14 @@
       default: "'0"
       package: "lc_ctrl_pkg"
     }
+    // HW config input for DEVICE_ID
+    { struct:  "otp_hw_cfg"
+      type:    "uni"
+      name:    "otp_hw_cfg"
+      act:     "rcv"
+      default: "'0"
+      package: "otp_ctrl_part_pkg"
+    }
   ] // inter_signal_list
 
   registers: [
diff --git a/hw/ip/lc_ctrl/dv/tb.sv b/hw/ip/lc_ctrl/dv/tb.sv
index 047ec3d..a150bcf 100644
--- a/hw/ip/lc_ctrl/dv/tb.sv
+++ b/hw/ip/lc_ctrl/dv/tb.sv
@@ -42,8 +42,8 @@
     .alert_rx_i            (alert_rx ),
     .alert_tx_o            (alert_tx ),
 
-    .jtag_req_i            (0),
-    .jtag_rsp_o            (),
+    .jtag_i                (0),
+    .jtag_o                (),
 
     .esc_wipe_secrets_tx_i ({2'b01}),
     .esc_wipe_secrets_rx_o (),
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
index fdd6035..2ed366a 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
@@ -26,8 +26,8 @@
   input  tlul_pkg::tl_h2d_t                          tl_i,
   output tlul_pkg::tl_d2h_t                          tl_o,
   // JTAG TAP.
-  input  jtag_pkg::jtag_req_t                        jtag_req_i,
-  output jtag_pkg::jtag_rsp_t                        jtag_rsp_o,
+  input  jtag_pkg::jtag_req_t                        jtag_i,
+  output jtag_pkg::jtag_rsp_t                        jtag_o,
   // This bypasses the clock inverter inside the JTAG TAP for scanmmode.
   input                                              scanmode_i,
   // Alert outputs.
@@ -153,12 +153,12 @@
     .dmi_resp_i       ( dmi_resp          ),
     .dmi_resp_ready_o ( dmi_resp_ready    ),
     .dmi_resp_valid_i ( dmi_resp_valid    ),
-    .tck_i            ( jtag_req_i.tck    ),
-    .tms_i            ( jtag_req_i.tms    ),
-    .trst_ni          ( jtag_req_i.trst_n ),
-    .td_i             ( jtag_req_i.tdi    ),
-    .td_o             ( jtag_rsp_o.tdo    ),
-    .tdo_oe_o         ( jtag_rsp_o.tdo_oe )
+    .tck_i            ( jtag_i.tck        ),
+    .tms_i            ( jtag_i.tms        ),
+    .trst_ni          ( jtag_i.trst_n     ),
+    .td_i             ( jtag_i.tdi        ),
+    .td_o             ( jtag_o.tdo        ),
+    .tdo_oe_o         ( jtag_o.tdo_oe     )
   );
 
   // DMI to TL-UL transducing
@@ -291,7 +291,7 @@
         end
 
         if (tap_reg2hw.transition_target.qe) begin
-          transition_target_d = tap_reg2hw.transition_target.q;
+          transition_target_d = dec_lc_state_e'(tap_reg2hw.transition_target.q);
         end
       end else if (sw_claim_transition_if_q == 8'hA5) begin
         transition_cmd = reg2hw.transition_cmd.q &
@@ -304,7 +304,7 @@
         end
 
         if (reg2hw.transition_target.qe) begin
-          transition_target_d = reg2hw.transition_target.q;
+          transition_target_d = dec_lc_state_e'(reg2hw.transition_target.q);
         end
       end
     end
@@ -322,7 +322,7 @@
       sw_claim_transition_if_q  <= '0;
       tap_claim_transition_if_q <= '0;
       transition_token_q        <= '0;
-      transition_target_q       <= '0;
+      transition_target_q       <= DecLcStRaw;
     end else begin
       // All status and error bits are terminal and require a reset cycle.
       trans_success_q           <= trans_success_d        | trans_success_q;
@@ -524,25 +524,25 @@
   // Assertions //
   ////////////////
 
-  `ASSERT_KNOWN(TlOKnown,               tl_o                 )
-  `ASSERT_KNOWN(AlertTxKnown_A,         alert_tx_o           )
-  `ASSERT_KNOWN(PwrLcKnown_A,           pwr_lc_o             )
-  `ASSERT_KNOWN(LcOtpProgramKnwon_A,    lc_otp_program_o     )
-  `ASSERT_KNOWN(LcOtpTokenKnown_A,      lc_otp_token_o       )
-  `ASSERT_KNOWN(LcDftEnKnown_A,         lc_dft_en_o          )
-  `ASSERT_KNOWN(LcNvmDebugEnKnown_A,    lc_nvm_debug_en_o    )
-  `ASSERT_KNOWN(LcHwDebugEnKnown_A,     lc_hw_debug_en_o     )
-  `ASSERT_KNOWN(LcCpuEnKnown_A,         lc_cpu_en_o          )
-  `ASSERT_KNOWN(LcCreatorSwRwEn_A,      lc_creator_seed_sw_rw_en_o)
-  `ASSERT_KNOWN(LcOwnerSwRwEn_A,        lc_owner_seed_sw_rw_en_o)
-  `ASSERT_KNOWN(LcIsoSwRwEn_A,          lc_iso_part_sw_rd_en_o)
-  `ASSERT_KNOWN(LcIsoSwWrEn_A,          lc_iso_part_sw_wr_en_o)
-  `ASSERT_KNOWN(LcSeedHwRdEn_A,         lc_seed_hw_rd_en_o   )
-  `ASSERT_KNOWN(LcKeymgrEnKnown_A,      lc_keymgr_en_o       )
-  `ASSERT_KNOWN(LcEscalateEnKnown_A,    lc_escalate_en_o     )
-  `ASSERT_KNOWN(LcClkBypReqKnown_A,     lc_clk_byp_req_o     )
-  `ASSERT_KNOWN(LcFlashRmaSeedKnown_A,  lc_flash_rma_seed_o  )
-  `ASSERT_KNOWN(LcFlashRmaReqKnown_A,   lc_flash_rma_req_o   )
-  `ASSERT_KNOWN(LcKeymgrDiv_A,          lc_keymgr_div_o      )
+  `ASSERT_KNOWN(TlOKnown,               tl_o                       )
+  `ASSERT_KNOWN(AlertTxKnown_A,         alert_tx_o                 )
+  `ASSERT_KNOWN(PwrLcKnown_A,           pwr_lc_o                   )
+  `ASSERT_KNOWN(LcOtpProgramKnown_A,    lc_otp_program_o           )
+  `ASSERT_KNOWN(LcOtpTokenKnown_A,      lc_otp_token_o             )
+  `ASSERT_KNOWN(LcDftEnKnown_A,         lc_dft_en_o                )
+  `ASSERT_KNOWN(LcNvmDebugEnKnown_A,    lc_nvm_debug_en_o          )
+  `ASSERT_KNOWN(LcHwDebugEnKnown_A,     lc_hw_debug_en_o           )
+  `ASSERT_KNOWN(LcCpuEnKnown_A,         lc_cpu_en_o                )
+  `ASSERT_KNOWN(LcCreatorSwRwEn_A,      lc_creator_seed_sw_rw_en_o )
+  `ASSERT_KNOWN(LcOwnerSwRwEn_A,        lc_owner_seed_sw_rw_en_o   )
+  `ASSERT_KNOWN(LcIsoSwRwEn_A,          lc_iso_part_sw_rd_en_o     )
+  `ASSERT_KNOWN(LcIsoSwWrEn_A,          lc_iso_part_sw_wr_en_o     )
+  `ASSERT_KNOWN(LcSeedHwRdEn_A,         lc_seed_hw_rd_en_o         )
+  `ASSERT_KNOWN(LcKeymgrEnKnown_A,      lc_keymgr_en_o             )
+  `ASSERT_KNOWN(LcEscalateEnKnown_A,    lc_escalate_en_o           )
+  `ASSERT_KNOWN(LcClkBypReqKnown_A,     lc_clk_byp_req_o           )
+  `ASSERT_KNOWN(LcFlashRmaSeedKnown_A,  lc_flash_rma_seed_o        )
+  `ASSERT_KNOWN(LcFlashRmaReqKnown_A,   lc_flash_rma_req_o         )
+  `ASSERT_KNOWN(LcKeymgrDiv_A,          lc_keymgr_div_o            )
 
 endmodule : lc_ctrl
diff --git a/hw/ip/prim/rtl/prim_alert_pkg.sv b/hw/ip/prim/rtl/prim_alert_pkg.sv
index a7c6be8..a3594b6 100644
--- a/hw/ip/prim/rtl/prim_alert_pkg.sv
+++ b/hw/ip/prim/rtl/prim_alert_pkg.sv
@@ -3,6 +3,7 @@
 // SPDX-License-Identifier: Apache-2.0
 
 package prim_alert_pkg;
+
   typedef struct packed {
     logic alert_p;
     logic alert_n;
@@ -14,4 +15,13 @@
     logic ack_p;
     logic ack_n;
   } alert_rx_t;
-endpackage
+
+  parameter alert_tx_t ALERT_TX_DEFAULT = '{alert_p:  1'b0,
+                                            alert_n:  1'b1};
+
+  parameter alert_rx_t ALERT_RX_DEFAULT = '{ping_p: 1'b0,
+                                            ping_n: 1'b1,
+                                            ack_p: 1'b0,
+                                            ack_n: 1'b1};
+
+endpackage : prim_alert_pkg
diff --git a/hw/ip/prim/rtl/prim_esc_pkg.sv b/hw/ip/prim/rtl/prim_esc_pkg.sv
index 6d300b8..8cd9c4e 100644
--- a/hw/ip/prim/rtl/prim_esc_pkg.sv
+++ b/hw/ip/prim/rtl/prim_esc_pkg.sv
@@ -3,6 +3,7 @@
 // SPDX-License-Identifier: Apache-2.0
 
 package prim_esc_pkg;
+
   typedef struct packed {
     logic esc_p;
     logic esc_n;
@@ -12,4 +13,11 @@
     logic resp_p;
     logic resp_n;
   } esc_rx_t;
-endpackage
+
+  parameter esc_tx_t ESC_TX_DEFAULT = '{esc_p:  1'b0,
+                                        esc_n:  1'b1};
+
+  parameter esc_rx_t ESC_RX_DEFAULT = '{resp_p: 1'b0,
+                                        resp_n: 1'b1};
+
+endpackage : prim_esc_pkg
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index 4c770f3..5958ba1 100755
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -221,6 +221,13 @@
       reset_connections: {rst_ni: "lc_io_div4"},
       base_addr: "0x40130000",
     },
+    { name: "lc_ctrl",
+      type: "lc_ctrl",
+      clock_srcs: {clk_i: "io_div4"},
+      clock_group: "timers",
+      reset_connections: {rst_ni: "lc_io_div4"},
+      base_addr: "0x40140000",
+    },
     { name: "pwrmgr",
       type: "pwrmgr",
       clock_srcs: {clk_i: "io_div4", clk_slow_i: "aon"},
@@ -463,6 +470,12 @@
           act: "rsp"
           name: "tl"
         },
+        { struct: "lc_tx",
+          package: "lc_ctrl_pkg",
+          type: "uni"
+          act: "rcv"
+          name: "lc_dft_en"
+        },
         { struct: "logic"
           package: ""
           type: "uni"
@@ -488,12 +501,6 @@
           act: "rcv"
           name: "flash_test_voltage_h"
         },
-        { struct: "lc_tx",
-          package: "lc_ctrl",
-          type: "uni"
-          act: "rcv"
-          name: "lc_dft_en"
-        },
       ],
     },
   ],
@@ -507,6 +514,13 @@
   inter_module: {
     'connect': {
       'alert_handler.crashdump': ['rstmgr.alert_dump'],
+      // TODO: uncomment once NMI gen is removed,
+      // the processor core wrapper supports intermodule signals
+      // and the reset manager has an escalation input.
+      //'alert_handler.esc_rx': ['lc_ctrl.esc_wipe_secrets_rx',
+      //                         'lc_ctrl.esc_scrap_state_rx'],
+      //'alert_handler.esc_tx': ['lc_ctrl.esc_wipe_secrets_tx',
+      //                         'lc_ctrl.esc_scrap_state_tx'],
       'csrng.csrng_cmd' : ['edn0.csrng_cmd', 'edn1.csrng_cmd'],
       'csrng.entropy_src_hw_if' : ['entropy_src.entropy_src_hw_if'],
       'flash_ctrl.flash' : ['eflash.flash_ctrl'],
@@ -516,16 +530,13 @@
       'pwrmgr.pwr_rst'   : ['rstmgr.pwr'],
       'pwrmgr.pwr_clk'   : ['clkmgr.pwr'],
       'pwrmgr.pwr_otp'   : ['otp_ctrl.pwr_otp'],
+      'pwrmgr.pwr_lc'    : ['lc_ctrl.pwr_lc'],
       'flash_ctrl.keymgr': ['keymgr.flash'],
       'alert_handler.crashdump': ['rstmgr.alert_dump'],
       'csrng.entropy_src_hw_if' : ['entropy_src.entropy_src_hw_if'],
       // TODO see #4447
       //'edn0.edn' : ['keymgr.edn'],
 
-      // life cycle connections
-      // Temporarily commented out because lc_ctrl not instantiated yet
-      //'lc_ctrl.lc_dft_en': ['eflash.lc_dft_en'],
-
       // KeyMgr Sideload & KDF function
       'otp_ctrl.otp_keymgr_key': ['keymgr.otp_key'],
       'keymgr.kmac_key' : ['kmac.keymgr_key']
@@ -534,6 +545,44 @@
       // The user does not need to explicitly declare anything other than
       // an empty list.
       'clkmgr.idle'      : [],
+
+      // OTP LC interface
+      'otp_ctrl.otp_lc_data'   : ['lc_ctrl.otp_lc_data'],
+      'lc_ctrl.lc_otp_program' : ['otp_ctrl.lc_otp_program'],
+      'lc_ctrl.lc_otp_token'   : ['otp_ctrl.lc_otp_token'],
+
+      // HW_CFG broadcast
+       'otp_ctrl.otp_hw_cfg'   : ['lc_ctrl.otp_hw_cfg'],
+
+      // Diversification constant coming from life cycle
+      'lc_ctrl.lc_keymgr_div'  : [],
+
+      // LC function control signal broadcast
+      // TODO(#3920): connect all these signals once top-level sim and FPGA can backload LC state
+      'lc_ctrl.lc_dft_en'          : ['otp_ctrl.lc_dft_en', 'eflash.lc_dft_en'],
+      'lc_ctrl.lc_nvm_debug_en'    : [],
+      'lc_ctrl.lc_hw_debug_en'     : [],
+      'lc_ctrl.lc_cpu_en'          : [],
+      'lc_ctrl.lc_keymgr_en'       : [],
+      'lc_ctrl.lc_escalate_en'     : ['otp_ctrl.lc_escalate_en'],
+
+      // TODO: OTP Clock bypass signal going from LC to AST/clkmgr
+      'lc_ctrl.lc_clk_byp_req'  : [],
+      //'lc_ctrl.lc_clk_byp_ack'  : [],
+
+      // TODO: Flash RMA
+      'lc_ctrl.lc_flash_rma_req'    : [],
+      'lc_ctrl.lc_flash_rma_seed'   : [],
+      //'lc_ctrl.lc_flash_rma_ack'    : [],
+
+      // LC access control signal broadcast
+      'lc_ctrl.lc_creator_seed_sw_rw_en'   : ['otp_ctrl.lc_creator_seed_sw_rw_en',
+                                      'flash_ctrl.lc_creator_seed_sw_rw_en'],
+      'lc_ctrl.lc_owner_seed_sw_rw_en'     : ['flash_ctrl.lc_owner_seed_sw_rw_en'],
+      'lc_ctrl.lc_iso_part_sw_rd_en'       : ['flash_ctrl.lc_iso_part_sw_rd_en'],
+      'lc_ctrl.lc_iso_part_sw_wr_en'       : ['flash_ctrl.lc_iso_part_sw_wr_en'],
+      'lc_ctrl.lc_seed_hw_rd_en'           : ['otp_ctrl.lc_seed_hw_rd_en',
+                                              'flash_ctrl.lc_seed_hw_rd_en'],
     }
 
     // top is to connect to top net/struct.
@@ -608,7 +657,7 @@
   // ===== ALERT HANDLER ======================================================
   // list all modules that expose alerts
   // first item goes to LSB of the alert source
-  alert_module: [ "aes", "otbn", "sensor_ctrl", "keymgr", "otp_ctrl", "entropy_src" ]
+  alert_module: [ "aes", "otbn", "sensor_ctrl", "keymgr", "otp_ctrl", "lc_ctrl", "entropy_src"]
 
   // generated list of alerts:
   alert: [
diff --git a/hw/top_earlgrey/data/top_earlgrey.sv.tpl b/hw/top_earlgrey/data/top_earlgrey.sv.tpl
index 6fd4ab7..c41134d 100644
--- a/hw/top_earlgrey/data/top_earlgrey.sv.tpl
+++ b/hw/top_earlgrey/data/top_earlgrey.sv.tpl
@@ -479,7 +479,7 @@
     .host_rdata_o    (flash_host_rdata),
     .flash_ctrl_i    (${m["inter_signal_list"][0]["top_signame"]}_req),
     .flash_ctrl_o    (${m["inter_signal_list"][0]["top_signame"]}_rsp),
-    .lc_dft_en_i     (lc_ctrl_pkg::LC_TX_DEFAULT),
+    .lc_dft_en_i     (${m["inter_signal_list"][2]["top_signame"]}),
     .tck_i           ('0),
     .tdi_i           ('0),
     .tms_i           ('0),
@@ -605,8 +605,6 @@
       .dio_attr_o,
     % endif
     % if m["type"] == "alert_handler":
-      // TODO: wire this to TRNG
-      .entropy_i   ( 1'b0     ),
       // alert signals
       .alert_rx_o  ( alert_rx ),
       .alert_tx_i  ( alert_tx ),
diff --git a/hw/top_earlgrey/data/xbar_peri.hjson b/hw/top_earlgrey/data/xbar_peri.hjson
index 8990872..d0f4392 100644
--- a/hw/top_earlgrey/data/xbar_peri.hjson
+++ b/hw/top_earlgrey/data/xbar_peri.hjson
@@ -73,7 +73,13 @@
       type:      "device",
       clock:     "clk_peri_i",
       reset:     "rst_peri_ni",
-      pipeline: "false"
+      pipeline:  "false"
+    },
+    { name:      "lc_ctrl",
+      type:      "device",
+      clock:     "clk_peri_i",
+      reset:     "rst_peri_ni",
+      pipeline:  "false"
     },
     { name:      "sensor_ctrl",
       type:      "device",
@@ -98,6 +104,6 @@
   ],
   connections: {
     main:  ["uart", "gpio", "spi_device", "rv_timer", "usbdev", "pwrmgr", "rstmgr", "clkmgr",
-            "ram_ret", "otp_ctrl", "sensor_ctrl", "ast_wrapper"],
+            "ram_ret", "otp_ctrl", "lc_ctrl", "sensor_ctrl", "ast_wrapper"],
   },
 }
diff --git a/hw/top_earlgrey/top_earlgrey.core b/hw/top_earlgrey/top_earlgrey.core
index e351bf1..0617cc2 100644
--- a/hw/top_earlgrey/top_earlgrey.core
+++ b/hw/top_earlgrey/top_earlgrey.core
@@ -36,6 +36,7 @@
       - lowrisc:constants:top_pkg
       - lowrisc:ip:nmi_gen
       - lowrisc:ip:otp_ctrl
+      - lowrisc:ip:lc_ctrl
       - lowrisc:ip:usbdev
       - lowrisc:top_earlgrey:xbar_main
       - lowrisc:top_earlgrey:xbar_peri