[csrng/dv] Added support for multiple hw_apps, removed halt main_sm

Signed-off-by: Steve Nelson <steve.nelson@wdc.com>
diff --git a/hw/ip/csrng/dv/env/csrng_env.sv b/hw/ip/csrng/dv/env/csrng_env.sv
index b256bb0..c6b33b3 100644
--- a/hw/ip/csrng/dv/env/csrng_env.sv
+++ b/hw/ip/csrng/dv/env/csrng_env.sv
@@ -11,7 +11,7 @@
   `uvm_component_utils(csrng_env)
 
   push_pull_agent#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH))  m_entropy_src_agent;
-  csrng_agent   m_edn_agent;
+  csrng_agent   m_edn_agent[NUM_HW_APPS];
 
   `uvm_component_new
 
@@ -27,14 +27,17 @@
     cfg.m_entropy_src_agent_cfg.if_mode    = dv_utils_pkg::Device;
     cfg.m_entropy_src_agent_cfg.en_cov     = cfg.en_cov;
 
-    m_edn_agent = csrng_agent::type_id::create("m_edn_agent", this);
-    uvm_config_db#(csrng_agent_cfg)::set(this, "m_edn_agent*", "cfg", cfg.m_edn_agent_cfg);
-    cfg.m_edn_agent_cfg.if_mode = dv_utils_pkg::Host;
-    cfg.m_edn_agent_cfg.en_cov  = cfg.en_cov;
+    for (int i = 0; i < NUM_HW_APPS; i++) begin
+      string edn_agent_name = $sformatf("m_edn_agent[%0d]", i);
+      m_edn_agent[i] = csrng_agent::type_id::create(edn_agent_name, this);
+      uvm_config_db#(csrng_agent_cfg)::set(this, $sformatf("%0s*", edn_agent_name), "cfg", cfg.m_edn_agent_cfg[i]);
+      cfg.m_edn_agent_cfg[i].if_mode = dv_utils_pkg::Host;
+      cfg.m_edn_agent_cfg[i].en_cov  = cfg.en_cov;
 
-    if (!uvm_config_db#(virtual pins_if)::get(this, "", "efuse_sw_app_enable_vif",
-         cfg.efuse_sw_app_enable_vif)) begin
-      `uvm_fatal(get_full_name(), "failed to get efuse_sw_app_enable_vif from uvm_config_db")
+      if (!uvm_config_db#(virtual pins_if)::get(this, "", "efuse_sw_app_enable_vif",
+           cfg.efuse_sw_app_enable_vif)) begin
+        `uvm_fatal(get_full_name(), "failed to get efuse_sw_app_enable_vif from uvm_config_db")
+      end
     end
   endfunction
 
@@ -42,13 +45,17 @@
     super.connect_phase(phase);
     if (cfg.en_scb) begin
       m_entropy_src_agent.monitor.analysis_port.connect(scoreboard.entropy_src_fifo.analysis_export);
-      m_edn_agent.monitor.analysis_port.connect(scoreboard.csrng_cmd_fifo.analysis_export);
+      for (int i = 0; i < NUM_HW_APPS; i++) begin
+        m_edn_agent[i].monitor.analysis_port.connect(scoreboard.csrng_cmd_fifo[i].analysis_export);
+      end
     end
     if (cfg.is_active) begin
       if (cfg.m_entropy_src_agent_cfg.is_active)
         virtual_sequencer.entropy_src_sequencer_h = m_entropy_src_agent.sequencer;
-      if (cfg.m_edn_agent_cfg.is_active)
-        virtual_sequencer.edn_sequencer_h = m_edn_agent.sequencer;
+      for (int i = 0; i < NUM_HW_APPS; i++) begin
+        if (cfg.m_edn_agent_cfg[i].is_active)
+          virtual_sequencer.edn_sequencer_h[i] = m_edn_agent[i].sequencer;
+      end
     end
   endfunction
 
diff --git a/hw/ip/csrng/dv/env/csrng_env_cfg.sv b/hw/ip/csrng/dv/env/csrng_env_cfg.sv
index 0708fe1..99173aa 100644
--- a/hw/ip/csrng/dv/env/csrng_env_cfg.sv
+++ b/hw/ip/csrng/dv/env/csrng_env_cfg.sv
@@ -13,7 +13,7 @@
   rand push_pull_agent_cfg#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH))
        m_entropy_src_agent_cfg;
 
-  rand csrng_agent_cfg   m_edn_agent_cfg;
+  rand csrng_agent_cfg   m_edn_agent_cfg[NUM_HW_APPS];
 
   virtual pins_if  efuse_sw_app_enable_vif;
 
@@ -24,10 +24,10 @@
   rand bit [3:0]   cmd_length, cmd_flags;
 
   // Variables
-  bit                                    compliance, status;
-  bit [csrng_env_pkg::KEY_LEN-1:0]       key;
-  bit [csrng_env_pkg::BLOCK_LEN-1:0]     v;
-  bit [csrng_env_pkg::RSD_CTR_LEN-1:0]   reseed_counter;
+  bit                                    compliance[NUM_HW_APPS], status[NUM_HW_APPS];
+  bit [csrng_env_pkg::KEY_LEN-1:0]       key[NUM_HW_APPS];
+  bit [csrng_env_pkg::BLOCK_LEN-1:0]     v[NUM_HW_APPS];
+  bit [csrng_env_pkg::RSD_CTR_LEN-1:0]   reseed_counter[NUM_HW_APPS];
 
   // Constraints
   constraint c_efuse_sw_app_enable {efuse_sw_app_enable dist { 1 :/ efuse_sw_app_enable_pct,
@@ -51,7 +51,9 @@
     m_entropy_src_agent_cfg = push_pull_agent_cfg#(.HostDataWidth(entropy_src_pkg::
                               FIPS_CSRNG_BUS_WIDTH))::type_id::create("m_entropy_src_agent_cfg");
 
-    m_edn_agent_cfg = csrng_agent_cfg::type_id::create("m_edn_agent_cfg");
+    for (int i = 0; i < NUM_HW_APPS; i++) begin
+      m_edn_agent_cfg[i] = csrng_agent_cfg::type_id::create($sformatf("m_edn_agent_cfg[%0d]", i));
+    end
 
     // set num_interrupts & num_alerts
     begin
@@ -63,37 +65,33 @@
   endfunction
 
     // Compare internal state
-  task check_int_state();
+  task check_int_state(uint hwapp);
     bit [TL_DW-1:0]                        rdata;
     bit                                    hw_compliance, hw_status;
     bit [csrng_env_pkg::KEY_LEN-1:0]       hw_key;
     bit [csrng_env_pkg::BLOCK_LEN-1:0]     hw_v;
     bit [csrng_env_pkg::RSD_CTR_LEN-1:0]   hw_reseed_counter;
 
-    csr_wr(.ptr(ral.halt_main_sm), .value(1'b1));
-    csr_spinwait(.ptr(ral.main_sm_sts), .exp_data(1'b1));
-    csr_wr(.ptr(ral.int_state_num), .value(1'b0));
+    csr_wr(.ptr(ral.int_state_num), .value(hwapp));
     for (int i = 0; i < RSD_CTR_LEN/TL_DW; i++) begin
       csr_rd(.ptr(ral.int_state_val), .value(rdata));
       hw_reseed_counter = (rdata<<TL_DW*i) + hw_reseed_counter;
     end
-    `DV_CHECK_EQ_FATAL(hw_reseed_counter, reseed_counter)
+    `DV_CHECK_EQ_FATAL(hw_reseed_counter, reseed_counter[hwapp])
     for (int i = 0; i < BLOCK_LEN/TL_DW; i++) begin
       csr_rd(.ptr(ral.int_state_val), .value(rdata));
       hw_v = (rdata<<TL_DW*i) + hw_v;
     end
-    `DV_CHECK_EQ_FATAL(hw_v, v)
+    `DV_CHECK_EQ_FATAL(hw_v, v[hwapp])
     for (int i = 0; i < KEY_LEN/TL_DW; i++) begin
       csr_rd(.ptr(ral.int_state_val), .value(rdata));
       hw_key = (rdata<<TL_DW*i) + hw_key;
     end
-    `DV_CHECK_EQ_FATAL(hw_key, key)
+    `DV_CHECK_EQ_FATAL(hw_key, key[hwapp])
     csr_rd(.ptr(ral.int_state_val), .value(rdata));
     hw_compliance = rdata[1];
     hw_status     = rdata[0];
-    `DV_CHECK_EQ_FATAL({hw_compliance, hw_status}, {compliance, status})
-    csr_wr(.ptr(ral.halt_main_sm), .value(1'b0));
-    csr_spinwait(.ptr(ral.main_sm_sts), .exp_data(1'b0));
+    `DV_CHECK_EQ_FATAL({hw_compliance, hw_status}, {compliance[hwapp], status[hwapp]})
  endtask
 
   virtual function string convert2string();
diff --git a/hw/ip/csrng/dv/env/csrng_env_pkg.sv b/hw/ip/csrng/dv/env/csrng_env_pkg.sv
index f9ffb0c..6a65fdf 100644
--- a/hw/ip/csrng/dv/env/csrng_env_pkg.sv
+++ b/hw/ip/csrng/dv/env/csrng_env_pkg.sv
@@ -21,7 +21,7 @@
   `include "dv_macros.svh"
 
   // parameters
-  parameter uint     NUM_HW_APPS      = 1;
+  parameter uint     NUM_HW_APPS      = 2;
   parameter string   LIST_OF_ALERTS[] = {"fatal_alert"};
   parameter uint     NUM_ALERTS       = 1;
   parameter uint     KEY_LEN          = 256;
diff --git a/hw/ip/csrng/dv/env/csrng_scoreboard.sv b/hw/ip/csrng/dv/env/csrng_scoreboard.sv
index dff8757..0987847 100644
--- a/hw/ip/csrng/dv/env/csrng_scoreboard.sv
+++ b/hw/ip/csrng/dv/env/csrng_scoreboard.sv
@@ -10,7 +10,6 @@
   `uvm_component_utils(csrng_scoreboard)
 
   // local variables
-  csrng_item              cs_item;
   bit [RSD_CTR_LEN-1:0]   reseed_counter;
   bit [BLOCK_LEN-1:0]     v;
   bit [KEY_LEN-1:0]       key;
@@ -19,7 +18,7 @@
   // TLM agent fifos
   uvm_tlm_analysis_fifo#(push_pull_item#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH)))
       entropy_src_fifo;
-  uvm_tlm_analysis_fifo#(csrng_item)   csrng_cmd_fifo;
+  uvm_tlm_analysis_fifo#(csrng_item)   csrng_cmd_fifo[NUM_HW_APPS];
 
   // local queues to hold incoming packets pending comparison
   push_pull_item#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH))
@@ -31,7 +30,9 @@
     super.build_phase(phase);
 
     entropy_src_fifo = new("entropy_src_fifo", this);
-    csrng_cmd_fifo   = new("csrng_cmd_fifo", this);
+    for (int i = 0; i < NUM_HW_APPS; i++) begin
+      csrng_cmd_fifo[i] = new($sformatf("csrng_cmd_fifo[%0d]", i), this);
+    end
   endfunction
 
   function void connect_phase(uvm_phase phase);
@@ -43,7 +44,8 @@
 
     fork
       process_entropy_src_fifo();
-      process_csrng_cmd_fifo();
+      for (int i = 0; i < NUM_HW_APPS; i++)
+        process_csrng_cmd_fifo(i);
     join_none
   endtask
 
@@ -152,7 +154,8 @@
   endfunction
 
   // From NIST.SP.800-90Ar1
-  function bit [csrng_env_pkg::BLOCK_LEN-1:0] block_encrypt(bit [csrng_env_pkg::KEY_LEN-1:0] key,
+  function automatic bit [csrng_env_pkg::BLOCK_LEN-1:0] block_encrypt(
+      bit [csrng_env_pkg::KEY_LEN-1:0]   key,
       bit [csrng_env_pkg::BLOCK_LEN-1:0] input_block);
 
     bit [csrng_env_pkg::BLOCK_LEN-1:0]   output_block;
@@ -169,9 +172,8 @@
     return output_block;
   endfunction
 
-  function void ctr_drbg_update(bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0] provided_data,
-                                ref bit [csrng_env_pkg::KEY_LEN-1:0]       key,
-                                ref bit [csrng_env_pkg::BLOCK_LEN-1:0]     v);
+  function automatic void ctr_drbg_update(uint hwapp,
+                                bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0] provided_data);
 
     bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0]   temp;
     bit [csrng_env_pkg::CTR_LEN-1:0]             inc;
@@ -180,68 +182,71 @@
 
     for (int i = 0; i < (entropy_src_pkg::CSRNG_BUS_WIDTH/csrng_env_pkg::BLOCK_LEN); i++) begin
       if (csrng_env_pkg::CTR_LEN < csrng_env_pkg::BLOCK_LEN) begin
-        inc = (v[csrng_env_pkg::CTR_LEN-1:0] + 1);
+        inc = (cfg.v[hwapp][csrng_env_pkg::CTR_LEN-1:0] + 1);
         mod_val = 2**csrng_env_pkg::CTR_LEN;
         inc = inc % mod_val;
-        v = {v[csrng_env_pkg::BLOCK_LEN - 1:csrng_env_pkg::CTR_LEN], inc};
+        cfg.v[hwapp] = {cfg.v[hwapp][csrng_env_pkg::BLOCK_LEN - 1:csrng_env_pkg::CTR_LEN], inc};
       end
       else begin
-        v += 1;
+        cfg.v[hwapp] += 1;
         mod_val = 2**csrng_env_pkg::BLOCK_LEN;
-        v = v % mod_val;
+        cfg.v[hwapp] = cfg.v[hwapp] % mod_val;
       end
 
-      output_block = block_encrypt(key, v);
+      output_block = block_encrypt(cfg.key[hwapp], cfg.v[hwapp]);
       temp = {temp, output_block};
     end
 
     temp = temp ^ provided_data;
-    key  = temp[entropy_src_pkg::CSRNG_BUS_WIDTH-1:(entropy_src_pkg::CSRNG_BUS_WIDTH -
-           csrng_env_pkg::KEY_LEN)];
-    v    = temp[csrng_env_pkg::BLOCK_LEN-1:0];
+    cfg.key[hwapp] = temp[entropy_src_pkg::CSRNG_BUS_WIDTH-1:(entropy_src_pkg::CSRNG_BUS_WIDTH -
+        csrng_env_pkg::KEY_LEN)];
+    cfg.v[hwapp] = temp[csrng_env_pkg::BLOCK_LEN-1:0];
   endfunction
 
-  function void ctr_drbg_instantiate(bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0] entropy_input,
+  function automatic void ctr_drbg_instantiate(uint hwapp,
+                                     bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0] entropy_input,
                                      bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0]
                                          personalization_string = 'h0);
 
     bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0]   seed_material;
 
     seed_material = entropy_input ^ personalization_string;
-    cfg.key = 'h0;
-    cfg.v = 'h0;
-    ctr_drbg_update(seed_material, cfg.key, cfg.v);
-    cfg.reseed_counter = 1'b1;
-    cfg.status = 1'b1;
+    cfg.key[hwapp] = 'h0;
+    cfg.v[hwapp] = 'h0;
+    ctr_drbg_update(hwapp, seed_material);
+    cfg.reseed_counter[hwapp] = 1'b1;
+    cfg.status[hwapp] = 1'b1;
   endfunction
 
-  function void ctr_drbg_reseed(bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0] entropy_input,
+  function automatic void ctr_drbg_reseed(uint hwapp,
+                                bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0] entropy_input,
                                 bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0]
                                     additional_input = 'h0);
 
     bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0]   seed_material;
 
     seed_material = entropy_input ^ additional_input;
-    ctr_drbg_update(seed_material, cfg.key, cfg.v);
-    cfg.reseed_counter = 1'b1;
+    ctr_drbg_update(hwapp, seed_material);
+    cfg.reseed_counter[hwapp] = 1'b1;
   endfunction
 
-  virtual task process_csrng_cmd_fifo();
+  task automatic process_csrng_cmd_fifo(uint hwapp);
     bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0]   seed;
+    csrng_item                                   cs_item;
 
     forever begin
-      csrng_cmd_fifo.get(cs_item);
-      seed = '0;
-      for (int i = 0; i < cs_item.cmd_data_q.size(); i++) begin
-        seed = (cs_item.cmd_data_q[i] << i * csrng_pkg::CSRNG_CMD_WIDTH) + seed;
-      end
-
-      case (cs_item.acmd)
-        csrng_pkg::INS: begin
-          ctr_drbg_instantiate(seed);
+        csrng_cmd_fifo[hwapp].get(cs_item);
+        seed = '0;
+        for (int i = 0; i < cs_item.cmd_data_q.size(); i++) begin
+          seed = (cs_item.cmd_data_q[i] << i * csrng_pkg::CSRNG_CMD_WIDTH) + seed;
         end
-      endcase
-    end
+
+        case (cs_item.acmd)
+          csrng_pkg::INS: begin
+            ctr_drbg_instantiate(hwapp, seed);
+          end
+        endcase
+      end
   endtask
 
 endclass
diff --git a/hw/ip/csrng/dv/env/csrng_virtual_sequencer.sv b/hw/ip/csrng/dv/env/csrng_virtual_sequencer.sv
index 0af494c..e729d0d 100644
--- a/hw/ip/csrng/dv/env/csrng_virtual_sequencer.sv
+++ b/hw/ip/csrng/dv/env/csrng_virtual_sequencer.sv
@@ -11,7 +11,7 @@
   push_pull_sequencer#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH))
     entropy_src_sequencer_h;
 
-  csrng_sequencer   edn_sequencer_h;
+  csrng_sequencer   edn_sequencer_h[NUM_HW_APPS];
 
   `uvm_component_new
 
diff --git a/hw/ip/csrng/dv/env/seq_lib/csrng_base_vseq.sv b/hw/ip/csrng/dv/env/seq_lib/csrng_base_vseq.sv
index 57fa9fd..cedc4b0 100644
--- a/hw/ip/csrng/dv/env/seq_lib/csrng_base_vseq.sv
+++ b/hw/ip/csrng/dv/env/seq_lib/csrng_base_vseq.sv
@@ -41,20 +41,18 @@
     csr_wr(.ptr(ral.cmd_req), .value({1'b0, glen, flags, clen, acmd}));
   endtask
 
-  virtual task send_cmd_req(csrng_item cs_item);
+  task automatic send_cmd_req(uint hwapp, csrng_item cs_item);
     bit [csrng_pkg::CSRNG_CMD_WIDTH-1:0]   cmd;
     // Gen cmd_req
     cmd = {cs_item.glen, cs_item.flags, cs_item.clen, 1'b0, cs_item.acmd};
-    cfg.m_edn_agent_cfg.m_cmd_push_agent_cfg.add_h_user_data(cmd);
-      m_edn_push_seq.num_trans = cs_item.clen + 1;
-      for (int i = 0; i < cs_item.clen; i++)
-        cfg.m_edn_agent_cfg.m_cmd_push_agent_cfg.add_h_user_data(cs_item.cmd_data_q.pop_front());
+    cfg.m_edn_agent_cfg[hwapp].m_cmd_push_agent_cfg.add_h_user_data(cmd);
+    m_edn_push_seq.num_trans = cs_item.clen + 1;
+    for (int i = 0; i < cs_item.clen; i++)
+      cfg.m_edn_agent_cfg[hwapp].m_cmd_push_agent_cfg.add_h_user_data(cs_item.cmd_data_q.pop_front());
     // Drive cmd_req
-    m_edn_push_seq.start(p_sequencer.edn_sequencer_h.m_cmd_push_sequencer);
+    m_edn_push_seq.start(p_sequencer.edn_sequencer_h[hwapp].m_cmd_push_sequencer);
     // Wait for cmd_ack
-    cfg.m_edn_agent_cfg.vif.wait_cmd_ack();
-    if (cfg.chk_int_state)
-      cfg.check_int_state();
+    cfg.m_edn_agent_cfg[hwapp].vif.wait_cmd_ack();
   endtask
 
 endclass : csrng_base_vseq
diff --git a/hw/ip/csrng/dv/env/seq_lib/csrng_cmds_vseq.sv b/hw/ip/csrng/dv/env/seq_lib/csrng_cmds_vseq.sv
index 5b90fb3..b1177ab 100644
--- a/hw/ip/csrng/dv/env/seq_lib/csrng_cmds_vseq.sv
+++ b/hw/ip/csrng/dv/env/seq_lib/csrng_cmds_vseq.sv
@@ -9,7 +9,7 @@
   `uvm_object_new
 
   rand bit [entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH-1:0]   entropy_val;
-  rand csrng_item                                        cs_item;
+  rand csrng_item                                        cs_item[NUM_HW_APPS];
   bit [csrng_pkg::CSRNG_CMD_WIDTH-1:0]                   cmd_data, cmd_data_q[$];
   bit [csrng_pkg::GENBITS_BUS_WIDTH-1:0]                 genbits;
 
@@ -29,32 +29,30 @@
     // Create csrng_cmd host sequence
     m_edn_push_seq = push_pull_host_seq#(csrng_pkg::CSRNG_CMD_WIDTH)::type_id::create("m_edn_push_seq");
 
-    cs_item = csrng_item::type_id::create("cs_item");
+    for (int i = 0; i < NUM_HW_APPS; i++)
+      cs_item[i] = csrng_item::type_id::create($sformatf("cs_item[%0d]", i));
 
     fork
-      begin
-//      for (int i = 0; i < num_trans; i++) begin
-//        `DV_CHECK_STD_RANDOMIZE_FATAL(entropy_val);
-          // Set FIPS bit to 0
-          // TODO: Not always 0, maybe leave randomized
-//        entropy_val[entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH] = 1'b0;
-//          entropy_val = ;
-          // TODO: randomize entropy
+      fork
+        begin
+          // TODO: randomize entropy/fips
           cfg.m_entropy_src_agent_cfg.add_d_user_data(384'hdeadbeef);
           cfg.m_entropy_src_agent_cfg.add_d_user_data(384'hbeefdead);
-//      end
-        m_entropy_src_pull_seq.start(p_sequencer.entropy_src_sequencer_h);
-      end
+          m_entropy_src_pull_seq.start(p_sequencer.entropy_src_sequencer_h);
+        end
+      join_none
 
-      begin
-        //instantiate cmd
-        for (int i = 0; i < 10; i++) begin
-        `DV_CHECK_RANDOMIZE_WITH_FATAL(cs_item,
-                                       cs_item.acmd  == csrng_pkg::INS;
-                                       cs_item.flags == 4'h1;
-                                       cs_item.glen  == 'h0;)
-        send_cmd_req(cs_item);
-      end
+      // TODO: gen cmds for multiple hw_apps
+      for (int i = 0; i < 1; i++) begin
+        // instantiate cmd
+        // TODO: randomize num_cmds
+        for (int j = 0; j < 10; j++) begin
+          `DV_CHECK_RANDOMIZE_WITH_FATAL(cs_item[i],
+                                         cs_item[i].acmd  == csrng_pkg::INS;
+                                         cs_item[i].flags == 4'h1;
+                                         cs_item[i].glen  == 'h0;)
+          send_cmd_req(i, cs_item[i]);
+        end
 
         // TODO: add other commands
         // //generate cmd
@@ -72,7 +70,12 @@
 
         // send_cmd_req(.acmd(csrng_pkg::UNI), .clen(4'h0), .flags(4'h0), .glen(19'h0));
       end
-    join_none
+    join
+
+    if (cfg.chk_int_state) begin
+      for (int i = 0; i < NUM_HW_APPS; i++)
+        cfg.check_int_state(i);
+    end
 
   endtask : body
 endclass : csrng_cmds_vseq
diff --git a/hw/ip/csrng/dv/tb.sv b/hw/ip/csrng/dv/tb.sv
index a3dfe92..a9551ab 100644
--- a/hw/ip/csrng/dv/tb.sv
+++ b/hw/ip/csrng/dv/tb.sv
@@ -20,6 +20,8 @@
   wire intr_entropy_req;
   wire intr_hw_inst_exc;
   wire intr_cs_fatal_err;
+  csrng_pkg::csrng_req_t [NUM_HW_APPS-1:0] csrng_cmd_req;
+  csrng_pkg::csrng_rsp_t [NUM_HW_APPS-1:0] csrng_cmd_rsp;
 
   // interfaces
   clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n));
@@ -27,7 +29,7 @@
   pins_if#(1) devmode_if(devmode);
   pins_if#(1) efuse_sw_app_enable_if(efuse_sw_app_enable);
   tl_if tl_if(.clk(clk), .rst_n(rst_n));
-  csrng_if  csrng_if(.clk(clk), .rst_n(rst_n));
+  csrng_if  csrng_if[NUM_HW_APPS](.clk(clk), .rst_n(rst_n));
   push_pull_if#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH))
       entropy_src_if(.clk(clk), .rst_n(rst_n));
 
@@ -58,8 +60,8 @@
     .cs_aes_halt_i           (1'b0),
     .cs_aes_halt_o           (),
 
-    .csrng_cmd_i             (csrng_if.cmd_req),
-    .csrng_cmd_o             (csrng_if.cmd_rsp),
+    .csrng_cmd_i             (csrng_cmd_req),
+    .csrng_cmd_o             (csrng_cmd_rsp),
 
     .alert_rx_i              (alert_rx),
     .alert_tx_o              (alert_tx),
@@ -70,6 +72,15 @@
     .intr_cs_fatal_err_o     (intr_cs_fatal_err)
   );
 
+  for (genvar i = 0; i < NUM_HW_APPS; i++) begin : gen_csrng_if
+    assign csrng_cmd_req[i]    = csrng_if[i].cmd_req;
+    assign csrng_if[i].cmd_rsp = csrng_cmd_rsp[i];
+    initial begin
+      uvm_config_db#(virtual csrng_if)::set(null, $sformatf("*.env.m_edn_agent[%0d]*", i),
+          "vif", csrng_if[i]);
+    end
+  end
+
   assign interrupts[CmdReqDone] = intr_cmd_req_done;
   assign interrupts[EntropyReq] = intr_entropy_req;
   assign interrupts[HwInstExc]  = intr_hw_inst_exc;
@@ -86,7 +97,6 @@
     uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if);
     uvm_config_db#(virtual push_pull_if#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH)))::
       set(null, "*.env.m_entropy_src_agent*", "vif", entropy_src_if);
-    uvm_config_db#(virtual csrng_if)::set(null, "*.env.m_edn_agent*", "vif", csrng_if);
     $timeformat(-12, 0, " ps", 12);
     run_test();
   end