diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 043732ed..babd1190 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,9 +26,11 @@ jobs:
run: make bender
- name: Python Requirements
run: pip install -r requirements.txt
+ - name: Checkout dependencies
+ run: ./bender checkout
- name: Check clean make targets
run: |
- make -B gen_ODRG gen_TCLS gen_ecc_registers gen_ECC
+ make -B gen_ODRG gen_TCLS gen_ecc_registers gen_ECC gen_HMR
git status && test -z "$(git status --porcelain)"
lint-verilog:
runs-on: ubuntu-latest
@@ -59,6 +61,7 @@ jobs:
./rtl/HMR/hmr_registers_reg_top.sv
./rtl/HMR/hmr_tmr_regs_reg_pkg.sv
./rtl/HMR/hmr_tmr_regs_reg_top.sv
+ ./rtl/HMR/hmr_registers_reg_addr_pkg.sv
./rtl/pulpissimo_tcls/tcls_manager_reg_pkg.sv
./rtl/pulpissimo_tcls/tcls_manager_reg_top.sv
extra_args: "--rules=-interface-name-style --lint_fatal --parse_fatal --waiver_files .github/waiver.verible"
diff --git a/Bender.yml b/Bender.yml
index ea8f550b..b28acae2 100644
--- a/Bender.yml
+++ b/Bender.yml
@@ -8,7 +8,8 @@ dependencies:
common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.0 }
register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.4 }
common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.35.0 }
-
+ apb: { git: "https://github.com/pulp-platform/apb.git", version: 0.2.4 }
+
export_include_dirs:
- include
@@ -139,7 +140,7 @@ sources:
- rtl/HMR/hmr_dmr_ctrl.sv
- rtl/HMR/hmr_tmr_regs_reg_top.sv
- rtl/HMR/hmr_tmr_ctrl.sv
- - rtl/HMR/HMR_wrap.sv
+ # - rtl/HMR/HMR_wrap.sv # Legacy, plase use hmr_unit instead
- rtl/HMR/hmr_unit.sv
vendor_package:
diff --git a/Makefile b/Makefile
index 153a1446..558fa819 100644
--- a/Makefile
+++ b/Makefile
@@ -19,13 +19,20 @@ REG_PATH = $(shell $(BENDER) path register_interface)
# use if you need to hardcode location of regtool
# REG_PATH = ../register_interface
REG_TOOL = $(REG_PATH)/vendor/lowrisc_opentitan/util/regtool.py
+PEAKRDL ?= peakrdl
HJSON_ODRG = rtl/ODRG_unit/ODRG_unit.hjson
HJSON_TCLS = rtl/pulpissimo_tcls/TCLS_unit.hjson
-HJSON_HMR = rtl/HMR/HMR_regs.hjson
-HJSON_HMR_core = rtl/HMR/HMR_core_regs.hjson
-HJSON_HMR_dmr = rtl/HMR/HMR_dmr_regs.hjson
-HJSON_HMR_tmr = rtl/HMR/HMR_tmr_regs.hjson
+RDL_HMR_TOP = rtl/HMR/hmr_all.rdl
+RDL_HMR = rtl/HMR/hmr_regs.rdl
+RDL_HMR_core = rtl/HMR/hmr_core_regs.rdl
+RDL_HMR_dmr = rtl/HMR/hmr_dmr_regs.rdl
+RDL_HMR_tmr = rtl/HMR/hmr_tmr_regs.rdl
+HMR_NUM_CORES ?= 12
+HMR_NUM_DMR_GROUPS ?= $(HMR_NUM_CORES)/2
+HMR_NUM_TMR_GROUPS ?= $(HMR_NUM_CORES)/3
+HMR_DMR_AVAILABLE ?= 1
+HMR_TMR_AVAILABLE ?= 1
HJSON_ECC = rtl/ecc_wrap/ecc_sram_wrapper.hjson
TARGET_DIR_ODRG = rtl/ODRG_unit
@@ -33,49 +40,6 @@ TARGET_DIR_TCLS = rtl/pulpissimo_tcls
TARGET_DIR_HMR = rtl/HMR
TARGET_DIR_ECC = rtl/ecc_wrap
-define HMR_H_HEADER_STRING
-/*
- * Copyright (C) 2023 ETH Zurich and University of Bologna
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __ARCHI_HMR_HMR_V1_H__
-#define __ARCHI_HMR_HMR_V1_H__
-
-#define HMR_IN_INTERLEAVED 1
-
-#define HMR_TOP_OFFSET 0x000
-#define HMR_CORE_OFFSET 0x100
-#define HMR_DMR_OFFSET 0x200
-#define HMR_TMR_OFFSET 0x300
-
-#define HMR_CORE_INCREMENT 0x010
-#define HMR_CORE_SLL 0x004
-#define HMR_DMR_INCREMENT 0x010
-#define HMR_DMR_SLL 0x004
-#define HMR_TMR_INCREMENT 0x010
-#define HMR_TMR_SLL 0x004
-\n
-endef
-define HMR_H_FINAL_STRING
-\n\n
-#endif // __ARCHI_HMR_HMR_V1_H__
-
-endef
-export HMR_H_HEADER_STRING
-export HMR_H_FINAL_STRING
-
.PHONY: gen_ODRG gen_TCLS gen_ecc_registers gen_ECC
gen_ODRG:
python $(REG_TOOL) $(HJSON_ODRG) -t $(TARGET_DIR_ODRG) -r
@@ -87,23 +51,22 @@ gen_TCLS:
python $(REG_TOOL) $(HJSON_TCLS) -d > $(TARGET_DIR_TCLS)/doc.md
python $(REG_TOOL) $(HJSON_TCLS) -D > $(TARGET_DIR_TCLS)/TCLS.h
-gen_HMR:
- python $(REG_TOOL) $(HJSON_HMR) -t $(TARGET_DIR_HMR) -r
- python $(REG_TOOL) $(HJSON_HMR) -d > $(TARGET_DIR_HMR)/doc.html
- python $(REG_TOOL) $(HJSON_HMR) --doc > $(TARGET_DIR_HMR)/doc.md
- python $(REG_TOOL) $(HJSON_HMR_core) -t $(TARGET_DIR_HMR) -r
- python $(REG_TOOL) $(HJSON_HMR_dmr) -t $(TARGET_DIR_HMR) -r
- python $(REG_TOOL) $(HJSON_HMR_tmr) -t $(TARGET_DIR_HMR) -r
-
- @printf "$$HMR_H_HEADER_STRING" > $(TARGET_DIR_HMR)/hmr_v1.h
- python $(REG_TOOL) $(HJSON_HMR) -D >> $(TARGET_DIR_HMR)/hmr_v1.h
- @printf "\n\n" >> $(TARGET_DIR_HMR)/hmr_v1.h
- python $(REG_TOOL) $(HJSON_HMR_core) -D >> $(TARGET_DIR_HMR)/hmr_v1.h
- @printf "\n\n" >> $(TARGET_DIR_HMR)/hmr_v1.h
- python $(REG_TOOL) $(HJSON_HMR_dmr) -D >> $(TARGET_DIR_HMR)/hmr_v1.h
- @printf "\n\n" >> $(TARGET_DIR_HMR)/hmr_v1.h
- python $(REG_TOOL) $(HJSON_HMR_tmr) -D >> $(TARGET_DIR_HMR)/hmr_v1.h
- @printf "$$HMR_H_FINAL_STRING" >> $(TARGET_DIR_HMR)/hmr_v1.h
+gen_HMR: $(RDL_HMR_TOP) $(RDL_HMR) $(RDL_HMR_core) $(RDL_HMR_dmr) $(RDL_HMR_tmr)
+ $(PEAKRDL) regblock $(RDL_HMR) -o $(TARGET_DIR_HMR) --cpuif apb4-flat --default-reset arst_n \
+ --module-name hmr_registers_reg_top --package-name hmr_registers_reg_pkg \
+ -P NumCores=$(HMR_NUM_CORES) -P NumDMRGroups=$(HMR_NUM_DMR_GROUPS) -P NumTMRGroups=$(HMR_NUM_TMR_GROUPS)
+ $(PEAKRDL) regblock $(RDL_HMR_core) -o $(TARGET_DIR_HMR) --cpuif apb4-flat --default-reset arst_n \
+ --module-name hmr_core_regs_reg_top --package-name hmr_core_regs_reg_pkg
+ $(PEAKRDL) regblock $(RDL_HMR_dmr) -o $(TARGET_DIR_HMR) --cpuif apb4-flat --default-reset arst_n \
+ --module-name hmr_dmr_regs_reg_top --package-name hmr_dmr_regs_reg_pkg
+ $(PEAKRDL) regblock $(RDL_HMR_tmr) -o $(TARGET_DIR_HMR) --cpuif apb4-flat --default-reset arst_n \
+ --module-name hmr_tmr_regs_reg_top --package-name hmr_tmr_regs_reg_pkg
+ $(PEAKRDL) raw-header $(RDL_HMR_TOP) -I $(TARGET_DIR_HMR) -o $(TARGET_DIR_HMR)/hmr_registers_reg_addr_pkg.sv --format svpkg \
+ -P NumCores=$(HMR_NUM_CORES) -P NumDMRGroups=$(HMR_NUM_DMR_GROUPS) -P NumTMRGroups=$(HMR_NUM_TMR_GROUPS) \
+ -P DMRAvailable=$(HMR_DMR_AVAILABLE) -P TMRAvailable=$(HMR_TMR_AVAILABLE)
+ $(PEAKRDL) c-header $(RDL_HMR_TOP) -I $(TARGET_DIR_HMR) -o $(TARGET_DIR_HMR)/hmr_registers.h \
+ -P NumCores=$(HMR_NUM_CORES) -P NumDMRGroups=$(HMR_NUM_DMR_GROUPS) -P NumTMRGroups=$(HMR_NUM_TMR_GROUPS) \
+ -P DMRAvailable=$(HMR_DMR_AVAILABLE) -P TMRAvailable=$(HMR_TMR_AVAILABLE)
gen_ecc_registers:
python $(REG_TOOL) $(HJSON_ECC) -t $(TARGET_DIR_ECC) -r
diff --git a/README.md b/README.md
index 63dff9f5..50a2df8c 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,105 @@
This repository contains various modules used to add redundancy.
+## Hybrid Modular Redundancy (HMR)
+
+The HMR unit (contained in `rtl/HMR/hmr_unit.sv`) is designed as a configurable bridge between the system and multiple cores. This bridge allows to configure the cores to run independently, run in a dual/DMR/DCLS mode, or run in a triple/TMR/TCLS mode. These configurations can be switched at runtime (given the availability at design time), or fixed with a parameter at design time.
+
+### System integration
+
+### Instantiation
+
+This module should be placed between all signals connecting the processor cores to the rest of the system. Some additional modules are required to support certain features:
+- To allow runtime switching between independent, DMR, and TMR modes, logic should be implemented to signal when the cores are ready to group together and synchronize. If in `DMRFixed` or `TMRFixed` configuration, this is not needed.
+
+#### Parameters
+
+To integrate this module into a system, the following parameters *require* configuration:
+- `NumCores`: The number of physical cores within the system
+- `all_inputs_t`: A custom struct type containing all inputs required for the implemented core
+- `nominal_outputs_t`: A custom struct type containing all normal output signals from the implemented core
+- `apb_req_t/apb_resp_t`: APB types (see [apb](https://github.com/pulp-platform/apb)) to access configuration registers
+
+The following parameters are optional for custom configurations:
+- `DMRSupported`: Enables support for DMR mode (default: `1'b1`).
+- `DMRFixed`: Enforces permanent DMR mode. Cannot be used with `TMRSupported` or `TMRFixed` (default: `1'b0`).
+- `TMRSupported`: Enables support for TMR mode (default: `1'b1`).
+- `TMRFixed`: Enforces permanent TMR mode. Cannot be used with `DMRSupported` or `DMRFixed` (default: `1'b0`).
+- `InterleaveGrps`: Uses interleaved cores for groups instead of sequential cores for groups (e.g., for 6 cores TMR, interleaved groups 0,2,4 and 1,3,5 together vs. sequential groups 0,1,2 and 3,4,5 together) (default: `1'b1`).
+- `DefaultNominalOutputs`: Sets a custom default value the core outputs should have towards the system when disabled (i.e., part of a DMR/TMR group) (default: `'{default: '0}`).
+- `SeparateData`: Have separate error signalling for data buses, disabling error notification when the bus is disabled (default: `1'b0`). Requires `NumBusVoters` and `bus_outputs_t` to be set.
+- `bus_outputs_t`: A custom struct type containing output signals from the implemented core for a separated bus (default: `logic`).
+- `DefaultBusOutputs`: Sets a custom default value the bus outptus should have towards the system when disabled (i.e., part of a DMR/TMR group) (default: `'{default: '0}`).
+- `RapidRecovery`: Enables the *rapid recovery* feature. Requires `RfAddrWidth`, `SysDataWidth`, `core_backup_t`, and `rapid_recovery_t` to be set. Please check the HMR paper and the code for more information (default: `1'b0`).
+
+When using a non-standard configuration, it may be beneficial to regenerate the configuration registers with the desired values. The `Makefile` sets up a target for this with variables to configure:
+
+```sh
+make gen_HMR HMR_NUM_CORES=[12|your desired core number] HMR_DMR_AVAILABLE=[1|your DMRSupported/Fixed config] HMR_TMR_AVAILABLE=[1|your TMRSupported/Fixed config]
+```
+
+#### Signals
+
+The following signals are required for baseline functionality:
+- `clk_i`: The clock.
+- `rst_ni`: The reset.
+- `apb_req_i`: An APB request struct input (see [apb](https://github.com/pulp-platform/apb)).
+- `apb_resp_o`: An APB response struct output (see [apb](https://github.com/pulp-platform/apb)).
+
+All signals with a `sys_` prefix connect to the system:
+- `sys_bootaddress_i`: Default boot address (required for *checkpoint* feature in DMR, otherwise can be tied to `'0`).
+- `sys_inputs_i`: All inputs to the cores from the system.
+- `sys_nominal_outputs_o`: All normal outputs from the cores to the system.
+- `sys_bus_outputs_o`: Bus outputs from the system. Can be left unconnected if `SeparateData` is disabled.
+- `sys_fetch_en_i`: Allows configuration switching prior to coer startup.
+- `enable_bus_vote_i`: Signals bus outputs are enabled. Can be tied to `'0` if `SeparateData` is disabled.
+
+All signals with a `core_` prefix connect to the core:
+- `core_bootaddress_o`: Connect to the cores' boot address input signal (if *checkpoint* feature in DMR is desired, otherwise can be unconnected).
+- `core_setback_o`: Reset signal to the processor cores (may need FF if aynchronous reset is used internally).
+- `core_inputs_o`: All inputs to the cores.
+- `core_nominal_output_i`: All normal outputs from the cores.
+- `core_bus_outputs_i`: Bus outputs from the cores. Can be tied to `'0` if `SeparateData` is disabled.
+
+Both DMR and TMR feature some indicator signals:
+- `?mr_failure_o`: Indicates an unrecoverable mismatch detected.
+- `tmr_error_o`: Indicates a mismatch of a single core.
+- `?mr_resynch_req_o`: Interrupt to cores to trigger software resynchronization routine.
+- `?mr_sw_synch_req_o`: Interrupt to cores to trigger a software routine to synchronize independent cores. Can be left unconnected for ?MRFixed configurations.
+- `?mr_cores_synch_i`: Signal indicating independent cores for a group are synchronized and ready to lock together.
+- `redundancy_enable_o`: Signal indicating any redundancy currently is enabled.
+
+To support the *rapid recovery* feature, additional signals are required connecting to a rapid recovery capable core. Please check the HMR paper and the code for more information. If unused, these signals can be left unconnected (outputs) or tied to '0 (inputs).
+
+### Citing
+
+If you are using HMR in your academic work you can cite us:
+```BibTeX
+@article{10.1145/3635161,
+author = {Rogenmoser, Michael and Tortorella, Yvan and Rossi, Davide and Conti, Francesco and Benini, Luca},
+title = {Hybrid Modular Redundancy: Exploring Modular Redundancy Approaches in RISC-V Multi-core Computing Clusters for Reliable Processing in Space},
+year = {2025},
+issue_date = {January 2025},
+publisher = {Association for Computing Machinery},
+address = {New York, NY, USA},
+volume = {9},
+number = {1},
+issn = {2378-962X},
+url = {https://doi.org/10.1145/3635161},
+doi = {10.1145/3635161},
+abstract = {Space Cyber-Physical Systems such as spacecraft and satellites strongly rely on the reliability of onboard computers to guarantee the success of their missions. Relying solely on radiation-hardened technologies is extremely expensive, and developing inflexible architectural and microarchitectural modifications to introduce modular redundancy within a system leads to significant area increase and performance degradation. To mitigate the overheads of traditional radiation hardening and modular redundancy approaches, we present a novel Hybrid Modular Redundancy approach, a redundancy scheme that features a cluster of RISC-V processors with a flexible on-demand dual-core and triple-core lockstep grouping of computing cores with runtime split-lock capabilities. Further, we propose two recovery approaches, software-based and hardware-based, trading off performance and area overhead. Running at 430 MHz, our fault-tolerant cluster achieves up to 1,160 MOPS on a matrix multiplication benchmark when configured in non-redundant mode and 617 and 414 MOPS in dual and triple mode, respectively. A software-based recovery in triple mode requires 363 clock cycles and occupies 0.612 mm2, representing a 1.3\% area overhead over a non-redundant 12-core RISC-V cluster. As a high-performance alternative, a new hardware-based method provides rapid fault recovery in just 24 clock cycles and occupies 0.660 mm2, namely, ∼9.4\% area overhead over the baseline non-redundant RISC-V cluster. The cluster is also enhanced with split-lock capabilities to enter one of the available redundant modes with minimum performance loss, allowing execution of a mission-critical portion of code when in independent mode, or a performance section when in a reliability mode, with <400 clock cycles overhead for entry and exit. The proposed system is the first to integrate these functionalities on an open-source RISC-V-based compute device, enabling finely tunable reliability versus performance trade-offs.},
+journal = {ACM Trans. Cyber-Phys. Syst.},
+month = jan,
+articleno = {8},
+numpages = {29},
+keywords = {RISC-V, adaptive fault tolerance, space vehicle computer, reliable computing}
+}
+```
+
## On-Demand Redundancy Grouping (ODRG_unit)
+> [!NOTE]
+> This module has been superceeded by HMR above. ODRG functionality is supported within certain configurations of HMR.
+
The `ODRG_unit` is designed as a configurable bridge between three ibex cores, allowing for independent operation or lock-step operation with majority voting, triggering an interrupt in case a mismatch is detected. It uses lowrisc's reggen tool to generate the required configuration registers.
### Testing
@@ -13,8 +111,8 @@ If you are using ODRG in your academic work you can cite us:
```BibTeX
@INPROCEEDINGS{9912026,
author={Rogenmoser, Michael and Wistoff, Nils and Vogel, Pirmin and Gürkaynak, Frank and Benini, Luca},
- booktitle={2022 IEEE Computer Society Annual Symposium on VLSI (ISVLSI)},
- title={On-Demand Redundancy Grouping: Selectable Soft-Error Tolerance for a Multicore Cluster},
+ booktitle={2022 IEEE Computer Society Annual Symposium on VLSI (ISVLSI)},
+ title={On-Demand Redundancy Grouping: Selectable Soft-Error Tolerance for a Multicore Cluster},
year={2022},
volume={},
number={},
diff --git a/requirements.txt b/requirements.txt
index c87c92a8..deb228b1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,3 +2,5 @@ hjson
mako
pyyaml
tabulate
+peakrdl
+peakrdl-rawheader @ git+https://github.com/micprog/PeakRDL-rawheader.git
diff --git a/rtl/HMR/HMR_core_regs.hjson b/rtl/HMR/HMR_core_regs.hjson
deleted file mode 100644
index c55f5ede..00000000
--- a/rtl/HMR/HMR_core_regs.hjson
+++ /dev/null
@@ -1,60 +0,0 @@
-{ name: "HMR_core_regs",
- clock_primary: "clk_i",
- reset_primary: "rst_ni",
- bus_interfaces: [
- { protocol: "reg_iface",
- direction: "device"
- }
- ],
-
- regwidth: "32",
- registers: [
- { name: "Current_mode",
- desc: "Value to determine wich redundancy mode the core with that ID is in.",
- swaccess: "ro",
- hwaccess: "hwo",
- hwext: "true",
- fields: [
- { bits: "0",
- name: "independent",
- resval: "1",
- desc: ""
- },
- { bits: "1",
- name: "dual",
- resval: "0",
- desc: ""
- },
- { bits: "2",
- name: "triple",
- resval: "0",
- desc: ""
- }
- ]
-
- },
- { name: "mismatches",
- desc: "Mismatches of the core",
- swaccess: "rw0c",
- hwaccess: "hrw",
- fields: [
- { bits: "31:0",
- name: "mismatches",
- desc: "mismatch counter of the core"
- }
- ]
- },
- { name: "sp_store",
- desc: "Stack Pointer storage register",
- swaccess: "rw",
- hwaccess: "hro",
- hwqe: "true",
- fields: [
- { bits: "31:0",
- name: "SP",
- desc: "Stack Pointer"
- }
- ]
- }
- ]
-}
diff --git a/rtl/HMR/HMR_dmr_regs.hjson b/rtl/HMR/HMR_dmr_regs.hjson
deleted file mode 100644
index 12e16d44..00000000
--- a/rtl/HMR/HMR_dmr_regs.hjson
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- name: "HMR_dmr_regs",
- clock_primary: "clk_i",
- reset_primary: "rst_ni",
- bus_interfaces: [
- { protocol: "reg_iface",
- direction: "device"
- }
- ],
-
- regwidth: "32",
-
- registers: [
- { name: "DMR_enable",
- desc: "DMR configuration enable.",
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- resval: "0",
- fields: [
- { bits: "0",
- name: "DMR_enable",
- desc: "DMR configuration enable."
- }
- ]
- },
- { name: "DMR_config",
- desc: "DMR configuration bits."
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- fields: [
- { bits: "0",
- name: "rapid_recovery",
- desc: "Enable rapid recovery using an additional register file."
- },
- { bits: "1"
- name: "force_recovery",
- desc: "Forces recovery routine (if rapid_recovery is available)."
- }
- ]
- },
- { name: "checkpoint_addr",
- desc: "Address for the last checkpoint.",
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- fields: [
- { bits: "31:0",
- name: "checkpoint_addr",
- desc: "Address for the last checkpoint."
- }
- ]
- }
- ]
-}
diff --git a/rtl/HMR/HMR_regs.hjson b/rtl/HMR/HMR_regs.hjson
deleted file mode 100644
index c6a10cbc..00000000
--- a/rtl/HMR/HMR_regs.hjson
+++ /dev/null
@@ -1,141 +0,0 @@
-{
- name: "HMR_registers",
- clock_primary: "clk_i",
- reset_primary: "rst_ni",
- bus_interfaces: [
- { protocol: "reg_iface",
- direction: "device"
- }
- ],
-
- regwidth: "32",
-
- param_list: [
- { name: "NumCores",
- default: "12" # Supports up to 16 cores
- },
- { name: "NumDMRGroups",
- default: "6"
- },
- { name: "NumTMRGroups",
- default: "4"
- }
- ],
-
- registers: [
- { name: "avail_config",
- desc: "Available Configurations from implemented hardware.",
- swaccess: "ro",
- hwaccess: "hwo",
- hwext: "true",
- fields: [
- { bits: "0",
- name: "independent",
- desc: "Independent mode is available."
- },
- { bits: "1",
- name: "dual",
- desc: "Dual Modular Redundancy (DMR) is available."
- },
- { bits: "2",
- name: "triple",
- desc: "Triple Modular Redundancy (TMR) is available."
- },
- { bits: "8",
- name: "rapid_recovery",
- desc: "Rapid Recovery is available."
- }
- ]
- },
- { name: "cores_en",
- desc: "Enabled cores, based on the configuration. Can be used for barriers.",
- swaccess: "ro",
- hwaccess: "hwo",
- hwext: "true",
- fields: [
- { bits: "NumCores-1:0"
- name: "cores_en",
- desc: "Enabled cores."
- }
- ]
- },
- { name: "DMR_enable",
- desc: "DMR configuration enable, on bit per DMR group.",
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- hwext: "true",
- resval: "0",
- fields: [
- { bits: "NumDMRGroups-1:0",
- name: "DMR_enable",
- desc: "DMR configuration enable."
- }
- ]
- },
- { name: "TMR_enable",
- desc: "TMR configuration enable, one bit per TMR group.",
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- hwext: "true",
- resval: "0",
- fields: [
- { bits: "NumTMRGroups-1:0",
- name: "TMR_enable",
- desc: "TMR configuration enable."
- }
- ]
- },
- { name: "DMR_config",
- desc: "DMR configuration bits."
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- hwext: "true",
- fields: [
- { bits: "0",
- name: "rapid_recovery",
- desc: "Enable rapid recovery using an additional register file."
- },
- { bits: "1"
- name: "force_recovery",
- desc: "Forces recovery routine (if rapid_recovery is available)."
- }
- ]
- },
- { name: "TMR_config",
- desc: "TMR configuration bits."
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- hwext: "true",
- fields: [
- { bits: "0",
- name: "delay_resynch",
- resval: "0",
- desc: "Enable wait-for-restoration"
- },
- { bits: "1",
- name: "setback",
- resval: "1",
- desc: "Enable setback (synchronous reset) during re-synch."
- },
- { bits: "2",
- name: "reload_setback",
- resval: "1",
- desc: "Enable setback on mismatch during reload section of re-synch (only possible with `setback`)"
- },
- { bits: "3",
- name: "rapid_recovery",
- desc: "Enable rapid recovery using additional register file."
- },
- { bits: "4",
- name: "force_resynch",
- resval: "0",
- desc: "Forces a resynchronization routine"
- }
- ]
- }
- ]
-}
diff --git a/rtl/HMR/HMR_tmr_regs.hjson b/rtl/HMR/HMR_tmr_regs.hjson
deleted file mode 100644
index 8d6dab90..00000000
--- a/rtl/HMR/HMR_tmr_regs.hjson
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- name: "HMR_tmr_regs",
- clock_primary: "clk_i",
- reset_primary: "rst_ni",
- bus_interfaces: [
- { protocol: "reg_iface",
- direction: "device"
- }
- ],
-
- regwidth: "32",
-
- registers: [
- { name: "TMR_enable",
- desc: "TMR configuration enable.",
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- resval: "0",
- fields: [
- { bits: "0",
- name: "TMR_enable",
- desc: "TMR configuration enable."
- }
- ]
- },
- { name: "TMR_config",
- desc: "TMR configuration bits."
- swaccess: "rw",
- hwaccess: "hrw",
- hwqe: "true",
- fields: [
- { bits: "0",
- name: "delay_resynch",
- resval: "0",
- desc: "Enable wait-for-restoration"
- },
- { bits: "1",
- name: "setback",
- resval: "1",
- desc: "Enable setback (synchronous reset) during re-synch."
- },
- { bits: "2",
- name: "reload_setback",
- resval: "1",
- desc: "Enable setback on mismatch during reload section of re-synch (only possible with `setback`)"
- },
- { bits: "3",
- name: "rapid_recovery",
- desc: "Enable rapid recovery using additional register file."
- },
- { bits: "4",
- name: "force_resynch",
- resval: "0",
- desc: "Forces a resynchronization routine"
- }
- ]
- }
- ]
-}
diff --git a/rtl/HMR/doc.html b/rtl/HMR/doc.html
deleted file mode 100644
index ab3898ef..00000000
--- a/rtl/HMR/doc.html
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
- |
- HMR_registers.avail_config @ 0x0
- Available Configurations from implemented hardware.
- Reset default = 0x0, mask 0x107
- |
-
-| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | | |
-
-| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
-rapid_recovery |
- |
-triple |
-dual |
-independent |
-
|
-| Bits | Type | Reset | Name | Description |
|---|
| 0 | ro | x | independent | Independent mode is available. |
| 1 | ro | x | dual | Dual Modular Redundancy (DMR) is available. |
| 2 | ro | x | triple | Triple Modular Redundancy (TMR) is available. |
| 7:3 | | | | Reserved |
| 8 | ro | x | rapid_recovery | Rapid Recovery is available. |
-
-
-
- |
- HMR_registers.cores_en @ 0x4
- Enabled cores, based on the configuration. Can be used for barriers.
- Reset default = 0x0, mask 0xfff
- |
-
-| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | | |
-
-| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
-cores_en |
-
|
-| Bits | Type | Reset | Name | Description |
|---|
| 11:0 | ro | x | cores_en | Enabled cores. |
-
-
-
- |
- HMR_registers.DMR_enable @ 0x8
- DMR configuration enable, on bit per DMR group.
- Reset default = 0x0, mask 0x3f
- |
-
-| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | | |
-
-| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
-DMR_enable |
-
|
-| Bits | Type | Reset | Name | Description |
|---|
| 5:0 | rw | 0x0 | DMR_enable | DMR configuration enable. |
-
-
-
- |
- HMR_registers.TMR_enable @ 0xc
- TMR configuration enable, one bit per TMR group.
- Reset default = 0x0, mask 0xf
- |
-
-| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | | |
-
-| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
-TMR_enable |
-
|
-| Bits | Type | Reset | Name | Description |
|---|
| 3:0 | rw | 0x0 | TMR_enable | TMR configuration enable. |
-
-
-
- |
- HMR_registers.DMR_config @ 0x10
-
- Reset default = 0x0, mask 0x3
- |
-
-| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | | |
-
-| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
-force_recovery |
-rapid_recovery |
-
|
-| Bits | Type | Reset | Name | Description |
|---|
| 0 | rw | x | rapid_recovery | Enable rapid recovery using an additional register file. |
| 1 | rw | x | force_recovery | Forces recovery routine (if rapid_recovery is available). |
-
-
-
- |
- HMR_registers.TMR_config @ 0x14
-
- Reset default = 0x6, mask 0x1f
- |
-
-| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | | |
-
-| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
-force_resynch |
-rapid_recovery |
-reload_setback |
-setback |
-delay_resynch |
-
|
-| Bits | Type | Reset | Name | Description |
|---|
| 0 | rw | 0x0 | delay_resynch | Enable wait-for-restoration |
| 1 | rw | 0x1 | setback | Enable setback (synchronous reset) during re-synch. |
| 2 | rw | 0x1 | reload_setback | Enable setback on mismatch during reload section of re-synch (only possible with setback) |
| 3 | rw | x | rapid_recovery | Enable rapid recovery using additional register file. |
| 4 | rw | 0x0 | force_resynch | Forces a resynchronization routine |
-
diff --git a/rtl/HMR/doc.md b/rtl/HMR/doc.md
deleted file mode 100644
index 892ab665..00000000
--- a/rtl/HMR/doc.md
+++ /dev/null
@@ -1,312 +0,0 @@
-
-
-
-
-The tables describe each key and the type of the value. The following
-types are used:
-
-Type | Description
----- | -----------
-int | integer (binary 0b, octal 0o, decimal, hex 0x)
-xint | x for undefined otherwise int
-bitrange | bit number as decimal integer, or bit-range as decimal integers msb:lsb
-list | comma separated list enclosed in `[]`
-name list | comma separated list enclosed in `[]` of one or more groups that have just name and dscr keys. e.g. `{ name: "name", desc: "description"}`
-name list+ | name list that optionally contains a width
-parameter list | parameter list having default value optionally
-group | comma separated group of key:value enclosed in `{}`
-list of group | comma separated group of key:value enclosed in `{}` the second entry of the list is the sub group format
-string | string, typically short
-text | string, may be multi-line enclosed in `'''` may use `**bold**`, `*italic*` or `!!Reg` markup
-tuple | tuple enclosed in ()
-python int | Native Python type int (generated)
-python Bool | Native Python type Bool (generated)
-python list | Native Python type list (generated)
-python enum | Native Python type enum (generated)
-
-
-Register fields are tagged using the swaccess key to describe the
-permitted access and side-effects. This key must have one of these
-values:
-
-
-Key | Description
---- | -----------
-none | No access
-ro | Read Only
-rc | Read Only, reading clears
-rw | Read/Write
-r0w1c | Read zero, Write with 1 clears
-rw1s | Read, Write with 1 sets
-rw1c | Read, Write with 1 clears
-rw0c | Read, Write with 0 clears
-wo | Write Only
-
-
-Register fields are tagged using the hwaccess key to describe the
-permitted access from hardware logic and side-effects. This key must
-have one of these values:
-
-
-Key | Description
---- | -----------
-hro | Read Only
-hrw | Read/Write
-hwo | Write Only
-none | No Access Needed
-
-
-The top level of the JSON is a group containing the following keys:
-
-Key | Kind | Type | Description of Value
---- | ---- | ---- | --------------------
-name | required | string | name of the component
-clock_primary | required | string | name of the primary clock
-bus_interfaces | required | list | bus interfaces for the device
-registers | required | list | list of register definition groups and offset control groups
-alert_list | optional | name list+ | list of peripheral alerts
-available_inout_list | optional | name list+ | list of available peripheral inouts
-available_input_list | optional | name list+ | list of available peripheral inputs
-available_output_list | optional | name list+ | list of available peripheral outputs
-hier_path | additional hierarchy path before the reg block instance
-interrupt_list | optional | name list+ | list of peripheral interrupts
-inter_signal_list | optional | list | list of inter-module signals
-no_auto_alert_regs | optional | string | Set to true to suppress automatic generation of alert test registers. Defaults to true if no alert_list is present. Otherwise this defaults to false.
-no_auto_intr_regs | optional | string | Set to true to suppress automatic generation of interrupt registers. Defaults to true if no interrupt_list is present. Otherwise this defaults to false.
-other_clock_list | optional | list | list of other chip clocks needed
-other_reset_list | optional | list | list of other resets
-param_list | optional | parameter list | list of parameters of the IP
-regwidth | optional | int | width of registers in bits (default 32)
-reset_primary | optional | string | primary reset used by the module
-reset_request_list | optional | list | list of signals requesting reset
-scan | optional | python Bool | Indicates the module have `scanmode_i`
-scan_reset | optional | python Bool | Indicates the module have `scan_rst_ni`
-scan_en | optional | python Bool | Indicates the module has `scan_en_i`
-SPDX-License-Identifier | optional | string | License ientifier (if using pure json) Only use this if unable to put this information in a comment at the top of the file.
-wakeup_list | optional | name list+ | list of peripheral wakeups
-
-The basic structure of a register definition file is thus:
-
-```hjson
-{
- name: "GP",
- regwidth: "32",
- registers: [
- // register definitions...
- ]
-}
-
-```
-
-
-
-The list of registers includes register definition groups containing the following keys:
-
-Key | Kind | Type | Description of Value
---- | ---- | ---- | --------------------
-name | required | string | name of the register
-desc | required | text | description of the register
-fields | required | list | list of register field description groups
-swaccess | optional | string | software access permission to use for fields that don't specify swaccess
-hwaccess | optional | string | hardware access permission to use for fields that don't specify hwaccess
-hwext | optional | string | 'true' if the register is stored outside of the register module
-hwqe | optional | string | 'true' if hardware uses 'q' enable signal, which is latched signal of software write pulse.
-hwre | optional | string | 'true' if hardware uses 're' signal, which is latched signal of software read pulse.
-regwen | optional | string | if register is write-protected by another register, that register name should be given here. empty-string for no register write protection
-resval | optional | int | reset value of full register (default 0)
-tags | optional | string | tags for the register, following the format 'tag_name:item1:item2...'
-shadowed | optional | string | 'true' if the register is shadowed
-update_err_alert | optional | string | alert that will be triggered if this shadowed register has update error
-storage_err_alert | optional | string | alert that will be triggered if this shadowed register has storage error
-
-
-The basic register definition group will follow this pattern:
-
-```hjson
- { name: "REGA",
- desc: "Description of register",
- swaccess: "rw",
- resval: "42",
- fields: [
- // bit field definitions...
- ]
- }
-```
-
-The name and brief description are required. If the swaccess key is
-provided it describes the access pattern that will be used by all
-bitfields in the register that do not override with their own swaccess
-key. This is a useful shortcut because in most cases a register will
-have the same access restrictions for all fields. The reset value of
-the register may also be provided here or in the individual fields. If
-it is provided in both places then they must match, if it is provided
-in neither place then the reset value defaults to zero for all except
-write-only fields when it defaults to x.
-
-
-
-In the fields list each field definition is a group itself containing the following keys:
-
-Key | Kind | Type | Description of Value
---- | ---- | ---- | --------------------
-bits | required | bitrange | bit or bit range (msb:lsb)
-name | optional | string | name of the field
-desc | optional | text | description of field (required if the field has a name)
-swaccess | optional | string | software access permission, copied from register if not provided in field. (Tool adds if not provided.)
-hwaccess | optional | string | hardware access permission, copied from register if not prvided in field. (Tool adds if not provided.)
-resval | optional | xint | reset value, comes from register resval if not provided in field. Zero if neither are provided and the field is readable, x if neither are provided and the field is wo. Must match if both are provided.
-enum | optional | list | list of permitted enumeration groups
-tags | optional | string | tags for the field, followed by the format 'tag_name:item1:item2...'
-
-
-Field names should be relatively short because they will be used
-frequently (and need to fit in the register layout picture!) The field
-description is expected to be longer and will most likely make use of
-the Hjson ability to include multi-line strings. An example with three
-fields:
-
-```hjson
- fields: [
- { bits: "15:0",
- name: "RXS",
- desc: '''
- Last 16 oversampled values of RX. These are captured at 16x the baud
- rate clock. This is a shift register with the most recent bit in
- bit 0 and the oldest in bit 15. Only valid when ENRXS is set.
- '''
- }
- { bits: "16",
- name: "ENRXS",
- desc: '''
- If this bit is set the receive oversampled data is collected
- in the RXS field.
- '''
- }
- {bits: "20:19", name: "TXILVL",
- desc: "Trigger level for TX interrupts",
- resval: "2",
- enum: [
- { value: "0", name: "txlvl1", desc: "1 character" },
- { value: "1", name: "txlvl4", desc: "4 characters" },
- { value: "2", name: "txlvl8", desc: "8 characters" },
- { value: "3", name: "txlvl16", desc: "16 characters" }
- ]
- }
- ]
-```
-
-In all of these the swaccess parameter is inherited from the register
-level, and will be added so this key is always available to the
-backend. The RXS and ENRXS will default to zero reset value (unless
-something different is provided for the register) and will have the
-key added, but TXILVL expicitly sets its reset value as 2.
-
-The missing bits 17 and 18 will be treated as reserved by the tool, as
-will any bits between 21 and the maximum in the register.
-
-The TXILVL is an example using an enumeration to specify all valid
-values for the field. In this case all possible values are described,
-if the list is incomplete then the field is marked with the rsvdenum
-key so the backend can take appropriate action. (If the enum field is
-more than 7 bits then the checking is not done.)
-
-
-
-Definitions in an enumeration group contain:
-
-Key | Kind | Type | Description of Value
---- | ---- | ---- | --------------------
-name | required | string | name of the member of the enum
-desc | required | text | description when field has this value
-value | required | int | value of this member of the enum
-
-
-The list of registers may include single entry groups to control the offset, open a window or generate registers:
-
-Key | Kind | Type | Description of Value
---- | ---- | ---- | --------------------
-reserved | optional | int | number of registers to reserve space for
-skipto | optional | int | set next register offset to value
-window | optional | group | group defining an address range for something other than standard registers
-multireg | optional | group | group defining registers generated from a base instance.
-
-
-
-
-Registers can protect themselves from software writes by using the
-register attribute regwen. When not an emptry string (the default
-value), regwen indicates that another register must be true in order
-to allow writes to this register. This is useful for the prevention
-of software modification. The register-enable register (call it
-REGWEN) must be one bit in width, and should default to 1 and be rw1c
-for preferred security control. This allows all writes to proceed
-until at some point software disables future modifications by clearing
-REGWEN. An error is reported if REGWEN does not exist, contains more
-than one bit, is not `rw1c` or does not default to 1. One REGWEN can
-protect multiple registers. The REGWEN register must precede those
-registers that refer to it in the .hjson register list. An example:
-
-```hjson
- { name: "REGWEN",
- desc: "Register write enable for a bank of registers",
- swaccess: "rw1c",
- fields: [ { bits: "0", resval: "1" } ]
- }
- { name: "REGA",
- swaccess: "rw",
- regwen: "REGWEN",
- ...
- }
- { name: "REGB",
- swaccess: "rw",
- regwen: "REGWEN",
- ...
- }
-```
-
-
-A window defines an open region of the register space that can be used
-for things that are not registers (for example access to a buffer ram).
-
-
-Key | Kind | Type | Description of Value
---- | ---- | ---- | --------------------
-name | required | string | name of the window
-desc | required | text | description of the window
-items | required | int | size in fieldaccess width words of the window
-swaccess | required | string | software access permitted
-data-intg-passthru | optional | string | True if the window has data integrity pass through. Defaults to false if not present.
-byte-write | optional | string | True if byte writes are supported. Defaults to false if not present.
-validbits | optional | int | Number of valid data bits within regwidth sized word. Defaults to regwidth. If smaller than the regwidth then in each word of the window bits [regwidth-1:validbits] are unused and bits [validbits-1:0] are valid.
-unusual | optional | string | True if window has unusual parameters (set to prevent Unusual: errors).Defaults to false if not present.
-
-
-The multireg expands on the register required fields and will generate
-a list of the generated registers (that contain all required and
-generated keys for an actual register).
-
-
-Key | Kind | Type | Description of Value
---- | ---- | ---- | --------------------
-name | required | string | base name of the registers
-desc | required | text | description of the registers
-count | required | string | number of instances to generate. This field can be integer or string matching from param_list.
-cname | required | string | base name for each instance, mostly useful for referring to instance in messages.
-fields | required | list | list of register field description groups. Describes bit positions used for base instance.
-swaccess | optional | string | software access permission to use for fields that don't specify swaccess
-hwaccess | optional | string | hardware access permission to use for fields that don't specify hwaccess
-hwext | optional | string | 'true' if the register is stored outside of the register module
-hwqe | optional | string | 'true' if hardware uses 'q' enable signal, which is latched signal of software write pulse.
-hwre | optional | string | 'true' if hardware uses 're' signal, which is latched signal of software read pulse.
-regwen | optional | string | if register is write-protected by another register, that register name should be given here. empty-string for no register write protection
-resval | optional | int | reset value of full register (default 0)
-tags | optional | string | tags for the register, following the format 'tag_name:item1:item2...'
-shadowed | optional | string | 'true' if the register is shadowed
-update_err_alert | optional | string | alert that will be triggered if this shadowed register has update error
-storage_err_alert | optional | string | alert that will be triggered if this shadowed register has storage error
-regwen_multi | optional | python Bool | If true, regwen term increments along with current multireg count.
-compact | optional | python Bool | If true, allow multireg compacting.If false, do not compact.
-
-
-(end of output generated by `regtool.py --doc`)
-
diff --git a/rtl/HMR/hmr_all.rdl b/rtl/HMR/hmr_all.rdl
new file mode 100644
index 00000000..a9ed329d
--- /dev/null
+++ b/rtl/HMR/hmr_all.rdl
@@ -0,0 +1,29 @@
+// Copyright 2025 ETH Zurich and University of Bologna.
+// Copyright and related rights are licensed under the Solderpad Hardware
+// License, Version 0.51 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at
+// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+// or agreed to in writing, software, hardware and materials distributed under
+// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+addrmap hmr_all #(
+ longint unsigned NumCores = 12,
+ longint unsigned NumDMRGroups = 6,
+ longint unsigned NumTMRGroups = 4,
+ bit DMRAvailable = 1,
+ bit TMRAvailable = 1
+) {
+ `include "hmr_regs.rdl"
+ `include "hmr_core_regs.rdl"
+ `include "hmr_dmr_regs.rdl"
+ `include "hmr_tmr_regs.rdl"
+
+ hmr hmr @0x0;
+ hmr_core hmr_core[NumCores] @0x100 += 0x10;
+ hmr_dmr hmr_dmr[NumDMRGroups] @0x200 += 0x10;
+ hmr_tmr hmr_tmr[NumTMRGroups] @0x300 += 0x10;
+ hmr_dmr->ispresent = DMRAvailable;
+ hmr_tmr->ispresent = TMRAvailable;
+};
diff --git a/rtl/HMR/hmr_core_regs.rdl b/rtl/HMR/hmr_core_regs.rdl
new file mode 100644
index 00000000..d2527d0b
--- /dev/null
+++ b/rtl/HMR/hmr_core_regs.rdl
@@ -0,0 +1,63 @@
+// Copyright 2025 ETH Zurich and University of Bologna.
+// Copyright and related rights are licensed under the Solderpad Hardware
+// License, Version 0.51 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at
+// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+// or agreed to in writing, software, hardware and materials distributed under
+// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+addrmap hmr_core {
+ reg current_mode {
+ name = "current_mode";
+ desc = "Value to determine wich redundancy mode the core with that ID is in.";
+ field {
+ name = "independent";
+ desc = "1 if in independent mode";
+ sw = r;
+ hw = rw;
+ } independent[0:0] = 0x1;
+ field {
+ name = "dual";
+ desc = "1 if in dual/DMR mode";
+ sw = r;
+ hw = rw;
+ } dual[1:1] = 0x0;
+ field {
+ name = "triple";
+ desc = "1 if in triple/TMR mode";
+ sw = r;
+ hw = rw;
+ } triple[2:2] = 0x0;
+ };
+
+ reg mismatches {
+ name = "mismatches";
+ desc = "Number of mismatches detected in the core.";
+ field {
+ name = "mismatches";
+ desc = "Number of mismatches detected in the core.";
+ sw = rw;
+ hw = rw;
+ woclr;
+ we = true;
+ } mismatches[31:0] = 0x0;
+ };
+
+ reg sp_store {
+ name = "sp_store";
+ desc = "Stack pointer storage register.";
+ field {
+ name = "sp_store";
+ desc = "Stack Pointer";
+ sw = rw;
+ hw = r;
+ swmod = true;
+ } sp_store[31:0] = 0x0;
+ };
+
+ external current_mode current_mode;
+ mismatches mismatches;
+ sp_store sp_store;
+};
diff --git a/rtl/HMR/hmr_core_regs_reg_pkg.sv b/rtl/HMR/hmr_core_regs_reg_pkg.sv
index 602bd91a..3dc97194 100644
--- a/rtl/HMR/hmr_core_regs_reg_pkg.sv
+++ b/rtl/HMR/hmr_core_regs_reg_pkg.sv
@@ -1,80 +1,63 @@
-// 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
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+// https://github.com/SystemRDL/PeakRDL-regblock
package hmr_core_regs_reg_pkg;
- // Address widths within the block
- parameter int BlockAw = 4;
-
- ////////////////////////////
- // Typedefs for registers //
- ////////////////////////////
-
- typedef struct packed {
- logic [31:0] q;
- } hmr_core_regs_reg2hw_mismatches_reg_t;
-
- typedef struct packed {
- logic [31:0] q;
- logic qe;
- } hmr_core_regs_reg2hw_sp_store_reg_t;
-
- typedef struct packed {
- struct packed {
- logic d;
- } independent;
- struct packed {
- logic d;
- } dual;
- struct packed {
- logic d;
- } triple;
- } hmr_core_regs_hw2reg_current_mode_reg_t;
-
- typedef struct packed {
- logic [31:0] d;
- logic de;
- } hmr_core_regs_hw2reg_mismatches_reg_t;
-
- // Register -> HW type
- typedef struct packed {
- hmr_core_regs_reg2hw_mismatches_reg_t mismatches; // [64:33]
- hmr_core_regs_reg2hw_sp_store_reg_t sp_store; // [32:0]
- } hmr_core_regs_reg2hw_t;
-
- // HW -> register type
- typedef struct packed {
- hmr_core_regs_hw2reg_current_mode_reg_t current_mode; // [35:33]
- hmr_core_regs_hw2reg_mismatches_reg_t mismatches; // [32:0]
- } hmr_core_regs_hw2reg_t;
-
- // Register offsets
- parameter logic [BlockAw-1:0] HMR_CORE_REGS_CURRENT_MODE_OFFSET = 4'h 0;
- parameter logic [BlockAw-1:0] HMR_CORE_REGS_MISMATCHES_OFFSET = 4'h 4;
- parameter logic [BlockAw-1:0] HMR_CORE_REGS_SP_STORE_OFFSET = 4'h 8;
-
- // Reset values for hwext registers and their fields
- parameter logic [2:0] HMR_CORE_REGS_CURRENT_MODE_RESVAL = 3'h 1;
- parameter logic [0:0] HMR_CORE_REGS_CURRENT_MODE_INDEPENDENT_RESVAL = 1'h 1;
- parameter logic [0:0] HMR_CORE_REGS_CURRENT_MODE_DUAL_RESVAL = 1'h 0;
- parameter logic [0:0] HMR_CORE_REGS_CURRENT_MODE_TRIPLE_RESVAL = 1'h 0;
-
- // Register index
- typedef enum int {
- HMR_CORE_REGS_CURRENT_MODE,
- HMR_CORE_REGS_MISMATCHES,
- HMR_CORE_REGS_SP_STORE
- } hmr_core_regs_id_e;
-
- // Register width information to check illegal writes
- parameter logic [3:0] HMR_CORE_REGS_PERMIT [3] = '{
- 4'b 0001, // index[0] HMR_CORE_REGS_CURRENT_MODE
- 4'b 1111, // index[1] HMR_CORE_REGS_MISMATCHES
- 4'b 1111 // index[2] HMR_CORE_REGS_SP_STORE
- };
-
+ localparam HMR_CORE_REGS_REG_TOP_DATA_WIDTH = 32;
+ localparam HMR_CORE_REGS_REG_TOP_MIN_ADDR_WIDTH = 4;
+ localparam HMR_CORE_REGS_REG_TOP_SIZE = 'hc;
+
+ typedef struct packed {
+ logic [28:0] _reserved_31_3;
+ logic triple;
+ logic dual;
+ logic independent;
+ } hmr_core__current_mode__external__fields__in_t;
+
+ typedef struct {
+ logic rd_ack;
+ hmr_core__current_mode__external__fields__in_t rd_data;
+ } hmr_core__current_mode__external__in_t;
+
+ typedef struct {
+ logic [31:0] next;
+ logic we;
+ } hmr_core__mismatches__mismatches__in_t;
+
+ typedef struct {
+ hmr_core__mismatches__mismatches__in_t mismatches;
+ } hmr_core__mismatches__in_t;
+
+ typedef struct {
+ hmr_core__current_mode__external__in_t current_mode;
+ hmr_core__mismatches__in_t mismatches;
+ } hmr_core__in_t;
+
+ typedef struct {
+ logic req;
+ logic req_is_wr;
+ } hmr_core__current_mode__external__out_t;
+
+ typedef struct {
+ logic [31:0] value;
+ } hmr_core__mismatches__mismatches__out_t;
+
+ typedef struct {
+ hmr_core__mismatches__mismatches__out_t mismatches;
+ } hmr_core__mismatches__out_t;
+
+ typedef struct {
+ logic [31:0] value;
+ logic swmod;
+ } hmr_core__sp_store__sp_store__out_t;
+
+ typedef struct {
+ hmr_core__sp_store__sp_store__out_t sp_store;
+ } hmr_core__sp_store__out_t;
+
+ typedef struct {
+ hmr_core__current_mode__external__out_t current_mode;
+ hmr_core__mismatches__out_t mismatches;
+ hmr_core__sp_store__out_t sp_store;
+ } hmr_core__out_t;
endpackage
-
diff --git a/rtl/HMR/hmr_core_regs_reg_top.sv b/rtl/HMR/hmr_core_regs_reg_top.sv
index d9cf8ceb..47a58eac 100644
--- a/rtl/HMR/hmr_core_regs_reg_top.sv
+++ b/rtl/HMR/hmr_core_regs_reg_top.sv
@@ -1,306 +1,277 @@
-// 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`
-
-
-`include "common_cells/assertions.svh"
-
-module hmr_core_regs_reg_top #(
- parameter type reg_req_t = logic,
- parameter type reg_rsp_t = logic,
- parameter int AW = 4
-) (
- input logic clk_i,
- input logic rst_ni,
- input reg_req_t reg_req_i,
- output reg_rsp_t reg_rsp_o,
- // To HW
- output hmr_core_regs_reg_pkg::hmr_core_regs_reg2hw_t reg2hw, // Write
- input hmr_core_regs_reg_pkg::hmr_core_regs_hw2reg_t hw2reg, // Read
-
-
- // Config
- input devmode_i // If 1, explicit error return for unmapped register access
-);
-
- import hmr_core_regs_reg_pkg::* ;
-
- localparam int DW = 32;
- localparam int 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;
-
- // Below register interface can be changed
- reg_req_t reg_intf_req;
- reg_rsp_t reg_intf_rsp;
-
-
- assign reg_intf_req = reg_req_i;
- assign reg_rsp_o = reg_intf_rsp;
-
-
- assign reg_we = reg_intf_req.valid & reg_intf_req.write;
- assign reg_re = reg_intf_req.valid & ~reg_intf_req.write;
- assign reg_addr = reg_intf_req.addr;
- assign reg_wdata = reg_intf_req.wdata;
- assign reg_be = reg_intf_req.wstrb;
- assign reg_intf_rsp.rdata = reg_rdata;
- assign reg_intf_rsp.error = reg_error;
- assign reg_intf_rsp.ready = 1'b1;
-
- assign reg_rdata = reg_rdata_next ;
- assign reg_error = (devmode_i & addrmiss) | wr_err;
-
-
- // Define SW related signals
- // Format: __{wd|we|qs}
- // or _{wd|we|qs} if field == 1 or 0
- logic current_mode_independent_qs;
- logic current_mode_independent_re;
- logic current_mode_dual_qs;
- logic current_mode_dual_re;
- logic current_mode_triple_qs;
- logic current_mode_triple_re;
- logic [31:0] mismatches_qs;
- logic [31:0] mismatches_wd;
- logic mismatches_we;
- logic [31:0] sp_store_qs;
- logic [31:0] sp_store_wd;
- logic sp_store_we;
-
- // Register instances
- // R[current_mode]: V(True)
-
- // F[independent]: 0:0
- prim_subreg_ext #(
- .DW (1)
- ) u_current_mode_independent (
- .re (current_mode_independent_re),
- .we (1'b0),
- .wd ('0),
- .d (hw2reg.current_mode.independent.d),
- .qre (),
- .qe (),
- .q (),
- .qs (current_mode_independent_qs)
- );
-
-
- // F[dual]: 1:1
- prim_subreg_ext #(
- .DW (1)
- ) u_current_mode_dual (
- .re (current_mode_dual_re),
- .we (1'b0),
- .wd ('0),
- .d (hw2reg.current_mode.dual.d),
- .qre (),
- .qe (),
- .q (),
- .qs (current_mode_dual_qs)
- );
-
-
- // F[triple]: 2:2
- prim_subreg_ext #(
- .DW (1)
- ) u_current_mode_triple (
- .re (current_mode_triple_re),
- .we (1'b0),
- .wd ('0),
- .d (hw2reg.current_mode.triple.d),
- .qre (),
- .qe (),
- .q (),
- .qs (current_mode_triple_qs)
- );
-
-
- // R[mismatches]: V(False)
-
- prim_subreg #(
- .DW (32),
- .SWACCESS("W0C"),
- .RESVAL (32'h0)
- ) u_mismatches (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (mismatches_we),
- .wd (mismatches_wd),
-
- // from internal hardware
- .de (hw2reg.mismatches.de),
- .d (hw2reg.mismatches.d ),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.mismatches.q ),
-
- // to register interface (read)
- .qs (mismatches_qs)
- );
-
-
- // R[sp_store]: V(False)
-
- prim_subreg #(
- .DW (32),
- .SWACCESS("RW"),
- .RESVAL (32'h0)
- ) u_sp_store (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (sp_store_we),
- .wd (sp_store_wd),
-
- // from internal hardware
- .de (1'b0),
- .d ('0 ),
-
- // to internal hardware
- .qe (reg2hw.sp_store.qe),
- .q (reg2hw.sp_store.q ),
-
- // to register interface (read)
- .qs (sp_store_qs)
- );
-
-
-
-
- logic [2:0] addr_hit;
- always_comb begin
- addr_hit = '0;
- addr_hit[0] = (reg_addr == HMR_CORE_REGS_CURRENT_MODE_OFFSET);
- addr_hit[1] = (reg_addr == HMR_CORE_REGS_MISMATCHES_OFFSET);
- addr_hit[2] = (reg_addr == HMR_CORE_REGS_SP_STORE_OFFSET);
- end
-
- assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
-
- // Check sub-word write is permitted
- always_comb begin
- wr_err = (reg_we &
- ((addr_hit[0] & (|(HMR_CORE_REGS_PERMIT[0] & ~reg_be))) |
- (addr_hit[1] & (|(HMR_CORE_REGS_PERMIT[1] & ~reg_be))) |
- (addr_hit[2] & (|(HMR_CORE_REGS_PERMIT[2] & ~reg_be)))));
- end
-
- assign current_mode_independent_re = addr_hit[0] & reg_re & !reg_error;
-
- assign current_mode_dual_re = addr_hit[0] & reg_re & !reg_error;
-
- assign current_mode_triple_re = addr_hit[0] & reg_re & !reg_error;
-
- assign mismatches_we = addr_hit[1] & reg_we & !reg_error;
- assign mismatches_wd = reg_wdata[31:0];
-
- assign sp_store_we = addr_hit[2] & reg_we & !reg_error;
- assign sp_store_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] = current_mode_independent_qs;
- reg_rdata_next[1] = current_mode_dual_qs;
- reg_rdata_next[2] = current_mode_triple_qs;
- end
-
- addr_hit[1]: begin
- reg_rdata_next[31:0] = mismatches_qs;
- end
-
- addr_hit[2]: begin
- reg_rdata_next[31:0] = sp_store_qs;
- end
-
- default: begin
- reg_rdata_next = '1;
- end
- endcase
- end
-
- // Unused signal tieoff
-
- // wdata / byte enable are not always fully used
- // add a blanket unused statement to handle lint waivers
- logic unused_wdata;
- logic unused_be;
- assign unused_wdata = ^reg_wdata;
- assign unused_be = ^reg_be;
-
- // Assertions for Register Interface
- `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit))
-
-endmodule
-
-module hmr_core_regs_reg_top_intf
-#(
- parameter int AW = 4,
- localparam int DW = 32
-) (
- input logic clk_i,
- input logic rst_ni,
- REG_BUS.in regbus_slave,
- // To HW
- output hmr_core_regs_reg_pkg::hmr_core_regs_reg2hw_t reg2hw, // Write
- input hmr_core_regs_reg_pkg::hmr_core_regs_hw2reg_t hw2reg, // Read
- // Config
- input devmode_i // If 1, explicit error return for unmapped register access
-);
- localparam int unsigned STRB_WIDTH = DW/8;
-
-`include "register_interface/typedef.svh"
-`include "register_interface/assign.svh"
-
- // Define structs for reg_bus
- typedef logic [AW-1:0] addr_t;
- typedef logic [DW-1:0] data_t;
- typedef logic [STRB_WIDTH-1:0] strb_t;
- `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t)
-
- reg_bus_req_t s_reg_req;
- reg_bus_rsp_t s_reg_rsp;
-
- // Assign SV interface to structs
- `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave)
- `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp)
-
-
-
- hmr_core_regs_reg_top #(
- .reg_req_t(reg_bus_req_t),
- .reg_rsp_t(reg_bus_rsp_t),
- .AW(AW)
- ) i_regs (
- .clk_i,
- .rst_ni,
- .reg_req_i(s_reg_req),
- .reg_rsp_o(s_reg_rsp),
- .reg2hw, // Write
- .hw2reg, // Read
- .devmode_i
- );
-
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+// https://github.com/SystemRDL/PeakRDL-regblock
+
+module hmr_core_regs_reg_top (
+ input wire clk,
+ input wire arst_n,
+
+ input wire s_apb_psel,
+ input wire s_apb_penable,
+ input wire s_apb_pwrite,
+ input wire [2:0] s_apb_pprot,
+ input wire [3:0] s_apb_paddr,
+ input wire [31:0] s_apb_pwdata,
+ input wire [3:0] s_apb_pstrb,
+ output logic s_apb_pready,
+ output logic [31:0] s_apb_prdata,
+ output logic s_apb_pslverr,
+
+ input hmr_core_regs_reg_pkg::hmr_core__in_t hwif_in,
+ output hmr_core_regs_reg_pkg::hmr_core__out_t hwif_out
+ );
+
+ //--------------------------------------------------------------------------
+ // CPU Bus interface logic
+ //--------------------------------------------------------------------------
+ logic cpuif_req;
+ logic cpuif_req_is_wr;
+ logic [3:0] cpuif_addr;
+ logic [31:0] cpuif_wr_data;
+ logic [31:0] cpuif_wr_biten;
+ logic cpuif_req_stall_wr;
+ logic cpuif_req_stall_rd;
+
+ logic cpuif_rd_ack;
+ logic cpuif_rd_err;
+ logic [31:0] cpuif_rd_data;
+
+ logic cpuif_wr_ack;
+ logic cpuif_wr_err;
+
+ // Request
+ logic is_active;
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ is_active <= '0;
+ cpuif_req <= '0;
+ cpuif_req_is_wr <= '0;
+ cpuif_addr <= '0;
+ cpuif_wr_data <= '0;
+ cpuif_wr_biten <= '0;
+ end else begin
+ if(~is_active) begin
+ if(s_apb_psel) begin
+ is_active <= '1;
+ cpuif_req <= '1;
+ cpuif_req_is_wr <= s_apb_pwrite;
+ cpuif_addr <= {s_apb_paddr[3:2], 2'b0};
+ cpuif_wr_data <= s_apb_pwdata;
+ for(int i=0; i<4; i++) begin
+ cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}};
+ end
+ end
+ end else begin
+ cpuif_req <= '0;
+ if(cpuif_rd_ack || cpuif_wr_ack) begin
+ is_active <= '0;
+ end
+ end
+ end
+ end
+
+ // Response
+ assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack;
+ assign s_apb_prdata = cpuif_rd_data;
+ assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err;
+
+ logic cpuif_req_masked;
+ logic external_req;
+ logic external_pending;
+ logic external_wr_ack;
+ logic external_rd_ack;
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ external_pending <= '0;
+ end else begin
+ if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1;
+ else if(external_wr_ack | external_rd_ack) external_pending <= '0;
+ `ifndef SYNTHESIS
+ assert_bad_ext_wr_ack: assert(!external_wr_ack || (external_pending | external_req))
+ else $error("An external wr_ack strobe was asserted when no external request was active");
+ assert_bad_ext_rd_ack: assert(!external_rd_ack || (external_pending | external_req))
+ else $error("An external rd_ack strobe was asserted when no external request was active");
+ `endif
+ end
+ end
+
+ // Read & write latencies are balanced. Stalls not required
+ // except if external
+ assign cpuif_req_stall_rd = external_pending;
+ assign cpuif_req_stall_wr = external_pending;
+ assign cpuif_req_masked = cpuif_req
+ & !(!cpuif_req_is_wr & cpuif_req_stall_rd)
+ & !(cpuif_req_is_wr & cpuif_req_stall_wr);
+
+ //--------------------------------------------------------------------------
+ // Address Decode
+ //--------------------------------------------------------------------------
+ typedef struct {
+ logic current_mode;
+ logic mismatches;
+ logic sp_store;
+ } decoded_reg_strb_t;
+ decoded_reg_strb_t decoded_reg_strb;
+ logic decoded_strb_is_external;
+
+ logic decoded_req;
+ logic decoded_req_is_wr;
+ logic [31:0] decoded_wr_data;
+ logic [31:0] decoded_wr_biten;
+
+ always_comb begin
+ automatic logic is_external;
+ is_external = '0;
+ decoded_reg_strb.current_mode = cpuif_req_masked & (cpuif_addr == 4'h0);
+ is_external |= cpuif_req_masked & (cpuif_addr == 4'h0) & !cpuif_req_is_wr;
+ decoded_reg_strb.mismatches = cpuif_req_masked & (cpuif_addr == 4'h4);
+ decoded_reg_strb.sp_store = cpuif_req_masked & (cpuif_addr == 4'h8);
+ decoded_strb_is_external = is_external;
+ external_req = is_external;
+ end
+
+ // Pass down signals to next stage
+ assign decoded_req = cpuif_req_masked;
+ assign decoded_req_is_wr = cpuif_req_is_wr;
+ assign decoded_wr_data = cpuif_wr_data;
+ assign decoded_wr_biten = cpuif_wr_biten;
+
+ //--------------------------------------------------------------------------
+ // Field logic
+ //--------------------------------------------------------------------------
+ typedef struct {
+ struct {
+ struct {
+ logic [31:0] next;
+ logic load_next;
+ } mismatches;
+ } mismatches;
+ struct {
+ struct {
+ logic [31:0] next;
+ logic load_next;
+ } sp_store;
+ } sp_store;
+ } field_combo_t;
+ field_combo_t field_combo;
+
+ typedef struct {
+ struct {
+ struct {
+ logic [31:0] value;
+ } mismatches;
+ } mismatches;
+ struct {
+ struct {
+ logic [31:0] value;
+ } sp_store;
+ } sp_store;
+ } field_storage_t;
+ field_storage_t field_storage;
+
+
+ assign hwif_out.current_mode.req = !decoded_req_is_wr ? decoded_reg_strb.current_mode : '0;
+ assign hwif_out.current_mode.req_is_wr = decoded_req_is_wr;
+ // Field: hmr_core.mismatches.mismatches
+ always_comb begin
+ automatic logic [31:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.mismatches.mismatches.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.mismatches && decoded_req_is_wr) begin // SW write 1 clear
+ next_c = field_storage.mismatches.mismatches.value & ~(decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
+ load_next_c = '1;
+ end else if(hwif_in.mismatches.mismatches.we) begin // HW Write - we
+ next_c = hwif_in.mismatches.mismatches.next;
+ load_next_c = '1;
+ end
+ field_combo.mismatches.mismatches.next = next_c;
+ field_combo.mismatches.mismatches.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.mismatches.mismatches.value <= 32'h0;
+ end else begin
+ if(field_combo.mismatches.mismatches.load_next) begin
+ field_storage.mismatches.mismatches.value <= field_combo.mismatches.mismatches.next;
+ end
+ end
+ end
+ assign hwif_out.mismatches.mismatches.value = field_storage.mismatches.mismatches.value;
+ // Field: hmr_core.sp_store.sp_store
+ always_comb begin
+ automatic logic [31:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.sp_store.sp_store.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.sp_store && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.sp_store.sp_store.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
+ load_next_c = '1;
+ end
+ field_combo.sp_store.sp_store.next = next_c;
+ field_combo.sp_store.sp_store.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.sp_store.sp_store.value <= 32'h0;
+ end else begin
+ if(field_combo.sp_store.sp_store.load_next) begin
+ field_storage.sp_store.sp_store.value <= field_combo.sp_store.sp_store.next;
+ end
+ end
+ end
+ assign hwif_out.sp_store.sp_store.value = field_storage.sp_store.sp_store.value;
+ assign hwif_out.sp_store.sp_store.swmod = decoded_reg_strb.sp_store && decoded_req_is_wr && |(decoded_wr_biten[31:0]);
+
+ //--------------------------------------------------------------------------
+ // Write response
+ //--------------------------------------------------------------------------
+ always_comb begin
+ automatic logic wr_ack;
+ wr_ack = '0;
+
+ external_wr_ack = wr_ack;
+ end
+ assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external);
+ // Writes are always granted with no error response
+ assign cpuif_wr_err = '0;
+
+ //--------------------------------------------------------------------------
+ // Readback
+ //--------------------------------------------------------------------------
+ logic readback_external_rd_ack_c;
+ always_comb begin
+ automatic logic rd_ack;
+ rd_ack = '0;
+ rd_ack |= hwif_in.current_mode.rd_ack;
+ readback_external_rd_ack_c = rd_ack;
+ end
+
+ logic readback_external_rd_ack;
+
+ assign readback_external_rd_ack = readback_external_rd_ack_c;
+
+ logic readback_err;
+ logic readback_done;
+ logic [31:0] readback_data;
+
+ // Assign readback values to a flattened array
+ logic [31:0] readback_array[3];
+ assign readback_array[0] = hwif_in.current_mode.rd_ack ? hwif_in.current_mode.rd_data : '0;
+ assign readback_array[1][31:0] = (decoded_reg_strb.mismatches && !decoded_req_is_wr) ? field_storage.mismatches.mismatches.value : '0;
+ assign readback_array[2][31:0] = (decoded_reg_strb.sp_store && !decoded_req_is_wr) ? field_storage.sp_store.sp_store.value : '0;
+
+ // Reduce the array
+ always_comb begin
+ automatic logic [31:0] readback_data_var;
+ readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external;
+ readback_err = '0;
+ readback_data_var = '0;
+ for(int i=0; i<3; i++) readback_data_var |= readback_array[i];
+ readback_data = readback_data_var;
+ end
+
+ assign external_rd_ack = readback_external_rd_ack;
+ assign cpuif_rd_ack = readback_done | readback_external_rd_ack;
+ assign cpuif_rd_data = readback_data;
+ assign cpuif_rd_err = readback_err;
endmodule
-
-
diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv
index ad74eab0..244aecd5 100644
--- a/rtl/HMR/hmr_dmr_ctrl.sv
+++ b/rtl/HMR/hmr_dmr_ctrl.sv
@@ -18,16 +18,16 @@ module hmr_dmr_ctrl
parameter bit DMRFixed = 1'b0,
parameter bit DefaultInDMR = DMRFixed ? 1'b1 : 1'b0,
parameter bit RapidRecovery = 1'b0,
- parameter type reg_req_t = logic,
- parameter type reg_resp_t = logic
+ parameter type apb_req_t = logic,
+ parameter type apb_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
// input logic test_enable_i,
// Register interface
- input reg_req_t reg_req_i,
- output reg_resp_t reg_resp_o,
+ input apb_req_t reg_req_i,
+ output apb_resp_t reg_resp_o,
// CTRL from external (e.g. HMR ctrl regs)
input logic dmr_enable_q_i,
@@ -60,39 +60,45 @@ module hmr_dmr_ctrl
typedef enum logic [2:0] {NON_DMR, DMR_RUN, DMR_RESTORE} dmr_mode_e;
localparam dmr_mode_e DefaultDMRMode = DefaultInDMR || DMRFixed ? DMR_RUN : NON_DMR;
- hmr_dmr_regs_reg_pkg::hmr_dmr_regs_reg2hw_t dmr_reg2hw;
- hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t dmr_hw2reg;
+ hmr_dmr_regs_reg_pkg::hmr_dmr__out_t dmr_reg2hw;
+ hmr_dmr_regs_reg_pkg::hmr_dmr__in_t dmr_hw2reg;
dmr_mode_e dmr_red_mode_d, dmr_red_mode_q;
assign grp_in_independent_o = dmr_red_mode_q == NON_DMR;
- assign rapid_recovery_en_o = dmr_reg2hw.dmr_config.rapid_recovery.q && RapidRecovery;
+ assign rapid_recovery_en_o = dmr_reg2hw.dmr_config.rapid_recovery.value && RapidRecovery;
assign sw_synch_req_o = synch_req & ~synch_req_sent_q;
assign synch_req_sent_d = synch_req;
assign sw_resynch_req_o = resynch_req & ~resynch_req_sent_q;
assign resynch_req_sent_d = resynch_req;
- assign checkpoint_o = dmr_reg2hw.checkpoint_addr.q;
-
- hmr_dmr_regs_reg_top #(
- .reg_req_t(reg_req_t),
- .reg_rsp_t(reg_resp_t)
- ) i_dmr_regs (
- .clk_i,
- .rst_ni,
- .reg_req_i(reg_req_i),
- .reg_rsp_o(reg_resp_o),
- .reg2hw (dmr_reg2hw),
- .hw2reg (dmr_hw2reg),
- .devmode_i('0)
+ assign checkpoint_o = dmr_reg2hw.checkpoint_addr.checkpoint_addr.value;
+
+ hmr_dmr_regs_reg_top i_dmr_regs (
+ .clk(clk_i),
+ .arst_n(rst_ni),
+ .s_apb_psel(reg_req_i.psel),
+ .s_apb_penable(apb_req_i.penable),
+ .s_apb_pwrite(apb_req_i.pwrite),
+ .s_apb_pprot(apb_req_i.pprot),
+ .s_apb_paddr(apb_req_i.paddr[3:0]),
+ .s_apb_pwdata(apb_req_i.pwdata),
+ .s_apb_pstrb(apb_req_i.pstrb),
+ .s_apb_pready(apb_resp_o.pready),
+ .s_apb_prdata(apb_resp_o.prdata),
+ .s_apb_pslverr(apb_resp_o.pslverr),
+ .hwif_in(dmr_hw2reg),
+ .hwif_out(dmr_reg2hw)
);
// Global config update
- assign dmr_hw2reg.dmr_enable.de = dmr_enable_qe_i;
- assign dmr_hw2reg.dmr_enable.d = dmr_enable_q_i;
- assign dmr_hw2reg.dmr_config.rapid_recovery.de = rapid_recovery_qe_i || ~RapidRecovery;
- assign dmr_hw2reg.dmr_config.rapid_recovery.d = rapid_recovery_q_i && RapidRecovery;
- assign dmr_hw2reg.dmr_config.force_recovery.d = force_recovery_qe_i ? force_recovery_q_i : 1'b0;
+ assign dmr_hw2reg.dmr_enable.dmr_enable.we = dmr_enable_qe_i;
+ assign dmr_hw2reg.dmr_enable.dmr_enable.next = dmr_enable_q_i;
+ assign dmr_hw2reg.dmr_config.rapid_recovery.we = rapid_recovery_qe_i || ~RapidRecovery;
+ assign dmr_hw2reg.dmr_config.rapid_recovery.next = rapid_recovery_q_i && RapidRecovery;
+ assign dmr_hw2reg.dmr_config.force_recovery.next = force_recovery_qe_i ?
+ force_recovery_q_i :
+ 1'b0;
/**************************
* FSM for DMR lockstep *
@@ -106,24 +112,24 @@ module hmr_dmr_ctrl
resynch_req = 1'b0;
synch_req = 1'b0;
- dmr_hw2reg.dmr_config.force_recovery.de = force_recovery_qe_i;
+ dmr_hw2reg.dmr_config.force_recovery.we = force_recovery_qe_i;
case (dmr_red_mode_q)
DMR_RUN: begin
// If forced execute recovery
- if (dmr_reg2hw.dmr_config.force_recovery.q && RapidRecovery &&
- dmr_reg2hw.dmr_config.rapid_recovery.q) begin
- dmr_hw2reg.dmr_config.force_recovery.de = 1'b1;
+ if (dmr_reg2hw.dmr_config.force_recovery.value && RapidRecovery &&
+ dmr_reg2hw.dmr_config.rapid_recovery.value) begin
+ dmr_hw2reg.dmr_config.force_recovery.we = 1'b1;
dmr_red_mode_d = DMR_RESTORE;
end
// If error detected, restore
- if (dmr_error_i && RapidRecovery && dmr_reg2hw.dmr_config.rapid_recovery.q) begin
+ if (dmr_error_i && RapidRecovery && dmr_reg2hw.dmr_config.rapid_recovery.value) begin
$display("[HMR-dual] %t - mismatch detected, rapid recovery starting", $realtime);
dmr_red_mode_d = DMR_RESTORE;
end
- if (dmr_error_i && (!RapidRecovery || !dmr_reg2hw.dmr_config.rapid_recovery.q)) begin
+ if (dmr_error_i && (!RapidRecovery || !dmr_reg2hw.dmr_config.rapid_recovery.value)) begin
$display("[HMR-dual] %t - mismatch detected, SW trigger", $realtime);
resynch_req = 1'b1;
end
@@ -144,10 +150,10 @@ module hmr_dmr_ctrl
// Logic to switch in and out of DMR
if (!DMRFixed) begin
// Set DMR mode on external signal that cores are synchronized
- if (dmr_red_mode_q == NON_DMR && dmr_reg2hw.dmr_enable.q == 1'b1) begin
+ if (dmr_red_mode_q == NON_DMR && dmr_reg2hw.dmr_enable.dmr_enable.value == 1'b1) begin
synch_req = 1'b1;
if (cores_synch_q == 1'b1) begin
- if (dmr_reg2hw.dmr_config.rapid_recovery.q == 1'b1) begin
+ if (dmr_reg2hw.dmr_config.rapid_recovery.value == 1'b1) begin
dmr_red_mode_d = DMR_RESTORE;
end else begin
dmr_red_mode_d = DMR_RUN;
@@ -157,7 +163,7 @@ module hmr_dmr_ctrl
end
// Before core startup: set DMR mode from reg2hw.dmr_enable
if (fetch_en_i == 0) begin
- if (dmr_reg2hw.dmr_enable.q == 1'b0) begin
+ if (dmr_reg2hw.dmr_enable.dmr_enable.value == 1'b0) begin
dmr_red_mode_d = NON_DMR;
end else begin
synch_req = 1'b0;
@@ -166,7 +172,7 @@ module hmr_dmr_ctrl
end
// split tolerant mode to performance mode anytime (but require correct core state)
if (dmr_red_mode_q == DMR_RUN) begin
- if (dmr_reg2hw.dmr_enable.q == 1'b0) begin
+ if (dmr_reg2hw.dmr_enable.dmr_enable.value == 1'b0) begin
dmr_red_mode_d = NON_DMR;
setback_o = 2'b10;
end
diff --git a/rtl/HMR/hmr_dmr_regs.rdl b/rtl/HMR/hmr_dmr_regs.rdl
new file mode 100644
index 00000000..1d17fff2
--- /dev/null
+++ b/rtl/HMR/hmr_dmr_regs.rdl
@@ -0,0 +1,59 @@
+// Copyright 2025 ETH Zurich and University of Bologna.
+// Copyright and related rights are licensed under the Solderpad Hardware
+// License, Version 0.51 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at
+// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+// or agreed to in writing, software, hardware and materials distributed under
+// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+addrmap hmr_dmr {
+ reg dmr_enable {
+ name = "dmr_enable";
+ desc = "DMR Configuration Enable";
+ field {
+ name = "enable";
+ desc = "Enable DMR mode";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } dmr_enable[0:0] = 0x0;
+ };
+ reg dmr_config {
+ name = "dmr_config";
+ desc = "DMR Configuration Register";
+ field {
+ name = "rapid_recovery";
+ desc = "Enable rapid recovery using an additional register file.";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } rapid_recovery[0:0] = 0x0;
+ field {
+ name = "force_recovery";
+ desc = "Forces recovery routine (if rapid_recovery is available).";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } force_recovery[1:1] = 0x0;
+ };
+ reg checkpoint_addr {
+ name = "checkpoint_addr";
+ desc = "Address for the last checkpoint.";
+ field {
+ name = "checkpoint_addr";
+ desc = "Address for the last checkpoint.";
+ sw = rw;
+ hw = r;
+ // swmod = true;
+ } checkpoint_addr[31:0] = 0x0;
+ };
+
+ dmr_enable dmr_enable;
+ dmr_config dmr_config;
+ checkpoint_addr checkpoint_addr;
+};
diff --git a/rtl/HMR/hmr_dmr_regs_reg_pkg.sv b/rtl/HMR/hmr_dmr_regs_reg_pkg.sv
index 95199d4c..9800a335 100644
--- a/rtl/HMR/hmr_dmr_regs_reg_pkg.sv
+++ b/rtl/HMR/hmr_dmr_regs_reg_pkg.sv
@@ -1,92 +1,73 @@
-// 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
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+// https://github.com/SystemRDL/PeakRDL-regblock
package hmr_dmr_regs_reg_pkg;
- // Address widths within the block
- parameter int BlockAw = 4;
-
- ////////////////////////////
- // Typedefs for registers //
- ////////////////////////////
-
- typedef struct packed {
- logic q;
- logic qe;
- } hmr_dmr_regs_reg2hw_dmr_enable_reg_t;
-
- typedef struct packed {
- struct packed {
- logic q;
- logic qe;
- } rapid_recovery;
- struct packed {
- logic q;
- logic qe;
- } force_recovery;
- } hmr_dmr_regs_reg2hw_dmr_config_reg_t;
-
- typedef struct packed {
- logic [31:0] q;
- logic qe;
- } hmr_dmr_regs_reg2hw_checkpoint_addr_reg_t;
-
- typedef struct packed {
- logic d;
- logic de;
- } hmr_dmr_regs_hw2reg_dmr_enable_reg_t;
-
- typedef struct packed {
- struct packed {
- logic d;
- logic de;
- } rapid_recovery;
- struct packed {
- logic d;
- logic de;
- } force_recovery;
- } hmr_dmr_regs_hw2reg_dmr_config_reg_t;
-
- typedef struct packed {
- logic [31:0] d;
- logic de;
- } hmr_dmr_regs_hw2reg_checkpoint_addr_reg_t;
-
- // Register -> HW type
- typedef struct packed {
- hmr_dmr_regs_reg2hw_dmr_enable_reg_t dmr_enable; // [38:37]
- hmr_dmr_regs_reg2hw_dmr_config_reg_t dmr_config; // [36:33]
- hmr_dmr_regs_reg2hw_checkpoint_addr_reg_t checkpoint_addr; // [32:0]
- } hmr_dmr_regs_reg2hw_t;
-
- // HW -> register type
- typedef struct packed {
- hmr_dmr_regs_hw2reg_dmr_enable_reg_t dmr_enable; // [38:37]
- hmr_dmr_regs_hw2reg_dmr_config_reg_t dmr_config; // [36:33]
- hmr_dmr_regs_hw2reg_checkpoint_addr_reg_t checkpoint_addr; // [32:0]
- } hmr_dmr_regs_hw2reg_t;
-
- // Register offsets
- parameter logic [BlockAw-1:0] HMR_DMR_REGS_DMR_ENABLE_OFFSET = 4'h 0;
- parameter logic [BlockAw-1:0] HMR_DMR_REGS_DMR_CONFIG_OFFSET = 4'h 4;
- parameter logic [BlockAw-1:0] HMR_DMR_REGS_CHECKPOINT_ADDR_OFFSET = 4'h 8;
-
- // Register index
- typedef enum int {
- HMR_DMR_REGS_DMR_ENABLE,
- HMR_DMR_REGS_DMR_CONFIG,
- HMR_DMR_REGS_CHECKPOINT_ADDR
- } hmr_dmr_regs_id_e;
-
- // Register width information to check illegal writes
- parameter logic [3:0] HMR_DMR_REGS_PERMIT [3] = '{
- 4'b 0001, // index[0] HMR_DMR_REGS_DMR_ENABLE
- 4'b 0001, // index[1] HMR_DMR_REGS_DMR_CONFIG
- 4'b 1111 // index[2] HMR_DMR_REGS_CHECKPOINT_ADDR
- };
-
+ localparam HMR_DMR_REGS_REG_TOP_DATA_WIDTH = 32;
+ localparam HMR_DMR_REGS_REG_TOP_MIN_ADDR_WIDTH = 4;
+ localparam HMR_DMR_REGS_REG_TOP_SIZE = 'hc;
+
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_dmr__dmr_enable__dmr_enable__in_t;
+
+ typedef struct {
+ hmr_dmr__dmr_enable__dmr_enable__in_t dmr_enable;
+ } hmr_dmr__dmr_enable__in_t;
+
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_dmr__dmr_config__rapid_recovery__in_t;
+
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_dmr__dmr_config__force_recovery__in_t;
+
+ typedef struct {
+ hmr_dmr__dmr_config__rapid_recovery__in_t rapid_recovery;
+ hmr_dmr__dmr_config__force_recovery__in_t force_recovery;
+ } hmr_dmr__dmr_config__in_t;
+
+ typedef struct {
+ hmr_dmr__dmr_enable__in_t dmr_enable;
+ hmr_dmr__dmr_config__in_t dmr_config;
+ } hmr_dmr__in_t;
+
+ typedef struct {
+ logic value;
+ } hmr_dmr__dmr_enable__dmr_enable__out_t;
+
+ typedef struct {
+ hmr_dmr__dmr_enable__dmr_enable__out_t dmr_enable;
+ } hmr_dmr__dmr_enable__out_t;
+
+ typedef struct {
+ logic value;
+ } hmr_dmr__dmr_config__rapid_recovery__out_t;
+
+ typedef struct {
+ logic value;
+ } hmr_dmr__dmr_config__force_recovery__out_t;
+
+ typedef struct {
+ hmr_dmr__dmr_config__rapid_recovery__out_t rapid_recovery;
+ hmr_dmr__dmr_config__force_recovery__out_t force_recovery;
+ } hmr_dmr__dmr_config__out_t;
+
+ typedef struct {
+ logic [31:0] value;
+ } hmr_dmr__checkpoint_addr__checkpoint_addr__out_t;
+
+ typedef struct {
+ hmr_dmr__checkpoint_addr__checkpoint_addr__out_t checkpoint_addr;
+ } hmr_dmr__checkpoint_addr__out_t;
+
+ typedef struct {
+ hmr_dmr__dmr_enable__out_t dmr_enable;
+ hmr_dmr__dmr_config__out_t dmr_config;
+ hmr_dmr__checkpoint_addr__out_t checkpoint_addr;
+ } hmr_dmr__out_t;
endpackage
-
diff --git a/rtl/HMR/hmr_dmr_regs_reg_top.sv b/rtl/HMR/hmr_dmr_regs_reg_top.sv
index 209d9348..d2b0c3e5 100644
--- a/rtl/HMR/hmr_dmr_regs_reg_top.sv
+++ b/rtl/HMR/hmr_dmr_regs_reg_top.sv
@@ -1,312 +1,302 @@
-// 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`
-
-
-`include "common_cells/assertions.svh"
-
-module hmr_dmr_regs_reg_top #(
- parameter type reg_req_t = logic,
- parameter type reg_rsp_t = logic,
- parameter int AW = 4
-) (
- input logic clk_i,
- input logic rst_ni,
- input reg_req_t reg_req_i,
- output reg_rsp_t reg_rsp_o,
- // To HW
- output hmr_dmr_regs_reg_pkg::hmr_dmr_regs_reg2hw_t reg2hw, // Write
- input hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t hw2reg, // Read
-
-
- // Config
- input devmode_i // If 1, explicit error return for unmapped register access
-);
-
- import hmr_dmr_regs_reg_pkg::* ;
-
- localparam int DW = 32;
- localparam int 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;
-
- // Below register interface can be changed
- reg_req_t reg_intf_req;
- reg_rsp_t reg_intf_rsp;
-
-
- assign reg_intf_req = reg_req_i;
- assign reg_rsp_o = reg_intf_rsp;
-
-
- assign reg_we = reg_intf_req.valid & reg_intf_req.write;
- assign reg_re = reg_intf_req.valid & ~reg_intf_req.write;
- assign reg_addr = reg_intf_req.addr;
- assign reg_wdata = reg_intf_req.wdata;
- assign reg_be = reg_intf_req.wstrb;
- assign reg_intf_rsp.rdata = reg_rdata;
- assign reg_intf_rsp.error = reg_error;
- assign reg_intf_rsp.ready = 1'b1;
-
- assign reg_rdata = reg_rdata_next ;
- assign reg_error = (devmode_i & addrmiss) | wr_err;
-
-
- // Define SW related signals
- // Format: __{wd|we|qs}
- // or _{wd|we|qs} if field == 1 or 0
- logic dmr_enable_qs;
- logic dmr_enable_wd;
- logic dmr_enable_we;
- logic dmr_config_rapid_recovery_qs;
- logic dmr_config_rapid_recovery_wd;
- logic dmr_config_rapid_recovery_we;
- logic dmr_config_force_recovery_qs;
- logic dmr_config_force_recovery_wd;
- logic dmr_config_force_recovery_we;
- logic [31:0] checkpoint_addr_qs;
- logic [31:0] checkpoint_addr_wd;
- logic checkpoint_addr_we;
-
- // Register instances
- // R[dmr_enable]: V(False)
-
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h0)
- ) u_dmr_enable (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (dmr_enable_we),
- .wd (dmr_enable_wd),
-
- // from internal hardware
- .de (hw2reg.dmr_enable.de),
- .d (hw2reg.dmr_enable.d ),
-
- // to internal hardware
- .qe (reg2hw.dmr_enable.qe),
- .q (reg2hw.dmr_enable.q ),
-
- // to register interface (read)
- .qs (dmr_enable_qs)
- );
-
-
- // R[dmr_config]: V(False)
-
- // F[rapid_recovery]: 0:0
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h0)
- ) u_dmr_config_rapid_recovery (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (dmr_config_rapid_recovery_we),
- .wd (dmr_config_rapid_recovery_wd),
-
- // from internal hardware
- .de (hw2reg.dmr_config.rapid_recovery.de),
- .d (hw2reg.dmr_config.rapid_recovery.d ),
-
- // to internal hardware
- .qe (reg2hw.dmr_config.rapid_recovery.qe),
- .q (reg2hw.dmr_config.rapid_recovery.q ),
-
- // to register interface (read)
- .qs (dmr_config_rapid_recovery_qs)
- );
-
-
- // F[force_recovery]: 1:1
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h0)
- ) u_dmr_config_force_recovery (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (dmr_config_force_recovery_we),
- .wd (dmr_config_force_recovery_wd),
-
- // from internal hardware
- .de (hw2reg.dmr_config.force_recovery.de),
- .d (hw2reg.dmr_config.force_recovery.d ),
-
- // to internal hardware
- .qe (reg2hw.dmr_config.force_recovery.qe),
- .q (reg2hw.dmr_config.force_recovery.q ),
-
- // to register interface (read)
- .qs (dmr_config_force_recovery_qs)
- );
-
-
- // R[checkpoint_addr]: V(False)
-
- prim_subreg #(
- .DW (32),
- .SWACCESS("RW"),
- .RESVAL (32'h0)
- ) u_checkpoint_addr (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (checkpoint_addr_we),
- .wd (checkpoint_addr_wd),
-
- // from internal hardware
- .de (hw2reg.checkpoint_addr.de),
- .d (hw2reg.checkpoint_addr.d ),
-
- // to internal hardware
- .qe (reg2hw.checkpoint_addr.qe),
- .q (reg2hw.checkpoint_addr.q ),
-
- // to register interface (read)
- .qs (checkpoint_addr_qs)
- );
-
-
-
-
- logic [2:0] addr_hit;
- always_comb begin
- addr_hit = '0;
- addr_hit[0] = (reg_addr == HMR_DMR_REGS_DMR_ENABLE_OFFSET);
- addr_hit[1] = (reg_addr == HMR_DMR_REGS_DMR_CONFIG_OFFSET);
- addr_hit[2] = (reg_addr == HMR_DMR_REGS_CHECKPOINT_ADDR_OFFSET);
- end
-
- assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
-
- // Check sub-word write is permitted
- always_comb begin
- wr_err = (reg_we &
- ((addr_hit[0] & (|(HMR_DMR_REGS_PERMIT[0] & ~reg_be))) |
- (addr_hit[1] & (|(HMR_DMR_REGS_PERMIT[1] & ~reg_be))) |
- (addr_hit[2] & (|(HMR_DMR_REGS_PERMIT[2] & ~reg_be)))));
- end
-
- assign dmr_enable_we = addr_hit[0] & reg_we & !reg_error;
- assign dmr_enable_wd = reg_wdata[0];
-
- assign dmr_config_rapid_recovery_we = addr_hit[1] & reg_we & !reg_error;
- assign dmr_config_rapid_recovery_wd = reg_wdata[0];
-
- assign dmr_config_force_recovery_we = addr_hit[1] & reg_we & !reg_error;
- assign dmr_config_force_recovery_wd = reg_wdata[1];
-
- assign checkpoint_addr_we = addr_hit[2] & reg_we & !reg_error;
- assign checkpoint_addr_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] = dmr_enable_qs;
- end
-
- addr_hit[1]: begin
- reg_rdata_next[0] = dmr_config_rapid_recovery_qs;
- reg_rdata_next[1] = dmr_config_force_recovery_qs;
- end
-
- addr_hit[2]: begin
- reg_rdata_next[31:0] = checkpoint_addr_qs;
- end
-
- default: begin
- reg_rdata_next = '1;
- end
- endcase
- end
-
- // Unused signal tieoff
-
- // wdata / byte enable are not always fully used
- // add a blanket unused statement to handle lint waivers
- logic unused_wdata;
- logic unused_be;
- assign unused_wdata = ^reg_wdata;
- assign unused_be = ^reg_be;
-
- // Assertions for Register Interface
- `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit))
-
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+// https://github.com/SystemRDL/PeakRDL-regblock
+
+module hmr_dmr_regs_reg_top (
+ input wire clk,
+ input wire arst_n,
+
+ input wire s_apb_psel,
+ input wire s_apb_penable,
+ input wire s_apb_pwrite,
+ input wire [2:0] s_apb_pprot,
+ input wire [3:0] s_apb_paddr,
+ input wire [31:0] s_apb_pwdata,
+ input wire [3:0] s_apb_pstrb,
+ output logic s_apb_pready,
+ output logic [31:0] s_apb_prdata,
+ output logic s_apb_pslverr,
+
+ input hmr_dmr_regs_reg_pkg::hmr_dmr__in_t hwif_in,
+ output hmr_dmr_regs_reg_pkg::hmr_dmr__out_t hwif_out
+ );
+
+ //--------------------------------------------------------------------------
+ // CPU Bus interface logic
+ //--------------------------------------------------------------------------
+ logic cpuif_req;
+ logic cpuif_req_is_wr;
+ logic [3:0] cpuif_addr;
+ logic [31:0] cpuif_wr_data;
+ logic [31:0] cpuif_wr_biten;
+ logic cpuif_req_stall_wr;
+ logic cpuif_req_stall_rd;
+
+ logic cpuif_rd_ack;
+ logic cpuif_rd_err;
+ logic [31:0] cpuif_rd_data;
+
+ logic cpuif_wr_ack;
+ logic cpuif_wr_err;
+
+ // Request
+ logic is_active;
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ is_active <= '0;
+ cpuif_req <= '0;
+ cpuif_req_is_wr <= '0;
+ cpuif_addr <= '0;
+ cpuif_wr_data <= '0;
+ cpuif_wr_biten <= '0;
+ end else begin
+ if(~is_active) begin
+ if(s_apb_psel) begin
+ is_active <= '1;
+ cpuif_req <= '1;
+ cpuif_req_is_wr <= s_apb_pwrite;
+ cpuif_addr <= {s_apb_paddr[3:2], 2'b0};
+ cpuif_wr_data <= s_apb_pwdata;
+ for(int i=0; i<4; i++) begin
+ cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}};
+ end
+ end
+ end else begin
+ cpuif_req <= '0;
+ if(cpuif_rd_ack || cpuif_wr_ack) begin
+ is_active <= '0;
+ end
+ end
+ end
+ end
+
+ // Response
+ assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack;
+ assign s_apb_prdata = cpuif_rd_data;
+ assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err;
+
+ logic cpuif_req_masked;
+
+ // Read & write latencies are balanced. Stalls not required
+ assign cpuif_req_stall_rd = '0;
+ assign cpuif_req_stall_wr = '0;
+ assign cpuif_req_masked = cpuif_req
+ & !(!cpuif_req_is_wr & cpuif_req_stall_rd)
+ & !(cpuif_req_is_wr & cpuif_req_stall_wr);
+
+ //--------------------------------------------------------------------------
+ // Address Decode
+ //--------------------------------------------------------------------------
+ typedef struct {
+ logic dmr_enable;
+ logic dmr_config;
+ logic checkpoint_addr;
+ } decoded_reg_strb_t;
+ decoded_reg_strb_t decoded_reg_strb;
+ logic decoded_req;
+ logic decoded_req_is_wr;
+ logic [31:0] decoded_wr_data;
+ logic [31:0] decoded_wr_biten;
+
+ always_comb begin
+ decoded_reg_strb.dmr_enable = cpuif_req_masked & (cpuif_addr == 4'h0);
+ decoded_reg_strb.dmr_config = cpuif_req_masked & (cpuif_addr == 4'h4);
+ decoded_reg_strb.checkpoint_addr = cpuif_req_masked & (cpuif_addr == 4'h8);
+ end
+
+ // Pass down signals to next stage
+ assign decoded_req = cpuif_req_masked;
+ assign decoded_req_is_wr = cpuif_req_is_wr;
+ assign decoded_wr_data = cpuif_wr_data;
+ assign decoded_wr_biten = cpuif_wr_biten;
+
+ //--------------------------------------------------------------------------
+ // Field logic
+ //--------------------------------------------------------------------------
+ typedef struct {
+ struct {
+ struct {
+ logic next;
+ logic load_next;
+ } dmr_enable;
+ } dmr_enable;
+ struct {
+ struct {
+ logic next;
+ logic load_next;
+ } rapid_recovery;
+ struct {
+ logic next;
+ logic load_next;
+ } force_recovery;
+ } dmr_config;
+ struct {
+ struct {
+ logic [31:0] next;
+ logic load_next;
+ } checkpoint_addr;
+ } checkpoint_addr;
+ } field_combo_t;
+ field_combo_t field_combo;
+
+ typedef struct {
+ struct {
+ struct {
+ logic value;
+ } dmr_enable;
+ } dmr_enable;
+ struct {
+ struct {
+ logic value;
+ } rapid_recovery;
+ struct {
+ logic value;
+ } force_recovery;
+ } dmr_config;
+ struct {
+ struct {
+ logic [31:0] value;
+ } checkpoint_addr;
+ } checkpoint_addr;
+ } field_storage_t;
+ field_storage_t field_storage;
+
+ // Field: hmr_dmr.dmr_enable.dmr_enable
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.dmr_enable.dmr_enable.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.dmr_enable && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.dmr_enable.dmr_enable.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]);
+ load_next_c = '1;
+ end else if(hwif_in.dmr_enable.dmr_enable.we) begin // HW Write - we
+ next_c = hwif_in.dmr_enable.dmr_enable.next;
+ load_next_c = '1;
+ end
+ field_combo.dmr_enable.dmr_enable.next = next_c;
+ field_combo.dmr_enable.dmr_enable.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.dmr_enable.dmr_enable.value <= 1'h0;
+ end else begin
+ if(field_combo.dmr_enable.dmr_enable.load_next) begin
+ field_storage.dmr_enable.dmr_enable.value <= field_combo.dmr_enable.dmr_enable.next;
+ end
+ end
+ end
+ assign hwif_out.dmr_enable.dmr_enable.value = field_storage.dmr_enable.dmr_enable.value;
+ // Field: hmr_dmr.dmr_config.rapid_recovery
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.dmr_config.rapid_recovery.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.dmr_config && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.dmr_config.rapid_recovery.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]);
+ load_next_c = '1;
+ end else if(hwif_in.dmr_config.rapid_recovery.we) begin // HW Write - we
+ next_c = hwif_in.dmr_config.rapid_recovery.next;
+ load_next_c = '1;
+ end
+ field_combo.dmr_config.rapid_recovery.next = next_c;
+ field_combo.dmr_config.rapid_recovery.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.dmr_config.rapid_recovery.value <= 1'h0;
+ end else begin
+ if(field_combo.dmr_config.rapid_recovery.load_next) begin
+ field_storage.dmr_config.rapid_recovery.value <= field_combo.dmr_config.rapid_recovery.next;
+ end
+ end
+ end
+ assign hwif_out.dmr_config.rapid_recovery.value = field_storage.dmr_config.rapid_recovery.value;
+ // Field: hmr_dmr.dmr_config.force_recovery
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.dmr_config.force_recovery.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.dmr_config && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.dmr_config.force_recovery.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]);
+ load_next_c = '1;
+ end else if(hwif_in.dmr_config.force_recovery.we) begin // HW Write - we
+ next_c = hwif_in.dmr_config.force_recovery.next;
+ load_next_c = '1;
+ end
+ field_combo.dmr_config.force_recovery.next = next_c;
+ field_combo.dmr_config.force_recovery.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.dmr_config.force_recovery.value <= 1'h0;
+ end else begin
+ if(field_combo.dmr_config.force_recovery.load_next) begin
+ field_storage.dmr_config.force_recovery.value <= field_combo.dmr_config.force_recovery.next;
+ end
+ end
+ end
+ assign hwif_out.dmr_config.force_recovery.value = field_storage.dmr_config.force_recovery.value;
+ // Field: hmr_dmr.checkpoint_addr.checkpoint_addr
+ always_comb begin
+ automatic logic [31:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.checkpoint_addr.checkpoint_addr.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.checkpoint_addr && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.checkpoint_addr.checkpoint_addr.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
+ load_next_c = '1;
+ end
+ field_combo.checkpoint_addr.checkpoint_addr.next = next_c;
+ field_combo.checkpoint_addr.checkpoint_addr.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.checkpoint_addr.checkpoint_addr.value <= 32'h0;
+ end else begin
+ if(field_combo.checkpoint_addr.checkpoint_addr.load_next) begin
+ field_storage.checkpoint_addr.checkpoint_addr.value <= field_combo.checkpoint_addr.checkpoint_addr.next;
+ end
+ end
+ end
+ assign hwif_out.checkpoint_addr.checkpoint_addr.value = field_storage.checkpoint_addr.checkpoint_addr.value;
+
+ //--------------------------------------------------------------------------
+ // Write response
+ //--------------------------------------------------------------------------
+ assign cpuif_wr_ack = decoded_req & decoded_req_is_wr;
+ // Writes are always granted with no error response
+ assign cpuif_wr_err = '0;
+
+ //--------------------------------------------------------------------------
+ // Readback
+ //--------------------------------------------------------------------------
+
+ logic readback_err;
+ logic readback_done;
+ logic [31:0] readback_data;
+
+ // Assign readback values to a flattened array
+ logic [31:0] readback_array[3];
+ assign readback_array[0][0:0] = (decoded_reg_strb.dmr_enable && !decoded_req_is_wr) ? field_storage.dmr_enable.dmr_enable.value : '0;
+ assign readback_array[0][31:1] = '0;
+ assign readback_array[1][0:0] = (decoded_reg_strb.dmr_config && !decoded_req_is_wr) ? field_storage.dmr_config.rapid_recovery.value : '0;
+ assign readback_array[1][1:1] = (decoded_reg_strb.dmr_config && !decoded_req_is_wr) ? field_storage.dmr_config.force_recovery.value : '0;
+ assign readback_array[1][31:2] = '0;
+ assign readback_array[2][31:0] = (decoded_reg_strb.checkpoint_addr && !decoded_req_is_wr) ? field_storage.checkpoint_addr.checkpoint_addr.value : '0;
+
+ // Reduce the array
+ always_comb begin
+ automatic logic [31:0] readback_data_var;
+ readback_done = decoded_req & ~decoded_req_is_wr;
+ readback_err = '0;
+ readback_data_var = '0;
+ for(int i=0; i<3; i++) readback_data_var |= readback_array[i];
+ readback_data = readback_data_var;
+ end
+
+ assign cpuif_rd_ack = readback_done;
+ assign cpuif_rd_data = readback_data;
+ assign cpuif_rd_err = readback_err;
endmodule
-
-module hmr_dmr_regs_reg_top_intf
-#(
- parameter int AW = 4,
- localparam int DW = 32
-) (
- input logic clk_i,
- input logic rst_ni,
- REG_BUS.in regbus_slave,
- // To HW
- output hmr_dmr_regs_reg_pkg::hmr_dmr_regs_reg2hw_t reg2hw, // Write
- input hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t hw2reg, // Read
- // Config
- input devmode_i // If 1, explicit error return for unmapped register access
-);
- localparam int unsigned STRB_WIDTH = DW/8;
-
-`include "register_interface/typedef.svh"
-`include "register_interface/assign.svh"
-
- // Define structs for reg_bus
- typedef logic [AW-1:0] addr_t;
- typedef logic [DW-1:0] data_t;
- typedef logic [STRB_WIDTH-1:0] strb_t;
- `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t)
-
- reg_bus_req_t s_reg_req;
- reg_bus_rsp_t s_reg_rsp;
-
- // Assign SV interface to structs
- `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave)
- `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp)
-
-
-
- hmr_dmr_regs_reg_top #(
- .reg_req_t(reg_bus_req_t),
- .reg_rsp_t(reg_bus_rsp_t),
- .AW(AW)
- ) i_regs (
- .clk_i,
- .rst_ni,
- .reg_req_i(s_reg_req),
- .reg_rsp_o(s_reg_rsp),
- .reg2hw, // Write
- .hw2reg, // Read
- .devmode_i
- );
-
-endmodule
-
-
diff --git a/rtl/HMR/hmr_registers.h b/rtl/HMR/hmr_registers.h
new file mode 100644
index 00000000..323bec79
--- /dev/null
+++ b/rtl/HMR/hmr_registers.h
@@ -0,0 +1,209 @@
+// Generated by PeakRDL-cheader - A free and open-source header generator
+// https://github.com/SystemRDL/PeakRDL-cheader
+
+#ifndef HMR_REGISTERS_H
+#define HMR_REGISTERS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+
+// Reg - hmr_all::hmr::avail_config
+#define HMR_ALL__HMR__AVAIL_CONFIG__INDEPENDENT_bm 0x1
+#define HMR_ALL__HMR__AVAIL_CONFIG__INDEPENDENT_bp 0
+#define HMR_ALL__HMR__AVAIL_CONFIG__INDEPENDENT_bw 1
+#define HMR_ALL__HMR__AVAIL_CONFIG__INDEPENDENT_reset 0x1
+#define HMR_ALL__HMR__AVAIL_CONFIG__DUAL_bm 0x2
+#define HMR_ALL__HMR__AVAIL_CONFIG__DUAL_bp 1
+#define HMR_ALL__HMR__AVAIL_CONFIG__DUAL_bw 1
+#define HMR_ALL__HMR__AVAIL_CONFIG__DUAL_reset 0x1
+#define HMR_ALL__HMR__AVAIL_CONFIG__TRIPLE_bm 0x4
+#define HMR_ALL__HMR__AVAIL_CONFIG__TRIPLE_bp 2
+#define HMR_ALL__HMR__AVAIL_CONFIG__TRIPLE_bw 1
+#define HMR_ALL__HMR__AVAIL_CONFIG__TRIPLE_reset 0x1
+#define HMR_ALL__HMR__AVAIL_CONFIG__RAPID_RECOVERY_bm 0x100
+#define HMR_ALL__HMR__AVAIL_CONFIG__RAPID_RECOVERY_bp 8
+#define HMR_ALL__HMR__AVAIL_CONFIG__RAPID_RECOVERY_bw 1
+#define HMR_ALL__HMR__AVAIL_CONFIG__RAPID_RECOVERY_reset 0x1
+
+// Reg - hmr_all::hmr::cores_en
+#define HMR_ALL__HMR__CORES_EN__CORES_EN_bm 0xfff
+#define HMR_ALL__HMR__CORES_EN__CORES_EN_bp 0
+#define HMR_ALL__HMR__CORES_EN__CORES_EN_bw 12
+#define HMR_ALL__HMR__CORES_EN__CORES_EN_reset 0x0
+
+// Reg - hmr_all::hmr::dmr_enable
+#define HMR_ALL__HMR__DMR_ENABLE__DMR_ENABLE_bm 0x3f
+#define HMR_ALL__HMR__DMR_ENABLE__DMR_ENABLE_bp 0
+#define HMR_ALL__HMR__DMR_ENABLE__DMR_ENABLE_bw 6
+#define HMR_ALL__HMR__DMR_ENABLE__DMR_ENABLE_reset 0x0
+
+// Reg - hmr_all::hmr::tmr_enable
+#define HMR_ALL__HMR__TMR_ENABLE__TMR_ENABLE_bm 0xf
+#define HMR_ALL__HMR__TMR_ENABLE__TMR_ENABLE_bp 0
+#define HMR_ALL__HMR__TMR_ENABLE__TMR_ENABLE_bw 4
+#define HMR_ALL__HMR__TMR_ENABLE__TMR_ENABLE_reset 0x0
+
+// Reg - hmr_all::hmr::dmr_config
+#define HMR_ALL__HMR__DMR_CONFIG__RAPID_RECOVERY_bm 0x1
+#define HMR_ALL__HMR__DMR_CONFIG__RAPID_RECOVERY_bp 0
+#define HMR_ALL__HMR__DMR_CONFIG__RAPID_RECOVERY_bw 1
+#define HMR_ALL__HMR__DMR_CONFIG__RAPID_RECOVERY_reset 0x0
+#define HMR_ALL__HMR__DMR_CONFIG__FORCE_RECOVERY_bm 0x2
+#define HMR_ALL__HMR__DMR_CONFIG__FORCE_RECOVERY_bp 1
+#define HMR_ALL__HMR__DMR_CONFIG__FORCE_RECOVERY_bw 1
+#define HMR_ALL__HMR__DMR_CONFIG__FORCE_RECOVERY_reset 0x0
+
+// Reg - hmr_all::hmr::tmr_config
+#define HMR_ALL__HMR__TMR_CONFIG__DELAY_RESYNCH_bm 0x1
+#define HMR_ALL__HMR__TMR_CONFIG__DELAY_RESYNCH_bp 0
+#define HMR_ALL__HMR__TMR_CONFIG__DELAY_RESYNCH_bw 1
+#define HMR_ALL__HMR__TMR_CONFIG__DELAY_RESYNCH_reset 0x0
+#define HMR_ALL__HMR__TMR_CONFIG__SETBACK_bm 0x2
+#define HMR_ALL__HMR__TMR_CONFIG__SETBACK_bp 1
+#define HMR_ALL__HMR__TMR_CONFIG__SETBACK_bw 1
+#define HMR_ALL__HMR__TMR_CONFIG__SETBACK_reset 0x1
+#define HMR_ALL__HMR__TMR_CONFIG__RELOAD_SETBACK_bm 0x4
+#define HMR_ALL__HMR__TMR_CONFIG__RELOAD_SETBACK_bp 2
+#define HMR_ALL__HMR__TMR_CONFIG__RELOAD_SETBACK_bw 1
+#define HMR_ALL__HMR__TMR_CONFIG__RELOAD_SETBACK_reset 0x1
+#define HMR_ALL__HMR__TMR_CONFIG__RAPID_RECOVERY_bm 0x8
+#define HMR_ALL__HMR__TMR_CONFIG__RAPID_RECOVERY_bp 3
+#define HMR_ALL__HMR__TMR_CONFIG__RAPID_RECOVERY_bw 1
+#define HMR_ALL__HMR__TMR_CONFIG__RAPID_RECOVERY_reset 0x0
+#define HMR_ALL__HMR__TMR_CONFIG__FORCE_RESYNCH_bm 0x10
+#define HMR_ALL__HMR__TMR_CONFIG__FORCE_RESYNCH_bp 4
+#define HMR_ALL__HMR__TMR_CONFIG__FORCE_RESYNCH_bw 1
+#define HMR_ALL__HMR__TMR_CONFIG__FORCE_RESYNCH_reset 0x0
+
+// Addrmap - hmr_all::hmr
+typedef struct __attribute__ ((__packed__)) {
+ uint32_t avail_config;
+ uint32_t cores_en;
+ uint32_t dmr_enable;
+ uint32_t tmr_enable;
+ uint32_t dmr_config;
+ uint32_t tmr_config;
+} hmr_all__hmr_t;
+
+// Reg - hmr_all::hmr_core::current_mode
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__INDEPENDENT_bm 0x1
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__INDEPENDENT_bp 0
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__INDEPENDENT_bw 1
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__INDEPENDENT_reset 0x1
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__DUAL_bm 0x2
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__DUAL_bp 1
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__DUAL_bw 1
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__DUAL_reset 0x0
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__TRIPLE_bm 0x4
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__TRIPLE_bp 2
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__TRIPLE_bw 1
+#define HMR_ALL__HMR_CORE__CURRENT_MODE__TRIPLE_reset 0x0
+
+// Reg - hmr_all::hmr_core::mismatches
+#define HMR_ALL__HMR_CORE__MISMATCHES__MISMATCHES_bm 0xffffffff
+#define HMR_ALL__HMR_CORE__MISMATCHES__MISMATCHES_bp 0
+#define HMR_ALL__HMR_CORE__MISMATCHES__MISMATCHES_bw 32
+#define HMR_ALL__HMR_CORE__MISMATCHES__MISMATCHES_reset 0x0
+
+// Reg - hmr_all::hmr_core::sp_store
+#define HMR_ALL__HMR_CORE__SP_STORE__SP_STORE_bm 0xffffffff
+#define HMR_ALL__HMR_CORE__SP_STORE__SP_STORE_bp 0
+#define HMR_ALL__HMR_CORE__SP_STORE__SP_STORE_bw 32
+#define HMR_ALL__HMR_CORE__SP_STORE__SP_STORE_reset 0x0
+
+// Addrmap - hmr_all::hmr_core
+typedef struct __attribute__ ((__packed__)) {
+ uint32_t current_mode;
+ uint32_t mismatches;
+ uint32_t sp_store;
+ uint8_t RESERVED_c_f[0x4];
+} hmr_all__hmr_core__stride10_t;
+
+// Reg - hmr_all::hmr_dmr_ispresent_t::dmr_enable
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_ENABLE__DMR_ENABLE_bm 0x1
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_ENABLE__DMR_ENABLE_bp 0
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_ENABLE__DMR_ENABLE_bw 1
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_ENABLE__DMR_ENABLE_reset 0x0
+
+// Reg - hmr_all::hmr_dmr_ispresent_t::dmr_config
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__RAPID_RECOVERY_bm 0x1
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__RAPID_RECOVERY_bp 0
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__RAPID_RECOVERY_bw 1
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__RAPID_RECOVERY_reset 0x0
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__FORCE_RECOVERY_bm 0x2
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__FORCE_RECOVERY_bp 1
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__FORCE_RECOVERY_bw 1
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__FORCE_RECOVERY_reset 0x0
+
+// Reg - hmr_all::hmr_dmr_ispresent_t::checkpoint_addr
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__CHECKPOINT_ADDR__CHECKPOINT_ADDR_bm 0xffffffff
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__CHECKPOINT_ADDR__CHECKPOINT_ADDR_bp 0
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__CHECKPOINT_ADDR__CHECKPOINT_ADDR_bw 32
+#define HMR_ALL__HMR_DMR_ISPRESENT_T__CHECKPOINT_ADDR__CHECKPOINT_ADDR_reset 0x0
+
+// Addrmap - hmr_all::hmr_dmr_ispresent_t
+typedef struct __attribute__ ((__packed__)) {
+ uint32_t dmr_enable;
+ uint32_t dmr_config;
+ uint32_t checkpoint_addr;
+ uint8_t RESERVED_c_f[0x4];
+} hmr_all__hmr_dmr_ispresent_t__stride10_t;
+
+// Reg - hmr_all::hmr_tmr_ispresent_t::tmr_enable
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_ENABLE__TMR_ENABLE_bm 0x1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_ENABLE__TMR_ENABLE_bp 0
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_ENABLE__TMR_ENABLE_bw 1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_ENABLE__TMR_ENABLE_reset 0x0
+
+// Reg - hmr_all::hmr_tmr_ispresent_t::tmr_config
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__DELAY_RESYNCH_bm 0x1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__DELAY_RESYNCH_bp 0
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__DELAY_RESYNCH_bw 1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__DELAY_RESYNCH_reset 0x0
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__SETBACK_bm 0x2
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__SETBACK_bp 1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__SETBACK_bw 1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__SETBACK_reset 0x1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RELOAD_SETBACK_bm 0x4
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RELOAD_SETBACK_bp 2
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RELOAD_SETBACK_bw 1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RELOAD_SETBACK_reset 0x1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RAPID_RECOVERY_bm 0x8
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RAPID_RECOVERY_bp 3
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RAPID_RECOVERY_bw 1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RAPID_RECOVERY_reset 0x0
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__FORCE_RESYNCH_bm 0x10
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__FORCE_RESYNCH_bp 4
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__FORCE_RESYNCH_bw 1
+#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__FORCE_RESYNCH_reset 0x0
+
+// Addrmap - hmr_all::hmr_tmr_ispresent_t
+typedef struct __attribute__ ((__packed__)) {
+ uint32_t tmr_enable;
+ uint32_t tmr_config;
+ uint8_t RESERVED_8_f[0x8];
+} hmr_all__hmr_tmr_ispresent_t__stride10_t;
+
+// Addrmap - hmr_all
+typedef struct __attribute__ ((__packed__)) {
+ hmr_all__hmr_t hmr;
+ uint8_t RESERVED_18_ff[0xe8];
+ hmr_all__hmr_core__stride10_t hmr_core[12];
+ uint8_t RESERVED_1c0_1ff[0x40];
+ hmr_all__hmr_dmr_ispresent_t__stride10_t hmr_dmr[6];
+ uint8_t RESERVED_260_2ff[0xa0];
+ hmr_all__hmr_tmr_ispresent_t__stride10_t hmr_tmr[4];
+} hmr_all_t;
+
+
+static_assert(sizeof(hmr_all_t) == 0x340, "Packing error");
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HMR_REGISTERS_H */
diff --git a/rtl/HMR/hmr_registers_reg_addr_pkg.sv b/rtl/HMR/hmr_registers_reg_addr_pkg.sv
new file mode 100644
index 00000000..cd3cd5bb
--- /dev/null
+++ b/rtl/HMR/hmr_registers_reg_addr_pkg.sv
@@ -0,0 +1,304 @@
+package hmr_all_addrmap_pkg;
+
+
+localparam longint unsigned HMR_ALL_BASE_ADDR = 64'h00000000;
+localparam longint unsigned HMR_ALL_SIZE = 64'h00000340;
+
+
+localparam longint unsigned HMR_ALL_HMR_BASE_ADDR = 64'h00000000;
+localparam longint unsigned HMR_ALL_HMR_SIZE = 64'h00000018;
+
+localparam longint unsigned HMR_ALL_HMR_AVAIL_CONFIG_REG_ADDR = 64'h00000000;
+localparam longint unsigned HMR_ALL_HMR_AVAIL_CONFIG_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORES_EN_REG_ADDR = 64'h00000004;
+localparam longint unsigned HMR_ALL_HMR_CORES_EN_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_ENABLE_REG_ADDR = 64'h00000008;
+localparam longint unsigned HMR_ALL_HMR_DMR_ENABLE_REG_OFFSET = 64'h00000008;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_ENABLE_REG_ADDR = 64'h0000000C;
+localparam longint unsigned HMR_ALL_HMR_TMR_ENABLE_REG_OFFSET = 64'h0000000C;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_CONFIG_REG_ADDR = 64'h00000010;
+localparam longint unsigned HMR_ALL_HMR_DMR_CONFIG_REG_OFFSET = 64'h00000010;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_CONFIG_REG_ADDR = 64'h00000014;
+localparam longint unsigned HMR_ALL_HMR_TMR_CONFIG_REG_OFFSET = 64'h00000014;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_0_BASE_ADDR = 64'h00000100;
+localparam longint unsigned HMR_ALL_HMR_CORE_0_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_0_CURRENT_MODE_REG_ADDR = 64'h00000100;
+localparam longint unsigned HMR_ALL_HMR_CORE_0_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_0_MISMATCHES_REG_ADDR = 64'h00000104;
+localparam longint unsigned HMR_ALL_HMR_CORE_0_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_0_SP_STORE_REG_ADDR = 64'h00000108;
+localparam longint unsigned HMR_ALL_HMR_CORE_0_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_1_BASE_ADDR = 64'h00000110;
+localparam longint unsigned HMR_ALL_HMR_CORE_1_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_1_CURRENT_MODE_REG_ADDR = 64'h00000110;
+localparam longint unsigned HMR_ALL_HMR_CORE_1_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_1_MISMATCHES_REG_ADDR = 64'h00000114;
+localparam longint unsigned HMR_ALL_HMR_CORE_1_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_1_SP_STORE_REG_ADDR = 64'h00000118;
+localparam longint unsigned HMR_ALL_HMR_CORE_1_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_2_BASE_ADDR = 64'h00000120;
+localparam longint unsigned HMR_ALL_HMR_CORE_2_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_2_CURRENT_MODE_REG_ADDR = 64'h00000120;
+localparam longint unsigned HMR_ALL_HMR_CORE_2_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_2_MISMATCHES_REG_ADDR = 64'h00000124;
+localparam longint unsigned HMR_ALL_HMR_CORE_2_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_2_SP_STORE_REG_ADDR = 64'h00000128;
+localparam longint unsigned HMR_ALL_HMR_CORE_2_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_3_BASE_ADDR = 64'h00000130;
+localparam longint unsigned HMR_ALL_HMR_CORE_3_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_3_CURRENT_MODE_REG_ADDR = 64'h00000130;
+localparam longint unsigned HMR_ALL_HMR_CORE_3_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_3_MISMATCHES_REG_ADDR = 64'h00000134;
+localparam longint unsigned HMR_ALL_HMR_CORE_3_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_3_SP_STORE_REG_ADDR = 64'h00000138;
+localparam longint unsigned HMR_ALL_HMR_CORE_3_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_4_BASE_ADDR = 64'h00000140;
+localparam longint unsigned HMR_ALL_HMR_CORE_4_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_4_CURRENT_MODE_REG_ADDR = 64'h00000140;
+localparam longint unsigned HMR_ALL_HMR_CORE_4_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_4_MISMATCHES_REG_ADDR = 64'h00000144;
+localparam longint unsigned HMR_ALL_HMR_CORE_4_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_4_SP_STORE_REG_ADDR = 64'h00000148;
+localparam longint unsigned HMR_ALL_HMR_CORE_4_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_5_BASE_ADDR = 64'h00000150;
+localparam longint unsigned HMR_ALL_HMR_CORE_5_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_5_CURRENT_MODE_REG_ADDR = 64'h00000150;
+localparam longint unsigned HMR_ALL_HMR_CORE_5_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_5_MISMATCHES_REG_ADDR = 64'h00000154;
+localparam longint unsigned HMR_ALL_HMR_CORE_5_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_5_SP_STORE_REG_ADDR = 64'h00000158;
+localparam longint unsigned HMR_ALL_HMR_CORE_5_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_6_BASE_ADDR = 64'h00000160;
+localparam longint unsigned HMR_ALL_HMR_CORE_6_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_6_CURRENT_MODE_REG_ADDR = 64'h00000160;
+localparam longint unsigned HMR_ALL_HMR_CORE_6_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_6_MISMATCHES_REG_ADDR = 64'h00000164;
+localparam longint unsigned HMR_ALL_HMR_CORE_6_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_6_SP_STORE_REG_ADDR = 64'h00000168;
+localparam longint unsigned HMR_ALL_HMR_CORE_6_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_7_BASE_ADDR = 64'h00000170;
+localparam longint unsigned HMR_ALL_HMR_CORE_7_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_7_CURRENT_MODE_REG_ADDR = 64'h00000170;
+localparam longint unsigned HMR_ALL_HMR_CORE_7_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_7_MISMATCHES_REG_ADDR = 64'h00000174;
+localparam longint unsigned HMR_ALL_HMR_CORE_7_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_7_SP_STORE_REG_ADDR = 64'h00000178;
+localparam longint unsigned HMR_ALL_HMR_CORE_7_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_8_BASE_ADDR = 64'h00000180;
+localparam longint unsigned HMR_ALL_HMR_CORE_8_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_8_CURRENT_MODE_REG_ADDR = 64'h00000180;
+localparam longint unsigned HMR_ALL_HMR_CORE_8_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_8_MISMATCHES_REG_ADDR = 64'h00000184;
+localparam longint unsigned HMR_ALL_HMR_CORE_8_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_8_SP_STORE_REG_ADDR = 64'h00000188;
+localparam longint unsigned HMR_ALL_HMR_CORE_8_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_9_BASE_ADDR = 64'h00000190;
+localparam longint unsigned HMR_ALL_HMR_CORE_9_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_9_CURRENT_MODE_REG_ADDR = 64'h00000190;
+localparam longint unsigned HMR_ALL_HMR_CORE_9_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_9_MISMATCHES_REG_ADDR = 64'h00000194;
+localparam longint unsigned HMR_ALL_HMR_CORE_9_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_9_SP_STORE_REG_ADDR = 64'h00000198;
+localparam longint unsigned HMR_ALL_HMR_CORE_9_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_10_BASE_ADDR = 64'h000001A0;
+localparam longint unsigned HMR_ALL_HMR_CORE_10_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_10_CURRENT_MODE_REG_ADDR = 64'h000001A0;
+localparam longint unsigned HMR_ALL_HMR_CORE_10_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_10_MISMATCHES_REG_ADDR = 64'h000001A4;
+localparam longint unsigned HMR_ALL_HMR_CORE_10_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_10_SP_STORE_REG_ADDR = 64'h000001A8;
+localparam longint unsigned HMR_ALL_HMR_CORE_10_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_CORE_11_BASE_ADDR = 64'h000001B0;
+localparam longint unsigned HMR_ALL_HMR_CORE_11_SIZE = 64'h000000C0;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_11_CURRENT_MODE_REG_ADDR = 64'h000001B0;
+localparam longint unsigned HMR_ALL_HMR_CORE_11_CURRENT_MODE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_11_MISMATCHES_REG_ADDR = 64'h000001B4;
+localparam longint unsigned HMR_ALL_HMR_CORE_11_MISMATCHES_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_CORE_11_SP_STORE_REG_ADDR = 64'h000001B8;
+localparam longint unsigned HMR_ALL_HMR_CORE_11_SP_STORE_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_DMR_0_BASE_ADDR = 64'h00000200;
+localparam longint unsigned HMR_ALL_HMR_DMR_0_SIZE = 64'h00000060;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_0_DMR_ENABLE_REG_ADDR = 64'h00000200;
+localparam longint unsigned HMR_ALL_HMR_DMR_0_DMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_0_DMR_CONFIG_REG_ADDR = 64'h00000204;
+localparam longint unsigned HMR_ALL_HMR_DMR_0_DMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_0_CHECKPOINT_ADDR_REG_ADDR = 64'h00000208;
+localparam longint unsigned HMR_ALL_HMR_DMR_0_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_DMR_1_BASE_ADDR = 64'h00000210;
+localparam longint unsigned HMR_ALL_HMR_DMR_1_SIZE = 64'h00000060;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_1_DMR_ENABLE_REG_ADDR = 64'h00000210;
+localparam longint unsigned HMR_ALL_HMR_DMR_1_DMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_1_DMR_CONFIG_REG_ADDR = 64'h00000214;
+localparam longint unsigned HMR_ALL_HMR_DMR_1_DMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_1_CHECKPOINT_ADDR_REG_ADDR = 64'h00000218;
+localparam longint unsigned HMR_ALL_HMR_DMR_1_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_DMR_2_BASE_ADDR = 64'h00000220;
+localparam longint unsigned HMR_ALL_HMR_DMR_2_SIZE = 64'h00000060;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_2_DMR_ENABLE_REG_ADDR = 64'h00000220;
+localparam longint unsigned HMR_ALL_HMR_DMR_2_DMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_2_DMR_CONFIG_REG_ADDR = 64'h00000224;
+localparam longint unsigned HMR_ALL_HMR_DMR_2_DMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_2_CHECKPOINT_ADDR_REG_ADDR = 64'h00000228;
+localparam longint unsigned HMR_ALL_HMR_DMR_2_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_DMR_3_BASE_ADDR = 64'h00000230;
+localparam longint unsigned HMR_ALL_HMR_DMR_3_SIZE = 64'h00000060;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_3_DMR_ENABLE_REG_ADDR = 64'h00000230;
+localparam longint unsigned HMR_ALL_HMR_DMR_3_DMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_3_DMR_CONFIG_REG_ADDR = 64'h00000234;
+localparam longint unsigned HMR_ALL_HMR_DMR_3_DMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_3_CHECKPOINT_ADDR_REG_ADDR = 64'h00000238;
+localparam longint unsigned HMR_ALL_HMR_DMR_3_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_DMR_4_BASE_ADDR = 64'h00000240;
+localparam longint unsigned HMR_ALL_HMR_DMR_4_SIZE = 64'h00000060;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_4_DMR_ENABLE_REG_ADDR = 64'h00000240;
+localparam longint unsigned HMR_ALL_HMR_DMR_4_DMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_4_DMR_CONFIG_REG_ADDR = 64'h00000244;
+localparam longint unsigned HMR_ALL_HMR_DMR_4_DMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_4_CHECKPOINT_ADDR_REG_ADDR = 64'h00000248;
+localparam longint unsigned HMR_ALL_HMR_DMR_4_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_DMR_5_BASE_ADDR = 64'h00000250;
+localparam longint unsigned HMR_ALL_HMR_DMR_5_SIZE = 64'h00000060;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_5_DMR_ENABLE_REG_ADDR = 64'h00000250;
+localparam longint unsigned HMR_ALL_HMR_DMR_5_DMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_5_DMR_CONFIG_REG_ADDR = 64'h00000254;
+localparam longint unsigned HMR_ALL_HMR_DMR_5_DMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+localparam longint unsigned HMR_ALL_HMR_DMR_5_CHECKPOINT_ADDR_REG_ADDR = 64'h00000258;
+localparam longint unsigned HMR_ALL_HMR_DMR_5_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008;
+
+
+localparam longint unsigned HMR_ALL_HMR_TMR_0_BASE_ADDR = 64'h00000300;
+localparam longint unsigned HMR_ALL_HMR_TMR_0_SIZE = 64'h00000040;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_0_TMR_ENABLE_REG_ADDR = 64'h00000300;
+localparam longint unsigned HMR_ALL_HMR_TMR_0_TMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_0_TMR_CONFIG_REG_ADDR = 64'h00000304;
+localparam longint unsigned HMR_ALL_HMR_TMR_0_TMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+
+localparam longint unsigned HMR_ALL_HMR_TMR_1_BASE_ADDR = 64'h00000310;
+localparam longint unsigned HMR_ALL_HMR_TMR_1_SIZE = 64'h00000040;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_1_TMR_ENABLE_REG_ADDR = 64'h00000310;
+localparam longint unsigned HMR_ALL_HMR_TMR_1_TMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_1_TMR_CONFIG_REG_ADDR = 64'h00000314;
+localparam longint unsigned HMR_ALL_HMR_TMR_1_TMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+
+localparam longint unsigned HMR_ALL_HMR_TMR_2_BASE_ADDR = 64'h00000320;
+localparam longint unsigned HMR_ALL_HMR_TMR_2_SIZE = 64'h00000040;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_2_TMR_ENABLE_REG_ADDR = 64'h00000320;
+localparam longint unsigned HMR_ALL_HMR_TMR_2_TMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_2_TMR_CONFIG_REG_ADDR = 64'h00000324;
+localparam longint unsigned HMR_ALL_HMR_TMR_2_TMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+
+localparam longint unsigned HMR_ALL_HMR_TMR_3_BASE_ADDR = 64'h00000330;
+localparam longint unsigned HMR_ALL_HMR_TMR_3_SIZE = 64'h00000040;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_3_TMR_ENABLE_REG_ADDR = 64'h00000330;
+localparam longint unsigned HMR_ALL_HMR_TMR_3_TMR_ENABLE_REG_OFFSET = 64'h00000000;
+
+localparam longint unsigned HMR_ALL_HMR_TMR_3_TMR_CONFIG_REG_ADDR = 64'h00000334;
+localparam longint unsigned HMR_ALL_HMR_TMR_3_TMR_CONFIG_REG_OFFSET = 64'h00000004;
+
+
+endpackage;
diff --git a/rtl/HMR/hmr_registers_reg_pkg.sv b/rtl/HMR/hmr_registers_reg_pkg.sv
index 1c590cce..8f814e0d 100644
--- a/rtl/HMR/hmr_registers_reg_pkg.sv
+++ b/rtl/HMR/hmr_registers_reg_pkg.sv
@@ -1,180 +1,166 @@
-// 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
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+// https://github.com/SystemRDL/PeakRDL-regblock
package hmr_registers_reg_pkg;
- // Param list
- parameter int NumCores = 12;
- parameter int NumDMRGroups = 6;
- parameter int NumTMRGroups = 4;
-
- // Address widths within the block
- parameter int BlockAw = 5;
-
- ////////////////////////////
- // Typedefs for registers //
- ////////////////////////////
-
- typedef struct packed {
- logic [5:0] q;
- logic qe;
- } hmr_registers_reg2hw_dmr_enable_reg_t;
-
- typedef struct packed {
- logic [3:0] q;
- logic qe;
- } hmr_registers_reg2hw_tmr_enable_reg_t;
-
- typedef struct packed {
- struct packed {
- logic q;
- logic qe;
- } rapid_recovery;
- struct packed {
- logic q;
- logic qe;
- } force_recovery;
- } hmr_registers_reg2hw_dmr_config_reg_t;
-
- typedef struct packed {
- struct packed {
- logic q;
- logic qe;
- } delay_resynch;
- struct packed {
- logic q;
- logic qe;
- } setback;
- struct packed {
- logic q;
- logic qe;
- } reload_setback;
- struct packed {
- logic q;
- logic qe;
- } rapid_recovery;
- struct packed {
- logic q;
- logic qe;
- } force_resynch;
- } hmr_registers_reg2hw_tmr_config_reg_t;
-
- typedef struct packed {
- struct packed {
- logic d;
- } independent;
- struct packed {
- logic d;
- } dual;
- struct packed {
- logic d;
- } triple;
- struct packed {
- logic d;
- } rapid_recovery;
- } hmr_registers_hw2reg_avail_config_reg_t;
-
- typedef struct packed {
- logic [11:0] d;
- } hmr_registers_hw2reg_cores_en_reg_t;
-
- typedef struct packed {
- logic [5:0] d;
- } hmr_registers_hw2reg_dmr_enable_reg_t;
-
- typedef struct packed {
- logic [3:0] d;
- } hmr_registers_hw2reg_tmr_enable_reg_t;
-
- typedef struct packed {
- struct packed {
- logic d;
- } rapid_recovery;
- struct packed {
- logic d;
- } force_recovery;
- } hmr_registers_hw2reg_dmr_config_reg_t;
-
- typedef struct packed {
- struct packed {
- logic d;
- } delay_resynch;
- struct packed {
- logic d;
- } setback;
- struct packed {
- logic d;
- } reload_setback;
- struct packed {
- logic d;
- } rapid_recovery;
- struct packed {
- logic d;
- } force_resynch;
- } hmr_registers_hw2reg_tmr_config_reg_t;
-
- // Register -> HW type
- typedef struct packed {
- hmr_registers_reg2hw_dmr_enable_reg_t dmr_enable; // [25:19]
- hmr_registers_reg2hw_tmr_enable_reg_t tmr_enable; // [18:14]
- hmr_registers_reg2hw_dmr_config_reg_t dmr_config; // [13:10]
- hmr_registers_reg2hw_tmr_config_reg_t tmr_config; // [9:0]
- } hmr_registers_reg2hw_t;
-
- // HW -> register type
- typedef struct packed {
- hmr_registers_hw2reg_avail_config_reg_t avail_config; // [32:29]
- hmr_registers_hw2reg_cores_en_reg_t cores_en; // [28:17]
- hmr_registers_hw2reg_dmr_enable_reg_t dmr_enable; // [16:11]
- hmr_registers_hw2reg_tmr_enable_reg_t tmr_enable; // [10:7]
- hmr_registers_hw2reg_dmr_config_reg_t dmr_config; // [6:5]
- hmr_registers_hw2reg_tmr_config_reg_t tmr_config; // [4:0]
- } hmr_registers_hw2reg_t;
-
- // Register offsets
- parameter logic [BlockAw-1:0] HMR_REGISTERS_AVAIL_CONFIG_OFFSET = 5'h 0;
- parameter logic [BlockAw-1:0] HMR_REGISTERS_CORES_EN_OFFSET = 5'h 4;
- parameter logic [BlockAw-1:0] HMR_REGISTERS_DMR_ENABLE_OFFSET = 5'h 8;
- parameter logic [BlockAw-1:0] HMR_REGISTERS_TMR_ENABLE_OFFSET = 5'h c;
- parameter logic [BlockAw-1:0] HMR_REGISTERS_DMR_CONFIG_OFFSET = 5'h 10;
- parameter logic [BlockAw-1:0] HMR_REGISTERS_TMR_CONFIG_OFFSET = 5'h 14;
-
- // Reset values for hwext registers and their fields
- parameter logic [8:0] HMR_REGISTERS_AVAIL_CONFIG_RESVAL = 9'h 0;
- parameter logic [11:0] HMR_REGISTERS_CORES_EN_RESVAL = 12'h 0;
- parameter logic [5:0] HMR_REGISTERS_DMR_ENABLE_RESVAL = 6'h 0;
- parameter logic [5:0] HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_RESVAL = 6'h 0;
- parameter logic [3:0] HMR_REGISTERS_TMR_ENABLE_RESVAL = 4'h 0;
- parameter logic [3:0] HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_RESVAL = 4'h 0;
- parameter logic [1:0] HMR_REGISTERS_DMR_CONFIG_RESVAL = 2'h 0;
- parameter logic [4:0] HMR_REGISTERS_TMR_CONFIG_RESVAL = 5'h 6;
- parameter logic [0:0] HMR_REGISTERS_TMR_CONFIG_DELAY_RESYNCH_RESVAL = 1'h 0;
- parameter logic [0:0] HMR_REGISTERS_TMR_CONFIG_SETBACK_RESVAL = 1'h 1;
- parameter logic [0:0] HMR_REGISTERS_TMR_CONFIG_RELOAD_SETBACK_RESVAL = 1'h 1;
- parameter logic [0:0] HMR_REGISTERS_TMR_CONFIG_FORCE_RESYNCH_RESVAL = 1'h 0;
-
- // Register index
- typedef enum int {
- HMR_REGISTERS_AVAIL_CONFIG,
- HMR_REGISTERS_CORES_EN,
- HMR_REGISTERS_DMR_ENABLE,
- HMR_REGISTERS_TMR_ENABLE,
- HMR_REGISTERS_DMR_CONFIG,
- HMR_REGISTERS_TMR_CONFIG
- } hmr_registers_id_e;
-
- // Register width information to check illegal writes
- parameter logic [3:0] HMR_REGISTERS_PERMIT [6] = '{
- 4'b 0011, // index[0] HMR_REGISTERS_AVAIL_CONFIG
- 4'b 0011, // index[1] HMR_REGISTERS_CORES_EN
- 4'b 0001, // index[2] HMR_REGISTERS_DMR_ENABLE
- 4'b 0001, // index[3] HMR_REGISTERS_TMR_ENABLE
- 4'b 0001, // index[4] HMR_REGISTERS_DMR_CONFIG
- 4'b 0001 // index[5] HMR_REGISTERS_TMR_CONFIG
- };
-
+ localparam HMR_REGISTERS_REG_TOP_DATA_WIDTH = 32;
+ localparam HMR_REGISTERS_REG_TOP_MIN_ADDR_WIDTH = 5;
+ localparam HMR_REGISTERS_REG_TOP_SIZE = 'h18;
+ localparam NumCores = 'hc;
+ localparam NumDMRGroups = 'h6;
+ localparam NumTMRGroups = 'h4;
+
+ typedef struct packed {
+ logic [22:0] _reserved_31_9;
+ logic rapid_recovery;
+ logic [4:0] _reserved_7_3;
+ logic triple;
+ logic dual;
+ logic independent;
+ } hmr__avail_config__external__fields__in_t;
+
+ typedef struct {
+ logic rd_ack;
+ hmr__avail_config__external__fields__in_t rd_data;
+ } hmr__avail_config__external__in_t;
+
+ typedef struct packed {
+ logic [19:0] _reserved_31_12;
+ logic [11:0] cores_en;
+ } hmr__cores_en__external__fields__in_t;
+
+ typedef struct {
+ logic rd_ack;
+ hmr__cores_en__external__fields__in_t rd_data;
+ } hmr__cores_en__external__in_t;
+
+ typedef struct packed {
+ logic [25:0] _reserved_31_6;
+ logic [5:0] dmr_enable;
+ } hmr__dmr_enable__external__fields__in_t;
+
+ typedef struct {
+ logic rd_ack;
+ hmr__dmr_enable__external__fields__in_t rd_data;
+ logic wr_ack;
+ } hmr__dmr_enable__external__in_t;
+
+ typedef struct packed {
+ logic [27:0] _reserved_31_4;
+ logic [3:0] tmr_enable;
+ } hmr__tmr_enable__external__fields__in_t;
+
+ typedef struct {
+ logic rd_ack;
+ hmr__tmr_enable__external__fields__in_t rd_data;
+ logic wr_ack;
+ } hmr__tmr_enable__external__in_t;
+
+ typedef struct packed {
+ logic [29:0] _reserved_31_2;
+ logic force_recovery;
+ logic rapid_recovery;
+ } hmr__dmr_config__external__fields__in_t;
+
+ typedef struct {
+ logic rd_ack;
+ hmr__dmr_config__external__fields__in_t rd_data;
+ logic wr_ack;
+ } hmr__dmr_config__external__in_t;
+
+ typedef struct packed {
+ logic [26:0] _reserved_31_5;
+ logic force_resynch;
+ logic rapid_recovery;
+ logic reload_setback;
+ logic setback;
+ logic delay_resynch;
+ } hmr__tmr_config__external__fields__in_t;
+
+ typedef struct {
+ logic rd_ack;
+ hmr__tmr_config__external__fields__in_t rd_data;
+ logic wr_ack;
+ } hmr__tmr_config__external__in_t;
+
+ typedef struct {
+ hmr__avail_config__external__in_t avail_config;
+ hmr__cores_en__external__in_t cores_en;
+ hmr__dmr_enable__external__in_t dmr_enable;
+ hmr__tmr_enable__external__in_t tmr_enable;
+ hmr__dmr_config__external__in_t dmr_config;
+ hmr__tmr_config__external__in_t tmr_config;
+ } hmr__in_t;
+
+ typedef struct {
+ logic req;
+ logic req_is_wr;
+ } hmr__avail_config__external__out_t;
+
+ typedef struct {
+ logic req;
+ logic req_is_wr;
+ } hmr__cores_en__external__out_t;
+
+ typedef struct packed {
+ logic [25:0] _reserved_31_6;
+ logic [5:0] dmr_enable;
+ } hmr__dmr_enable__external__fields__out_t;
+
+ typedef struct {
+ logic req;
+ logic req_is_wr;
+ hmr__dmr_enable__external__fields__out_t wr_data;
+ hmr__dmr_enable__external__fields__out_t wr_biten;
+ } hmr__dmr_enable__external__out_t;
+
+ typedef struct packed {
+ logic [27:0] _reserved_31_4;
+ logic [3:0] tmr_enable;
+ } hmr__tmr_enable__external__fields__out_t;
+
+ typedef struct {
+ logic req;
+ logic req_is_wr;
+ hmr__tmr_enable__external__fields__out_t wr_data;
+ hmr__tmr_enable__external__fields__out_t wr_biten;
+ } hmr__tmr_enable__external__out_t;
+
+ typedef struct packed {
+ logic [29:0] _reserved_31_2;
+ logic force_recovery;
+ logic rapid_recovery;
+ } hmr__dmr_config__external__fields__out_t;
+
+ typedef struct {
+ logic req;
+ logic req_is_wr;
+ hmr__dmr_config__external__fields__out_t wr_data;
+ hmr__dmr_config__external__fields__out_t wr_biten;
+ } hmr__dmr_config__external__out_t;
+
+ typedef struct packed {
+ logic [26:0] _reserved_31_5;
+ logic force_resynch;
+ logic rapid_recovery;
+ logic reload_setback;
+ logic setback;
+ logic delay_resynch;
+ } hmr__tmr_config__external__fields__out_t;
+
+ typedef struct {
+ logic req;
+ logic req_is_wr;
+ hmr__tmr_config__external__fields__out_t wr_data;
+ hmr__tmr_config__external__fields__out_t wr_biten;
+ } hmr__tmr_config__external__out_t;
+
+ typedef struct {
+ hmr__avail_config__external__out_t avail_config;
+ hmr__cores_en__external__out_t cores_en;
+ hmr__dmr_enable__external__out_t dmr_enable;
+ hmr__tmr_enable__external__out_t tmr_enable;
+ hmr__dmr_config__external__out_t dmr_config;
+ hmr__tmr_config__external__out_t tmr_config;
+ } hmr__out_t;
endpackage
-
diff --git a/rtl/HMR/hmr_registers_reg_top.sv b/rtl/HMR/hmr_registers_reg_top.sv
index 9769fed7..52d5d4dd 100644
--- a/rtl/HMR/hmr_registers_reg_top.sv
+++ b/rtl/HMR/hmr_registers_reg_top.sv
@@ -1,516 +1,246 @@
-// 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`
-
-
-`include "common_cells/assertions.svh"
-
-module hmr_registers_reg_top #(
- parameter type reg_req_t = logic,
- parameter type reg_rsp_t = logic,
- parameter int AW = 5
-) (
- input logic clk_i,
- input logic rst_ni,
- input reg_req_t reg_req_i,
- output reg_rsp_t reg_rsp_o,
- // To HW
- output hmr_registers_reg_pkg::hmr_registers_reg2hw_t reg2hw, // Write
- input hmr_registers_reg_pkg::hmr_registers_hw2reg_t hw2reg, // Read
-
-
- // Config
- input devmode_i // If 1, explicit error return for unmapped register access
-);
-
- import hmr_registers_reg_pkg::* ;
-
- localparam int DW = 32;
- localparam int 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;
-
- // Below register interface can be changed
- reg_req_t reg_intf_req;
- reg_rsp_t reg_intf_rsp;
-
-
- assign reg_intf_req = reg_req_i;
- assign reg_rsp_o = reg_intf_rsp;
-
-
- assign reg_we = reg_intf_req.valid & reg_intf_req.write;
- assign reg_re = reg_intf_req.valid & ~reg_intf_req.write;
- assign reg_addr = reg_intf_req.addr;
- assign reg_wdata = reg_intf_req.wdata;
- assign reg_be = reg_intf_req.wstrb;
- assign reg_intf_rsp.rdata = reg_rdata;
- assign reg_intf_rsp.error = reg_error;
- assign reg_intf_rsp.ready = 1'b1;
-
- assign reg_rdata = reg_rdata_next ;
- assign reg_error = (devmode_i & addrmiss) | wr_err;
-
-
- // Define SW related signals
- // Format: __{wd|we|qs}
- // or _{wd|we|qs} if field == 1 or 0
- logic avail_config_independent_qs;
- logic avail_config_independent_re;
- logic avail_config_dual_qs;
- logic avail_config_dual_re;
- logic avail_config_triple_qs;
- logic avail_config_triple_re;
- logic avail_config_rapid_recovery_qs;
- logic avail_config_rapid_recovery_re;
- logic [11:0] cores_en_qs;
- logic cores_en_re;
- logic [5:0] dmr_enable_qs;
- logic [5:0] dmr_enable_wd;
- logic dmr_enable_we;
- logic dmr_enable_re;
- logic [3:0] tmr_enable_qs;
- logic [3:0] tmr_enable_wd;
- logic tmr_enable_we;
- logic tmr_enable_re;
- logic dmr_config_rapid_recovery_qs;
- logic dmr_config_rapid_recovery_wd;
- logic dmr_config_rapid_recovery_we;
- logic dmr_config_rapid_recovery_re;
- logic dmr_config_force_recovery_qs;
- logic dmr_config_force_recovery_wd;
- logic dmr_config_force_recovery_we;
- logic dmr_config_force_recovery_re;
- logic tmr_config_delay_resynch_qs;
- logic tmr_config_delay_resynch_wd;
- logic tmr_config_delay_resynch_we;
- logic tmr_config_delay_resynch_re;
- logic tmr_config_setback_qs;
- logic tmr_config_setback_wd;
- logic tmr_config_setback_we;
- logic tmr_config_setback_re;
- logic tmr_config_reload_setback_qs;
- logic tmr_config_reload_setback_wd;
- logic tmr_config_reload_setback_we;
- logic tmr_config_reload_setback_re;
- logic tmr_config_rapid_recovery_qs;
- logic tmr_config_rapid_recovery_wd;
- logic tmr_config_rapid_recovery_we;
- logic tmr_config_rapid_recovery_re;
- logic tmr_config_force_resynch_qs;
- logic tmr_config_force_resynch_wd;
- logic tmr_config_force_resynch_we;
- logic tmr_config_force_resynch_re;
-
- // Register instances
- // R[avail_config]: V(True)
-
- // F[independent]: 0:0
- prim_subreg_ext #(
- .DW (1)
- ) u_avail_config_independent (
- .re (avail_config_independent_re),
- .we (1'b0),
- .wd ('0),
- .d (hw2reg.avail_config.independent.d),
- .qre (),
- .qe (),
- .q (),
- .qs (avail_config_independent_qs)
- );
-
-
- // F[dual]: 1:1
- prim_subreg_ext #(
- .DW (1)
- ) u_avail_config_dual (
- .re (avail_config_dual_re),
- .we (1'b0),
- .wd ('0),
- .d (hw2reg.avail_config.dual.d),
- .qre (),
- .qe (),
- .q (),
- .qs (avail_config_dual_qs)
- );
-
-
- // F[triple]: 2:2
- prim_subreg_ext #(
- .DW (1)
- ) u_avail_config_triple (
- .re (avail_config_triple_re),
- .we (1'b0),
- .wd ('0),
- .d (hw2reg.avail_config.triple.d),
- .qre (),
- .qe (),
- .q (),
- .qs (avail_config_triple_qs)
- );
-
-
- // F[rapid_recovery]: 8:8
- prim_subreg_ext #(
- .DW (1)
- ) u_avail_config_rapid_recovery (
- .re (avail_config_rapid_recovery_re),
- .we (1'b0),
- .wd ('0),
- .d (hw2reg.avail_config.rapid_recovery.d),
- .qre (),
- .qe (),
- .q (),
- .qs (avail_config_rapid_recovery_qs)
- );
-
-
- // R[cores_en]: V(True)
-
- prim_subreg_ext #(
- .DW (12)
- ) u_cores_en (
- .re (cores_en_re),
- .we (1'b0),
- .wd ('0),
- .d (hw2reg.cores_en.d),
- .qre (),
- .qe (),
- .q (),
- .qs (cores_en_qs)
- );
-
-
- // R[dmr_enable]: V(True)
-
- prim_subreg_ext #(
- .DW (6)
- ) u_dmr_enable (
- .re (dmr_enable_re),
- .we (dmr_enable_we),
- .wd (dmr_enable_wd),
- .d (hw2reg.dmr_enable.d),
- .qre (),
- .qe (reg2hw.dmr_enable.qe),
- .q (reg2hw.dmr_enable.q ),
- .qs (dmr_enable_qs)
- );
-
-
- // R[tmr_enable]: V(True)
-
- prim_subreg_ext #(
- .DW (4)
- ) u_tmr_enable (
- .re (tmr_enable_re),
- .we (tmr_enable_we),
- .wd (tmr_enable_wd),
- .d (hw2reg.tmr_enable.d),
- .qre (),
- .qe (reg2hw.tmr_enable.qe),
- .q (reg2hw.tmr_enable.q ),
- .qs (tmr_enable_qs)
- );
-
-
- // R[dmr_config]: V(True)
-
- // F[rapid_recovery]: 0:0
- prim_subreg_ext #(
- .DW (1)
- ) u_dmr_config_rapid_recovery (
- .re (dmr_config_rapid_recovery_re),
- .we (dmr_config_rapid_recovery_we),
- .wd (dmr_config_rapid_recovery_wd),
- .d (hw2reg.dmr_config.rapid_recovery.d),
- .qre (),
- .qe (reg2hw.dmr_config.rapid_recovery.qe),
- .q (reg2hw.dmr_config.rapid_recovery.q ),
- .qs (dmr_config_rapid_recovery_qs)
- );
-
-
- // F[force_recovery]: 1:1
- prim_subreg_ext #(
- .DW (1)
- ) u_dmr_config_force_recovery (
- .re (dmr_config_force_recovery_re),
- .we (dmr_config_force_recovery_we),
- .wd (dmr_config_force_recovery_wd),
- .d (hw2reg.dmr_config.force_recovery.d),
- .qre (),
- .qe (reg2hw.dmr_config.force_recovery.qe),
- .q (reg2hw.dmr_config.force_recovery.q ),
- .qs (dmr_config_force_recovery_qs)
- );
-
-
- // R[tmr_config]: V(True)
-
- // F[delay_resynch]: 0:0
- prim_subreg_ext #(
- .DW (1)
- ) u_tmr_config_delay_resynch (
- .re (tmr_config_delay_resynch_re),
- .we (tmr_config_delay_resynch_we),
- .wd (tmr_config_delay_resynch_wd),
- .d (hw2reg.tmr_config.delay_resynch.d),
- .qre (),
- .qe (reg2hw.tmr_config.delay_resynch.qe),
- .q (reg2hw.tmr_config.delay_resynch.q ),
- .qs (tmr_config_delay_resynch_qs)
- );
-
-
- // F[setback]: 1:1
- prim_subreg_ext #(
- .DW (1)
- ) u_tmr_config_setback (
- .re (tmr_config_setback_re),
- .we (tmr_config_setback_we),
- .wd (tmr_config_setback_wd),
- .d (hw2reg.tmr_config.setback.d),
- .qre (),
- .qe (reg2hw.tmr_config.setback.qe),
- .q (reg2hw.tmr_config.setback.q ),
- .qs (tmr_config_setback_qs)
- );
-
-
- // F[reload_setback]: 2:2
- prim_subreg_ext #(
- .DW (1)
- ) u_tmr_config_reload_setback (
- .re (tmr_config_reload_setback_re),
- .we (tmr_config_reload_setback_we),
- .wd (tmr_config_reload_setback_wd),
- .d (hw2reg.tmr_config.reload_setback.d),
- .qre (),
- .qe (reg2hw.tmr_config.reload_setback.qe),
- .q (reg2hw.tmr_config.reload_setback.q ),
- .qs (tmr_config_reload_setback_qs)
- );
-
-
- // F[rapid_recovery]: 3:3
- prim_subreg_ext #(
- .DW (1)
- ) u_tmr_config_rapid_recovery (
- .re (tmr_config_rapid_recovery_re),
- .we (tmr_config_rapid_recovery_we),
- .wd (tmr_config_rapid_recovery_wd),
- .d (hw2reg.tmr_config.rapid_recovery.d),
- .qre (),
- .qe (reg2hw.tmr_config.rapid_recovery.qe),
- .q (reg2hw.tmr_config.rapid_recovery.q ),
- .qs (tmr_config_rapid_recovery_qs)
- );
-
-
- // F[force_resynch]: 4:4
- prim_subreg_ext #(
- .DW (1)
- ) u_tmr_config_force_resynch (
- .re (tmr_config_force_resynch_re),
- .we (tmr_config_force_resynch_we),
- .wd (tmr_config_force_resynch_wd),
- .d (hw2reg.tmr_config.force_resynch.d),
- .qre (),
- .qe (reg2hw.tmr_config.force_resynch.qe),
- .q (reg2hw.tmr_config.force_resynch.q ),
- .qs (tmr_config_force_resynch_qs)
- );
-
-
-
-
- logic [5:0] addr_hit;
- always_comb begin
- addr_hit = '0;
- addr_hit[0] = (reg_addr == HMR_REGISTERS_AVAIL_CONFIG_OFFSET);
- addr_hit[1] = (reg_addr == HMR_REGISTERS_CORES_EN_OFFSET);
- addr_hit[2] = (reg_addr == HMR_REGISTERS_DMR_ENABLE_OFFSET);
- addr_hit[3] = (reg_addr == HMR_REGISTERS_TMR_ENABLE_OFFSET);
- addr_hit[4] = (reg_addr == HMR_REGISTERS_DMR_CONFIG_OFFSET);
- addr_hit[5] = (reg_addr == HMR_REGISTERS_TMR_CONFIG_OFFSET);
- end
-
- assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
-
- // Check sub-word write is permitted
- always_comb begin
- wr_err = (reg_we &
- ((addr_hit[0] & (|(HMR_REGISTERS_PERMIT[0] & ~reg_be))) |
- (addr_hit[1] & (|(HMR_REGISTERS_PERMIT[1] & ~reg_be))) |
- (addr_hit[2] & (|(HMR_REGISTERS_PERMIT[2] & ~reg_be))) |
- (addr_hit[3] & (|(HMR_REGISTERS_PERMIT[3] & ~reg_be))) |
- (addr_hit[4] & (|(HMR_REGISTERS_PERMIT[4] & ~reg_be))) |
- (addr_hit[5] & (|(HMR_REGISTERS_PERMIT[5] & ~reg_be)))));
- end
-
- assign avail_config_independent_re = addr_hit[0] & reg_re & !reg_error;
-
- assign avail_config_dual_re = addr_hit[0] & reg_re & !reg_error;
-
- assign avail_config_triple_re = addr_hit[0] & reg_re & !reg_error;
-
- assign avail_config_rapid_recovery_re = addr_hit[0] & reg_re & !reg_error;
-
- assign cores_en_re = addr_hit[1] & reg_re & !reg_error;
-
- assign dmr_enable_we = addr_hit[2] & reg_we & !reg_error;
- assign dmr_enable_wd = reg_wdata[5:0];
- assign dmr_enable_re = addr_hit[2] & reg_re & !reg_error;
-
- assign tmr_enable_we = addr_hit[3] & reg_we & !reg_error;
- assign tmr_enable_wd = reg_wdata[3:0];
- assign tmr_enable_re = addr_hit[3] & reg_re & !reg_error;
-
- assign dmr_config_rapid_recovery_we = addr_hit[4] & reg_we & !reg_error;
- assign dmr_config_rapid_recovery_wd = reg_wdata[0];
- assign dmr_config_rapid_recovery_re = addr_hit[4] & reg_re & !reg_error;
-
- assign dmr_config_force_recovery_we = addr_hit[4] & reg_we & !reg_error;
- assign dmr_config_force_recovery_wd = reg_wdata[1];
- assign dmr_config_force_recovery_re = addr_hit[4] & reg_re & !reg_error;
-
- assign tmr_config_delay_resynch_we = addr_hit[5] & reg_we & !reg_error;
- assign tmr_config_delay_resynch_wd = reg_wdata[0];
- assign tmr_config_delay_resynch_re = addr_hit[5] & reg_re & !reg_error;
-
- assign tmr_config_setback_we = addr_hit[5] & reg_we & !reg_error;
- assign tmr_config_setback_wd = reg_wdata[1];
- assign tmr_config_setback_re = addr_hit[5] & reg_re & !reg_error;
-
- assign tmr_config_reload_setback_we = addr_hit[5] & reg_we & !reg_error;
- assign tmr_config_reload_setback_wd = reg_wdata[2];
- assign tmr_config_reload_setback_re = addr_hit[5] & reg_re & !reg_error;
-
- assign tmr_config_rapid_recovery_we = addr_hit[5] & reg_we & !reg_error;
- assign tmr_config_rapid_recovery_wd = reg_wdata[3];
- assign tmr_config_rapid_recovery_re = addr_hit[5] & reg_re & !reg_error;
-
- assign tmr_config_force_resynch_we = addr_hit[5] & reg_we & !reg_error;
- assign tmr_config_force_resynch_wd = reg_wdata[4];
- assign tmr_config_force_resynch_re = addr_hit[5] & reg_re & !reg_error;
-
- // Read data return
- always_comb begin
- reg_rdata_next = '0;
- unique case (1'b1)
- addr_hit[0]: begin
- reg_rdata_next[0] = avail_config_independent_qs;
- reg_rdata_next[1] = avail_config_dual_qs;
- reg_rdata_next[2] = avail_config_triple_qs;
- reg_rdata_next[8] = avail_config_rapid_recovery_qs;
- end
-
- addr_hit[1]: begin
- reg_rdata_next[11:0] = cores_en_qs;
- end
-
- addr_hit[2]: begin
- reg_rdata_next[5:0] = dmr_enable_qs;
- end
-
- addr_hit[3]: begin
- reg_rdata_next[3:0] = tmr_enable_qs;
- end
-
- addr_hit[4]: begin
- reg_rdata_next[0] = dmr_config_rapid_recovery_qs;
- reg_rdata_next[1] = dmr_config_force_recovery_qs;
- end
-
- addr_hit[5]: begin
- reg_rdata_next[0] = tmr_config_delay_resynch_qs;
- reg_rdata_next[1] = tmr_config_setback_qs;
- reg_rdata_next[2] = tmr_config_reload_setback_qs;
- reg_rdata_next[3] = tmr_config_rapid_recovery_qs;
- reg_rdata_next[4] = tmr_config_force_resynch_qs;
- end
-
- default: begin
- reg_rdata_next = '1;
- end
- endcase
- end
-
- // Unused signal tieoff
-
- // wdata / byte enable are not always fully used
- // add a blanket unused statement to handle lint waivers
- logic unused_wdata;
- logic unused_be;
- assign unused_wdata = ^reg_wdata;
- assign unused_be = ^reg_be;
-
- // Assertions for Register Interface
- `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit))
-
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+// https://github.com/SystemRDL/PeakRDL-regblock
+
+module hmr_registers_reg_top (
+ input wire clk,
+ input wire arst_n,
+
+ input wire s_apb_psel,
+ input wire s_apb_penable,
+ input wire s_apb_pwrite,
+ input wire [2:0] s_apb_pprot,
+ input wire [4:0] s_apb_paddr,
+ input wire [31:0] s_apb_pwdata,
+ input wire [3:0] s_apb_pstrb,
+ output logic s_apb_pready,
+ output logic [31:0] s_apb_prdata,
+ output logic s_apb_pslverr,
+
+ input hmr_registers_reg_pkg::hmr__in_t hwif_in,
+ output hmr_registers_reg_pkg::hmr__out_t hwif_out
+ );
+
+ //--------------------------------------------------------------------------
+ // CPU Bus interface logic
+ //--------------------------------------------------------------------------
+ logic cpuif_req;
+ logic cpuif_req_is_wr;
+ logic [4:0] cpuif_addr;
+ logic [31:0] cpuif_wr_data;
+ logic [31:0] cpuif_wr_biten;
+ logic cpuif_req_stall_wr;
+ logic cpuif_req_stall_rd;
+
+ logic cpuif_rd_ack;
+ logic cpuif_rd_err;
+ logic [31:0] cpuif_rd_data;
+
+ logic cpuif_wr_ack;
+ logic cpuif_wr_err;
+
+ // Request
+ logic is_active;
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ is_active <= '0;
+ cpuif_req <= '0;
+ cpuif_req_is_wr <= '0;
+ cpuif_addr <= '0;
+ cpuif_wr_data <= '0;
+ cpuif_wr_biten <= '0;
+ end else begin
+ if(~is_active) begin
+ if(s_apb_psel) begin
+ is_active <= '1;
+ cpuif_req <= '1;
+ cpuif_req_is_wr <= s_apb_pwrite;
+ cpuif_addr <= {s_apb_paddr[4:2], 2'b0};
+ cpuif_wr_data <= s_apb_pwdata;
+ for(int i=0; i<4; i++) begin
+ cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}};
+ end
+ end
+ end else begin
+ cpuif_req <= '0;
+ if(cpuif_rd_ack || cpuif_wr_ack) begin
+ is_active <= '0;
+ end
+ end
+ end
+ end
+
+ // Response
+ assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack;
+ assign s_apb_prdata = cpuif_rd_data;
+ assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err;
+
+ logic cpuif_req_masked;
+ logic external_req;
+ logic external_pending;
+ logic external_wr_ack;
+ logic external_rd_ack;
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ external_pending <= '0;
+ end else begin
+ if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1;
+ else if(external_wr_ack | external_rd_ack) external_pending <= '0;
+ `ifndef SYNTHESIS
+ assert_bad_ext_wr_ack: assert(!external_wr_ack || (external_pending | external_req))
+ else $error("An external wr_ack strobe was asserted when no external request was active");
+ assert_bad_ext_rd_ack: assert(!external_rd_ack || (external_pending | external_req))
+ else $error("An external rd_ack strobe was asserted when no external request was active");
+ `endif
+ end
+ end
+
+ // Read & write latencies are balanced. Stalls not required
+ // except if external
+ assign cpuif_req_stall_rd = external_pending;
+ assign cpuif_req_stall_wr = external_pending;
+ assign cpuif_req_masked = cpuif_req
+ & !(!cpuif_req_is_wr & cpuif_req_stall_rd)
+ & !(cpuif_req_is_wr & cpuif_req_stall_wr);
+
+ //--------------------------------------------------------------------------
+ // Address Decode
+ //--------------------------------------------------------------------------
+ typedef struct {
+ logic avail_config;
+ logic cores_en;
+ logic dmr_enable;
+ logic tmr_enable;
+ logic dmr_config;
+ logic tmr_config;
+ } decoded_reg_strb_t;
+ decoded_reg_strb_t decoded_reg_strb;
+ logic decoded_strb_is_external;
+
+ logic decoded_req;
+ logic decoded_req_is_wr;
+ logic [31:0] decoded_wr_data;
+ logic [31:0] decoded_wr_biten;
+
+ always_comb begin
+ automatic logic is_external;
+ is_external = '0;
+ decoded_reg_strb.avail_config = cpuif_req_masked & (cpuif_addr == 5'h0);
+ is_external |= cpuif_req_masked & (cpuif_addr == 5'h0) & !cpuif_req_is_wr;
+ decoded_reg_strb.cores_en = cpuif_req_masked & (cpuif_addr == 5'h4);
+ is_external |= cpuif_req_masked & (cpuif_addr == 5'h4) & !cpuif_req_is_wr;
+ decoded_reg_strb.dmr_enable = cpuif_req_masked & (cpuif_addr == 5'h8);
+ is_external |= cpuif_req_masked & (cpuif_addr == 5'h8);
+ decoded_reg_strb.tmr_enable = cpuif_req_masked & (cpuif_addr == 5'hc);
+ is_external |= cpuif_req_masked & (cpuif_addr == 5'hc);
+ decoded_reg_strb.dmr_config = cpuif_req_masked & (cpuif_addr == 5'h10);
+ is_external |= cpuif_req_masked & (cpuif_addr == 5'h10);
+ decoded_reg_strb.tmr_config = cpuif_req_masked & (cpuif_addr == 5'h14);
+ is_external |= cpuif_req_masked & (cpuif_addr == 5'h14);
+ decoded_strb_is_external = is_external;
+ external_req = is_external;
+ end
+
+ // Pass down signals to next stage
+ assign decoded_req = cpuif_req_masked;
+ assign decoded_req_is_wr = cpuif_req_is_wr;
+ assign decoded_wr_data = cpuif_wr_data;
+ assign decoded_wr_biten = cpuif_wr_biten;
+
+ //--------------------------------------------------------------------------
+ // Field logic
+ //--------------------------------------------------------------------------
+
+
+
+
+
+ assign hwif_out.avail_config.req = !decoded_req_is_wr ? decoded_reg_strb.avail_config : '0;
+ assign hwif_out.avail_config.req_is_wr = decoded_req_is_wr;
+
+ assign hwif_out.cores_en.req = !decoded_req_is_wr ? decoded_reg_strb.cores_en : '0;
+ assign hwif_out.cores_en.req_is_wr = decoded_req_is_wr;
+
+ assign hwif_out.dmr_enable.req = decoded_reg_strb.dmr_enable;
+ assign hwif_out.dmr_enable.req_is_wr = decoded_req_is_wr;
+ assign hwif_out.dmr_enable.wr_data = decoded_wr_data;
+ assign hwif_out.dmr_enable.wr_biten = decoded_wr_biten;
+
+ assign hwif_out.tmr_enable.req = decoded_reg_strb.tmr_enable;
+ assign hwif_out.tmr_enable.req_is_wr = decoded_req_is_wr;
+ assign hwif_out.tmr_enable.wr_data = decoded_wr_data;
+ assign hwif_out.tmr_enable.wr_biten = decoded_wr_biten;
+
+ assign hwif_out.dmr_config.req = decoded_reg_strb.dmr_config;
+ assign hwif_out.dmr_config.req_is_wr = decoded_req_is_wr;
+ assign hwif_out.dmr_config.wr_data = decoded_wr_data;
+ assign hwif_out.dmr_config.wr_biten = decoded_wr_biten;
+
+ assign hwif_out.tmr_config.req = decoded_reg_strb.tmr_config;
+ assign hwif_out.tmr_config.req_is_wr = decoded_req_is_wr;
+ assign hwif_out.tmr_config.wr_data = decoded_wr_data;
+ assign hwif_out.tmr_config.wr_biten = decoded_wr_biten;
+
+ //--------------------------------------------------------------------------
+ // Write response
+ //--------------------------------------------------------------------------
+ always_comb begin
+ automatic logic wr_ack;
+ wr_ack = '0;
+ wr_ack |= hwif_in.dmr_enable.wr_ack;
+ wr_ack |= hwif_in.tmr_enable.wr_ack;
+ wr_ack |= hwif_in.dmr_config.wr_ack;
+ wr_ack |= hwif_in.tmr_config.wr_ack;
+ external_wr_ack = wr_ack;
+ end
+ assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external);
+ // Writes are always granted with no error response
+ assign cpuif_wr_err = '0;
+
+ //--------------------------------------------------------------------------
+ // Readback
+ //--------------------------------------------------------------------------
+ logic readback_external_rd_ack_c;
+ always_comb begin
+ automatic logic rd_ack;
+ rd_ack = '0;
+ rd_ack |= hwif_in.avail_config.rd_ack;
+ rd_ack |= hwif_in.cores_en.rd_ack;
+ rd_ack |= hwif_in.dmr_enable.rd_ack;
+ rd_ack |= hwif_in.tmr_enable.rd_ack;
+ rd_ack |= hwif_in.dmr_config.rd_ack;
+ rd_ack |= hwif_in.tmr_config.rd_ack;
+ readback_external_rd_ack_c = rd_ack;
+ end
+
+ logic readback_external_rd_ack;
+
+ assign readback_external_rd_ack = readback_external_rd_ack_c;
+
+ logic readback_err;
+ logic readback_done;
+ logic [31:0] readback_data;
+
+ // Assign readback values to a flattened array
+ logic [31:0] readback_array[6];
+ assign readback_array[0] = hwif_in.avail_config.rd_ack ? hwif_in.avail_config.rd_data : '0;
+ assign readback_array[1] = hwif_in.cores_en.rd_ack ? hwif_in.cores_en.rd_data : '0;
+ assign readback_array[2] = hwif_in.dmr_enable.rd_ack ? hwif_in.dmr_enable.rd_data : '0;
+ assign readback_array[3] = hwif_in.tmr_enable.rd_ack ? hwif_in.tmr_enable.rd_data : '0;
+ assign readback_array[4] = hwif_in.dmr_config.rd_ack ? hwif_in.dmr_config.rd_data : '0;
+ assign readback_array[5] = hwif_in.tmr_config.rd_ack ? hwif_in.tmr_config.rd_data : '0;
+
+ // Reduce the array
+ always_comb begin
+ automatic logic [31:0] readback_data_var;
+ readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external;
+ readback_err = '0;
+ readback_data_var = '0;
+ for(int i=0; i<6; i++) readback_data_var |= readback_array[i];
+ readback_data = readback_data_var;
+ end
+
+ assign external_rd_ack = readback_external_rd_ack;
+ assign cpuif_rd_ack = readback_done | readback_external_rd_ack;
+ assign cpuif_rd_data = readback_data;
+ assign cpuif_rd_err = readback_err;
endmodule
-
-module hmr_registers_reg_top_intf
-#(
- parameter int AW = 5,
- localparam int DW = 32
-) (
- input logic clk_i,
- input logic rst_ni,
- REG_BUS.in regbus_slave,
- // To HW
- output hmr_registers_reg_pkg::hmr_registers_reg2hw_t reg2hw, // Write
- input hmr_registers_reg_pkg::hmr_registers_hw2reg_t hw2reg, // Read
- // Config
- input devmode_i // If 1, explicit error return for unmapped register access
-);
- localparam int unsigned STRB_WIDTH = DW/8;
-
-`include "register_interface/typedef.svh"
-`include "register_interface/assign.svh"
-
- // Define structs for reg_bus
- typedef logic [AW-1:0] addr_t;
- typedef logic [DW-1:0] data_t;
- typedef logic [STRB_WIDTH-1:0] strb_t;
- `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t)
-
- reg_bus_req_t s_reg_req;
- reg_bus_rsp_t s_reg_rsp;
-
- // Assign SV interface to structs
- `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave)
- `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp)
-
-
-
- hmr_registers_reg_top #(
- .reg_req_t(reg_bus_req_t),
- .reg_rsp_t(reg_bus_rsp_t),
- .AW(AW)
- ) i_regs (
- .clk_i,
- .rst_ni,
- .reg_req_i(s_reg_req),
- .reg_rsp_o(s_reg_rsp),
- .reg2hw, // Write
- .hw2reg, // Read
- .devmode_i
- );
-
-endmodule
-
-
diff --git a/rtl/HMR/hmr_regs.rdl b/rtl/HMR/hmr_regs.rdl
new file mode 100644
index 00000000..a053c0b9
--- /dev/null
+++ b/rtl/HMR/hmr_regs.rdl
@@ -0,0 +1,145 @@
+// Copyright 2025 ETH Zurich and University of Bologna.
+// Copyright and related rights are licensed under the Solderpad Hardware
+// License, Version 0.51 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at
+// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+// or agreed to in writing, software, hardware and materials distributed under
+// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+addrmap hmr #(
+ longint unsigned NumCores = 12,
+ longint unsigned NumDMRGroups = 6,
+ longint unsigned NumTMRGroups = 4
+) {
+
+ reg avail_config {
+ name = "avail_config";
+ desc = "Available Configurations from implemented hardware.";
+ field {
+ name = "independent";
+ desc = "1 if independent mode is available";
+ sw = r;
+ hw = w;
+ } independent[0:0] = 0x1;
+ field {
+ name = "dual";
+ desc = "1 if dual/DMR mode is available";
+ sw = r;
+ hw = w;
+ } dual[1:1] = 0x1;
+ field {
+ name = "triple";
+ desc = "1 if triple/TMR mode is available";
+ sw = r;
+ hw = w;
+ } triple[2:2] = 0x1;
+ field {
+ name = "rapid_recovery";
+ desc = "Number of cores in the system.";
+ sw = r;
+ hw = w;
+ } rapid_recovery[8:8] = 0x1;
+ };
+
+ reg cores_en {
+ name = "cores_en";
+ desc = "Enabled cores, based on the configuration. Can be used for barriers.";
+ field {
+ name = "cores_en";
+ desc = "Enabled cores.";
+ sw = r;
+ hw = w;
+ } cores_en[NumCores-1:0] = 0x0;
+ };
+
+ reg dmr_enable {
+ name = "dmr_enable";
+ desc = "DMR configuration enable, on bit per DMR group.";
+ field {
+ name = "dmr_enable";
+ desc = "Enable DMR mode";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } dmr_enable[NumDMRGroups-1:0] = 0x0;
+ };
+
+ reg tmr_enable {
+ name = "tmr_enable";
+ desc = "TMR configuration enable, on bit per TMR group.";
+ field {
+ name = "tmr_enable";
+ desc = "Enable TMR mode";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } tmr_enable[NumTMRGroups-1:0] = 0x0;
+ };
+ reg dmr_config { // From hmr_dmr_regs.rdl
+ name = "dmr_config";
+ desc = "DMR Configuration Register";
+ field {
+ name = "rapid_recovery";
+ desc = "Enable rapid recovery using an additional register file.";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } rapid_recovery[0:0] = 0x0;
+ field {
+ name = "force_recovery";
+ desc = "Forces recovery routine (if rapid_recovery is available).";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } force_recovery[1:1] = 0x0;
+ };
+ reg tmr_config { // From hmr_tmr_regs.rdl
+ name = "tmr_config";
+ desc = "TMR Configuration Register";
+ field {
+ name = "delay_resynch";
+ desc = "Enable wait-for-restoration.";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } delay_resynch[0:0] = 0x0;
+ field {
+ name = "setback";
+ desc = "Enable setback (synchronous reset) during re-synch.";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } setback[1:1] = 0x1;
+ field {
+ name = "reload_setback";
+ desc = "Enable reload of the setback value from the register.";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } reload_setback[2:2] = 0x1;
+ field {
+ name = "rapid_recovery";
+ desc = "Enable rapid recovery using an additional register file.";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } rapid_recovery[3:3] = 0x0;
+ field {
+ name = "force_resynch";
+ desc = "Forces a resynchronization routine.";
+ sw = rw;
+ hw = rw;
+ swmod = true;
+ } force_resynch[4:4] = 0x0;
+ };
+
+
+ external avail_config avail_config;
+ external cores_en cores_en;
+ external dmr_enable dmr_enable;
+ external tmr_enable tmr_enable;
+ external dmr_config dmr_config;
+ external tmr_config tmr_config;
+};
diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv
index f23512f3..49fefb4d 100644
--- a/rtl/HMR/hmr_tmr_ctrl.sv
+++ b/rtl/HMR/hmr_tmr_ctrl.sv
@@ -15,16 +15,16 @@ module hmr_tmr_ctrl #(
parameter bit TMRFixed = 1'b0,
parameter bit DefaultInTMR = TMRFixed ? 1'b1 : 1'b0,
parameter bit RapidRecovery = 1'b0,
- parameter type reg_req_t = logic,
- parameter type reg_resp_t = logic
+ parameter type apb_req_t = logic,
+ parameter type apb_resp_t = logic
) (
input logic clk_i,
input logic rst_ni,
// input logic test_enable_i,
// Register interface
- input reg_req_t reg_req_i,
- output reg_resp_t reg_resp_o,
+ input apb_req_t apb_req_i,
+ output apb_resp_t apb_resp_o,
// CTRL from external (e.g. HMR ctrl regs)
input logic tmr_enable_q_i,
@@ -65,45 +65,49 @@ module hmr_tmr_ctrl #(
typedef enum logic [2:0] {NON_TMR, TMR_RUN, TMR_UNLOAD, TMR_RELOAD, TMR_RAPID} tmr_mode_e;
localparam tmr_mode_e DefaultTMRMode = DefaultInTMR || TMRFixed ? TMR_RUN : NON_TMR;
- hmr_tmr_regs_reg_pkg::hmr_tmr_regs_reg2hw_t tmr_reg2hw;
- hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t tmr_hw2reg;
+ hmr_tmr_regs_reg_pkg::hmr_tmr__out_t tmr_reg2hw;
+ hmr_tmr_regs_reg_pkg::hmr_tmr__in_t tmr_hw2reg;
tmr_mode_e tmr_red_mode_d, tmr_red_mode_q;
assign grp_in_independent_o = tmr_red_mode_q == NON_TMR;
assign tmr_resynch_req_o = tmr_red_mode_q == TMR_UNLOAD;
- assign rapid_recovery_en_o = tmr_reg2hw.tmr_config.rapid_recovery.q & RapidRecovery;
+ assign rapid_recovery_en_o = tmr_reg2hw.tmr_config.rapid_recovery.value & RapidRecovery;
assign sw_synch_req_o = synch_req & ~synch_req_sent_q;
assign synch_req_sent_d = synch_req;
assign sw_resynch_req_o = resynch_req & ~resynch_req_sent_q;
assign resynch_req_sent_d = resynch_req;
- hmr_tmr_regs_reg_top #(
- .reg_req_t(reg_req_t),
- .reg_rsp_t(reg_resp_t)
- ) i_tmr_regs (
- .clk_i,
- .rst_ni,
- .reg_req_i(reg_req_i),
- .reg_rsp_o(reg_resp_o),
- .reg2hw (tmr_reg2hw),
- .hw2reg (tmr_hw2reg),
- .devmode_i('0)
+ hmr_tmr_regs_reg_top i_tmr_regs (
+ .clk (clk_i),
+ .arst_n (rst_ni),
+ .s_apb_psel (apb_req_i.psel),
+ .s_apb_penable (apb_req_i.penable),
+ .s_apb_pwrite (apb_req_i.pwrite),
+ .s_apb_pprot (apb_req_i.pprot),
+ .s_apb_paddr (apb_req_i.paddr[2:0]),
+ .s_apb_pwdata (apb_req_i.pwdata),
+ .s_apb_pstrb (apb_req_i.pstrb),
+ .s_apb_pready (apb_resp_o.pready),
+ .s_apb_prdata (apb_resp_o.prdata),
+ .s_apb_pslverr (apb_resp_o.pslverr),
+ .hwif_in (tmr_hw2reg),
+ .hwif_out (tmr_reg2hw)
);
// Global config update
- assign tmr_hw2reg.tmr_enable.de = tmr_enable_qe_i;
- assign tmr_hw2reg.tmr_enable.d = tmr_enable_q_i;
- assign tmr_hw2reg.tmr_config.delay_resynch.de = delay_resynch_qe_i;
- assign tmr_hw2reg.tmr_config.delay_resynch.d = delay_resynch_q_i;
- assign tmr_hw2reg.tmr_config.setback.de = setback_qe_i;
- assign tmr_hw2reg.tmr_config.setback.d = setback_q_i;
- assign tmr_hw2reg.tmr_config.reload_setback.de = reload_setback_qe_i;
- assign tmr_hw2reg.tmr_config.reload_setback.d = reload_setback_q_i;
- assign tmr_hw2reg.tmr_config.rapid_recovery.de = rapid_recovery_qe_i;
- assign tmr_hw2reg.tmr_config.rapid_recovery.d = rapid_recovery_q_i;
- assign tmr_hw2reg.tmr_config.force_resynch.d = force_resynch_qe_i ? force_resynch_q_i : 1'b0;
+ assign tmr_hw2reg.tmr_enable.tmr_enable.we = tmr_enable_qe_i;
+ assign tmr_hw2reg.tmr_enable.tmr_enable.next = tmr_enable_q_i;
+ assign tmr_hw2reg.tmr_config.delay_resynch.we = delay_resynch_qe_i;
+ assign tmr_hw2reg.tmr_config.delay_resynch.next = delay_resynch_q_i;
+ assign tmr_hw2reg.tmr_config.setback.we = setback_qe_i;
+ assign tmr_hw2reg.tmr_config.setback.next = setback_q_i;
+ assign tmr_hw2reg.tmr_config.reload_setback.we = reload_setback_qe_i;
+ assign tmr_hw2reg.tmr_config.reload_setback.next = reload_setback_q_i;
+ assign tmr_hw2reg.tmr_config.rapid_recovery.we = rapid_recovery_qe_i;
+ assign tmr_hw2reg.tmr_config.rapid_recovery.next = rapid_recovery_q_i;
+ assign tmr_hw2reg.tmr_config.force_resynch.next = force_resynch_qe_i ? force_resynch_q_i : 1'b0;
/**************************
* FSM for TMR lockstep *
@@ -116,16 +120,16 @@ module hmr_tmr_ctrl #(
resynch_req = 1'b0;
synch_req = 1'b0;
- tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i;
+ tmr_hw2reg.tmr_config.force_resynch.we = force_resynch_qe_i;
case (tmr_red_mode_q)
TMR_RUN: begin
// If forced execute resynchronization
- if (tmr_reg2hw.tmr_config.force_resynch.q) begin
- tmr_hw2reg.tmr_config.force_resynch.de = 1'b1;
- if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin
+ if (tmr_reg2hw.tmr_config.force_resynch.value) begin
+ tmr_hw2reg.tmr_config.force_resynch.we = 1'b1;
+ if (tmr_reg2hw.tmr_config.rapid_recovery.value == 1'b1 && RapidRecovery) begin
tmr_red_mode_d = TMR_RAPID;
- end else if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin
+ end else if (tmr_reg2hw.tmr_config.delay_resynch.value == '0) begin
tmr_red_mode_d = TMR_UNLOAD;
// TODO: buffer the restoration until delay_resynch is disabled
end
@@ -138,9 +142,9 @@ module hmr_tmr_ctrl #(
if (tmr_error_i[1]) tmr_incr_mismatches_o[1] = 1'b1;
if (tmr_error_i[2]) tmr_incr_mismatches_o[2] = 1'b1;
- if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin
+ if (tmr_reg2hw.tmr_config.rapid_recovery.value == 1'b1 && RapidRecovery) begin
tmr_red_mode_d = TMR_RAPID;
- end else if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin
+ end else if (tmr_reg2hw.tmr_config.delay_resynch.value == '0) begin
tmr_red_mode_d = TMR_UNLOAD;
// TODO: buffer the restoration until delay_resynch is disabled
end
@@ -152,7 +156,7 @@ module hmr_tmr_ctrl #(
// If unload complete, go to reload (and reset)
if (!sp_store_is_zero) begin
tmr_red_mode_d = TMR_RELOAD;
- if (tmr_reg2hw.tmr_config.setback.q) begin
+ if (tmr_reg2hw.tmr_config.setback.value) begin
setback_o = 3'b111;
end
end
@@ -164,8 +168,8 @@ module hmr_tmr_ctrl #(
// $display("[HMR-triple] %t - mismatch restored", $realtime);
tmr_red_mode_d = TMR_RUN;
end else begin
- if ((tmr_single_mismatch_i || tmr_failure_i) && tmr_reg2hw.tmr_config.setback.q &&
- tmr_reg2hw.tmr_config.reload_setback.q &&
+ if ((tmr_single_mismatch_i || tmr_failure_i) && tmr_reg2hw.tmr_config.setback.value &&
+ tmr_reg2hw.tmr_config.reload_setback.value &&
!sp_store_will_be_zero) begin
setback_o = 3'b111;
end
@@ -188,14 +192,14 @@ module hmr_tmr_ctrl #(
// Logic to switch in and out of TMR
if (!TMRFixed) begin
// Set TMR mode on external signal that cores are synchronized
- if (tmr_red_mode_q == NON_TMR && tmr_reg2hw.tmr_enable.q == 1'b1) begin
+ if (tmr_red_mode_q == NON_TMR && tmr_reg2hw.tmr_enable.tmr_enable.value == 1'b1) begin
synch_req = 1'b1;
if (cores_synch_q == 1'b1) begin
- if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin
+ if (tmr_reg2hw.tmr_config.rapid_recovery.value == 1'b1 && RapidRecovery) begin
tmr_red_mode_d = TMR_RAPID;
end else begin
tmr_red_mode_d = TMR_RELOAD;
- if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin
+ if (tmr_reg2hw.tmr_config.setback.value == 1'b1) begin
setback_o = 3'b111;
end
end
@@ -203,7 +207,7 @@ module hmr_tmr_ctrl #(
end
// Before core startup: set TMR mode from reg2hw.tmr_enable
if (fetch_en_i == 0) begin
- if (tmr_reg2hw.tmr_enable.q == 1'b0) begin
+ if (tmr_reg2hw.tmr_enable.tmr_enable.value == 1'b0) begin
tmr_red_mode_d = NON_TMR;
end else begin
tmr_red_mode_d = TMR_RUN;
@@ -212,8 +216,8 @@ module hmr_tmr_ctrl #(
end
// split tolerant mode to performance mode anytime (but require correct core state)
if (tmr_red_mode_q == TMR_RUN) begin
- if (tmr_reg2hw.tmr_enable.q == 1'b0) begin
- if (tmr_reg2hw.tmr_config.setback.q) begin
+ if (tmr_reg2hw.tmr_enable.tmr_enable.value == 1'b0) begin
+ if (tmr_reg2hw.tmr_config.setback.value) begin
setback_o = 3'b110;
end
tmr_red_mode_d = NON_TMR;
diff --git a/rtl/HMR/hmr_tmr_regs.rdl b/rtl/HMR/hmr_tmr_regs.rdl
new file mode 100644
index 00000000..664dbdf2
--- /dev/null
+++ b/rtl/HMR/hmr_tmr_regs.rdl
@@ -0,0 +1,71 @@
+// Copyright 2025 ETH Zurich and University of Bologna.
+// Copyright and related rights are licensed under the Solderpad Hardware
+// License, Version 0.51 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at
+// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+// or agreed to in writing, software, hardware and materials distributed under
+// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+addrmap hmr_tmr {
+ reg tmr_enable {
+ name = "tmr_enable";
+ desc = "TMR Configuration Enable";
+ field {
+ name = "enable";
+ desc = "Enable TMR mode";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } tmr_enable[0:0] = 0x0;
+ };
+ reg tmr_config {
+ name = "tmr_config";
+ desc = "TMR Configuration Register";
+ field {
+ name = "delay_resynch";
+ desc = "Enable wait-for-restoration.";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } delay_resynch[0:0] = 0x0;
+ field {
+ name = "setback";
+ desc = "Enable setback (synchronous reset) during re-synch.";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } setback[1:1] = 0x1;
+ field {
+ name = "reload_setback";
+ desc = "Enable reload of the setback value from the register.";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } reload_setback[2:2] = 0x1;
+ field {
+ name = "rapid_recovery";
+ desc = "Enable rapid recovery using an additional register file.";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } rapid_recovery[3:3] = 0x0;
+ field {
+ name = "force_resynch";
+ desc = "Forces a resynchronization routine.";
+ sw = rw;
+ hw = rw;
+ // swmod = true;
+ we = true;
+ } force_resynch[4:4] = 0x0;
+ };
+
+ tmr_enable tmr_enable;
+ tmr_config tmr_config;
+};
diff --git a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv
index 89eeca99..c9d18a35 100644
--- a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv
+++ b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv
@@ -1,101 +1,97 @@
-// 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
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+// https://github.com/SystemRDL/PeakRDL-regblock
package hmr_tmr_regs_reg_pkg;
- // Address widths within the block
- parameter int BlockAw = 3;
-
- ////////////////////////////
- // Typedefs for registers //
- ////////////////////////////
-
- typedef struct packed {
- logic q;
- logic qe;
- } hmr_tmr_regs_reg2hw_tmr_enable_reg_t;
-
- typedef struct packed {
- struct packed {
- logic q;
- logic qe;
- } delay_resynch;
- struct packed {
- logic q;
- logic qe;
- } setback;
- struct packed {
- logic q;
- logic qe;
- } reload_setback;
- struct packed {
- logic q;
- logic qe;
- } rapid_recovery;
- struct packed {
- logic q;
- logic qe;
- } force_resynch;
- } hmr_tmr_regs_reg2hw_tmr_config_reg_t;
-
- typedef struct packed {
- logic d;
- logic de;
- } hmr_tmr_regs_hw2reg_tmr_enable_reg_t;
-
- typedef struct packed {
- struct packed {
- logic d;
- logic de;
- } delay_resynch;
- struct packed {
- logic d;
- logic de;
- } setback;
- struct packed {
- logic d;
- logic de;
- } reload_setback;
- struct packed {
- logic d;
- logic de;
- } rapid_recovery;
- struct packed {
- logic d;
- logic de;
- } force_resynch;
- } hmr_tmr_regs_hw2reg_tmr_config_reg_t;
-
- // Register -> HW type
- typedef struct packed {
- hmr_tmr_regs_reg2hw_tmr_enable_reg_t tmr_enable; // [11:10]
- hmr_tmr_regs_reg2hw_tmr_config_reg_t tmr_config; // [9:0]
- } hmr_tmr_regs_reg2hw_t;
-
- // HW -> register type
- typedef struct packed {
- hmr_tmr_regs_hw2reg_tmr_enable_reg_t tmr_enable; // [11:10]
- hmr_tmr_regs_hw2reg_tmr_config_reg_t tmr_config; // [9:0]
- } hmr_tmr_regs_hw2reg_t;
-
- // Register offsets
- parameter logic [BlockAw-1:0] HMR_TMR_REGS_TMR_ENABLE_OFFSET = 3'h 0;
- parameter logic [BlockAw-1:0] HMR_TMR_REGS_TMR_CONFIG_OFFSET = 3'h 4;
-
- // Register index
- typedef enum int {
- HMR_TMR_REGS_TMR_ENABLE,
- HMR_TMR_REGS_TMR_CONFIG
- } hmr_tmr_regs_id_e;
-
- // Register width information to check illegal writes
- parameter logic [3:0] HMR_TMR_REGS_PERMIT [2] = '{
- 4'b 0001, // index[0] HMR_TMR_REGS_TMR_ENABLE
- 4'b 0001 // index[1] HMR_TMR_REGS_TMR_CONFIG
- };
+ localparam HMR_TMR_REGS_REG_TOP_DATA_WIDTH = 32;
+ localparam HMR_TMR_REGS_REG_TOP_MIN_ADDR_WIDTH = 3;
+ localparam HMR_TMR_REGS_REG_TOP_SIZE = 'h8;
-endpackage
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_tmr__tmr_enable__tmr_enable__in_t;
+
+ typedef struct {
+ hmr_tmr__tmr_enable__tmr_enable__in_t tmr_enable;
+ } hmr_tmr__tmr_enable__in_t;
+
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_tmr__tmr_config__delay_resynch__in_t;
+
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_tmr__tmr_config__setback__in_t;
+
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_tmr__tmr_config__reload_setback__in_t;
+
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_tmr__tmr_config__rapid_recovery__in_t;
+
+ typedef struct {
+ logic next;
+ logic we;
+ } hmr_tmr__tmr_config__force_resynch__in_t;
+
+ typedef struct {
+ hmr_tmr__tmr_config__delay_resynch__in_t delay_resynch;
+ hmr_tmr__tmr_config__setback__in_t setback;
+ hmr_tmr__tmr_config__reload_setback__in_t reload_setback;
+ hmr_tmr__tmr_config__rapid_recovery__in_t rapid_recovery;
+ hmr_tmr__tmr_config__force_resynch__in_t force_resynch;
+ } hmr_tmr__tmr_config__in_t;
+
+ typedef struct {
+ hmr_tmr__tmr_enable__in_t tmr_enable;
+ hmr_tmr__tmr_config__in_t tmr_config;
+ } hmr_tmr__in_t;
+ typedef struct {
+ logic value;
+ } hmr_tmr__tmr_enable__tmr_enable__out_t;
+
+ typedef struct {
+ hmr_tmr__tmr_enable__tmr_enable__out_t tmr_enable;
+ } hmr_tmr__tmr_enable__out_t;
+
+ typedef struct {
+ logic value;
+ } hmr_tmr__tmr_config__delay_resynch__out_t;
+
+ typedef struct {
+ logic value;
+ } hmr_tmr__tmr_config__setback__out_t;
+
+ typedef struct {
+ logic value;
+ } hmr_tmr__tmr_config__reload_setback__out_t;
+
+ typedef struct {
+ logic value;
+ } hmr_tmr__tmr_config__rapid_recovery__out_t;
+
+ typedef struct {
+ logic value;
+ } hmr_tmr__tmr_config__force_resynch__out_t;
+
+ typedef struct {
+ hmr_tmr__tmr_config__delay_resynch__out_t delay_resynch;
+ hmr_tmr__tmr_config__setback__out_t setback;
+ hmr_tmr__tmr_config__reload_setback__out_t reload_setback;
+ hmr_tmr__tmr_config__rapid_recovery__out_t rapid_recovery;
+ hmr_tmr__tmr_config__force_resynch__out_t force_resynch;
+ } hmr_tmr__tmr_config__out_t;
+
+ typedef struct {
+ hmr_tmr__tmr_enable__out_t tmr_enable;
+ hmr_tmr__tmr_config__out_t tmr_config;
+ } hmr_tmr__out_t;
+endpackage
diff --git a/rtl/HMR/hmr_tmr_regs_reg_top.sv b/rtl/HMR/hmr_tmr_regs_reg_top.sv
index 1249580e..4a846355 100644
--- a/rtl/HMR/hmr_tmr_regs_reg_top.sv
+++ b/rtl/HMR/hmr_tmr_regs_reg_top.sv
@@ -1,372 +1,367 @@
-// 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`
-
-
-`include "common_cells/assertions.svh"
-
-module hmr_tmr_regs_reg_top #(
- parameter type reg_req_t = logic,
- parameter type reg_rsp_t = logic,
- parameter int AW = 3
-) (
- input logic clk_i,
- input logic rst_ni,
- input reg_req_t reg_req_i,
- output reg_rsp_t reg_rsp_o,
- // To HW
- output hmr_tmr_regs_reg_pkg::hmr_tmr_regs_reg2hw_t reg2hw, // Write
- input hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t hw2reg, // Read
-
-
- // Config
- input devmode_i // If 1, explicit error return for unmapped register access
-);
-
- import hmr_tmr_regs_reg_pkg::* ;
-
- localparam int DW = 32;
- localparam int 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;
-
- // Below register interface can be changed
- reg_req_t reg_intf_req;
- reg_rsp_t reg_intf_rsp;
-
-
- assign reg_intf_req = reg_req_i;
- assign reg_rsp_o = reg_intf_rsp;
-
-
- assign reg_we = reg_intf_req.valid & reg_intf_req.write;
- assign reg_re = reg_intf_req.valid & ~reg_intf_req.write;
- assign reg_addr = reg_intf_req.addr;
- assign reg_wdata = reg_intf_req.wdata;
- assign reg_be = reg_intf_req.wstrb;
- assign reg_intf_rsp.rdata = reg_rdata;
- assign reg_intf_rsp.error = reg_error;
- assign reg_intf_rsp.ready = 1'b1;
-
- assign reg_rdata = reg_rdata_next ;
- assign reg_error = (devmode_i & addrmiss) | wr_err;
-
-
- // Define SW related signals
- // Format: __{wd|we|qs}
- // or _{wd|we|qs} if field == 1 or 0
- logic tmr_enable_qs;
- logic tmr_enable_wd;
- logic tmr_enable_we;
- logic tmr_config_delay_resynch_qs;
- logic tmr_config_delay_resynch_wd;
- logic tmr_config_delay_resynch_we;
- logic tmr_config_setback_qs;
- logic tmr_config_setback_wd;
- logic tmr_config_setback_we;
- logic tmr_config_reload_setback_qs;
- logic tmr_config_reload_setback_wd;
- logic tmr_config_reload_setback_we;
- logic tmr_config_rapid_recovery_qs;
- logic tmr_config_rapid_recovery_wd;
- logic tmr_config_rapid_recovery_we;
- logic tmr_config_force_resynch_qs;
- logic tmr_config_force_resynch_wd;
- logic tmr_config_force_resynch_we;
-
- // Register instances
- // R[tmr_enable]: V(False)
-
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h0)
- ) u_tmr_enable (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (tmr_enable_we),
- .wd (tmr_enable_wd),
-
- // from internal hardware
- .de (hw2reg.tmr_enable.de),
- .d (hw2reg.tmr_enable.d ),
-
- // to internal hardware
- .qe (reg2hw.tmr_enable.qe),
- .q (reg2hw.tmr_enable.q ),
-
- // to register interface (read)
- .qs (tmr_enable_qs)
- );
-
-
- // R[tmr_config]: V(False)
-
- // F[delay_resynch]: 0:0
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h0)
- ) u_tmr_config_delay_resynch (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (tmr_config_delay_resynch_we),
- .wd (tmr_config_delay_resynch_wd),
-
- // from internal hardware
- .de (hw2reg.tmr_config.delay_resynch.de),
- .d (hw2reg.tmr_config.delay_resynch.d ),
-
- // to internal hardware
- .qe (reg2hw.tmr_config.delay_resynch.qe),
- .q (reg2hw.tmr_config.delay_resynch.q ),
-
- // to register interface (read)
- .qs (tmr_config_delay_resynch_qs)
- );
-
-
- // F[setback]: 1:1
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h1)
- ) u_tmr_config_setback (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (tmr_config_setback_we),
- .wd (tmr_config_setback_wd),
-
- // from internal hardware
- .de (hw2reg.tmr_config.setback.de),
- .d (hw2reg.tmr_config.setback.d ),
-
- // to internal hardware
- .qe (reg2hw.tmr_config.setback.qe),
- .q (reg2hw.tmr_config.setback.q ),
-
- // to register interface (read)
- .qs (tmr_config_setback_qs)
- );
-
-
- // F[reload_setback]: 2:2
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h1)
- ) u_tmr_config_reload_setback (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (tmr_config_reload_setback_we),
- .wd (tmr_config_reload_setback_wd),
-
- // from internal hardware
- .de (hw2reg.tmr_config.reload_setback.de),
- .d (hw2reg.tmr_config.reload_setback.d ),
-
- // to internal hardware
- .qe (reg2hw.tmr_config.reload_setback.qe),
- .q (reg2hw.tmr_config.reload_setback.q ),
-
- // to register interface (read)
- .qs (tmr_config_reload_setback_qs)
- );
-
-
- // F[rapid_recovery]: 3:3
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h0)
- ) u_tmr_config_rapid_recovery (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (tmr_config_rapid_recovery_we),
- .wd (tmr_config_rapid_recovery_wd),
-
- // from internal hardware
- .de (hw2reg.tmr_config.rapid_recovery.de),
- .d (hw2reg.tmr_config.rapid_recovery.d ),
-
- // to internal hardware
- .qe (reg2hw.tmr_config.rapid_recovery.qe),
- .q (reg2hw.tmr_config.rapid_recovery.q ),
-
- // to register interface (read)
- .qs (tmr_config_rapid_recovery_qs)
- );
-
-
- // F[force_resynch]: 4:4
- prim_subreg #(
- .DW (1),
- .SWACCESS("RW"),
- .RESVAL (1'h0)
- ) u_tmr_config_force_resynch (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
- .we (tmr_config_force_resynch_we),
- .wd (tmr_config_force_resynch_wd),
-
- // from internal hardware
- .de (hw2reg.tmr_config.force_resynch.de),
- .d (hw2reg.tmr_config.force_resynch.d ),
-
- // to internal hardware
- .qe (reg2hw.tmr_config.force_resynch.qe),
- .q (reg2hw.tmr_config.force_resynch.q ),
-
- // to register interface (read)
- .qs (tmr_config_force_resynch_qs)
- );
-
-
-
-
- logic [1:0] addr_hit;
- always_comb begin
- addr_hit = '0;
- addr_hit[0] = (reg_addr == HMR_TMR_REGS_TMR_ENABLE_OFFSET);
- addr_hit[1] = (reg_addr == HMR_TMR_REGS_TMR_CONFIG_OFFSET);
- end
-
- assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
-
- // Check sub-word write is permitted
- always_comb begin
- wr_err = (reg_we &
- ((addr_hit[0] & (|(HMR_TMR_REGS_PERMIT[0] & ~reg_be))) |
- (addr_hit[1] & (|(HMR_TMR_REGS_PERMIT[1] & ~reg_be)))));
- end
-
- assign tmr_enable_we = addr_hit[0] & reg_we & !reg_error;
- assign tmr_enable_wd = reg_wdata[0];
-
- assign tmr_config_delay_resynch_we = addr_hit[1] & reg_we & !reg_error;
- assign tmr_config_delay_resynch_wd = reg_wdata[0];
-
- assign tmr_config_setback_we = addr_hit[1] & reg_we & !reg_error;
- assign tmr_config_setback_wd = reg_wdata[1];
-
- assign tmr_config_reload_setback_we = addr_hit[1] & reg_we & !reg_error;
- assign tmr_config_reload_setback_wd = reg_wdata[2];
-
- assign tmr_config_rapid_recovery_we = addr_hit[1] & reg_we & !reg_error;
- assign tmr_config_rapid_recovery_wd = reg_wdata[3];
-
- assign tmr_config_force_resynch_we = addr_hit[1] & reg_we & !reg_error;
- assign tmr_config_force_resynch_wd = reg_wdata[4];
-
- // Read data return
- always_comb begin
- reg_rdata_next = '0;
- unique case (1'b1)
- addr_hit[0]: begin
- reg_rdata_next[0] = tmr_enable_qs;
- end
-
- addr_hit[1]: begin
- reg_rdata_next[0] = tmr_config_delay_resynch_qs;
- reg_rdata_next[1] = tmr_config_setback_qs;
- reg_rdata_next[2] = tmr_config_reload_setback_qs;
- reg_rdata_next[3] = tmr_config_rapid_recovery_qs;
- reg_rdata_next[4] = tmr_config_force_resynch_qs;
- end
-
- default: begin
- reg_rdata_next = '1;
- end
- endcase
- end
-
- // Unused signal tieoff
-
- // wdata / byte enable are not always fully used
- // add a blanket unused statement to handle lint waivers
- logic unused_wdata;
- logic unused_be;
- assign unused_wdata = ^reg_wdata;
- assign unused_be = ^reg_be;
-
- // Assertions for Register Interface
- `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit))
-
-endmodule
-
-module hmr_tmr_regs_reg_top_intf
-#(
- parameter int AW = 3,
- localparam int DW = 32
-) (
- input logic clk_i,
- input logic rst_ni,
- REG_BUS.in regbus_slave,
- // To HW
- output hmr_tmr_regs_reg_pkg::hmr_tmr_regs_reg2hw_t reg2hw, // Write
- input hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t hw2reg, // Read
- // Config
- input devmode_i // If 1, explicit error return for unmapped register access
-);
- localparam int unsigned STRB_WIDTH = DW/8;
-
-`include "register_interface/typedef.svh"
-`include "register_interface/assign.svh"
-
- // Define structs for reg_bus
- typedef logic [AW-1:0] addr_t;
- typedef logic [DW-1:0] data_t;
- typedef logic [STRB_WIDTH-1:0] strb_t;
- `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t)
-
- reg_bus_req_t s_reg_req;
- reg_bus_rsp_t s_reg_rsp;
-
- // Assign SV interface to structs
- `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave)
- `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp)
-
-
-
- hmr_tmr_regs_reg_top #(
- .reg_req_t(reg_bus_req_t),
- .reg_rsp_t(reg_bus_rsp_t),
- .AW(AW)
- ) i_regs (
- .clk_i,
- .rst_ni,
- .reg_req_i(s_reg_req),
- .reg_rsp_o(s_reg_rsp),
- .reg2hw, // Write
- .hw2reg, // Read
- .devmode_i
- );
-
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+// https://github.com/SystemRDL/PeakRDL-regblock
+
+module hmr_tmr_regs_reg_top (
+ input wire clk,
+ input wire arst_n,
+
+ input wire s_apb_psel,
+ input wire s_apb_penable,
+ input wire s_apb_pwrite,
+ input wire [2:0] s_apb_pprot,
+ input wire [2:0] s_apb_paddr,
+ input wire [31:0] s_apb_pwdata,
+ input wire [3:0] s_apb_pstrb,
+ output logic s_apb_pready,
+ output logic [31:0] s_apb_prdata,
+ output logic s_apb_pslverr,
+
+ input hmr_tmr_regs_reg_pkg::hmr_tmr__in_t hwif_in,
+ output hmr_tmr_regs_reg_pkg::hmr_tmr__out_t hwif_out
+ );
+
+ //--------------------------------------------------------------------------
+ // CPU Bus interface logic
+ //--------------------------------------------------------------------------
+ logic cpuif_req;
+ logic cpuif_req_is_wr;
+ logic [2:0] cpuif_addr;
+ logic [31:0] cpuif_wr_data;
+ logic [31:0] cpuif_wr_biten;
+ logic cpuif_req_stall_wr;
+ logic cpuif_req_stall_rd;
+
+ logic cpuif_rd_ack;
+ logic cpuif_rd_err;
+ logic [31:0] cpuif_rd_data;
+
+ logic cpuif_wr_ack;
+ logic cpuif_wr_err;
+
+ // Request
+ logic is_active;
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ is_active <= '0;
+ cpuif_req <= '0;
+ cpuif_req_is_wr <= '0;
+ cpuif_addr <= '0;
+ cpuif_wr_data <= '0;
+ cpuif_wr_biten <= '0;
+ end else begin
+ if(~is_active) begin
+ if(s_apb_psel) begin
+ is_active <= '1;
+ cpuif_req <= '1;
+ cpuif_req_is_wr <= s_apb_pwrite;
+ cpuif_addr <= {s_apb_paddr[2:2], 2'b0};
+ cpuif_wr_data <= s_apb_pwdata;
+ for(int i=0; i<4; i++) begin
+ cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}};
+ end
+ end
+ end else begin
+ cpuif_req <= '0;
+ if(cpuif_rd_ack || cpuif_wr_ack) begin
+ is_active <= '0;
+ end
+ end
+ end
+ end
+
+ // Response
+ assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack;
+ assign s_apb_prdata = cpuif_rd_data;
+ assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err;
+
+ logic cpuif_req_masked;
+
+ // Read & write latencies are balanced. Stalls not required
+ assign cpuif_req_stall_rd = '0;
+ assign cpuif_req_stall_wr = '0;
+ assign cpuif_req_masked = cpuif_req
+ & !(!cpuif_req_is_wr & cpuif_req_stall_rd)
+ & !(cpuif_req_is_wr & cpuif_req_stall_wr);
+
+ //--------------------------------------------------------------------------
+ // Address Decode
+ //--------------------------------------------------------------------------
+ typedef struct {
+ logic tmr_enable;
+ logic tmr_config;
+ } decoded_reg_strb_t;
+ decoded_reg_strb_t decoded_reg_strb;
+ logic decoded_req;
+ logic decoded_req_is_wr;
+ logic [31:0] decoded_wr_data;
+ logic [31:0] decoded_wr_biten;
+
+ always_comb begin
+ decoded_reg_strb.tmr_enable = cpuif_req_masked & (cpuif_addr == 3'h0);
+ decoded_reg_strb.tmr_config = cpuif_req_masked & (cpuif_addr == 3'h4);
+ end
+
+ // Pass down signals to next stage
+ assign decoded_req = cpuif_req_masked;
+ assign decoded_req_is_wr = cpuif_req_is_wr;
+ assign decoded_wr_data = cpuif_wr_data;
+ assign decoded_wr_biten = cpuif_wr_biten;
+
+ //--------------------------------------------------------------------------
+ // Field logic
+ //--------------------------------------------------------------------------
+ typedef struct {
+ struct {
+ struct {
+ logic next;
+ logic load_next;
+ } tmr_enable;
+ } tmr_enable;
+ struct {
+ struct {
+ logic next;
+ logic load_next;
+ } delay_resynch;
+ struct {
+ logic next;
+ logic load_next;
+ } setback;
+ struct {
+ logic next;
+ logic load_next;
+ } reload_setback;
+ struct {
+ logic next;
+ logic load_next;
+ } rapid_recovery;
+ struct {
+ logic next;
+ logic load_next;
+ } force_resynch;
+ } tmr_config;
+ } field_combo_t;
+ field_combo_t field_combo;
+
+ typedef struct {
+ struct {
+ struct {
+ logic value;
+ } tmr_enable;
+ } tmr_enable;
+ struct {
+ struct {
+ logic value;
+ } delay_resynch;
+ struct {
+ logic value;
+ } setback;
+ struct {
+ logic value;
+ } reload_setback;
+ struct {
+ logic value;
+ } rapid_recovery;
+ struct {
+ logic value;
+ } force_resynch;
+ } tmr_config;
+ } field_storage_t;
+ field_storage_t field_storage;
+
+ // Field: hmr_tmr.tmr_enable.tmr_enable
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.tmr_enable.tmr_enable.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.tmr_enable && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.tmr_enable.tmr_enable.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]);
+ load_next_c = '1;
+ end else if(hwif_in.tmr_enable.tmr_enable.we) begin // HW Write - we
+ next_c = hwif_in.tmr_enable.tmr_enable.next;
+ load_next_c = '1;
+ end
+ field_combo.tmr_enable.tmr_enable.next = next_c;
+ field_combo.tmr_enable.tmr_enable.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.tmr_enable.tmr_enable.value <= 1'h0;
+ end else begin
+ if(field_combo.tmr_enable.tmr_enable.load_next) begin
+ field_storage.tmr_enable.tmr_enable.value <= field_combo.tmr_enable.tmr_enable.next;
+ end
+ end
+ end
+ assign hwif_out.tmr_enable.tmr_enable.value = field_storage.tmr_enable.tmr_enable.value;
+ // Field: hmr_tmr.tmr_config.delay_resynch
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.tmr_config.delay_resynch.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.tmr_config.delay_resynch.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]);
+ load_next_c = '1;
+ end else if(hwif_in.tmr_config.delay_resynch.we) begin // HW Write - we
+ next_c = hwif_in.tmr_config.delay_resynch.next;
+ load_next_c = '1;
+ end
+ field_combo.tmr_config.delay_resynch.next = next_c;
+ field_combo.tmr_config.delay_resynch.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.tmr_config.delay_resynch.value <= 1'h0;
+ end else begin
+ if(field_combo.tmr_config.delay_resynch.load_next) begin
+ field_storage.tmr_config.delay_resynch.value <= field_combo.tmr_config.delay_resynch.next;
+ end
+ end
+ end
+ assign hwif_out.tmr_config.delay_resynch.value = field_storage.tmr_config.delay_resynch.value;
+ // Field: hmr_tmr.tmr_config.setback
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.tmr_config.setback.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.tmr_config.setback.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]);
+ load_next_c = '1;
+ end else if(hwif_in.tmr_config.setback.we) begin // HW Write - we
+ next_c = hwif_in.tmr_config.setback.next;
+ load_next_c = '1;
+ end
+ field_combo.tmr_config.setback.next = next_c;
+ field_combo.tmr_config.setback.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.tmr_config.setback.value <= 1'h1;
+ end else begin
+ if(field_combo.tmr_config.setback.load_next) begin
+ field_storage.tmr_config.setback.value <= field_combo.tmr_config.setback.next;
+ end
+ end
+ end
+ assign hwif_out.tmr_config.setback.value = field_storage.tmr_config.setback.value;
+ // Field: hmr_tmr.tmr_config.reload_setback
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.tmr_config.reload_setback.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.tmr_config.reload_setback.value & ~decoded_wr_biten[2:2]) | (decoded_wr_data[2:2] & decoded_wr_biten[2:2]);
+ load_next_c = '1;
+ end else if(hwif_in.tmr_config.reload_setback.we) begin // HW Write - we
+ next_c = hwif_in.tmr_config.reload_setback.next;
+ load_next_c = '1;
+ end
+ field_combo.tmr_config.reload_setback.next = next_c;
+ field_combo.tmr_config.reload_setback.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.tmr_config.reload_setback.value <= 1'h1;
+ end else begin
+ if(field_combo.tmr_config.reload_setback.load_next) begin
+ field_storage.tmr_config.reload_setback.value <= field_combo.tmr_config.reload_setback.next;
+ end
+ end
+ end
+ assign hwif_out.tmr_config.reload_setback.value = field_storage.tmr_config.reload_setback.value;
+ // Field: hmr_tmr.tmr_config.rapid_recovery
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.tmr_config.rapid_recovery.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.tmr_config.rapid_recovery.value & ~decoded_wr_biten[3:3]) | (decoded_wr_data[3:3] & decoded_wr_biten[3:3]);
+ load_next_c = '1;
+ end else if(hwif_in.tmr_config.rapid_recovery.we) begin // HW Write - we
+ next_c = hwif_in.tmr_config.rapid_recovery.next;
+ load_next_c = '1;
+ end
+ field_combo.tmr_config.rapid_recovery.next = next_c;
+ field_combo.tmr_config.rapid_recovery.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.tmr_config.rapid_recovery.value <= 1'h0;
+ end else begin
+ if(field_combo.tmr_config.rapid_recovery.load_next) begin
+ field_storage.tmr_config.rapid_recovery.value <= field_combo.tmr_config.rapid_recovery.next;
+ end
+ end
+ end
+ assign hwif_out.tmr_config.rapid_recovery.value = field_storage.tmr_config.rapid_recovery.value;
+ // Field: hmr_tmr.tmr_config.force_resynch
+ always_comb begin
+ automatic logic [0:0] next_c;
+ automatic logic load_next_c;
+ next_c = field_storage.tmr_config.force_resynch.value;
+ load_next_c = '0;
+ if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write
+ next_c = (field_storage.tmr_config.force_resynch.value & ~decoded_wr_biten[4:4]) | (decoded_wr_data[4:4] & decoded_wr_biten[4:4]);
+ load_next_c = '1;
+ end else if(hwif_in.tmr_config.force_resynch.we) begin // HW Write - we
+ next_c = hwif_in.tmr_config.force_resynch.next;
+ load_next_c = '1;
+ end
+ field_combo.tmr_config.force_resynch.next = next_c;
+ field_combo.tmr_config.force_resynch.load_next = load_next_c;
+ end
+ always_ff @(posedge clk or negedge arst_n) begin
+ if(~arst_n) begin
+ field_storage.tmr_config.force_resynch.value <= 1'h0;
+ end else begin
+ if(field_combo.tmr_config.force_resynch.load_next) begin
+ field_storage.tmr_config.force_resynch.value <= field_combo.tmr_config.force_resynch.next;
+ end
+ end
+ end
+ assign hwif_out.tmr_config.force_resynch.value = field_storage.tmr_config.force_resynch.value;
+
+ //--------------------------------------------------------------------------
+ // Write response
+ //--------------------------------------------------------------------------
+ assign cpuif_wr_ack = decoded_req & decoded_req_is_wr;
+ // Writes are always granted with no error response
+ assign cpuif_wr_err = '0;
+
+ //--------------------------------------------------------------------------
+ // Readback
+ //--------------------------------------------------------------------------
+
+ logic readback_err;
+ logic readback_done;
+ logic [31:0] readback_data;
+
+ // Assign readback values to a flattened array
+ logic [31:0] readback_array[2];
+ assign readback_array[0][0:0] = (decoded_reg_strb.tmr_enable && !decoded_req_is_wr) ? field_storage.tmr_enable.tmr_enable.value : '0;
+ assign readback_array[0][31:1] = '0;
+ assign readback_array[1][0:0] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.delay_resynch.value : '0;
+ assign readback_array[1][1:1] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.setback.value : '0;
+ assign readback_array[1][2:2] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.reload_setback.value : '0;
+ assign readback_array[1][3:3] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.rapid_recovery.value : '0;
+ assign readback_array[1][4:4] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.force_resynch.value : '0;
+ assign readback_array[1][31:5] = '0;
+
+ // Reduce the array
+ always_comb begin
+ automatic logic [31:0] readback_data_var;
+ readback_done = decoded_req & ~decoded_req_is_wr;
+ readback_err = '0;
+ readback_data_var = '0;
+ for(int i=0; i<2; i++) readback_data_var |= readback_array[i];
+ readback_data = readback_data_var;
+ end
+
+ assign cpuif_rd_ack = readback_done;
+ assign cpuif_rd_data = readback_data;
+ assign cpuif_rd_err = readback_err;
endmodule
-
-
diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv
index bbabbce5..f1c56e31 100644
--- a/rtl/HMR/hmr_unit.sv
+++ b/rtl/HMR/hmr_unit.sv
@@ -38,9 +38,9 @@ module hmr_unit #(
parameter type bus_outputs_t = logic,
/// Default bus outputs when output ports are disabled (requires SeparateData)
parameter bus_outputs_t DefaultBusOutputs = '{ default: '0 },
- /// Register bus types
- parameter type reg_req_t = logic,
- parameter type reg_rsp_t = logic,
+ /// APB bus types for config registers
+ parameter type apb_req_t = logic,
+ parameter type apb_resp_t = logic,
/// Enables rapid recovery feature
parameter bit RapidRecovery = 1'b0,
/// Address width of the core register file (in RISC-V it should be always 6) (requires RapidRecovery)
@@ -72,8 +72,8 @@ module hmr_unit #(
input logic rst_ni,
/// Port to configuration unit
- input reg_req_t reg_request_i ,
- output reg_rsp_t reg_response_o,
+ input apb_req_t apb_req_i ,
+ output apb_resp_t apb_resp_o,
/// TMR signals
/// Indicates if the TMR group has multiple mismatches
@@ -241,119 +241,156 @@ module hmr_unit #(
'0;
end
- reg_req_t [3:0] top_register_reqs;
- reg_rsp_t [3:0] top_register_resps;
+ apb_req_t [3:0] top_register_reqs;
+ apb_resp_t [3:0] top_register_resps;
// 0x000-0x100 -> Top config
// 0x100-0x200 -> Core configs
// 0x200-0x300 -> DMR configs
// 0x300-0x400 -> TMR configs
- reg_demux #(
- .NoPorts ( 4 ),
- .req_t ( reg_req_t ),
- .rsp_t ( reg_rsp_t )
+ apb_demux #(
+ .NoMstPorts ( 4 ),
+ .req_t ( apb_req_t ),
+ .resp_t ( apb_resp_t )
) i_reg_demux (
- .clk_i,
- .rst_ni,
- .in_select_i( reg_request_i.addr[9:8] ),
- .in_req_i ( reg_request_i ),
- .in_rsp_o ( reg_response_o ),
- .out_req_o ( top_register_reqs ),
- .out_rsp_i ( top_register_resps )
+ .select_i ( apb_req_i.paddr[9:8] ),
+ .slv_req_i ( apb_req_i ),
+ .slv_resp_o ( apb_resp_o ),
+ .mst_req_o ( top_register_reqs ),
+ .mst_resp_i ( top_register_resps )
);
// Global config registers
- hmr_registers_reg_pkg::hmr_registers_hw2reg_t hmr_hw2reg;
- hmr_registers_reg_pkg::hmr_registers_reg2hw_t hmr_reg2hw;
-
- hmr_registers_reg_top #(
- .reg_req_t( reg_req_t ),
- .reg_rsp_t( reg_rsp_t )
- ) i_hmr_registers (
- .clk_i,
- .rst_ni,
- .reg_req_i(top_register_reqs[0] ),
- .reg_rsp_o(top_register_resps[0]),
- .reg2hw (hmr_reg2hw),
- .hw2reg (hmr_hw2reg),
- .devmode_i('0)
+ hmr_registers_reg_pkg::hmr__in_t hmr_hw2reg;
+ hmr_registers_reg_pkg::hmr__out_t hmr_reg2hw;
+
+ hmr_registers_reg_top i_hmr_registers (
+ .clk (clk_i),
+ .arst_n (rst_ni),
+ .s_apb_psel (top_register_reqs[0].psel),
+ .s_apb_penable (top_register_reqs[0].penable),
+ .s_apb_pwrite (top_register_reqs[0].pwrite),
+ .s_apb_pprot (top_register_reqs[0].pprot),
+ .s_apb_paddr (top_register_reqs[0].paddr[4:0]),
+ .s_apb_pwdata (top_register_reqs[0].pwdata),
+ .s_apb_pstrb (top_register_reqs[0].pstrb),
+ .s_apb_pready (top_register_resps[0].pready),
+ .s_apb_prdata (top_register_resps[0].prdata),
+ .s_apb_pslverr (top_register_resps[0].pslverr),
+ .hwif_out (hmr_reg2hw),
+ .hwif_in (hmr_hw2reg)
);
- assign hmr_hw2reg.avail_config.independent.d = ~(TMRFixed | DMRFixed);
- assign hmr_hw2reg.avail_config.dual.d = DMRFixed | DMRSupported;
- assign hmr_hw2reg.avail_config.triple.d = TMRFixed | TMRSupported;
- assign hmr_hw2reg.avail_config.rapid_recovery.d = RapidRecovery;
-
always_comb begin : proc_reg_status
- hmr_hw2reg.cores_en.d = '0;
- hmr_hw2reg.cores_en.d = core_en_as_master;
-
- hmr_hw2reg.dmr_enable.d = '0;
- hmr_hw2reg.dmr_enable.d[NumDMRGroups-1:0] = ~dmr_grp_in_independent;
- hmr_hw2reg.tmr_enable.d = '0;
- hmr_hw2reg.tmr_enable.d[NumTMRGroups-1:0] = ~tmr_grp_in_independent;
+ hmr_hw2reg.avail_config.rd_data = '{default: '0};
+ hmr_hw2reg.avail_config.rd_data.independent = ~(TMRFixed | DMRFixed);
+ hmr_hw2reg.avail_config.rd_data.dual = DMRFixed | DMRSupported;
+ hmr_hw2reg.avail_config.rd_data.triple = TMRFixed | TMRSupported;
+ hmr_hw2reg.avail_config.rd_data.rapid_recovery = RapidRecovery;
+
+ hmr_hw2reg.cores_en.rd_data = '{default: '0};
+ hmr_hw2reg.cores_en.rd_data.cores_en = core_en_as_master;
+
+ hmr_hw2reg.dmr_enable.rd_data = '{default: '0};
+ hmr_hw2reg.dmr_enable.rd_data.dmr_enable[NumDMRGroups-1:0] = ~dmr_grp_in_independent;
+
+ hmr_hw2reg.tmr_enable.rd_data = '{default: '0};
+ hmr_hw2reg.tmr_enable.rd_data.tmr_enable[NumTMRGroups-1:0] = ~tmr_grp_in_independent;
+
+ hmr_hw2reg.tmr_config.rd_data = '{default: '0};
+ hmr_hw2reg.tmr_config.rd_data.delay_resynch = '0;
+ hmr_hw2reg.tmr_config.rd_data.setback = '0;
+ hmr_hw2reg.tmr_config.rd_data.reload_setback = '0;
+ hmr_hw2reg.tmr_config.rd_data.force_resynch = '0;
+ hmr_hw2reg.tmr_config.rd_data.rapid_recovery = '0;
+
+ hmr_hw2reg.dmr_config.rd_data = '{default: '0};
+ hmr_hw2reg.dmr_config.rd_data.rapid_recovery = '0;
+ hmr_hw2reg.dmr_config.rd_data.force_recovery = '0;
end
-
- assign hmr_hw2reg.tmr_config.delay_resynch.d = '0;
- assign hmr_hw2reg.tmr_config.setback.d = '0;
- assign hmr_hw2reg.tmr_config.reload_setback.d = '0;
- assign hmr_hw2reg.tmr_config.force_resynch.d = '0;
- assign hmr_hw2reg.tmr_config.rapid_recovery.d = '0;
-
- assign hmr_hw2reg.dmr_config.rapid_recovery.d = '0;
- assign hmr_hw2reg.dmr_config.force_recovery.d = '0;
+ assign hmr_hw2reg.avail_config.rd_ack = hmr_reg2hw.avail_config.req &&
+ !hmr_reg2hw.avail_config.req_is_wr;
+ assign hmr_hw2reg.cores_en.rd_ack = hmr_reg2hw.cores_en.req &&
+ !hmr_reg2hw.cores_en.req_is_wr;
+ assign hmr_hw2reg.dmr_enable.rd_ack = hmr_reg2hw.dmr_enable.req &&
+ !hmr_reg2hw.dmr_enable.req_is_wr;
+ assign hmr_hw2reg.dmr_enable.wr_ack = hmr_reg2hw.dmr_enable.req &&
+ hmr_reg2hw.dmr_enable.req_is_wr;
+ assign hmr_hw2reg.tmr_enable.rd_ack = hmr_reg2hw.tmr_enable.req &&
+ !hmr_reg2hw.tmr_enable.req_is_wr;
+ assign hmr_hw2reg.tmr_enable.wr_ack = hmr_reg2hw.tmr_enable.req &&
+ hmr_reg2hw.tmr_enable.req_is_wr;
+
+ assign hmr_hw2reg.tmr_config.rd_ack = hmr_reg2hw.tmr_config.req &&
+ !hmr_reg2hw.tmr_config.req_is_wr;
+ assign hmr_hw2reg.tmr_config.wr_ack = hmr_reg2hw.tmr_config.req &&
+ hmr_reg2hw.tmr_config.req_is_wr;
+
+ assign hmr_hw2reg.dmr_config.rd_ack = hmr_reg2hw.dmr_config.req &&
+ !hmr_reg2hw.dmr_config.req_is_wr;
+ assign hmr_hw2reg.dmr_config.wr_ack = hmr_reg2hw.dmr_config.req &&
+ hmr_reg2hw.dmr_config.req_is_wr;
// Core Config Registers
- reg_req_t [NumCores-1:0] core_register_reqs;
- reg_rsp_t [NumCores-1:0] core_register_resps;
+ apb_req_t [NumCores-1:0] core_register_reqs;
+ apb_resp_t [NumCores-1:0] core_register_resps;
// 4 words per core
- reg_demux #(
- .NoPorts ( NumCores ),
- .req_t ( reg_req_t ),
- .rsp_t ( reg_rsp_t )
+ apb_demux #(
+ .NoMstPorts ( NumCores ),
+ .req_t ( apb_req_t ),
+ .resp_t ( apb_resp_t )
) i_core_reg_demux (
- .clk_i,
- .rst_ni,
- .in_select_i( top_register_reqs [1].addr[4+$clog2(NumCores)-1:4] ),
- .in_req_i ( top_register_reqs [1] ),
- .in_rsp_o ( top_register_resps[1] ),
- .out_req_o ( core_register_reqs ),
- .out_rsp_i ( core_register_resps )
+ .select_i ( top_register_reqs [1].paddr[4+$clog2(NumCores)-1:4] ),
+ .slv_req_i ( top_register_reqs [1] ),
+ .slv_resp_o ( top_register_resps[1] ),
+ .mst_req_o ( core_register_reqs ),
+ .mst_resp_i ( core_register_resps )
);
- hmr_core_regs_reg_pkg::hmr_core_regs_reg2hw_t [NumCores-1:0] core_config_reg2hw;
- hmr_core_regs_reg_pkg::hmr_core_regs_hw2reg_t [NumCores-1:0] core_config_hw2reg;
+ hmr_core_regs_reg_pkg::hmr_core__out_t core_config_reg2hw [NumCores];
+ hmr_core_regs_reg_pkg::hmr_core__in_t core_config_hw2reg [NumCores];
logic [NumCores-1:0] tmr_incr_mismatches;
logic [NumCores-1:0] dmr_incr_mismatches;
for (genvar i = 0; i < NumCores; i++) begin : gen_core_registers
- hmr_core_regs_reg_top #(
- .reg_req_t(reg_req_t),
- .reg_rsp_t(reg_rsp_t)
- ) icore_registers (
- .clk_i,
- .rst_ni,
- .reg_req_i( core_register_reqs [i] ),
- .reg_rsp_o( core_register_resps[i] ),
- .reg2hw ( core_config_reg2hw [i] ),
- .hw2reg ( core_config_hw2reg [i] ),
- .devmode_i('0)
+ hmr_core_regs_reg_top i_core_registers (
+ .clk (clk_i),
+ .arst_n (rst_ni),
+ .s_apb_psel ( core_register_reqs [i].psel ),
+ .s_apb_penable ( core_register_reqs [i].penable ),
+ .s_apb_pwrite ( core_register_reqs [i].pwrite ),
+ .s_apb_pprot ( core_register_reqs [i].pprot ),
+ .s_apb_paddr ( core_register_reqs [i].paddr[3:0] ),
+ .s_apb_pwdata ( core_register_reqs [i].pwdata ),
+ .s_apb_pstrb ( core_register_reqs [i].pstrb ),
+ .s_apb_pready ( core_register_resps[i].pready ),
+ .s_apb_prdata ( core_register_resps[i].prdata ),
+ .s_apb_pslverr ( core_register_resps[i].pslverr ),
+ .hwif_out ( core_config_reg2hw [i] ),
+ .hwif_in ( core_config_hw2reg [i] )
);
- assign core_config_hw2reg[i].mismatches.d = core_config_reg2hw[i].mismatches.q + 1;
- assign core_config_hw2reg[i].mismatches.de = tmr_incr_mismatches[i] | dmr_incr_mismatches[i];
- assign core_config_hw2reg[i].current_mode.independent.d = core_in_independent[i];
- assign core_config_hw2reg[i].current_mode.dual.d = core_in_dmr[i];
- assign core_config_hw2reg[i].current_mode.triple.d = core_in_tmr[i];
- assign sp_store_is_zero[i] = core_config_reg2hw[i].sp_store.q == '0;
- assign sp_store_will_be_zero[i] = core_config_reg2hw[i].sp_store.qe &&
- core_register_reqs[i].wdata == '0;
+ assign core_config_hw2reg[i].mismatches.mismatches.next =
+ core_config_reg2hw[i].mismatches.mismatches.value + 1;
+ assign core_config_hw2reg[i].mismatches.mismatches.we = tmr_incr_mismatches[i] |
+ dmr_incr_mismatches[i];
+ always_comb begin
+ core_config_hw2reg[i].current_mode.rd_data = '{default: '0};
+ core_config_hw2reg[i].current_mode.rd_data.independent = core_in_independent[i];
+ core_config_hw2reg[i].current_mode.rd_data.dual = core_in_dmr[i];
+ core_config_hw2reg[i].current_mode.rd_data.triple = core_in_tmr[i];
+ core_config_hw2reg[i].current_mode.rd_ack = core_config_reg2hw[i].current_mode.req &&
+ !core_config_reg2hw[i].current_mode.req_is_wr;
+ end
+ assign sp_store_is_zero[i] = core_config_reg2hw[i].sp_store.sp_store.value == '0;
+ assign sp_store_will_be_zero[i] = core_config_reg2hw[i].sp_store.sp_store.swmod &&
+ core_register_reqs[i].pwdata == '0;
end
/**********************************************************
@@ -363,8 +400,8 @@ module hmr_unit #(
if (TMRSupported || TMRFixed) begin : gen_tmr_logic
if (TMRFixed && NumCores % 3 != 0) $warning("Extra cores added not properly handled!");
- reg_req_t [NumTMRGroups-1:0] tmr_register_reqs;
- reg_rsp_t [NumTMRGroups-1:0] tmr_register_resps;
+ apb_req_t [NumTMRGroups-1:0] tmr_register_reqs;
+ apb_resp_t [NumTMRGroups-1:0] tmr_register_resps;
logic [NumTMRGroups-1:0] tmr_sw_resynch_req, tmr_sw_synch_req;
localparam int unsigned TMRSelWidth = $clog2(NumTMRGroups);
@@ -376,18 +413,16 @@ module hmr_unit #(
assign tmr_register_reqs[0] = top_register_reqs[3];
assign top_register_resps[3] = tmr_register_resps[0];
end else begin : gen_multi_tmr_group_reg_connect
- reg_demux #(
- .NoPorts ( NumTMRGroups ),
- .req_t ( reg_req_t ),
- .rsp_t ( reg_rsp_t )
+ apb_demux #(
+ .NoMstPorts ( NumTMRGroups ),
+ .req_t ( apb_req_t ),
+ .resp_t ( apb_resp_t )
) i_reg_demux (
- .clk_i,
- .rst_ni,
- .in_select_i( top_register_reqs[3].addr[4+$clog2(NumTMRGroups)-1:4] ),
- .in_req_i ( top_register_reqs[3] ),
- .in_rsp_o ( top_register_resps[3] ),
- .out_req_o ( tmr_register_reqs ),
- .out_rsp_i ( tmr_register_resps )
+ .select_i ( top_register_reqs[3].paddr[4+$clog2(NumTMRGroups)-1:4] ),
+ .slv_req_i ( top_register_reqs[3] ),
+ .slv_resp_o ( top_register_resps[3] ),
+ .mst_req_o ( tmr_register_reqs ),
+ .mst_resp_i ( tmr_register_resps )
);
end
@@ -400,8 +435,8 @@ module hmr_unit #(
for (genvar i = 0; i < NumTMRGroups; i++) begin : gen_tmr_groups
hmr_tmr_ctrl #(
- .reg_req_t ( reg_req_t ),
- .reg_resp_t ( reg_rsp_t ),
+ .apb_req_t ( apb_req_t ),
+ .apb_resp_t ( apb_resp_t ),
.TMRFixed ( TMRFixed ),
.InterleaveGrps ( InterleaveGrps ),
.DefaultInTMR ( 1'b0 ),
@@ -410,21 +445,33 @@ module hmr_unit #(
.clk_i,
.rst_ni,
- .reg_req_i ( tmr_register_reqs[i] ),
- .reg_resp_o ( tmr_register_resps[i] ),
-
- .tmr_enable_q_i ( hmr_reg2hw.tmr_enable.q[i] ),
- .tmr_enable_qe_i ( hmr_reg2hw.tmr_enable.qe ),
- .delay_resynch_q_i ( hmr_reg2hw.tmr_config.delay_resynch.q ),
- .delay_resynch_qe_i ( hmr_reg2hw.tmr_config.delay_resynch.qe ),
- .setback_q_i ( hmr_reg2hw.tmr_config.setback.q ),
- .setback_qe_i ( hmr_reg2hw.tmr_config.setback.qe ),
- .reload_setback_q_i ( hmr_reg2hw.tmr_config.reload_setback.q ),
- .reload_setback_qe_i ( hmr_reg2hw.tmr_config.reload_setback.qe ),
- .rapid_recovery_q_i ( hmr_reg2hw.tmr_config.rapid_recovery.q ),
- .rapid_recovery_qe_i ( hmr_reg2hw.tmr_config.rapid_recovery.qe ),
- .force_resynch_q_i ( hmr_reg2hw.tmr_config.force_resynch.q ),
- .force_resynch_qe_i ( hmr_reg2hw.tmr_config.force_resynch.qe ),
+ .apb_req_i ( tmr_register_reqs[i] ),
+ .apb_resp_o ( tmr_register_resps[i] ),
+
+ .tmr_enable_q_i ( hmr_reg2hw.tmr_enable.wr_data.tmr_enable[i] ),
+ .tmr_enable_qe_i ( hmr_reg2hw.tmr_enable.req &
+ hmr_reg2hw.tmr_enable.req_is_wr &
+ hmr_reg2hw.tmr_enable.wr_data.tmr_enable[i] ),
+ .delay_resynch_q_i ( hmr_reg2hw.tmr_config.wr_data.delay_resynch ),
+ .delay_resynch_qe_i ( hmr_reg2hw.tmr_config.req &
+ hmr_reg2hw.tmr_config.req_is_wr &
+ hmr_reg2hw.tmr_config.wr_data.delay_resynch ),
+ .setback_q_i ( hmr_reg2hw.tmr_config.wr_data.setback ),
+ .setback_qe_i ( hmr_reg2hw.tmr_config.req &
+ hmr_reg2hw.tmr_config.req_is_wr &
+ hmr_reg2hw.tmr_config.wr_data.setback ),
+ .reload_setback_q_i ( hmr_reg2hw.tmr_config.wr_data.reload_setback ),
+ .reload_setback_qe_i ( hmr_reg2hw.tmr_config.req &
+ hmr_reg2hw.tmr_config.req_is_wr &
+ hmr_reg2hw.tmr_config.wr_data.reload_setback ),
+ .rapid_recovery_q_i ( hmr_reg2hw.tmr_config.wr_data.rapid_recovery ),
+ .rapid_recovery_qe_i ( hmr_reg2hw.tmr_config.req &
+ hmr_reg2hw.tmr_config.req_is_wr &
+ hmr_reg2hw.tmr_config.wr_data.rapid_recovery ),
+ .force_resynch_q_i ( hmr_reg2hw.tmr_config.wr_data.force_resynch ),
+ .force_resynch_qe_i ( hmr_reg2hw.tmr_config.req &
+ hmr_reg2hw.tmr_config.req_is_wr &
+ hmr_reg2hw.tmr_config.wr_data.force_resynch ),
.setback_o ( tmr_setback_q[i] ),
.sw_resynch_req_o ( tmr_sw_resynch_req[i] ),
@@ -508,9 +555,13 @@ module hmr_unit #(
assign tmr_failure = '0;
assign tmr_nominal_outputs = DefaultNominalOutputs;
assign tmr_bus_outputs = DefaultBusOutputs;
- assign top_register_resps[3].rdata = '0;
- assign top_register_resps[3].error = 1'b1;
- assign top_register_resps[3].ready = 1'b1;
+ apb_err_slv #(
+ .req_t ( apb_req_t ),
+ .resp_t( apb_resp_t )
+ ) i_apb_err_slv (
+ .apb_req_i ( top_register_reqs[3] ),
+ .apb_resp_o ( top_register_resps[3] )
+ );
assign tmr_incr_mismatches = '0;
assign tmr_grp_in_independent = '1;
assign tmr_setback_q = '0;
@@ -524,11 +575,8 @@ module hmr_unit #(
if (DMRSupported || DMRFixed) begin: gen_dmr_logic
- hmr_dmr_regs_reg_pkg::hmr_dmr_regs_reg2hw_t [NumDMRGroups-1:0] dmr_reg2hw;
- hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t [NumDMRGroups-1:0] dmr_hw2reg;
-
- reg_req_t [NumDMRGroups-1:0] dmr_register_reqs;
- reg_rsp_t [NumDMRGroups-1:0] dmr_register_resps;
+ apb_req_t [NumDMRGroups-1:0] dmr_register_reqs;
+ apb_resp_t [NumDMRGroups-1:0] dmr_register_resps;
logic [NumDMRGroups-1:0] dmr_sw_synch_req;
logic [NumDMRGroups-1:0] dmr_sw_resynch_req;
@@ -541,18 +589,16 @@ module hmr_unit #(
assign dmr_register_reqs[0] = top_register_reqs[2];
assign top_register_resps[2] = dmr_register_resps[0];
end else begin : gen_multi_dmr_group_reg_connect
- reg_demux #(
- .NoPorts ( NumDMRGroups ),
- .req_t ( reg_req_t ),
- .rsp_t ( reg_rsp_t )
+ apb_demux #(
+ .NoMstPorts ( NumDMRGroups ),
+ .req_t ( apb_req_t ),
+ .resp_t ( apb_resp_t )
) i_reg_demux (
- .clk_i,
- .rst_ni,
- .in_select_i( top_register_reqs[2].addr[4+$clog2(NumDMRGroups)-1:4] ),
- .in_req_i ( top_register_reqs[2] ),
- .in_rsp_o ( top_register_resps[2] ),
- .out_req_o ( dmr_register_reqs ),
- .out_rsp_i ( dmr_register_resps )
+ .select_i ( top_register_reqs[2].paddr[4+$clog2(NumDMRGroups)-1:4] ),
+ .slv_req_i ( top_register_reqs[2] ),
+ .slv_resp_o ( top_register_resps[2] ),
+ .mst_req_o ( dmr_register_reqs ),
+ .mst_resp_i ( dmr_register_resps )
);
end
@@ -565,8 +611,8 @@ module hmr_unit #(
for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_dmr_groups
hmr_dmr_ctrl #(
- .reg_req_t ( reg_req_t ),
- .reg_resp_t ( reg_rsp_t ),
+ .apb_req_t ( apb_req_t ),
+ .apb_resp_t ( apb_resp_t ),
.DataWidth ( SysDataWidth ),
.InterleaveGrps( InterleaveGrps ),
.DMRFixed ( DMRFixed ),
@@ -576,15 +622,21 @@ module hmr_unit #(
.clk_i,
.rst_ni,
- .reg_req_i ( dmr_register_reqs [i] ),
- .reg_resp_o ( dmr_register_resps[i] ),
-
- .dmr_enable_q_i ( hmr_reg2hw.dmr_enable.q[i] ),
- .dmr_enable_qe_i ( hmr_reg2hw.dmr_enable.qe ),
- .rapid_recovery_q_i ( hmr_reg2hw.dmr_config.rapid_recovery.q ),
- .rapid_recovery_qe_i ( hmr_reg2hw.dmr_config.rapid_recovery.qe ),
- .force_recovery_q_i ( hmr_reg2hw.dmr_config.force_recovery.q ),
- .force_recovery_qe_i ( hmr_reg2hw.dmr_config.force_recovery.qe ),
+ .apb_req_i ( dmr_register_reqs [i] ),
+ .apb_resp_o ( dmr_register_resps[i] ),
+
+ .dmr_enable_q_i ( hmr_reg2hw.dmr_enable.wr_data.dmr_enable[i] ),
+ .dmr_enable_qe_i ( hmr_reg2hw.dmr_enable.req &
+ hmr_reg2hw.dmr_enable.req_is_wr &
+ hmr_reg2hw.dmr_enable.wr_biten.dmr_enable[i] ),
+ .rapid_recovery_q_i ( hmr_reg2hw.dmr_config.wr_data.rapid_recovery ),
+ .rapid_recovery_qe_i ( hmr_reg2hw.dmr_config.req &
+ hmr_reg2hw.dmr_config.req_is_wr &
+ hmr_reg2hw.dmr_config.wr_biten.rapid_recovery ),
+ .force_recovery_q_i ( hmr_reg2hw.dmr_config.wr_data.force_recovery ),
+ .force_recovery_qe_i ( hmr_reg2hw.dmr_config.req &
+ hmr_reg2hw.dmr_config.req_is_wr &
+ hmr_reg2hw.dmr_config.wr_biten.force_recovery ),
.setback_o ( dmr_setback_q [i] ),
.sw_resynch_req_o ( dmr_sw_resynch_req [i] ),
@@ -715,9 +767,13 @@ module hmr_unit #(
assign dmr_incr_mismatches = '0;
assign dmr_nominal_outputs = DefaultNominalOutputs;
assign dmr_bus_outputs = DefaultBusOutputs;
- assign top_register_resps[2].rdata = '0;
- assign top_register_resps[2].error = 1'b1;
- assign top_register_resps[2].ready = 1'b1;
+ apb_err_slv #(
+ .req_t ( apb_req_t ),
+ .resp_t( apb_resp_t )
+ ) i_dmr_err_slv (
+ .slv_req_i ( top_register_reqs[2] ),
+ .slv_resp_o( top_register_resps[2] )
+ );
assign dmr_sw_synch_req_o = '0;
assign dmr_resynch_req_o = '0;
assign dmr_grp_in_independent = '1;
diff --git a/rtl/HMR/hmr_v1.h b/rtl/HMR/hmr_v1.h
deleted file mode 100644
index 7a4e0bfa..00000000
--- a/rtl/HMR/hmr_v1.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2023 ETH Zurich and University of Bologna
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __ARCHI_HMR_HMR_V1_H__
-#define __ARCHI_HMR_HMR_V1_H__
-
-#define HMR_IN_INTERLEAVED 1
-
-#define HMR_TOP_OFFSET 0x000
-#define HMR_CORE_OFFSET 0x100
-#define HMR_DMR_OFFSET 0x200
-#define HMR_TMR_OFFSET 0x300
-
-#define HMR_CORE_INCREMENT 0x010
-#define HMR_CORE_SLL 0x004
-#define HMR_DMR_INCREMENT 0x010
-#define HMR_DMR_SLL 0x004
-#define HMR_TMR_INCREMENT 0x010
-#define HMR_TMR_SLL 0x004
-
-// Generated register defines for HMR_registers
-
-#ifndef _HMR_REGISTERS_REG_DEFS_
-#define _HMR_REGISTERS_REG_DEFS_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#define HMR_REGISTERS_PARAM_NUM_CORES 12
-
-#define HMR_REGISTERS_PARAM_NUM_D_M_R_GROUPS 6
-
-#define HMR_REGISTERS_PARAM_NUM_T_M_R_GROUPS 4
-
-// Register width
-#define HMR_REGISTERS_PARAM_REG_WIDTH 32
-
-// Available Configurations from implemented hardware.
-#define HMR_REGISTERS_AVAIL_CONFIG_REG_OFFSET 0x0
-#define HMR_REGISTERS_AVAIL_CONFIG_INDEPENDENT_BIT 0
-#define HMR_REGISTERS_AVAIL_CONFIG_DUAL_BIT 1
-#define HMR_REGISTERS_AVAIL_CONFIG_TRIPLE_BIT 2
-#define HMR_REGISTERS_AVAIL_CONFIG_RAPID_RECOVERY_BIT 8
-
-// Enabled cores, based on the configuration. Can be used for barriers.
-#define HMR_REGISTERS_CORES_EN_REG_OFFSET 0x4
-#define HMR_REGISTERS_CORES_EN_CORES_EN_MASK 0xfff
-#define HMR_REGISTERS_CORES_EN_CORES_EN_OFFSET 0
-#define HMR_REGISTERS_CORES_EN_CORES_EN_FIELD \
- ((bitfield_field32_t) { .mask = HMR_REGISTERS_CORES_EN_CORES_EN_MASK, .index = HMR_REGISTERS_CORES_EN_CORES_EN_OFFSET })
-
-// DMR configuration enable, on bit per DMR group.
-#define HMR_REGISTERS_DMR_ENABLE_REG_OFFSET 0x8
-#define HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_MASK 0x3f
-#define HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_OFFSET 0
-#define HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_FIELD \
- ((bitfield_field32_t) { .mask = HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_MASK, .index = HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_OFFSET })
-
-// TMR configuration enable, one bit per TMR group.
-#define HMR_REGISTERS_TMR_ENABLE_REG_OFFSET 0xc
-#define HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_MASK 0xf
-#define HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_OFFSET 0
-#define HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_FIELD \
- ((bitfield_field32_t) { .mask = HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_MASK, .index = HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_OFFSET })
-
-// DMR configuration bits.
-#define HMR_REGISTERS_DMR_CONFIG_REG_OFFSET 0x10
-#define HMR_REGISTERS_DMR_CONFIG_RAPID_RECOVERY_BIT 0
-#define HMR_REGISTERS_DMR_CONFIG_FORCE_RECOVERY_BIT 1
-
-// TMR configuration bits.
-#define HMR_REGISTERS_TMR_CONFIG_REG_OFFSET 0x14
-#define HMR_REGISTERS_TMR_CONFIG_DELAY_RESYNCH_BIT 0
-#define HMR_REGISTERS_TMR_CONFIG_SETBACK_BIT 1
-#define HMR_REGISTERS_TMR_CONFIG_RELOAD_SETBACK_BIT 2
-#define HMR_REGISTERS_TMR_CONFIG_RAPID_RECOVERY_BIT 3
-#define HMR_REGISTERS_TMR_CONFIG_FORCE_RESYNCH_BIT 4
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-#endif // _HMR_REGISTERS_REG_DEFS_
-// End generated register defines for HMR_registers
-
-// Generated register defines for HMR_core_regs
-
-#ifndef _HMR_CORE_REGS_REG_DEFS_
-#define _HMR_CORE_REGS_REG_DEFS_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-// Register width
-#define HMR_CORE_REGS_PARAM_REG_WIDTH 32
-
-// Value to determine wich redundancy mode the core with that ID is in.
-#define HMR_CORE_REGS_CURRENT_MODE_REG_OFFSET 0x0
-#define HMR_CORE_REGS_CURRENT_MODE_INDEPENDENT_BIT 0
-#define HMR_CORE_REGS_CURRENT_MODE_DUAL_BIT 1
-#define HMR_CORE_REGS_CURRENT_MODE_TRIPLE_BIT 2
-
-// Mismatches of the core
-#define HMR_CORE_REGS_MISMATCHES_REG_OFFSET 0x4
-
-// Stack Pointer storage register
-#define HMR_CORE_REGS_SP_STORE_REG_OFFSET 0x8
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-#endif // _HMR_CORE_REGS_REG_DEFS_
-// End generated register defines for HMR_core_regs
-
-// Generated register defines for HMR_dmr_regs
-
-#ifndef _HMR_DMR_REGS_REG_DEFS_
-#define _HMR_DMR_REGS_REG_DEFS_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-// Register width
-#define HMR_DMR_REGS_PARAM_REG_WIDTH 32
-
-// DMR configuration enable.
-#define HMR_DMR_REGS_DMR_ENABLE_REG_OFFSET 0x0
-#define HMR_DMR_REGS_DMR_ENABLE_DMR_ENABLE_BIT 0
-
-// DMR configuration bits.
-#define HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET 0x4
-#define HMR_DMR_REGS_DMR_CONFIG_RAPID_RECOVERY_BIT 0
-#define HMR_DMR_REGS_DMR_CONFIG_FORCE_RECOVERY_BIT 1
-
-// Address for the last checkpoint.
-#define HMR_DMR_REGS_CHECKPOINT_ADDR_REG_OFFSET 0x8
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-#endif // _HMR_DMR_REGS_REG_DEFS_
-// End generated register defines for HMR_dmr_regs
-
-// Generated register defines for HMR_tmr_regs
-
-#ifndef _HMR_TMR_REGS_REG_DEFS_
-#define _HMR_TMR_REGS_REG_DEFS_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-// Register width
-#define HMR_TMR_REGS_PARAM_REG_WIDTH 32
-
-// TMR configuration enable.
-#define HMR_TMR_REGS_TMR_ENABLE_REG_OFFSET 0x0
-#define HMR_TMR_REGS_TMR_ENABLE_TMR_ENABLE_BIT 0
-
-// TMR configuration bits.
-#define HMR_TMR_REGS_TMR_CONFIG_REG_OFFSET 0x4
-#define HMR_TMR_REGS_TMR_CONFIG_DELAY_RESYNCH_BIT 0
-#define HMR_TMR_REGS_TMR_CONFIG_SETBACK_BIT 1
-#define HMR_TMR_REGS_TMR_CONFIG_RELOAD_SETBACK_BIT 2
-#define HMR_TMR_REGS_TMR_CONFIG_RAPID_RECOVERY_BIT 3
-#define HMR_TMR_REGS_TMR_CONFIG_FORCE_RESYNCH_BIT 4
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-#endif // _HMR_TMR_REGS_REG_DEFS_
-// End generated register defines for HMR_tmr_regs
-
-
-#endif // __ARCHI_HMR_HMR_V1_H__