[aes/rtl] Switch to new reggen version
diff --git a/hw/ip/aes/rtl/aes.sv b/hw/ip/aes/rtl/aes.sv
index 25ae0d5..0f5d8d7 100644
--- a/hw/ip/aes/rtl/aes.sv
+++ b/hw/ip/aes/rtl/aes.sv
@@ -12,7 +12,9 @@
 
   // Bus Interface
   input  tlul_pkg::tl_h2d_t tl_i,
-  output tlul_pkg::tl_d2h_t tl_o
+  output tlul_pkg::tl_d2h_t tl_o,
+
+  input                     devmode_i
 );
 
   import aes_reg_pkg::*;
@@ -26,7 +28,8 @@
     .tl_i,
     .tl_o,
     .reg2hw,
-    .hw2reg
+    .hw2reg,
+    .devmode_i
   );
 
   aes_core #(
diff --git a/hw/ip/aes/rtl/aes_core.sv b/hw/ip/aes/rtl/aes_core.sv
index af80193..16115b3 100644
--- a/hw/ip/aes/rtl/aes_core.sv
+++ b/hw/ip/aes/rtl/aes_core.sv
@@ -68,25 +68,25 @@
   logic    [31:0] unused_data_out_q[4];
 
   // Inputs
-  assign key_init[0] = reg2hw.key0.q;
-  assign key_init[1] = reg2hw.key1.q;
-  assign key_init[2] = reg2hw.key2.q;
-  assign key_init[3] = reg2hw.key3.q;
-  assign key_init[4] = reg2hw.key4.q;
-  assign key_init[5] = reg2hw.key5.q;
-  assign key_init[6] = reg2hw.key6.q;
-  assign key_init[7] = reg2hw.key7.q;
+  assign key_init[0] = reg2hw.key[0].q;
+  assign key_init[1] = reg2hw.key[1].q;
+  assign key_init[2] = reg2hw.key[2].q;
+  assign key_init[3] = reg2hw.key[3].q;
+  assign key_init[4] = reg2hw.key[4].q;
+  assign key_init[5] = reg2hw.key[5].q;
+  assign key_init[6] = reg2hw.key[6].q;
+  assign key_init[7] = reg2hw.key[7].q;
 
-  assign key_init_qe = {reg2hw.key7.qe, reg2hw.key6.qe, reg2hw.key5.qe, reg2hw.key4.qe,
-                        reg2hw.key3.qe, reg2hw.key2.qe, reg2hw.key1.qe, reg2hw.key0.qe};
+  assign key_init_qe = {reg2hw.key[7].qe, reg2hw.key[6].qe, reg2hw.key[5].qe, reg2hw.key[4].qe,
+                        reg2hw.key[3].qe, reg2hw.key[2].qe, reg2hw.key[1].qe, reg2hw.key[0].qe};
 
-  assign data_in[0] = reg2hw.data_in0.q;
-  assign data_in[1] = reg2hw.data_in1.q;
-  assign data_in[2] = reg2hw.data_in2.q;
-  assign data_in[3] = reg2hw.data_in3.q;
+  assign data_in[0] = reg2hw.data_in[0].q;
+  assign data_in[1] = reg2hw.data_in[1].q;
+  assign data_in[2] = reg2hw.data_in[2].q;
+  assign data_in[3] = reg2hw.data_in[3].q;
 
-  assign data_in_qe = {reg2hw.data_in3.qe, reg2hw.data_in2.qe,
-                       reg2hw.data_in1.qe, reg2hw.data_in0.qe};
+  assign data_in_qe = {reg2hw.data_in[3].qe, reg2hw.data_in[2].qe,
+                       reg2hw.data_in[1].qe, reg2hw.data_in[0].qe};
 
   always_comb begin : conv_data_in_to_state
     for (int i=0; i<4; i++) begin
@@ -110,15 +110,15 @@
     endcase
   end
 
-  assign data_out_re = {reg2hw.data_out3.re, reg2hw.data_out2.re,
-                        reg2hw.data_out1.re, reg2hw.data_out0.re};
+  assign data_out_re = {reg2hw.data_out[3].re, reg2hw.data_out[2].re,
+                        reg2hw.data_out[1].re, reg2hw.data_out[0].re};
 
   // Unused inputs
   // data_out is actually hwo, but we need hrw for hwre
-  assign unused_data_out_q[0] = reg2hw.data_out0.q;
-  assign unused_data_out_q[1] = reg2hw.data_out1.q;
-  assign unused_data_out_q[2] = reg2hw.data_out2.q;
-  assign unused_data_out_q[3] = reg2hw.data_out3.q;
+  assign unused_data_out_q[0] = reg2hw.data_out[0].q;
+  assign unused_data_out_q[1] = reg2hw.data_out[1].q;
+  assign unused_data_out_q[2] = reg2hw.data_out[2].q;
+  assign unused_data_out_q[3] = reg2hw.data_out[3].q;
 
   // State registers
   always_comb begin : state_mux
@@ -347,10 +347,10 @@
   );
 
   // Outputs
-  assign hw2reg.data_out0.d = data_out_q[0];
-  assign hw2reg.data_out1.d = data_out_q[1];
-  assign hw2reg.data_out2.d = data_out_q[2];
-  assign hw2reg.data_out3.d = data_out_q[3];
+  assign hw2reg.data_out[0].d = data_out_q[0];
+  assign hw2reg.data_out[1].d = data_out_q[1];
+  assign hw2reg.data_out[2].d = data_out_q[2];
+  assign hw2reg.data_out[3].d = data_out_q[3];
 
   assign hw2reg.ctrl.key_len.d  = {key_len};
   assign hw2reg.ctrl.key_len.de = reg2hw.ctrl.key_len.qe;
diff --git a/hw/ip/aes/rtl/aes_reg_pkg.sv b/hw/ip/aes/rtl/aes_reg_pkg.sv
index 73705b8..5347712 100644
--- a/hw/ip/aes/rtl/aes_reg_pkg.sv
+++ b/hw/ip/aes/rtl/aes_reg_pkg.sv
@@ -6,73 +6,40 @@
 
 package aes_reg_pkg;
 
-// Register to internal design logic
-typedef struct packed {
+  // Param list
+  localparam int KEY = 8;
+  localparam int DATA_IN = 4;
+  localparam int DATA_OUT = 4;
 
-  struct packed {
-    logic [31:0] q; // [538:507]
-    logic qe; // [506]
-  } key0;
-  struct packed {
-    logic [31:0] q; // [505:474]
-    logic qe; // [473]
-  } key1;
-  struct packed {
-    logic [31:0] q; // [472:441]
-    logic qe; // [440]
-  } key2;
-  struct packed {
-    logic [31:0] q; // [439:408]
-    logic qe; // [407]
-  } key3;
-  struct packed {
-    logic [31:0] q; // [406:375]
-    logic qe; // [374]
-  } key4;
-  struct packed {
-    logic [31:0] q; // [373:342]
-    logic qe; // [341]
-  } key5;
-  struct packed {
-    logic [31:0] q; // [340:309]
-    logic qe; // [308]
-  } key6;
-  struct packed {
-    logic [31:0] q; // [307:276]
-    logic qe; // [275]
-  } key7;
-  struct packed {
-    logic [31:0] q; // [274:243]
-    logic qe; // [242]
-  } data_in0;
-  struct packed {
-    logic [31:0] q; // [241:210]
-    logic qe; // [209]
-  } data_in1;
-  struct packed {
-    logic [31:0] q; // [208:177]
-    logic qe; // [176]
-  } data_in2;
-  struct packed {
-    logic [31:0] q; // [175:144]
-    logic qe; // [143]
-  } data_in3;
-  struct packed {
-    logic [31:0] q; // [142:111]
-    logic re; // [110]
-  } data_out0;
-  struct packed {
-    logic [31:0] q; // [109:78]
-    logic re; // [77]
-  } data_out1;
-  struct packed {
-    logic [31:0] q; // [76:45]
-    logic re; // [44]
-  } data_out2;
-  struct packed {
-    logic [31:0] q; // [43:12]
-    logic re; // [11]
-  } data_out3;
+/////////////////////////////////////////////////////////////////////
+// Typedefs for multiregs
+/////////////////////////////////////////////////////////////////////
+
+typedef struct packed {
+  logic [31:0] q;
+  logic qe;
+} aes_reg2hw_key_mreg_t;
+typedef struct packed {
+  logic [31:0] q;
+  logic qe;
+} aes_reg2hw_data_in_mreg_t;
+typedef struct packed {
+  logic [31:0] q;
+  logic re;
+} aes_reg2hw_data_out_mreg_t;
+
+typedef struct packed {
+  logic [31:0] d;
+} aes_hw2reg_data_out_mreg_t;
+
+/////////////////////////////////////////////////////////////////////
+// Register to internal design logic
+/////////////////////////////////////////////////////////////////////
+
+typedef struct packed {
+  aes_reg2hw_key_mreg_t [7:0] key; // [538:275]
+  aes_reg2hw_data_in_mreg_t [3:0] data_in; // [274:143]
+  aes_reg2hw_data_out_mreg_t [3:0] data_out; // [142:11]
   struct packed {
     struct packed {
       logic q; // [10]
@@ -96,21 +63,12 @@
   } trigger;
 } aes_reg2hw_t;
 
+/////////////////////////////////////////////////////////////////////
 // Internal design logic to register
-typedef struct packed {
+/////////////////////////////////////////////////////////////////////
 
-  struct packed {
-    logic [31:0] d; // [141:110]
-  } data_out0;
-  struct packed {
-    logic [31:0] d; // [109:78]
-  } data_out1;
-  struct packed {
-    logic [31:0] d; // [77:46]
-  } data_out2;
-  struct packed {
-    logic [31:0] d; // [45:14]
-  } data_out3;
+typedef struct packed {
+  aes_hw2reg_data_out_mreg_t [3:0] data_out; // [141:14]
   struct packed {
     struct packed {
       logic [2:0] d; // [13:11]
@@ -123,19 +81,19 @@
   } trigger;
   struct packed {
     struct packed {
-      logic d;  // [7]
+      logic d; // [7]
       logic de; // [6]
     } idle;
     struct packed {
-      logic d;  // [5]
+      logic d; // [5]
       logic de; // [4]
     } stall;
     struct packed {
-      logic d;  // [3]
+      logic d; // [3]
       logic de; // [2]
     } output_valid;
     struct packed {
-      logic d;  // [1]
+      logic d; // [1]
       logic de; // [0]
     } input_ready;
   } status;
@@ -163,4 +121,50 @@
   parameter AES_STATUS_OFFSET = 7'h 48;
 
 
+  // Register Index
+  typedef enum int {
+    AES_KEY0,
+    AES_KEY1,
+    AES_KEY2,
+    AES_KEY3,
+    AES_KEY4,
+    AES_KEY5,
+    AES_KEY6,
+    AES_KEY7,
+    AES_DATA_IN0,
+    AES_DATA_IN1,
+    AES_DATA_IN2,
+    AES_DATA_IN3,
+    AES_DATA_OUT0,
+    AES_DATA_OUT1,
+    AES_DATA_OUT2,
+    AES_DATA_OUT3,
+    AES_CTRL,
+    AES_TRIGGER,
+    AES_STATUS
+  } aes_id_e;
+
+  // Register width information to check illegal writes
+  localparam logic [3:0] AES_PERMIT [19] = '{
+    4'b 1111, // index[ 0] AES_KEY0
+    4'b 1111, // index[ 1] AES_KEY1
+    4'b 1111, // index[ 2] AES_KEY2
+    4'b 1111, // index[ 3] AES_KEY3
+    4'b 1111, // index[ 4] AES_KEY4
+    4'b 1111, // index[ 5] AES_KEY5
+    4'b 1111, // index[ 6] AES_KEY6
+    4'b 1111, // index[ 7] AES_KEY7
+    4'b 1111, // index[ 8] AES_DATA_IN0
+    4'b 1111, // index[ 9] AES_DATA_IN1
+    4'b 1111, // index[10] AES_DATA_IN2
+    4'b 1111, // index[11] AES_DATA_IN3
+    4'b 1111, // index[12] AES_DATA_OUT0
+    4'b 1111, // index[13] AES_DATA_OUT1
+    4'b 1111, // index[14] AES_DATA_OUT2
+    4'b 1111, // index[15] AES_DATA_OUT3
+    4'b 0001, // index[16] AES_CTRL
+    4'b 0001, // index[17] AES_TRIGGER
+    4'b 0001  // index[18] AES_STATUS
+  };
 endpackage
+
diff --git a/hw/ip/aes/rtl/aes_reg_top.sv b/hw/ip/aes/rtl/aes_reg_top.sv
index f46e1e9..f1e2db9 100644
--- a/hw/ip/aes/rtl/aes_reg_top.sv
+++ b/hw/ip/aes/rtl/aes_reg_top.sv
@@ -4,7 +4,6 @@
 //
 // Register Top module auto-generated by `reggen`
 
-
 module aes_reg_top (
   input clk_i,
   input rst_ni,
@@ -14,7 +13,10 @@
   output tlul_pkg::tl_d2h_t tl_o,
   // To HW
   output aes_reg_pkg::aes_reg2hw_t reg2hw, // Write
-  input  aes_reg_pkg::aes_hw2reg_t hw2reg  // Read
+  input  aes_reg_pkg::aes_hw2reg_t hw2reg, // Read
+
+  // Config
+  input devmode_i // If 1, explicit error return for unmapped register access
 );
 
   import aes_reg_pkg::* ;
@@ -32,7 +34,7 @@
   logic [DW-1:0]  reg_rdata;
   logic           reg_error;
 
-  logic          malformed, addrmiss;
+  logic          addrmiss, wr_err;
 
   logic [DW-1:0] reg_rdata_next;
 
@@ -62,32 +64,7 @@
   );
 
   assign reg_rdata = reg_rdata_next ;
-  assign reg_error = malformed | addrmiss ;
-
-  // Malformed request check only affects to the write access
-  always_comb begin : malformed_check
-    if (reg_we && (reg_be != '1)) begin
-      malformed = 1'b1;
-    end else begin
-      malformed = 1'b0;
-    end
-  end
-
-  // TODO(eunchan): Revise Register Interface logic after REG INTF finalized
-  // TODO(eunchan): Make concrete scenario
-  //    1. Write: No response, so that it can guarantee a request completes a clock after we
-  //              It means, bus_reg_ready doesn't have to be lowered.
-  //    2. Read: response. So bus_reg_ready should assert after reg_bus_valid & reg_bus_ready
-  //               _____         _____
-  // a_valid _____/     \_______/     \______
-  //         ___________         _____
-  // a_ready            \_______/     \______ <- ERR though no logic malfunction
-  //                     _____________
-  // d_valid ___________/             \______
-  //                             _____
-  // d_ready ___________________/     \______
-  //
-  // Above example is fine but if r.b.r doesn't assert within two cycle, then it can be wrong.
+  assign reg_error = (devmode_i & addrmiss) | wr_err ;
 
   // Define SW related signals
   // Format: <reg>_<field>_{wd|we|qs}
@@ -145,6 +122,8 @@
   logic status_input_ready_qs;
 
   // Register instances
+
+  // Subregister 0 of Multireg key
   // R[key0]: V(False)
 
   prim_subreg #(
@@ -164,13 +143,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.key0.qe),
-    .q      (reg2hw.key0.q ),
+    .qe     (reg2hw.key[0].qe),
+    .q      (reg2hw.key[0].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 1 of Multireg key
   // R[key1]: V(False)
 
   prim_subreg #(
@@ -190,13 +169,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.key1.qe),
-    .q      (reg2hw.key1.q ),
+    .qe     (reg2hw.key[1].qe),
+    .q      (reg2hw.key[1].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 2 of Multireg key
   // R[key2]: V(False)
 
   prim_subreg #(
@@ -216,13 +195,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.key2.qe),
-    .q      (reg2hw.key2.q ),
+    .qe     (reg2hw.key[2].qe),
+    .q      (reg2hw.key[2].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 3 of Multireg key
   // R[key3]: V(False)
 
   prim_subreg #(
@@ -242,13 +221,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.key3.qe),
-    .q      (reg2hw.key3.q ),
+    .qe     (reg2hw.key[3].qe),
+    .q      (reg2hw.key[3].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 4 of Multireg key
   // R[key4]: V(False)
 
   prim_subreg #(
@@ -268,13 +247,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.key4.qe),
-    .q      (reg2hw.key4.q ),
+    .qe     (reg2hw.key[4].qe),
+    .q      (reg2hw.key[4].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 5 of Multireg key
   // R[key5]: V(False)
 
   prim_subreg #(
@@ -294,13 +273,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.key5.qe),
-    .q      (reg2hw.key5.q ),
+    .qe     (reg2hw.key[5].qe),
+    .q      (reg2hw.key[5].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 6 of Multireg key
   // R[key6]: V(False)
 
   prim_subreg #(
@@ -320,13 +299,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.key6.qe),
-    .q      (reg2hw.key6.q ),
+    .qe     (reg2hw.key[6].qe),
+    .q      (reg2hw.key[6].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 7 of Multireg key
   // R[key7]: V(False)
 
   prim_subreg #(
@@ -346,13 +325,15 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.key7.qe),
-    .q      (reg2hw.key7.q ),
+    .qe     (reg2hw.key[7].qe),
+    .q      (reg2hw.key[7].q ),
 
     .qs     ()
   );
 
 
+
+  // Subregister 0 of Multireg data_in
   // R[data_in0]: V(False)
 
   prim_subreg #(
@@ -372,13 +353,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.data_in0.qe),
-    .q      (reg2hw.data_in0.q ),
+    .qe     (reg2hw.data_in[0].qe),
+    .q      (reg2hw.data_in[0].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 1 of Multireg data_in
   // R[data_in1]: V(False)
 
   prim_subreg #(
@@ -398,13 +379,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.data_in1.qe),
-    .q      (reg2hw.data_in1.q ),
+    .qe     (reg2hw.data_in[1].qe),
+    .q      (reg2hw.data_in[1].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 2 of Multireg data_in
   // R[data_in2]: V(False)
 
   prim_subreg #(
@@ -424,13 +405,13 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.data_in2.qe),
-    .q      (reg2hw.data_in2.q ),
+    .qe     (reg2hw.data_in[2].qe),
+    .q      (reg2hw.data_in[2].q ),
 
     .qs     ()
   );
 
-
+  // Subregister 3 of Multireg data_in
   // R[data_in3]: V(False)
 
   prim_subreg #(
@@ -450,13 +431,15 @@
     .d      ('0  ),
 
     // to internal hardware
-    .qe     (reg2hw.data_in3.qe),
-    .q      (reg2hw.data_in3.q ),
+    .qe     (reg2hw.data_in[3].qe),
+    .q      (reg2hw.data_in[3].q ),
 
     .qs     ()
   );
 
 
+
+  // Subregister 0 of Multireg data_out
   // R[data_out0]: V(True)
 
   prim_subreg_ext #(
@@ -465,14 +448,14 @@
     .re     (data_out0_re),
     .we     (1'b0),
     .wd     ('0),
-    .d      (hw2reg.data_out0.d),
-    .qre    (reg2hw.data_out0.re),
+    .d      (hw2reg.data_out[0].d),
+    .qre    (reg2hw.data_out[0].re),
     .qe     (),
-    .q      (reg2hw.data_out0.q ),
+    .q      (reg2hw.data_out[0].q ),
     .qs     (data_out0_qs)
   );
 
-
+  // Subregister 1 of Multireg data_out
   // R[data_out1]: V(True)
 
   prim_subreg_ext #(
@@ -481,14 +464,14 @@
     .re     (data_out1_re),
     .we     (1'b0),
     .wd     ('0),
-    .d      (hw2reg.data_out1.d),
-    .qre    (reg2hw.data_out1.re),
+    .d      (hw2reg.data_out[1].d),
+    .qre    (reg2hw.data_out[1].re),
     .qe     (),
-    .q      (reg2hw.data_out1.q ),
+    .q      (reg2hw.data_out[1].q ),
     .qs     (data_out1_qs)
   );
 
-
+  // Subregister 2 of Multireg data_out
   // R[data_out2]: V(True)
 
   prim_subreg_ext #(
@@ -497,14 +480,14 @@
     .re     (data_out2_re),
     .we     (1'b0),
     .wd     ('0),
-    .d      (hw2reg.data_out2.d),
-    .qre    (reg2hw.data_out2.re),
+    .d      (hw2reg.data_out[2].d),
+    .qre    (reg2hw.data_out[2].re),
     .qe     (),
-    .q      (reg2hw.data_out2.q ),
+    .q      (reg2hw.data_out[2].q ),
     .qs     (data_out2_qs)
   );
 
-
+  // Subregister 3 of Multireg data_out
   // R[data_out3]: V(True)
 
   prim_subreg_ext #(
@@ -513,10 +496,10 @@
     .re     (data_out3_re),
     .we     (1'b0),
     .wd     ('0),
-    .d      (hw2reg.data_out3.d),
-    .qre    (reg2hw.data_out3.re),
+    .d      (hw2reg.data_out[3].d),
+    .qre    (reg2hw.data_out[3].re),
     .qe     (),
-    .q      (reg2hw.data_out3.q ),
+    .q      (reg2hw.data_out[3].q ),
     .qs     (data_out3_qs)
   );
 
@@ -757,19 +740,20 @@
 
 
 
+
   logic [18:0] addr_hit;
   always_comb begin
     addr_hit = '0;
-    addr_hit[0] = (reg_addr == AES_KEY0_OFFSET);
-    addr_hit[1] = (reg_addr == AES_KEY1_OFFSET);
-    addr_hit[2] = (reg_addr == AES_KEY2_OFFSET);
-    addr_hit[3] = (reg_addr == AES_KEY3_OFFSET);
-    addr_hit[4] = (reg_addr == AES_KEY4_OFFSET);
-    addr_hit[5] = (reg_addr == AES_KEY5_OFFSET);
-    addr_hit[6] = (reg_addr == AES_KEY6_OFFSET);
-    addr_hit[7] = (reg_addr == AES_KEY7_OFFSET);
-    addr_hit[8] = (reg_addr == AES_DATA_IN0_OFFSET);
-    addr_hit[9] = (reg_addr == AES_DATA_IN1_OFFSET);
+    addr_hit[ 0] = (reg_addr == AES_KEY0_OFFSET);
+    addr_hit[ 1] = (reg_addr == AES_KEY1_OFFSET);
+    addr_hit[ 2] = (reg_addr == AES_KEY2_OFFSET);
+    addr_hit[ 3] = (reg_addr == AES_KEY3_OFFSET);
+    addr_hit[ 4] = (reg_addr == AES_KEY4_OFFSET);
+    addr_hit[ 5] = (reg_addr == AES_KEY5_OFFSET);
+    addr_hit[ 6] = (reg_addr == AES_KEY6_OFFSET);
+    addr_hit[ 7] = (reg_addr == AES_KEY7_OFFSET);
+    addr_hit[ 8] = (reg_addr == AES_DATA_IN0_OFFSET);
+    addr_hit[ 9] = (reg_addr == AES_DATA_IN1_OFFSET);
     addr_hit[10] = (reg_addr == AES_DATA_IN2_OFFSET);
     addr_hit[11] = (reg_addr == AES_DATA_IN3_OFFSET);
     addr_hit[12] = (reg_addr == AES_DATA_OUT0_OFFSET);
@@ -781,50 +765,66 @@
     addr_hit[18] = (reg_addr == AES_STATUS_OFFSET);
   end
 
-  always_ff @(posedge clk_i or negedge rst_ni) begin
-    if (!rst_ni) begin
-      addrmiss <= 1'b0;
-    end else if (reg_re || reg_we) begin
-      addrmiss <= ~|addr_hit;
-    end
+  assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
+
+  // Check sub-word write is permitted
+  always_comb begin
+    wr_err = 1'b0;
+    if (addr_hit[ 0] && reg_we && (AES_PERMIT[ 0] != (AES_PERMIT[ 0] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 1] && reg_we && (AES_PERMIT[ 1] != (AES_PERMIT[ 1] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 2] && reg_we && (AES_PERMIT[ 2] != (AES_PERMIT[ 2] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 3] && reg_we && (AES_PERMIT[ 3] != (AES_PERMIT[ 3] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 4] && reg_we && (AES_PERMIT[ 4] != (AES_PERMIT[ 4] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 5] && reg_we && (AES_PERMIT[ 5] != (AES_PERMIT[ 5] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 6] && reg_we && (AES_PERMIT[ 6] != (AES_PERMIT[ 6] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 7] && reg_we && (AES_PERMIT[ 7] != (AES_PERMIT[ 7] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 8] && reg_we && (AES_PERMIT[ 8] != (AES_PERMIT[ 8] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[ 9] && reg_we && (AES_PERMIT[ 9] != (AES_PERMIT[ 9] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[10] && reg_we && (AES_PERMIT[10] != (AES_PERMIT[10] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[11] && reg_we && (AES_PERMIT[11] != (AES_PERMIT[11] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[12] && reg_we && (AES_PERMIT[12] != (AES_PERMIT[12] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[13] && reg_we && (AES_PERMIT[13] != (AES_PERMIT[13] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[14] && reg_we && (AES_PERMIT[14] != (AES_PERMIT[14] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[15] && reg_we && (AES_PERMIT[15] != (AES_PERMIT[15] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[16] && reg_we && (AES_PERMIT[16] != (AES_PERMIT[16] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[17] && reg_we && (AES_PERMIT[17] != (AES_PERMIT[17] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[18] && reg_we && (AES_PERMIT[18] != (AES_PERMIT[18] & reg_be))) wr_err = 1'b1 ;
   end
 
-  // Write Enable signal
-
-  assign key0_we = addr_hit[0] && reg_we;
+  assign key0_we = addr_hit[0] & reg_we & ~wr_err;
   assign key0_wd = reg_wdata[31:0];
 
-  assign key1_we = addr_hit[1] && reg_we;
+  assign key1_we = addr_hit[1] & reg_we & ~wr_err;
   assign key1_wd = reg_wdata[31:0];
 
-  assign key2_we = addr_hit[2] && reg_we;
+  assign key2_we = addr_hit[2] & reg_we & ~wr_err;
   assign key2_wd = reg_wdata[31:0];
 
-  assign key3_we = addr_hit[3] && reg_we;
+  assign key3_we = addr_hit[3] & reg_we & ~wr_err;
   assign key3_wd = reg_wdata[31:0];
 
-  assign key4_we = addr_hit[4] && reg_we;
+  assign key4_we = addr_hit[4] & reg_we & ~wr_err;
   assign key4_wd = reg_wdata[31:0];
 
-  assign key5_we = addr_hit[5] && reg_we;
+  assign key5_we = addr_hit[5] & reg_we & ~wr_err;
   assign key5_wd = reg_wdata[31:0];
 
-  assign key6_we = addr_hit[6] && reg_we;
+  assign key6_we = addr_hit[6] & reg_we & ~wr_err;
   assign key6_wd = reg_wdata[31:0];
 
-  assign key7_we = addr_hit[7] && reg_we;
+  assign key7_we = addr_hit[7] & reg_we & ~wr_err;
   assign key7_wd = reg_wdata[31:0];
 
-  assign data_in0_we = addr_hit[8] && reg_we;
+  assign data_in0_we = addr_hit[8] & reg_we & ~wr_err;
   assign data_in0_wd = reg_wdata[31:0];
 
-  assign data_in1_we = addr_hit[9] && reg_we;
+  assign data_in1_we = addr_hit[9] & reg_we & ~wr_err;
   assign data_in1_wd = reg_wdata[31:0];
 
-  assign data_in2_we = addr_hit[10] && reg_we;
+  assign data_in2_we = addr_hit[10] & reg_we & ~wr_err;
   assign data_in2_wd = reg_wdata[31:0];
 
-  assign data_in3_we = addr_hit[11] && reg_we;
+  assign data_in3_we = addr_hit[11] & reg_we & ~wr_err;
   assign data_in3_wd = reg_wdata[31:0];
 
   assign data_out0_re = addr_hit[12] && reg_re;
@@ -835,19 +835,19 @@
 
   assign data_out3_re = addr_hit[15] && reg_re;
 
-  assign ctrl_mode_we = addr_hit[16] && reg_we;
+  assign ctrl_mode_we = addr_hit[16] & reg_we & ~wr_err;
   assign ctrl_mode_wd = reg_wdata[0];
 
-  assign ctrl_key_len_we = addr_hit[16] && reg_we;
+  assign ctrl_key_len_we = addr_hit[16] & reg_we & ~wr_err;
   assign ctrl_key_len_wd = reg_wdata[3:1];
 
-  assign ctrl_manual_start_trigger_we = addr_hit[16] && reg_we;
+  assign ctrl_manual_start_trigger_we = addr_hit[16] & reg_we & ~wr_err;
   assign ctrl_manual_start_trigger_wd = reg_wdata[4];
 
-  assign ctrl_force_data_overwrite_we = addr_hit[16] && reg_we;
+  assign ctrl_force_data_overwrite_we = addr_hit[16] & reg_we & ~wr_err;
   assign ctrl_force_data_overwrite_wd = reg_wdata[5];
 
-  assign trigger_we = addr_hit[17] && reg_we;
+  assign trigger_we = addr_hit[17] & reg_we & ~wr_err;
   assign trigger_wd = reg_wdata[0];