[entropy_src] rnd interface added

Signed-off-by: Mark Branstad <mark.branstad@wdc.com>
diff --git a/hw/ip/entropy_src/rtl/entropy_src.sv b/hw/ip/entropy_src/rtl/entropy_src.sv
index 1218104..41ab7d8 100755
--- a/hw/ip/entropy_src/rtl/entropy_src.sv
+++ b/hw/ip/entropy_src/rtl/entropy_src.sv
@@ -4,19 +4,33 @@
 //
 // Description: entropy_src top level wrapper file
 
-module entropy_src  #(
-  parameter int unsigned EsFifoDepth = 32
+
+module entropy_src import entropy_src_pkg::*; #(
+  parameter int unsigned EsFifoDepth = 16
 ) (
-  input           clk_i,
-  input           rst_ni,
+  input  clk_i,
+  input  rst_ni,
 
   // Bus Interface
   input  tlul_pkg::tl_h2d_t tl_i,
   output tlul_pkg::tl_d2h_t tl_o,
 
+  // Efuse Interface
+  input efuse_es_sw_reg_en_i,
+
+  // Entropy Interface
+  input  entropy_src_hw_if_req_t entropy_src_hw_if_i,
+  output entropy_src_hw_if_rsp_t entropy_src_hw_if_o,
+
+  // RNG Interface
+  output entropy_src_rng_req_t entropy_src_rng_o,
+  input  entropy_src_rng_rsp_t entropy_src_rng_i,
+
   // Interrupts
   output logic    es_entropy_valid_o,
-  output logic    es_entropy_fifo_err_o
+  output logic    es_rct_failed_o,
+  output logic    es_apt_failed_o,
+  output logic    es_fifo_err_o
 );
 
   import entropy_src_reg_pkg::*;
@@ -35,14 +49,26 @@
     .devmode_i(1'b1)
   );
 
-  entropy_src_core u_entropy_src_core (
+  entropy_src_core #(
+    .EsFifoDepth(EsFifoDepth)
+  ) u_entropy_src_core (
     .clk_i,
     .rst_ni,
     .reg2hw,
     .hw2reg,
 
+    .efuse_es_sw_reg_en_i,
+
+    .entropy_src_hw_if_o,
+    .entropy_src_hw_if_i,
+
+    .entropy_src_rng_o,
+    .entropy_src_rng_i,
+
     .es_entropy_valid_o,
-    .es_entropy_fifo_err_o
+    .es_rct_failed_o,
+    .es_apt_failed_o,
+    .es_fifo_err_o
   );
 
 endmodule
diff --git a/hw/ip/entropy_src/rtl/entropy_src_align_sm.sv b/hw/ip/entropy_src/rtl/entropy_src_align_sm.sv
new file mode 100755
index 0000000..0a93d4f
--- /dev/null
+++ b/hw/ip/entropy_src/rtl/entropy_src_align_sm.sv
@@ -0,0 +1,140 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description: entropy_src byte allignment of entropy bits state machine module
+//
+
+module entropy_src_align_sm (
+  input                  clk_i,
+  input                  rst_ni,
+
+   // ins req interface
+  input logic            es_enable_i,
+  input logic            es_health_fail_i,
+  input logic            upstr_fifo_vld_i,
+  input logic            dwstr_fifo_not_full_i,
+  output logic           dwstr_fifo_push_o,
+  output logic           es_load_byte0_o,
+  output logic           es_load_byte1_o,
+  output logic           es_load_byte2_o,
+  output logic           es_load_byte3_o,
+  input logic            other_dwstr_fifo_empty_i,
+  output logic           dwstr_fifo_swap_o,
+  output logic           dwstr_fifo_clr_o
+);
+
+
+  typedef enum logic [3:0] {
+                            IDLE  = 4'h0,
+                            BYTE0 = 4'h1,
+                            BYTE1 = 4'h2,
+                            BYTE2 = 4'h3,
+                            BYTE3 = 4'h4,
+                            PUSH  = 4'h5,
+                            FCHK  = 4'h6,
+                            SWAP  = 4'h7,
+                            BAIL  = 4'h8
+                            } state_e;
+
+  state_e state_q, state_d;
+
+
+  always_ff @(posedge clk_i or negedge rst_ni)
+    if (!rst_ni) begin
+      state_q    <= IDLE;
+    end else begin
+      state_q    <= state_d;
+    end
+
+
+  always_comb begin
+    state_d = state_q;
+    dwstr_fifo_push_o = 1'b0;
+    es_load_byte0_o = 1'b0;
+    es_load_byte1_o = 1'b0;
+    es_load_byte2_o = 1'b0;
+    es_load_byte3_o = 1'b0;
+    dwstr_fifo_clr_o = 1'b0;
+    dwstr_fifo_swap_o = 1'b0;
+    unique case (state_q)
+//    case (state_q)
+      IDLE: begin
+        if (es_enable_i) begin
+          state_d = BYTE0;
+        end
+      end
+      BYTE0: begin
+        if (es_health_fail_i) begin
+          state_d = BAIL;
+        end else if (upstr_fifo_vld_i) begin
+          es_load_byte0_o = 1'b1;
+          state_d = BYTE1;
+        end else begin
+          state_d = BYTE0;
+        end
+      end
+      BYTE1: begin
+        if (es_health_fail_i) begin
+          state_d = BAIL;
+        end else if (upstr_fifo_vld_i) begin
+          es_load_byte1_o = 1'b1;
+          state_d = BYTE2;
+        end else begin
+          state_d = BYTE1;
+        end
+      end
+      BYTE2: begin
+        if (es_health_fail_i) begin
+          state_d = BAIL;
+        end else if (upstr_fifo_vld_i) begin
+          es_load_byte2_o = 1'b1;
+          state_d = BYTE3;
+        end else begin
+          state_d = BYTE2;
+        end
+      end
+      BYTE3: begin
+        if (es_health_fail_i) begin
+          state_d = BAIL;
+        end else if (upstr_fifo_vld_i) begin
+          es_load_byte3_o = 1'b1;
+          state_d = PUSH;
+        end else begin
+          state_d = BYTE3;
+        end
+      end
+      PUSH: begin
+        if (es_health_fail_i) begin
+          state_d = BAIL;
+        end else if (dwstr_fifo_not_full_i) begin
+          dwstr_fifo_push_o = 1'b1;
+          state_d = FCHK;
+        end else begin
+          state_d = PUSH;
+        end
+      end
+      FCHK: begin
+        if (!dwstr_fifo_not_full_i) begin
+          state_d = SWAP;
+        end else begin
+          state_d = IDLE;
+        end
+      end
+      SWAP: begin
+        if (other_dwstr_fifo_empty_i) begin
+          dwstr_fifo_swap_o = 1'b1;
+          state_d = IDLE;
+        end else begin
+          state_d = SWAP;
+        end
+      end
+      BAIL: begin
+        dwstr_fifo_clr_o = 1'b1;
+        state_d = IDLE;
+      end
+      default: state_d = IDLE;
+    endcase
+  end
+
+endmodule
diff --git a/hw/ip/entropy_src/rtl/entropy_src_core.sv b/hw/ip/entropy_src/rtl/entropy_src_core.sv
index bf3c6d9..6bdef00 100755
--- a/hw/ip/entropy_src/rtl/entropy_src_core.sv
+++ b/hw/ip/entropy_src/rtl/entropy_src_core.sv
@@ -5,8 +5,8 @@
 // Description: entropy_src core module
 //
 
-module entropy_src_core #(
-  parameter int unsigned EsFifoDepth = 32
+module entropy_src_core import entropy_src_pkg::*; #(
+  parameter int unsigned EsFifoDepth = 16
 ) (
   input                  clk_i,
   input                  rst_ni,
@@ -14,55 +14,137 @@
   input  entropy_src_reg_pkg::entropy_src_reg2hw_t reg2hw,
   output entropy_src_reg_pkg::entropy_src_hw2reg_t hw2reg,
 
+  // Efuse Interface
+  input efuse_es_sw_reg_en_i,
+
+
+  // Entropy Interface
+  input  entropy_src_hw_if_req_t entropy_src_hw_if_i,
+  output entropy_src_hw_if_rsp_t entropy_src_hw_if_o,
+
+  // RNG Interface
+  output entropy_src_rng_req_t entropy_src_rng_o,
+  input  entropy_src_rng_rsp_t entropy_src_rng_i,
+
   output logic           es_entropy_valid_o,
-  output logic           es_entropy_fifo_err_o
+  output logic           es_rct_failed_o,
+  output logic           es_apt_failed_o,
+  output logic           es_fifo_err_o
 );
 
   import entropy_src_reg_pkg::*;
 
-  localparam int unsigned DEPTHW = $clog2(EsFifoDepth+1);
+  localparam int unsigned PostHTDepth = $clog2(EsFifoDepth);
+  localparam int unsigned RngBusWidth = 4;
 
   // signals
-  logic [31:0] lfsr_value;
-  logic [31:0] seed_value;
-  logic        load_seed;
-  logic        es_enable;
-  logic        es_init;
-  logic        esentropy_rd_pls;
-  logic        event_es_entropy_valid;
-  logic        event_es_entropy_fifo_err;
-  logic        sfifo_esentropy_push;
-  logic        sfifo_esentropy_pop;
-  logic [31:0] sfifo_esentropy_din;
-  logic [31:0] sfifo_esentropy_dout;
-  logic        sfifo_esentropy_full;
-  logic        not_sfifo_esentropy_full;
-  logic        sfifo_esentropy_empty;
-  logic        not_sfifo_esentropy_empty;
-  logic        sfifo_esentropy_err;
+  logic [RngBusWidth-1:0] lfsr_value;
+  logic [RngBusWidth-1:0] seed_value;
+  logic       load_seed;
+  logic       es_enable;
+  logic       es_enable_dig;
+  logic       es_enable_rng;
+  logic       rng_bit_en;
+  logic [1:0] rng_bit_sel;
+  logic       lfsr_enable;
+  logic       esentropy_rd_pls;
+  logic       event_es_entropy_valid;
+  logic       event_es_apt_failed;
+  logic       event_es_rct_failed;
+//  logic       event_es_rng_bits_err;
+  logic       event_es_fifo_err;
   logic [15:0] es_rate;
   logic        es_rate_entropy_valid;
-  logic [6:0]  es_reg_fifo_thresh;
-  logic [DEPTHW-1:0] es_fifo_thresh;
-  logic [DEPTHW-1:0] sfifo_esentropy_depth;
+  logic        es_rate_entropy_valid_en;
+  logic [2:0]  es_fifo_thresh;
+  logic       es_rng_src_ok;
+
+  logic        sfifo_esdig_push;
+  logic        sfifo_esdig_pop;
+  logic        sfifo_esdig_clr;
+  logic [RngBusWidth-1:0] sfifo_esdig_wdata;
+  logic [RngBusWidth-1:0] sfifo_esdig_rdata;
+  logic [2:0]  sfifo_esdig_depth;
+  logic        sfifo_esdig_not_full;
+  logic        sfifo_esdig_not_empty;
+  logic        sfifo_esdig_err;
+
+  logic        sfifo_postht_push;
+  logic        sfifo_postht_pop;
+  logic        sfifo_postht_clr;
+  logic [31:0] sfifo_postht_wdata;
+  logic [31:0] sfifo_postht_rdata;
+  logic [PostHTDepth:0] sfifo_postht_depth;
+  logic        sfifo_postht_not_full;
+  logic        sfifo_postht_not_empty;
+  logic        sfifo_postht_err;
+  logic        sfifo_postht_avail;
+
+  logic        sfifo_essw_push;
+  logic        sfifo_essw_pop;
+  logic        sfifo_essw_clr;
+  logic [31:0] sfifo_essw_wdata;
+  logic [31:0] sfifo_essw_rdata;
+  logic [2:0 ] sfifo_essw_depth;
+  logic        sfifo_essw_not_full;
+  logic        sfifo_essw_not_empty;
+  logic        sfifo_essw_err;
+
+  logic        sfifo_eshw_push;
+  logic        sfifo_eshw_pop;
+  logic        sfifo_eshw_clr;
+  logic [31:0] sfifo_eshw_wdata;
+  logic [31:0] sfifo_eshw_rdata;
+  logic [2:0]  sfifo_eshw_depth;
+  logic        sfifo_eshw_not_full;
+  logic        sfifo_eshw_not_empty;
+  logic        sfifo_eshw_err;
+
+//  logic [RngBusWidth-1:0] rng_bits_err;
+  logic [RngBusWidth-1:0] rct_active;
+  logic [15:0] rct_max_cnt;
+  logic [RngBusWidth-1:0] apt_active;
+  logic [15:0] apt_max_cnt;
+  logic [15:0] apt_window;
+  logic [RngBusWidth-1:0] apt_fail_pls;
+  logic [RngBusWidth-1:0] rct_fail_pls;
+  logic [RngBusWidth-1:0] shtests_passing;
+  logic [RngBusWidth-1:0] packer_esbus_wdata;
+  logic [31:0] packer_esbus_rdata;
+  logic        packer_esbus_push;
+  logic        packer_esbus_clr;
+  logic        packer_esbus_valid;
+  logic        packer_esbit_wdata;
+  logic [31:0] packer_esbit_rdata;
+  logic        packer_esbit_push;
+  logic        packer_esbit_clr;
+  logic        packer_esbit_valid;
+  logic        packer_valid;
+  logic        fill_sfifo_essw;
 
   // flops
   logic        entropy_val_q, entropy_val_d;
   logic [15:0] es_rate_cntr_q, es_rate_cntr_d;
+//  logic        rng_bits_err_q, rng_bits_err_d;
 
   always_ff @(posedge clk_i or negedge rst_ni)
     if (!rst_ni) begin
-      entropy_val_q <= '0;
-      es_rate_cntr_q <= 16'h0001;
+      entropy_val_q         <= '0;
+      es_rate_cntr_q        <= 16'h0001;
+//      rng_bits_err_q        <= '0;
     end else begin
-      entropy_val_q <= entropy_val_d;
-      es_rate_cntr_q <= es_rate_cntr_d;
+      entropy_val_q         <= entropy_val_d;
+      es_rate_cntr_q        <= es_rate_cntr_d;
+//      rng_bits_err_q        <= rng_bits_err_d;
     end
 
-  assign es_enable = reg2hw.es_conf.q;
-  assign es_init = reg2hw.es_ctrl.q;
-  assign load_seed = ((sfifo_esentropy_full & es_init) | ~es_enable);
-  assign esentropy_rd_pls = reg2hw.es_entropy.re;
+  assign es_enable = (|reg2hw.es_conf.enable.q);
+  assign es_enable_dig = reg2hw.es_conf.enable.q[0];
+  assign es_enable_rng = reg2hw.es_conf.enable.q[1];
+  assign load_seed = ~es_enable;
+
+  assign entropy_src_rng_o.rng_enable = reg2hw.es_conf.rng_src_en.q;
+
 
   //--------------------------------------------
   // instantiate interrupt hardware primitives
@@ -79,88 +161,80 @@
     .intr_o                 (es_entropy_valid_o)
   );
 
-  prim_intr_hw #(.Width(1)) intr_hw_es_entropy_fifo_err (
-    .event_intr_i           (event_es_entropy_fifo_err),
-    .reg2hw_intr_enable_q_i (reg2hw.intr_enable.es_entropy_fifo_err.q),
-    .reg2hw_intr_test_q_i   (reg2hw.intr_test.es_entropy_fifo_err.q),
-    .reg2hw_intr_test_qe_i  (reg2hw.intr_test.es_entropy_fifo_err.qe),
-    .reg2hw_intr_state_q_i  (reg2hw.intr_state.es_entropy_fifo_err.q),
-    .hw2reg_intr_state_de_o (hw2reg.intr_state.es_entropy_fifo_err.de),
-    .hw2reg_intr_state_d_o  (hw2reg.intr_state.es_entropy_fifo_err.d),
-    .intr_o                 (es_entropy_fifo_err_o)
+  prim_intr_hw #(.Width(1)) intr_hw_es_rct_failed (
+    .event_intr_i           (event_es_rct_failed),
+    .reg2hw_intr_enable_q_i (reg2hw.intr_enable.es_rct_failed.q),
+    .reg2hw_intr_test_q_i   (reg2hw.intr_test.es_rct_failed.q),
+    .reg2hw_intr_test_qe_i  (reg2hw.intr_test.es_rct_failed.qe),
+    .reg2hw_intr_state_q_i  (reg2hw.intr_state.es_rct_failed.q),
+    .hw2reg_intr_state_de_o (hw2reg.intr_state.es_rct_failed.de),
+    .hw2reg_intr_state_d_o  (hw2reg.intr_state.es_rct_failed.d),
+    .intr_o                 (es_rct_failed_o)
+  );
+
+  prim_intr_hw #(.Width(1)) intr_hw_es_apt_failed (
+    .event_intr_i           (event_es_apt_failed),
+    .reg2hw_intr_enable_q_i (reg2hw.intr_enable.es_apt_failed.q),
+    .reg2hw_intr_test_q_i   (reg2hw.intr_test.es_apt_failed.q),
+    .reg2hw_intr_test_qe_i  (reg2hw.intr_test.es_apt_failed.qe),
+    .reg2hw_intr_state_q_i  (reg2hw.intr_state.es_apt_failed.q),
+    .hw2reg_intr_state_de_o (hw2reg.intr_state.es_apt_failed.de),
+    .hw2reg_intr_state_d_o  (hw2reg.intr_state.es_apt_failed.d),
+    .intr_o                 (es_apt_failed_o)
+  );
+
+
+  prim_intr_hw #(.Width(1)) intr_hw_es_fifo_err (
+    .event_intr_i           (event_es_fifo_err),
+    .reg2hw_intr_enable_q_i (reg2hw.intr_enable.es_fifo_err.q),
+    .reg2hw_intr_test_q_i   (reg2hw.intr_test.es_fifo_err.q),
+    .reg2hw_intr_test_qe_i  (reg2hw.intr_test.es_fifo_err.qe),
+    .reg2hw_intr_state_q_i  (reg2hw.intr_state.es_fifo_err.q),
+    .hw2reg_intr_state_de_o (hw2reg.intr_state.es_fifo_err.de),
+    .hw2reg_intr_state_d_o  (hw2reg.intr_state.es_fifo_err.d),
+    .intr_o                 (es_fifo_err_o)
   );
 
   //--------------------------------------------
   // lfsr - a version of a entropy source
   //--------------------------------------------
 
-  prim_lfsr #(.LfsrDw(32), .EntropyDw(32), .StateOutDw(32), .DefaultSeed(1), .CustomCoeffs('0))
+  assign lfsr_enable = es_enable_dig && es_rate_entropy_valid;
+
+  prim_lfsr #(.LfsrDw(RngBusWidth),
+              .EntropyDw(RngBusWidth),
+              .StateOutDw(RngBusWidth),
+              .DefaultSeed(1),
+              .CustomCoeffs('0))
     u_prim_lfsr (
     .clk_i          (clk_i),
     .rst_ni         (rst_ni),
     .seed_en_i      (load_seed),
     .seed_i         (seed_value),
-    .lfsr_en_i      (es_enable),
+    .lfsr_en_i      (lfsr_enable),
     .entropy_i      ('0),
     .state_o        (lfsr_value)
   );
 
   // entropy rate limiter
 
-  assign es_rate_cntr_d = ~es_enable ? 16'h0001 :
+  assign es_rate_cntr_d =
+         ~es_rate_entropy_valid_en ? 16'h0001 :
          (es_rate == '0) ? 16'h0000 :
          es_rate_entropy_valid ? es_rate :
          (es_rate_cntr_q - 1);
 
   assign es_rate_entropy_valid =
-         ~es_enable ? 1'b0 :
+         ~es_rate_entropy_valid_en ? 1'b0 :
          (es_rate == '0) ? 1'b0 :
          (es_rate_cntr_q == 16'h0001);
 
-  //--------------------------------------------
-  // fifo for entropy collection
-  //--------------------------------------------
-
-  prim_fifo_sync # (.Width(32),.Pass(0),.Depth(EsFifoDepth))
-    u_prim_fifo_sync_esentropy (
-    .clk_i          (clk_i),
-    .rst_ni         (rst_ni),
-    .clr_i          (~es_enable),
-    .wvalid         (sfifo_esentropy_push),
-    .wready         (not_sfifo_esentropy_full),
-    .wdata          (sfifo_esentropy_din),
-    .rvalid         (not_sfifo_esentropy_empty),
-    .rready         (sfifo_esentropy_pop),
-    .rdata          (sfifo_esentropy_dout),
-    .depth          (sfifo_esentropy_depth)
-  );
-
-  assign sfifo_esentropy_full = ~not_sfifo_esentropy_full;
-  assign sfifo_esentropy_empty = ~not_sfifo_esentropy_empty;
-  assign sfifo_esentropy_err =
-         (sfifo_esentropy_push & sfifo_esentropy_full) |
-         (sfifo_esentropy_empty & sfifo_esentropy_pop);
-
-  // fifo controls
-  assign sfifo_esentropy_push = es_enable & es_rate_entropy_valid & ~sfifo_esentropy_full;
-  assign sfifo_esentropy_din = lfsr_value;
-  assign sfifo_esentropy_pop = es_enable & ~sfifo_esentropy_empty & esentropy_rd_pls;
-
-  // threshold
-  assign es_fifo_thresh = es_reg_fifo_thresh[DEPTHW-1:0];
-
-  // entropy valid
-  assign entropy_val_d = ~es_enable ? 1'b0 : (sfifo_esentropy_depth >= es_fifo_thresh);
+  assign es_rate_entropy_valid_en = (es_enable_rng & es_rng_src_ok) | es_enable_dig;
 
   //--------------------------------------------
   // tlul register settings
   //--------------------------------------------
 
-  // set the es entropy to the read reg
-  assign hw2reg.es_entropy.d = sfifo_esentropy_dout;
-
-  // set the es fifo depth to the read reg
-  assign hw2reg.es_fdepthst.d = sfifo_esentropy_depth;
 
   // seed register
   assign seed_value = reg2hw.es_seed.q;
@@ -168,20 +242,272 @@
   // es rate register
   assign es_rate = reg2hw.es_rate.q;
 
-  // es fifo threshold register
-  assign es_reg_fifo_thresh = reg2hw.es_thresh.q;
-
   // set the interrupt event when enabled
   assign event_es_entropy_valid = entropy_val_q;
 
   // set the interrupt sources
-  assign event_es_entropy_fifo_err = sfifo_esentropy_err;
+  assign event_es_fifo_err =
+         sfifo_esdig_err |
+         sfifo_postht_err |
+         sfifo_essw_err |
+         sfifo_eshw_err;
+
+  // set the debug status reg
+  assign hw2reg.es_fifo_status.dig_src_depth.d = sfifo_esdig_depth;
+  assign hw2reg.es_fifo_status.hwif_depth.d = sfifo_eshw_depth;
+  assign hw2reg.es_fifo_status.es_depth.d = sfifo_postht_depth;
+
 
   //--------------------------------------------
-  // status
+  // basic checks for RNG bus input
   //--------------------------------------------
 
-  // set the status bit
-  assign hw2reg.es_status.d = entropy_val_q;
+  assign rng_bit_en = reg2hw.es_conf.rng_bit_en.q;
+  assign rng_bit_sel = reg2hw.es_conf.rng_bit_sel.q;
+
+
+  assign es_rng_src_ok = entropy_src_rng_i.rng_ok;
+
+
+  prim_fifo_sync # (.Width(RngBusWidth),.Pass(0),.Depth(4))
+    u_prim_fifo_sync_esdig (
+    .clk_i          (clk_i),
+    .rst_ni         (rst_ni),
+    .clr_i          (sfifo_esdig_clr),
+    .wvalid         (sfifo_esdig_push),
+    .wready         (sfifo_esdig_not_full),
+    .wdata          (sfifo_esdig_wdata),
+    .rvalid         (sfifo_esdig_not_empty),
+    .rready         (sfifo_esdig_pop),
+    .rdata          (sfifo_esdig_rdata),
+    .depth          (sfifo_esdig_depth)
+  );
+
+  // fifo controls
+  assign sfifo_esdig_push = es_enable & es_rate_entropy_valid & sfifo_esdig_not_full;
+  assign sfifo_esdig_clr  = ~es_enable;
+  assign sfifo_esdig_wdata = es_enable_dig ? lfsr_value : entropy_src_rng_i.rng_b;
+  assign sfifo_esdig_pop = es_enable & sfifo_esdig_not_empty & sfifo_postht_avail;
+
+  // note: allow input lfsr entropy to drop
+
+  // fifo err
+  assign sfifo_esdig_err =
+         (sfifo_esdig_pop & ~sfifo_esdig_not_empty );
+
+  // pack esbus before moving to a 32 bit bus
+
+  prim_packer # (.InW(RngBusWidth),.OutW(32))
+    u_prim_packer_esbus (
+    .clk_i          (clk_i),
+    .rst_ni         (rst_ni),
+    .valid_i        (packer_esbus_push),
+    .data_i         (packer_esbus_wdata),
+    .mask_i         ({RngBusWidth{1'b1}}),
+    .ready_o        (),
+    .valid_o        (packer_esbus_valid),
+    .data_o         (packer_esbus_rdata),
+    .mask_o         (),
+    .ready_i        (1'b1),
+    .flush_i        (packer_esbus_clr),
+    .flush_done_o   ()
+  );
+
+  assign packer_esbus_push = ~rng_bit_en & sfifo_esdig_pop;
+  assign packer_esbus_wdata = sfifo_esdig_rdata;
+  assign packer_esbus_clr = ~es_enable;
+
+  // pack esbit before moving to a 32 bit bus
+
+  prim_packer # (.InW(1),.OutW(32))
+    u_prim_packer_esbit (
+    .clk_i          (clk_i),
+    .rst_ni         (rst_ni),
+    .valid_i        (packer_esbit_push),
+    .data_i         (packer_esbit_wdata),
+    .mask_i         (1'b1),
+    .ready_o        (),
+    .valid_o        (packer_esbit_valid),
+    .data_o         (packer_esbit_rdata),
+    .mask_o         (),
+    .ready_i        (1'b1),
+    .flush_i        (packer_esbit_clr),
+    .flush_done_o   ()
+  );
+
+  assign packer_esbit_push = rng_bit_en & sfifo_esdig_pop;
+  assign packer_esbit_clr = ~es_enable;
+  assign packer_esbit_wdata =
+         (rng_bit_sel == 2'h0) ? sfifo_esdig_rdata[0] :
+         (rng_bit_sel == 2'h1) ? sfifo_esdig_rdata[1] :
+         (rng_bit_sel == 2'h2) ? sfifo_esdig_rdata[2] :
+         sfifo_esdig_rdata[3];
+
+
+  // combine packers
+  assign packer_valid = packer_esbus_valid | packer_esbit_valid;
+
+
+  prim_fifo_sync # (.Width(32),.Pass(0),.Depth(EsFifoDepth))
+    u_prim_fifo_sync_postht (
+    .clk_i          (clk_i),
+    .rst_ni         (rst_ni),
+    .clr_i          (sfifo_postht_clr),
+    .wvalid         (sfifo_postht_push),
+    .wready         (sfifo_postht_not_full),
+    .wdata          (sfifo_postht_wdata),
+    .rvalid         (sfifo_postht_not_empty),
+    .rready         (sfifo_postht_pop),
+    .rdata          (sfifo_postht_rdata),
+    .depth          (sfifo_postht_depth)
+  );
+
+  // fifo controls
+  assign sfifo_postht_push = es_enable & packer_valid & (&shtests_passing);
+  assign sfifo_postht_clr  = ~es_enable;
+  assign sfifo_postht_wdata = rng_bit_en ? packer_esbit_rdata : packer_esbus_rdata;
+  assign sfifo_postht_pop = es_enable & sfifo_postht_not_empty &
+         (fill_sfifo_essw | sfifo_eshw_not_full);
+
+  // allow one extra location because of packer
+  assign sfifo_postht_avail = (sfifo_postht_depth < (EsFifoDepth-1));
+
+  // fifo err
+  assign sfifo_postht_err =
+         (sfifo_postht_push & ~sfifo_postht_not_full) |
+         (sfifo_postht_pop & ~sfifo_postht_not_empty );
+
+
+  //--------------------------------------------
+  // health tests
+  //--------------------------------------------
+
+  genvar ta;
+  generate
+    for (ta = 0; ta < RngBusWidth; ta = ta+1) begin : gen_test_act
+      assign rct_active[ta] = rng_bit_en ? ((rng_bit_sel == ta) & reg2hw.es_conf.rct_en.q) :
+                              reg2hw.es_conf.rct_en.q;
+      assign apt_active[ta] = rng_bit_en ? ((rng_bit_sel == ta) & reg2hw.es_conf.apt_en.q) :
+             reg2hw.es_conf.apt_en.q;
+    end
+  endgenerate
+
+  assign rct_max_cnt = reg2hw.es_rct_health.q;
+
+  assign apt_max_cnt = reg2hw.es_apt_health.apt_max.q;
+  assign apt_window  = reg2hw.es_apt_health.apt_win.q;
+
+  genvar sh;
+  generate
+    for (sh = 0; sh < RngBusWidth; sh = sh+1) begin : gen_shtests
+      entropy_src_shtests
+        u_entropy_src_shtests (
+       .clk_i               (clk_i),
+       .rst_ni              (rst_ni),
+       .entropy_bit_i       (sfifo_esdig_rdata[sh]),
+       .entropy_bit_vld_i   (sfifo_esdig_pop),
+       .rct_active_i        (rct_active[sh]),
+       .rct_max_cnt_i       (rct_max_cnt),
+       .apt_active_i        (apt_active[sh]),
+       .apt_max_cnt_i       (apt_max_cnt),
+       .apt_window_i        (apt_window),
+       .rct_fail_pls_o      (rct_fail_pls[sh]),
+       .apt_fail_pls_o      (apt_fail_pls[sh]),
+       .shtests_passing_o   (shtests_passing[sh])
+      );
+    end
+  endgenerate
+
+  assign event_es_rct_failed = |rct_fail_pls;
+  assign event_es_apt_failed = |apt_fail_pls;
+
+
+  //--------------------------------------------
+  // fifos for final distribution
+  //--------------------------------------------
+
+  assign fill_sfifo_essw = es_enable & sfifo_essw_not_full & efuse_es_sw_reg_en_i;
+
+  // this fifo feeds the sw register interface
+
+  prim_fifo_sync # (.Width(32),.Pass(0),.Depth(4))
+    u_prim_fifo_sync_essw (
+    .clk_i          (clk_i),
+    .rst_ni         (rst_ni),
+    .clr_i          (sfifo_essw_clr),
+    .wvalid         (sfifo_essw_push),
+    .wready         (sfifo_essw_not_full),
+    .wdata          (sfifo_essw_wdata),
+    .rvalid         (sfifo_essw_not_empty),
+    .rready         (sfifo_essw_pop),
+    .rdata          (sfifo_essw_rdata),
+    .depth          (sfifo_essw_depth)
+  );
+
+  // fifo controls
+  assign sfifo_essw_push = es_enable & sfifo_postht_pop & fill_sfifo_essw;
+  assign sfifo_essw_clr  = ~es_enable;
+  assign sfifo_essw_wdata = sfifo_postht_rdata;
+  assign sfifo_essw_pop = es_enable & esentropy_rd_pls & efuse_es_sw_reg_en_i;
+
+  // fifo err
+  assign sfifo_essw_err =
+         (sfifo_essw_push & ~sfifo_essw_not_full) |
+         (sfifo_essw_pop & ~sfifo_essw_not_empty );
+
+  // set the es entropy to the read reg
+  assign hw2reg.es_entropy.d = es_enable ? sfifo_essw_rdata : '0;
+  assign esentropy_rd_pls = reg2hw.es_entropy.re;
+
+  // threshold
+  assign es_fifo_thresh = reg2hw.es_thresh.q;
+
+  // entropy valid
+  assign entropy_val_d = ~es_enable ? 1'b0 : (sfifo_essw_depth >= es_fifo_thresh);
+
+  // set the es fifo depth to the read reg
+  assign hw2reg.es_fdepthst.d = sfifo_essw_depth;
+
+
+
+  // this fifo feeds the hw bus interface
+
+  prim_fifo_sync # (.Width(32),.Pass(0),.Depth(4))
+    u_prim_fifo_sync_eshw (
+    .clk_i          (clk_i),
+    .rst_ni         (rst_ni),
+    .clr_i          (sfifo_eshw_clr),
+    .wvalid         (sfifo_eshw_push),
+    .wready         (sfifo_eshw_not_full),
+    .wdata          (sfifo_eshw_wdata),
+    .rvalid         (sfifo_eshw_not_empty),
+    .rready         (sfifo_eshw_pop),
+    .rdata          (sfifo_eshw_rdata),
+    .depth          (sfifo_eshw_depth)
+  );
+
+  // fifo controls
+  assign sfifo_eshw_push = es_enable & sfifo_postht_pop & ~fill_sfifo_essw;
+  assign sfifo_eshw_clr  = ~es_enable;
+  assign sfifo_eshw_wdata = sfifo_postht_rdata;
+  assign sfifo_eshw_pop = es_enable & entropy_src_hw_if_i.entropy_src_rdy
+         & sfifo_eshw_not_empty;
+
+  // fifo err
+  assign sfifo_eshw_err =
+         (sfifo_eshw_push & ~sfifo_eshw_not_full) |
+         (sfifo_eshw_pop & ~sfifo_eshw_not_empty );
+
+  // drive out hw interface
+  assign entropy_src_hw_if_o.entropy_src_vld = sfifo_eshw_not_empty;
+  assign entropy_src_hw_if_o.entropy_src_bits = sfifo_eshw_rdata;
+
+  //--------------------------------------------
+  // diag settings
+  //--------------------------------------------
+
+  assign hw2reg.es_fifo_status.diag.d  =
+         reg2hw.es_regen.q &
+         (&reg2hw.es_entropy.q);
 
 endmodule
diff --git a/hw/ip/entropy_src/rtl/entropy_src_pkg.sv b/hw/ip/entropy_src/rtl/entropy_src_pkg.sv
new file mode 100755
index 0000000..c74fbee
--- /dev/null
+++ b/hw/ip/entropy_src/rtl/entropy_src_pkg.sv
@@ -0,0 +1,32 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License; Version 2.0; see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+
+package entropy_src_pkg;
+
+  //-------------------------
+  // Entropy Interface
+  //-------------------------
+
+  typedef struct packed {
+    logic        entropy_src_vld;
+    logic [31:0] entropy_src_bits;
+  } entropy_src_hw_if_rsp_t;
+
+  typedef struct packed {
+    logic entropy_src_rdy;
+  } entropy_src_hw_if_req_t;
+
+  typedef struct packed {
+    logic rng_enable;
+  } entropy_src_rng_req_t;
+
+  typedef struct packed {
+    logic rng_ok;
+    logic [3:0] rng_b;
+  } entropy_src_rng_rsp_t;
+
+
+endpackage : entropy_src_pkg
\ No newline at end of file
diff --git a/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv b/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv
index 1d692be..b4c9813 100644
--- a/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv
+++ b/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv
@@ -18,7 +18,13 @@
     } es_entropy_valid;
     struct packed {
       logic        q;
-    } es_entropy_fifo_err;
+    } es_rct_failed;
+    struct packed {
+      logic        q;
+    } es_apt_failed;
+    struct packed {
+      logic        q;
+    } es_fifo_err;
   } entropy_src_reg2hw_intr_state_reg_t;
 
   typedef struct packed {
@@ -27,7 +33,13 @@
     } es_entropy_valid;
     struct packed {
       logic        q;
-    } es_entropy_fifo_err;
+    } es_rct_failed;
+    struct packed {
+      logic        q;
+    } es_apt_failed;
+    struct packed {
+      logic        q;
+    } es_fifo_err;
   } entropy_src_reg2hw_intr_enable_reg_t;
 
   typedef struct packed {
@@ -38,7 +50,15 @@
     struct packed {
       logic        q;
       logic        qe;
-    } es_entropy_fifo_err;
+    } es_rct_failed;
+    struct packed {
+      logic        q;
+      logic        qe;
+    } es_apt_failed;
+    struct packed {
+      logic        q;
+      logic        qe;
+    } es_fifo_err;
   } entropy_src_reg2hw_intr_test_reg_t;
 
   typedef struct packed {
@@ -46,20 +66,38 @@
   } entropy_src_reg2hw_es_regen_reg_t;
 
   typedef struct packed {
-    logic        q;
+    struct packed {
+      logic [1:0]  q;
+    } enable;
+    struct packed {
+      logic        q;
+    } rng_src_en;
+    struct packed {
+      logic        q;
+    } rct_en;
+    struct packed {
+      logic        q;
+    } apt_en;
+    struct packed {
+      logic        q;
+    } rng_bit_en;
+    struct packed {
+      logic [1:0]  q;
+    } rng_bit_sel;
   } entropy_src_reg2hw_es_conf_reg_t;
 
   typedef struct packed {
+    logic [15:0] q;
+  } entropy_src_reg2hw_es_rct_health_reg_t;
+
+  typedef struct packed {
     struct packed {
-      logic [7:0]  q;
-    } abi_revision;
+      logic [15:0] q;
+    } apt_max;
     struct packed {
-      logic [7:0]  q;
-    } hw_revision;
-    struct packed {
-      logic [7:0]  q;
-    } chip_type;
-  } entropy_src_reg2hw_es_rev_reg_t;
+      logic [15:0] q;
+    } apt_win;
+  } entropy_src_reg2hw_es_apt_health_reg_t;
 
   typedef struct packed {
     logic [31:0] q;
@@ -67,30 +105,15 @@
   } entropy_src_reg2hw_es_entropy_reg_t;
 
   typedef struct packed {
-    logic        q;
-  } entropy_src_reg2hw_es_ctrl_reg_t;
-
-  typedef struct packed {
-    logic        q;
-  } entropy_src_reg2hw_es_status_reg_t;
-
-  typedef struct packed {
-    logic [6:0]  q;
-  } entropy_src_reg2hw_es_fdepthst_reg_t;
-
-  typedef struct packed {
-    logic [6:0]  q;
-    logic        qe;
+    logic [2:0]  q;
   } entropy_src_reg2hw_es_thresh_reg_t;
 
   typedef struct packed {
     logic [15:0] q;
-    logic        qe;
   } entropy_src_reg2hw_es_rate_reg_t;
 
   typedef struct packed {
-    logic [31:0] q;
-    logic        qe;
+    logic [3:0]  q;
   } entropy_src_reg2hw_es_seed_reg_t;
 
 
@@ -102,7 +125,15 @@
     struct packed {
       logic        d;
       logic        de;
-    } es_entropy_fifo_err;
+    } es_rct_failed;
+    struct packed {
+      logic        d;
+      logic        de;
+    } es_apt_failed;
+    struct packed {
+      logic        d;
+      logic        de;
+    } es_fifo_err;
   } entropy_src_hw2reg_intr_state_reg_t;
 
   typedef struct packed {
@@ -110,11 +141,22 @@
   } entropy_src_hw2reg_es_entropy_reg_t;
 
   typedef struct packed {
-    logic        d;
-  } entropy_src_hw2reg_es_status_reg_t;
+    struct packed {
+      logic [2:0]  d;
+    } dig_src_depth;
+    struct packed {
+      logic [2:0]  d;
+    } hwif_depth;
+    struct packed {
+      logic [4:0]  d;
+    } es_depth;
+    struct packed {
+      logic        d;
+    } diag;
+  } entropy_src_hw2reg_es_fifo_status_reg_t;
 
   typedef struct packed {
-    logic [6:0]  d;
+    logic [2:0]  d;
   } entropy_src_hw2reg_es_fdepthst_reg_t;
 
 
@@ -122,29 +164,27 @@
   // Register to internal design logic //
   ///////////////////////////////////////
   typedef struct packed {
-    entropy_src_reg2hw_intr_state_reg_t intr_state; // [133:132]
-    entropy_src_reg2hw_intr_enable_reg_t intr_enable; // [131:130]
-    entropy_src_reg2hw_intr_test_reg_t intr_test; // [129:126]
-    entropy_src_reg2hw_es_regen_reg_t es_regen; // [125:125]
-    entropy_src_reg2hw_es_conf_reg_t es_conf; // [124:124]
-    entropy_src_reg2hw_es_rev_reg_t es_rev; // [123:100]
-    entropy_src_reg2hw_es_entropy_reg_t es_entropy; // [99:67]
-    entropy_src_reg2hw_es_ctrl_reg_t es_ctrl; // [66:66]
-    entropy_src_reg2hw_es_status_reg_t es_status; // [65:65]
-    entropy_src_reg2hw_es_fdepthst_reg_t es_fdepthst; // [64:58]
-    entropy_src_reg2hw_es_thresh_reg_t es_thresh; // [57:50]
-    entropy_src_reg2hw_es_rate_reg_t es_rate; // [49:33]
-    entropy_src_reg2hw_es_seed_reg_t es_seed; // [32:0]
+    entropy_src_reg2hw_intr_state_reg_t intr_state; // [128:125]
+    entropy_src_reg2hw_intr_enable_reg_t intr_enable; // [124:121]
+    entropy_src_reg2hw_intr_test_reg_t intr_test; // [120:113]
+    entropy_src_reg2hw_es_regen_reg_t es_regen; // [112:112]
+    entropy_src_reg2hw_es_conf_reg_t es_conf; // [111:104]
+    entropy_src_reg2hw_es_rct_health_reg_t es_rct_health; // [103:88]
+    entropy_src_reg2hw_es_apt_health_reg_t es_apt_health; // [87:56]
+    entropy_src_reg2hw_es_entropy_reg_t es_entropy; // [55:23]
+    entropy_src_reg2hw_es_thresh_reg_t es_thresh; // [22:20]
+    entropy_src_reg2hw_es_rate_reg_t es_rate; // [19:4]
+    entropy_src_reg2hw_es_seed_reg_t es_seed; // [3:0]
   } entropy_src_reg2hw_t;
 
   ///////////////////////////////////////
   // Internal design logic to register //
   ///////////////////////////////////////
   typedef struct packed {
-    entropy_src_hw2reg_intr_state_reg_t intr_state; // [43:42]
-    entropy_src_hw2reg_es_entropy_reg_t es_entropy; // [41:9]
-    entropy_src_hw2reg_es_status_reg_t es_status; // [8:8]
-    entropy_src_hw2reg_es_fdepthst_reg_t es_fdepthst; // [7:1]
+    entropy_src_hw2reg_intr_state_reg_t intr_state; // [54:51]
+    entropy_src_hw2reg_es_entropy_reg_t es_entropy; // [50:18]
+    entropy_src_hw2reg_es_fifo_status_reg_t es_fifo_status; // [17:18]
+    entropy_src_hw2reg_es_fdepthst_reg_t es_fdepthst; // [17:18]
   } entropy_src_hw2reg_t;
 
   // Register Address
@@ -152,15 +192,16 @@
   parameter logic [5:0] ENTROPY_SRC_INTR_ENABLE_OFFSET = 6'h 4;
   parameter logic [5:0] ENTROPY_SRC_INTR_TEST_OFFSET = 6'h 8;
   parameter logic [5:0] ENTROPY_SRC_ES_REGEN_OFFSET = 6'h c;
-  parameter logic [5:0] ENTROPY_SRC_ES_CONF_OFFSET = 6'h 10;
-  parameter logic [5:0] ENTROPY_SRC_ES_REV_OFFSET = 6'h 14;
-  parameter logic [5:0] ENTROPY_SRC_ES_ENTROPY_OFFSET = 6'h 18;
-  parameter logic [5:0] ENTROPY_SRC_ES_CTRL_OFFSET = 6'h 1c;
-  parameter logic [5:0] ENTROPY_SRC_ES_STATUS_OFFSET = 6'h 20;
-  parameter logic [5:0] ENTROPY_SRC_ES_FDEPTHST_OFFSET = 6'h 24;
-  parameter logic [5:0] ENTROPY_SRC_ES_THRESH_OFFSET = 6'h 28;
-  parameter logic [5:0] ENTROPY_SRC_ES_RATE_OFFSET = 6'h 2c;
-  parameter logic [5:0] ENTROPY_SRC_ES_SEED_OFFSET = 6'h 30;
+  parameter logic [5:0] ENTROPY_SRC_ES_REV_OFFSET = 6'h 10;
+  parameter logic [5:0] ENTROPY_SRC_ES_CONF_OFFSET = 6'h 14;
+  parameter logic [5:0] ENTROPY_SRC_ES_RCT_HEALTH_OFFSET = 6'h 18;
+  parameter logic [5:0] ENTROPY_SRC_ES_APT_HEALTH_OFFSET = 6'h 1c;
+  parameter logic [5:0] ENTROPY_SRC_ES_ENTROPY_OFFSET = 6'h 20;
+  parameter logic [5:0] ENTROPY_SRC_ES_FIFO_STATUS_OFFSET = 6'h 24;
+  parameter logic [5:0] ENTROPY_SRC_ES_FDEPTHST_OFFSET = 6'h 28;
+  parameter logic [5:0] ENTROPY_SRC_ES_THRESH_OFFSET = 6'h 2c;
+  parameter logic [5:0] ENTROPY_SRC_ES_RATE_OFFSET = 6'h 30;
+  parameter logic [5:0] ENTROPY_SRC_ES_SEED_OFFSET = 6'h 34;
 
 
   // Register Index
@@ -169,11 +210,12 @@
     ENTROPY_SRC_INTR_ENABLE,
     ENTROPY_SRC_INTR_TEST,
     ENTROPY_SRC_ES_REGEN,
-    ENTROPY_SRC_ES_CONF,
     ENTROPY_SRC_ES_REV,
+    ENTROPY_SRC_ES_CONF,
+    ENTROPY_SRC_ES_RCT_HEALTH,
+    ENTROPY_SRC_ES_APT_HEALTH,
     ENTROPY_SRC_ES_ENTROPY,
-    ENTROPY_SRC_ES_CTRL,
-    ENTROPY_SRC_ES_STATUS,
+    ENTROPY_SRC_ES_FIFO_STATUS,
     ENTROPY_SRC_ES_FDEPTHST,
     ENTROPY_SRC_ES_THRESH,
     ENTROPY_SRC_ES_RATE,
@@ -181,20 +223,21 @@
   } entropy_src_id_e;
 
   // Register width information to check illegal writes
-  parameter logic [3:0] ENTROPY_SRC_PERMIT [13] = '{
+  parameter logic [3:0] ENTROPY_SRC_PERMIT [14] = '{
     4'b 0001, // index[ 0] ENTROPY_SRC_INTR_STATE
     4'b 0001, // index[ 1] ENTROPY_SRC_INTR_ENABLE
     4'b 0001, // index[ 2] ENTROPY_SRC_INTR_TEST
     4'b 0001, // index[ 3] ENTROPY_SRC_ES_REGEN
-    4'b 0001, // index[ 4] ENTROPY_SRC_ES_CONF
-    4'b 0111, // index[ 5] ENTROPY_SRC_ES_REV
-    4'b 1111, // index[ 6] ENTROPY_SRC_ES_ENTROPY
-    4'b 0001, // index[ 7] ENTROPY_SRC_ES_CTRL
-    4'b 0001, // index[ 8] ENTROPY_SRC_ES_STATUS
-    4'b 0001, // index[ 9] ENTROPY_SRC_ES_FDEPTHST
-    4'b 0001, // index[10] ENTROPY_SRC_ES_THRESH
-    4'b 0011, // index[11] ENTROPY_SRC_ES_RATE
-    4'b 1111  // index[12] ENTROPY_SRC_ES_SEED
+    4'b 0111, // index[ 4] ENTROPY_SRC_ES_REV
+    4'b 0011, // index[ 5] ENTROPY_SRC_ES_CONF
+    4'b 0011, // index[ 6] ENTROPY_SRC_ES_RCT_HEALTH
+    4'b 1111, // index[ 7] ENTROPY_SRC_ES_APT_HEALTH
+    4'b 1111, // index[ 8] ENTROPY_SRC_ES_ENTROPY
+    4'b 1111, // index[ 9] ENTROPY_SRC_ES_FIFO_STATUS
+    4'b 0001, // index[10] ENTROPY_SRC_ES_FDEPTHST
+    4'b 0001, // index[11] ENTROPY_SRC_ES_THRESH
+    4'b 0011, // index[12] ENTROPY_SRC_ES_RATE
+    4'b 0001  // index[13] ENTROPY_SRC_ES_SEED
   };
 endpackage
 
diff --git a/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv b/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv
index 822d781..bd27cc3 100644
--- a/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv
+++ b/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv
@@ -74,45 +74,88 @@
   logic intr_state_es_entropy_valid_qs;
   logic intr_state_es_entropy_valid_wd;
   logic intr_state_es_entropy_valid_we;
-  logic intr_state_es_entropy_fifo_err_qs;
-  logic intr_state_es_entropy_fifo_err_wd;
-  logic intr_state_es_entropy_fifo_err_we;
+  logic intr_state_es_rct_failed_qs;
+  logic intr_state_es_rct_failed_wd;
+  logic intr_state_es_rct_failed_we;
+  logic intr_state_es_apt_failed_qs;
+  logic intr_state_es_apt_failed_wd;
+  logic intr_state_es_apt_failed_we;
+  logic intr_state_es_fifo_err_qs;
+  logic intr_state_es_fifo_err_wd;
+  logic intr_state_es_fifo_err_we;
   logic intr_enable_es_entropy_valid_qs;
   logic intr_enable_es_entropy_valid_wd;
   logic intr_enable_es_entropy_valid_we;
-  logic intr_enable_es_entropy_fifo_err_qs;
-  logic intr_enable_es_entropy_fifo_err_wd;
-  logic intr_enable_es_entropy_fifo_err_we;
+  logic intr_enable_es_rct_failed_qs;
+  logic intr_enable_es_rct_failed_wd;
+  logic intr_enable_es_rct_failed_we;
+  logic intr_enable_es_apt_failed_qs;
+  logic intr_enable_es_apt_failed_wd;
+  logic intr_enable_es_apt_failed_we;
+  logic intr_enable_es_fifo_err_qs;
+  logic intr_enable_es_fifo_err_wd;
+  logic intr_enable_es_fifo_err_we;
   logic intr_test_es_entropy_valid_wd;
   logic intr_test_es_entropy_valid_we;
-  logic intr_test_es_entropy_fifo_err_wd;
-  logic intr_test_es_entropy_fifo_err_we;
+  logic intr_test_es_rct_failed_wd;
+  logic intr_test_es_rct_failed_we;
+  logic intr_test_es_apt_failed_wd;
+  logic intr_test_es_apt_failed_we;
+  logic intr_test_es_fifo_err_wd;
+  logic intr_test_es_fifo_err_we;
   logic es_regen_qs;
   logic es_regen_wd;
   logic es_regen_we;
-  logic es_conf_qs;
-  logic es_conf_wd;
-  logic es_conf_we;
   logic [7:0] es_rev_abi_revision_qs;
   logic [7:0] es_rev_hw_revision_qs;
   logic [7:0] es_rev_chip_type_qs;
+  logic [1:0] es_conf_enable_qs;
+  logic [1:0] es_conf_enable_wd;
+  logic es_conf_enable_we;
+  logic es_conf_rng_src_en_qs;
+  logic es_conf_rng_src_en_wd;
+  logic es_conf_rng_src_en_we;
+  logic es_conf_rct_en_qs;
+  logic es_conf_rct_en_wd;
+  logic es_conf_rct_en_we;
+  logic es_conf_apt_en_qs;
+  logic es_conf_apt_en_wd;
+  logic es_conf_apt_en_we;
+  logic es_conf_rng_bit_en_qs;
+  logic es_conf_rng_bit_en_wd;
+  logic es_conf_rng_bit_en_we;
+  logic [1:0] es_conf_rng_bit_sel_qs;
+  logic [1:0] es_conf_rng_bit_sel_wd;
+  logic es_conf_rng_bit_sel_we;
+  logic [15:0] es_rct_health_qs;
+  logic [15:0] es_rct_health_wd;
+  logic es_rct_health_we;
+  logic [15:0] es_apt_health_apt_max_qs;
+  logic [15:0] es_apt_health_apt_max_wd;
+  logic es_apt_health_apt_max_we;
+  logic [15:0] es_apt_health_apt_win_qs;
+  logic [15:0] es_apt_health_apt_win_wd;
+  logic es_apt_health_apt_win_we;
   logic [31:0] es_entropy_qs;
   logic es_entropy_re;
-  logic es_ctrl_qs;
-  logic es_ctrl_wd;
-  logic es_ctrl_we;
-  logic es_status_qs;
-  logic es_status_re;
-  logic [6:0] es_fdepthst_qs;
+  logic [2:0] es_fifo_status_dig_src_depth_qs;
+  logic es_fifo_status_dig_src_depth_re;
+  logic [2:0] es_fifo_status_hwif_depth_qs;
+  logic es_fifo_status_hwif_depth_re;
+  logic [4:0] es_fifo_status_es_depth_qs;
+  logic es_fifo_status_es_depth_re;
+  logic es_fifo_status_diag_qs;
+  logic es_fifo_status_diag_re;
+  logic [2:0] es_fdepthst_qs;
   logic es_fdepthst_re;
-  logic [6:0] es_thresh_qs;
-  logic [6:0] es_thresh_wd;
+  logic [2:0] es_thresh_qs;
+  logic [2:0] es_thresh_wd;
   logic es_thresh_we;
   logic [15:0] es_rate_qs;
   logic [15:0] es_rate_wd;
   logic es_rate_we;
-  logic [31:0] es_seed_qs;
-  logic [31:0] es_seed_wd;
+  logic [3:0] es_seed_qs;
+  logic [3:0] es_seed_wd;
   logic es_seed_we;
 
   // Register instances
@@ -144,29 +187,81 @@
   );
 
 
-  //   F[es_entropy_fifo_err]: 1:1
+  //   F[es_rct_failed]: 1:1
   prim_subreg #(
     .DW      (1),
     .SWACCESS("W1C"),
     .RESVAL  (1'h0)
-  ) u_intr_state_es_entropy_fifo_err (
+  ) u_intr_state_es_rct_failed (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
     // from register interface
-    .we     (intr_state_es_entropy_fifo_err_we),
-    .wd     (intr_state_es_entropy_fifo_err_wd),
+    .we     (intr_state_es_rct_failed_we),
+    .wd     (intr_state_es_rct_failed_wd),
 
     // from internal hardware
-    .de     (hw2reg.intr_state.es_entropy_fifo_err.de),
-    .d      (hw2reg.intr_state.es_entropy_fifo_err.d ),
+    .de     (hw2reg.intr_state.es_rct_failed.de),
+    .d      (hw2reg.intr_state.es_rct_failed.d ),
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.intr_state.es_entropy_fifo_err.q ),
+    .q      (reg2hw.intr_state.es_rct_failed.q ),
 
     // to register interface (read)
-    .qs     (intr_state_es_entropy_fifo_err_qs)
+    .qs     (intr_state_es_rct_failed_qs)
+  );
+
+
+  //   F[es_apt_failed]: 2:2
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("W1C"),
+    .RESVAL  (1'h0)
+  ) u_intr_state_es_apt_failed (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (intr_state_es_apt_failed_we),
+    .wd     (intr_state_es_apt_failed_wd),
+
+    // from internal hardware
+    .de     (hw2reg.intr_state.es_apt_failed.de),
+    .d      (hw2reg.intr_state.es_apt_failed.d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.intr_state.es_apt_failed.q ),
+
+    // to register interface (read)
+    .qs     (intr_state_es_apt_failed_qs)
+  );
+
+
+  //   F[es_fifo_err]: 3:3
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("W1C"),
+    .RESVAL  (1'h0)
+  ) u_intr_state_es_fifo_err (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (intr_state_es_fifo_err_we),
+    .wd     (intr_state_es_fifo_err_wd),
+
+    // from internal hardware
+    .de     (hw2reg.intr_state.es_fifo_err.de),
+    .d      (hw2reg.intr_state.es_fifo_err.d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.intr_state.es_fifo_err.q ),
+
+    // to register interface (read)
+    .qs     (intr_state_es_fifo_err_qs)
   );
 
 
@@ -198,18 +293,18 @@
   );
 
 
-  //   F[es_entropy_fifo_err]: 1:1
+  //   F[es_rct_failed]: 1:1
   prim_subreg #(
     .DW      (1),
     .SWACCESS("RW"),
     .RESVAL  (1'h0)
-  ) u_intr_enable_es_entropy_fifo_err (
+  ) u_intr_enable_es_rct_failed (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
     // from register interface
-    .we     (intr_enable_es_entropy_fifo_err_we),
-    .wd     (intr_enable_es_entropy_fifo_err_wd),
+    .we     (intr_enable_es_rct_failed_we),
+    .wd     (intr_enable_es_rct_failed_wd),
 
     // from internal hardware
     .de     (1'b0),
@@ -217,10 +312,62 @@
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.intr_enable.es_entropy_fifo_err.q ),
+    .q      (reg2hw.intr_enable.es_rct_failed.q ),
 
     // to register interface (read)
-    .qs     (intr_enable_es_entropy_fifo_err_qs)
+    .qs     (intr_enable_es_rct_failed_qs)
+  );
+
+
+  //   F[es_apt_failed]: 2:2
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_intr_enable_es_apt_failed (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (intr_enable_es_apt_failed_we),
+    .wd     (intr_enable_es_apt_failed_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.intr_enable.es_apt_failed.q ),
+
+    // to register interface (read)
+    .qs     (intr_enable_es_apt_failed_qs)
+  );
+
+
+  //   F[es_fifo_err]: 3:3
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_intr_enable_es_fifo_err (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (intr_enable_es_fifo_err_we),
+    .wd     (intr_enable_es_fifo_err_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.intr_enable.es_fifo_err.q ),
+
+    // to register interface (read)
+    .qs     (intr_enable_es_fifo_err_qs)
   );
 
 
@@ -241,17 +388,47 @@
   );
 
 
-  //   F[es_entropy_fifo_err]: 1:1
+  //   F[es_rct_failed]: 1:1
   prim_subreg_ext #(
     .DW    (1)
-  ) u_intr_test_es_entropy_fifo_err (
+  ) u_intr_test_es_rct_failed (
     .re     (1'b0),
-    .we     (intr_test_es_entropy_fifo_err_we),
-    .wd     (intr_test_es_entropy_fifo_err_wd),
+    .we     (intr_test_es_rct_failed_we),
+    .wd     (intr_test_es_rct_failed_wd),
     .d      ('0),
     .qre    (),
-    .qe     (reg2hw.intr_test.es_entropy_fifo_err.qe),
-    .q      (reg2hw.intr_test.es_entropy_fifo_err.q ),
+    .qe     (reg2hw.intr_test.es_rct_failed.qe),
+    .q      (reg2hw.intr_test.es_rct_failed.q ),
+    .qs     ()
+  );
+
+
+  //   F[es_apt_failed]: 2:2
+  prim_subreg_ext #(
+    .DW    (1)
+  ) u_intr_test_es_apt_failed (
+    .re     (1'b0),
+    .we     (intr_test_es_apt_failed_we),
+    .wd     (intr_test_es_apt_failed_wd),
+    .d      ('0),
+    .qre    (),
+    .qe     (reg2hw.intr_test.es_apt_failed.qe),
+    .q      (reg2hw.intr_test.es_apt_failed.q ),
+    .qs     ()
+  );
+
+
+  //   F[es_fifo_err]: 3:3
+  prim_subreg_ext #(
+    .DW    (1)
+  ) u_intr_test_es_fifo_err (
+    .re     (1'b0),
+    .we     (intr_test_es_fifo_err_we),
+    .wd     (intr_test_es_fifo_err_wd),
+    .d      ('0),
+    .qre    (),
+    .qe     (reg2hw.intr_test.es_fifo_err.qe),
+    .q      (reg2hw.intr_test.es_fifo_err.q ),
     .qs     ()
   );
 
@@ -283,19 +460,37 @@
   );
 
 
+  // R[es_rev]: V(False)
+
+  //   F[abi_revision]: 7:0
+  // constant-only read
+  assign es_rev_abi_revision_qs = 8'h1;
+
+
+  //   F[hw_revision]: 15:8
+  // constant-only read
+  assign es_rev_hw_revision_qs = 8'h1;
+
+
+  //   F[chip_type]: 23:16
+  // constant-only read
+  assign es_rev_chip_type_qs = 8'h1;
+
+
   // R[es_conf]: V(False)
 
+  //   F[enable]: 1:0
   prim_subreg #(
-    .DW      (1),
+    .DW      (2),
     .SWACCESS("RW"),
-    .RESVAL  (1'h0)
-  ) u_es_conf (
+    .RESVAL  (2'h0)
+  ) u_es_conf_enable (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
     // from register interface (qualified with register enable)
-    .we     (es_conf_we & es_regen_qs),
-    .wd     (es_conf_wd),
+    .we     (es_conf_enable_we & es_regen_qs),
+    .wd     (es_conf_enable_wd),
 
     // from internal hardware
     .de     (1'b0),
@@ -303,26 +498,25 @@
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.es_conf.q ),
+    .q      (reg2hw.es_conf.enable.q ),
 
     // to register interface (read)
-    .qs     (es_conf_qs)
+    .qs     (es_conf_enable_qs)
   );
 
 
-  // R[es_rev]: V(False)
-
-  //   F[abi_revision]: 7:0
+  //   F[rng_src_en]: 4:4
   prim_subreg #(
-    .DW      (8),
-    .SWACCESS("RO"),
-    .RESVAL  (8'h1)
-  ) u_es_rev_abi_revision (
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_es_conf_rng_src_en (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
-    .we     (1'b0),
-    .wd     ('0  ),
+    // from register interface (qualified with register enable)
+    .we     (es_conf_rng_src_en_we & es_regen_qs),
+    .wd     (es_conf_rng_src_en_wd),
 
     // from internal hardware
     .de     (1'b0),
@@ -330,24 +524,25 @@
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.es_rev.abi_revision.q ),
+    .q      (reg2hw.es_conf.rng_src_en.q ),
 
     // to register interface (read)
-    .qs     (es_rev_abi_revision_qs)
+    .qs     (es_conf_rng_src_en_qs)
   );
 
 
-  //   F[hw_revision]: 15:8
+  //   F[rct_en]: 5:5
   prim_subreg #(
-    .DW      (8),
-    .SWACCESS("RO"),
-    .RESVAL  (8'h2)
-  ) u_es_rev_hw_revision (
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_es_conf_rct_en (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
-    .we     (1'b0),
-    .wd     ('0  ),
+    // from register interface (qualified with register enable)
+    .we     (es_conf_rct_en_we & es_regen_qs),
+    .wd     (es_conf_rct_en_wd),
 
     // from internal hardware
     .de     (1'b0),
@@ -355,24 +550,25 @@
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.es_rev.hw_revision.q ),
+    .q      (reg2hw.es_conf.rct_en.q ),
 
     // to register interface (read)
-    .qs     (es_rev_hw_revision_qs)
+    .qs     (es_conf_rct_en_qs)
   );
 
 
-  //   F[chip_type]: 23:16
+  //   F[apt_en]: 6:6
   prim_subreg #(
-    .DW      (8),
-    .SWACCESS("RO"),
-    .RESVAL  (8'h1)
-  ) u_es_rev_chip_type (
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_es_conf_apt_en (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
-    .we     (1'b0),
-    .wd     ('0  ),
+    // from register interface (qualified with register enable)
+    .we     (es_conf_apt_en_we & es_regen_qs),
+    .wd     (es_conf_apt_en_wd),
 
     // from internal hardware
     .de     (1'b0),
@@ -380,10 +576,143 @@
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.es_rev.chip_type.q ),
+    .q      (reg2hw.es_conf.apt_en.q ),
 
     // to register interface (read)
-    .qs     (es_rev_chip_type_qs)
+    .qs     (es_conf_apt_en_qs)
+  );
+
+
+  //   F[rng_bit_en]: 8:8
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_es_conf_rng_bit_en (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (es_conf_rng_bit_en_we & es_regen_qs),
+    .wd     (es_conf_rng_bit_en_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.es_conf.rng_bit_en.q ),
+
+    // to register interface (read)
+    .qs     (es_conf_rng_bit_en_qs)
+  );
+
+
+  //   F[rng_bit_sel]: 10:9
+  prim_subreg #(
+    .DW      (2),
+    .SWACCESS("RW"),
+    .RESVAL  (2'h0)
+  ) u_es_conf_rng_bit_sel (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (es_conf_rng_bit_sel_we & es_regen_qs),
+    .wd     (es_conf_rng_bit_sel_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.es_conf.rng_bit_sel.q ),
+
+    // to register interface (read)
+    .qs     (es_conf_rng_bit_sel_qs)
+  );
+
+
+  // R[es_rct_health]: V(False)
+
+  prim_subreg #(
+    .DW      (16),
+    .SWACCESS("RW"),
+    .RESVAL  (16'hb)
+  ) u_es_rct_health (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (es_rct_health_we & es_regen_qs),
+    .wd     (es_rct_health_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.es_rct_health.q ),
+
+    // to register interface (read)
+    .qs     (es_rct_health_qs)
+  );
+
+
+  // R[es_apt_health]: V(False)
+
+  //   F[apt_max]: 15:0
+  prim_subreg #(
+    .DW      (16),
+    .SWACCESS("RW"),
+    .RESVAL  (16'h298)
+  ) u_es_apt_health_apt_max (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (es_apt_health_apt_max_we & es_regen_qs),
+    .wd     (es_apt_health_apt_max_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.es_apt_health.apt_max.q ),
+
+    // to register interface (read)
+    .qs     (es_apt_health_apt_max_qs)
+  );
+
+
+  //   F[apt_win]: 31:16
+  prim_subreg #(
+    .DW      (16),
+    .SWACCESS("RW"),
+    .RESVAL  (16'h400)
+  ) u_es_apt_health_apt_win (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (es_apt_health_apt_win_we & es_regen_qs),
+    .wd     (es_apt_health_apt_win_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.es_apt_health.apt_win.q ),
+
+    // to register interface (read)
+    .qs     (es_apt_health_apt_win_qs)
   );
 
 
@@ -403,53 +732,72 @@
   );
 
 
-  // R[es_ctrl]: V(False)
+  // R[es_fifo_status]: V(True)
 
-  prim_subreg #(
-    .DW      (1),
-    .SWACCESS("RW"),
-    .RESVAL  (1'h0)
-  ) u_es_ctrl (
-    .clk_i   (clk_i    ),
-    .rst_ni  (rst_ni  ),
-
-    // from register interface (qualified with register enable)
-    .we     (es_ctrl_we & es_regen_qs),
-    .wd     (es_ctrl_wd),
-
-    // from internal hardware
-    .de     (1'b0),
-    .d      ('0  ),
-
-    // to internal hardware
+  //   F[dig_src_depth]: 2:0
+  prim_subreg_ext #(
+    .DW    (3)
+  ) u_es_fifo_status_dig_src_depth (
+    .re     (es_fifo_status_dig_src_depth_re),
+    .we     (1'b0),
+    .wd     ('0),
+    .d      (hw2reg.es_fifo_status.dig_src_depth.d),
+    .qre    (),
     .qe     (),
-    .q      (reg2hw.es_ctrl.q ),
-
-    // to register interface (read)
-    .qs     (es_ctrl_qs)
+    .q      (),
+    .qs     (es_fifo_status_dig_src_depth_qs)
   );
 
 
-  // R[es_status]: V(True)
-
+  //   F[hwif_depth]: 6:4
   prim_subreg_ext #(
-    .DW    (1)
-  ) u_es_status (
-    .re     (es_status_re),
+    .DW    (3)
+  ) u_es_fifo_status_hwif_depth (
+    .re     (es_fifo_status_hwif_depth_re),
     .we     (1'b0),
     .wd     ('0),
-    .d      (hw2reg.es_status.d),
+    .d      (hw2reg.es_fifo_status.hwif_depth.d),
     .qre    (),
     .qe     (),
-    .q      (reg2hw.es_status.q ),
-    .qs     (es_status_qs)
+    .q      (),
+    .qs     (es_fifo_status_hwif_depth_qs)
+  );
+
+
+  //   F[es_depth]: 16:12
+  prim_subreg_ext #(
+    .DW    (5)
+  ) u_es_fifo_status_es_depth (
+    .re     (es_fifo_status_es_depth_re),
+    .we     (1'b0),
+    .wd     ('0),
+    .d      (hw2reg.es_fifo_status.es_depth.d),
+    .qre    (),
+    .qe     (),
+    .q      (),
+    .qs     (es_fifo_status_es_depth_qs)
+  );
+
+
+  //   F[diag]: 31:31
+  prim_subreg_ext #(
+    .DW    (1)
+  ) u_es_fifo_status_diag (
+    .re     (es_fifo_status_diag_re),
+    .we     (1'b0),
+    .wd     ('0),
+    .d      (hw2reg.es_fifo_status.diag.d),
+    .qre    (),
+    .qe     (),
+    .q      (),
+    .qs     (es_fifo_status_diag_qs)
   );
 
 
   // R[es_fdepthst]: V(True)
 
   prim_subreg_ext #(
-    .DW    (7)
+    .DW    (3)
   ) u_es_fdepthst (
     .re     (es_fdepthst_re),
     .we     (1'b0),
@@ -457,7 +805,7 @@
     .d      (hw2reg.es_fdepthst.d),
     .qre    (),
     .qe     (),
-    .q      (reg2hw.es_fdepthst.q ),
+    .q      (),
     .qs     (es_fdepthst_qs)
   );
 
@@ -465,9 +813,9 @@
   // R[es_thresh]: V(False)
 
   prim_subreg #(
-    .DW      (7),
+    .DW      (3),
     .SWACCESS("RW"),
-    .RESVAL  (7'h0)
+    .RESVAL  (3'h0)
   ) u_es_thresh (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
@@ -481,7 +829,7 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.es_thresh.qe),
+    .qe     (),
     .q      (reg2hw.es_thresh.q ),
 
     // to register interface (read)
@@ -494,7 +842,7 @@
   prim_subreg #(
     .DW      (16),
     .SWACCESS("RW"),
-    .RESVAL  (16'h1)
+    .RESVAL  (16'h4)
   ) u_es_rate (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
@@ -508,7 +856,7 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.es_rate.qe),
+    .qe     (),
     .q      (reg2hw.es_rate.q ),
 
     // to register interface (read)
@@ -519,9 +867,9 @@
   // R[es_seed]: V(False)
 
   prim_subreg #(
-    .DW      (32),
+    .DW      (4),
     .SWACCESS("RW"),
-    .RESVAL  (32'h12345678)
+    .RESVAL  (4'hb)
   ) u_es_seed (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
@@ -535,7 +883,7 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.es_seed.qe),
+    .qe     (),
     .q      (reg2hw.es_seed.q ),
 
     // to register interface (read)
@@ -545,22 +893,23 @@
 
 
 
-  logic [12:0] addr_hit;
+  logic [13:0] addr_hit;
   always_comb begin
     addr_hit = '0;
     addr_hit[ 0] = (reg_addr == ENTROPY_SRC_INTR_STATE_OFFSET);
     addr_hit[ 1] = (reg_addr == ENTROPY_SRC_INTR_ENABLE_OFFSET);
     addr_hit[ 2] = (reg_addr == ENTROPY_SRC_INTR_TEST_OFFSET);
     addr_hit[ 3] = (reg_addr == ENTROPY_SRC_ES_REGEN_OFFSET);
-    addr_hit[ 4] = (reg_addr == ENTROPY_SRC_ES_CONF_OFFSET);
-    addr_hit[ 5] = (reg_addr == ENTROPY_SRC_ES_REV_OFFSET);
-    addr_hit[ 6] = (reg_addr == ENTROPY_SRC_ES_ENTROPY_OFFSET);
-    addr_hit[ 7] = (reg_addr == ENTROPY_SRC_ES_CTRL_OFFSET);
-    addr_hit[ 8] = (reg_addr == ENTROPY_SRC_ES_STATUS_OFFSET);
-    addr_hit[ 9] = (reg_addr == ENTROPY_SRC_ES_FDEPTHST_OFFSET);
-    addr_hit[10] = (reg_addr == ENTROPY_SRC_ES_THRESH_OFFSET);
-    addr_hit[11] = (reg_addr == ENTROPY_SRC_ES_RATE_OFFSET);
-    addr_hit[12] = (reg_addr == ENTROPY_SRC_ES_SEED_OFFSET);
+    addr_hit[ 4] = (reg_addr == ENTROPY_SRC_ES_REV_OFFSET);
+    addr_hit[ 5] = (reg_addr == ENTROPY_SRC_ES_CONF_OFFSET);
+    addr_hit[ 6] = (reg_addr == ENTROPY_SRC_ES_RCT_HEALTH_OFFSET);
+    addr_hit[ 7] = (reg_addr == ENTROPY_SRC_ES_APT_HEALTH_OFFSET);
+    addr_hit[ 8] = (reg_addr == ENTROPY_SRC_ES_ENTROPY_OFFSET);
+    addr_hit[ 9] = (reg_addr == ENTROPY_SRC_ES_FIFO_STATUS_OFFSET);
+    addr_hit[10] = (reg_addr == ENTROPY_SRC_ES_FDEPTHST_OFFSET);
+    addr_hit[11] = (reg_addr == ENTROPY_SRC_ES_THRESH_OFFSET);
+    addr_hit[12] = (reg_addr == ENTROPY_SRC_ES_RATE_OFFSET);
+    addr_hit[13] = (reg_addr == ENTROPY_SRC_ES_SEED_OFFSET);
   end
 
   assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -581,52 +930,98 @@
     if (addr_hit[10] && reg_we && (ENTROPY_SRC_PERMIT[10] != (ENTROPY_SRC_PERMIT[10] & reg_be))) wr_err = 1'b1 ;
     if (addr_hit[11] && reg_we && (ENTROPY_SRC_PERMIT[11] != (ENTROPY_SRC_PERMIT[11] & reg_be))) wr_err = 1'b1 ;
     if (addr_hit[12] && reg_we && (ENTROPY_SRC_PERMIT[12] != (ENTROPY_SRC_PERMIT[12] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[13] && reg_we && (ENTROPY_SRC_PERMIT[13] != (ENTROPY_SRC_PERMIT[13] & reg_be))) wr_err = 1'b1 ;
   end
 
   assign intr_state_es_entropy_valid_we = addr_hit[0] & reg_we & ~wr_err;
   assign intr_state_es_entropy_valid_wd = reg_wdata[0];
 
-  assign intr_state_es_entropy_fifo_err_we = addr_hit[0] & reg_we & ~wr_err;
-  assign intr_state_es_entropy_fifo_err_wd = reg_wdata[1];
+  assign intr_state_es_rct_failed_we = addr_hit[0] & reg_we & ~wr_err;
+  assign intr_state_es_rct_failed_wd = reg_wdata[1];
+
+  assign intr_state_es_apt_failed_we = addr_hit[0] & reg_we & ~wr_err;
+  assign intr_state_es_apt_failed_wd = reg_wdata[2];
+
+  assign intr_state_es_fifo_err_we = addr_hit[0] & reg_we & ~wr_err;
+  assign intr_state_es_fifo_err_wd = reg_wdata[3];
 
   assign intr_enable_es_entropy_valid_we = addr_hit[1] & reg_we & ~wr_err;
   assign intr_enable_es_entropy_valid_wd = reg_wdata[0];
 
-  assign intr_enable_es_entropy_fifo_err_we = addr_hit[1] & reg_we & ~wr_err;
-  assign intr_enable_es_entropy_fifo_err_wd = reg_wdata[1];
+  assign intr_enable_es_rct_failed_we = addr_hit[1] & reg_we & ~wr_err;
+  assign intr_enable_es_rct_failed_wd = reg_wdata[1];
+
+  assign intr_enable_es_apt_failed_we = addr_hit[1] & reg_we & ~wr_err;
+  assign intr_enable_es_apt_failed_wd = reg_wdata[2];
+
+  assign intr_enable_es_fifo_err_we = addr_hit[1] & reg_we & ~wr_err;
+  assign intr_enable_es_fifo_err_wd = reg_wdata[3];
 
   assign intr_test_es_entropy_valid_we = addr_hit[2] & reg_we & ~wr_err;
   assign intr_test_es_entropy_valid_wd = reg_wdata[0];
 
-  assign intr_test_es_entropy_fifo_err_we = addr_hit[2] & reg_we & ~wr_err;
-  assign intr_test_es_entropy_fifo_err_wd = reg_wdata[1];
+  assign intr_test_es_rct_failed_we = addr_hit[2] & reg_we & ~wr_err;
+  assign intr_test_es_rct_failed_wd = reg_wdata[1];
+
+  assign intr_test_es_apt_failed_we = addr_hit[2] & reg_we & ~wr_err;
+  assign intr_test_es_apt_failed_wd = reg_wdata[2];
+
+  assign intr_test_es_fifo_err_we = addr_hit[2] & reg_we & ~wr_err;
+  assign intr_test_es_fifo_err_wd = reg_wdata[3];
 
   assign es_regen_we = addr_hit[3] & reg_we & ~wr_err;
   assign es_regen_wd = reg_wdata[0];
 
-  assign es_conf_we = addr_hit[4] & reg_we & ~wr_err;
-  assign es_conf_wd = reg_wdata[0];
 
 
 
+  assign es_conf_enable_we = addr_hit[5] & reg_we & ~wr_err;
+  assign es_conf_enable_wd = reg_wdata[1:0];
 
-  assign es_entropy_re = addr_hit[6] && reg_re;
+  assign es_conf_rng_src_en_we = addr_hit[5] & reg_we & ~wr_err;
+  assign es_conf_rng_src_en_wd = reg_wdata[4];
 
-  assign es_ctrl_we = addr_hit[7] & reg_we & ~wr_err;
-  assign es_ctrl_wd = reg_wdata[0];
+  assign es_conf_rct_en_we = addr_hit[5] & reg_we & ~wr_err;
+  assign es_conf_rct_en_wd = reg_wdata[5];
 
-  assign es_status_re = addr_hit[8] && reg_re;
+  assign es_conf_apt_en_we = addr_hit[5] & reg_we & ~wr_err;
+  assign es_conf_apt_en_wd = reg_wdata[6];
 
-  assign es_fdepthst_re = addr_hit[9] && reg_re;
+  assign es_conf_rng_bit_en_we = addr_hit[5] & reg_we & ~wr_err;
+  assign es_conf_rng_bit_en_wd = reg_wdata[8];
 
-  assign es_thresh_we = addr_hit[10] & reg_we & ~wr_err;
-  assign es_thresh_wd = reg_wdata[6:0];
+  assign es_conf_rng_bit_sel_we = addr_hit[5] & reg_we & ~wr_err;
+  assign es_conf_rng_bit_sel_wd = reg_wdata[10:9];
 
-  assign es_rate_we = addr_hit[11] & reg_we & ~wr_err;
+  assign es_rct_health_we = addr_hit[6] & reg_we & ~wr_err;
+  assign es_rct_health_wd = reg_wdata[15:0];
+
+  assign es_apt_health_apt_max_we = addr_hit[7] & reg_we & ~wr_err;
+  assign es_apt_health_apt_max_wd = reg_wdata[15:0];
+
+  assign es_apt_health_apt_win_we = addr_hit[7] & reg_we & ~wr_err;
+  assign es_apt_health_apt_win_wd = reg_wdata[31:16];
+
+  assign es_entropy_re = addr_hit[8] && reg_re;
+
+  assign es_fifo_status_dig_src_depth_re = addr_hit[9] && reg_re;
+
+  assign es_fifo_status_hwif_depth_re = addr_hit[9] && reg_re;
+
+  assign es_fifo_status_es_depth_re = addr_hit[9] && reg_re;
+
+  assign es_fifo_status_diag_re = addr_hit[9] && reg_re;
+
+  assign es_fdepthst_re = addr_hit[10] && reg_re;
+
+  assign es_thresh_we = addr_hit[11] & reg_we & ~wr_err;
+  assign es_thresh_wd = reg_wdata[2:0];
+
+  assign es_rate_we = addr_hit[12] & reg_we & ~wr_err;
   assign es_rate_wd = reg_wdata[15:0];
 
-  assign es_seed_we = addr_hit[12] & reg_we & ~wr_err;
-  assign es_seed_wd = reg_wdata[31:0];
+  assign es_seed_we = addr_hit[13] & reg_we & ~wr_err;
+  assign es_seed_wd = reg_wdata[3:0];
 
   // Read data return
   always_comb begin
@@ -634,17 +1029,23 @@
     unique case (1'b1)
       addr_hit[0]: begin
         reg_rdata_next[0] = intr_state_es_entropy_valid_qs;
-        reg_rdata_next[1] = intr_state_es_entropy_fifo_err_qs;
+        reg_rdata_next[1] = intr_state_es_rct_failed_qs;
+        reg_rdata_next[2] = intr_state_es_apt_failed_qs;
+        reg_rdata_next[3] = intr_state_es_fifo_err_qs;
       end
 
       addr_hit[1]: begin
         reg_rdata_next[0] = intr_enable_es_entropy_valid_qs;
-        reg_rdata_next[1] = intr_enable_es_entropy_fifo_err_qs;
+        reg_rdata_next[1] = intr_enable_es_rct_failed_qs;
+        reg_rdata_next[2] = intr_enable_es_apt_failed_qs;
+        reg_rdata_next[3] = intr_enable_es_fifo_err_qs;
       end
 
       addr_hit[2]: begin
         reg_rdata_next[0] = '0;
         reg_rdata_next[1] = '0;
+        reg_rdata_next[2] = '0;
+        reg_rdata_next[3] = '0;
       end
 
       addr_hit[3]: begin
@@ -652,41 +1053,54 @@
       end
 
       addr_hit[4]: begin
-        reg_rdata_next[0] = es_conf_qs;
-      end
-
-      addr_hit[5]: begin
         reg_rdata_next[7:0] = es_rev_abi_revision_qs;
         reg_rdata_next[15:8] = es_rev_hw_revision_qs;
         reg_rdata_next[23:16] = es_rev_chip_type_qs;
       end
 
+      addr_hit[5]: begin
+        reg_rdata_next[1:0] = es_conf_enable_qs;
+        reg_rdata_next[4] = es_conf_rng_src_en_qs;
+        reg_rdata_next[5] = es_conf_rct_en_qs;
+        reg_rdata_next[6] = es_conf_apt_en_qs;
+        reg_rdata_next[8] = es_conf_rng_bit_en_qs;
+        reg_rdata_next[10:9] = es_conf_rng_bit_sel_qs;
+      end
+
       addr_hit[6]: begin
-        reg_rdata_next[31:0] = es_entropy_qs;
+        reg_rdata_next[15:0] = es_rct_health_qs;
       end
 
       addr_hit[7]: begin
-        reg_rdata_next[0] = es_ctrl_qs;
+        reg_rdata_next[15:0] = es_apt_health_apt_max_qs;
+        reg_rdata_next[31:16] = es_apt_health_apt_win_qs;
       end
 
       addr_hit[8]: begin
-        reg_rdata_next[0] = es_status_qs;
+        reg_rdata_next[31:0] = es_entropy_qs;
       end
 
       addr_hit[9]: begin
-        reg_rdata_next[6:0] = es_fdepthst_qs;
+        reg_rdata_next[2:0] = es_fifo_status_dig_src_depth_qs;
+        reg_rdata_next[6:4] = es_fifo_status_hwif_depth_qs;
+        reg_rdata_next[16:12] = es_fifo_status_es_depth_qs;
+        reg_rdata_next[31] = es_fifo_status_diag_qs;
       end
 
       addr_hit[10]: begin
-        reg_rdata_next[6:0] = es_thresh_qs;
+        reg_rdata_next[2:0] = es_fdepthst_qs;
       end
 
       addr_hit[11]: begin
-        reg_rdata_next[15:0] = es_rate_qs;
+        reg_rdata_next[2:0] = es_thresh_qs;
       end
 
       addr_hit[12]: begin
-        reg_rdata_next[31:0] = es_seed_qs;
+        reg_rdata_next[15:0] = es_rate_qs;
+      end
+
+      addr_hit[13]: begin
+        reg_rdata_next[3:0] = es_seed_qs;
       end
 
       default: begin
diff --git a/hw/ip/entropy_src/rtl/entropy_src_shtests.sv b/hw/ip/entropy_src/rtl/entropy_src_shtests.sv
new file mode 100755
index 0000000..7c3cd0e
--- /dev/null
+++ b/hw/ip/entropy_src/rtl/entropy_src_shtests.sv
@@ -0,0 +1,138 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Description: entropy_src health tests module
+//
+
+module entropy_src_shtests (
+  input                  clk_i,
+  input                  rst_ni,
+
+   // ins req interface
+  input logic            entropy_bit_i,
+  input logic            entropy_bit_vld_i,
+  input logic            rct_active_i,
+  input logic [15:0]     rct_max_cnt_i,
+  input logic            apt_active_i,
+  input logic [15:0]     apt_max_cnt_i,
+  input logic [15:0]     apt_window_i,
+  output logic           rct_fail_pls_o,
+  output logic           apt_fail_pls_o,
+  output logic           shtests_passing_o
+);
+
+  // signals
+  logic rct_samples_match;
+  logic rct_fail;
+  logic rct_pass;
+  logic apt_reset_test;
+  logic apt_samples_match;
+  logic apt_fail;
+  logic apt_pass;
+
+
+  // flops
+  logic        rct_prev_sample_q, rct_prev_sample_d;
+  logic [15:0] rct_rep_cntr_q, rct_rep_cntr_d;
+  logic        apt_initial_sample_q, apt_initial_sample_d;
+  logic [15:0] apt_sample_cntr_q, apt_sample_cntr_d;
+  logic [15:0] apt_match_cntr_q, apt_match_cntr_d;
+  logic        rct_passing_q, rct_passing_d;
+  logic        apt_passing_q, apt_passing_d;
+
+  always_ff @(posedge clk_i or negedge rst_ni)
+    if (!rst_ni) begin
+      rct_prev_sample_q     <= '0;
+      rct_rep_cntr_q        <= '0;
+      apt_initial_sample_q  <= '0;
+      apt_sample_cntr_q     <= '0;
+      apt_match_cntr_q      <= '0;
+      rct_passing_q    <= '0;
+      apt_passing_q    <= '0;
+    end else begin
+      rct_prev_sample_q     <= rct_prev_sample_d;
+      rct_rep_cntr_q        <= rct_rep_cntr_d;
+      apt_initial_sample_q  <= apt_initial_sample_d;
+      apt_sample_cntr_q     <= apt_sample_cntr_d;
+      apt_match_cntr_q      <= apt_match_cntr_d;
+      rct_passing_q    <= rct_passing_d;
+      apt_passing_q    <= apt_passing_d;
+    end
+
+
+
+  // Repetition Count Test (RCT)
+  //
+  // Point of test
+  //  check for back to back patterns up to a
+  //  limit, fail if it does
+
+
+  // NIST A sample
+  assign rct_prev_sample_d = ~rct_active_i ? 1'b0 :
+         (entropy_bit_vld_i & (rct_rep_cntr_q == 16'h0001)) ? entropy_bit_i :
+         rct_prev_sample_q;
+
+  assign rct_samples_match = (rct_prev_sample_q == (entropy_bit_vld_i & entropy_bit_i));
+
+  // NIST B counter
+  assign rct_rep_cntr_d =
+         ~rct_active_i ? 16'h0001 :
+         rct_fail ? 16'h0001 :
+         (entropy_bit_vld_i & rct_samples_match) ? (rct_rep_cntr_q+1) :
+         rct_pass ? 16'h0001 :
+         rct_rep_cntr_q;
+
+  assign rct_pass = rct_active_i & (entropy_bit_vld_i & ~rct_samples_match);
+  assign rct_fail = rct_active_i & (rct_rep_cntr_q >= rct_max_cnt_i);
+  assign rct_fail_pls_o = rct_fail;
+
+  assign rct_passing_d =
+         ~rct_active_i ? 1'b1 :
+         rct_fail ? 1'b0 :
+         rct_pass ? 1'b1 :
+         rct_passing_q;
+
+
+  // Adaptive Proportion Test (APT)
+  //
+  // Point of test
+  //  sample once, then check for period of time if
+  //  that pattern appears again, fail if it does
+
+
+  // NIST N value
+  assign apt_reset_test = ~apt_active_i | apt_fail | (apt_sample_cntr_q >= apt_window_i);
+
+  // NIST A counter
+  assign apt_initial_sample_d =
+         ((apt_sample_cntr_q == 16'h0000) & entropy_bit_vld_i) ? entropy_bit_i :
+         apt_initial_sample_q;
+
+  // NIST S counter
+  assign apt_sample_cntr_d = apt_reset_test ? 16'b0 :
+         entropy_bit_vld_i ? (apt_sample_cntr_q+1) :
+         apt_sample_cntr_q;
+
+  assign apt_samples_match = entropy_bit_vld_i & (apt_initial_sample_q == entropy_bit_i);
+
+  // NIST B counter
+  assign apt_match_cntr_d = apt_reset_test ? 16'b0 :
+         (entropy_bit_vld_i & apt_samples_match) ? (apt_match_cntr_q+1) :
+         apt_match_cntr_q;
+
+  assign apt_pass = (apt_sample_cntr_q >= apt_window_i);
+  assign apt_fail = apt_active_i & (apt_match_cntr_q >= apt_max_cnt_i);
+  assign apt_fail_pls_o = apt_fail;
+
+  assign apt_passing_d =
+         ~apt_active_i ? 1'b1 :
+         apt_fail ? 1'b0 :
+         apt_pass ? 1'b1 :
+         apt_passing_q;
+
+  // tests summary
+  assign shtests_passing_o = rct_passing_q && apt_passing_q;
+
+endmodule