[ibex] Add simple address translation scheme

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/rv_core_ibex/rtl/rv_core_addr_trans.sv b/hw/ip/rv_core_ibex/rtl/rv_core_addr_trans.sv
new file mode 100644
index 0000000..bc3da04
--- /dev/null
+++ b/hw/ip/rv_core_ibex/rtl/rv_core_addr_trans.sv
@@ -0,0 +1,85 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+/**
+ * Simple address translation for rv_core_ibex
+ * This performs a configurable address translation, please see
+ * https://docs.google.com/document/d/1uU2Zh46SJtoaOqZ9dCRO7oAQnhTUcWWZ7CstOa1PZiM/edit?usp=sharing
+ */
+
+module rv_core_addr_trans import rv_core_ibex_peri_pkg::*; #(
+  parameter int AddrWidth = 32,
+  parameter int NumRegions = 2
+) (
+  input clk_i,
+  input rst_ni,
+  input region_cfg_t [NumRegions-1:0] region_cfg_i,
+  input [AddrWidth-1:0] addr_i,
+  output logic [AddrWidth-1:0] addr_o
+);
+
+  typedef struct packed {
+    logic [AddrWidth-1:0] output_mask;
+    logic [AddrWidth-1:0] remap_addr;
+  } region_ctrls_t;
+
+  region_ctrls_t region_ctrls [NumRegions] ;
+  logic [NumRegions-1:0][AddrWidth-1:0] input_masks;
+
+  // Mask generation is based on the matching region configuration
+  // Since matching is done on a power-of-2 alignment, the mechanism is similar
+  // to RISC-V pmp's power-of-2 usage.
+  // As an example:
+  // If a matching region is programmed as 0x8007_FFFF,
+  // The matching input mask is 0xFFF0_0000
+  // The output mask is simply inverted 0x000F_FFFF
+  for (genvar i = 0; i < NumRegions; i++) begin : gen_region_ctrls
+    assign input_masks[i][0] = 1'b0;
+
+    for (genvar j = 1; j < AddrWidth; j++) begin : gen_addr_masks_lower_bits
+      assign input_masks[i][j] = ~&region_cfg_i[i].matching_region[j-1:0];
+    end
+
+    // pack things into region controls
+    assign region_ctrls[i].output_mask = ~input_masks[i];
+    assign region_ctrls[i].remap_addr = region_cfg_i[i].remap_addr;
+  end
+
+  logic [NumRegions-1:0] all_matches;
+  for (genvar i = 0; i < NumRegions; i++) begin : gen_region_matches
+    assign all_matches[i] = region_cfg_i[i].en &
+                            ((region_cfg_i[i].matching_region & input_masks[i]) ==
+                            (addr_i & input_masks[i]));
+  end
+
+  logic sel_match;
+  region_ctrls_t sel_region;
+  prim_arbiter_fixed #(
+    .N(NumRegions),
+    .DW($bits(region_ctrls_t)),
+    .EnDataPort(1)
+  ) u_sel_region (
+    .clk_i,
+    .rst_ni,
+    .req_i(all_matches),
+    .data_i(region_ctrls),
+    .gnt_o(),
+    .idx_o(),
+    .valid_o(sel_match),
+    .data_o(sel_region),
+    .ready_i(1'b1)
+  );
+
+  // if there is a match, mask off the address bits and remap
+  // if there is no match, just use incoming address
+  assign addr_o = sel_match ? addr_i & sel_region.output_mask | sel_region.remap_addr :
+                              addr_i;
+
+  // unused clock/reset, only needed for assertions
+  logic unused_clk;
+  logic unused_rst_n;
+  assign unused_clk = clk_i;
+  assign unused_rst_n = rst_ni;
+
+endmodule // rv_core_addr_trans
diff --git a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
index 1e466ec..527396e 100644
--- a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
+++ b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
@@ -8,7 +8,10 @@
  * 32 bit RISC-V core supporting the RV32I + optionally EMC instruction sets.
  * Instruction and data bus are 32 bit wide TileLink-UL (TL-UL).
  */
-module rv_core_ibex import rv_core_ibex_peri_pkg::*; #(
+module rv_core_ibex
+  import rv_core_ibex_peri_pkg::*;
+  import rv_core_ibex_peri_reg_pkg::*;
+#(
   parameter bit                 PMPEnable         = 1'b0,
   parameter int unsigned        PMPGranularity    = 0,
   parameter int unsigned        PMPNumRegions     = 4,
@@ -76,7 +79,11 @@
   // alert events to peripheral module
   output alert_event_t fatal_intg_event_o,
   output alert_event_t fatal_core_event_o,
-  output alert_event_t recov_core_event_o
+  output alert_event_t recov_core_event_o,
+
+  // configurations for address translation
+  input region_cfg_t [NumRegions-1:0] ibus_region_cfg_i,
+  input region_cfg_t [NumRegions-1:0] dbus_region_cfg_i
 );
 
   import top_pkg::*;
@@ -287,6 +294,18 @@
   //
   // Convert ibex data/instruction bus to TL-UL
   //
+  logic [31:0] instr_addr_trans;
+  rv_core_addr_trans #(
+    .AddrWidth(32),
+    .NumRegions(NumRegions)
+  ) u_ibus_trans (
+    .clk_i,
+    .rst_ni,
+    .region_cfg_i(ibus_region_cfg_i),
+    .addr_i(instr_addr),
+    .addr_o(instr_addr_trans)
+  );
+
   tlul_adapter_host #(
     .MAX_REQS(NumOutstandingReqs)
   ) tl_adapter_host_i_ibex (
@@ -295,7 +314,7 @@
     .req_i      (instr_req),
     .type_i     (tlul_pkg::InstrType),
     .gnt_o      (instr_gnt),
-    .addr_i     (instr_addr),
+    .addr_i     (instr_addr_trans),
     .we_i       (1'b0),
     .wdata_i    (32'b0),
     .be_i       (4'hF),
@@ -324,6 +343,18 @@
     .spare_rsp_i (1'b0),
     .spare_rsp_o ());
 
+  logic [31:0] data_addr_trans;
+  rv_core_addr_trans #(
+    .AddrWidth(32),
+    .NumRegions(NumRegions)
+  ) u_dbus_trans (
+    .clk_i,
+    .rst_ni,
+    .region_cfg_i(dbus_region_cfg_i),
+    .addr_i(data_addr),
+    .addr_o(data_addr_trans)
+  );
+
   tlul_adapter_host #(
     .MAX_REQS(2)
   ) tl_adapter_host_d_ibex (
@@ -332,7 +363,7 @@
     .req_i      (data_req),
     .type_i     (tlul_pkg::DataType),
     .gnt_o      (data_gnt),
-    .addr_i     (data_addr),
+    .addr_i     (data_addr_trans),
     .we_i       (data_we),
     .wdata_i    (data_wdata),
     .be_i       (data_be),
diff --git a/hw/ip/rv_core_ibex/rv_core_ibex.core b/hw/ip/rv_core_ibex/rv_core_ibex.core
index 457e802..2caa131 100644
--- a/hw/ip/rv_core_ibex/rv_core_ibex.core
+++ b/hw/ip/rv_core_ibex/rv_core_ibex.core
@@ -16,9 +16,10 @@
       - lowrisc:ip:lc_ctrl_pkg
       - lowrisc:prim:lc_sync
       - lowrisc:ip:alert_handler_reg
-      - lowrisc:ip:rv_core_ibex_peri_pkg
+      - lowrisc:ip:rv_core_ibex_peri
     files:
       - rtl/rv_core_ibex.sv
+      - rtl/rv_core_addr_trans.sv
     file_type: systemVerilogSource
 
   files_verilator_waiver:
diff --git a/hw/ip/rv_core_ibex_peri/data/rv_core_ibex_peri.hjson b/hw/ip/rv_core_ibex_peri/data/rv_core_ibex_peri.hjson
index 3d65efa..4c5d0e2 100644
--- a/hw/ip/rv_core_ibex_peri/data/rv_core_ibex_peri.hjson
+++ b/hw/ip/rv_core_ibex_peri/data/rv_core_ibex_peri.hjson
@@ -47,6 +47,20 @@
       package: "rv_core_ibex_peri_pkg",
     },
 
+    { struct:  "region_cfg",
+      type:    "uni",
+      name:    "ibus_region_cfg",
+      act:     "req",
+      package: "rv_core_ibex_peri_pkg",
+    },
+
+    { struct:  "region_cfg",
+      type:    "uni",
+      name:    "dbus_region_cfg",
+      act:     "req",
+      package: "rv_core_ibex_peri_pkg",
+    },
+
   ],
   param_list: [
     { name: "NumSwAlerts",
@@ -55,6 +69,13 @@
       default: "2",
       local: "true"
     },
+
+    { name: "NumRegions",
+      desc: "Number of translatable regions per ibex bus",
+      type: "int",
+      default: "2",
+      local: "true"
+    },
   ],
 
   regwidth: "32",
@@ -117,6 +138,230 @@
       },
     },
 
+    { multireg: {
+        cname: "IBUS_REGWEN",
+        name: "IBUS_REGWEN",
+        desc: "Ibus address control regwen.",
+        count: "NumRegions",
+        swaccess: "rw0c",
+        hwaccess: "none",
+        compact: false,
+        fields: [
+          { bits: "0",
+            name: "EN",
+            resval: "1",
+            desc: "Ibus address controls write enable.  Once set to 0, it can longer be configured to 1",
+            enum: [
+              { value: "0",
+                name: "locked",
+                desc: '''
+                        Address controls can no longer be configured until next reset.
+                        '''
+              },
+              { value: "1",
+                name: "enabled",
+                desc: '''
+                        Address controls can still be configured.
+                        '''
+              },
+            ]
+          },
+        ],
+      },
+    },
+
+    { multireg: {
+        cname: "IBUS_ADDR_CFG",
+        name: "IBUS_ADDR_EN",
+        regwen: "IBUS_REGWEN",
+        regwen_multi: true,
+        desc: '''
+          Enable Ibus address matching
+        ''',
+        count: "NumRegions",
+        compact: false,
+        swaccess: "rw",
+        hwaccess: "hro",
+        fields: [
+          { bits: "0",
+            name: "EN",
+            desc: '''
+              Enable ibus address matching.
+            ''',
+            resval: "0"
+          },
+        ],
+      },
+    },
+
+    { multireg: {
+        cname: "IBUS_ADDR_MATCHING",
+        name: "IBUS_ADDR_MATCHING",
+        regwen: "IBUS_REGWEN",
+        regwen_multi: true,
+        desc: '''
+          Matching region programming for ibus.
+
+          The value programmed is done at power-of-2 alignment.
+          For example, if the intended matching region is 0x8000_0000 to 0x8000_FFFF, the value programmed is 0x8000_7FFF.
+
+          The value programmed can be determined from the translation granule.
+          Assume the user wishes to translate a specific 64KB block to a different address.
+          64KB has a hex value of 0x10000.
+          Subtract 1 from this value and then right shift by one to obtain 0x7FFF.
+          This value OR'd with the upper matching address bits that select which 64KB block to translate would then be programmed.
+
+          Given a value of 0x8000_7FFF, it specifies that the 0x8000-th 64KB block is the translation target.
+        ''',
+        count: "NumRegions",
+        compact: false,
+        swaccess: "rw",
+        hwaccess: "hro",
+        fields: [
+          { bits: "31:0",
+            name: "VAL",
+            desc: '''
+              Matching region value
+            ''',
+            resval: "0"
+          },
+        ],
+      },
+    },
+
+    { multireg: {
+        cname: "IBUS_REMAP_ADDR",
+        name: "IBUS_REMAP_ADDR",
+        regwen: "IBUS_REGWEN",
+        regwen_multi: true,
+        desc: '''
+          The remap address after a match has been made.
+          The remap bits apply only to top portion of address bits not covered by the matching region.
+
+          For example, if the translation region is 64KB, the remapped address applies only to the upper
+          address bits that select which 64KB to be translated.
+        ''',
+        count: "NumRegions",
+        compact: false,
+        swaccess: "rw",
+        hwaccess: "hro",
+        fields: [
+          { bits: "31:0",
+            name: "VAL",
+            desc: '''
+              Remap addr value
+            ''',
+            resval: "0"
+          },
+        ],
+      },
+    },
+
+    { multireg: {
+        cname: "DBUS_REGWEN",
+        name: "DBUS_REGWEN",
+        desc: "Dbus address control regwen.",
+        count: "NumRegions",
+        swaccess: "rw0c",
+        hwaccess: "none",
+        compact: false,
+        fields: [
+          { bits: "0",
+            name: "EN",
+            resval: "1",
+            desc: "Ibus address controls write enable.  Once set to 0, it can longer be configured to 1",
+            enum: [
+              { value: "0",
+                name: "locked",
+                desc: '''
+                        Address controls can no longer be configured until next reset.
+                        '''
+              },
+              { value: "1",
+                name: "enabled",
+                desc: '''
+                        Address controls can still be configured.
+                        '''
+              },
+            ]
+          },
+        ],
+      },
+    },
+
+    { multireg: {
+        cname: "DBUS_ADDR_CFG",
+        name: "DBUS_ADDR_EN",
+        regwen: "DBUS_REGWEN",
+        regwen_multi: true,
+        desc: '''
+          Enable dbus address matching
+        ''',
+        count: "NumRegions",
+        compact: false,
+        swaccess: "rw",
+        hwaccess: "hro",
+        fields: [
+          { bits: "0",
+            name: "EN",
+            desc: '''
+              Enable dbus address matching.
+            ''',
+            resval: "0"
+          },
+        ],
+      },
+    },
+
+    { multireg: {
+        cname: "DBUS_ADDR_MATCHING",
+        name: "DBUS_ADDR_MATCHING",
+        regwen: "DBUS_REGWEN",
+        regwen_multi: true,
+        desc: '''
+          See !!IBUS_ADDR_MATCHING for detailed description.
+          ''',
+        count: "NumRegions",
+        compact: false,
+        swaccess: "rw",
+        hwaccess: "hro",
+        fields: [
+          { bits: "31:0",
+            name: "VAL",
+            desc: '''
+              Matching region value
+            ''',
+            resval: "0"
+          },
+        ],
+      },
+    },
+
+    { multireg: {
+        cname: "DBUS_REMAP_ADDR",
+        name: "DBUS_REMAP_ADDR",
+        regwen: "DBUS_REGWEN",
+        regwen_multi: true,
+        desc: '''
+          See !!IBUS_REMAP_ADDR for a detailed description.
+        ''',
+        count: "NumRegions",
+        compact: false,
+        swaccess: "rw",
+        hwaccess: "hro",
+        fields: [
+          { bits: "31:0",
+            name: "VAL",
+            desc: '''
+              Remap addr value
+            ''',
+            resval: "0"
+          },
+        ],
+      },
+    },
+
+
     { name: "ERR_STATUS",
       desc: "error status",
       swaccess: "rw1c",
diff --git a/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri.sv b/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri.sv
index ef3ed01..0dae343 100644
--- a/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri.sv
+++ b/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri.sv
@@ -25,6 +25,10 @@
   input alert_event_t fatal_core_event_i,
   input alert_event_t recov_core_event_i,
 
+  // region configuration to ibex
+  output region_cfg_t [NumRegions-1:0] ibus_region_cfg_o,
+  output region_cfg_t [NumRegions-1:0] dbus_region_cfg_o,
+
   // interrupts and alerts
   input  prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i,
   output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o
@@ -47,6 +51,22 @@
   );
 
   ///////////////////////
+  // Region assignments
+  ///////////////////////
+
+  for(genvar i = 0; i < NumRegions; i++) begin : gen_ibus_region_cfgs
+    assign ibus_region_cfg_o[i].en = reg2hw.ibus_addr_en[i];
+    assign ibus_region_cfg_o[i].matching_region = reg2hw.ibus_addr_matching[i];
+    assign ibus_region_cfg_o[i].remap_addr = reg2hw.ibus_remap_addr[i];
+  end
+
+  for(genvar i = 0; i < NumRegions; i++) begin : gen_dbus_region_cfgs
+    assign dbus_region_cfg_o[i].en = reg2hw.dbus_addr_en[i];
+    assign dbus_region_cfg_o[i].matching_region = reg2hw.dbus_addr_matching[i];
+    assign dbus_region_cfg_o[i].remap_addr = reg2hw.dbus_remap_addr[i];
+  end
+
+  ///////////////////////
   // Error assignment
   ///////////////////////
   logic fatal_intg_err, fatal_core_err, recov_core_err;
diff --git a/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_pkg.sv b/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_pkg.sv
index 9608955..aab7be1 100644
--- a/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_pkg.sv
+++ b/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_pkg.sv
@@ -14,4 +14,10 @@
 
   typedef alert_event_e alert_event_t;
 
+  typedef struct packed {
+    logic en;
+    logic [31:0] matching_region;
+    logic [31:0] remap_addr;
+  } region_cfg_t;
+
 endpackage // rv_core_ibex_peri_pkg
diff --git a/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_reg_pkg.sv b/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_reg_pkg.sv
index 4ff7533..356a79f 100644
--- a/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_reg_pkg.sv
+++ b/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_reg_pkg.sv
@@ -8,10 +8,11 @@
 
   // Param list
   parameter int NumSwAlerts = 2;
+  parameter int NumRegions = 2;
   parameter int NumAlerts = 4;
 
   // Address widths within the block
-  parameter int BlockAw = 5;
+  parameter int BlockAw = 7;
 
   ////////////////////////////
   // Typedefs for registers //
@@ -41,6 +42,30 @@
   } rv_core_ibex_peri_reg2hw_sw_alert_mreg_t;
 
   typedef struct packed {
+    logic        q;
+  } rv_core_ibex_peri_reg2hw_ibus_addr_en_mreg_t;
+
+  typedef struct packed {
+    logic [31:0] q;
+  } rv_core_ibex_peri_reg2hw_ibus_addr_matching_mreg_t;
+
+  typedef struct packed {
+    logic [31:0] q;
+  } rv_core_ibex_peri_reg2hw_ibus_remap_addr_mreg_t;
+
+  typedef struct packed {
+    logic        q;
+  } rv_core_ibex_peri_reg2hw_dbus_addr_en_mreg_t;
+
+  typedef struct packed {
+    logic [31:0] q;
+  } rv_core_ibex_peri_reg2hw_dbus_addr_matching_mreg_t;
+
+  typedef struct packed {
+    logic [31:0] q;
+  } rv_core_ibex_peri_reg2hw_dbus_remap_addr_mreg_t;
+
+  typedef struct packed {
     struct packed {
       logic        d;
       logic        de;
@@ -61,8 +86,14 @@
 
   // Register -> HW type
   typedef struct packed {
-    rv_core_ibex_peri_reg2hw_alert_test_reg_t alert_test; // [11:4]
-    rv_core_ibex_peri_reg2hw_sw_alert_mreg_t [1:0] sw_alert; // [3:0]
+    rv_core_ibex_peri_reg2hw_alert_test_reg_t alert_test; // [271:264]
+    rv_core_ibex_peri_reg2hw_sw_alert_mreg_t [1:0] sw_alert; // [263:260]
+    rv_core_ibex_peri_reg2hw_ibus_addr_en_mreg_t [1:0] ibus_addr_en; // [259:258]
+    rv_core_ibex_peri_reg2hw_ibus_addr_matching_mreg_t [1:0] ibus_addr_matching; // [257:194]
+    rv_core_ibex_peri_reg2hw_ibus_remap_addr_mreg_t [1:0] ibus_remap_addr; // [193:130]
+    rv_core_ibex_peri_reg2hw_dbus_addr_en_mreg_t [1:0] dbus_addr_en; // [129:128]
+    rv_core_ibex_peri_reg2hw_dbus_addr_matching_mreg_t [1:0] dbus_addr_matching; // [127:64]
+    rv_core_ibex_peri_reg2hw_dbus_remap_addr_mreg_t [1:0] dbus_remap_addr; // [63:0]
   } rv_core_ibex_peri_reg2hw_t;
 
   // HW -> register type
@@ -71,12 +102,28 @@
   } rv_core_ibex_peri_hw2reg_t;
 
   // Register offsets
-  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_ALERT_TEST_OFFSET = 5'h 0;
-  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_0_OFFSET = 5'h 4;
-  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_1_OFFSET = 5'h 8;
-  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_SW_ALERT_0_OFFSET = 5'h c;
-  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_SW_ALERT_1_OFFSET = 5'h 10;
-  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_ERR_STATUS_OFFSET = 5'h 14;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_ALERT_TEST_OFFSET = 7'h 0;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_0_OFFSET = 7'h 4;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_1_OFFSET = 7'h 8;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_SW_ALERT_0_OFFSET = 7'h c;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_SW_ALERT_1_OFFSET = 7'h 10;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_IBUS_REGWEN_0_OFFSET = 7'h 14;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_IBUS_REGWEN_1_OFFSET = 7'h 18;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_IBUS_ADDR_EN_0_OFFSET = 7'h 1c;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_IBUS_ADDR_EN_1_OFFSET = 7'h 20;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_0_OFFSET = 7'h 24;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_1_OFFSET = 7'h 28;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_0_OFFSET = 7'h 2c;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_1_OFFSET = 7'h 30;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_DBUS_REGWEN_0_OFFSET = 7'h 34;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_DBUS_REGWEN_1_OFFSET = 7'h 38;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_DBUS_ADDR_EN_0_OFFSET = 7'h 3c;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_DBUS_ADDR_EN_1_OFFSET = 7'h 40;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_0_OFFSET = 7'h 44;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_1_OFFSET = 7'h 48;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_0_OFFSET = 7'h 4c;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_1_OFFSET = 7'h 50;
+  parameter logic [BlockAw-1:0] RV_CORE_IBEX_PERI_ERR_STATUS_OFFSET = 7'h 54;
 
   // Reset values for hwext registers and their fields
   parameter logic [3:0] RV_CORE_IBEX_PERI_ALERT_TEST_RESVAL = 4'h 0;
@@ -92,17 +139,49 @@
     RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_1,
     RV_CORE_IBEX_PERI_SW_ALERT_0,
     RV_CORE_IBEX_PERI_SW_ALERT_1,
+    RV_CORE_IBEX_PERI_IBUS_REGWEN_0,
+    RV_CORE_IBEX_PERI_IBUS_REGWEN_1,
+    RV_CORE_IBEX_PERI_IBUS_ADDR_EN_0,
+    RV_CORE_IBEX_PERI_IBUS_ADDR_EN_1,
+    RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_0,
+    RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_1,
+    RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_0,
+    RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_1,
+    RV_CORE_IBEX_PERI_DBUS_REGWEN_0,
+    RV_CORE_IBEX_PERI_DBUS_REGWEN_1,
+    RV_CORE_IBEX_PERI_DBUS_ADDR_EN_0,
+    RV_CORE_IBEX_PERI_DBUS_ADDR_EN_1,
+    RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_0,
+    RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_1,
+    RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_0,
+    RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_1,
     RV_CORE_IBEX_PERI_ERR_STATUS
   } rv_core_ibex_peri_id_e;
 
   // Register width information to check illegal writes
-  parameter logic [3:0] RV_CORE_IBEX_PERI_PERMIT [6] = '{
-    4'b 0001, // index[0] RV_CORE_IBEX_PERI_ALERT_TEST
-    4'b 0001, // index[1] RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_0
-    4'b 0001, // index[2] RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_1
-    4'b 0001, // index[3] RV_CORE_IBEX_PERI_SW_ALERT_0
-    4'b 0001, // index[4] RV_CORE_IBEX_PERI_SW_ALERT_1
-    4'b 0011  // index[5] RV_CORE_IBEX_PERI_ERR_STATUS
+  parameter logic [3:0] RV_CORE_IBEX_PERI_PERMIT [22] = '{
+    4'b 0001, // index[ 0] RV_CORE_IBEX_PERI_ALERT_TEST
+    4'b 0001, // index[ 1] RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_0
+    4'b 0001, // index[ 2] RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_1
+    4'b 0001, // index[ 3] RV_CORE_IBEX_PERI_SW_ALERT_0
+    4'b 0001, // index[ 4] RV_CORE_IBEX_PERI_SW_ALERT_1
+    4'b 0001, // index[ 5] RV_CORE_IBEX_PERI_IBUS_REGWEN_0
+    4'b 0001, // index[ 6] RV_CORE_IBEX_PERI_IBUS_REGWEN_1
+    4'b 0001, // index[ 7] RV_CORE_IBEX_PERI_IBUS_ADDR_EN_0
+    4'b 0001, // index[ 8] RV_CORE_IBEX_PERI_IBUS_ADDR_EN_1
+    4'b 1111, // index[ 9] RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_0
+    4'b 1111, // index[10] RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_1
+    4'b 1111, // index[11] RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_0
+    4'b 1111, // index[12] RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_1
+    4'b 0001, // index[13] RV_CORE_IBEX_PERI_DBUS_REGWEN_0
+    4'b 0001, // index[14] RV_CORE_IBEX_PERI_DBUS_REGWEN_1
+    4'b 0001, // index[15] RV_CORE_IBEX_PERI_DBUS_ADDR_EN_0
+    4'b 0001, // index[16] RV_CORE_IBEX_PERI_DBUS_ADDR_EN_1
+    4'b 1111, // index[17] RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_0
+    4'b 1111, // index[18] RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_1
+    4'b 1111, // index[19] RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_0
+    4'b 1111, // index[20] RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_1
+    4'b 0011  // index[21] RV_CORE_IBEX_PERI_ERR_STATUS
   };
 
 endpackage
diff --git a/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_reg_top.sv b/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_reg_top.sv
index 9e8e05d..f7da480 100644
--- a/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_reg_top.sv
+++ b/hw/ip/rv_core_ibex_peri/rtl/rv_core_ibex_peri_reg_top.sv
@@ -25,7 +25,7 @@
 
   import rv_core_ibex_peri_reg_pkg::* ;
 
-  localparam int AW = 5;
+  localparam int AW = 7;
   localparam int DW = 32;
   localparam int DBW = DW/8;                    // Byte Width
 
@@ -121,6 +121,54 @@
   logic sw_alert_1_we;
   logic [1:0] sw_alert_1_qs;
   logic [1:0] sw_alert_1_wd;
+  logic ibus_regwen_0_we;
+  logic ibus_regwen_0_qs;
+  logic ibus_regwen_0_wd;
+  logic ibus_regwen_1_we;
+  logic ibus_regwen_1_qs;
+  logic ibus_regwen_1_wd;
+  logic ibus_addr_en_0_we;
+  logic ibus_addr_en_0_qs;
+  logic ibus_addr_en_0_wd;
+  logic ibus_addr_en_1_we;
+  logic ibus_addr_en_1_qs;
+  logic ibus_addr_en_1_wd;
+  logic ibus_addr_matching_0_we;
+  logic [31:0] ibus_addr_matching_0_qs;
+  logic [31:0] ibus_addr_matching_0_wd;
+  logic ibus_addr_matching_1_we;
+  logic [31:0] ibus_addr_matching_1_qs;
+  logic [31:0] ibus_addr_matching_1_wd;
+  logic ibus_remap_addr_0_we;
+  logic [31:0] ibus_remap_addr_0_qs;
+  logic [31:0] ibus_remap_addr_0_wd;
+  logic ibus_remap_addr_1_we;
+  logic [31:0] ibus_remap_addr_1_qs;
+  logic [31:0] ibus_remap_addr_1_wd;
+  logic dbus_regwen_0_we;
+  logic dbus_regwen_0_qs;
+  logic dbus_regwen_0_wd;
+  logic dbus_regwen_1_we;
+  logic dbus_regwen_1_qs;
+  logic dbus_regwen_1_wd;
+  logic dbus_addr_en_0_we;
+  logic dbus_addr_en_0_qs;
+  logic dbus_addr_en_0_wd;
+  logic dbus_addr_en_1_we;
+  logic dbus_addr_en_1_qs;
+  logic dbus_addr_en_1_wd;
+  logic dbus_addr_matching_0_we;
+  logic [31:0] dbus_addr_matching_0_qs;
+  logic [31:0] dbus_addr_matching_0_wd;
+  logic dbus_addr_matching_1_we;
+  logic [31:0] dbus_addr_matching_1_qs;
+  logic [31:0] dbus_addr_matching_1_wd;
+  logic dbus_remap_addr_0_we;
+  logic [31:0] dbus_remap_addr_0_qs;
+  logic [31:0] dbus_remap_addr_0_wd;
+  logic dbus_remap_addr_1_we;
+  logic [31:0] dbus_remap_addr_1_qs;
+  logic [31:0] dbus_remap_addr_1_wd;
   logic err_status_we;
   logic err_status_reg_intg_err_qs;
   logic err_status_reg_intg_err_wd;
@@ -306,6 +354,454 @@
   );
 
 
+
+  // Subregister 0 of Multireg ibus_regwen
+  // R[ibus_regwen_0]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("W0C"),
+    .RESVAL  (1'h1)
+  ) u_ibus_regwen_0 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (ibus_regwen_0_we),
+    .wd     (ibus_regwen_0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (ibus_regwen_0_qs)
+  );
+
+  // Subregister 1 of Multireg ibus_regwen
+  // R[ibus_regwen_1]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("W0C"),
+    .RESVAL  (1'h1)
+  ) u_ibus_regwen_1 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (ibus_regwen_1_we),
+    .wd     (ibus_regwen_1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (ibus_regwen_1_qs)
+  );
+
+
+
+  // Subregister 0 of Multireg ibus_addr_en
+  // R[ibus_addr_en_0]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_ibus_addr_en_0 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (ibus_addr_en_0_we & ibus_regwen_0_qs),
+    .wd     (ibus_addr_en_0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ibus_addr_en[0].q),
+
+    // to register interface (read)
+    .qs     (ibus_addr_en_0_qs)
+  );
+
+  // Subregister 1 of Multireg ibus_addr_en
+  // R[ibus_addr_en_1]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_ibus_addr_en_1 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (ibus_addr_en_1_we & ibus_regwen_1_qs),
+    .wd     (ibus_addr_en_1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ibus_addr_en[1].q),
+
+    // to register interface (read)
+    .qs     (ibus_addr_en_1_qs)
+  );
+
+
+
+  // Subregister 0 of Multireg ibus_addr_matching
+  // R[ibus_addr_matching_0]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("RW"),
+    .RESVAL  (32'h0)
+  ) u_ibus_addr_matching_0 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (ibus_addr_matching_0_we & ibus_regwen_0_qs),
+    .wd     (ibus_addr_matching_0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ibus_addr_matching[0].q),
+
+    // to register interface (read)
+    .qs     (ibus_addr_matching_0_qs)
+  );
+
+  // Subregister 1 of Multireg ibus_addr_matching
+  // R[ibus_addr_matching_1]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("RW"),
+    .RESVAL  (32'h0)
+  ) u_ibus_addr_matching_1 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (ibus_addr_matching_1_we & ibus_regwen_1_qs),
+    .wd     (ibus_addr_matching_1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ibus_addr_matching[1].q),
+
+    // to register interface (read)
+    .qs     (ibus_addr_matching_1_qs)
+  );
+
+
+
+  // Subregister 0 of Multireg ibus_remap_addr
+  // R[ibus_remap_addr_0]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("RW"),
+    .RESVAL  (32'h0)
+  ) u_ibus_remap_addr_0 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (ibus_remap_addr_0_we & ibus_regwen_0_qs),
+    .wd     (ibus_remap_addr_0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ibus_remap_addr[0].q),
+
+    // to register interface (read)
+    .qs     (ibus_remap_addr_0_qs)
+  );
+
+  // Subregister 1 of Multireg ibus_remap_addr
+  // R[ibus_remap_addr_1]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("RW"),
+    .RESVAL  (32'h0)
+  ) u_ibus_remap_addr_1 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (ibus_remap_addr_1_we & ibus_regwen_1_qs),
+    .wd     (ibus_remap_addr_1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ibus_remap_addr[1].q),
+
+    // to register interface (read)
+    .qs     (ibus_remap_addr_1_qs)
+  );
+
+
+
+  // Subregister 0 of Multireg dbus_regwen
+  // R[dbus_regwen_0]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("W0C"),
+    .RESVAL  (1'h1)
+  ) u_dbus_regwen_0 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (dbus_regwen_0_we),
+    .wd     (dbus_regwen_0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (dbus_regwen_0_qs)
+  );
+
+  // Subregister 1 of Multireg dbus_regwen
+  // R[dbus_regwen_1]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("W0C"),
+    .RESVAL  (1'h1)
+  ) u_dbus_regwen_1 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (dbus_regwen_1_we),
+    .wd     (dbus_regwen_1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (dbus_regwen_1_qs)
+  );
+
+
+
+  // Subregister 0 of Multireg dbus_addr_en
+  // R[dbus_addr_en_0]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_dbus_addr_en_0 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (dbus_addr_en_0_we & dbus_regwen_0_qs),
+    .wd     (dbus_addr_en_0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.dbus_addr_en[0].q),
+
+    // to register interface (read)
+    .qs     (dbus_addr_en_0_qs)
+  );
+
+  // Subregister 1 of Multireg dbus_addr_en
+  // R[dbus_addr_en_1]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_dbus_addr_en_1 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (dbus_addr_en_1_we & dbus_regwen_1_qs),
+    .wd     (dbus_addr_en_1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.dbus_addr_en[1].q),
+
+    // to register interface (read)
+    .qs     (dbus_addr_en_1_qs)
+  );
+
+
+
+  // Subregister 0 of Multireg dbus_addr_matching
+  // R[dbus_addr_matching_0]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("RW"),
+    .RESVAL  (32'h0)
+  ) u_dbus_addr_matching_0 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (dbus_addr_matching_0_we & dbus_regwen_0_qs),
+    .wd     (dbus_addr_matching_0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.dbus_addr_matching[0].q),
+
+    // to register interface (read)
+    .qs     (dbus_addr_matching_0_qs)
+  );
+
+  // Subregister 1 of Multireg dbus_addr_matching
+  // R[dbus_addr_matching_1]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("RW"),
+    .RESVAL  (32'h0)
+  ) u_dbus_addr_matching_1 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (dbus_addr_matching_1_we & dbus_regwen_1_qs),
+    .wd     (dbus_addr_matching_1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.dbus_addr_matching[1].q),
+
+    // to register interface (read)
+    .qs     (dbus_addr_matching_1_qs)
+  );
+
+
+
+  // Subregister 0 of Multireg dbus_remap_addr
+  // R[dbus_remap_addr_0]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("RW"),
+    .RESVAL  (32'h0)
+  ) u_dbus_remap_addr_0 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (dbus_remap_addr_0_we & dbus_regwen_0_qs),
+    .wd     (dbus_remap_addr_0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.dbus_remap_addr[0].q),
+
+    // to register interface (read)
+    .qs     (dbus_remap_addr_0_qs)
+  );
+
+  // Subregister 1 of Multireg dbus_remap_addr
+  // R[dbus_remap_addr_1]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("RW"),
+    .RESVAL  (32'h0)
+  ) u_dbus_remap_addr_1 (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (dbus_remap_addr_1_we & dbus_regwen_1_qs),
+    .wd     (dbus_remap_addr_1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.dbus_remap_addr[1].q),
+
+    // to register interface (read)
+    .qs     (dbus_remap_addr_1_qs)
+  );
+
+
   // R[err_status]: V(False)
 
   //   F[reg_intg_err]: 0:0
@@ -414,15 +910,31 @@
 
 
 
-  logic [5:0] addr_hit;
+  logic [21:0] addr_hit;
   always_comb begin
     addr_hit = '0;
-    addr_hit[0] = (reg_addr == RV_CORE_IBEX_PERI_ALERT_TEST_OFFSET);
-    addr_hit[1] = (reg_addr == RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_0_OFFSET);
-    addr_hit[2] = (reg_addr == RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_1_OFFSET);
-    addr_hit[3] = (reg_addr == RV_CORE_IBEX_PERI_SW_ALERT_0_OFFSET);
-    addr_hit[4] = (reg_addr == RV_CORE_IBEX_PERI_SW_ALERT_1_OFFSET);
-    addr_hit[5] = (reg_addr == RV_CORE_IBEX_PERI_ERR_STATUS_OFFSET);
+    addr_hit[ 0] = (reg_addr == RV_CORE_IBEX_PERI_ALERT_TEST_OFFSET);
+    addr_hit[ 1] = (reg_addr == RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_0_OFFSET);
+    addr_hit[ 2] = (reg_addr == RV_CORE_IBEX_PERI_SW_ALERT_REGWEN_1_OFFSET);
+    addr_hit[ 3] = (reg_addr == RV_CORE_IBEX_PERI_SW_ALERT_0_OFFSET);
+    addr_hit[ 4] = (reg_addr == RV_CORE_IBEX_PERI_SW_ALERT_1_OFFSET);
+    addr_hit[ 5] = (reg_addr == RV_CORE_IBEX_PERI_IBUS_REGWEN_0_OFFSET);
+    addr_hit[ 6] = (reg_addr == RV_CORE_IBEX_PERI_IBUS_REGWEN_1_OFFSET);
+    addr_hit[ 7] = (reg_addr == RV_CORE_IBEX_PERI_IBUS_ADDR_EN_0_OFFSET);
+    addr_hit[ 8] = (reg_addr == RV_CORE_IBEX_PERI_IBUS_ADDR_EN_1_OFFSET);
+    addr_hit[ 9] = (reg_addr == RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_0_OFFSET);
+    addr_hit[10] = (reg_addr == RV_CORE_IBEX_PERI_IBUS_ADDR_MATCHING_1_OFFSET);
+    addr_hit[11] = (reg_addr == RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_0_OFFSET);
+    addr_hit[12] = (reg_addr == RV_CORE_IBEX_PERI_IBUS_REMAP_ADDR_1_OFFSET);
+    addr_hit[13] = (reg_addr == RV_CORE_IBEX_PERI_DBUS_REGWEN_0_OFFSET);
+    addr_hit[14] = (reg_addr == RV_CORE_IBEX_PERI_DBUS_REGWEN_1_OFFSET);
+    addr_hit[15] = (reg_addr == RV_CORE_IBEX_PERI_DBUS_ADDR_EN_0_OFFSET);
+    addr_hit[16] = (reg_addr == RV_CORE_IBEX_PERI_DBUS_ADDR_EN_1_OFFSET);
+    addr_hit[17] = (reg_addr == RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_0_OFFSET);
+    addr_hit[18] = (reg_addr == RV_CORE_IBEX_PERI_DBUS_ADDR_MATCHING_1_OFFSET);
+    addr_hit[19] = (reg_addr == RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_0_OFFSET);
+    addr_hit[20] = (reg_addr == RV_CORE_IBEX_PERI_DBUS_REMAP_ADDR_1_OFFSET);
+    addr_hit[21] = (reg_addr == RV_CORE_IBEX_PERI_ERR_STATUS_OFFSET);
   end
 
   assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -430,12 +942,28 @@
   // Check sub-word write is permitted
   always_comb begin
     wr_err = (reg_we &
-              ((addr_hit[0] & (|(RV_CORE_IBEX_PERI_PERMIT[0] & ~reg_be))) |
-               (addr_hit[1] & (|(RV_CORE_IBEX_PERI_PERMIT[1] & ~reg_be))) |
-               (addr_hit[2] & (|(RV_CORE_IBEX_PERI_PERMIT[2] & ~reg_be))) |
-               (addr_hit[3] & (|(RV_CORE_IBEX_PERI_PERMIT[3] & ~reg_be))) |
-               (addr_hit[4] & (|(RV_CORE_IBEX_PERI_PERMIT[4] & ~reg_be))) |
-               (addr_hit[5] & (|(RV_CORE_IBEX_PERI_PERMIT[5] & ~reg_be)))));
+              ((addr_hit[ 0] & (|(RV_CORE_IBEX_PERI_PERMIT[ 0] & ~reg_be))) |
+               (addr_hit[ 1] & (|(RV_CORE_IBEX_PERI_PERMIT[ 1] & ~reg_be))) |
+               (addr_hit[ 2] & (|(RV_CORE_IBEX_PERI_PERMIT[ 2] & ~reg_be))) |
+               (addr_hit[ 3] & (|(RV_CORE_IBEX_PERI_PERMIT[ 3] & ~reg_be))) |
+               (addr_hit[ 4] & (|(RV_CORE_IBEX_PERI_PERMIT[ 4] & ~reg_be))) |
+               (addr_hit[ 5] & (|(RV_CORE_IBEX_PERI_PERMIT[ 5] & ~reg_be))) |
+               (addr_hit[ 6] & (|(RV_CORE_IBEX_PERI_PERMIT[ 6] & ~reg_be))) |
+               (addr_hit[ 7] & (|(RV_CORE_IBEX_PERI_PERMIT[ 7] & ~reg_be))) |
+               (addr_hit[ 8] & (|(RV_CORE_IBEX_PERI_PERMIT[ 8] & ~reg_be))) |
+               (addr_hit[ 9] & (|(RV_CORE_IBEX_PERI_PERMIT[ 9] & ~reg_be))) |
+               (addr_hit[10] & (|(RV_CORE_IBEX_PERI_PERMIT[10] & ~reg_be))) |
+               (addr_hit[11] & (|(RV_CORE_IBEX_PERI_PERMIT[11] & ~reg_be))) |
+               (addr_hit[12] & (|(RV_CORE_IBEX_PERI_PERMIT[12] & ~reg_be))) |
+               (addr_hit[13] & (|(RV_CORE_IBEX_PERI_PERMIT[13] & ~reg_be))) |
+               (addr_hit[14] & (|(RV_CORE_IBEX_PERI_PERMIT[14] & ~reg_be))) |
+               (addr_hit[15] & (|(RV_CORE_IBEX_PERI_PERMIT[15] & ~reg_be))) |
+               (addr_hit[16] & (|(RV_CORE_IBEX_PERI_PERMIT[16] & ~reg_be))) |
+               (addr_hit[17] & (|(RV_CORE_IBEX_PERI_PERMIT[17] & ~reg_be))) |
+               (addr_hit[18] & (|(RV_CORE_IBEX_PERI_PERMIT[18] & ~reg_be))) |
+               (addr_hit[19] & (|(RV_CORE_IBEX_PERI_PERMIT[19] & ~reg_be))) |
+               (addr_hit[20] & (|(RV_CORE_IBEX_PERI_PERMIT[20] & ~reg_be))) |
+               (addr_hit[21] & (|(RV_CORE_IBEX_PERI_PERMIT[21] & ~reg_be)))));
   end
   assign alert_test_we = addr_hit[0] & reg_we & !reg_error;
 
@@ -458,7 +986,55 @@
   assign sw_alert_1_we = addr_hit[4] & reg_we & !reg_error;
 
   assign sw_alert_1_wd = reg_wdata[1:0];
-  assign err_status_we = addr_hit[5] & reg_we & !reg_error;
+  assign ibus_regwen_0_we = addr_hit[5] & reg_we & !reg_error;
+
+  assign ibus_regwen_0_wd = reg_wdata[0];
+  assign ibus_regwen_1_we = addr_hit[6] & reg_we & !reg_error;
+
+  assign ibus_regwen_1_wd = reg_wdata[0];
+  assign ibus_addr_en_0_we = addr_hit[7] & reg_we & !reg_error;
+
+  assign ibus_addr_en_0_wd = reg_wdata[0];
+  assign ibus_addr_en_1_we = addr_hit[8] & reg_we & !reg_error;
+
+  assign ibus_addr_en_1_wd = reg_wdata[0];
+  assign ibus_addr_matching_0_we = addr_hit[9] & reg_we & !reg_error;
+
+  assign ibus_addr_matching_0_wd = reg_wdata[31:0];
+  assign ibus_addr_matching_1_we = addr_hit[10] & reg_we & !reg_error;
+
+  assign ibus_addr_matching_1_wd = reg_wdata[31:0];
+  assign ibus_remap_addr_0_we = addr_hit[11] & reg_we & !reg_error;
+
+  assign ibus_remap_addr_0_wd = reg_wdata[31:0];
+  assign ibus_remap_addr_1_we = addr_hit[12] & reg_we & !reg_error;
+
+  assign ibus_remap_addr_1_wd = reg_wdata[31:0];
+  assign dbus_regwen_0_we = addr_hit[13] & reg_we & !reg_error;
+
+  assign dbus_regwen_0_wd = reg_wdata[0];
+  assign dbus_regwen_1_we = addr_hit[14] & reg_we & !reg_error;
+
+  assign dbus_regwen_1_wd = reg_wdata[0];
+  assign dbus_addr_en_0_we = addr_hit[15] & reg_we & !reg_error;
+
+  assign dbus_addr_en_0_wd = reg_wdata[0];
+  assign dbus_addr_en_1_we = addr_hit[16] & reg_we & !reg_error;
+
+  assign dbus_addr_en_1_wd = reg_wdata[0];
+  assign dbus_addr_matching_0_we = addr_hit[17] & reg_we & !reg_error;
+
+  assign dbus_addr_matching_0_wd = reg_wdata[31:0];
+  assign dbus_addr_matching_1_we = addr_hit[18] & reg_we & !reg_error;
+
+  assign dbus_addr_matching_1_wd = reg_wdata[31:0];
+  assign dbus_remap_addr_0_we = addr_hit[19] & reg_we & !reg_error;
+
+  assign dbus_remap_addr_0_wd = reg_wdata[31:0];
+  assign dbus_remap_addr_1_we = addr_hit[20] & reg_we & !reg_error;
+
+  assign dbus_remap_addr_1_wd = reg_wdata[31:0];
+  assign err_status_we = addr_hit[21] & reg_we & !reg_error;
 
   assign err_status_reg_intg_err_wd = reg_wdata[0];
 
@@ -496,6 +1072,70 @@
       end
 
       addr_hit[5]: begin
+        reg_rdata_next[0] = ibus_regwen_0_qs;
+      end
+
+      addr_hit[6]: begin
+        reg_rdata_next[0] = ibus_regwen_1_qs;
+      end
+
+      addr_hit[7]: begin
+        reg_rdata_next[0] = ibus_addr_en_0_qs;
+      end
+
+      addr_hit[8]: begin
+        reg_rdata_next[0] = ibus_addr_en_1_qs;
+      end
+
+      addr_hit[9]: begin
+        reg_rdata_next[31:0] = ibus_addr_matching_0_qs;
+      end
+
+      addr_hit[10]: begin
+        reg_rdata_next[31:0] = ibus_addr_matching_1_qs;
+      end
+
+      addr_hit[11]: begin
+        reg_rdata_next[31:0] = ibus_remap_addr_0_qs;
+      end
+
+      addr_hit[12]: begin
+        reg_rdata_next[31:0] = ibus_remap_addr_1_qs;
+      end
+
+      addr_hit[13]: begin
+        reg_rdata_next[0] = dbus_regwen_0_qs;
+      end
+
+      addr_hit[14]: begin
+        reg_rdata_next[0] = dbus_regwen_1_qs;
+      end
+
+      addr_hit[15]: begin
+        reg_rdata_next[0] = dbus_addr_en_0_qs;
+      end
+
+      addr_hit[16]: begin
+        reg_rdata_next[0] = dbus_addr_en_1_qs;
+      end
+
+      addr_hit[17]: begin
+        reg_rdata_next[31:0] = dbus_addr_matching_0_qs;
+      end
+
+      addr_hit[18]: begin
+        reg_rdata_next[31:0] = dbus_addr_matching_1_qs;
+      end
+
+      addr_hit[19]: begin
+        reg_rdata_next[31:0] = dbus_remap_addr_0_qs;
+      end
+
+      addr_hit[20]: begin
+        reg_rdata_next[31:0] = dbus_remap_addr_1_qs;
+      end
+
+      addr_hit[21]: begin
         reg_rdata_next[0] = err_status_reg_intg_err_qs;
         reg_rdata_next[8] = err_status_fatal_intg_err_qs;
         reg_rdata_next[9] = err_status_fatal_core_err_qs;
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index e126913..e7bfe6a 100644
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -230,6 +230,20 @@
           act:     "req",
           package: "rv_core_ibex_peri_pkg",
         },
+
+        { struct:  "region_cfg",
+          type:    "uni",
+          name:    "ibus_region_cfg",
+          act:     "rcv",
+          package: "rv_core_ibex_peri_pkg",
+        },
+
+        { struct:  "region_cfg",
+          type:    "uni",
+          name:    "dbus_region_cfg",
+          act:     "rcv",
+          package: "rv_core_ibex_peri_pkg",
+        },
       ],
     }
     { name: "rv_dm",
@@ -989,6 +1003,8 @@
       'rv_core_ibex.fatal_intg_event' : ['rv_core_ibex_peri.fatal_intg_event'],
       'rv_core_ibex.fatal_core_event' : ['rv_core_ibex_peri.fatal_core_event'],
       'rv_core_ibex.recov_core_event' : ['rv_core_ibex_peri.recov_core_event'],
+      'rv_core_ibex_peri.ibus_region_cfg' : ['rv_core_ibex.ibus_region_cfg'],
+      'rv_core_ibex_peri.dbus_region_cfg' : ['rv_core_ibex.dbus_region_cfg'],
 
       // spi passthrough connection
       'spi_device.passthrough'     : ['spi_host0.passthrough']