[entropy_src/doc] initial version of doc
Signed-off-by: Mark Branstad <mark.branstad@wdc.com>
diff --git a/hw/_index.md b/hw/_index.md
index c29a11c..ce0414b 100644
--- a/hw/_index.md
+++ b/hw/_index.md
@@ -17,7 +17,7 @@
|--------|-------------|---------|
| `aes` | [design spec]({{< relref "hw/ip/aes/doc" >}}) | [DV plan]({{< relref "hw/ip/aes/doc/dv_plan" >}}) |
| `alert_handler` | [design spec]({{< relref "hw/ip/alert_handler/doc" >}}) | [DV plan]({{< relref "hw/ip/alert_handler/doc/dv_plan" >}}) |
-| `entropy_src` | | |
+| `entropy_src` | [design spec]({{< relref "hw/ip/entropy_src/doc" >}}) | |
| `flash_ctrl` | [design spec]({{< relref "hw/ip/flash_ctrl/doc" >}}) | |
| `gpio` | [design spec]({{< relref "hw/ip/gpio/doc" >}}) | [DV plan]({{< relref "hw/ip/gpio/doc/dv_plan" >}}) |
| `hmac` | [design spec]({{< relref "hw/ip/hmac/doc" >}}) | [DV plan]({{< relref "hw/ip/hmac/doc/dv_plan" >}}) |
diff --git a/hw/ip/entropy_src/data/entropy_src.hjson b/hw/ip/entropy_src/data/entropy_src.hjson
new file mode 100755
index 0000000..034df59
--- /dev/null
+++ b/hw/ip/entropy_src/data/entropy_src.hjson
@@ -0,0 +1,166 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+{ name: "entropy_src",
+ clock_primary: "clk_i",
+ bus_device: "tlul",
+ bus_host: "none",
+ param_list: [
+ { name: "EsFifoDepth",
+ desc: "Depth of the entropy FIFO",
+ type: "int",
+ default: "32",
+ local: "true"
+ },
+ ],
+ interrupt_list: [
+ { name: "es_entropy_valid"
+ desc: "Asserted when entropy source bits are available."}
+ { name: "es_entropy_fifo_err"
+ desc: "Asserted when a FIFO error occurs."}
+ ],
+ regwidth: "32",
+ registers: [
+ { name: "ES_REGEN",
+ desc: "Register write enable for all control registers",
+ swaccess: "rw1c",
+ hwaccess: "hro",
+ fields: [
+ {
+ bits: "0",
+ desc: ''' When true, the ES_CONF, ES_CTRL, and ES_SEED registers can be modified.
+ When false, they become read-only. Defaults true, write one to clear. Note that this needs to be
+ cleared after initial configuration at boot in order to lock in the listed register settings.
+ '''
+ resval: 1
+ },
+ ]
+ },
+ { name: "ES_CONF",
+ desc: "ENTROPY_SRC configuration register",
+ swaccess: "rw",
+ hwaccess: "hro",
+ regwen: "ES_REGEN",
+ fields: [
+ { bits: "0",
+ name: "ENABLE",
+ desc: "Master enable for the ENTROPY_SRC entropy generation function."
+ }
+ ]
+ },
+ { name: "ES_REV",
+ desc: "ENTROPY_SRC revision register",
+ swaccess: "ro",
+ hwaccess: "hro",
+ fields: [
+ { bits: "23:16",
+ name: "CHIP_TYPE",
+ desc: "Read of this register shows the type of chip using this block.",
+ resval: "0x1"
+ }
+ { bits: "15:8",
+ name: "HW_REVISION",
+ desc: "Read of this register shows the revision of this block.",
+ resval: "0x2"
+ }
+ { bits: "7:0",
+ name: "ABI_REVISION",
+ desc: "Read of this register shows the ABI of this block.",
+ resval: "0x1"
+ }
+ ]
+ },
+ { name: "ES_ENTROPY",
+ desc: "ENTROPY_SRC entropy source",
+ swaccess: "ro",
+ hwaccess: "hrw",
+ hwext: "true",
+ hwre: "true",
+ fields: [
+ { bits: "31:0",
+ desc: "A read of this register provides entropy needed for an entropy source."
+ }
+ ]
+ },
+ { name: "ES_CTRL",
+ desc: "ENTROPY_SRC control register",
+ swaccess: "rw",
+ hwaccess: "hro",
+ regwen: "ES_REGEN",
+ fields: [
+ { bits: "0",
+ name: "INIT_ENT_SRC",
+ desc: "Setting this bit will initialize the entropy source function."
+ }
+ ]
+ },
+ { name: "ES_STATUS",
+ desc: "ENTROPY_SRC status register",
+ swaccess: "ro",
+ hwaccess: "hrw",
+ hwext: "true",
+ fields: [
+ { bits: "0",
+ name: "ENTROPY_RDY",
+ desc: '''This is set when the entropy source FIFO has met or exceeded the ES_THRESH value. This status bit will
+ automatically clear once the FIFO depth drops below the threshold value. This bit will not set unless the
+ block is enabled.
+ '''
+ }
+ ]
+ },
+ { name: "ES_FDEPTHST",
+ desc: "ENTROPY_SRC FIFO depth status register",
+ swaccess: "ro",
+ hwaccess: "hrw",
+ hwext: "true",
+ fields: [
+ { bits: "6:0",
+ name: "ENTROPY_FIFO_DEPTH",
+ desc: "This register will reflect the current depth of the entropy FIFO."
+ }
+ ]
+ },
+ { name: "ES_THRESH",
+ desc: "ENTROPY_SRC threshold register",
+ swaccess: "rw",
+ hwqe: "true",
+ fields: [
+ { bits: "6:0",
+ name: "FIFO_THRESHOLD",
+ desc: "The entropy FIFO depth will be compared against this register value when setting the ENTROPY_RDY bit and es_entropy_valid interrupt signal."
+ }
+ ]
+ }
+ { name: "ES_RATE",
+ desc: "ENTROPY_SRC entropy rate register",
+ swaccess: "rw",
+ hwqe: "true",
+ fields: [
+ { bits: "15:0",
+ name: "ENTROPY_RATE",
+ desc: '''This register determines the rate that entropy bits will be supplied. Its purpose to is simulate slow entropy sources.
+ A value of 1 will deliver full rate entropy. A value of 2 will cut a full entropy source in half. A value of 8 will cut
+ the rate by 1/8th. The precise equation for entropy delivery is one clock cycle of entropy is generated
+ every 1/(ENTROPY_RATE) equal to one. A value of 0 disables all entropy generation.
+ '''
+ resval: "0x00000001"
+ }
+ ]
+ }
+ { name: "ES_SEED",
+ desc: "ENTROPY_SRC seed register",
+ swaccess: "rw",
+ hwqe: "true",
+ regwen: "ES_REGEN",
+ fields: [
+ { bits: "31:0",
+ name: "LFSR_SEED",
+ desc: "Seed used to load into the LFSR for the initial state. This field will not update if the ES_REGEN bit 0 is cleared.",
+ resval: "0x12345678"
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/hw/ip/entropy_src/doc/_index.md b/hw/ip/entropy_src/doc/_index.md
new file mode 100755
index 0000000..d0a9484
--- /dev/null
+++ b/hw/ip/entropy_src/doc/_index.md
@@ -0,0 +1,212 @@
+---
+title: "ENTROPY_SRC HWIP Technical Specification"
+---
+
+# Overview
+
+This document specifies ENTROPY_SRC hardware IP functionality.
+This module conforms to the [Comportable guideline for peripheral functionality.]({{< relref "doc/rm/comportability_specification" >}})
+
+
+## Features
+
+- The initial revision only supports an entropy source in the form of an LFSR (linear feedback shift register).
+This is a pseudo-random type of entropy source, as opposed to a truly random entropy source.
+A noise source and its relation to an entropy source are defined by [SP 800-90B](https://csrc.nist.gov/publications/detail/sp/800-90b/final).
+- A set of registers is provided for firmware to manage and obtain entropy bits.
+- The set of registers is designed such that firmware should not have to change for the case where a random source of entropy is provided in a future revision.
+- Interrupts are supported:
+ - Entropy bits are available.
+ - An internal error has occurred.
+- No SP 800-90B defined health checks are done by this revision (these functions are left for the firmware to implement).
+- No alerts are supported by this revision.
+
+
+## Description
+
+This IP block provides an entropy source that is part of a larger solution to generate true random numbers (a TRNG mechanism).
+The general solution for TRNG relies on firmware to orchestrate the majority of the function, getting helper services from specific hardware blocks.
+For purposes of reference in this document, the NIST term "noise" will be synonymous with the term "entropy".
+Likewise, no conditioning function will be performed in this block.
+For the generation of entropy, this block provides the entropy bits needed for the entropy source solution as required by the firmware.
+
+At a high-level, this ENTROPY_SRC block, when enabled, will continuously collect entropy bits from the entropy source into a FIFO that can be read from the TLUL bus.
+For this revision, the entropy generation can be very fast, based on programming.
+Other sources could be much slower.
+The support logic in the block will support entropy sources of any rate.
+
+Once the required number of entropy bits have been collected, the firmware has two options of notification: an interrupt, or polling.
+For this revision, the `ENTROPY_RDY` bit will always be set if the {{< regref "ES_THRESH" >}} register is configured to a low value, so a firmware scheme of just reading the status bit to confirm that entropy is available is a good strategy.
+For slower sources, an interrupt may be a better use of CPU cycles.
+
+## Compatibility
+This IP block does not have any direct hardware compatibility requirements.
+The firmware routines, as described by SP 800-90B, must be supported.
+However, as long as the function provided by the register set supports all of the call parameters, any compatibility requirements will be met.
+
+# Theory of Operations
+
+As already described, this IP block will collect bits of entropy for firmware consumption.
+This revision is a straightforward implementation using an LFSR.
+In principal, any polynomial may be used so long as it is primitive in Galois Field of order 2, or GF(2).
+However, preference should be given to polynomials with the fewest number of terms.
+
+The first step is enabling and initialization.
+The main difference between these steps is that enabling is a global block enable.
+The initialization step can be done at anytime while the block is enabled and running.
+Before setting the `ENABLE` bit, the LFSR seed input should be initialized, using the {{< regref "ES_SEED" >}} register.
+The {{< regref "ES_SEED" >}} register will transfer its value according to the initialization sequence.
+After the block is enabled and initialized, entropy bits will be collected up indefinitely until disabled.
+
+It is assumed that any entropy source will drop bits.
+This means that the FIFO used to collect up the entropy bits will fill, and until the firmware starts pulling out bits, continuously generated entropy source bits may be dropped from usage.
+The process of filling and draining the FIFO is the same, independent of what speed the entropy generation rate is at.
+
+Once the `ENTROPY_RDY` status bit is set, the firmware will read the {{< regref "ES_ENTROPY" >}} register as many times as needed to get the required entropy bits, typically 128 bits or 256 bits at a time.
+For ease of firmware operation, the status bit does not need to be reset.
+A read of the {{< regref "ES_THRESH" >}} register could be done to verify how many entries are in the FIFO at the current time.
+The {{< regref "ES_THRESH" >}} register will determine when the status bit is set, or when the interrupt will assert if enabled.
+For this revision, this same {{< regref "ES_THRESH" >}} register has a range of between 1 and 32 entries in the FIFO.
+An RTL parameter can be set to make this range smaller and save on gate count.
+
+The above process will be repeated for as long as entropy bits are to be collected.
+At any time, the enable bit can be cleared, and the entropy generation will halt immediately.
+
+
+## Block Diagram
+
+
+
+## Hardware Interfaces
+
+{{< hwcfg "hw/ip/entropy_src/data/entropy_src.hjson" >}}
+
+## Design Details
+
+### Initialization
+
+After power-up, the ENTROPY_SRC block is disabled.
+In this state, the seed register will continuously be loaded into the LFSR.
+The seed register can be written without restriction, regardless of any state of any control bits.
+Once the `ENABLE` bit is set, subsequent loads of the seed into the LFSR will occur only when the `INIT_ENT_SRC` bit is set, and the state of the FIFO is full.
+The intent for this is that the FIFO is in a safe state, and any attempted seed updates to the LFSR will be ignored.
+
+A configuration/control register locking function is performed by the {{< regref "ES_REGEN" >}} register.
+Clearing the bit in this register will prevent future modification of the {{< regref "ES_CONF" >}} register, the {{< regref "ES_CTRL" >}} register, or the {{< regref "ES_SEED" >}} by firmware.
+
+The {{< regref "ES_SEED" >}} register can be updated at any time while the entropy FIFO is in operational mode.
+As long as the update sequence is followed by firmware, there will be no timing hazards when accessing these registers by the firmware.
+
+### Entropy Processing
+
+When enabled, the ENTROPY_SRC block will generate entropy bits continuously.
+The `ENTROPY_RDY` bit in the {{< regref "ES_STATUS" >}} register will signal to the firmware when entropy bits should read from the {{< regref "ES_ENTROPY" >}} register.
+While the firmware is reading the FIFO, additional entropy bits could be captured by the FIFO as long as the FIFO is not full.
+The firmware will do 32-bit register reads of the {{< regref "ES_ENTROPY" >}} register to retrieve the entropy bits.
+Each read will automatically pop an entry off the head of the FIFO.
+New entropy bits can enter the FIFO at the tail concurrently.
+
+Since the entropy flow is continuous, these is no tracking state machine required for the design.
+Instead, the {{< regref "ES_THRESH" >}} register is used to set the point of notification to the firmware.
+Notification can be either by polling or by an interrupt.
+For debug, the {{< regref "ES_FDEPTHST" >}} register can be read to find out the current state of the FIFO at any time.
+
+An additional feature is the {{< regref "ES_RATE" >}} register.
+The purpose of this register is to simulate slower entropy generation sources.
+This will aid firmware design and debug when trying to handle all entropy source types and rates.
+
+### Interrupts
+
+The ENTROPY_SRC module has two interrupts: `es_entropy_valid` and `es_entropy_fifo_err`.
+
+The `es_entropy_valid` interrupt should be used when a entropy source has been implemented that is relatively slow.
+For this revision, the entropy source can be very fast (at full rate), and polling the `ENTROPY_RDY` status bit should be done.
+
+The `es_entropy_fifo_err` interrupt will fire when the entropy FIFO has a malfunction.
+The conditions that cause this to happen are either when there is a push to a full FIFO or a pull from an empty FIFO.
+
+### Entropy FIFO Operational Sequence
+The following waveform show an example of how the entropy source is collected into the entropy FIFO.
+In this example, the FIFO parameter is set to a depth of 4. The {{< regref "ES_THRESH" >}} register is set to a value of 2, and will trigger an interrupt when the FIFO has met this value.
+The FIFO in this example will fill quickly, then will drain as the firmware reads the {{< regref "ES_ENTROPY" >}} register. As the entropy bits are read out, new entropy bits, if available and valid, will immediately enter the FIFO.
+
+
+{{< wavejson >}}
+{signal: [
+ {name: 'clk' , wave: 'p.......|............'},
+ {name: 'es_enable' , wave: '01......|............'},
+ {name: 'es_init' , wave: '010.....|............'},
+ {name: 'fifo_push_capt_entropy', wave: '0..1...0|.10.10.10.10', data: ['ph0','ph1','ph2','ph3']},
+ {name: 'entropy_bits' , wave: 'x..3453x|.4x.5x.3x.4x', data: ['es0','es1','es2','es3','es4','es5','es6','es7']},
+ {name: 'fifo_full' , wave: '0......1|.01.01.01.01'},
+ {name: 'fifo_empty' , wave: '1..0....|............'},
+ {name: 'fifo_pop_read_entropy' , wave: '0.......|10.10.10.10.'},
+ {name: 'threshold reg' , wave: '4.......|............', data: ['2']},
+ {name: 'interrupt/status' , wave: '0....1..|............'},
+ {},
+]}{{< /wavejson >}}
+
+
+# Programmers Guide
+
+## Initialization
+
+The following code snippet demonstrates initializing the ENTROPY_SRC block for entropy bit generation.
+
+```cpp
+
+void entropy_src_init(unsigned int seed) {
+
+ // set the seed value
+ *ES_SEED_REG = seed;
+
+ // set the configuration enable bit
+ *ES_CONF_REG = 0x1;
+
+ // the ENTROPY_SRC interrupts can optionally be enabled
+}
+```
+
+## Entropy Processing
+
+The following code snippet demonstrates reading entropy bits from the ENTROPY_SRC block.
+
+```cpp
+
+int entropy_src_entropy(unsigned int numEntropyBits) {
+
+ // read numEntropyBits, check for ES_STATUS bit 0 (ENTROPY_RDY)
+ return *ES_ENTROPY_REG;
+
+}
+```
+
+## Update Seed
+
+The following code snippet demonstrates initializing the ENTROPY_SRC block for updating the seed after initialization has been done.
+
+```cpp
+
+void entropy_src_seed_update(unsigned int seed) {
+
+ // set the seed value
+ *ES_SEED_REG = seed;
+
+ // set the control initialization bit
+ *ES_CTRL_REG = 0x1;
+
+ // reset the control initialization bit
+ *ES_CTRL_REG = 0x0;
+
+}
+```
+
+## Error conditions
+
+Need to alert the system of a FIFO overflow condition.
+
+
+## Register Table
+
+
+{{< registers "hw/ip/entropy_src/data/entropy_src.hjson" >}}
diff --git a/hw/ip/entropy_src/doc/entsrc_blk_diag.svg b/hw/ip/entropy_src/doc/entsrc_blk_diag.svg
new file mode 100755
index 0000000..90e31b1
--- /dev/null
+++ b/hw/ip/entropy_src/doc/entsrc_blk_diag.svg
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by Microsoft Visio, SVG Export entsrc_blk_diag.svg Page-1 -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
+ xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="11in" height="8.5in" viewBox="0 0 792 612"
+ xml:space="preserve" color-interpolation-filters="sRGB" class="st16">
+ <v:documentProperties v:langID="1033" v:viewMarkup="false">
+ <v:userDefs>
+ <v:ud v:nameU="msvSubprocessMaster" v:prompt="" v:val="VT4(Rectangle)"/>
+ <v:ud v:nameU="msvNoAutoConnect" v:val="VT0(1):26"/>
+ </v:userDefs>
+ </v:documentProperties>
+
+ <style type="text/css">
+ <![CDATA[
+ .st1 {fill:#ffffff;stroke:#000000;stroke-width:0.25}
+ .st2 {fill:#000000;font-family:Calibri;font-size:0.833336em}
+ .st3 {fill:none;stroke:none;stroke-width:0.25}
+ .st4 {font-size:1em}
+ .st5 {marker-end:url(#mrkr13-22);marker-start:url(#mrkr13-20);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.25}
+ .st6 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.47169811320755}
+ .st7 {marker-start:url(#mrkr5-31);stroke:#000000;stroke-width:0.75}
+ .st8 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.22935779816514}
+ .st9 {marker-end:url(#mrkr5-37);stroke:#000000;stroke-width:2.25}
+ .st10 {marker-end:url(#mrkr5-37);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.25}
+ .st11 {stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.25}
+ .st12 {marker-end:url(#mrkr5-76);stroke:#000000;stroke-width:0.75}
+ .st13 {stroke:#000000;stroke-width:2.25}
+ .st14 {marker-end:url(#mrkr5-130);stroke:#e8ebf4;stroke-width:0.75}
+ .st15 {fill:#e8ebf4;fill-opacity:1;stroke:#e8ebf4;stroke-opacity:1;stroke-width:0.22935779816514}
+ .st16 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+ ]]>
+ </style>
+
+ <defs id="Markers">
+ <g id="lend13">
+ <path d="M 3 1 L 0 0 L 3 -1 L 3 1 " style="stroke:none"/>
+ </g>
+ <marker id="mrkr13-20" class="st6" v:arrowType="13" v:arrowSize="2" v:setback="6.2" refX="6.2" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend13" transform="scale(2.12) "/>
+ </marker>
+ <marker id="mrkr13-22" class="st6" v:arrowType="13" v:arrowSize="2" v:setback="6.36" refX="-6.36" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend13" transform="scale(-2.12,-2.12) "/>
+ </marker>
+ <g id="lend5">
+ <path d="M 2 1 L 0 0 L 1.98117 -0.993387 C 1.67173 -0.364515 1.67301 0.372641 1.98465 1.00043 " style="stroke:none"/>
+ </g>
+ <marker id="mrkr5-31" class="st8" v:arrowType="5" v:arrowSize="2" v:setback="7.15" refX="7.15" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(4.36) "/>
+ </marker>
+ <marker id="mrkr5-37" class="st6" v:arrowType="5" v:arrowSize="2" v:setback="3.71" refX="-3.71" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-2.12,-2.12) "/>
+ </marker>
+ <marker id="mrkr5-76" class="st8" v:arrowType="5" v:arrowSize="2" v:setback="7.63" refX="-7.63" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-4.36,-4.36) "/>
+ </marker>
+ <marker id="mrkr5-130" class="st15" v:arrowType="5" v:arrowSize="2" v:setback="7.63" refX="-7.63" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-4.36,-4.36) "/>
+ </marker>
+ </defs>
+ <g v:mID="0" v:index="1" v:groupContext="foregroundPage">
+ <v:userDefs>
+ <v:ud v:nameU="msvThemeOrder" v:val="VT0(0):26"/>
+ </v:userDefs>
+ <title>Page-1</title>
+ <v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
+ <v:layer v:name="Flowchart" v:index="0"/>
+ <g id="shape480-1" v:mID="480" v:groupContext="shape" transform="translate(121.5,-135)">
+ <title>Sheet.480</title>
+ <desc>Registers</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="71.7998" cy="396" width="143.6" height="432"/>
+ <rect x="0" y="180" width="143.6" height="432" class="st1"/>
+ <text x="53.28" y="193" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Registers</text> </g>
+ <g id="shape484-4" v:mID="484" v:groupContext="shape" transform="translate(165.854,-318.255)">
+ <title>Sheet.484</title>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <rect x="0" y="551.545" width="99.2459" height="60.4551" class="st3"/>
+ </g>
+ <g id="shape490-6" v:mID="490" v:groupContext="shape" transform="translate(165.854,-402.75)">
+ <title>Sheet.490</title>
+ <desc>es_cntrl.q es_conf.q es_seed.q es_rate.q es_threshold.q</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="49.6229" cy="561.375" width="99.25" height="101.25"/>
+ <rect x="0" y="510.75" width="99.2459" height="101.25" class="st3"/>
+ <text x="54.99" y="559.75" class="st2" v:langID="1033"><v:paragraph v:horizAlign="2"/><v:tabList/><v:space/><v:newlineChar/><v:newlineChar/><v:newlineChar/>es_cntrl.q<tspan
+ x="53.53" dy="1.2em" class="st4"> </tspan>es_conf.q<tspan x="52.22" dy="1.2em" class="st4"> </tspan>es_seed.q<tspan
+ x="54.74" dy="1.2em" class="st4"> </tspan>es_rate.q<tspan x="32.29" dy="1.2em" class="st4"> </tspan>es_threshold.q<tspan
+ dy="1.2em" class="st4"> </tspan><v:newlineChar/> </text> </g>
+ <g id="shape491-14" v:mID="491" v:groupContext="shape" transform="translate(65.6742,-468)">
+ <title>Sheet.491</title>
+ <path d="M13.95 612 L14.31 612 L41.52 612" class="st5"/>
+ </g>
+ <g id="shape492-23" v:mID="492" v:groupContext="shape" transform="translate(121.5,-419.772)">
+ <title>Sheet.492</title>
+ <desc>TLUL Interface</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="49.6229" cy="581.772" width="99.25" height="60.4551"/>
+ <rect x="0" y="551.545" width="99.2459" height="60.4551" class="st3"/>
+ <text x="6.26" y="564.55" class="st2" v:langID="1033"><v:paragraph/><v:tabList/>TLUL Interface<v:newlineChar/></text> </g>
+ <g id="shape498-26" v:mID="498" v:groupContext="shape" transform="translate(265.5,765.184) scale(1,-1)">
+ <title>Sheet.498</title>
+ <path d="M161.14 612 L160.78 612 L55.83 612 L0 612" class="st7"/>
+ </g>
+ <g id="shape500-32" v:mID="500" v:groupContext="shape" transform="translate(265.5,-434.996)">
+ <title>Sheet.500</title>
+ <path d="M0 612 L55.83 612 L153.65 612" class="st9"/>
+ </g>
+ <g id="shape506-38" v:mID="506" v:groupContext="shape" transform="translate(459,-315)">
+ <title>Sheet.506</title>
+ <path d="M0 612 L47.48 612" class="st10"/>
+ </g>
+ <g id="group507-43" transform="translate(513.87,-279)" v:mID="507" v:groupContext="group">
+ <title>Sheet.507</title>
+ <g id="shape508-44" v:mID="508" v:groupContext="shape" transform="translate(10.4997,0)">
+ <title>Sheet.508</title>
+ <rect x="0" y="551.545" width="10.3868" height="60.4551" class="st1"/>
+ </g>
+ <g id="shape509-46" v:mID="509" v:groupContext="shape" transform="translate(20.8865,0)">
+ <title>Sheet.509</title>
+ <rect x="0" y="551.545" width="10.3868" height="60.4551" class="st1"/>
+ </g>
+ <g id="shape510-48" v:mID="510" v:groupContext="shape" transform="translate(31.2732,0)">
+ <title>Sheet.510</title>
+ <rect x="0" y="551.545" width="10.3868" height="60.4551" class="st1"/>
+ </g>
+ <g id="shape511-50" v:mID="511" v:groupContext="shape" transform="translate(41.66,0)">
+ <title>Sheet.511</title>
+ <rect x="0" y="551.545" width="10.3868" height="60.4551" class="st1"/>
+ </g>
+ <g id="shape512-52" v:mID="512" v:groupContext="shape" transform="translate(51.708,1163.54) rotate(180)">
+ <title>Sheet.512</title>
+ <path d="M0 612 L51.71 612" class="st11"/>
+ </g>
+ <g id="shape513-55" v:mID="513" v:groupContext="shape" transform="translate(51.708,1224) rotate(180)">
+ <title>Sheet.513</title>
+ <path d="M0 612 L51.71 612" class="st11"/>
+ </g>
+ </g>
+ <g id="shape514-58" v:mID="514" v:groupContext="shape" transform="translate(499.785,-341.11)">
+ <title>Sheet.514</title>
+ <desc>Entropy FIFO 32w x 32d</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="36" cy="599.18" width="72" height="25.6401"/>
+ <rect x="0" y="586.36" width="72" height="25.6401" class="st3"/>
+ <text x="9.69" y="596.18" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Entropy FIFO <v:newlineChar/><tspan
+ x="15.24" dy="1.2em" class="st4">32w x 32d</tspan></text> </g>
+ <g id="group518-62" transform="translate(396,-423)" v:mID="518" v:groupContext="group">
+ <title>LSFR block</title>
+ <g id="shape519-63" v:mID="519" v:groupContext="shape" transform="translate(79.3461,-46.1096)">
+ <title>Sheet.519</title>
+ <desc>LFSR</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="36" cy="601.305" width="72" height="21.3904"/>
+ <rect x="0" y="590.61" width="72" height="21.3904" class="st1"/>
+ <text x="26.59" y="604.3" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>LFSR</text> </g>
+ <g id="shape520-66" v:mID="520" v:groupContext="shape" transform="translate(151.346,1167.19) scale(1,-1)">
+ <title>Sheet.520</title>
+ <path d="M0 612 L14.53 612" class="st10"/>
+ </g>
+ <g id="shape521-71" v:mID="521" v:groupContext="shape" transform="translate(70.7266,1177.89) scale(1,-1)">
+ <title>Sheet.521</title>
+ <path d="M0 588.39 L22.88 588.39 L40.5 588.39 L40.5 606.28" class="st12"/>
+ </g>
+ <g id="shape522-77" v:mID="522" v:groupContext="shape">
+ <title>Sheet.522</title>
+ <desc>lfsr.en lfsr.load_seed lsfr.seed</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="36" cy="589.5" width="72" height="45"/>
+ <rect x="0" y="567" width="72" height="45" class="st3"/>
+ <text x="42.5" y="580" class="st2" v:langID="1033"><v:paragraph v:horizAlign="2"/><v:tabList/>lfsr.en<v:newlineChar/><tspan
+ x="11.02" dy="1.2em" class="st4">lfsr.load_seed<v:newlineChar/></tspan><tspan x="33.62" dy="1.2em"
+ class="st4">lsfr.seed</tspan><v:newlineChar/> </text> </g>
+ <g id="shape523-82" v:mID="523" v:groupContext="shape" transform="translate(174.227,-46.1096)">
+ <title>Sheet.523</title>
+ <desc>lfsr.value</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="26.0234" cy="601.305" width="52.05" height="21.3904"/>
+ <rect x="0" y="590.61" width="52.0468" height="21.3904" class="st3"/>
+ <text x="4" y="603.61" class="st2" v:langID="1033"><v:paragraph/><v:tabList/>lfsr.value</text> </g>
+ <g id="shape524-85" v:mID="524" v:groupContext="shape" transform="translate(70.7266,1177.89) scale(1,-1)">
+ <title>Sheet.524</title>
+ <path d="M0 600.2 L27 600.2 L27 606.28" class="st12"/>
+ </g>
+ <g id="shape525-90" v:mID="525" v:groupContext="shape" transform="translate(70.7266,1177.89) scale(1,-1)">
+ <title>Sheet.525</title>
+ <path d="M0 577.7 L31.54 577.7 L55.83 577.7 L55.83 603.65" class="st9"/>
+ </g>
+ </g>
+ <g id="shape531-95" v:mID="531" v:groupContext="shape" transform="translate(459,-315)">
+ <title>Sheet.531</title>
+ <path d="M0 612 L0 540 L180 540 L180 445.5 L163.27 445.5" class="st13"/>
+ </g>
+ <g id="shape543-98" v:mID="543" v:groupContext="shape" transform="translate(265.1,-224.445)">
+ <title>Sheet.543</title>
+ <path d="M303.42 521.45 L364.9 521.45 L364.9 612 L8.35 612" class="st9"/>
+ </g>
+ <g id="shape570-103" v:mID="570" v:groupContext="shape" transform="translate(586.953,-266.61)">
+ <title>LSFR block.523</title>
+ <desc>depth</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="26.0234" cy="601.305" width="52.05" height="21.3904"/>
+ <rect x="0" y="590.61" width="52.0468" height="21.3904" class="st3"/>
+ <text x="4" y="603.61" class="st2" v:langID="1033"><v:paragraph/><v:tabList/>depth</text> </g>
+ <g id="shape571-106" v:mID="571" v:groupContext="shape" transform="translate(442.953,-279)">
+ <title>LSFR block.571</title>
+ <desc>push</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="26.0234" cy="601.305" width="52.05" height="21.3904"/>
+ <rect x="0" y="590.61" width="52.0468" height="21.3904" class="st3"/>
+ <text x="4" y="603.61" class="st2" v:langID="1033"><v:paragraph/><v:tabList/>push</text> </g>
+ <g id="shape572-109" v:mID="572" v:groupContext="shape" transform="translate(265.1,-216)">
+ <title>Sheet.572</title>
+ <path d="M0 612 L382.9 612 L382.9 495 L306.54 495" class="st12"/>
+ </g>
+ <g id="shape573-114" v:mID="573" v:groupContext="shape" transform="translate(620.757,-333)">
+ <title>LSFR block.573</title>
+ <desc>pop</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="26.0234" cy="601.305" width="52.05" height="21.3904"/>
+ <rect x="0" y="590.61" width="52.0468" height="21.3904" class="st3"/>
+ <text x="4" y="603.61" class="st2" v:langID="1033"><v:paragraph/><v:tabList/>pop</text> </g>
+ <g id="shape574-117" v:mID="574" v:groupContext="shape" transform="translate(265.5,778.5) scale(1,-1)">
+ <title>Sheet.574</title>
+ <path d="M134.14 612 L133.78 612 L46.77 612 L0 612" class="st7"/>
+ </g>
+ <g id="shape575-122" v:mID="575" v:groupContext="shape" transform="translate(351,-387.555)">
+ <title>LSFR block.519</title>
+ <desc>Count Down</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="36" cy="601.305" width="72" height="21.3904"/>
+ <rect x="0" y="590.61" width="72" height="21.3904" class="st1"/>
+ <text x="10.72" y="604.3" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Count Down</text> </g>
+ <g id="shape578-125" v:mID="578" v:groupContext="shape" transform="translate(265.1,-238.5)">
+ <title>Sheet.578</title>
+ <path d="M300.82 553.5 L319.9 553.5 L319.9 612 L5.72 612" class="st14"/>
+ </g>
+ <g id="shape579-131" v:mID="579" v:groupContext="shape" transform="translate(266.25,-238.5)">
+ <title>Sheet.579</title>
+ <path d="M300.75 553.5 L318.75 553.5 L318.75 612 L5.72 612" class="st14"/>
+ </g>
+ <g id="shape580-136" v:mID="580" v:groupContext="shape" transform="translate(265.1,-238.5)">
+ <title>Sheet.580</title>
+ <path d="M300.82 553.5 L319.9 553.5 L319.9 612 L5.72 612" class="st12"/>
+ </g>
+ <g id="shape581-141" v:mID="581" v:groupContext="shape" transform="translate(243,-252)">
+ <title>Sheet.581</title>
+ </g>
+ <g id="shape582-142" v:mID="582" v:groupContext="shape" transform="translate(306,-257.055)">
+ <title>LSFR block.582</title>
+ <desc>Thresh >= depth</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="40.5" cy="601.305" width="81" height="21.3904"/>
+ <rect x="0" y="590.61" width="81" height="21.3904" class="st1"/>
+ <text x="7.34" y="604.3" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Thresh >= depth</text> </g>
+ <g id="shape583-145" v:mID="583" v:groupContext="shape" transform="translate(265.1,-408.945)">
+ <title>Sheet.583</title>
+ <path d="M0 597.95 L121.9 597.95 L121.9 603.65" class="st9"/>
+ </g>
+ <g id="shape584-150" v:mID="584" v:groupContext="shape" transform="translate(265.1,-278.445)">
+ <title>Sheet.584</title>
+ <path d="M0 480.95 L58.9 480.95 L58.9 603.65" class="st9"/>
+ </g>
+ <g id="shape585-155" v:mID="585" v:groupContext="shape" transform="translate(387,-297)">
+ <title>Sheet.585</title>
+ <path d="M0 521.45 L0 612 L30.75 612 L120.28 612" class="st12"/>
+ </g>
+ <g id="shape586-160" v:mID="586" v:groupContext="shape" transform="translate(387,-349.305)">
+ <title>LSFR block.586</title>
+ <desc>Cnt = 1</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="20.8867" cy="601.305" width="41.78" height="21.3904"/>
+ <rect x="0" y="590.61" width="41.7734" height="21.3904" class="st3"/>
+ <text x="4" y="603.61" class="st2" v:langID="1033"><v:paragraph/><v:tabList/>Cnt = 1</text> </g>
+ <g id="shape587-163" v:mID="587" v:groupContext="shape" transform="translate(387,-238.5)">
+ <title>Sheet.587</title>
+ <path d="M18 612 L18 580.5 L5.72 580.5" class="st12"/>
+ </g>
+ <g id="shape588-168" v:mID="588" v:groupContext="shape" transform="translate(265.1,-252)">
+ <title>Sheet.588</title>
+ <path d="M40.9 594 L21.4 594 L21.4 612 L5.72 612" class="st12"/>
+ </g>
+ <g id="shape589-173" v:mID="589" v:groupContext="shape" transform="translate(158.877,-212.625)">
+ <title>Sheet.589</title>
+ <desc>es_status.d es_fdepthst.d es_entropy.d es_entropy_rd</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="49.6229" cy="561.375" width="99.25" height="101.25"/>
+ <rect x="0" y="510.75" width="99.2459" height="101.25" class="st3"/>
+ <text x="49.03" y="571.75" class="st2" v:langID="1033"><v:paragraph v:horizAlign="2"/><v:tabList/><v:space/><v:newlineChar/><v:newlineChar/><v:newlineChar/><v:space/><v:newlineChar/>es_status.d<tspan
+ x="36.94" dy="1.2em" class="st4"> </tspan>es_fdepthst.d<tspan x="39.22" dy="1.2em" class="st4"> </tspan>es_entropy.d<tspan
+ x="33.28" dy="1.2em" class="st4"> </tspan>es_entropy_rd<tspan dy="1.2em" class="st4"> </tspan><v:newlineChar/> </text> </g>
+ <g id="shape590-180" v:mID="590" v:groupContext="shape" transform="translate(444.488,-162)">
+ <title>LSFR block.590</title>
+ <desc>Note: Entropy FIFO depth is parameterized</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="0"/>
+ <v:textRect cx="109.012" cy="601.305" width="218.03" height="21.3904"/>
+ <rect x="0" y="590.61" width="218.023" height="21.3904" class="st3"/>
+ <text x="4" y="603.61" class="st2" v:langID="1033"><v:paragraph/><v:tabList/>Note: Entropy FIFO depth is parameterized</text> </g>
+ </g>
+</svg>
diff --git a/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv b/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv
new file mode 100644
index 0000000..50b6296
--- /dev/null
+++ b/hw/ip/entropy_src/rtl/entropy_src_reg_pkg.sv
@@ -0,0 +1,200 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Register Package auto-generated by `reggen` containing data structure
+
+package entropy_src_reg_pkg;
+
+ // Param list
+ localparam int EsFifoDepth = 32;
+
+ ////////////////////////////
+ // Typedefs for registers //
+ ////////////////////////////
+ typedef struct packed {
+ struct packed {
+ logic q;
+ } es_entropy_valid;
+ struct packed {
+ logic q;
+ } es_entropy_fifo_err;
+ } entropy_src_reg2hw_intr_state_reg_t;
+
+ typedef struct packed {
+ struct packed {
+ logic q;
+ } es_entropy_valid;
+ struct packed {
+ logic q;
+ } es_entropy_fifo_err;
+ } entropy_src_reg2hw_intr_enable_reg_t;
+
+ typedef struct packed {
+ struct packed {
+ logic q;
+ logic qe;
+ } es_entropy_valid;
+ struct packed {
+ logic q;
+ logic qe;
+ } es_entropy_fifo_err;
+ } entropy_src_reg2hw_intr_test_reg_t;
+
+ typedef struct packed {
+ logic q;
+ } entropy_src_reg2hw_es_regen_reg_t;
+
+ typedef struct packed {
+ logic q;
+ } entropy_src_reg2hw_es_conf_reg_t;
+
+ typedef struct packed {
+ struct packed {
+ logic [7:0] q;
+ } abi_revision;
+ struct packed {
+ logic [7:0] q;
+ } hw_revision;
+ struct packed {
+ logic [7:0] q;
+ } chip_type;
+ } entropy_src_reg2hw_es_rev_reg_t;
+
+ typedef struct packed {
+ logic [31:0] q;
+ logic re;
+ } 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;
+ } 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;
+ } entropy_src_reg2hw_es_seed_reg_t;
+
+
+ typedef struct packed {
+ struct packed {
+ logic d;
+ logic de;
+ } es_entropy_valid;
+ struct packed {
+ logic d;
+ logic de;
+ } es_entropy_fifo_err;
+ } entropy_src_hw2reg_intr_state_reg_t;
+
+ typedef struct packed {
+ logic [31:0] d;
+ } entropy_src_hw2reg_es_entropy_reg_t;
+
+ typedef struct packed {
+ logic d;
+ } entropy_src_hw2reg_es_status_reg_t;
+
+ typedef struct packed {
+ logic [6:0] d;
+ } entropy_src_hw2reg_es_fdepthst_reg_t;
+
+
+ ///////////////////////////////////////
+ // 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_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_t;
+
+ // Register Address
+ parameter ENTROPY_SRC_INTR_STATE_OFFSET = 6'h 0;
+ parameter ENTROPY_SRC_INTR_ENABLE_OFFSET = 6'h 4;
+ parameter ENTROPY_SRC_INTR_TEST_OFFSET = 6'h 8;
+ parameter ENTROPY_SRC_ES_REGEN_OFFSET = 6'h c;
+ parameter ENTROPY_SRC_ES_CONF_OFFSET = 6'h 10;
+ parameter ENTROPY_SRC_ES_REV_OFFSET = 6'h 14;
+ parameter ENTROPY_SRC_ES_ENTROPY_OFFSET = 6'h 18;
+ parameter ENTROPY_SRC_ES_CTRL_OFFSET = 6'h 1c;
+ parameter ENTROPY_SRC_ES_STATUS_OFFSET = 6'h 20;
+ parameter ENTROPY_SRC_ES_FDEPTHST_OFFSET = 6'h 24;
+ parameter ENTROPY_SRC_ES_THRESH_OFFSET = 6'h 28;
+ parameter ENTROPY_SRC_ES_RATE_OFFSET = 6'h 2c;
+ parameter ENTROPY_SRC_ES_SEED_OFFSET = 6'h 30;
+
+
+ // Register Index
+ typedef enum int {
+ ENTROPY_SRC_INTR_STATE,
+ ENTROPY_SRC_INTR_ENABLE,
+ ENTROPY_SRC_INTR_TEST,
+ ENTROPY_SRC_ES_REGEN,
+ ENTROPY_SRC_ES_CONF,
+ ENTROPY_SRC_ES_REV,
+ ENTROPY_SRC_ES_ENTROPY,
+ ENTROPY_SRC_ES_CTRL,
+ ENTROPY_SRC_ES_STATUS,
+ ENTROPY_SRC_ES_FDEPTHST,
+ ENTROPY_SRC_ES_THRESH,
+ ENTROPY_SRC_ES_RATE,
+ ENTROPY_SRC_ES_SEED
+ } entropy_src_id_e;
+
+ // Register width information to check illegal writes
+ localparam logic [3:0] ENTROPY_SRC_PERMIT [13] = '{
+ 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
+ };
+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
new file mode 100644
index 0000000..ded89da
--- /dev/null
+++ b/hw/ip/entropy_src/rtl/entropy_src_reg_top.sv
@@ -0,0 +1,708 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Register Top module auto-generated by `reggen`
+
+module entropy_src_reg_top (
+ input clk_i,
+ input rst_ni,
+
+ // Below Regster interface can be changed
+ input tlul_pkg::tl_h2d_t tl_i,
+ output tlul_pkg::tl_d2h_t tl_o,
+ // To HW
+ output entropy_src_reg_pkg::entropy_src_reg2hw_t reg2hw, // Write
+ input entropy_src_reg_pkg::entropy_src_hw2reg_t hw2reg, // Read
+
+ // Config
+ input devmode_i // If 1, explicit error return for unmapped register access
+);
+
+ import entropy_src_reg_pkg::* ;
+
+ localparam AW = 6;
+ localparam DW = 32;
+ localparam DBW = DW/8; // Byte Width
+
+ // register signals
+ logic reg_we;
+ logic reg_re;
+ logic [AW-1:0] reg_addr;
+ logic [DW-1:0] reg_wdata;
+ logic [DBW-1:0] reg_be;
+ logic [DW-1:0] reg_rdata;
+ logic reg_error;
+
+ logic addrmiss, wr_err;
+
+ logic [DW-1:0] reg_rdata_next;
+
+ tlul_pkg::tl_h2d_t tl_reg_h2d;
+ tlul_pkg::tl_d2h_t tl_reg_d2h;
+
+ assign tl_reg_h2d = tl_i;
+ assign tl_o = tl_reg_d2h;
+
+ tlul_adapter_reg #(
+ .RegAw(AW),
+ .RegDw(DW)
+ ) u_reg_if (
+ .clk_i,
+ .rst_ni,
+
+ .tl_i (tl_reg_h2d),
+ .tl_o (tl_reg_d2h),
+
+ .we_o (reg_we),
+ .re_o (reg_re),
+ .addr_o (reg_addr),
+ .wdata_o (reg_wdata),
+ .be_o (reg_be),
+ .rdata_i (reg_rdata),
+ .error_i (reg_error)
+ );
+
+ assign reg_rdata = reg_rdata_next ;
+ assign reg_error = (devmode_i & addrmiss) | wr_err ;
+
+ // Define SW related signals
+ // Format: <reg>_<field>_{wd|we|qs}
+ // or <reg>_{wd|we|qs} if field == 1 or 0
+ 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_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_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 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 [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 es_fdepthst_re;
+ logic [6:0] es_thresh_qs;
+ logic [6: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 es_seed_we;
+
+ // Register instances
+ // R[intr_state]: V(False)
+
+ // F[es_entropy_valid]: 0:0
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("W1C"),
+ .RESVAL (1'h0)
+ ) u_intr_state_es_entropy_valid (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (intr_state_es_entropy_valid_we),
+ .wd (intr_state_es_entropy_valid_wd),
+
+ // from internal hardware
+ .de (hw2reg.intr_state.es_entropy_valid.de),
+ .d (hw2reg.intr_state.es_entropy_valid.d ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.intr_state.es_entropy_valid.q ),
+
+ // to register interface (read)
+ .qs (intr_state_es_entropy_valid_qs)
+ );
+
+
+ // F[es_entropy_fifo_err]: 1:1
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("W1C"),
+ .RESVAL (1'h0)
+ ) u_intr_state_es_entropy_fifo_err (
+ .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),
+
+ // from internal hardware
+ .de (hw2reg.intr_state.es_entropy_fifo_err.de),
+ .d (hw2reg.intr_state.es_entropy_fifo_err.d ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.intr_state.es_entropy_fifo_err.q ),
+
+ // to register interface (read)
+ .qs (intr_state_es_entropy_fifo_err_qs)
+ );
+
+
+ // R[intr_enable]: V(False)
+
+ // F[es_entropy_valid]: 0:0
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h0)
+ ) u_intr_enable_es_entropy_valid (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (intr_enable_es_entropy_valid_we),
+ .wd (intr_enable_es_entropy_valid_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.intr_enable.es_entropy_valid.q ),
+
+ // to register interface (read)
+ .qs (intr_enable_es_entropy_valid_qs)
+ );
+
+
+ // F[es_entropy_fifo_err]: 1:1
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h0)
+ ) u_intr_enable_es_entropy_fifo_err (
+ .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),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.intr_enable.es_entropy_fifo_err.q ),
+
+ // to register interface (read)
+ .qs (intr_enable_es_entropy_fifo_err_qs)
+ );
+
+
+ // R[intr_test]: V(True)
+
+ // F[es_entropy_valid]: 0:0
+ prim_subreg_ext #(
+ .DW (1)
+ ) u_intr_test_es_entropy_valid (
+ .re (1'b0),
+ .we (intr_test_es_entropy_valid_we),
+ .wd (intr_test_es_entropy_valid_wd),
+ .d ('0),
+ .qre (),
+ .qe (reg2hw.intr_test.es_entropy_valid.qe),
+ .q (reg2hw.intr_test.es_entropy_valid.q ),
+ .qs ()
+ );
+
+
+ // F[es_entropy_fifo_err]: 1:1
+ prim_subreg_ext #(
+ .DW (1)
+ ) u_intr_test_es_entropy_fifo_err (
+ .re (1'b0),
+ .we (intr_test_es_entropy_fifo_err_we),
+ .wd (intr_test_es_entropy_fifo_err_wd),
+ .d ('0),
+ .qre (),
+ .qe (reg2hw.intr_test.es_entropy_fifo_err.qe),
+ .q (reg2hw.intr_test.es_entropy_fifo_err.q ),
+ .qs ()
+ );
+
+
+ // R[es_regen]: V(False)
+
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("W1C"),
+ .RESVAL (1'h1)
+ ) u_es_regen (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (es_regen_we),
+ .wd (es_regen_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.es_regen.q ),
+
+ // to register interface (read)
+ .qs (es_regen_qs)
+ );
+
+
+ // R[es_conf]: V(False)
+
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h0)
+ ) u_es_conf (
+ .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),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.es_conf.q ),
+
+ // to register interface (read)
+ .qs (es_conf_qs)
+ );
+
+
+ // R[es_rev]: V(False)
+
+ // F[abi_revision]: 7:0
+ prim_subreg #(
+ .DW (8),
+ .SWACCESS("RO"),
+ .RESVAL (8'h1)
+ ) u_es_rev_abi_revision (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ .we (1'b0),
+ .wd ('0 ),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.es_rev.abi_revision.q ),
+
+ // to register interface (read)
+ .qs (es_rev_abi_revision_qs)
+ );
+
+
+ // F[hw_revision]: 15:8
+ prim_subreg #(
+ .DW (8),
+ .SWACCESS("RO"),
+ .RESVAL (8'h2)
+ ) u_es_rev_hw_revision (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ .we (1'b0),
+ .wd ('0 ),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.es_rev.hw_revision.q ),
+
+ // to register interface (read)
+ .qs (es_rev_hw_revision_qs)
+ );
+
+
+ // F[chip_type]: 23:16
+ prim_subreg #(
+ .DW (8),
+ .SWACCESS("RO"),
+ .RESVAL (8'h1)
+ ) u_es_rev_chip_type (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ .we (1'b0),
+ .wd ('0 ),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.es_rev.chip_type.q ),
+
+ // to register interface (read)
+ .qs (es_rev_chip_type_qs)
+ );
+
+
+ // R[es_entropy]: V(True)
+
+ prim_subreg_ext #(
+ .DW (32)
+ ) u_es_entropy (
+ .re (es_entropy_re),
+ .we (1'b0),
+ .wd ('0),
+ .d (hw2reg.es_entropy.d),
+ .qre (reg2hw.es_entropy.re),
+ .qe (),
+ .q (reg2hw.es_entropy.q ),
+ .qs (es_entropy_qs)
+ );
+
+
+ // R[es_ctrl]: V(False)
+
+ 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
+ .qe (),
+ .q (reg2hw.es_ctrl.q ),
+
+ // to register interface (read)
+ .qs (es_ctrl_qs)
+ );
+
+
+ // R[es_status]: V(True)
+
+ prim_subreg_ext #(
+ .DW (1)
+ ) u_es_status (
+ .re (es_status_re),
+ .we (1'b0),
+ .wd ('0),
+ .d (hw2reg.es_status.d),
+ .qre (),
+ .qe (),
+ .q (reg2hw.es_status.q ),
+ .qs (es_status_qs)
+ );
+
+
+ // R[es_fdepthst]: V(True)
+
+ prim_subreg_ext #(
+ .DW (7)
+ ) u_es_fdepthst (
+ .re (es_fdepthst_re),
+ .we (1'b0),
+ .wd ('0),
+ .d (hw2reg.es_fdepthst.d),
+ .qre (),
+ .qe (),
+ .q (reg2hw.es_fdepthst.q ),
+ .qs (es_fdepthst_qs)
+ );
+
+
+ // R[es_thresh]: V(False)
+
+ prim_subreg #(
+ .DW (7),
+ .SWACCESS("RW"),
+ .RESVAL (7'h0)
+ ) u_es_thresh (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (es_thresh_we),
+ .wd (es_thresh_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (reg2hw.es_thresh.qe),
+ .q (reg2hw.es_thresh.q ),
+
+ // to register interface (read)
+ .qs (es_thresh_qs)
+ );
+
+
+ // R[es_rate]: V(False)
+
+ prim_subreg #(
+ .DW (16),
+ .SWACCESS("RW"),
+ .RESVAL (16'h1)
+ ) u_es_rate (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (es_rate_we),
+ .wd (es_rate_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (reg2hw.es_rate.qe),
+ .q (reg2hw.es_rate.q ),
+
+ // to register interface (read)
+ .qs (es_rate_qs)
+ );
+
+
+ // R[es_seed]: V(False)
+
+ prim_subreg #(
+ .DW (32),
+ .SWACCESS("RW"),
+ .RESVAL (32'h12345678)
+ ) u_es_seed (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface (qualified with register enable)
+ .we (es_seed_we & es_regen_qs),
+ .wd (es_seed_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (reg2hw.es_seed.qe),
+ .q (reg2hw.es_seed.q ),
+
+ // to register interface (read)
+ .qs (es_seed_qs)
+ );
+
+
+
+
+ logic [12: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);
+ end
+
+ assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
+
+ // Check sub-word write is permitted
+ always_comb begin
+ wr_err = 1'b0;
+ if (addr_hit[ 0] && reg_we && (ENTROPY_SRC_PERMIT[ 0] != (ENTROPY_SRC_PERMIT[ 0] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 1] && reg_we && (ENTROPY_SRC_PERMIT[ 1] != (ENTROPY_SRC_PERMIT[ 1] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 2] && reg_we && (ENTROPY_SRC_PERMIT[ 2] != (ENTROPY_SRC_PERMIT[ 2] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 3] && reg_we && (ENTROPY_SRC_PERMIT[ 3] != (ENTROPY_SRC_PERMIT[ 3] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 4] && reg_we && (ENTROPY_SRC_PERMIT[ 4] != (ENTROPY_SRC_PERMIT[ 4] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 5] && reg_we && (ENTROPY_SRC_PERMIT[ 5] != (ENTROPY_SRC_PERMIT[ 5] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 6] && reg_we && (ENTROPY_SRC_PERMIT[ 6] != (ENTROPY_SRC_PERMIT[ 6] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 7] && reg_we && (ENTROPY_SRC_PERMIT[ 7] != (ENTROPY_SRC_PERMIT[ 7] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 8] && reg_we && (ENTROPY_SRC_PERMIT[ 8] != (ENTROPY_SRC_PERMIT[ 8] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[ 9] && reg_we && (ENTROPY_SRC_PERMIT[ 9] != (ENTROPY_SRC_PERMIT[ 9] & reg_be))) wr_err = 1'b1 ;
+ 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 ;
+ 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_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_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 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_entropy_re = addr_hit[6] && reg_re;
+
+ assign es_ctrl_we = addr_hit[7] & reg_we & ~wr_err;
+ assign es_ctrl_wd = reg_wdata[0];
+
+ assign es_status_re = addr_hit[8] && reg_re;
+
+ assign es_fdepthst_re = addr_hit[9] && reg_re;
+
+ assign es_thresh_we = addr_hit[10] & reg_we & ~wr_err;
+ assign es_thresh_wd = reg_wdata[6:0];
+
+ assign es_rate_we = addr_hit[11] & 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];
+
+ // Read data return
+ always_comb begin
+ reg_rdata_next = '0;
+ 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;
+ 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;
+ end
+
+ addr_hit[2]: begin
+ reg_rdata_next[0] = '0;
+ reg_rdata_next[1] = '0;
+ end
+
+ addr_hit[3]: begin
+ reg_rdata_next[0] = es_regen_qs;
+ 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[6]: begin
+ reg_rdata_next[31:0] = es_entropy_qs;
+ end
+
+ addr_hit[7]: begin
+ reg_rdata_next[0] = es_ctrl_qs;
+ end
+
+ addr_hit[8]: begin
+ reg_rdata_next[0] = es_status_qs;
+ end
+
+ addr_hit[9]: begin
+ reg_rdata_next[6:0] = es_fdepthst_qs;
+ end
+
+ addr_hit[10]: begin
+ reg_rdata_next[6:0] = es_thresh_qs;
+ end
+
+ addr_hit[11]: begin
+ reg_rdata_next[15:0] = es_rate_qs;
+ end
+
+ addr_hit[12]: begin
+ reg_rdata_next[31:0] = es_seed_qs;
+ end
+
+ default: begin
+ reg_rdata_next = '1;
+ end
+ endcase
+ end
+
+ // Assertions for Register Interface
+ `ASSERT_PULSE(wePulse, reg_we, clk_i, !rst_ni)
+ `ASSERT_PULSE(rePulse, reg_re, clk_i, !rst_ni)
+
+ `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o.d_valid, clk_i, !rst_ni)
+
+ `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), clk_i, !rst_ni)
+
+ // this is formulated as an assumption such that the FPV testbenches do disprove this
+ // property by mistake
+ `ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.parity_en == 1'b0, clk_i, !rst_ni)
+
+endmodule
diff --git a/util/build_docs.py b/util/build_docs.py
index d6fb3b0..53a7635 100755
--- a/util/build_docs.py
+++ b/util/build_docs.py
@@ -49,6 +49,7 @@
"hardware_definitions": [
"hw/ip/aes/data/aes.hjson",
"hw/ip/alert_handler/data/alert_handler.hjson",
+ "hw/ip/entropy_src/data/entropy_src.hjson",
"hw/ip/flash_ctrl/data/flash_ctrl.hjson",
"hw/ip/gpio/data/gpio.hjson",
"hw/ip/hmac/data/hmac.hjson",