[dv/clkmgr] Fix external clock handling

The RTL handling of external clock was recently changed.
Update DV to match interface changes.

Signed-off-by: Guillermo Maturana <maturana@google.com>
diff --git a/hw/ip/clkmgr/dv/env/clkmgr_if.sv b/hw/ip/clkmgr/dv/env/clkmgr_if.sv
index 5e8d33d..faffb6e 100644
--- a/hw/ip/clkmgr/dv/env/clkmgr_if.sv
+++ b/hw/ip/clkmgr/dv/env/clkmgr_if.sv
@@ -44,6 +44,8 @@
   prim_mubi_pkg::mubi4_t all_clk_byp_req;
   prim_mubi_pkg::mubi4_t all_clk_byp_ack;
 
+  prim_mubi_pkg::mubi4_t div_step_down_req;
+
   prim_mubi_pkg::mubi4_t jitter_en_o;
   clkmgr_pkg::clkmgr_out_t clocks_o;
 
@@ -81,9 +83,8 @@
 
   prim_mubi_pkg::mubi4_t extclk_ctrl_csr_step_down;
   always_comb begin
-    extclk_ctrl_csr_step_down = (`CLKMGR_HIER.hi_speed_sel_o == prim_mubi_pkg::MuBi4False) ?
-                                 prim_mubi_pkg::MuBi4True :
-                                 prim_mubi_pkg::MuBi4False;
+    extclk_ctrl_csr_step_down = prim_mubi_pkg::mubi4_t'(
+        `CLKMGR_HIER.reg2hw.extclk_ctrl.hi_speed_sel.q);
   end
 
   prim_mubi_pkg::mubi4_t jitter_enable_csr;
@@ -190,6 +191,12 @@
     all_clk_byp_ack = value;
   endfunction
 
+  function automatic void update_div_step_down_req(prim_mubi_pkg::mubi4_t value);
+    `uvm_info("clkmgr_if", $sformatf("In clkmgr_if update_div_step_down_req with %b", value),
+              UVM_MEDIUM)
+    div_step_down_req = value;
+  endfunction
+
   function automatic void update_io_clk_byp_ack(prim_mubi_pkg::mubi4_t value);
     io_clk_byp_ack = value;
   endfunction
diff --git a/hw/ip/clkmgr/dv/env/clkmgr_scoreboard.sv b/hw/ip/clkmgr/dv/env/clkmgr_scoreboard.sv
index 5d5741e..a4b555f 100644
--- a/hw/ip/clkmgr/dv/env/clkmgr_scoreboard.sv
+++ b/hw/ip/clkmgr/dv/env/clkmgr_scoreboard.sv
@@ -54,11 +54,6 @@
           prev_all_clk_byp_req = cfg.clkmgr_vif.all_clk_byp_req;
         end
         if (cfg.clk_rst_vif.rst_n) begin
-          if ((cfg.clkmgr_vif.clk_cb.extclk_ctrl_csr_sel == MuBi4True) &&
-              (cfg.clkmgr_vif.clk_cb.lc_hw_debug_en_i == On)) begin
-            `DV_CHECK_EQ(cfg.clkmgr_vif.all_clk_byp_req, MuBi4True,
-                         "Expected all_clk_byp_req to be On")
-          end
           if (cfg.en_cov) begin
             cov.extclk_cg.sample(cfg.clkmgr_vif.clk_cb.extclk_ctrl_csr_sel == MuBi4True,
                                  cfg.clkmgr_vif.clk_cb.extclk_ctrl_csr_step_down == MuBi4True,
@@ -81,10 +76,6 @@
           prev_lc_clk_byp_req = cfg.clkmgr_vif.lc_clk_byp_req;
         end
         if (cfg.clk_rst_vif.rst_n) begin
-          if (cfg.clkmgr_vif.clk_cb.lc_clk_byp_req == On) begin
-            `DV_CHECK_EQ(cfg.clkmgr_vif.io_clk_byp_req, MuBi4True,
-                         "Expected io_clk_byp_req to be True")
-          end
           if (cfg.en_cov) begin
             cov.extclk_cg.sample(cfg.clkmgr_vif.clk_cb.extclk_ctrl_csr_sel == MuBi4True,
                                  cfg.clkmgr_vif.clk_cb.extclk_ctrl_csr_step_down == MuBi4True,
@@ -276,9 +267,13 @@
                        })
         end
       end
+      "jitter_regwen": begin
+      end
       "jitter_enable": begin
         if (addr_phase_write) begin
-          `DV_CHECK_EQ(prim_mubi_pkg::mubi4_t'(item.a_data), cfg.clkmgr_vif.jitter_enable_csr)
+          if (`gmv(ral.jitter_regwen)) begin
+            `DV_CHECK_EQ(prim_mubi_pkg::mubi4_t'(item.a_data), cfg.clkmgr_vif.jitter_enable_csr)
+          end
         end
       end
       "clk_enables": begin
diff --git a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_base_vseq.sv b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_base_vseq.sv
index e53088a..297b38d 100644
--- a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_base_vseq.sv
+++ b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_base_vseq.sv
@@ -88,6 +88,7 @@
     cfg.clkmgr_vif.update_main_ip_clk_en(1'b0);
     cfg.clkmgr_vif.update_usb_ip_clk_en(1'b0);
     cfg.clkmgr_vif.update_all_clk_byp_ack(MuBi4False);
+    cfg.clkmgr_vif.update_div_step_down_req(MuBi4False);
     cfg.clkmgr_vif.update_io_clk_byp_ack(MuBi4False);
 
     disable_unnecessary_exclusions();
diff --git a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_extclk_vseq.sv b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_extclk_vseq.sv
index b8ddac3..87a4f6e 100644
--- a/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_extclk_vseq.sv
+++ b/hw/ip/clkmgr/dv/env/seq_lib/clkmgr_extclk_vseq.sv
@@ -24,24 +24,33 @@
   rand int cycles_before_lc_clk_byp_req;
   rand int cycles_before_lc_clk_byp_ack;
   rand int cycles_before_all_clk_byp_ack;
+  rand int cycles_before_div_step_down_req;
   rand int cycles_before_io_clk_byp_ack;
   rand int cycles_before_next_trans;
 
   constraint cycles_to_stim_c {
     cycles_before_extclk_ctrl_sel inside {[4 : 20]};
     cycles_before_lc_clk_byp_req inside {[4 : 20]};
-    cycles_before_lc_clk_byp_ack inside {[12 : 20]};
+    cycles_before_lc_clk_byp_ack inside {[16 : 30]};
     cycles_before_all_clk_byp_ack inside {[3 : 11]};
+    cycles_before_div_step_down_req inside {[3 : 11]};
     cycles_before_io_clk_byp_ack inside {[3 : 11]};
-    cycles_before_next_trans inside {[15 : 25]};
+    cycles_before_next_trans inside {[15 : 35]};
   }
 
   lc_tx_t lc_clk_byp_req;
   lc_tx_t lc_debug_en;
+  mubi4_t io_clk_byp_ack_non_true;
+  mubi4_t all_clk_byp_ack_non_true;
+  mubi4_t div_step_down_req_non_true;
 
   function void post_randomize();
     lc_clk_byp_req = get_rand_lc_tx_val(8, 2, 2);
     lc_debug_en = get_rand_lc_tx_val(8, 2, 2);
+    io_clk_byp_ack_non_true = get_rand_mubi4_val(0, 2, 8);
+    all_clk_byp_ack_non_true = get_rand_mubi4_val(0, 2, 8);
+    div_step_down_req_non_true = get_rand_mubi4_val(0, 2, 8);
+
     `uvm_info(`gfn, $sformatf(
               "randomize gives lc_clk_byp_req=0x%x, lc_debug_en=0x%x", lc_clk_byp_req, lc_debug_en),
               UVM_MEDIUM)
@@ -50,17 +59,39 @@
 
   // Notice only all_clk_byp_req and io_clk_byp_req Mubi4True and Mubi4False cause transitions.
 
+  local task delayed_update_all_clk_byp_ack(mubi4_t value, int cycles);
+    cfg.clk_rst_vif.wait_clks(cycles);
+    cfg.clkmgr_vif.update_all_clk_byp_ack(value);
+  endtask
+
+  local task delayed_update_div_step_down_req(mubi4_t value, int cycles);
+    cfg.clk_rst_vif.wait_clks(cycles);
+    cfg.clkmgr_vif.update_div_step_down_req(value);
+  endtask
+
+  local task delayed_update_io_clk_byp_ack(mubi4_t value, int cycles);
+    cfg.clk_rst_vif.wait_clks(cycles);
+    cfg.clkmgr_vif.update_io_clk_byp_ack(value);
+  endtask
+
   local task all_clk_byp_handshake();
     forever
       @cfg.clkmgr_vif.all_clk_byp_req begin : all_clk_byp_ack
         if (cfg.clkmgr_vif.all_clk_byp_req == prim_mubi_pkg::MuBi4True) begin
           `uvm_info(`gfn, "Got all_clk_byp_req on", UVM_MEDIUM)
-          cfg.clk_rst_vif.wait_clks(cycles_before_all_clk_byp_ack);
-          cfg.clkmgr_vif.update_all_clk_byp_ack(prim_mubi_pkg::MuBi4True);
-        end else if (cfg.clkmgr_vif.all_clk_byp_req == prim_mubi_pkg::MuBi4False) begin
+          fork
+            delayed_update_all_clk_byp_ack(MuBi4True, cycles_before_all_clk_byp_ack);
+            delayed_update_div_step_down_req(MuBi4True, cycles_before_div_step_down_req);
+          join
+        end else begin
           `uvm_info(`gfn, "Got all_clk_byp_req off", UVM_MEDIUM)
-          cfg.clk_rst_vif.wait_clks(cycles_before_all_clk_byp_ack);
-          cfg.clkmgr_vif.update_all_clk_byp_ack(prim_mubi_pkg::MuBi4False);
+          // Set inputs to mubi4 non-True.
+          fork
+            delayed_update_all_clk_byp_ack(all_clk_byp_ack_non_true,
+                                           cycles_before_all_clk_byp_ack);
+            delayed_update_div_step_down_req(div_step_down_req_non_true,
+                                             cycles_before_div_step_down_req);
+          join
         end
       end
   endtask
@@ -68,14 +99,21 @@
   local task io_clk_byp_handshake();
     forever
       @cfg.clkmgr_vif.io_clk_byp_req begin : io_clk_byp_ack
-        if (cfg.clkmgr_vif.io_clk_byp_req == prim_mubi_pkg::MuBi4True) begin
-          `uvm_info(`gfn, "Got io_clk_byp_req on", UVM_MEDIUM)
-          cfg.clk_rst_vif.wait_clks(cycles_before_io_clk_byp_ack);
-          cfg.clkmgr_vif.update_io_clk_byp_ack(prim_mubi_pkg::MuBi4True);
+        if (cfg.clkmgr_vif.io_clk_byp_req == MuBi4True) begin
+          `uvm_info(`gfn, "Got io_clk_byp_req True", UVM_MEDIUM)
+          fork
+            delayed_update_io_clk_byp_ack(MuBi4True, cycles_before_io_clk_byp_ack);
+            delayed_update_div_step_down_req(MuBi4True, cycles_before_div_step_down_req);
+          join
         end else begin
-          `uvm_info(`gfn, "Got io_clk_byp_req off", UVM_MEDIUM)
-          cfg.clk_rst_vif.wait_clks(cycles_before_io_clk_byp_ack);
-          cfg.clkmgr_vif.update_io_clk_byp_ack(prim_mubi_pkg::MuBi4False);
+          `uvm_info(`gfn, "Got io_clk_byp_req non True", UVM_MEDIUM)
+          // Set inputs to mubi4 non-True.
+          fork
+            delayed_update_io_clk_byp_ack(io_clk_byp_ack_non_true,
+                                          cycles_before_io_clk_byp_ack);
+            delayed_update_div_step_down_req(div_step_down_req_non_true,
+                                             cycles_before_div_step_down_req);
+          join
         end
       end
   endtask
diff --git a/hw/ip/clkmgr/dv/sva/clkmgr_bind.sv b/hw/ip/clkmgr/dv/sva/clkmgr_bind.sv
index 2458304..6c9b977 100644
--- a/hw/ip/clkmgr/dv/sva/clkmgr_bind.sv
+++ b/hw/ip/clkmgr/dv/sva/clkmgr_bind.sv
@@ -10,9 +10,9 @@
 
 
   // In top-level testbench, do not bind the csr_assert_fpv to reduce simulation time.
-  `ifndef TOP_LEVEL_DV
+`ifndef TOP_LEVEL_DV
   bind clkmgr clkmgr_csr_assert_fpv clkmgr_csr_assert (.clk_i, .rst_ni, .h2d(tl_i), .d2h(tl_o));
-  `endif
+`endif
 
   bind clkmgr clkmgr_pwrmgr_sva_if clkmgr_pwrmgr_sva_if (
     .clk_i,
@@ -97,19 +97,25 @@
     .gated_clk(clocks_o.clk_main_otbn)
   );
 
+  bind clkmgr clkmgr_extclk_sva_if clkmgr_extclk_sva_if (
+    .clk_i,
+    .rst_ni,
+    .extclk_ctrl_sel(mubi4_t'(reg2hw.extclk_ctrl.sel.q)),
+    .extclk_ctrl_hi_speed_sel(mubi4_t'(reg2hw.extclk_ctrl.hi_speed_sel.q)),
+    .lc_hw_debug_en_i,
+    .lc_clk_byp_req_i,
+    .io_clk_byp_req_o,
+    .all_clk_byp_req_o,
+    .hi_speed_sel_o
+  );
+
   bind clkmgr clkmgr_div_sva_if #(
     .DIV(2)
   ) clkmgr_div2_sva_if (
     .clk(clocks_o.clk_io_powerup),
     .rst_n(rst_ni),
     .maybe_divided_clk(clocks_o.clk_io_div2_powerup),
-    .lc_step_down_ctrl(lc_clk_byp_req_i == lc_ctrl_pkg::On),
-    .lc_step_down_ack(io_clk_byp_ack_i == prim_mubi_pkg::MuBi4True),
-    .sw_step_down_ctrl(lc_hw_debug_en_i == lc_ctrl_pkg::On &&
-                       reg2hw.extclk_ctrl.sel.q == prim_mubi_pkg::MuBi4True &&
-                       reg2hw.extclk_ctrl.hi_speed_sel.q == prim_mubi_pkg::MuBi4False),
-    .sw_step_down_ack(all_clk_byp_ack_i == prim_mubi_pkg::MuBi4True),
-    .sw_step_up_ack(all_clk_byp_ack_i == prim_mubi_pkg::MuBi4False),
+    .div_step_down_req_i(div_step_down_req_i == prim_mubi_pkg::MuBi4True),
     .scanmode(scanmode_i == prim_mubi_pkg::MuBi4True)
   );
 
@@ -120,13 +126,7 @@
     .clk(clocks_o.clk_io_div2_powerup),
     .rst_n(rst_ni),
     .maybe_divided_clk(clocks_o.clk_io_div4_powerup),
-    .lc_step_down_ctrl(lc_clk_byp_req_i == lc_ctrl_pkg::On),
-    .lc_step_down_ack(io_clk_byp_ack_i == prim_mubi_pkg::MuBi4True),
-    .sw_step_down_ctrl(lc_hw_debug_en_i == lc_ctrl_pkg::On &&
-                       reg2hw.extclk_ctrl.sel.q == prim_mubi_pkg::MuBi4True &&
-                       reg2hw.extclk_ctrl.hi_speed_sel.q == prim_mubi_pkg::MuBi4False),
-    .sw_step_down_ack(all_clk_byp_ack_i == prim_mubi_pkg::MuBi4True),
-    .sw_step_up_ack(all_clk_byp_ack_i == prim_mubi_pkg::MuBi4False),
+    .div_step_down_req_i(div_step_down_req_i == prim_mubi_pkg::MuBi4True),
     .scanmode(scanmode_i == prim_mubi_pkg::MuBi4True)
   );
 
@@ -288,8 +288,7 @@
     .clk(clk_main_i),
     .rst_n(rst_main_ni),
     .ip_clk_en(clk_main_en),
-    .sw_clk_en(u_clk_main_aes_trans.sw_hint_synced ||
-               !u_clk_main_aes_trans.idle_valid),
+    .sw_clk_en(u_clk_main_aes_trans.sw_hint_synced || !u_clk_main_aes_trans.idle_valid),
     .scanmode(prim_mubi_pkg::MuBi4False),
     .cg_en(cg_en_o.main_aes == prim_mubi_pkg::MuBi4True)
   );
@@ -298,8 +297,7 @@
     .clk(clk_main_i),
     .rst_n(rst_main_ni),
     .ip_clk_en(clk_main_en),
-    .sw_clk_en(u_clk_main_hmac_trans.sw_hint_synced ||
-               !u_clk_main_hmac_trans.idle_valid),
+    .sw_clk_en(u_clk_main_hmac_trans.sw_hint_synced || !u_clk_main_hmac_trans.idle_valid),
     .scanmode(prim_mubi_pkg::MuBi4False),
     .cg_en(cg_en_o.main_hmac == prim_mubi_pkg::MuBi4True)
   );
@@ -308,8 +306,7 @@
     .clk(clk_main_i),
     .rst_n(rst_main_ni),
     .ip_clk_en(clk_main_en),
-    .sw_clk_en(u_clk_main_kmac_trans.sw_hint_synced ||
-               !u_clk_main_kmac_trans.idle_valid),
+    .sw_clk_en(u_clk_main_kmac_trans.sw_hint_synced || !u_clk_main_kmac_trans.idle_valid),
     .scanmode(prim_mubi_pkg::MuBi4False),
     .cg_en(cg_en_o.main_kmac == prim_mubi_pkg::MuBi4True)
   );
@@ -318,8 +315,7 @@
     .clk(clk_main_i),
     .rst_n(rst_main_ni),
     .ip_clk_en(clk_main_en),
-    .sw_clk_en(u_clk_main_otbn_trans.sw_hint_synced ||
-               !u_clk_main_otbn_trans.idle_valid),
+    .sw_clk_en(u_clk_main_otbn_trans.sw_hint_synced || !u_clk_main_otbn_trans.idle_valid),
     .scanmode(prim_mubi_pkg::MuBi4False),
     .cg_en(cg_en_o.main_otbn == prim_mubi_pkg::MuBi4True)
   );
diff --git a/hw/ip/clkmgr/dv/sva/clkmgr_div_sva_if.sv b/hw/ip/clkmgr/dv/sva/clkmgr_div_sva_if.sv
index 033dce8..1940a91 100644
--- a/hw/ip/clkmgr/dv/sva/clkmgr_div_sva_if.sv
+++ b/hw/ip/clkmgr/dv/sva/clkmgr_div_sva_if.sv
@@ -16,30 +16,16 @@
   input logic clk,
   input logic rst_n,
   input logic maybe_divided_clk,
-  input logic lc_step_down_ctrl,
-  input logic lc_step_down_ack,
-  input logic sw_step_down_ctrl,
-  input logic sw_step_down_ack,
-  input logic sw_step_up_ack,
+  input logic div_step_down_req_i,
   input logic scanmode
 );
 
   localparam int WAIT_CYCLES = 20;
-
-  logic lc_step_down;
-  always_comb lc_step_down = lc_step_down_ctrl && lc_step_down_ack;
-  logic lc_step_up;
-  always_comb lc_step_up = !lc_step_down_ctrl && !lc_step_down_ack;
-  logic sw_step_down;
-  always_comb sw_step_down = sw_step_down_ctrl && sw_step_down_ack;
-  logic sw_step_up;
-  always_comb sw_step_up = !sw_step_down_ctrl && sw_step_up_ack;
-
   logic step_down;
-  always_comb step_down = (lc_step_down || sw_step_down) && !scanmode;
+  always_comb step_down = div_step_down_req_i && !scanmode;
 
   logic step_up;
-  always_comb step_up = (lc_step_up && sw_step_up) || scanmode;
+  always_comb step_up = !step_down;
 
   sequence WholeLeadHigh_S;
     step_down || maybe_divided_clk ##1 step_down || !maybe_divided_clk;
@@ -58,8 +44,8 @@
     `ASSERT(Div2Stepped_A, $rose(step_down) ##1 step_down [* WAIT_CYCLES] |-> TracksClk_S, !clk,
             !rst_n)
     `ASSERT(Div2Whole_A,
-            $rose(step_up) ##1 step_up [* WAIT_CYCLES] |-> WholeLeadLow_S or WholeLeadHigh_S, !clk,
-            !rst_n)
+            $fell(step_down) ##1 !step_down [* WAIT_CYCLES] |-> WholeLeadLow_S or WholeLeadHigh_S,
+            !clk, !rst_n)
 
   end else begin : g_div4
 
@@ -75,8 +61,8 @@
             $rose(step_down) ##1 step_down [* WAIT_CYCLES] |-> StepLeadLow_S or StepLeadHigh_S,
             !clk, !rst_n)
     `ASSERT(Div4Whole_A,
-            $rose(step_up) ##1 step_up [* WAIT_CYCLES] |-> WholeLeadLow_S or WholeLeadHigh_S, !clk,
-            !rst_n)
+            $fell(step_down) ##1 !step_down [* WAIT_CYCLES] |-> WholeLeadLow_S or WholeLeadHigh_S,
+            !clk, !rst_n)
 
   end
 endinterface
diff --git a/hw/ip/clkmgr/dv/sva/clkmgr_extclk_sva_if.sv b/hw/ip/clkmgr/dv/sva/clkmgr_extclk_sva_if.sv
new file mode 100644
index 0000000..fae8ec3
--- /dev/null
+++ b/hw/ip/clkmgr/dv/sva/clkmgr_extclk_sva_if.sv
@@ -0,0 +1,81 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// This contains SVA assertions to check the external clock bypass control outputs.
+//
+// Notice when a condition fails we allow the logic to generate non strict mubi values. Ideally it
+// would generate mubi False: see https://github.com/lowRISC/opentitan/issues/11400.
+interface clkmgr_extclk_sva_if
+  import prim_mubi_pkg::*, lc_ctrl_pkg::*;
+(
+  input logic   clk_i,
+  input logic   rst_ni,
+  input mubi4_t extclk_ctrl_sel,
+  input mubi4_t extclk_ctrl_hi_speed_sel,
+  input lc_tx_t lc_hw_debug_en_i,
+  input lc_tx_t lc_clk_byp_req_i,
+  input mubi4_t io_clk_byp_req_o,
+  input mubi4_t all_clk_byp_req_o,
+  input mubi4_t hi_speed_sel_o
+);
+
+  // The times are to cover the clock domain synchronizers.
+  localparam int FallCyclesMin = 1;
+  localparam int FallCyclesMax = 3;
+
+  localparam int RiseCyclesMin = 1;
+  localparam int RiseCyclesMax = 3;
+
+  bit   disable_sva;
+
+  // Check lc_clk_byp_req_i triggers io_clk_byp_req_o.
+  logic lc_clk_byp_req;
+  always_comb lc_clk_byp_req = lc_clk_byp_req_i == On;
+
+  `ASSERT(IoClkBypReqRise_A,
+          $rose(
+              lc_clk_byp_req
+          ) |=> ##[RiseCyclesMin:RiseCyclesMax] !lc_clk_byp_req || (io_clk_byp_req_o == MuBi4True),
+          clk_i, !rst_ni || disable_sva)
+  `ASSERT(IoClkBypReqFall_A,
+          $fell(
+              lc_clk_byp_req
+          ) |=> ##[FallCyclesMin:FallCyclesMax] lc_clk_byp_req || (io_clk_byp_req_o != MuBi4False),
+          clk_i, !rst_ni || disable_sva)
+
+  // Check extclk_ctrl triggers all_clk_byp_req_o and hi_speed_sel_o.
+  logic extclk_sel_enabled;
+  always_comb extclk_sel_enabled = extclk_ctrl_sel == MuBi4True && lc_hw_debug_en_i == On;
+
+  `ASSERT(AllClkBypReqRise_A,
+          $rose(
+              extclk_sel_enabled
+          ) |=> ##[RiseCyclesMin:RiseCyclesMax]
+              !extclk_sel_enabled || (all_clk_byp_req_o == MuBi4True),
+          clk_i, !rst_ni || disable_sva)
+  `ASSERT(AllClkBypReqFall_A,
+          $fell(
+              extclk_sel_enabled
+          ) |=> ##[FallCyclesMin:FallCyclesMax]
+              extclk_sel_enabled || (all_clk_byp_req_o != MuBi4False),
+          clk_i, !rst_ni || disable_sva)
+
+  logic hi_speed_enabled;
+  always_comb begin
+    hi_speed_enabled = extclk_ctrl_sel == MuBi4True && extclk_ctrl_hi_speed_sel == MuBi4True &&
+        lc_hw_debug_en_i == On;
+  end
+
+  `ASSERT(HiSpeedSelRise_A,
+          $rose(
+              hi_speed_enabled
+          ) |=> ##[RiseCyclesMin:RiseCyclesMax] !hi_speed_enabled || (hi_speed_sel_o == MuBi4True),
+          clk_i, !rst_ni || disable_sva)
+  `ASSERT(HiSpeedSelFall_A,
+          $fell(
+              hi_speed_enabled
+          ) |=> ##[FallCyclesMin:FallCyclesMax] hi_speed_enabled || (hi_speed_sel_o != MuBi4True),
+          clk_i, !rst_ni || disable_sva)
+
+endinterface
diff --git a/hw/ip/clkmgr/dv/sva/clkmgr_sva_ifs.core b/hw/ip/clkmgr/dv/sva/clkmgr_sva_ifs.core
index c8cca64..1a85f41 100644
--- a/hw/ip/clkmgr/dv/sva/clkmgr_sva_ifs.core
+++ b/hw/ip/clkmgr/dv/sva/clkmgr_sva_ifs.core
@@ -8,12 +8,15 @@
   files_dv:
     depend:
       - lowrisc:prim:assert
+      - lowrisc:prim:mubi
+      - lowrisc:ip:lc_ctrl_pkg
       - lowrisc:dv:clkmgr_pwrmgr_sva_if
     files:
       - clkmgr_div_sva_if.sv
       - clkmgr_gated_clock_sva_if.sv
       - clkmgr_aon_cg_en_sva_if.sv
       - clkmgr_cg_en_sva_if.sv
+      - clkmgr_extclk_sva_if.sv
     file_type: systemVerilogSource
 
 targets:
diff --git a/hw/ip/clkmgr/dv/tb.sv b/hw/ip/clkmgr/dv/tb.sv
index ab8d1e1..1ca05ba 100644
--- a/hw/ip/clkmgr/dv/tb.sv
+++ b/hw/ip/clkmgr/dv/tb.sv
@@ -72,7 +72,7 @@
 
   // dut
   clkmgr dut (
-    .clk_i (clk),
+    .clk_i(clk),
     .rst_ni(rst_n),
     .rst_shadowed_ni(rst_n),
 
@@ -100,15 +100,14 @@
     .scanmode_i(clkmgr_if.scanmode_i),
     .idle_i    (clkmgr_if.idle_i),
 
-    .lc_hw_debug_en_i (clkmgr_if.lc_hw_debug_en_i),
+    .lc_hw_debug_en_i(clkmgr_if.lc_hw_debug_en_i),
     .all_clk_byp_req_o(clkmgr_if.all_clk_byp_req),
     .all_clk_byp_ack_i(clkmgr_if.all_clk_byp_ack),
-    .io_clk_byp_req_o (clkmgr_if.io_clk_byp_req),
-    .io_clk_byp_ack_i (clkmgr_if.io_clk_byp_ack),
-    .lc_clk_byp_req_i (clkmgr_if.lc_clk_byp_req),
-    .lc_clk_byp_ack_o (clkmgr_if.lc_clk_byp_ack),
-    // TODO: The new external step down signal must be verified
-    .div_step_down_req_i (prim_mubi_pkg::MuBi4False),
+    .io_clk_byp_req_o(clkmgr_if.io_clk_byp_req),
+    .io_clk_byp_ack_i(clkmgr_if.io_clk_byp_ack),
+    .lc_clk_byp_req_i(clkmgr_if.lc_clk_byp_req),
+    .lc_clk_byp_ack_o(clkmgr_if.lc_clk_byp_ack),
+    .div_step_down_req_i(clkmgr_if.div_step_down_req),
 
     .cg_en_o(),