[edn/dv] multiple endpoints

Signed-off-by: Steve Nelson <steve.nelson@wdc.com>
diff --git a/hw/ip/csrng/rtl/csrng_pkg.sv b/hw/ip/csrng/rtl/csrng_pkg.sv
index 24f0894..9c29ee9 100755
--- a/hw/ip/csrng/rtl/csrng_pkg.sv
+++ b/hw/ip/csrng/rtl/csrng_pkg.sv
@@ -10,6 +10,8 @@
   // Application Interfaces
   //-------------------------
 
+  parameter int unsigned   GENBITS_BUS_WIDTH = 128;
+
   // instantiation interface
   typedef struct packed {
     logic         csrng_req_valid;
@@ -31,7 +33,7 @@
     logic         csrng_rsp_sts;
     logic         genbits_valid;
     logic         genbits_fips;
-    logic [127:0] genbits_bus;
+    logic [GENBITS_BUS_WIDTH-1:0] genbits_bus;
   } csrng_rsp_t;
 
   // default value of csrng_rsp_t (for dangling ports)
diff --git a/hw/ip/edn/dv/env/edn_env.sv b/hw/ip/edn/dv/env/edn_env.sv
index 7d1d339..b4d2231 100644
--- a/hw/ip/edn/dv/env/edn_env.sv
+++ b/hw/ip/edn/dv/env/edn_env.sv
@@ -10,44 +10,43 @@
   );
   `uvm_component_utils(edn_env)
 
-  push_pull_agent#(.DataWidth(GENBITS_BUS_WIDTH)) m_csrng_agent;
-  push_pull_agent#(.DataWidth(ENDPOINT_BUS_WIDTH)) m_endpoint_agent [NUM_ENDPOINTS-1:0];
+  push_pull_agent#(.DataWidth(csrng_pkg::GENBITS_BUS_WIDTH)) m_csrng_agent;
+  push_pull_agent#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH))  m_endpoint_agent [NUM_ENDPOINTS-1:0];
 
   `uvm_component_new
 
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
     // create components
-    m_csrng_agent = push_pull_agent#(.DataWidth(GENBITS_BUS_WIDTH))::type_id::create("m_csrng_agent", this);
-    uvm_config_db#(push_pull_agent_cfg#(.DataWidth(GENBITS_BUS_WIDTH)))::set(this, "m_csrng_agent*", "cfg", cfg.m_csrng_agent_cfg);
+    m_csrng_agent = push_pull_agent#(.DataWidth(csrng_pkg::GENBITS_BUS_WIDTH))::type_id::create
+                    ("m_csrng_agent", this);
+    uvm_config_db#(push_pull_agent_cfg#(.DataWidth(csrng_pkg::GENBITS_BUS_WIDTH)))::set
+                  (this, "m_csrng_agent*", "cfg", cfg.m_csrng_agent_cfg);
     cfg.m_csrng_agent_cfg.agent_type = push_pull_agent_pkg::PushAgent;
     cfg.m_csrng_agent_cfg.if_mode    = dv_utils_pkg::Host;
 
-    //TODO: For Loop?
-    m_endpoint_agent[NUM_ENDPOINTS-1] = push_pull_agent#(.DataWidth(ENDPOINT_BUS_WIDTH))::type_id::create("m_endpoint_agent[NUM_ENDPOINTS-1]", this);
-    uvm_config_db#(push_pull_agent_cfg#(.DataWidth(ENDPOINT_BUS_WIDTH)))::set(this, "m_endpoint_agent*", "cfg", cfg.m_endpoint_agent_cfg[NUM_ENDPOINTS-1]);
-    cfg.m_endpoint_agent_cfg[NUM_ENDPOINTS-1].agent_type = push_pull_agent_pkg::PullAgent;
-    cfg.m_endpoint_agent_cfg[NUM_ENDPOINTS-1].if_mode    = dv_utils_pkg::Host;
-
-    m_endpoint_agent[0] = push_pull_agent#(.DataWidth(ENDPOINT_BUS_WIDTH))::type_id::create("m_endpoint_agent[0]", this);
-    uvm_config_db#(push_pull_agent_cfg#(.DataWidth(ENDPOINT_BUS_WIDTH)))::set(this, "m_endpoint_agent*", "cfg", cfg.m_endpoint_agent_cfg[0]);
-    cfg.m_endpoint_agent_cfg[0].agent_type = push_pull_agent_pkg::PullAgent;
-    cfg.m_endpoint_agent_cfg[0].if_mode    = dv_utils_pkg::Host;
+    for (int i = 0; i < NUM_ENDPOINTS; i++) begin
+      string endpoint_agent_name = $sformatf("m_endpoint_agent[%0d]", i);
+      m_endpoint_agent[i] = push_pull_agent#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH))::type_id::
+                            create(endpoint_agent_name, this);
+      uvm_config_db#(push_pull_agent_cfg#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH)))::set
+                    (this, $sformatf("%0s*", endpoint_agent_name), "cfg", cfg.m_endpoint_agent_cfg[i]);
+      cfg.m_endpoint_agent_cfg[NUM_ENDPOINTS-1].agent_type = push_pull_agent_pkg::PullAgent;
+      cfg.m_endpoint_agent_cfg[NUM_ENDPOINTS-1].if_mode    = dv_utils_pkg::Host;
+    end
   endfunction
 
   function void connect_phase(uvm_phase phase);
     super.connect_phase(phase);
-    //TODO: For Loop?
     if (cfg.en_scb) begin
-      m_endpoint_agent[NUM_ENDPOINTS-1].monitor.analysis_port.connect(scoreboard.endpoint_fifo[NUM_ENDPOINTS-1].analysis_export);
-      m_endpoint_agent[0].monitor.analysis_port.connect(scoreboard.endpoint_fifo[0].analysis_export);
-    end
-    if (cfg.is_active) begin
-      if (cfg.m_endpoint_agent_cfg[NUM_ENDPOINTS-1].is_active) begin
-        virtual_sequencer.endpoint_sequencer_h[NUM_ENDPOINTS-1] = m_endpoint_agent[NUM_ENDPOINTS-1].sequencer;
+      for (int i = 0; i < NUM_ENDPOINTS; i++) begin
+        m_endpoint_agent[i].monitor.analysis_port.connect
+        (scoreboard.endpoint_fifo[i].analysis_export);
       end
-      if (cfg.m_endpoint_agent_cfg[0].is_active) begin
-        virtual_sequencer.endpoint_sequencer_h[0] = m_endpoint_agent[0].sequencer;
+    end
+    for (int i = 0; i < NUM_ENDPOINTS; i++) begin
+      if (cfg.m_endpoint_agent_cfg[i].is_active) begin
+        virtual_sequencer.endpoint_sequencer_h[i] = m_endpoint_agent[i].sequencer;
       end
     end
   endfunction
diff --git a/hw/ip/edn/dv/env/edn_env_cfg.sv b/hw/ip/edn/dv/env/edn_env_cfg.sv
index 9bef21c..1ff714f 100644
--- a/hw/ip/edn/dv/env/edn_env_cfg.sv
+++ b/hw/ip/edn/dv/env/edn_env_cfg.sv
@@ -5,13 +5,15 @@
 class edn_env_cfg extends cip_base_env_cfg #(.RAL_T(edn_reg_block));
 
   // ext component cfgs
-  rand push_pull_agent_cfg#(.DataWidth(GENBITS_BUS_WIDTH))     m_csrng_agent_cfg;
-  rand push_pull_agent_cfg#(.DataWidth(ENDPOINT_BUS_WIDTH))    m_endpoint_agent_cfg [NUM_ENDPOINTS:0];
+  rand push_pull_agent_cfg#(.DataWidth(csrng_pkg::GENBITS_BUS_WIDTH))   m_csrng_agent_cfg;
+  rand push_pull_agent_cfg#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH))
+         m_endpoint_agent_cfg [NUM_ENDPOINTS:0];
 
   `uvm_object_utils_begin(edn_env_cfg)
     `uvm_field_object(m_csrng_agent_cfg, UVM_DEFAULT)
-    // TODO: multiple endpoints, for loop?
-    `uvm_field_object(m_endpoint_agent_cfg[NUM_ENDPOINTS-1], UVM_DEFAULT)
+    for (int i = 0; i < NUM_ENDPOINTS; i++) begin
+      `uvm_field_object(m_endpoint_agent_cfg[i], UVM_DEFAULT)
+    end
   `uvm_object_utils_end
 
   `uvm_object_new
@@ -19,9 +21,13 @@
   virtual function void initialize(bit [31:0] csr_base_addr = '1);
     super.initialize(csr_base_addr);
     // create config objects
-    m_csrng_agent_cfg = push_pull_agent_cfg#(.DataWidth(GENBITS_BUS_WIDTH))::type_id::create("m_csrng_agent_cfg");
-    // TODO: multiple endpoints, for loop?
-    m_endpoint_agent_cfg[NUM_ENDPOINTS-1] = push_pull_agent_cfg#(.DataWidth(ENDPOINT_BUS_WIDTH))::type_id::create($sformatf("m_endpoint_agent_cfg[$0d]", NUM_ENDPOINTS-1));
+    m_csrng_agent_cfg = push_pull_agent_cfg#(.DataWidth(csrng_pkg::GENBITS_BUS_WIDTH))::type_id::
+                        create("m_csrng_agent_cfg");
+
+    for (int i = 0; i < NUM_ENDPOINTS; i++) begin
+      m_endpoint_agent_cfg[i] = push_pull_agent_cfg#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH))::
+                                type_id::create($sformatf("m_endpoint_agent_cfg[$0d]", i));
+    end
 
     // set num_interrupts & num_alerts
     begin
diff --git a/hw/ip/edn/dv/env/edn_env_pkg.sv b/hw/ip/edn/dv/env/edn_env_pkg.sv
index cc9fd73..1871331 100644
--- a/hw/ip/edn/dv/env/edn_env_pkg.sv
+++ b/hw/ip/edn/dv/env/edn_env_pkg.sv
@@ -19,10 +19,7 @@
   `include "dv_macros.svh"
 
   // parameters
-  // TODO: add multiple endpoints
-  parameter uint   NUM_ENDPOINTS      = 1;
-  parameter uint   ENDPOINT_BUS_WIDTH = 32;
-  parameter uint   GENBITS_BUS_WIDTH  = 128;
+  parameter uint   NUM_ENDPOINTS = 1;
 
   // types
   typedef enum int {
diff --git a/hw/ip/edn/dv/env/edn_scoreboard.sv b/hw/ip/edn/dv/env/edn_scoreboard.sv
index 512cadc..8787756 100644
--- a/hw/ip/edn/dv/env/edn_scoreboard.sv
+++ b/hw/ip/edn/dv/env/edn_scoreboard.sv
@@ -12,18 +12,18 @@
   // local variables
 
   // TLM agent fifos
-  uvm_tlm_analysis_fifo #(push_pull_item#(.DataWidth(ENDPOINT_BUS_WIDTH))) endpoint_fifo[NUM_ENDPOINTS-1:0];
+  uvm_tlm_analysis_fifo #(push_pull_item#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH))) endpoint_fifo[NUM_ENDPOINTS-1:0];
 
   // local queues to hold incoming packets pending comparison
-  push_pull_item#(.DataWidth(ENDPOINT_BUS_WIDTH)) endpoint_q[$][NUM_ENDPOINTS-1:0];
+  push_pull_item#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH)) endpoint_q[$][NUM_ENDPOINTS-1:0];
 
   `uvm_component_new
 
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
-  // TODO: for loop
-    endpoint_fifo[NUM_ENDPOINTS-1] = new("endpoint_fifo[NUM_ENDPOINTS-1]", this);
-    endpoint_fifo[0] = new("endpoint_fifo[0]", this);
+    for (int i = 0; i < NUM_ENDPOINTS; i++) begin
+      endpoint_fifo[i] = new($sformatf("endpoint_fifo[%0d]", i), this);
+    end
   endfunction
 
   function void connect_phase(uvm_phase phase);
@@ -33,21 +33,9 @@
   task run_phase(uvm_phase phase);
     super.run_phase(phase);
     fork
-      process_push_pull_fifo();
     join_none
   endtask
 
-  virtual task process_push_pull_fifo();
-    // TODO: for loop
-    push_pull_item#(.DataWidth(ENDPOINT_BUS_WIDTH)) item[NUM_ENDPOINTS-1:0];
-        endpoint_fifo[NUM_ENDPOINTS-1].get(item[NUM_ENDPOINTS-1]);
-        `uvm_info(`gfn, $sformatf("received endpoint[%0d-1] item:\n%0s", NUM_ENDPOINTS, item[NUM_ENDPOINTS-1].sprint()), UVM_HIGH)
-    forever begin
-        endpoint_fifo[0].get(item[0]);
-        `uvm_info(`gfn, $sformatf("received endpoint[0] item:\n%0s", item[0].sprint()), UVM_HIGH)
-    end
-  endtask
-
   virtual task process_tl_access(tl_seq_item item, tl_channels_e channel = DataChannel);
     uvm_reg csr;
     bit     do_read_check   = 1'b1;
diff --git a/hw/ip/edn/dv/env/edn_virtual_sequencer.sv b/hw/ip/edn/dv/env/edn_virtual_sequencer.sv
index bcc718a..98d9b5c 100644
--- a/hw/ip/edn/dv/env/edn_virtual_sequencer.sv
+++ b/hw/ip/edn/dv/env/edn_virtual_sequencer.sv
@@ -8,7 +8,7 @@
   );
   `uvm_component_utils(edn_virtual_sequencer)
 
-  push_pull_sequencer#(.DataWidth(ENDPOINT_BUS_WIDTH)) endpoint_sequencer_h[NUM_ENDPOINTS-1:0];
+  push_pull_sequencer#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH)) endpoint_sequencer_h[NUM_ENDPOINTS-1:0];
 
   `uvm_component_new
 
diff --git a/hw/ip/edn/dv/tb.sv b/hw/ip/edn/dv/tb.sv
index 6f03577..e36517e 100644
--- a/hw/ip/edn/dv/tb.sv
+++ b/hw/ip/edn/dv/tb.sv
@@ -17,15 +17,16 @@
   wire devmode;
   wire intr_edn_cmd_req_done, intr_edn_fifo_err;
   wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
+  edn_pkg::edn_req_t [NUM_ENDPOINTS-1:0] endpoint_req;
+  edn_pkg::edn_rsp_t [NUM_ENDPOINTS-1:0] endpoint_rsp;
 
   // interfaces
   clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n));
   pins_if #(NUM_MAX_INTERRUPTS) intr_if(interrupts);
   pins_if #(1) devmode_if(devmode);
   tl_if tl_if(.clk(clk), .rst_n(rst_n));
-  push_pull_if#(.DataWidth(GENBITS_BUS_WIDTH))  csrng_if();
-  // TODO: add multiple endpoints, generate?
-  push_pull_if#(.DataWidth(ENDPOINT_BUS_WIDTH)) endpoint_if[NUM_ENDPOINTS-1:0]();
+  push_pull_if#(.DataWidth(csrng_pkg::GENBITS_BUS_WIDTH))   csrng_if();
+  push_pull_if#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH))    endpoint_if[NUM_ENDPOINTS-1:0]();
 
   // dut
   edn#(.NumEndPoints(NUM_ENDPOINTS)) dut (
@@ -35,10 +36,8 @@
     .tl_i                      (tl_if.h2d),
     .tl_o                      (tl_if.d2h),
 
-    // TODO: add multiple endpoints, generate?
-    // .edn_i                     ({endpoint_if[NUM_ENDPOINTS-1].req, endpoint_if[0].req}),
-    .edn_i                     (endpoint_if[0].req),
-    .edn_o                     (),
+    .edn_i                     (endpoint_req),
+    .edn_o                     (endpoint_rsp),
 
     .csrng_cmd_i               ('h0),
     .csrng_cmd_o               (),
@@ -47,6 +46,16 @@
     .intr_edn_fifo_err_o       (intr_edn_fifo_err)
   );
 
+  for (genvar i = 0; i < NUM_ENDPOINTS; i++) begin : gen_endpoint_if
+    assign endpoint_req[i].edn_req = endpoint_if[i].req;
+    assign endpoint_if[i].ack      = endpoint_rsp[i].edn_ack;
+    assign endpoint_if[i].data     = endpoint_rsp[i].edn_bus;
+    initial begin
+      uvm_config_db#(virtual push_pull_if#(.DataWidth(edn_pkg::ENDPOINT_BUS_WIDTH)))::set(null,
+                     $sformatf("*.env.m_endpoint_agent[%0d]*", i), "vif", endpoint_if[i]);
+    end
+  end
+
   assign interrupts[CmdReqDone] = intr_edn_cmd_req_done;
   assign interrupts[FifoErr]    = intr_edn_fifo_err;
 
@@ -57,9 +66,7 @@
     uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if);
     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 push_pull_if#(.DataWidth(GENBITS_BUS_WIDTH)))::set(null, "*.env.m_csrng_agent*", "vif", csrng_if);
-    // TODO: add multiple endpoints, generate?
-    uvm_config_db#(virtual push_pull_if#(.DataWidth(ENDPOINT_BUS_WIDTH)))::set(null, "*.env.m_endpoint_agent*", "vif", endpoint_if[NUM_ENDPOINTS-1]);
+    uvm_config_db#(virtual push_pull_if#(.DataWidth(csrng_pkg::GENBITS_BUS_WIDTH)))::set(null, "*.env.m_csrng_agent*", "vif", csrng_if);
     $timeformat(-12, 0, " ps", 12);
     run_test();
   end
diff --git a/hw/ip/edn/rtl/edn_pkg.sv b/hw/ip/edn/rtl/edn_pkg.sv
index 5efbeed..14e600b 100755
--- a/hw/ip/edn/rtl/edn_pkg.sv
+++ b/hw/ip/edn/rtl/edn_pkg.sv
@@ -9,6 +9,8 @@
   // Peripheral Interfaces //
   ///////////////////////////
 
+  parameter int unsigned   ENDPOINT_BUS_WIDTH = 32;
+
   // EDN request interface
   typedef struct packed {
     logic                                 edn_req;
@@ -16,7 +18,7 @@
   typedef struct packed {
     logic                                 edn_ack;
     logic                                 edn_fips;
-    logic [31:0]                          edn_bus;
+    logic [ENDPOINT_BUS_WIDTH-1:0]        edn_bus;
   } edn_rsp_t;
 
   parameter edn_req_t EDN_REQ_DEFAULT = '{default: '0};
diff --git a/hw/ip/entropy_src/rtl/entropy_src_pkg.sv b/hw/ip/entropy_src/rtl/entropy_src_pkg.sv
index 3155ec3..06de2ac 100755
--- a/hw/ip/entropy_src/rtl/entropy_src_pkg.sv
+++ b/hw/ip/entropy_src/rtl/entropy_src_pkg.sv
@@ -10,7 +10,9 @@
   // Entropy Interface
   //-------------------------
 
-  parameter int  RNG_DATA_WIDTH = 4, CSRNG_DATA_WIDTH = 384;
+  parameter int  RNG_DATA_WIDTH   = 4;
+  parameter int  CSRNG_DATA_WIDTH = 384;
+  parameter int  FIPS_WIDTH       = 1;
 
   // es entropy i/f
   typedef struct packed {