[csrng/dv] Added generate command/prediction

Signed-off-by: Steve Nelson <steve.nelson@wdc.com>
diff --git a/hw/dv/sv/csrng_agent/csrng_monitor.sv b/hw/dv/sv/csrng_agent/csrng_monitor.sv
index d05f45e..94b9122 100644
--- a/hw/dv/sv/csrng_agent/csrng_monitor.sv
+++ b/hw/dv/sv/csrng_agent/csrng_monitor.sv
@@ -70,7 +70,6 @@
           cs_item.cmd_data_q.push_back(item.h_data);
         end
       end
-      @(posedge cfg.vif.mon_cb.cmd_rsp.csrng_rsp_ack);
       `uvm_info(`gfn, $sformatf("Captured item: %s", cs_item.convert2string()), UVM_HIGH)
       analysis_port.write(cs_item);
     end
diff --git a/hw/ip/csrng/dv/env/csrng_scoreboard.sv b/hw/ip/csrng/dv/env/csrng_scoreboard.sv
index 7cada3d..0b6cac7 100644
--- a/hw/ip/csrng/dv/env/csrng_scoreboard.sv
+++ b/hw/ip/csrng/dv/env/csrng_scoreboard.sv
@@ -23,6 +23,7 @@
   // local queues to hold incoming packets pending comparison
   push_pull_item#(.HostDataWidth(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH))
       entropy_src_q[$];
+  bit [csrng_pkg::GENBITS_BUS_WIDTH-1 : 0]    genbits_q[NUM_HW_APPS][$];
 
   `uvm_component_new
 
@@ -160,12 +161,17 @@
     // post test checks - ensure that all local fifos and queues are empty
   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,
-      bit [csrng_env_pkg::BLOCK_LEN-1:0] input_block);
+  function void capture_genbits(bit [NUM_HW_APPS-1:0] hwapp,
+                                bit [csrng_pkg::GENBITS_BUS_WIDTH-1:0] genbits);
+    genbits_q[hwapp].push_back(genbits);
+  endfunction
 
-    bit [csrng_env_pkg::BLOCK_LEN-1:0]   output_block;
+  // From NIST.SP.800-90Ar1
+  function bit [BLOCK_LEN-1:0] block_encrypt(
+      bit [KEY_LEN-1:0]   key,
+      bit [BLOCK_LEN-1:0] input_block);
+
+    bit [BLOCK_LEN-1:0]   output_block;
 
     sv_dpi_aes_crypt_block(.impl_i(1'b0), .op_i(1'b0), .mode_i(6'b00_0001), .key_len_i(3'b100),
                            .iv_i('h0),
@@ -179,20 +185,20 @@
                                 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;
-    bit [csrng_env_pkg::BLOCK_LEN-1:0]           output_block;
+    bit [CTR_LEN-1:0]                            inc;
+    bit [BLOCK_LEN-1:0]                          output_block;
     bit [63:0]                                   mod_val;
 
-    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 = (cfg.v[hwapp][csrng_env_pkg::CTR_LEN-1:0] + 1);
-        mod_val = 2**csrng_env_pkg::CTR_LEN;
+    for (int i = 0; i < (entropy_src_pkg::CSRNG_BUS_WIDTH/BLOCK_LEN); i++) begin
+      if (CTR_LEN < BLOCK_LEN) begin
+        inc = (cfg.v[hwapp][CTR_LEN-1:0] + 1);
+        mod_val = 2**CTR_LEN;
         inc = inc % mod_val;
-        cfg.v[hwapp] = {cfg.v[hwapp][csrng_env_pkg::BLOCK_LEN - 1:csrng_env_pkg::CTR_LEN], inc};
+        cfg.v[hwapp] = {cfg.v[hwapp][BLOCK_LEN - 1:CTR_LEN], inc};
       end
       else begin
         cfg.v[hwapp] += 1;
-        mod_val = 2**csrng_env_pkg::BLOCK_LEN;
+        mod_val = 2**BLOCK_LEN;
         cfg.v[hwapp] = cfg.v[hwapp] % mod_val;
       end
 
@@ -202,8 +208,8 @@
 
     temp = temp ^ provided_data;
     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];
+        KEY_LEN)];
+    cfg.v[hwapp] = temp[BLOCK_LEN-1:0];
   endfunction
 
   function void ctr_drbg_instantiate(uint hwapp,
@@ -240,12 +246,47 @@
     cfg.status[hwapp]         = 1'b0;
   endfunction
 
+  function void ctr_drbg_generate(uint hwapp,
+                                  bit [18:0] requested_genbits,
+                                  bit [entropy_src_pkg::CSRNG_BUS_WIDTH-1:0]
+                                      additional_input = 'h0);
+
+    uint                                     requested_bits;
+    bit [csrng_pkg::GENBITS_BUS_WIDTH-1:0]   genbits;
+    bit [CTR_LEN-1:0]                        inc;
+    bit [BLOCK_LEN-1:0]                      output_block;
+    bit [63:0]                               mod_val;
+
+    requested_bits = requested_genbits * csrng_pkg::GENBITS_BUS_WIDTH;
+    for (int i = 0; i < requested_genbits; i++) begin
+      if (CTR_LEN < BLOCK_LEN) begin
+        inc = (cfg.v[hwapp][CTR_LEN-1:0] + 1);
+        mod_val = 2**CTR_LEN;
+        inc = inc % mod_val;
+        cfg.v[hwapp] = {cfg.v[hwapp][BLOCK_LEN - 1:CTR_LEN], inc};
+      end
+      else begin
+        cfg.v[hwapp] += 1;
+        mod_val = 2**BLOCK_LEN;
+        cfg.v[hwapp] = cfg.v[hwapp] % mod_val;
+      end
+      output_block = block_encrypt(cfg.key[hwapp], cfg.v[hwapp]);
+      genbits      = output_block;
+      `uvm_info(`gfn, $sformatf("genbits[%0d]      = %h", hwapp, genbits), UVM_DEBUG)
+      `uvm_info(`gfn, $sformatf("genbits_q[%0d][0] = %h", hwapp, genbits_q[hwapp][0]), UVM_DEBUG)
+      `DV_CHECK_EQ_FATAL(genbits, genbits_q[hwapp].pop_front())
+    end
+    ctr_drbg_update(hwapp, additional_input);
+    cfg.reseed_counter[hwapp] += 1;
+  endfunction
+
   task 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[hwapp].get(cs_item);
+        `uvm_info(`gfn, $sformatf("received csrng_cmd:\n%0s", cs_item.convert2string()), UVM_HIGH)
         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;
@@ -253,9 +294,19 @@
 
         case (cs_item.acmd)
           csrng_pkg::INS: begin
+            @(posedge cfg.m_edn_agent_cfg[hwapp].vif.mon_cb.cmd_rsp.csrng_rsp_ack);
             ctr_drbg_instantiate(hwapp, seed);
           end
+          csrng_pkg::GEN: begin
+            for (int i = 0; i < cs_item.glen; i++) begin
+              @(posedge cfg.m_edn_agent_cfg[hwapp].vif.mon_cb.cmd_rsp.genbits_valid);
+              capture_genbits(hwapp, cfg.m_edn_agent_cfg[hwapp].vif.mon_cb.cmd_rsp.genbits_bus);
+            end
+            @(posedge cfg.m_edn_agent_cfg[hwapp].vif.mon_cb.cmd_rsp.csrng_rsp_ack);
+            ctr_drbg_generate(hwapp, cs_item.glen);
+          end
           csrng_pkg::UNI: begin
+            @(posedge cfg.m_edn_agent_cfg[hwapp].vif.mon_cb.cmd_rsp.csrng_rsp_ack);
             ctr_drbg_uninstantiate(hwapp);
           end
         endcase
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 e4f05ef..5fdcadd 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
@@ -14,9 +14,7 @@
   bit                                               uninstantiate;
 
   task body();
-    // TODO: Create/start entropy_src device sequence still under development. Will remove/modify
-    // as necessary. Also consider making task if it stays.
-    // TODO: Enhance to run all cmds in the queues
+    // TODO: Add/randomize other commands. Use/add prediction for entropy from entropy_src agent.
 
     // Create entropy_src sequence
     m_entropy_src_pull_seq = push_pull_device_seq#(entropy_src_pkg::FIPS_CSRNG_BUS_WIDTH)::type_id::
@@ -29,27 +27,34 @@
 
     // Generate queues of csrng commands
     for (int i = 0; i < NUM_HW_APPS; i++) begin
-      uint   num_cmds;
-      `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(num_cmds, num_cmds inside {[1:10]};)
-      for (int j = 0; j < num_cmds; j++) begin
-        `DV_CHECK_RANDOMIZE_WITH_FATAL(cs_item,
-                                       cs_item.acmd  == csrng_pkg::INS;
-                                       cs_item.flags == 4'h1;
-                                       cs_item.glen  == 'h0;)
-        `downcast(cs_item_clone, cs_item.clone());
-        cs_item_q[i].push_back(cs_item_clone);
-      end
+      `DV_CHECK_RANDOMIZE_WITH_FATAL(cs_item,
+                                     cs_item.acmd  == csrng_pkg::INS;
+                                     cs_item.flags == 4'h1;
+                                     cs_item.clen  inside {[0:12]};)
+      `downcast(cs_item_clone, cs_item.clone());
+      cs_item_q[i].push_back(cs_item_clone);
 
-      // Generate uninstantiate cmds
+      `DV_CHECK_RANDOMIZE_WITH_FATAL(cs_item,
+                                     cs_item.acmd  == csrng_pkg::GEN;
+                                     cs_item.flags == 4'h0;
+                                     cs_item.clen  == 4'h0;
+                                     cs_item.glen inside {[1:32]};)
+      `downcast(cs_item_clone, cs_item.clone());
+      cs_item_q[i].push_back(cs_item_clone);
+
+      // Randomize whether to add an uninstantiate command
+      // so it checks internal state without uninstantiate sometimes
       `DV_CHECK_STD_RANDOMIZE_FATAL(uninstantiate)
-      if (cs_item_q[i].size() && uninstantiate) begin
+      if (uninstantiate) begin
         `DV_CHECK_RANDOMIZE_WITH_FATAL(cs_item,
                                        cs_item.acmd  == csrng_pkg::UNI;)
         `downcast(cs_item_clone, cs_item.clone());
         cs_item_q[i].push_back(cs_item_clone);
       end
+    end
 
-      // Print cs_items
+    // Print cs_items
+    for (int i = 0; i < NUM_HW_APPS; i++) begin
       foreach (cs_item_q[i][j]) begin
         cmds_gen += 1;
         `uvm_info(`gfn, $sformatf("cs_item_q[%0d][%0d]: %s", i, j, cs_item_q[i][j].convert2string()), UVM_DEBUG)
@@ -83,22 +88,6 @@
       wait (cmds_sent == cmds_gen);
     join
 
-        // TODO: add other commands
-        // //generate cmd
-        // send_cmd_req(.acmd(csrng_pkg::GEN), .clen(4'h0), .flags(4'h0), .glen(19'h1));
-        // genbits = ctr_drbg_generate();
-
-        // //reseed cmd
-        // send_cmd_req(.acmd(csrng_pkg::RES), .clen(4'h0), .flags(4'h0), .glen(19'h0));
-        // ctr_drbg_reseed(384'hbeefdead);
-
-        // //update cmd
-        // cmd_data_q.push_back(32'hdeadbeef);
-        // send_cmd_req(.acmd(csrng_pkg::UPD), .clen(4'h1), .flags(4'h0), .glen(19'h0), .data_q(cmd_data_q));
-        // csrng_update(384'hdeadbeef);
-
-        // send_cmd_req(.acmd(csrng_pkg::UNI), .clen(4'h0), .flags(4'h0), .glen(19'h0));
-
     // Check internal state
     if (cfg.chk_int_state) begin
       for (int i = 0; i < NUM_HW_APPS; i++)