[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