[entropy_src, top] Add option to stub out entropy_src

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/entropy_src/data/entropy_src.hjson b/hw/ip/entropy_src/data/entropy_src.hjson
index 839a2dc..00bbfd3 100644
--- a/hw/ip/entropy_src/data/entropy_src.hjson
+++ b/hw/ip/entropy_src/data/entropy_src.hjson
@@ -53,6 +53,15 @@
       package: ""
     }
   ],
+  param_list: [
+    { name:    "Stub",
+      type:    "bit",
+      default: "0",
+      desc:    "Stub out the core of entropy_src logic"
+      local:   "false",
+      expose:  "true"
+    },
+  ]
   alert_list: [
     { name: "recov_alert",
       desc: "This alert is triggered upon the alert health test threshold criteria not met."
diff --git a/hw/ip/entropy_src/rtl/entropy_src.sv b/hw/ip/entropy_src/rtl/entropy_src.sv
index 6e770a4..e563495 100644
--- a/hw/ip/entropy_src/rtl/entropy_src.sv
+++ b/hw/ip/entropy_src/rtl/entropy_src.sv
@@ -11,6 +11,7 @@
   import entropy_src_pkg::*;
   import entropy_src_reg_pkg::*;
 #(
+  parameter bit Stub = 1'b0,
   parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}},
   parameter int EsFifoDepth = 4
 ) (
@@ -55,19 +56,62 @@
 
   import entropy_src_reg_pkg::*;
 
-  entropy_src_reg2hw_t reg2hw;
+  // common signals
   entropy_src_hw2reg_t hw2reg;
-
+  entropy_src_reg2hw_t reg2hw;
   logic [NumAlerts-1:0] alert_test;
   logic [NumAlerts-1:0] alert;
 
+  // core signals
+  logic core_rst_n;
+  entropy_src_hw2reg_t core_hw2reg;
+  entropy_src_hw_if_rsp_t core_entropy_hw_if;
+  entropy_src_rng_req_t core_rng;
+  cs_aes_halt_req_t core_aes_halt;
+  entropy_src_xht_req_t core_xht;
+  logic core_intr_es_entropy_valid;
+  logic core_intr_es_health_test_failed;
+  logic core_intr_es_fatal_err;
+  logic [NumAlerts-1:0] core_alert_test;
+  logic [NumAlerts-1:0] core_alert;
+
+  //stub signals
+  localparam int StubLfsrWidth = 64;
+  localparam int Copies = CSRNG_BUS_WIDTH / StubLfsrWidth;
+  entropy_src_hw2reg_t stub_hw2reg;
+  entropy_src_hw_if_rsp_t stub_entropy_hw_if;
+  logic stub_es_valid;
+  logic [NumAlerts-1:0] stub_alert_test;
+  logic [NumAlerts-1:0] stub_alert;
+  logic [StubLfsrWidth-1:0] stub_lfsr_value;
+
+  ///////////////////////////
+  // Selecting between core and stub
+  ///////////////////////////
+
+  assign hw2reg                       = Stub ? stub_hw2reg        : core_hw2reg;
+  assign core_rst_n                   = Stub ? '0                 : rst_ni;
+  assign entropy_src_hw_if_o          = Stub ? stub_entropy_hw_if : core_entropy_hw_if;
+  assign entropy_src_rng_o            = Stub ? '1                 : core_rng;
+  assign cs_aes_halt_o                = Stub ? '0                 : core_aes_halt;
+  assign entropy_src_xht_o            = Stub ? '0                 : core_xht;
+  assign intr_es_entropy_valid_o      = Stub ? stub_es_valid      : core_intr_es_entropy_valid;
+  assign intr_es_health_test_failed_o = Stub ? '0                 : core_intr_es_health_test_failed;
+  assign intr_es_fatal_err_o          = Stub ? '0                 : core_intr_es_fatal_err;
+  assign alert_test                   = Stub ? stub_alert_test    : core_alert_test;
+  assign alert                        = Stub ? stub_alert         : core_alert;
+
+  ///////////////////////////
+  // core entropy operation
+  ///////////////////////////
+
   entropy_src_reg_top u_reg (
     .clk_i,
     .rst_ni,
     .tl_i,
     .tl_o,
     .reg2hw,
-    .hw2reg,
+    .hw2reg(hw2reg),
     .intg_err_o(),
     .devmode_i(1'b1)
   );
@@ -81,37 +125,100 @@
     .EsFifoDepth(EsFifoDepth)
   ) u_entropy_src_core (
     .clk_i,
-    .rst_ni,
+    .rst_ni(core_rst_n),
     .reg2hw,
-    .hw2reg,
+    .hw2reg(core_hw2reg),
 
     .efuse_es_sw_reg_en_i(efuse_es_sw_reg_en),
     .rng_fips_o,
 
-    .entropy_src_hw_if_o,
+    .entropy_src_hw_if_o(core_entropy_hw_if),
     .entropy_src_hw_if_i,
 
-    .entropy_src_xht_o,
+    .entropy_src_xht_o(core_xht),
     .entropy_src_xht_i,
 
-    .entropy_src_rng_o,
+    .entropy_src_rng_o(core_rng),
     .entropy_src_rng_i,
 
-    .cs_aes_halt_o,
+    .cs_aes_halt_o(core_aes_halt),
     .cs_aes_halt_i,
 
-    .recov_alert_o(alert[0]),
-    .fatal_alert_o(alert[1]),
+    .recov_alert_o(core_alert[0]),
+    .fatal_alert_o(core_alert[1]),
 
-    .recov_alert_test_o(alert_test[0]),
-    .fatal_alert_test_o(alert_test[1]),
+    .recov_alert_test_o(core_alert_test[0]),
+    .fatal_alert_test_o(core_alert_test[1]),
 
-    .intr_es_entropy_valid_o,
-    .intr_es_health_test_failed_o,
-    .intr_es_fatal_err_o
+    .intr_es_entropy_valid_o(core_intr_es_entropy_valid),
+    .intr_es_health_test_failed_o(core_intr_es_health_test_failed),
+    .intr_es_fatal_err_o(core_intr_es_fatal_err)
   );
 
+  ///////////////////////////
+  // stub entropy operation
+  ///////////////////////////
 
+  assign stub_alert = '0;
+  assign stub_alert_test = '0;
+  assign stub_entropy_hw_if = '{
+    es_ack:  '1,
+    es_bits:  {Copies{stub_lfsr_value}},
+    es_fips: '1
+  };
+  // once enabled, stub entropy is always available
+  assign stub_es_valid = |reg2hw.conf.enable.q;
+
+  if (Stub) begin : gen_stub_entropy_src
+
+    logic seed_ld, lfsr_en;
+    always_ff @(posedge clk_i or negedge rst_ni) begin
+      if (!rst_ni) begin
+        lfsr_en <= '0;
+      end else begin
+        lfsr_en <= |reg2hw.conf.enable.q;
+      end
+    end
+    assign seed_ld = |reg2hw.conf.enable.q & !lfsr_en;
+
+    prim_lfsr #(
+      .LfsrDw(StubLfsrWidth),
+      .StateOutDw(StubLfsrWidth)
+    ) u_prim_lfsr (
+      .clk_i          (clk_i),
+      .rst_ni         (rst_ni),
+      .seed_en_i      (seed_ld),
+      .seed_i         (StubLfsrWidth'(reg2hw.seed.q)),
+      .lfsr_en_i      (lfsr_en),
+      .entropy_i      ('0),
+      .state_o        (stub_lfsr_value)
+    );
+
+    // hardwire hw2reg inputs
+    always_comb begin
+      stub_hw2reg = '0;
+
+      // as long as enable is 1, do not allow registers to be written
+      stub_hw2reg.regwen.d = ~|reg2hw.conf.enable.q;
+      stub_hw2reg.fw_ov_rd_data.d = stub_lfsr_value[31:0];
+      stub_hw2reg.fw_ov_fifo_sts.d = '1;
+      stub_hw2reg.entropy_data.d = stub_lfsr_value[31:0];
+      stub_hw2reg.debug_status.main_sm_idle.d = 1'b1;
+      // need to move this to package so that it can be referenced
+      stub_hw2reg.debug_status.main_sm_state.d = 8'b01110110;
+
+      stub_hw2reg.intr_state.es_entropy_valid.de = |reg2hw.conf.enable.q;
+      stub_hw2reg.intr_state.es_entropy_valid.d = 1'b1;
+
+    end
+  end else begin : gen_stub_tieoff
+    assign stub_hw2reg = '0;
+    assign stub_lfsr_value = '0;
+  end
+
+  ///////////////////////////
+  // Alert generation
+  ///////////////////////////
   for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_tx
     prim_alert_sender #(
       .AsyncOn(AlertAsyncOn[i]),
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 8e186e9..dc0326d 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -4498,7 +4498,17 @@
         clk_i: clkmgr_aon_clocks.clk_main_secure
       }
       domain: "0"
-      param_list: []
+      param_list:
+      [
+        {
+          name: Stub
+          desc: Stub out the core of entropy_src logic
+          type: bit
+          default: "0"
+          expose: "true"
+          name_top: EntropySrcStub
+        }
+      ]
       inter_signal_list:
       [
         {
diff --git a/hw/top_earlgrey/rtl/autogen/chip_earlgrey_nexysvideo.sv b/hw/top_earlgrey/rtl/autogen/chip_earlgrey_nexysvideo.sv
index 251a96a..6142c6a 100644
--- a/hw/top_earlgrey/rtl/autogen/chip_earlgrey_nexysvideo.sv
+++ b/hw/top_earlgrey/rtl/autogen/chip_earlgrey_nexysvideo.sv
@@ -715,6 +715,7 @@
     .SecAesStartTriggerDelay(0),
     .SecAesAllowForcingMasks(1'b0),
     .SecAesSkipPRNGReseeding(1'b0),
+    .EntropySrcStub(1'b1),
     .CsrngSBoxImpl(aes_pkg::SBoxImplLut),
     .OtbnRegFile(otbn_pkg::RegFileFPGA),
     .OtbnStub(1'b1),
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index febfccc..8667265 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -22,6 +22,7 @@
   parameter bit KmacEnMasking = 0,
   parameter int KmacReuseShare = 0,
   parameter aes_pkg::sbox_impl_e CsrngSBoxImpl = aes_pkg::SBoxImplCanright,
+  parameter bit EntropySrcStub = 0,
   parameter bit SramCtrlMainInstrExec = 1,
   parameter bit OtbnStub = 0,
   parameter otbn_pkg::regfile_e OtbnRegFile = otbn_pkg::RegFileFF,
@@ -2140,7 +2141,8 @@
   );
 
   entropy_src #(
-    .AlertAsyncOn(alert_handler_reg_pkg::AsyncOn[23:22])
+    .AlertAsyncOn(alert_handler_reg_pkg::AsyncOn[23:22]),
+    .Stub(EntropySrcStub)
   ) u_entropy_src (
 
       // Interrupt
diff --git a/test/systemtest/config.py b/test/systemtest/config.py
index 33fcd85..c953640 100644
--- a/test/systemtest/config.py
+++ b/test/systemtest/config.py
@@ -72,6 +72,7 @@
     },
     {
         "name": "dif_entropy_smoketest",
+        "targets": ["sim_verilator"],
     },
     {
         "name": "flash_ctrl_test",
diff --git a/util/topgen/templates/chiplevel.sv.tpl b/util/topgen/templates/chiplevel.sv.tpl
index f647099..e327b05 100644
--- a/util/topgen/templates/chiplevel.sv.tpl
+++ b/util/topgen/templates/chiplevel.sv.tpl
@@ -1111,6 +1111,7 @@
     .SecAesStartTriggerDelay(0),
     .SecAesAllowForcingMasks(1'b0),
     .SecAesSkipPRNGReseeding(1'b0),
+    .EntropySrcStub(1'b1),
     .CsrngSBoxImpl(aes_pkg::SBoxImplLut),
     .OtbnRegFile(otbn_pkg::RegFileFPGA),
     .OtbnStub(1'b1),