[dv] Added keymgr_sideload_agent and integrated it with otbn and kmac TB

Following additions/ modifications have been made in this commit:
1. Added key_sideload_agent and related files.
2. Integrated key_sideload_agent with OTBN and KMAC TB.
3. Added key_sideload_set_seq to set keymgr interface.
4. In OTBN TB, key_sideload_set_seq runs forever changing keymgr
   interface values every few (randomized between 10 to 100)
   clock cycles.
5. In kmac_smoke_vseq, key_sideload_set_seq is called to generate keymgr
   interface values.

Signed-off-by: Prajwala Puttappa <prajwalaputtappa@lowrisc.org>
diff --git a/hw/dv/sv/key_sideload_agent/README.md b/hw/dv/sv/key_sideload_agent/README.md
new file mode 100644
index 0000000..35361db
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/README.md
@@ -0,0 +1,3 @@
+# KEY_SIDELOAD UVM Agent
+
+KEY_SIDELOAD UVM Agent is extended from DV library agent classes.
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_agent.core b/hw/dv/sv/key_sideload_agent/key_sideload_agent.core
new file mode 100644
index 0000000..ac41a3f
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_agent.core
@@ -0,0 +1,30 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:dv:key_sideload_agent:0.1"
+description: "KEY_SIDELOAD DV UVM agent"
+filesets:
+  files_dv:
+    depend:
+      - lowrisc:dv:dv_utils
+      - lowrisc:dv:dv_lib
+      - lowrisc:ip:keymgr_pkg
+    files:
+      - key_sideload_if.sv
+      - key_sideload_agent_pkg.sv
+      - key_sideload_item.sv: {is_include_file: true}
+      - key_sideload_agent_cfg.sv: {is_include_file: true}
+      - key_sideload_agent_cov.sv: {is_include_file: true}
+      - key_sideload_driver.sv: {is_include_file: true}
+      - key_sideload_monitor.sv: {is_include_file: true}
+      - key_sideload_agent.sv: {is_include_file: true}
+      - seq_lib/key_sideload_base_seq.sv: {is_include_file: true}
+      - seq_lib/key_sideload_set_seq.sv: {is_include_file: true}
+      - seq_lib/key_sideload_seq_list.sv: {is_include_file: true}
+    file_type: systemVerilogSource
+
+targets:
+  default:
+    filesets:
+      - files_dv
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_agent.sv b/hw/dv/sv/key_sideload_agent/key_sideload_agent.sv
new file mode 100644
index 0000000..050c1b7
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_agent.sv
@@ -0,0 +1,38 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class key_sideload_agent extends dv_base_agent #(
+  .CFG_T          (key_sideload_agent_cfg),
+  .DRIVER_T       (key_sideload_driver),
+  .SEQUENCER_T    (key_sideload_sequencer),
+  .MONITOR_T      (key_sideload_monitor),
+  .COV_T          (key_sideload_agent_cov)
+);
+
+  `uvm_component_utils(key_sideload_agent)
+
+  `uvm_component_new
+
+  function void build_phase(uvm_phase phase);
+    super.build_phase(phase);
+    // get key_sideload_if handle
+    if (!uvm_config_db#(virtual key_sideload_if)::get(this, "", "vif", cfg.vif)) begin
+      `uvm_fatal(`gfn, "failed to get key_sideload_if handle from uvm_config_db")
+    end
+  endfunction
+
+  virtual task run_phase(uvm_phase phase);
+    key_sideload_set_seq p_seq;
+    if (cfg.start_default_seq) begin
+      p_seq = key_sideload_set_seq::type_id::create("p_seq", this);
+      forever begin
+        `DV_CHECK_RANDOMIZE_FATAL(p_seq)
+        p_seq.start(sequencer);
+        repeat($urandom_range(10,100)) begin
+          @(posedge cfg.vif.clk_i);
+        end
+      end
+    end
+  endtask
+endclass
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_agent_cfg.sv b/hw/dv/sv/key_sideload_agent/key_sideload_agent_cfg.sv
new file mode 100644
index 0000000..c7a56fe
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_agent_cfg.sv
@@ -0,0 +1,17 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class key_sideload_agent_cfg extends dv_base_agent_cfg;
+
+  // interface handle used by driver, monitor & the sequencer, via cfg handle
+  virtual key_sideload_if vif;
+
+  bit start_default_seq = 1;
+
+  `uvm_object_utils_begin(key_sideload_agent_cfg)
+  `uvm_object_utils_end
+
+  `uvm_object_new
+
+endclass
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_agent_cov.sv b/hw/dv/sv/key_sideload_agent/key_sideload_agent_cov.sv
new file mode 100644
index 0000000..4b2fa44
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_agent_cov.sv
@@ -0,0 +1,18 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class key_sideload_agent_cov extends dv_base_agent_cov #(key_sideload_agent_cfg);
+  `uvm_component_utils(key_sideload_agent_cov)
+
+  // the base class provides the following handles for use:
+  // key_sideload_agent_cfg: cfg
+
+  // covergroups
+
+  function new(string name, uvm_component parent);
+    super.new(name, parent);
+    // instantiate all covergroups here
+  endfunction : new
+
+endclass
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_agent_pkg.sv b/hw/dv/sv/key_sideload_agent/key_sideload_agent_pkg.sv
new file mode 100644
index 0000000..c9ee3c0
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_agent_pkg.sv
@@ -0,0 +1,37 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+package key_sideload_agent_pkg;
+  // dep packages
+  import uvm_pkg::*;
+  import dv_utils_pkg::*;
+  import dv_lib_pkg::*;
+
+  // macro includes
+  `include "uvm_macros.svh"
+  `include "dv_macros.svh"
+
+  // parameters
+
+  // local types
+  // forward declare classes to allow typedefs below
+  typedef class key_sideload_item;
+  typedef class key_sideload_agent_cfg;
+
+  // reuse dv_base_sequencer as is with the right parameter set
+  typedef dv_base_sequencer #(.ITEM_T(key_sideload_item),
+                              .CFG_T (key_sideload_agent_cfg)) key_sideload_sequencer;
+
+  // functions
+
+  // package sources
+  `include "key_sideload_item.sv"
+  `include "key_sideload_agent_cfg.sv"
+  `include "key_sideload_agent_cov.sv"
+  `include "key_sideload_driver.sv"
+  `include "key_sideload_monitor.sv"
+  `include "key_sideload_seq_list.sv"
+  `include "key_sideload_agent.sv"
+
+endpackage: key_sideload_agent_pkg
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_driver.sv b/hw/dv/sv/key_sideload_agent/key_sideload_driver.sv
new file mode 100644
index 0000000..8d4fa47
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_driver.sv
@@ -0,0 +1,49 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class key_sideload_driver extends dv_base_driver #(.ITEM_T(key_sideload_item),
+                                              .CFG_T (key_sideload_agent_cfg));
+  `uvm_component_utils(key_sideload_driver)
+
+  // the base class provides the following handles for use:
+  // key_sideload_agent_cfg: cfg
+
+  `uvm_component_new
+
+  virtual task run_phase(uvm_phase phase);
+    // base class forks off reset_signals() and get_and_drive() tasks
+    super.run_phase(phase);
+  endtask
+
+  // reset signals
+  virtual task reset_signals();
+    cfg.vif.sideload_key.valid = 0;
+    cfg.vif.sideload_key.key[0] = 'x;
+    cfg.vif.sideload_key.key[1] = 'x;
+  endtask
+
+  // drive trans received from sequencer
+  virtual task get_and_drive();
+    forever begin
+      seq_item_port.get_next_item(req);
+      $cast(rsp, req.clone());
+      rsp.set_id_info(req);
+      `uvm_info(`gfn, $sformatf("rcvd item:\n%0s", req.sprint()), UVM_HIGH)
+      cfg.vif.sideload_key.valid = req.valid;
+      if (req.valid) begin
+        cfg.vif.sideload_key.key[0] = req.key0;
+        cfg.vif.sideload_key.key[1] = req.key1;
+      end
+      else begin
+        cfg.vif.sideload_key.key[0] = 'x;
+        cfg.vif.sideload_key.key[1] = 'x;
+      end
+      // send rsp back to seq
+      `uvm_info(`gfn, "item sent", UVM_HIGH)
+      cfg.vif.wait_clks(req.rsp_delay);
+      seq_item_port.item_done(req);
+    end
+  endtask
+
+endclass
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_if.sv b/hw/dv/sv/key_sideload_agent/key_sideload_if.sv
new file mode 100644
index 0000000..568698c
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_if.sv
@@ -0,0 +1,30 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+interface key_sideload_if #(
+  parameter type KEY_T = keymgr_pkg::hw_key_req_t,
+  parameter int  KeyWidth = keymgr_pkg::KeyWidth
+) (
+  input logic clk_i,
+  input logic rst_ni,
+  // This struct contains three fields:
+  // - valid
+  // - key_share0
+  // - key_share1
+  output KEY_T sideload_key
+);
+
+  string msg_id = "key_sideload_if";
+
+  task automatic wait_valid(logic is_valid);
+    wait (sideload_key.valid === is_valid);
+  endtask
+
+  task automatic wait_clks(int rsp_delay);
+    for (int i = 0; i < rsp_delay; i++) begin
+      if (!rst_ni) break;
+      @(posedge clk_i or negedge rst_ni);
+    end
+  endtask
+endinterface
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_item.sv b/hw/dv/sv/key_sideload_agent/key_sideload_item.sv
new file mode 100644
index 0000000..090fa77
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_item.sv
@@ -0,0 +1,24 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class key_sideload_item extends uvm_sequence_item;
+
+  // random variables
+  rand bit                            valid;
+  rand bit [keymgr_pkg::KeyWidth-1:0] key0;
+  rand bit [keymgr_pkg::KeyWidth-1:0] key1;
+  rand int unsigned                   rsp_delay = 1;
+
+  constraint rsp_delay_constraint_c {rsp_delay inside {[1:10]};}
+
+  `uvm_object_utils_begin(key_sideload_item)
+    `uvm_field_int(valid, UVM_DEFAULT)
+    `uvm_field_int(key0,  UVM_DEFAULT)
+    `uvm_field_int(key1,  UVM_DEFAULT)
+    `uvm_field_int(rsp_delay,  UVM_DEFAULT)
+  `uvm_object_utils_end
+
+  `uvm_object_new
+
+endclass
diff --git a/hw/dv/sv/key_sideload_agent/key_sideload_monitor.sv b/hw/dv/sv/key_sideload_agent/key_sideload_monitor.sv
new file mode 100644
index 0000000..ebc81aa
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/key_sideload_monitor.sv
@@ -0,0 +1,43 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class key_sideload_monitor extends dv_base_monitor #(
+    .ITEM_T (key_sideload_item),
+    .CFG_T  (key_sideload_agent_cfg),
+    .COV_T  (key_sideload_agent_cov)
+  );
+  `uvm_component_utils(key_sideload_monitor)
+
+  // the base class provides the following handles for use:
+  // key_sideload_agent_cfg: cfg
+  // key_sideload_agent_cov: cov
+  // uvm_analysis_port #(key_sideload_item): analysis_port
+
+  `uvm_component_new
+
+  function void build_phase(uvm_phase phase);
+    super.build_phase(phase);
+  endfunction
+
+  task run_phase(uvm_phase phase);
+    super.run_phase(phase);
+  endtask
+
+  // collect transactions forever - already forked in dv_base_monitor::run_phase
+  virtual protected task collect_trans(uvm_phase phase);
+    forever begin
+      // TODO: detect event
+
+      // TODO: sample the interface
+
+      // TODO: sample the covergroups
+
+      // TODO: write trans to analysis_port
+
+      // TODO: remove the line below: it is added to prevent zero delay loop in template code
+      #1us;
+    end
+  endtask
+
+endclass
diff --git a/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_base_seq.sv b/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_base_seq.sv
new file mode 100644
index 0000000..b9364db
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_base_seq.sv
@@ -0,0 +1,18 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class key_sideload_base_seq extends dv_base_seq #(
+    .REQ         (key_sideload_item),
+    .CFG_T       (key_sideload_agent_cfg),
+    .SEQUENCER_T (key_sideload_sequencer)
+  );
+  `uvm_object_utils(key_sideload_base_seq)
+
+  `uvm_object_new
+
+  virtual task body();
+    `uvm_fatal(`gtn, "Need to override this when you extend from this class!")
+  endtask
+
+endclass
diff --git a/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_seq_list.sv b/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_seq_list.sv
new file mode 100644
index 0000000..8e919e5
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_seq_list.sv
@@ -0,0 +1,6 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+`include "key_sideload_base_seq.sv"
+`include "key_sideload_set_seq.sv"
diff --git a/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_set_seq.sv b/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_set_seq.sv
new file mode 100644
index 0000000..1fd7233
--- /dev/null
+++ b/hw/dv/sv/key_sideload_agent/seq_lib/key_sideload_set_seq.sv
@@ -0,0 +1,22 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class key_sideload_set_seq extends key_sideload_base_seq;
+  `uvm_object_utils(key_sideload_set_seq)
+
+  `uvm_object_new
+  rand keymgr_pkg::hw_key_req_t sideload_key;
+
+  virtual task body();
+    key_sideload_item item;
+    item = key_sideload_item::type_id::create("item");
+    start_item(item);
+    item.valid = sideload_key.valid;
+    item.key0  = sideload_key.key[0];
+    item.key1  = sideload_key.key[1];
+    finish_item(item);
+    get_response(item);
+  endtask
+
+endclass
diff --git a/hw/dv/sv/key_sideload_if/key_sideload_if.core b/hw/dv/sv/key_sideload_if/key_sideload_if.core
deleted file mode 100644
index b2702a4..0000000
--- a/hw/dv/sv/key_sideload_if/key_sideload_if.core
+++ /dev/null
@@ -1,21 +0,0 @@
-CAPI=2:
-# Copyright lowRISC contributors.
-# Licensed under the Apache License, Version 2.0, see LICENSE for details.
-# SPDX-License-Identifier: Apache-2.0
-name: "lowrisc:dv:key_sideload_if"
-description: "Common key sideload interfaces used in ast, kmac, otbn"
-
-filesets:
-  files_rtl:
-    depend:
-      - lowrisc:ip:keymgr_pkg
-  files_dv:
-    files:
-      - key_sideload_if.sv
-    file_type: systemVerilogSource
-
-targets:
-  default:
-    filesets:
-      - files_rtl
-      - files_dv
diff --git a/hw/dv/sv/key_sideload_if/key_sideload_if.sv b/hw/dv/sv/key_sideload_if/key_sideload_if.sv
deleted file mode 100644
index 2e6783d..0000000
--- a/hw/dv/sv/key_sideload_if/key_sideload_if.sv
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-interface key_sideload_if #(parameter type KEY_T = keymgr_pkg::hw_key_req_t,
-                            parameter int  KeyWidth = keymgr_pkg::KeyWidth
-);
-  // This struct contains three fields:
-  // - valid
-  // - key_share0
-  // - key_share1
-  KEY_T sideload_key;
-
-  string msg_id = "key_sideload_if";
-
-  // share0 and share1 are only driven when `valid` is 1.
-  task automatic drive_sideload_key(logic key_valid,
-                                    logic [KeyWidth-1:0] share0 = '0,
-                                    logic [KeyWidth-1:0] share1 = '0);
-    KEY_T key;
-
-    `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(key, key.valid == key_valid;, , msg_id)
-    key.key[0] = (key_valid) ? share0 : 'hx;
-    key.key[1] = (key_valid) ? share1 : 'hx;
-
-    sideload_key = key;
-  endtask
-
-  task automatic wait_valid(logic is_valid);
-    wait (sideload_key.valid === is_valid);
-  endtask
-
-endinterface
diff --git a/hw/ip/kmac/dv/env/kmac_env.core b/hw/ip/kmac/dv/env/kmac_env.core
index 0f1537b..8b0090b 100644
--- a/hw/ip/kmac/dv/env/kmac_env.core
+++ b/hw/ip/kmac/dv/env/kmac_env.core
@@ -14,7 +14,7 @@
       - lowrisc:dv:str_utils
       - lowrisc:dv:test_vectors
       - lowrisc:dv:digestpp_dpi:0.1
-      - lowrisc:dv:key_sideload_if
+      - lowrisc:dv:key_sideload_agent
       - lowrisc:ip:kmac
     files:
       - kmac_env_pkg.sv
diff --git a/hw/ip/kmac/dv/env/kmac_env.sv b/hw/ip/kmac/dv/env/kmac_env.sv
index 9cccee4..9340fef 100644
--- a/hw/ip/kmac/dv/env/kmac_env.sv
+++ b/hw/ip/kmac/dv/env/kmac_env.sv
@@ -13,6 +13,7 @@
   `uvm_component_new
 
   kmac_app_agent m_kmac_app_agent[kmac_pkg::NumAppIntf];
+  key_sideload_agent keymgr_sideload_agent;
 
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
@@ -27,9 +28,9 @@
     if (!uvm_config_db#(idle_vif)::get(this, "", "idle_vif", cfg.idle_vif)) begin
       `uvm_fatal(`gfn, "failed to get idle_vif handle from uvm_config_db")
     end
-    if (!uvm_config_db#(sideload_vif)::get(this, "", "sideload_vif", cfg.sideload_vif)) begin
-      `uvm_fatal(`gfn, "failed to get sideload_vif handle from uvm_config_db")
-    end
+    keymgr_sideload_agent = key_sideload_agent::type_id::create("keymgr_sideload_agent", this);
+    uvm_config_db#(key_sideload_agent_cfg)::set(this, "keymgr_sideload_agent*",
+                                                "cfg", cfg.keymgr_sideload_agent_cfg);
   endfunction
 
   function void connect_phase(uvm_phase phase);
@@ -39,8 +40,10 @@
       m_kmac_app_agent[i].monitor.analysis_port.connect(scoreboard.kmac_app_rsp_fifo[i].analysis_export);
       m_kmac_app_agent[i].m_data_push_agent.monitor.analysis_port.connect(
         scoreboard.kmac_app_req_fifo[i].analysis_export);
-      virtual_sequencer.kmac_app_sequencer_h[i] = m_kmac_app_agent[i].sequencer;
+      virtual_sequencer.kmac_app_sequencer_h[i]  = m_kmac_app_agent[i].sequencer;
+      virtual_sequencer.key_sideload_sequencer_h = keymgr_sideload_agent.sequencer;
     end
+    cfg.keymgr_sideload_agent_cfg.start_default_seq = 0;
 
   endfunction
 
diff --git a/hw/ip/kmac/dv/env/kmac_env_cfg.sv b/hw/ip/kmac/dv/env/kmac_env_cfg.sv
index fdbfcd5..2b9f421 100644
--- a/hw/ip/kmac/dv/env/kmac_env_cfg.sv
+++ b/hw/ip/kmac/dv/env/kmac_env_cfg.sv
@@ -6,9 +6,9 @@
 
   // ext interfaces
   idle_vif        idle_vif;
-  sideload_vif    sideload_vif;
 
   rand kmac_app_agent_cfg m_kmac_app_agent_cfg[kmac_pkg::NumAppIntf];
+  rand key_sideload_agent_cfg keymgr_sideload_agent_cfg;
 
   // Masked KMAC is the default configuration
   bit enable_masking = 1;
@@ -33,7 +33,8 @@
       m_kmac_app_agent_cfg[i] = kmac_app_agent_cfg::type_id::create(name);
       m_kmac_app_agent_cfg[i].if_mode = dv_utils_pkg::Host;
     end
-
+    keymgr_sideload_agent_cfg = key_sideload_agent_cfg::type_id
+                                ::create("keymgr_sideload_agent_cfg");
     void'($value$plusargs("enable_masking=%0d", enable_masking));
     void'($value$plusargs("test_vectors_sha3_variant=%0d", sha3_variant));
     void'($value$plusargs("test_vectors_shake_variant=%0d", shake_variant));
diff --git a/hw/ip/kmac/dv/env/kmac_env_pkg.sv b/hw/ip/kmac/dv/env/kmac_env_pkg.sv
index d414b1b..09f9756 100644
--- a/hw/ip/kmac/dv/env/kmac_env_pkg.sv
+++ b/hw/ip/kmac/dv/env/kmac_env_pkg.sv
@@ -20,6 +20,7 @@
   import kmac_ral_pkg::*;
   import kmac_pkg::*;
   import keymgr_pkg::*;
+  import key_sideload_agent_pkg::*;
 
   // macro includes
   `include "uvm_macros.svh"
diff --git a/hw/ip/kmac/dv/env/kmac_scoreboard.sv b/hw/ip/kmac/dv/env/kmac_scoreboard.sv
index 5aab558..4bc54b4 100644
--- a/hw/ip/kmac/dv/env/kmac_scoreboard.sv
+++ b/hw/ip/kmac/dv/env/kmac_scoreboard.sv
@@ -301,13 +301,13 @@
       `DV_SPINWAIT_EXIT(
           forever begin
             // Wait for a valid sideloaded key
-            cfg.sideload_vif.wait_valid(logic'(1'b1));
+            cfg.keymgr_sideload_agent_cfg.vif.wait_valid(logic'(1'b1));
 
             // Once valid sideload keys have been seen, update scoreboard state.
             //
             // Note: max size of sideloaded key is keymgr_pkg::KeyWidth
 
-            sideload_key = cfg.sideload_vif.sideload_key;
+            sideload_key = cfg.keymgr_sideload_agent_cfg.vif.sideload_key;
 
             `uvm_info(`gfn, $sformatf("detected valid sideload_key: %0p", sideload_key), UVM_HIGH)
 
@@ -317,7 +317,7 @@
             end
 
             // Sequence will drop the sideloaded key after scb can process the digest
-            cfg.sideload_vif.wait_valid(logic'(1'b0));
+            cfg.keymgr_sideload_agent_cfg.vif.wait_valid(logic'(1'b0));
           end
           ,
           wait(cfg.under_reset);
@@ -414,7 +414,8 @@
                 end
               end
               StAppCfg: begin
-                if (app_mode == AppKeymgr && !cfg.sideload_vif.sideload_key.valid) begin
+                if (app_mode == AppKeymgr &&
+                    !cfg.keymgr_sideload_agent_cfg.vif.sideload_key.valid) begin
                   app_st = StKeyMgrErrKeyNotValid;
                 end else begin
                   app_st = StAppMsg;
diff --git a/hw/ip/kmac/dv/env/kmac_virtual_sequencer.sv b/hw/ip/kmac/dv/env/kmac_virtual_sequencer.sv
index ad58015..151a85b 100644
--- a/hw/ip/kmac/dv/env/kmac_virtual_sequencer.sv
+++ b/hw/ip/kmac/dv/env/kmac_virtual_sequencer.sv
@@ -11,5 +11,6 @@
   `uvm_component_new
 
   kmac_app_sequencer kmac_app_sequencer_h[kmac_pkg::NumAppIntf];
+  key_sideload_sequencer key_sideload_sequencer_h;
 
 endclass
diff --git a/hw/ip/kmac/dv/env/seq_lib/kmac_smoke_vseq.sv b/hw/ip/kmac/dv/env/seq_lib/kmac_smoke_vseq.sv
index 6cebe3d..7ba6890 100644
--- a/hw/ip/kmac/dv/env/seq_lib/kmac_smoke_vseq.sv
+++ b/hw/ip/kmac/dv/env/seq_lib/kmac_smoke_vseq.sv
@@ -97,6 +97,7 @@
 
     logic [keymgr_pkg::KeyWidth-1:0] sideload_share0;
     logic [keymgr_pkg::KeyWidth-1:0] sideload_share1;
+    key_sideload_set_seq sideload_seq;
 
     `uvm_info(`gfn, $sformatf("Starting %0d message hashes", num_trans), UVM_LOW)
 
@@ -120,15 +121,11 @@
       if (kmac_en) begin
         // provide a random sideloaded key
         if (en_sideload || provide_sideload_key) begin
-          `DV_CHECK_STD_RANDOMIZE_FATAL(sideload_share0)
-          `DV_CHECK_STD_RANDOMIZE_FATAL(sideload_share1)
-
-          `uvm_info(`gfn, $sformatf("sideload_key_share0: 0x%0x", sideload_share0), UVM_HIGH)
-          `uvm_info(`gfn, $sformatf("sideload_key_share1: 0x%0x", sideload_share1), UVM_HIGH)
-
-          cfg.sideload_vif.drive_sideload_key(kmac_err_type != kmac_pkg::ErrKeyNotValid,
-                                              sideload_share0,
-                                              sideload_share1);
+          `uvm_create_on(sideload_seq, p_sequencer.key_sideload_sequencer_h);
+          `DV_CHECK_RANDOMIZE_WITH_FATAL(sideload_seq,
+                                         sideload_key.valid == kmac_err_type !=
+                                         kmac_pkg::ErrKeyNotValid;)
+          `uvm_send(sideload_seq)
         end
         // write the SW key to the CSRs
         if (!en_app) begin
@@ -297,7 +294,9 @@
       // Drop the sideloaded key if it was provided to the DUT.
       if (kmac_en && (en_sideload || provide_sideload_key)) begin
         `uvm_info(`gfn, "dropping sideload key", UVM_HIGH)
-        cfg.sideload_vif.drive_sideload_key(0);
+        `DV_CHECK_RANDOMIZE_WITH_FATAL(sideload_seq,
+                                       sideload_key.valid == 0;)
+        sideload_seq.start(p_sequencer.key_sideload_sequencer_h);
       end
 
     end
diff --git a/hw/ip/kmac/dv/tb.sv b/hw/ip/kmac/dv/tb.sv
index 8d212f3..e49de94 100644
--- a/hw/ip/kmac/dv/tb.sv
+++ b/hw/ip/kmac/dv/tb.sv
@@ -34,7 +34,10 @@
 
   tl_if tl_if(.clk(clk), .rst_n(rst_n));
 
-  key_sideload_if sideload_if();
+  key_sideload_if sideload_if(
+    .clk_i  (clk),
+    .rst_ni (rst_n)
+  );
 
   kmac_app_intf kmac_app_if[kmac_pkg::NumAppIntf](.clk(clk), .rst_n(rst_n));
 
@@ -103,7 +106,8 @@
     uvm_config_db#(devmode_vif)::set(null, "*.env", "devmode_vif", devmode_if);
     uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if);
     uvm_config_db#(virtual pins_if#(1))::set(null, "*.env", "idle_vif", idle_if);
-    uvm_config_db#(virtual key_sideload_if)::set(null, "*.env", "sideload_vif", sideload_if);
+    uvm_config_db#(virtual key_sideload_if)::set(null, "*.env.keymgr_sideload_agent*",
+                                                 "vif", sideload_if);
     $timeformat(-12, 0, " ps", 12);
     run_test();
   end
diff --git a/hw/ip/otbn/dv/model/otbn_core_model.sv b/hw/ip/otbn/dv/model/otbn_core_model.sv
index 6f41c43..1ed1ed8 100644
--- a/hw/ip/otbn/dv/model/otbn_core_model.sv
+++ b/hw/ip/otbn/dv/model/otbn_core_model.sv
@@ -193,7 +193,7 @@
   // Assertion to ensure that keymgr key valid is never unknown.
   `ASSERT_KNOWN(KeyValidIsKnownChk_A, keymgr_key_i.valid)
   // Assertion to ensure that keymgr key values are never unknown if valid is high.
-  `ASSERT_KNOWN_IF(KeyIsKnownChk_A, keymgr_key_i.valid, {keymgr_key_i.key[0], keymgr_key_i.key[1]})
+  `ASSERT_KNOWN_IF(KeyIsKnownChk_A, {keymgr_key_i.key[0], keymgr_key_i.key[1]}, keymgr_key_i.valid)
   assign unused_raw_err_bits = ^raw_err_bits_q[31:$bits(err_bits_t)];
   assign unused_edn_rsp_fips = edn_rnd_i.edn_fips & edn_urnd_i.edn_fips;
 
diff --git a/hw/ip/otbn/dv/uvm/env/otbn_env.core b/hw/ip/otbn/dv/uvm/env/otbn_env.core
index a1caba9..31c1991 100644
--- a/hw/ip/otbn/dv/uvm/env/otbn_env.core
+++ b/hw/ip/otbn/dv/uvm/env/otbn_env.core
@@ -14,6 +14,7 @@
       - lowrisc:dv:tl_agent
       - lowrisc:dv:alert_esc_agent
       - lowrisc:dv:otbn_model_agent
+      - lowrisc:dv:key_sideload_agent
     files:
       - otbn_env_pkg.sv
       - otbn_loop_if.sv
diff --git a/hw/ip/otbn/dv/uvm/env/otbn_env.sv b/hw/ip/otbn/dv/uvm/env/otbn_env.sv
index 1f46240..6d2d9fb 100644
--- a/hw/ip/otbn/dv/uvm/env/otbn_env.sv
+++ b/hw/ip/otbn/dv/uvm/env/otbn_env.sv
@@ -12,6 +12,7 @@
 
   otbn_model_agent   model_agent;
   otbn_trace_monitor trace_monitor;
+  key_sideload_agent keymgr_sideload_agent;
 
   `uvm_component_new
 
@@ -25,6 +26,10 @@
     uvm_config_db#(otbn_model_agent_cfg)::set(this, "model_agent*", "cfg", cfg.model_agent_cfg);
     cfg.model_agent_cfg.en_cov = cfg.en_cov;
 
+    keymgr_sideload_agent = key_sideload_agent::type_id::create("keymgr_sideload_agent", this);
+    uvm_config_db#(key_sideload_agent_cfg)::set(this, "keymgr_sideload_agent*",
+                                                "cfg", cfg.keymgr_sideload_agent_cfg);
+
     if (!uvm_config_db#(virtual otbn_trace_if)::get(this, "", "trace_vif", cfg.trace_vif)) begin
       `uvm_fatal(`gfn, "failed to get otbn_trace_if handle from uvm_config_db")
     end
diff --git a/hw/ip/otbn/dv/uvm/env/otbn_env_cfg.sv b/hw/ip/otbn/dv/uvm/env/otbn_env_cfg.sv
index 8056228..81172ed 100644
--- a/hw/ip/otbn/dv/uvm/env/otbn_env_cfg.sv
+++ b/hw/ip/otbn/dv/uvm/env/otbn_env_cfg.sv
@@ -7,6 +7,8 @@
   // ext component cfgs
   rand otbn_model_agent_cfg model_agent_cfg;
 
+  rand key_sideload_agent_cfg keymgr_sideload_agent_cfg;
+
   `uvm_object_utils_begin(otbn_env_cfg)
   `uvm_object_utils_end
 
@@ -69,7 +71,9 @@
     // Tell the CIP base code what alert we generate if we see a TL fault.
     tl_intg_alert_name = "fatal";
 
-    model_agent_cfg = otbn_model_agent_cfg::type_id::create("model_agent_cfg");
+    model_agent_cfg  = otbn_model_agent_cfg  ::type_id::create("model_agent_cfg");
+    keymgr_sideload_agent_cfg = key_sideload_agent_cfg::type_id
+                                ::create("keymgr_sideload_agent_cfg");
 
     super.initialize(csr_base_addr);
 
diff --git a/hw/ip/otbn/dv/uvm/env/otbn_env_pkg.sv b/hw/ip/otbn/dv/uvm/env/otbn_env_pkg.sv
index 808101e..0c98e32 100644
--- a/hw/ip/otbn/dv/uvm/env/otbn_env_pkg.sv
+++ b/hw/ip/otbn/dv/uvm/env/otbn_env_pkg.sv
@@ -16,6 +16,7 @@
   import mem_bkdr_util_pkg::mem_bkdr_util;
   import prim_util_pkg::vbits;
   import prim_mubi_pkg::*;
+  import key_sideload_agent_pkg::*;
 
   // autogenerated RAL model
   import otbn_reg_pkg::*;
diff --git a/hw/ip/otbn/dv/uvm/tb.sv b/hw/ip/otbn/dv/uvm/tb.sv
index 571ade9..4121b87 100644
--- a/hw/ip/otbn/dv/uvm/tb.sv
+++ b/hw/ip/otbn/dv/uvm/tb.sv
@@ -23,7 +23,6 @@
   wire clk, rst_n;
   wire idle, intr_done;
   wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
-  otbn_key_req_t keymgr_key;
 
   // interfaces
   clk_rst_if                    clk_rst_if (.clk(clk), .rst_n(rst_n));
@@ -36,9 +35,16 @@
   // needed for sequences that trigger alerts (locking OTBN) without telling the model.
   `DV_ASSERT_CTRL("otbn_status_assert_en", tb.MatchingStatus_A)
 
-  assign keymgr_key.key[0] = {12{32'hDEADBEEF}};
-  assign keymgr_key.key[1] = {12{32'hBAADF00D}};
-  assign keymgr_key.valid  = 1'b1;
+  otbn_key_req_t keymgr_key;
+  hw_key_req_t   sideload_key;
+  key_sideload_if keymgr_if (
+    .clk_i        (clk),
+    .rst_ni       (rst_n),
+    .sideload_key (sideload_key)
+  );
+  assign keymgr_key.valid  = sideload_key.valid;
+  assign keymgr_key.key[0] = sideload_key.key[0];
+  assign keymgr_key.key[1] = sideload_key.key[1];
 
   otbn_model_if #(
     .ImemSizeByte (otbn_reg_pkg::OTBN_IMEM_SIZE)
@@ -48,6 +54,7 @@
     .keymgr_key_i  (keymgr_key)
   );
 
+
   // edn_clk, edn_rst_n and edn_if is defined and driven in below macro
   `DV_EDN_IF_CONNECT
 
@@ -275,6 +282,8 @@
     uvm_config_db#(idle_vif)::set(null, "*.env", "idle_vif", idle_if);
     uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if);
     uvm_config_db#(virtual otbn_model_if)::set(null, "*.env.model_agent", "vif", model_if);
+    uvm_config_db#(virtual key_sideload_if)::set(null, "*.env.keymgr_sideload_agent",
+    "vif", keymgr_if);
 
     uvm_config_db#(virtual otbn_trace_if)::set(null, "*.env", "trace_vif",
                                                dut.u_otbn_core.i_otbn_trace_if);