[sw] Minor software updates for dif_entropy_src and test

- This change should now ensure the new seed is used and
  the entropy reads should be different between reads.
- Lastly, a few auxillary functions are added to poll for specific
  status.  These likely should be replaced long term by something
  more robust
- unittests are also udpated for the slightly tweaked sequence
- At the moment, since we disable / re-enable entropy_src, the
  timing differences between platforms (dv vs verilator) causes
  the test to spit out different results.  For the time being,
  favor verilator until #5941 is in.

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/sw/device/lib/dif/dif_entropy.c b/sw/device/lib/dif/dif_entropy.c
index ddbd77f..22a2621 100644
--- a/sw/device/lib/dif/dif_entropy.c
+++ b/sw/device/lib/dif/dif_entropy.c
@@ -93,12 +93,48 @@
   return kDifEntropyOk;
 }
 
+static bool get_entropy_avail(const dif_entropy_t *entropy) {
+  return mmio_region_get_bit32(entropy->params.base_addr,
+                               ENTROPY_SRC_INTR_STATE_REG_OFFSET,
+                               ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
+}
+
+dif_entropy_result_t dif_entropy_avail(const dif_entropy_t *entropy) {
+  if (entropy == NULL) {
+    return kDifEntropyBadArg;
+  }
+
+  return get_entropy_avail(entropy) ? kDifEntropyOk
+                                    : kDifEntropyDataUnAvailable;
+}
+
 dif_entropy_result_t dif_entropy_read(const dif_entropy_t *entropy,
                                       uint32_t *word) {
   if (entropy == NULL || word == NULL) {
     return kDifEntropyBadArg;
   }
+
+  // Check if entropy is available
+  if (!get_entropy_avail(entropy)) {
+    return kDifEntropyDataUnAvailable;
+  }
+
   *word = mmio_region_read32(entropy->params.base_addr,
                              ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET);
+
+  // clear interrupt state after fetching read
+  // if there is still entropy available, the interrupt state will set again
+  mmio_region_nonatomic_set_bit32(entropy->params.base_addr,
+                                  ENTROPY_SRC_INTR_STATE_REG_OFFSET,
+                                  ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
+
+  return kDifEntropyOk;
+}
+
+dif_entropy_result_t dif_entropy_disable(const dif_entropy_t *entropy) {
+  // TODO: should first check if entropy is locked and return error if it is.
+  mmio_region_write32(entropy->params.base_addr, ENTROPY_SRC_CONF_REG_OFFSET,
+                      0);
+
   return kDifEntropyOk;
 }
diff --git a/sw/device/lib/dif/dif_entropy.h b/sw/device/lib/dif/dif_entropy.h
index ff034a4..44fc894 100644
--- a/sw/device/lib/dif/dif_entropy.h
+++ b/sw/device/lib/dif/dif_entropy.h
@@ -363,6 +363,14 @@
    * succeed until hardware reset.
    */
   kDifEntropyLocked = 3,
+  /**
+   * Indicates that entropy is not yet available for software consumption
+   */
+  kDifEntropyDataUnAvailable = 4,
+  /**
+   * Indicates that entropy is not idle
+   */
+  kDifEntropyNotIdle = 5,
 } dif_entropy_result_t;
 
 /**
@@ -486,6 +494,15 @@
                                            bool *is_locked);
 
 /**
+ * Checks to see if entropy is available for software consumption
+ *
+ * @param entropy An entropy source handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_entropy_result_t dif_entropy_avail(const dif_entropy_t *entropy);
+
+/**
  * Reads off a word of entropy from the entropy source.
  *
  * @param entropy An entropy source handle.
@@ -682,6 +699,24 @@
 DIF_WARN_UNUSED_RESULT
 dif_entropy_result_t dif_entropy_fifo_reconnect(const dif_entropy_t *entropy);
 
+/**
+ * Disables the entropy module
+ *
+ * @param entropy An entropy source handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_entropy_result_t dif_entropy_disable(const dif_entropy_t *entropy);
+
+/**
+ * Get main entropy fsm idle status
+ *
+ * @param entropy An entropy source handle.
+ * @return The result of the operation.
+ */
+DIF_WARN_UNUSED_RESULT
+dif_entropy_result_t dif_entropy_get_idle(const dif_entropy_t *entropy);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif  // __cplusplus
diff --git a/sw/device/tests/dif/dif_entropy_smoketest.c b/sw/device/tests/dif/dif_entropy_smoketest.c
index e8d9b75..e78d18b 100644
--- a/sw/device/tests/dif/dif_entropy_smoketest.c
+++ b/sw/device/tests/dif/dif_entropy_smoketest.c
@@ -14,9 +14,13 @@
 const test_config_t kTestConfig;
 
 const size_t kEntropyDataNumWords = 12;
+
+// TODO: These values are specific to verilator right now and will not work
+// for DV or FPGA, see #5941
 const uint32_t kExpectedEntropyData[] = {
-    0x65585497, 0x65585497, 0x65585497, 0x65585497, 0x65585497, 0x65585497,
-    0x65585497, 0x65585497, 0x65585497, 0x65585497, 0x65585497, 0x65585497,
+    0x0a3f4df0, 0x4e36fad2, 0xb5f3e0b9, 0x918f5ec0, 0x54ddd680, 0x62f04975,
+    0x700cf2f2, 0x61044bfe, 0x723d6c89, 0xe2d70e19, 0x5f02a234, 0xbf586fcc,
+
 };
 
 bool test_main() {
@@ -26,6 +30,9 @@
   dif_entropy_t entropy;
   CHECK(dif_entropy_init(params, &entropy) == kDifEntropyOk);
 
+  // Disable entropy for test purpose, as it has been turned on by ROM
+  CHECK(dif_entropy_disable(&entropy) == kDifEntropyOk);
+
   const dif_entropy_config_t config = {
       .mode = kDifEntropyModeLfsr,
       .tests =
@@ -37,7 +44,8 @@
               [kDifEntropyTestMailbox] = false,
               [kDifEntropyTestVendorSpecific] = false,
           },
-      .reset_health_test_registers = true,
+      // this field needs to manually toggled by software.  Disable for now
+      .reset_health_test_registers = false,
       .single_bit_mode = kDifEntropySingleBitModeDisabled,
       .route_to_firmware = true,
       .sample_rate = 2,
@@ -47,7 +55,11 @@
 
   uint32_t entropy_data[kEntropyDataNumWords];
   for (uint32_t i = 0; i < kEntropyDataNumWords; ++i) {
-    CHECK(dif_entropy_read(&entropy, &entropy_data[i]) == kDifEntropyOk);
+    // wait for entropy to become available
+    while (dif_entropy_read(&entropy, &entropy_data[i]) != kDifEntropyOk)
+      ;
+    // LOG_INFO("received %x, expectecd %x", entropy_data[i],
+    // kExpectedEntropyData[i]);
     CHECK(entropy_data[i] == kExpectedEntropyData[i]);
   }
 
diff --git a/sw/device/tests/dif/dif_entropy_unittest.cc b/sw/device/tests/dif/dif_entropy_unittest.cc
index 12e3b53..f0d4603 100644
--- a/sw/device/tests/dif/dif_entropy_unittest.cc
+++ b/sw/device/tests/dif/dif_entropy_unittest.cc
@@ -143,9 +143,21 @@
   EXPECT_EQ(dif_entropy_read(&entropy_, nullptr), kDifEntropyBadArg);
 }
 
+TEST_F(ReadTest, ReadDataUnAvailable) {
+  EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET, 0);
+  uint32_t got_word;
+  EXPECT_EQ(dif_entropy_read(&entropy_, &got_word), kDifEntropyDataUnAvailable);
+}
+
 TEST_F(ReadTest, ReadOk) {
   const uint32_t expected_word = 0x65585497;
+  EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
+                1 << ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
   EXPECT_READ32(ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET, expected_word);
+  EXPECT_READ32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
+                1 << ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
+  EXPECT_WRITE32(ENTROPY_SRC_INTR_STATE_REG_OFFSET,
+                 {{ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT, true}});
 
   uint32_t got_word;
   EXPECT_EQ(dif_entropy_read(&entropy_, &got_word), kDifEntropyOk);
diff --git a/test/systemtest/config.py b/test/systemtest/config.py
index a5b9646..45d8bc0 100644
--- a/test/systemtest/config.py
+++ b/test/systemtest/config.py
@@ -74,6 +74,7 @@
     },
     {
         "name": "dif_entropy_smoketest",
+        "targets": ["sim_verilator"],
     },
     {
         "name": "flash_ctrl_test",