[aes] Add AES module

This is the first commit for the AES module. It contains the register
interface, as well as top-level and core RTL files.

Apart from the register interface, the module is not yet functional.
The functional blocks will be added with future commits.
diff --git a/hw/ip/aes/aes.core b/hw/ip/aes/aes.core
new file mode 100644
index 0000000..3725b26
--- /dev/null
+++ b/hw/ip/aes/aes.core
@@ -0,0 +1,24 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:ip:aes:0.5"
+description: "AES unit"
+filesets:
+  files_rtl:
+    depend:
+      - lowrisc:prim:all
+      - lowrisc:ip:tlul
+    files:
+      - rtl/aes_pkg.sv
+      - rtl/aes_reg_pkg.sv
+      - rtl/aes_reg_top.sv
+      - rtl/aes_core.sv
+      - rtl/aes.sv
+    file_type: systemVerilogSource
+
+targets:
+  default: &default_target
+    filesets:
+      - files_rtl
+    toplevel: aes
diff --git a/hw/ip/aes/doc/aes.hjson b/hw/ip/aes/doc/aes.hjson
new file mode 100644
index 0000000..d02db19
--- /dev/null
+++ b/hw/ip/aes/doc/aes.hjson
@@ -0,0 +1,163 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+# AES register template
+{
+  name: "aes",
+  clock_primary: "clk_fixed",
+  bus_device: "tlul",
+  regwidth: "32",
+
+  registers: [
+##############################################################################
+# initial key registers
+    { multireg: {
+      name: "KEY",
+      desc: '''
+        Initial Key Register. Loaded into the internal Full Key register upon
+        starting encryption/decryption of the next block. Can only be updated
+        when the AES unit is idle.
+      '''
+      count: 8,
+      cname: "KEY",
+      swaccess: "wo",
+      hwaccess: "hro",
+      hwqe:     "true",
+      fields: [
+        { bits: "31:0", name: "key", desc: "Initial Key" }
+      ],
+      }
+    },
+##############################################################################
+# input data registers
+    { multireg: {
+      name: "DATA_IN",
+      desc: '''
+        Input Data Register. Loaded into the internal State register upon
+        starting encryption/decryption of the next block. After that, the processor
+        can update the Input Data Register.
+      '''
+      count: 4,
+      cname: "DATA_IN",
+      swaccess: "wo",
+      hwaccess: "hro",
+      hwqe:     "true",
+      fields: [
+        { bits: "31:0", name: "data_in", desc: "Input Data" }
+      ],
+      }
+    },
+##############################################################################
+# output data registers
+    { multireg: {
+      name: "DATA_OUT",
+      desc: '''
+        Output Data Register. Holds the output data produced by the AES unit
+        during the last encryption/decryption operation. If FORCE_DATA_OVERWRITE=0
+        (see Control Register), the AES unit is stalled when the previous output
+        data has not yet been read and is about to be overwritten.
+      '''
+      count: 4,
+      cname: "DATA_OUT",
+      swaccess: "ro",
+      hwaccess: "hrw",
+      hwext:    "true",
+      hwre:     "true",
+      fields: [
+        { bits: "31:0", name: "data_out", desc: "Output Data" }
+      ],
+      }
+    },
+##############################################################################
+# control and status registers
+  { name: "CTRL",
+    desc: "Control Register",
+    swaccess: "rw",
+    hwaccess: "hro",
+    fields: [
+      { bits: "0",
+        name: "MODE",
+        desc:  '''
+          Select encryption(0) or decryption(1) operating mode of AES unit.
+        '''
+      }
+      { bits: "3:1",
+        name: "KEY_LEN",
+        resval: "1",
+        desc:  '''
+          3-bit one-hot field to select AES key length: 128 bit (3’b001), 192 bit (3’b010)
+          or 256 bit (3’b100). Invalid input values, i.e., value with multiple bits set,
+          value 3’b000, and value 3’b010 in case 192-bit keys are not supported (because
+          disabled at compile time) are mapped to 3’b001.
+        '''
+      }
+      { bits: "4",
+        name: "MANUAL_START_TRIGGER",
+        desc:  '''
+          Controls whether the AES unit should automatically start to encrypt/decrypt
+          when it receives new input data (0) or wait for separate trigger signal
+          before starting (1) (see Trigger Register).
+        '''
+      }
+      { bits: "5",
+        name: "FORCE_DATA_OVERWRITE",
+        desc:  '''
+          Control whether the AES unit is stalled during the last
+          encryption/decryption cycle if the previous output data has not yet been
+          read (0) or finishes the operation and overwrites the previous output data (1).
+        '''
+      }
+    ]
+  },
+  { name: "TRIGGER",
+    desc: "Trigger Register",
+    swaccess: "rw",
+    hwaccess: "hrw",
+    fields: [
+      { bits: "0",
+        name: "START",
+        desc:  '''
+          Keep AES unit paused (0) or trigger the encryption/decryption of one data block (1).
+        '''
+      }
+    ]
+  },
+  { name: "STATUS",
+    desc: "Status Register",
+    swaccess: "ro",
+    hwaccess: "hwo",
+    fields: [
+      { bits: "0",
+        name: "IDLE",
+        desc:  '''
+          The AES unit is idle (0) or busy (1).
+        '''
+      }
+      { bits: "1",
+        name: "STALL",
+        desc:  '''
+          The AES unit is not stalled (0) or stalled (1) because there is previous
+          output data that must be read by the processor before the AES unit can
+          overwrite this data.
+        '''
+      }
+      { bits: "2",
+        name: "OUTPUT_VALID",
+        desc:  '''
+          The AES unit has no valid output (0) or has valid output data (1).
+        '''
+      }
+      { bits: "3",
+        name: "INPUT_READY",
+        resval: "1",
+        desc:  '''
+          The AES unit is ready (1) to receive new data input via the DATA_IN registers or
+          the present values in the DATA_IN registers have not yet been loaded into the
+          module (0).
+        '''
+      }
+    ]
+  },
+  ],
+}
diff --git a/hw/ip/aes/rtl/aes.sv b/hw/ip/aes/rtl/aes.sv
new file mode 100644
index 0000000..25ae0d5
--- /dev/null
+++ b/hw/ip/aes/rtl/aes.sv
@@ -0,0 +1,41 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// AES top-level wrapper
+
+module aes #(
+  parameter bit AES192Enable = 1
+) (
+  input                     clk_i,
+  input                     rst_ni,
+
+  // Bus Interface
+  input  tlul_pkg::tl_h2d_t tl_i,
+  output tlul_pkg::tl_d2h_t tl_o
+);
+
+  import aes_reg_pkg::*;
+
+  aes_reg2hw_t reg2hw;
+  aes_hw2reg_t hw2reg;
+
+  aes_reg_top u_reg (
+    .clk_i,
+    .rst_ni,
+    .tl_i,
+    .tl_o,
+    .reg2hw,
+    .hw2reg
+  );
+
+  aes_core #(
+    .AES192Enable (AES192Enable)
+  ) aes_core (
+    .clk_i,
+    .rst_ni,
+    .reg2hw,
+    .hw2reg
+  );
+
+endmodule
diff --git a/hw/ip/aes/rtl/aes_core.sv b/hw/ip/aes/rtl/aes_core.sv
new file mode 100644
index 0000000..a60a4da
--- /dev/null
+++ b/hw/ip/aes/rtl/aes_core.sv
@@ -0,0 +1,209 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// AES core implementation
+
+module aes_core #(
+  parameter bit AES192Enable = 1
+) (
+  input                            clk_i,
+  input                            rst_ni,
+
+  // Bus Interface
+  input  aes_reg_pkg::aes_reg2hw_t reg2hw,
+  output aes_reg_pkg::aes_hw2reg_t hw2reg
+);
+
+  import aes_reg_pkg::*;
+  import aes_pkg::*;
+
+  // Types
+
+  // Signals
+  logic [31:0] data_in[4];
+  logic  [3:0] data_in_new_d, data_in_new_q;
+  logic        data_in_new;
+  logic        data_in_load;
+
+  logic [31:0] key_init[8];
+  logic  [7:0] key_init_new_d, key_init_new_q;
+  logic        key_init_new;
+  logic        dec_key_gen;
+
+  logic        force_data_overwrite;
+  logic        manual_start_trigger;
+  key_len_e    key_len;
+  logic        mode;
+  logic        start;
+
+  logic [7:0]  state_init[16];
+  logic [7:0]  state_d[16];
+  logic [7:0]  state_q[16];
+
+  logic [31:0] data_out_d[4];
+  logic [31:0] data_out_q[4];
+  logic        data_out_we;
+  logic  [3:0] data_out_read_d, data_out_read_q;
+  logic        data_out_read;
+
+  // Unused signals
+  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 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;
+
+  always_comb begin : conv_data_in_to_state
+    for (int i=0; i<4; i++) begin
+      state_init[4*i+0] = data_in[i][ 7: 0];
+      state_init[4*i+1] = data_in[i][15: 8];
+      state_init[4*i+2] = data_in[i][23:16];
+      state_init[4*i+3] = data_in[i][31:24];
+    end
+  end
+
+  assign force_data_overwrite = reg2hw.ctrl.force_data_overwrite.q;
+  assign manual_start_trigger = reg2hw.ctrl.manual_start_trigger.q;
+  assign mode                 = reg2hw.ctrl.mode.q;
+  assign start                = reg2hw.trigger.q;
+
+  always_comb begin : get_key_len
+    unique case (key_len_e'(reg2hw.ctrl.key_len.q))
+      AES_128: key_len   = AES_128;
+      AES_256: key_len   = AES_256;
+      AES_192: begin
+        key_len = AES192Enable ? AES_192 : AES_128;
+      end
+      default: key_len   = AES_128; // unsupported values are mapped to AES_128
+    endcase
+  end
+
+  // 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;
+
+  // Core modules
+
+  // State registers
+  assign state_d = data_in_load ? state_init : state_q;
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin : reg_state
+    if (!rst_ni) begin
+      state_q <= '{default: '0};
+    end else begin
+      state_q <= state_d;
+    end
+  end
+
+  // Detect new key, new input, output read
+  // Edge detectors are cleared by the FSM
+  assign key_init_new_d = dec_key_gen ? '0 : key_init_new_q |
+      {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_new = &key_init_new_d;
+
+  assign data_in_new_d = data_in_load ? '0 : data_in_new_q |
+      {reg2hw.data_in3.qe, reg2hw.data_in2.qe, reg2hw.data_in1.qe, reg2hw.data_in0.qe};
+  assign data_in_new = &data_in_new_d;
+
+  assign data_out_read_d = data_out_we ? '0 : data_out_read_q |
+      {reg2hw.data_out3.re, reg2hw.data_out2.re, reg2hw.data_out1.re, reg2hw.data_out0.re};
+  assign data_out_read = &data_out_read_d;
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin : reg_edge_detection
+    if (!rst_ni) begin
+      key_init_new_q  <= '0;
+      data_in_new_q   <= '0;
+      data_out_read_q <= '0;
+    end else begin
+      key_init_new_q  <= key_init_new_d;
+      data_in_new_q   <= data_in_new_d;
+      data_out_read_q <= data_out_read_d;
+    end
+  end
+
+  // Control FSM
+  assign dec_key_gen  = 1'b0;
+  assign data_in_load = 1'b0;
+  assign data_out_we  = 1'b0;
+
+  // placeholders
+  logic     unused_force_data_overwrite;
+  logic     unused_manual_start_trigger;
+  key_len_e unused_key_len;
+  logic     unused_mode;
+  logic     unused_start;
+  assign unused_force_data_overwrite = force_data_overwrite;
+  assign unused_manual_start_trigger = manual_start_trigger;
+  assign unused_key_len              = key_len;
+  assign unused_mode                 = mode;
+  assign unused_start                = start;
+  logic unused_data_in_new;
+  logic unused_key_init_new;
+  logic unused_data_out_read;
+  assign unused_data_in_new   = data_in_new;
+  assign unused_key_init_new  = key_init_new;
+  assign unused_data_out_read = data_out_read;
+  logic [31:0] unused_key_init[8];
+  assign unused_key_init[0] = key_init[0];
+  assign unused_key_init[1] = key_init[1];
+  assign unused_key_init[2] = key_init[2];
+  assign unused_key_init[3] = key_init[3];
+  assign unused_key_init[4] = key_init[4];
+  assign unused_key_init[5] = key_init[5];
+  assign unused_key_init[6] = key_init[6];
+  assign unused_key_init[7] = key_init[7];
+
+  // Output registers
+  always_comb begin : conv_state_to_data_out
+    for (int i=0; i<4; i++) begin
+      data_out_d[i] = {state_q[4*i+3], state_q[4*i+2], state_q[4*i+1], state_q[4*i+0]};
+    end
+  end
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin : reg_data_out
+    if (!rst_ni) begin
+      data_out_q <= '{default: '0};
+    end else if (data_out_we) begin
+      data_out_q <= data_out_d;
+    end
+  end
+
+  // 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.trigger.d   = 1'b0;
+  assign hw2reg.trigger.de  = 1'b1;
+
+  assign hw2reg.status.idle.d   = 1'b0;
+  assign hw2reg.status.idle.de  = 1'b1;
+  assign hw2reg.status.stall.d  = 1'b0;
+  assign hw2reg.status.stall.de = 1'b1;
+
+  // clear once all output regs have been read
+  assign hw2reg.status.output_valid.d  = data_out_we;
+  assign hw2reg.status.output_valid.de = data_out_we | data_out_read;
+
+  // clear once all input regs have been written
+  assign hw2reg.status.input_ready.d   = ~data_in_new;
+  assign hw2reg.status.input_ready.de  =  data_in_new | data_in_load;
+
+endmodule
diff --git a/hw/ip/aes/rtl/aes_pkg.sv b/hw/ip/aes/rtl/aes_pkg.sv
new file mode 100644
index 0000000..48ddb30
--- /dev/null
+++ b/hw/ip/aes/rtl/aes_pkg.sv
@@ -0,0 +1,15 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// AES package
+
+package aes_pkg;
+
+typedef enum logic [2:0] {
+  AES_128 = 3'b001,
+  AES_192 = 3'b010,
+  AES_256 = 3'b100
+} key_len_e;
+
+endpackage
diff --git a/hw/ip/aes/rtl/aes_reg_pkg.sv b/hw/ip/aes/rtl/aes_reg_pkg.sv
new file mode 100644
index 0000000..2f94b26
--- /dev/null
+++ b/hw/ip/aes/rtl/aes_reg_pkg.sv
@@ -0,0 +1,156 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Register Package auto-generated by `reggen` containing data structure
+
+package aes_reg_pkg;
+
+// Register to internal design logic
+typedef struct packed {
+
+  struct packed {
+    logic [31:0] q; // [534:503]
+    logic qe; // [502]
+  } key0;
+  struct packed {
+    logic [31:0] q; // [501:470]
+    logic qe; // [469]
+  } key1;
+  struct packed {
+    logic [31:0] q; // [468:437]
+    logic qe; // [436]
+  } key2;
+  struct packed {
+    logic [31:0] q; // [435:404]
+    logic qe; // [403]
+  } key3;
+  struct packed {
+    logic [31:0] q; // [402:371]
+    logic qe; // [370]
+  } key4;
+  struct packed {
+    logic [31:0] q; // [369:338]
+    logic qe; // [337]
+  } key5;
+  struct packed {
+    logic [31:0] q; // [336:305]
+    logic qe; // [304]
+  } key6;
+  struct packed {
+    logic [31:0] q; // [303:272]
+    logic qe; // [271]
+  } key7;
+  struct packed {
+    logic [31:0] q; // [270:239]
+    logic qe; // [238]
+  } data_in0;
+  struct packed {
+    logic [31:0] q; // [237:206]
+    logic qe; // [205]
+  } data_in1;
+  struct packed {
+    logic [31:0] q; // [204:173]
+    logic qe; // [172]
+  } data_in2;
+  struct packed {
+    logic [31:0] q; // [171:140]
+    logic qe; // [139]
+  } data_in3;
+  struct packed {
+    logic [31:0] q; // [138:107]
+    logic re; // [106]
+  } data_out0;
+  struct packed {
+    logic [31:0] q; // [105:74]
+    logic re; // [73]
+  } data_out1;
+  struct packed {
+    logic [31:0] q; // [72:41]
+    logic re; // [40]
+  } data_out2;
+  struct packed {
+    logic [31:0] q; // [39:8]
+    logic re; // [7]
+  } data_out3;
+  struct packed {
+    struct packed {
+      logic q; // [6]
+    } mode;
+    struct packed {
+      logic [2:0] q; // [5:3]
+    } key_len;
+    struct packed {
+      logic q; // [2]
+    } manual_start_trigger;
+    struct packed {
+      logic q; // [1]
+    } force_data_overwrite;
+  } ctrl;
+  struct packed {
+    logic [0:0] q; // [0:0]
+  } trigger;
+} aes_reg2hw_t;
+
+// Internal design logic to register
+typedef struct packed {
+
+  struct packed {
+    logic [31:0] d; // [137:106]
+  } data_out0;
+  struct packed {
+    logic [31:0] d; // [105:74]
+  } data_out1;
+  struct packed {
+    logic [31:0] d; // [73:42]
+  } data_out2;
+  struct packed {
+    logic [31:0] d; // [41:10]
+  } data_out3;
+  struct packed {
+    logic [0:0] d; // [9:9]
+    logic de; // [8]
+  } trigger;
+  struct packed {
+    struct packed {
+      logic d;  // [7]
+      logic de; // [6]
+    } idle;
+    struct packed {
+      logic d;  // [5]
+      logic de; // [4]
+    } stall;
+    struct packed {
+      logic d;  // [3]
+      logic de; // [2]
+    } output_valid;
+    struct packed {
+      logic d;  // [1]
+      logic de; // [0]
+    } input_ready;
+  } status;
+} aes_hw2reg_t;
+
+  // Register Address
+  parameter AES_KEY0_OFFSET = 7'h 0;
+  parameter AES_KEY1_OFFSET = 7'h 4;
+  parameter AES_KEY2_OFFSET = 7'h 8;
+  parameter AES_KEY3_OFFSET = 7'h c;
+  parameter AES_KEY4_OFFSET = 7'h 10;
+  parameter AES_KEY5_OFFSET = 7'h 14;
+  parameter AES_KEY6_OFFSET = 7'h 18;
+  parameter AES_KEY7_OFFSET = 7'h 1c;
+  parameter AES_DATA_IN0_OFFSET = 7'h 20;
+  parameter AES_DATA_IN1_OFFSET = 7'h 24;
+  parameter AES_DATA_IN2_OFFSET = 7'h 28;
+  parameter AES_DATA_IN3_OFFSET = 7'h 2c;
+  parameter AES_DATA_OUT0_OFFSET = 7'h 30;
+  parameter AES_DATA_OUT1_OFFSET = 7'h 34;
+  parameter AES_DATA_OUT2_OFFSET = 7'h 38;
+  parameter AES_DATA_OUT3_OFFSET = 7'h 3c;
+  parameter AES_CTRL_OFFSET = 7'h 40;
+  parameter AES_TRIGGER_OFFSET = 7'h 44;
+  parameter AES_STATUS_OFFSET = 7'h 48;
+
+
+endpackage
diff --git a/hw/ip/aes/rtl/aes_reg_top.sv b/hw/ip/aes/rtl/aes_reg_top.sv
new file mode 100644
index 0000000..bd9e344
--- /dev/null
+++ b/hw/ip/aes/rtl/aes_reg_top.sv
@@ -0,0 +1,959 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Register Top module auto-generated by `reggen`
+
+
+module aes_reg_top (
+  input clk_i,
+  input rst_ni,
+
+  // Below Regster interface can be changed
+  input  tlul_pkg::tl_h2d_t tl_i,
+  output tlul_pkg::tl_d2h_t tl_o,
+  // To HW
+  output aes_reg_pkg::aes_reg2hw_t reg2hw, // Write
+  input  aes_reg_pkg::aes_hw2reg_t hw2reg  // Read
+);
+
+  import aes_reg_pkg::* ;
+
+  localparam AW = 7;
+  localparam DW = 32;
+  localparam DBW = DW/8;                    // Byte Width
+
+  // register signals
+  logic           reg_we;
+  logic           reg_re;
+  logic [AW-1:0]  reg_addr;
+  logic [DW-1:0]  reg_wdata;
+  logic [DBW-1:0] reg_be;
+  logic [DW-1:0]  reg_rdata;
+  logic           reg_error;
+
+  logic          malformed, addrmiss;
+
+  logic [DW-1:0] reg_rdata_next;
+
+  tlul_pkg::tl_h2d_t tl_reg_h2d;
+  tlul_pkg::tl_d2h_t tl_reg_d2h;
+
+  assign tl_reg_h2d = tl_i;
+  assign tl_o       = tl_reg_d2h;
+
+  tlul_adapter_reg #(
+    .RegAw(AW),
+    .RegDw(DW)
+  ) u_reg_if (
+    .clk_i,
+    .rst_ni,
+
+    .tl_i (tl_reg_h2d),
+    .tl_o (tl_reg_d2h),
+
+    .we_o    (reg_we),
+    .re_o    (reg_re),
+    .addr_o  (reg_addr),
+    .wdata_o (reg_wdata),
+    .be_o    (reg_be),
+    .rdata_i (reg_rdata),
+    .error_i (reg_error)
+  );
+
+  assign reg_rdata = reg_rdata_next ;
+  assign reg_error = 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.
+
+  // Define SW related signals
+  // Format: <reg>_<field>_{wd|we|qs}
+  //        or <reg>_{wd|we|qs} if field == 1 or 0
+  logic [31:0] key0_wd;
+  logic key0_we;
+  logic [31:0] key1_wd;
+  logic key1_we;
+  logic [31:0] key2_wd;
+  logic key2_we;
+  logic [31:0] key3_wd;
+  logic key3_we;
+  logic [31:0] key4_wd;
+  logic key4_we;
+  logic [31:0] key5_wd;
+  logic key5_we;
+  logic [31:0] key6_wd;
+  logic key6_we;
+  logic [31:0] key7_wd;
+  logic key7_we;
+  logic [31:0] data_in0_wd;
+  logic data_in0_we;
+  logic [31:0] data_in1_wd;
+  logic data_in1_we;
+  logic [31:0] data_in2_wd;
+  logic data_in2_we;
+  logic [31:0] data_in3_wd;
+  logic data_in3_we;
+  logic [31:0] data_out0_qs;
+  logic data_out0_re;
+  logic [31:0] data_out1_qs;
+  logic data_out1_re;
+  logic [31:0] data_out2_qs;
+  logic data_out2_re;
+  logic [31:0] data_out3_qs;
+  logic data_out3_re;
+  logic ctrl_mode_qs;
+  logic ctrl_mode_wd;
+  logic ctrl_mode_we;
+  logic [2:0] ctrl_key_len_qs;
+  logic [2:0] ctrl_key_len_wd;
+  logic ctrl_key_len_we;
+  logic ctrl_manual_start_trigger_qs;
+  logic ctrl_manual_start_trigger_wd;
+  logic ctrl_manual_start_trigger_we;
+  logic ctrl_force_data_overwrite_qs;
+  logic ctrl_force_data_overwrite_wd;
+  logic ctrl_force_data_overwrite_we;
+  logic trigger_qs;
+  logic trigger_wd;
+  logic trigger_we;
+  logic status_idle_qs;
+  logic status_stall_qs;
+  logic status_output_valid_qs;
+  logic status_input_ready_qs;
+
+  // Register instances
+  // R[key0]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_key0 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (key0_we),
+    .wd     (key0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.key0.qe),
+    .q      (reg2hw.key0.q ),
+
+    .qs     ()
+  );
+
+
+  // R[key1]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_key1 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (key1_we),
+    .wd     (key1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.key1.qe),
+    .q      (reg2hw.key1.q ),
+
+    .qs     ()
+  );
+
+
+  // R[key2]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_key2 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (key2_we),
+    .wd     (key2_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.key2.qe),
+    .q      (reg2hw.key2.q ),
+
+    .qs     ()
+  );
+
+
+  // R[key3]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_key3 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (key3_we),
+    .wd     (key3_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.key3.qe),
+    .q      (reg2hw.key3.q ),
+
+    .qs     ()
+  );
+
+
+  // R[key4]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_key4 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (key4_we),
+    .wd     (key4_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.key4.qe),
+    .q      (reg2hw.key4.q ),
+
+    .qs     ()
+  );
+
+
+  // R[key5]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_key5 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (key5_we),
+    .wd     (key5_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.key5.qe),
+    .q      (reg2hw.key5.q ),
+
+    .qs     ()
+  );
+
+
+  // R[key6]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_key6 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (key6_we),
+    .wd     (key6_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.key6.qe),
+    .q      (reg2hw.key6.q ),
+
+    .qs     ()
+  );
+
+
+  // R[key7]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_key7 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (key7_we),
+    .wd     (key7_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.key7.qe),
+    .q      (reg2hw.key7.q ),
+
+    .qs     ()
+  );
+
+
+  // R[data_in0]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_data_in0 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (data_in0_we),
+    .wd     (data_in0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.data_in0.qe),
+    .q      (reg2hw.data_in0.q ),
+
+    .qs     ()
+  );
+
+
+  // R[data_in1]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_data_in1 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (data_in1_we),
+    .wd     (data_in1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.data_in1.qe),
+    .q      (reg2hw.data_in1.q ),
+
+    .qs     ()
+  );
+
+
+  // R[data_in2]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_data_in2 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (data_in2_we),
+    .wd     (data_in2_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.data_in2.qe),
+    .q      (reg2hw.data_in2.q ),
+
+    .qs     ()
+  );
+
+
+  // R[data_in3]: V(False)
+
+  prim_subreg #(
+    .DW      (32),
+    .SWACCESS("WO"),
+    .RESVAL  (32'h0)
+  ) u_data_in3 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (data_in3_we),
+    .wd     (data_in3_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (reg2hw.data_in3.qe),
+    .q      (reg2hw.data_in3.q ),
+
+    .qs     ()
+  );
+
+
+  // R[data_out0]: V(True)
+
+  prim_subreg_ext #(
+    .DW    (32)
+  ) u_data_out0 (
+    .re     (data_out0_re),
+    .we     (1'b0),
+    .wd     ('0),
+    .d      (hw2reg.data_out0.d),
+    .qre    (reg2hw.data_out0.re),
+    .qe     (),
+    .q      (reg2hw.data_out0.q ),
+    .qs     (data_out0_qs)
+  );
+
+
+  // R[data_out1]: V(True)
+
+  prim_subreg_ext #(
+    .DW    (32)
+  ) u_data_out1 (
+    .re     (data_out1_re),
+    .we     (1'b0),
+    .wd     ('0),
+    .d      (hw2reg.data_out1.d),
+    .qre    (reg2hw.data_out1.re),
+    .qe     (),
+    .q      (reg2hw.data_out1.q ),
+    .qs     (data_out1_qs)
+  );
+
+
+  // R[data_out2]: V(True)
+
+  prim_subreg_ext #(
+    .DW    (32)
+  ) u_data_out2 (
+    .re     (data_out2_re),
+    .we     (1'b0),
+    .wd     ('0),
+    .d      (hw2reg.data_out2.d),
+    .qre    (reg2hw.data_out2.re),
+    .qe     (),
+    .q      (reg2hw.data_out2.q ),
+    .qs     (data_out2_qs)
+  );
+
+
+  // R[data_out3]: V(True)
+
+  prim_subreg_ext #(
+    .DW    (32)
+  ) u_data_out3 (
+    .re     (data_out3_re),
+    .we     (1'b0),
+    .wd     ('0),
+    .d      (hw2reg.data_out3.d),
+    .qre    (reg2hw.data_out3.re),
+    .qe     (),
+    .q      (reg2hw.data_out3.q ),
+    .qs     (data_out3_qs)
+  );
+
+
+  // R[ctrl]: V(False)
+
+  //   F[mode]: 0:0
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_ctrl_mode (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (ctrl_mode_we),
+    .wd     (ctrl_mode_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ctrl.mode.q ),
+
+    // to register interface (read)
+    .qs     (ctrl_mode_qs)
+  );
+
+
+  //   F[key_len]: 3:1
+  prim_subreg #(
+    .DW      (3),
+    .SWACCESS("RW"),
+    .RESVAL  (3'h1)
+  ) u_ctrl_key_len (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (ctrl_key_len_we),
+    .wd     (ctrl_key_len_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ctrl.key_len.q ),
+
+    // to register interface (read)
+    .qs     (ctrl_key_len_qs)
+  );
+
+
+  //   F[manual_start_trigger]: 4:4
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_ctrl_manual_start_trigger (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (ctrl_manual_start_trigger_we),
+    .wd     (ctrl_manual_start_trigger_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ctrl.manual_start_trigger.q ),
+
+    // to register interface (read)
+    .qs     (ctrl_manual_start_trigger_qs)
+  );
+
+
+  //   F[force_data_overwrite]: 5:5
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_ctrl_force_data_overwrite (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (ctrl_force_data_overwrite_we),
+    .wd     (ctrl_force_data_overwrite_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.ctrl.force_data_overwrite.q ),
+
+    // to register interface (read)
+    .qs     (ctrl_force_data_overwrite_qs)
+  );
+
+
+  // R[trigger]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_trigger (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (trigger_we),
+    .wd     (trigger_wd),
+
+    // from internal hardware
+    .de     (hw2reg.trigger.de),
+    .d      (hw2reg.trigger.d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.trigger.q ),
+
+    // to register interface (read)
+    .qs     (trigger_qs)
+  );
+
+
+  // R[status]: V(False)
+
+  //   F[idle]: 0:0
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RO"),
+    .RESVAL  (1'h0)
+  ) u_status_idle (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    .we     (1'b0),
+    .wd     ('0  ),
+
+    // from internal hardware
+    .de     (hw2reg.status.idle.de),
+    .d      (hw2reg.status.idle.d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (status_idle_qs)
+  );
+
+
+  //   F[stall]: 1:1
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RO"),
+    .RESVAL  (1'h0)
+  ) u_status_stall (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    .we     (1'b0),
+    .wd     ('0  ),
+
+    // from internal hardware
+    .de     (hw2reg.status.stall.de),
+    .d      (hw2reg.status.stall.d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (status_stall_qs)
+  );
+
+
+  //   F[output_valid]: 2:2
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RO"),
+    .RESVAL  (1'h0)
+  ) u_status_output_valid (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    .we     (1'b0),
+    .wd     ('0  ),
+
+    // from internal hardware
+    .de     (hw2reg.status.output_valid.de),
+    .d      (hw2reg.status.output_valid.d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (status_output_valid_qs)
+  );
+
+
+  //   F[input_ready]: 3:3
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RO"),
+    .RESVAL  (1'h1)
+  ) u_status_input_ready (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    .we     (1'b0),
+    .wd     ('0  ),
+
+    // from internal hardware
+    .de     (hw2reg.status.input_ready.de),
+    .d      (hw2reg.status.input_ready.d ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (),
+
+    // to register interface (read)
+    .qs     (status_input_ready_qs)
+  );
+
+
+
+  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[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);
+    addr_hit[13] = (reg_addr == AES_DATA_OUT1_OFFSET);
+    addr_hit[14] = (reg_addr == AES_DATA_OUT2_OFFSET);
+    addr_hit[15] = (reg_addr == AES_DATA_OUT3_OFFSET);
+    addr_hit[16] = (reg_addr == AES_CTRL_OFFSET);
+    addr_hit[17] = (reg_addr == AES_TRIGGER_OFFSET);
+    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
+  end
+
+  // Write Enable signal
+
+  assign key0_we = addr_hit[0] && reg_we;
+  assign key0_wd = reg_wdata[31:0];
+
+  assign key1_we = addr_hit[1] && reg_we;
+  assign key1_wd = reg_wdata[31:0];
+
+  assign key2_we = addr_hit[2] && reg_we;
+  assign key2_wd = reg_wdata[31:0];
+
+  assign key3_we = addr_hit[3] && reg_we;
+  assign key3_wd = reg_wdata[31:0];
+
+  assign key4_we = addr_hit[4] && reg_we;
+  assign key4_wd = reg_wdata[31:0];
+
+  assign key5_we = addr_hit[5] && reg_we;
+  assign key5_wd = reg_wdata[31:0];
+
+  assign key6_we = addr_hit[6] && reg_we;
+  assign key6_wd = reg_wdata[31:0];
+
+  assign key7_we = addr_hit[7] && reg_we;
+  assign key7_wd = reg_wdata[31:0];
+
+  assign data_in0_we = addr_hit[8] && reg_we;
+  assign data_in0_wd = reg_wdata[31:0];
+
+  assign data_in1_we = addr_hit[9] && reg_we;
+  assign data_in1_wd = reg_wdata[31:0];
+
+  assign data_in2_we = addr_hit[10] && reg_we;
+  assign data_in2_wd = reg_wdata[31:0];
+
+  assign data_in3_we = addr_hit[11] && reg_we;
+  assign data_in3_wd = reg_wdata[31:0];
+
+  assign data_out0_re = addr_hit[12] && reg_re;
+
+  assign data_out1_re = addr_hit[13] && reg_re;
+
+  assign data_out2_re = addr_hit[14] && reg_re;
+
+  assign data_out3_re = addr_hit[15] && reg_re;
+
+  assign ctrl_mode_we = addr_hit[16] && reg_we;
+  assign ctrl_mode_wd = reg_wdata[0];
+
+  assign ctrl_key_len_we = addr_hit[16] && reg_we;
+  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_wd = reg_wdata[4];
+
+  assign ctrl_force_data_overwrite_we = addr_hit[16] && reg_we;
+  assign ctrl_force_data_overwrite_wd = reg_wdata[5];
+
+  assign trigger_we = addr_hit[17] && reg_we;
+  assign trigger_wd = reg_wdata[0];
+
+
+
+
+
+  // Read data return
+  always_comb begin
+    reg_rdata_next = '0;
+    unique case (1'b1)
+      addr_hit[0]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[1]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[2]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[3]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[4]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[5]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[6]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[7]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[8]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[9]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[10]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[11]: begin
+        reg_rdata_next[31:0] = '0;
+      end
+
+      addr_hit[12]: begin
+        reg_rdata_next[31:0] = data_out0_qs;
+      end
+
+      addr_hit[13]: begin
+        reg_rdata_next[31:0] = data_out1_qs;
+      end
+
+      addr_hit[14]: begin
+        reg_rdata_next[31:0] = data_out2_qs;
+      end
+
+      addr_hit[15]: begin
+        reg_rdata_next[31:0] = data_out3_qs;
+      end
+
+      addr_hit[16]: begin
+        reg_rdata_next[0] = ctrl_mode_qs;
+        reg_rdata_next[3:1] = ctrl_key_len_qs;
+        reg_rdata_next[4] = ctrl_manual_start_trigger_qs;
+        reg_rdata_next[5] = ctrl_force_data_overwrite_qs;
+      end
+
+      addr_hit[17]: begin
+        reg_rdata_next[0] = trigger_qs;
+      end
+
+      addr_hit[18]: begin
+        reg_rdata_next[0] = status_idle_qs;
+        reg_rdata_next[1] = status_stall_qs;
+        reg_rdata_next[2] = status_output_valid_qs;
+        reg_rdata_next[3] = status_input_ready_qs;
+      end
+
+      default: begin
+        reg_rdata_next = '1;
+      end
+    endcase
+  end
+
+  // Assertions for Register Interface
+  `ASSERT_PULSE(wePulse, reg_we, clk_i, !rst_ni)
+  `ASSERT_PULSE(rePulse, reg_re, clk_i, !rst_ni)
+
+  `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o.d_valid, clk_i, !rst_ni)
+
+  `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), clk_i, !rst_ni)
+
+  `ASSERT(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.parity_en == 1'b0, clk_i, !rst_ni)
+
+endmodule