[otbn] Implement RND/URND CSR/WSR and RND_PREFETCH CSR

This adds logic to read RND values from the EDN, removing the test RND
dummy value. A small cache to hold a single 256-bit random number from
an EDN request is provided. A RND_PREFETCH CSR is introduced which
prefetches to the cache when any value is written to it. Any RND read
will take the value from the cache, emptying it. If a value isn't
available in the cache the RND read will stall until one is available,
starting a new EDN request to fetch one if required.

An LFSR is added to supply values to URND. This is seeded via a request
to the EDN that occurs when OTBN starts. Execution cannot proceed until
the LFSR has been seeded.

Two dummy EDNs are provided in `otbn_top_sim.sv`. These provides the
existing test RND dummy value on every request after a fixed delay.

The ISS has been altered to support the new stalling behaviour for RND
reads. In a testbench the EDN interface is monitored and the ISS is
provided with RND values as they appear on the interface.

ISS support for URND has not yet been implemented, though it does
implement the stall at the beginning of execution whilst OTBN awaits a
URND reseed.

Signed-off-by: Greg Chadwick <gac@lowrisc.org>
diff --git a/hw/ip/otbn/dv/uvm/otbn_sim.core b/hw/ip/otbn/dv/uvm/otbn_sim.core
index da09dec..5cd960e 100644
--- a/hw/ip/otbn/dv/uvm/otbn_sim.core
+++ b/hw/ip/otbn/dv/uvm/otbn_sim.core
@@ -14,6 +14,7 @@
     depend:
       - lowrisc:dv:otbn_test
       - lowrisc:dv:otbn_sva
+      - lowrisc:ip:edn_pkg
     files:
       - tb.sv
     file_type: systemVerilogSource
diff --git a/hw/ip/otbn/dv/uvm/tb.sv b/hw/ip/otbn/dv/uvm/tb.sv
index 46af9f3..db72f9d 100644
--- a/hw/ip/otbn/dv/uvm/tb.sv
+++ b/hw/ip/otbn/dv/uvm/tb.sv
@@ -11,6 +11,7 @@
 
   // dep packages (rtl)
   import otbn_reg_pkg::*;
+  import edn_pkg::*;
 
   // macro includes
   `include "uvm_macros.svh"
@@ -36,6 +37,22 @@
 
   `DV_ALERT_IF_CONNECT
 
+  // Mock up EDN that just instantly returns fixed data when requested
+  // TODO: Provide a proper EDN agent
+  edn_req_t edn_rnd_req;
+  edn_rsp_t edn_rnd_rsp;
+
+  edn_req_t edn_urnd_req;
+  edn_rsp_t edn_urnd_rsp;
+
+  assign edn_rnd_rsp.edn_ack  = edn_rnd_req.edn_req;
+  assign edn_rnd_rsp.edn_fips = 1'b0;
+  assign edn_rnd_rsp.edn_bus  = 32'h99999999;
+
+  assign edn_urnd_rsp.edn_ack  = edn_urnd_req.edn_req;
+  assign edn_urnd_rsp.edn_fips = 1'b0;
+  assign edn_urnd_rsp.edn_bus  = 32'h99999999;
+
   // dut
   otbn dut (
     .clk_i       (clk),
@@ -49,8 +66,15 @@
     .intr_done_o (intr_done),
 
     .alert_rx_i  (alert_rx),
-    .alert_tx_o  (alert_tx)
+    .alert_tx_o  (alert_tx),
 
+    .clk_edn_i  (clk),
+    .rst_edn_ni (rst_n),
+    .edn_rnd_o ( edn_rnd_req ),
+    .edn_rnd_i ( edn_rnd_rsp ),
+
+    .edn_urnd_o ( edn_urnd_req ),
+    .edn_urnd_i ( edn_urnd_rsp )
   );
 
   bind otbn_core otbn_trace_if #(
@@ -60,6 +84,7 @@
 
   bind otbn_core otbn_tracer u_otbn_tracer(.*, .otbn_trace(i_otbn_trace_if));
 
+
   // OTBN model, wrapping an ISS.
   //
   // Note that we pull the "start" signal out of the DUT. This is because it's much more difficult
@@ -68,6 +93,15 @@
   // decoding errors).
   assign model_if.start = dut.start;
 
+  // Internally otbn_core uses a 256-bit width interface for EDN data. This maps to muliple EDN
+  // requests at this level (via a packing FIFO internal to otbn). The model works with the internal
+  // otbn_core interface so probe into it here to provide the relevant signals to the model.
+  logic edn_rnd_data_valid;
+  logic edn_urnd_data_valid;
+
+  assign edn_rnd_data_valid = dut.edn_rnd_req & dut.edn_rnd_ack;
+  assign edn_urnd_data_valid = dut.edn_urnd_req & dut.edn_urnd_ack;
+
   otbn_core_model #(
     .DmemSizeByte (otbn_reg_pkg::OTBN_DMEM_SIZE),
     .ImemSizeByte (otbn_reg_pkg::OTBN_IMEM_SIZE),
@@ -80,7 +114,11 @@
     .start_i      (model_if.start),
     .done_o       (model_if.done),
     .start_addr_i (model_if.start_addr),
-    .err_o        (model_if.err)
+    .err_o        (model_if.err),
+
+    .edn_rnd_data_valid_i  (edn_rnd_data_valid),
+    .edn_rnd_data_i        (dut.edn_rnd_data),
+    .edn_urnd_data_valid_i (edn_urnd_data_valid)
   );
 
   initial begin