[aes:dv] Rework of aes DV

  Reworked scoreboard to support CTR and CBC modes better
  Added new Tests and removed sanity sequence
  which is now using stress_vseq

Signed-off-by: Rasmus Madsen <rasmus.madsen@wdc.com>
diff --git a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv
index 15ca238..653d652 100644
--- a/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv
+++ b/hw/ip/aes/dv/aes_model_dpi/aes_model_dpi_pkg.sv
@@ -74,6 +74,5 @@
     c_dpi_aes_crypt_block(impl_i, op_i, mode_i, iv_in, key_len_i, key_i, data_in, data_out);
     data_o  = aes_transpose(data_out);
     return;
-  endfunction
-
+  endfunction // sv_dpi_aes_crypt_block
 endpackage
diff --git a/hw/ip/aes/dv/aes_sim_cfg.hjson b/hw/ip/aes/dv/aes_sim_cfg.hjson
index 95d7383..8f006b4 100644
--- a/hw/ip/aes/dv/aes_sim_cfg.hjson
+++ b/hw/ip/aes/dv/aes_sim_cfg.hjson
@@ -57,13 +57,20 @@
   tests: [
     {
       name: aes_wake_up
+      uvm_test: aes_wake_up_test
       uvm_test_seq: aes_wake_up_vseq
       reseed: 1
     }
 
     {
       name: aes_sanity
-      uvm_test_seq: aes_sanity_vseq
+      uvm_test: aes_sanity_test
+      uvm_test_seq: aes_stress_vseq
+    }
+    {
+      name: aes_stress
+      uvm_test: aes_stress_test
+      uvm_test_seq: aes_stress_vseq
     }
   ]
 
@@ -73,5 +80,9 @@
       name: sanity
       tests: ["aes_sanity"]
     }
+     {
+      name: stress
+      tests: ["aes_stress"]
+    }
   ]
 }
diff --git a/hw/ip/aes/dv/env/aes_env.core b/hw/ip/aes/dv/env/aes_env.core
index a60f994..636bf8b 100644
--- a/hw/ip/aes/dv/env/aes_env.core
+++ b/hw/ip/aes/dv/env/aes_env.core
@@ -17,6 +17,7 @@
     files:
       - aes_env_pkg.sv
       - aes_seq_item.sv: {is_include_file: true}
+      - aes_message_item.sv: {is_include_file: true}
       - aes_env_cfg.sv: {is_include_file: true}
       - aes_env_cov.sv: {is_include_file: true}
       - aes_virtual_sequencer.sv: {is_include_file: true}
@@ -26,7 +27,7 @@
       - seq_lib/aes_base_vseq.sv: {is_include_file: true}
       - seq_lib/aes_common_vseq.sv: {is_include_file: true}
       - seq_lib/aes_wake_up_vseq.sv: {is_include_file: true}
-      - seq_lib/aes_sanity_vseq.sv: {is_include_file: true}
+      - seq_lib/aes_stress_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
 generate:
diff --git a/hw/ip/aes/dv/env/aes_env_cfg.sv b/hw/ip/aes/dv/env/aes_env_cfg.sv
index be8ffbf..888780a 100644
--- a/hw/ip/aes/dv/env/aes_env_cfg.sv
+++ b/hw/ip/aes/dv/env/aes_env_cfg.sv
@@ -10,20 +10,42 @@
   `uvm_object_new
 
   // Knobs //
-  int          data_len_min    = 128;
-  int          data_len_max    = 128;
-  bit          use_key_mask    = 0;
-  bit          use_c_model_pct = 0;
+  int          num_messages_min   = 1;
+  int          num_messages_max   = 1;
+  int          message_len_min    = 128;
+  int          message_len_max    = 128;
+  bit          use_key_mask       = 0;
+  bit          use_c_model_pct    = 0;
+  bit          errors_en          = 0;
+  // Mode distribution //
+  // chance of selection ecb_mode
+  // ecb_mode /(ecb_mode + cbc_mode + ctr_mode)
+  // with the defaults 10/30 = 1/3 (33%)
+  int          ecb_weight         = 10;
+  int          cbc_weight         = 10;
+  int          ctr_weight         = 10;
+  // KEYLEN weights
+  // change of selecting 128b key
+  //  128b/(128+192+256) = 10/30 = (33%)
+  int          key_128b_weight    = 10;
+  int          key_192b_weight    = 10;
+  int          key_256b_weight    = 10;
 
+  bit  [2:0]   error_types        = 3'b111;      //   001: configuration errors
+                                                 //   010: malicous injection
+                                                 //   100: random resets
 
+  int          config_error_pct;                 // percentage of configuration errors
   // rand variables
   rand bit     ref_model;                        // 0: C model 1: OPEN_SSL/BORING_SSL
   rand bit     key_mask;                         // randomly select if we force unused key bits to 0
+  rand int     num_messages;                     // number of messages to encrypt/decrypt
 
-  // constraints
-  constraint c_ref_model { ref_model dist { 0 :/ use_c_model_pct,
-                                            1 :/ (100-use_c_model_pct) }; }
 
+   // constraints
+  constraint c_num_messages { num_messages inside {[num_messages_min : num_messages_max] };}
+  constraint c_ref_model    { ref_model    dist   { 0 :/ use_c_model_pct,
+                                                    1 :/ (100-use_c_model_pct) }; }
 
   function void post_randomize();
     if(use_key_mask) key_mask = 1;
@@ -33,11 +55,17 @@
   virtual function string convert2string();
     string str = "";
     str = super.convert2string();
-    str = {str,  $psprintf("\n\t ----| AES ENVIRONMENT CONFIG \t ") };
-    str = {str,  $psprintf("\n\t ----| Max data len %d bits \t ", data_len_max) };
-    str = {str,  $psprintf("\n\t ----| Min data len %d bits \t ", data_len_min) };
-    str = {str,  $psprintf("\n\t ----| Reference model:\t    %s              \t ",
-          (ref_model==0) ? "C-MODEL" : "OPEN_SSL" ) };
+    str = {str,  $sformatf("\n\t ----| AES ENVIRONMENT CONFIG \t ") };
+    str = {str,  $sformatf("\n\t ----| Max Number of message %d \t ", num_messages_max) };
+    str = {str,  $sformatf("\n\t ----| Min Number of message %d \t ", num_messages_min) };
+    str = {str,  $sformatf("\n\t ----| Max message len %d bytes \t ", message_len_max) };
+    str = {str,  $sformatf("\n\t ----| Min message len %d bytes \t ", message_len_min) };
+    str = {str,  $sformatf("\n\t ----| Reference model:\t    %s              \t ",
+         (ref_model==0) ? "C-MODEL" : "OPEN_SSL" ) };
+    str = {str,  $sformatf("\n\t ----| num_messages # %d \t ", num_messages) };
+    str = {str,  $sformatf("\n\t ----| ECB Weight: %d         \t ", ecb_weight) };
+    str = {str,  $sformatf("\n\t ----| CBC Weight: %d         \t ", cbc_weight) };   
+    str = {str,  $sformatf("\n\t ----| CTR Weight: %d         \t ", ctr_weight) }; 
     str = {str, "\n"};
     return str;
   endfunction
diff --git a/hw/ip/aes/dv/env/aes_env_pkg.sv b/hw/ip/aes/dv/env/aes_env_pkg.sv
index 5afc8b8..4fef4e9 100644
--- a/hw/ip/aes/dv/env/aes_env_pkg.sv
+++ b/hw/ip/aes/dv/env/aes_env_pkg.sv
@@ -13,6 +13,8 @@
   import cip_base_pkg::*;
   import aes_reg_pkg::*;
   import aes_ral_pkg::*;
+  import aes_pkg::*;
+
 
   // macro includes
   `include "uvm_macros.svh"
@@ -20,17 +22,16 @@
 
   // parameters
 
-   parameter uint AES_ADDR_MAP_SIZE      = 128;
-  // types
-  // forward declare classes to allow typedefs below
-  typedef class aes_env_cfg;
-  typedef class aes_env_cov;
+  parameter uint AES_ADDR_MAP_SIZE      = 128;
+
+  typedef enum int { AES_CFG=0, AES_DATA=1, AES_ERR_INJ=2 } aes_item_type_e;
 
   // functions
 
   // package sources
  `include "aes_env_cfg.sv"
  `include "aes_seq_item.sv"
+ `include "aes_message_item.sv"
  `include "aes_env_cov.sv"
  `include "aes_virtual_sequencer.sv"
  `include "aes_scoreboard.sv"
diff --git a/hw/ip/aes/dv/env/aes_message_item.sv b/hw/ip/aes/dv/env/aes_message_item.sv
new file mode 100644
index 0000000..a0294ff
--- /dev/null
+++ b/hw/ip/aes/dv/env/aes_message_item.sv
@@ -0,0 +1,182 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class aes_message_item extends uvm_sequence_item;
+
+  `uvm_object_utils(aes_message_item)
+
+  `uvm_object_new
+
+  ///////////////////////////////////////
+  //  control Knobs                    //
+  ///////////////////////////////////////
+
+  // min number of data bytes
+  int    message_len_max     = 16;
+  // Max number of data bytes
+  int    message_len_min     = 1;
+  // percentage of configuration errors
+  int    config_error_pct    = 20;
+  // errors enabled
+  bit    errors_en           = 1;
+  // configuraiton errors enabled
+  bit    config_err          = 0;
+
+  // Mode distribution //
+  // chance of selection ecb_mode
+  // ecb_mode /(ecb_mode + cbc_mode + ctr_mode)
+  // with the defaults 10/30 = 1/3 (33%)
+  int    ecb_weight          = 10;
+  int    cbc_weight          = 10;
+  int    ctr_weight          = 10;
+  // KEYLEN weights
+  int    key_128b_weight     = 10;
+  int    key_192b_weight     = 10;
+  int    key_256b_weight     = 10;
+
+  ///////////////////////////////////////
+  // Randomizable variables            //
+  ///////////////////////////////////////
+
+  // length of the message                                     //
+  rand int             message_length;
+  // mode - which type of ecnryption is used                   //
+  rand aes_mode_e      aes_mode;
+  // operation - encruption or decryption                      //
+  rand aes_op_e        aes_operation;
+  // aes key length                                            //
+  rand bit [2:0]       aes_keylen;
+  // 256 bit key (8x32 bit)                                    //
+  rand bit [7:0][31:0] aes_key;
+  // 256 bit initialization vector (8x32 bit)                  //
+  rand bit [3:0][31:0] aes_iv;
+  // configuration error                                       //
+  rand bit             has_config_error;
+
+  ///////////////////////////////////////
+  // FIXED variables                   //
+  ///////////////////////////////////////
+
+  bit [7:0]            input_msg[];
+  bit [7:0]            output_msg[];
+  bit [7:0]            predicted_msg[];
+
+  ///////////////////////////////////////
+  // Constraints                       //
+  ///////////////////////////////////////
+
+  constraint c_data { message_length inside { [message_len_min:message_len_max] };}
+
+  constraint c_keylen {
+    solve has_config_error before aes_keylen;
+    if(!has_config_error) {
+      // key len 001: 128, 010: 192, 100: 256
+      aes_keylen inside { 3'b001, 3'b010, 3'b100 };
+      // mode distribution
+      aes_keylen dist  { 3'b001 := key_128b_weight, 3'b010 := key_192b_weight, 3'b100 := key_256b_weight };
+    } else {
+      !(aes_keylen inside { 3'b001, 3'b010, 3'b100 });  // force the selection to be something invalid     
+    }
+  }
+
+  constraint c_mode { aes_mode dist  { AES_ECB := ecb_weight, AES_CBC:= cbc_weight, AES_CTR := ctr_weight };}
+
+  constraint c_has_config_error {
+    if(errors_en && config_err)
+      {
+      has_config_error dist { 0 :/ (100-config_error_pct),
+                              1 :/ config_error_pct    };
+    }
+    else { has_config_error == 0; }
+  }
+
+
+
+  function void add_data_item(aes_seq_item item);
+    for(int i=0; i < 4 ; i++ ) begin
+      // data_in.push_front (data_in[3:0])
+      input_msg  = { input_msg , item.data_in[i][7:0], item.data_in[i][15:8], item.data_in[i][23:16]
+                    ,item.data_in[i][31:24]};
+      // data_in.push_front (data_in[3:0])
+      output_msg = { output_msg, item.data_out[i][7:0], item.data_out[i][15:8],
+                     item.data_out[i][23:16],item.data_out[i][31:24] };
+    end
+  endfunction // add_data_item
+
+
+  function void add_start_msg_item(aes_seq_item item);
+    this.aes_mode      = item.mode;
+    this.aes_operation = item.operation;
+    this.aes_keylen    = item.key_len;
+    this.aes_key       = item.key;
+
+    add_data_item(item);
+  endfunction // add_start_msg_item
+
+
+  function void alloc_predicted_msg();
+    predicted_msg = new[input_msg.size()];
+  endfunction // alloc_predicted_msg
+
+
+  // convert to string //
+  virtual function string convert2string();
+    string str;
+    str = super.convert2string();
+    str = {str,  $sformatf("\n\t ----| AES MESSAGE ITEM                                  |----\t ")
+           };
+    str = {str,  $sformatf("\n\t ----| Mode:    \t %s                         |----\t ",
+                           aes_mode.name() ) };
+    str = {str,  $sformatf("\n\t ----| Operation:    \t %s                     |----\t ",
+                           aes_operation.name() ) };
+    str = {str,  $sformatf("\n\t ----| has Configuration error:    \t %s           |----\t ",
+                           (has_config_error==1) ? "TRUE" : "FALSE" ) };
+    str = {str,  $sformatf("\n\t ----| Message Length:    \t %d             |----\t ",
+                           message_length ) };
+
+    str = {str,  $sformatf("\n\t ----| Key Length:    \t %03b                             |----\t ",
+                           aes_keylen) };
+    str = {str,  $sformatf("\n\t ----| Key:         \t ") };
+    for(int i=0; i <8; i++) begin
+      str = {str, $sformatf("%h ",aes_key[i])};
+    end
+    str = {str,  $sformatf("\n\t ----| errors_enabled: %b         \t ", errors_en) };
+    str = {str,  $sformatf("\n\t ----| config_err: %b         \t ", config_err) };
+    str = {str,  $sformatf("\n\t ----| MODE Distribution:     \t " ) };
+    str = {str,  $sformatf("\n\t ----| ECB Weight: %d         \t ", ecb_weight) };
+    str = {str,  $sformatf("\n\t ----| CBC Weight: %d         \t ", cbc_weight) };
+    str = {str,  $sformatf("\n\t ----| CTR Weight: %d         \t ", ctr_weight) };
+    str = {str,  $sformatf("\n\t ----| Key Len Distribution   :\t " ) };
+    str = {str,  $sformatf("\n\t ----| 128 Weight: %d         \t ", key_128b_weight) };
+    str = {str,  $sformatf("\n\t ----| 192 Weight: %d         \t ", key_192b_weight) };
+    str = {str,  $sformatf("\n\t ----| 256 Weight: %d         \t ", key_256b_weight) };
+    str = {str,  $sformatf("\n\t") };
+
+    return str;
+  endfunction // conver2string
+
+
+  virtual function void do_copy(uvm_object rhs);
+    aes_message_item rhs_;
+
+    `downcast(rhs_,rhs)
+    super.do_copy(rhs);
+    aes_operation    = rhs_.aes_operation;
+    aes_key          = rhs_.aes_key;
+    aes_keylen       = rhs_.aes_keylen;
+    aes_mode         = rhs_.aes_mode;
+    aes_iv           = rhs_.aes_iv;
+    message_length   = rhs_.message_length;
+    has_config_error = rhs_.has_config_error;
+    ecb_weight       = rhs_.ecb_weight;
+    cbc_weight       = rhs_.cbc_weight;
+    ctr_weight       = rhs_.ctr_weight;
+    key_128b_weight  = rhs_.key_128b_weight;
+    key_192b_weight  = rhs_.key_192b_weight;
+    key_256b_weight  = rhs_.key_256b_weight;
+    input_msg        = rhs_.input_msg;
+    output_msg       = rhs_.output_msg;
+    predicted_msg    = rhs_.predicted_msg;
+  endfunction // copy
+endclass
diff --git a/hw/ip/aes/dv/env/aes_scoreboard.sv b/hw/ip/aes/dv/env/aes_scoreboard.sv
index 6735f4e..bfae3bb 100644
--- a/hw/ip/aes/dv/env/aes_scoreboard.sv
+++ b/hw/ip/aes/dv/env/aes_scoreboard.sv
@@ -1,32 +1,47 @@
 // Copyright lowRISC contributors.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
+
 import aes_model_dpi_pkg::*;
 import aes_pkg::*;
 
 class aes_scoreboard extends cip_base_scoreboard #(
-    .CFG_T(aes_env_cfg),
-    .RAL_T(aes_reg_block),
-    .COV_T(aes_env_cov)
+  .CFG_T(aes_env_cfg),
+  .RAL_T(aes_reg_block),
+  .COV_T(aes_env_cov)
   );
+
   `uvm_component_utils(aes_scoreboard)
 
   `uvm_component_new
 
   // local variables
-  aes_seq_item dut_item;
-  // TLM agent fifos
+  aes_seq_item input_item;                    // item containing data and config
+  aes_seq_item output_item;                   // item containing resulting output
+  aes_seq_item complete_item;                 // merge of input and output items
 
-  // local queues to hold incoming packets pending comparison
-  mailbox #(aes_seq_item) dut_fifo;                                   // all incoming TL transactions will be written to this one
-  mailbox #(aes_seq_item) ref_fifo;                                   // this will be a clone of the above before the result has been calculated by the dut!
+  bit          aes_from_rst   = 1;            // 1: nothing has happened since rst was released
+  bit          ok_to_fwd      = 0;            // 0: item is not ready to forward
+  bit          finish_message = 0;            // set when test is trying to end
+                                              // - to indicate the last message is finished
+  int          message_cnt    = 0;            // used to check that all messages were received
+
+  // local queues to hold incoming packets pending comparison //
+
+  // Items containing both input and output data, ready to be added to a message
+  mailbox      #(aes_seq_item)      item_fifo;
+  // completed message item ready for scoring
+  mailbox      #(aes_message_item)  msg_fifo;
+   // once an operation is started the item is put here to wait for the resuting output
+  aes_seq_item                      rcv_item_q[$];
 
 
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
-    dut_fifo = new();
-    ref_fifo = new();
-    dut_item = new("dut_item");
+    msg_fifo    = new();
+    item_fifo   = new();
+    input_item  = new("input_item");
+    output_item = new ();
   endfunction
 
 
@@ -37,15 +52,21 @@
 
   task run_phase(uvm_phase phase);
     super.run_phase(phase);
-    fork
-      compare();
-    join_none
+    `uvm_info(`gfn, $sformatf("%s", cfg.convert2string()), UVM_HIGH)
+    if(cfg.en_scb) begin
+      fork
+        compare();
+        rebuild_message();
+      join_none
+    end
   endtask
 
 
   virtual task process_tl_access(tl_seq_item item, tl_channels_e channel = DataChannel);
     uvm_reg        csr;
-    aes_seq_item   ref_item;
+    string         csr_name;
+    aes_seq_item   input_clone;
+    aes_seq_item   complete_clone;
     bit            do_read_check = 1'b0;
     bit            write         = item.is_write();
     uvm_reg_addr_t csr_addr      = get_normalized_addr(item.a_addr);
@@ -63,87 +84,159 @@
       if (write) begin
         void'(csr.predict(.value(item.a_data), .kind(UVM_PREDICT_WRITE), .be(item.a_mask)));
       end
-      case (csr.get_name())
+      `uvm_info(`gfn, $sformatf("ITEM received reg name : %s",csr.get_name() ), UVM_HIGH)
+      csr_name = csr.get_name();
+      case (1)
         // add individual case item for each csr
-        "ctrl": begin
-          {dut_item.allow_data_ovrwrt, dut_item.man_trigger,dut_item.key_size,dut_item.operation}
-          = item.a_data[5:0];
-        end
-        "key0": begin
-          dut_item.key[0] = item.a_data;
-        end
-        "key1": begin
-          dut_item.key[1] = item.a_data;
-        end
-        "key2": begin
-          dut_item.key[2] = item.a_data;
-        end
-        "key3": begin
-          dut_item.key[3] = item.a_data;
-        end
-        "key4": begin
-          dut_item.key[4] = item.a_data;
-        end
-        "key5": begin
-          dut_item.key[5] = item.a_data;
-        end
-        "key6": begin
-          dut_item.key[6] = item.a_data;
-        end
-        "key7": begin
-          dut_item.key[7] = item.a_data;
+         (!uvm_re_match("ctrl", csr_name)): begin
+          input_item.manual_op = item.a_data[7];
+          input_item.key_len   = item.a_data[6:4];
+          `downcast(input_item.operation, item.a_data[0]);
+          case (item.a_data[3:1])
+            3'b001:  input_item.mode = AES_ECB;
+            3'b010:  input_item.mode = AES_CBC;
+            3'b100:  input_item.mode = AES_CTR;
+            default: input_item.mode = AES_ECB;
+          endcase // case item.a_data[3
         end
 
-        "data_in0" :begin
-          dut_item.data_in[0]     = item.a_data;
-          dut_item.data_in_vld[0] = 1;
-        end
-
-        "data_in1" :begin
-          dut_item.data_in[1]     = item.a_data;
-          dut_item.data_in_vld[1] = 1;
-        end
-
-        "data_in2" :begin
-          dut_item.data_in[2]     = item.a_data;
-          dut_item.data_in_vld[2] = 1;
-        end
-
-        "data_in3": begin
-          dut_item.data_in[3]     = item.a_data;
-          dut_item.data_in_vld[3] = 1;
-        end
-
-        "trigger": begin
-          if (item.a_data[0]) begin
-            `downcast(ref_item, dut_item.clone());
-            ref_fifo.put(ref_item);
+        (!uvm_re_match("key*", csr_name)): begin
+          for (int i = 0; i < 8; i++) begin
+            string keyname = $sformatf("key%0d", i);
+            if (keyname == csr_name) begin
+               input_item.key[i]      = item.a_data;
+               input_item.key_vld[i]  = 1'b1;
+            end
           end
         end
 
-        "status": begin
-            //TBD
+        (!uvm_re_match("data_in*", csr_name)): begin
+          for (int i = 0; i < 4; i++) begin
+            string keyname = $sformatf("data_in%0d", i);
+            if (keyname == csr_name) begin
+              input_item.data_in[i]      = item.a_data;
+              input_item.data_in_vld[i]  = 1'b1;
+            end
+          end
         end
 
+       (!uvm_re_match("iv*", csr_name)): begin
+          for (int i = 0; i < 4; i++) begin
+            string keyname = $sformatf("iv%0d", i);
+            if (keyname == csr_name) begin
+              input_item.iv[i]      = item.a_data;
+              input_item.iv_vld[i]  = 1'b1;
+            end
+          end
+       end
+
+     //    TODO
+     //   "trigger": begin
+     //     if (item.a_data[0]) begin
+     //       //            `downcast(ref_item, input_item.clone());
+     //       //            ref_fifo.put(ref_item);
+     //     end
+     //   end
+     //
+     //   "status": begin
+     //     //TBD
+     //   end
+
         default: begin
-         // DO nothing- trying to write to a read only register
+          // DO nothing- trying to write to a read only register
         end
       endcase
 
-      // forward Item and clear valid bits
-        if (!dut_item.man_trigger && (& dut_item.data_in_vld)) begin
-        `downcast(ref_item, dut_item.clone());
-        ref_fifo.put(ref_item);
-        ref_item = new();
-        dut_item.data_in_vld = '0;
+
+      ///////////////////////////////////////
+      //             Valid checks          //
+      ///////////////////////////////////////
+
+      // check that the item is valid - all registers clean base on mode //
+      case (input_item.mode)
+        AES_ECB: begin
+          if(aes_from_rst) begin
+            // verify that all 4 data_in and all 8 key have been updated
+            if(input_item.data_in_valid() && input_item.key_clean(0)) begin
+              //clone and add to ref and rec data fifo
+              ok_to_fwd    = 1;
+              aes_from_rst = 0;
+              `uvm_info(`gfn, $sformatf("\n\t ----| First ITEM created  OK to clone"), UVM_HIGH)
+            end
+          end else begin
+            // verify that all 4 data_in and all 8 key are clean
+            `uvm_info(`gfn, $sformatf("\n\t ----|data_inv_vld?  %b, key clean ? %b",
+                      input_item.data_in_valid(), input_item.key_clean(1) ), UVM_HIGH)
+
+            if(input_item.data_in_valid() && input_item.key_clean(1)) begin
+              //clone and add to ref and rec data fifo
+              `uvm_info(`gfn, $sformatf("\n\t ----| OK to clone"), UVM_HIGH)
+              ok_to_fwd = 1;
+            end
+          end
+        end
+
+        AES_CBC: begin
+          if(aes_from_rst) begin
+            // verify that all 4 data_in and all 8 key and all 4 IV have been updated
+            if(input_item.data_in_valid() && input_item.key_clean(0) && input_item.iv_clean(0)) begin
+              //clone and add to ref and rec data fifo
+              ok_to_fwd    = 1;
+              aes_from_rst = 0;
+              `uvm_info(`gfn, $sformatf("\n\t ----| First ITEM created  OK to clone"), UVM_HIGH)
+            end
+          end else begin
+            // verify that all 4 data_in and all 8 key  and all 4 IV are clean
+            `uvm_info(`gfn, $sformatf("\n\t ----|data_inv_vld?  %b, key clean ? %b",
+                              input_item.data_in_valid(), input_item.key_clean(1) ), UVM_HIGH)
+
+            if(input_item.data_in_valid() && input_item.key_clean(1) && input_item.iv_clean(1)) begin
+              //clone and add to ref and rec data fifo
+              `uvm_info(`gfn, $sformatf("\n\t ----| OK to clone"), UVM_HIGH)
+              ok_to_fwd = 1;
+            end
+          end
+        end
+
+        AES_CTR: begin
+          if(aes_from_rst) begin
+            // verify that all 4 data_in and all 8 key and all 4 IV have been updated
+            if(input_item.data_in_valid() && input_item.key_clean(0) && input_item.iv_clean(0)) begin
+              //clone and add to ref and rec data fifo
+              ok_to_fwd    = 1;
+              aes_from_rst = 0;
+              `uvm_info(`gfn, $sformatf("\n\t ----| First ITEM created  OK to clone"), UVM_HIGH)
+            end
+          end else begin
+            // verify that all 4 data_in and all 8 and all 4 IV  key are clean
+            `uvm_info(`gfn, $sformatf("\n\t ----|data_inv_vld?  %b, key clean ? %b",input_item.data_in_valid(), input_item.key_clean(1) ), UVM_HIGH)
+            if(input_item.data_in_valid() && input_item.key_clean(1) && input_item.iv_clean(1)) begin
+              //clone and add to ref and rec data fifo
+              `uvm_info(`gfn, $sformatf("\n\t ----| OK to clone"), UVM_HIGH)
+              ok_to_fwd = 1;
+            end
+          end
+        end
+        default: begin
+          `uvm_fatal(`gfn, $sformatf("\n\t ----| I AM IN DEFAULT CASE I SHOULD NOT BE HERE"))
+        end
+      endcase // case (input_item.mode)
+
+      // forward item to receive side
+      if(ok_to_fwd ) begin
+        ok_to_fwd = 0;
+        `downcast(input_clone, input_item.clone());
+        `uvm_info(`gfn, $sformatf("\n\t AES INPUT ITEM RECEIVED - \n %s", input_clone.convert2string()), UVM_HIGH)
+        rcv_item_q.push_front(input_clone);
+        input_item.clean();
       end
     end
 
 
-    // process the csr req
-    // for write, update local variable and fifo at address phase
-    // for read, update predication at address phase and compare at data phase
-    // On reads, if do_read_check, is set, then check mirrored_value against item.d_data
+    //////////////////////////////////////////////////////////////////////////////
+    // get an item from the rcv queue and wait for all output data to be received
+    //////////////////////////////////////////////////////////////////////////////
+
     `uvm_info(`gfn, $sformatf("\n\t ---| channel  %h", channel), UVM_HIGH)
     if (!write && channel == DataChannel) begin
       if (do_read_check) begin
@@ -151,84 +244,175 @@
                      $sformatf("reg name: %0s", csr.get_full_name()))
       end
       void'(csr.predict(.value(item.d_data), .kind(UVM_PREDICT_READ)));
-        `uvm_info(`gfn, $sformatf("\n\t ----| SAW READ - %s data %02h",csr.get_name(),  item.d_data)
-                  , UVM_HIGH)
+      `uvm_info(`gfn, $sformatf("\n\t ----| SAW READ - %s data %02h",csr.get_name(),  item.d_data)
+                , UVM_HIGH)
 
       case (csr.get_name())
         "data_out0": begin
-          dut_item.data_out[0]     = item.d_data;
-          dut_item.data_out_vld[0] = 1;
+          output_item.data_out[0]     = item.d_data;
+          output_item.data_out_vld[0] = 1;
         end
         "data_out1": begin
-          dut_item.data_out[1]     = item.d_data;
-          dut_item.data_out_vld[1] = 1;
+          output_item.data_out[1]     = item.d_data;
+          output_item.data_out_vld[1] = 1;
         end
         "data_out2": begin
-          dut_item.data_out[2]     = item.d_data;
-          dut_item.data_out_vld[2] = 1;
+          output_item.data_out[2]     = item.d_data;
+          output_item.data_out_vld[2] = 1;
         end
         "data_out3": begin
-          dut_item.data_out[3]     = item.d_data;
-          dut_item.data_out_vld[3] = 1;
+          output_item.data_out[3]     = item.d_data;
+          output_item.data_out_vld[3] = 1;
         end
-      endcase
-        if (&dut_item.data_out_vld) begin
-        dut_fifo.put(dut_item);
-        dut_item = new();
+      endcase // case (csr.get_name())
+
+      if (output_item.data_out_valid()) begin
+        if( rcv_item_q.size() == 0) begin
+          `uvm_fatal(`gfn, $sformatf("\n\t ----| TRIED TO READ EMPTY RECEIVE QUEUE |----"))
+        end
+
+        complete_item              = rcv_item_q.pop_back();
+        complete_item.data_out     = output_item.data_out;
+
+        `downcast(complete_clone, complete_item.clone());
+        item_fifo.put(complete_clone);
+
+        output_item                = new();
+        complete_item              = new();
+        `uvm_info(`gfn,
+          $sformatf("\n\t ----|added data to item_fifo (output received) fifo entries %d", 
+                   item_fifo.num()), UVM_HIGH)
       end
     end
-  endtask
+  endtask // process_tl_access
+
+
+  // takes items from the item queue and builds full aes_messages with both input data and output data.
+  task rebuild_message();
+    typedef enum { MSG_START,MSG_RUN } aes_message_stat_t;
+
+    aes_message_item   message, msg_clone;
+    aes_seq_item       full_item;
+    aes_message_stat_t msg_state;
+
+    message = new();
+
+    fork
+      begin
+        forever begin
+          case(msg_state)
+            MSG_START: begin
+              full_item = new();
+              item_fifo.get(full_item);
+              `uvm_info(`gfn, $sformatf("\n\t ----| got item from item fifo"), UVM_FULL)
+              if(!full_item.message_start()) begin
+                `uvm_fatal(`gfn,
+                 $sformatf("\n\t ----| FIRST ITEM DID NOT HAVE MESSAGE START/CONFIG SETTINGS"))
+              end
+              message.add_start_msg_item(full_item);
+              msg_state = MSG_RUN;
+            end
+
+            MSG_RUN: begin
+              full_item = new();
+              item_fifo.get(full_item);
+              `uvm_info(`gfn, $sformatf("\n\t ----| got item from item fifo"), UVM_FULL)
+              if(full_item.message_start() ) begin
+                `uvm_info(`gfn, $sformatf("\n\t ----| adding message item to mg_fifo"), UVM_FULL)
+                `downcast(msg_clone, message.clone());
+                msg_fifo.put(msg_clone);
+                message = new();
+                message.add_start_msg_item(full_item);
+              end else begin
+                message.add_data_item(full_item);
+              end
+            end
+          endcase // case (msg_state)
+        end
+      end
+
+      begin
+        wait( finish_message )
+        `uvm_info(`gfn, $sformatf("\n\t ----|Finish test received adding message item to mg_fifo")
+         , UVM_HIGH)
+
+        `downcast(msg_clone, message.clone());
+        msg_fifo.put(msg_clone);
+      end
+    join_any
+  endtask // rebuild_message
 
 
   virtual task compare();
     string txt="";
+    bit [3:0][31:0] tmp_input;
+    bit [3:0][31:0] tmp_output;
+
     forever begin
-      aes_seq_item rtl_item;
-      aes_seq_item c_item;
-      bit [127:0] calc_data;
+      aes_message_item msg;
 
       `uvm_info(`gfn, $sformatf("\n\t ----| TRYING to get item "), UVM_HIGH)
-      dut_fifo.get(rtl_item);
-      ref_fifo.get(c_item );
+      msg_fifo.get(msg);
+
       `uvm_info(`gfn, $sformatf("\n\t ----| GOT item "), UVM_HIGH)
+      `uvm_info(`gfn, $sformatf("model %b, operation: %b, mode %03b, IV %h, key_len %03b, key %h ",
+                                cfg.ref_model, msg.aes_operation, msg.aes_mode, msg.aes_iv, msg.aes_keylen, msg.aes_key)
+                , UVM_HIGH)
 
-      sv_dpi_aes_crypt_block(1'b0, c_item.operation, 3'b001, 128'b0, c_item.key_size, c_item.key,
-          c_item.data_in, c_item.data_out);
-      `uvm_info(`gfn, $sformatf("\n\t ----| printing C MODEL %s", c_item.convert2string() )
-          , UVM_HIGH)
+      msg.alloc_predicted_msg();
+      //ref-model      / opration     / chipher mode /    IV   / key_len    / key /data i /data o //
+      c_dpi_aes_crypt_message(cfg.ref_model, msg.aes_operation, msg.aes_mode, msg.aes_iv, 
+                              msg.aes_keylen, msg.aes_key, msg.input_msg, msg.predicted_msg);
 
-      if (!rtl_item.compare(c_item)) begin
-        txt = {txt,  $sformatf("\n\t ----| RTL_ITEM %s \n\t ", rtl_item.convert2string())};
-        txt = {txt, $sformatf("\n\t ----| printing C MODEL %s", c_item.convert2string() )};
-        txt = {txt,  $sformatf("\n\t ----| \t\t\t  DATA OUTPUT \t\t  |---- ")};
-        txt = {txt, $sformatf("\n\t ----| \t\t\t  RTL \t\t REF \t  |---- ")};
-        foreach (rtl_item.data_out[i]) begin
-          txt = {txt, $sformatf("\n\t ----| [%d] \t %02h \t %02h |----", i, rtl_item.data_out[i],
-                                c_item.data_out[i])};
-        end
-        `uvm_fatal(`gfn, $sformatf("\t TEST FAILED ITEMS DOES NOT MATCH \n\t %s \n",txt))
-      end else begin
-        `uvm_info(`gfn, $sformatf("\n\t ----|    ITEMS MATCHED    |-----"), UVM_LOW)
+      `uvm_info(`gfn, $sformatf("\n\t ----| printing MESSAGE %s", msg.convert2string() )
+                , UVM_HIGH)
+      txt = "";
+      foreach(msg.input_msg[i]) begin
+        txt = { txt, $sformatf("\n\t  %h \t %h \t %h",
+                               msg.input_msg[i],msg.output_msg[i], msg.predicted_msg[i])};
       end
+
+      `uvm_info(`gfn, $sformatf("\n\t input \t output \t predicted %s",txt), UVM_HIGH)
+
+      for( int n =0 ; n < msg.input_msg.size(); n++) begin
+        if( msg.output_msg[n] != msg.predicted_msg[n]) begin
+          txt = "\t TEST FAILED MESSAGES DID NOT MATCH";
+
+          txt = {txt,  $sformatf("\n\t ----| ACTUAL OUTPUT DID NOT MATCH PREDICTED OUTPUT |----")};
+          txt = {txt, $sformatf("\n\t ----| FAILED AT BLOCK #%d \t ACTUAL: %h \t PREDICTED: %h, ", 
+                                n, msg.output_msg[n], msg.predicted_msg[n] )};
+          `uvm_fatal(`gfn, $sformatf(" # %d  \n\t %s \n",message_cnt, txt))
+        end
+      end
+      `uvm_info(`gfn, $sformatf("\n\t ----|   MESSAGE #%d MATCHED    |-----",message_cnt), UVM_HIGH)
+      message_cnt++;
     end
   endtask
 
-
+  // TODO get rid of this and do EOP checks in monitor
   virtual function void phase_ready_to_end(uvm_phase phase);
     if (phase.get_name() != "run") return;
-    if ( (dut_fifo.num() != 0 ) || (ref_fifo.num() != 0) ) begin
-      phase.raise_objection(this, "fifos still has data");
-      fork begin
-        wait_fifo_empty();
-        phase.drop_objection(this);
-      end
-      join_none
+
+    // the message currently being reassembled is should be sent for scoring
+    finish_message = 1;
+    `uvm_info(`gfn, $sformatf("Finish message: %b", finish_message), UVM_HIGH)
+
+    // AEs needs this objection - because PHASE READY TO END
+    // is the only way to know that the very last message is now complete
+    phase.raise_objection(this, "need time to finish last item");
+    fork begin
+      wait_fifo_empty();
+      phase.drop_objection(this);
     end
+    join_none
   endfunction
 
 
   virtual task wait_fifo_empty();
-    wait ((dut_fifo.num() == 0 ) && (ref_fifo.num() == 0));
+    `uvm_info(`gfn, $sformatf("item fifo entries %d", item_fifo.num()), UVM_HIGH)
+    wait (rcv_item_q.size() == 0 );
+    wait (item_fifo.num()   == 0 );
+    wait (msg_fifo.num()    == 0 );
   endtask
 
 
@@ -239,15 +423,43 @@
 
 
   function void check_phase(uvm_phase phase);
-    super.check_phase(phase);
-    `DV_EOT_PRINT_MAILBOX_CONTENTS(aes_seq_item, dut_fifo)
-    `DV_EOT_PRINT_MAILBOX_CONTENTS(aes_seq_item, ref_fifo)
+    string txt =  "";
+    if (cfg.en_scb) begin
+      `uvm_info(`gfn, $sformatf(" RASMUS JUST CHECKING"), UVM_LOW)
+      super.check_phase(phase);
+      `DV_EOT_PRINT_MAILBOX_CONTENTS(aes_message_item, msg_fifo)
+      `DV_EOT_PRINT_MAILBOX_CONTENTS(aes_seq_item, item_fifo)
+      `DV_EOT_PRINT_Q_CONTENTS(aes_seq_item, rcv_item_q)
+      if(message_cnt != cfg.num_messages) begin
+        txt = "\n\t ----| NO FAILURES BUT DIDN*T SEE ALL EXPECTED MESSAGES";
+        txt = { txt, $sformatf(" \n\t ----| expected %d, seen: %d", cfg.num_messages, message_cnt ) };
+        `uvm_fatal(`gfn, $sformatf("%s", txt) )
+      end
+    end
+
   endfunction
 
 
   function void report_phase(uvm_phase phase);
-    super.report_phase(phase);
-    `uvm_info(`gfn, $sformatf("%s", cfg.convert2string()), UVM_LOW)
-  endfunction
+    uvm_report_server rpt_srvr;
+    string txt="";
 
+    super.report_phase(phase);
+    txt = $sformatf("\n\t ----|        TEST FINISHED        |----");
+    txt = {   txt, $sformatf("\n\t SAW %d Good messages ", message_cnt)};
+    txt = {   txt, $sformatf("\n\t Expected %d messages ", cfg.num_messages)};
+    rpt_srvr = uvm_report_server::get_server();
+    if(rpt_srvr.get_severity_count(UVM_FATAL)+rpt_srvr.get_severity_count(UVM_ERROR)>0) begin
+      `uvm_info(`gfn, $sformatf("%s", cfg.convert2string()), UVM_LOW)
+      txt = { txt,"\n\t---------------------------------------"};
+      txt = { txt,"\n\t----            TEST FAILED        ----"};
+      txt = { txt,"\n\t---------------------------------------"};
+    end else begin
+      txt = {txt, "\n\t---------------------------------------"};
+      txt = { txt,"\n\t----            TEST PASSED        ----"};
+      txt = { txt,"\n\t---------------------------------------"};
+    end
+    `uvm_info(`gfn, $sformatf("%s", txt), UVM_HIGH)
+
+  endfunction // report_phase
 endclass
diff --git a/hw/ip/aes/dv/env/aes_seq_item.sv b/hw/ip/aes/dv/env/aes_seq_item.sv
index 12b2479..bf73731 100644
--- a/hw/ip/aes/dv/env/aes_seq_item.sv
+++ b/hw/ip/aes/dv/env/aes_seq_item.sv
@@ -2,86 +2,79 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
+
 class aes_seq_item extends uvm_sequence_item;
 
-  // Knobs //
-  // min number of data bytes
-  int    data_len_max;
-  // Max number of data bytes
-  int    data_len_min;
+  `uvm_object_utils(aes_seq_item)
 
+  aes_item_type_e  item_type;
 
-  // randomized values //
-  rand bit                                 operation; // TODO implement this as enum
-  // 0: auto start, 1: wait for start
-  rand bit                                 man_trigger;
+  aes_op_e operation;
+
+  ///////////////////////////////////////
+  //  control Knobs                    //
+  ///////////////////////////////////////
+
+  // 0: auto mode 1: manual start
+  bit             manual_op;
   // 0: output data cannot be overwritten
   // 1: new output will overwrite old output even if not read.
-  rand bit                                 allow_data_ovrwrt;
-  // lenth of plaintext / cypher
-  rand bit                   [31:0]        data_len;
+  bit             allow_data_ovrwrt;
+  // lenth of plaintext / cypher (max is 128b/16b per block)
+  // used to mask bits that are not part of the data vector
+  bit [3:0]       data_len            = 0;
   // key len 0: 128, 1: 192, 2: 256 3: NOT VALID
-  rand bit                   [2:0]         key_size;
+  bit [2:0]       key_len;
   // 256 bit key (8x32 bit)
-  rand bit              [7:0][31:0]        key;
-  // data queue to hold the randomized data
-  rand bit                   [31:0]        data_in_queue[$];
+  bit [7:0][31:0] key;
+  // which fields of the key is valid
+  bit [7:0]       key_vld             = 8'b0;
   // randomized data to add to queue
+  bit [3:0][31:0] iv;
+  // indicate if the initialization vector is valid
+  bit [3:0]       iv_vld;
+  aes_mode_e      mode;
 
 
+  ///////////////////////////////////////
+  // FIXED variables                   //
+  ///////////////////////////////////////
+
+  // indicate which words has data
+  bit [3:0]       data_in_vld         = 4'b0;
+  // indicate which words has data
+  bit [3:0]       data_out_vld        = 4'b0;
 
 
-  // fixed variables //
-  // indicated which words has data
-  bit [3:0] data_in_vld  = 4'b0;
-  // indicated which words has data
-  bit                         [3:0]       data_out_vld = 4'b0;
   // used by the checker
-  bit                   [3:0][31:0]       data_in;
-  // used by the checker
-  bit                   [3:0][31:0]       data_out;
-  // used to store output data
-  bit                        [31:0]       data_out_queue[$];
+  bit [3:0][31:0] data_out;
+  // used byt the scoreboard to rebuild plaintext messages
+  //   bit [31:0]      data_in_queue[$];
+  //used by the scoreboard to build the processed message
+  //   bit [31:0]      data_out_queue[$];
   // set if data should be fixed and not randomized
-  bit                                     fixed_data = 0;
+  bit             fixed_data          = 0;
   // if set unused key bytes will be forced to 0 - controlled from test
-  bit                                     key_mask=0;
+  bit             key_mask            = 0;
 
 
+  ///////////////////////////////////////
+  // Randomizable variables            //
+  ///////////////////////////////////////
+
+  // used by the checker
+  rand  bit [3:0][31:0] data_in;
+
 
   function new( string name="aes_sequence_item");
     super.new(name);
   endfunction
 
 
-  // contraints //
-  constraint c_data {
-    solve data_len before data_in_queue;
-    data_len inside { [data_len_min: data_len_max] };
-
-    if(data_len[1:0] == 2'b00) {
-      data_in_queue.size() == data_len >> 2;
-    } else {
-      data_in_queue.size() ==  data_len >> 2 + 1;
-    }
-    if(data_len[1:0] == 2'b01) {
-      data_in_queue[data_in_queue.size()-1][31:8]   == 0;
-    } else if (data_len[1:0] == 2'b10) {
-      data_in_queue[data_in_queue.size()-1][31:16]  == 0;
-    } else {
-      data_in_queue[data_in_queue.size()-1][31:24]  == 0;
-    }
-  }
-
-  constraint c_key_size {key_size inside {3'b001, 3'b010, 3'b100 };
-             // key len 0: 128, 1: 192, 2: 256 3: NOT VALID
-  }
-
-  constraint c_operation_reg {operation == 0; man_trigger == 0; allow_data_ovrwrt == 0; }
-
   function void post_randomize();
+    bit [3:0]           index;
     if(key_mask) begin
-      case (key_size)
+      case (key_len)
         3'b001: begin
           key[7:4] = 32'h00000000;
         end
@@ -92,77 +85,153 @@
         end
       endcase
     end
+
+    // mask unused data bits
+    if(data_len != 0) begin
+      for(int i=data_len; i<16; i++) begin
+        data_in[i[3:2]][i[1:0]*8+7 -:8] = 8'd0;
+      end
+    end
+  endfunction // post_randomize
+
+  // function to detect if all datafields
+  // have been updated.
+  function bit data_in_valid();
+    `uvm_info(`gfn, $sformatf("\n\t ----| Checking if ALL data is updated %4b", data_in_vld)
+              , UVM_FULL)
+
+    return &data_in_vld;
+  endfunction // data_in_valid
+
+  // function to detect if all datafields
+  // have been updated.
+  function bit data_out_valid();
+    `uvm_info(`gfn, $sformatf("\n\t ----| Checking if ALL data is valid  %4b", data_out_vld)
+      , UVM_FULL)
+
+    return &data_out_vld;
+  endfunction // data_in_valid
+
+  // if ret_clean = 0
+  // return 1 only of all registers have been written
+  // if ret_celan = 1
+  // return 1 if all or none of the registers have been written
+  function bit key_clean(bit ret_clean);
+    `uvm_info(`gfn, $sformatf("\n\t ----| Key status %b", key_vld), UVM_LOW)
+    if(ret_clean) begin
+      return ( (&key_vld) || ~(|key_vld));
+    end else begin
+      return &key_vld;
+    end
+  endfunction // key_clean
+
+  // if ret_clean = 0
+  // return 1 only of all registers have been written
+  // if ret_celan = 1
+  // return 1 if all or none of the registers have been written
+  function bit iv_clean(bit ret_clean);
+    if(ret_clean) begin
+      return  ( (&iv_vld) || ~(|iv_vld));
+    end else begin
+      return &iv_vld;
+    end
   endfunction
 
+  // bases on the AES mode
+  // function will return 1 if this is the start of a new message
+  function bit message_start();
+    case(mode)
+      AES_ECB: begin
+        `uvm_info(`gfn, $sformatf("return key vld(%b) %b",key_vld, &key_vld), UVM_LOW)
+        return (&key_vld);
+      end
+      AES_CBC: begin
+        `uvm_info(`gfn, $sformatf("return key vld(%b) %b AND iv (%b) &b",
+                   key_vld, &key_vld, iv_vld, &iv_vld), UVM_LOW)
+        return (&key_vld && &iv_vld);
+      end
+      AES_CTR: begin
+        `uvm_info(`gfn, $sformatf("return key vld(%b) %b AND iv (%b) &b",
+                   key_vld, &key_vld, iv_vld, &iv_vld), UVM_LOW)
+        return (&key_vld && &iv_vld);
+      end
+      default: begin
+        `uvm_fatal(`gfn, $sformatf("\n\t ----| I AM IN DEFAULT CASE I SHOULD NOT BE HERE"))
+      end
+    endcase // case (mode)
+  endfunction // message_start
 
-  function bit add2output( logic [31:0] data );
-    data_out_queue.push_back(data);
-    return 1;
-  endfunction
+
+  function void clean();
+    data_in_vld = '0;
+    iv_vld      = '0;
+    key_vld     = '0;
+    data_out_vld= '0;
+  endfunction // clean
 
 
   virtual function void do_copy(uvm_object rhs);
     aes_seq_item rhs_;
 
-    if(!$cast(rhs_,rhs) ) begin
-      uvm_report_error("do_copy:", "acst failed");
-      return;
-    end
+    `downcast(rhs_,rhs)
     super.do_copy(rhs);
-    operation = rhs_.operation;
-    data_in   = rhs_.data_in;
-    key       = rhs_.key;
-    key_size  = rhs_.key_size;
-    data_out  = rhs_.data_out;
+    item_type    = rhs_.item_type;
+    operation    = rhs_.operation;
+    mode         = rhs_.mode;
+    data_in      = rhs_.data_in;
+    key          = rhs_.key;
+    key_len      = rhs_.key_len;
+    key_vld      = rhs_.key_vld;
+    iv           = rhs_.iv;
+    iv_vld       = rhs_.iv_vld;
+    data_out     = rhs_.data_out;
+    data_len     = rhs_.data_len;
   endfunction // copy
 
 
-// do compare //
-virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
+  // do compare //
+  virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
 
-  aes_seq_item rhs_;
+    aes_seq_item rhs_;
 
-  if(!$cast(rhs_,rhs))begin
-    return 0; // compare failed because object is not of sequence item type
-  end
-
-return(super.do_compare(rhs,comparer) &&
-  (operation == rhs_.operation) &&
-  (data_in   == rhs_.data_in) &&
-  (key       == rhs_.key) &&
-  (data_out  == rhs_.data_out) );
-endfunction // compare
+    `downcast(rhs_,rhs)
+    return(super.do_compare(rhs,comparer) &&
+           (operation == rhs_.operation) &&
+           (mode      == rhs_.mode) &&
+           (data_in   == rhs_.data_in) &&
+           (key       == rhs_.key) &&
+           (data_out  == rhs_.data_out) );
+  endfunction // compare
 
 
-// convert to string //
-virtual function string convert2string();
- string str;
-  str = super.convert2string();
-  str = {str,  $psprintf("\n\t ----| AES SEQUENCE ITEM                                  |----\t ")
-        };
-  str = {str,  $psprintf("\n\t ----| Mode:    \t %s                          |----\t ",
-        (operation==1'b0) ? "ENCRYPT" : "DECRYPT" ) };
-  str = {str,  $psprintf("\n\t ----| Key size:    \t %s                             |----\t ",
-         (key_size==3'b001) ? "128b" : (key_size == 3'b010) ? "192b" : "256b") };
-  str = {str,  $psprintf("\n\t ----| Key:         \t ") };
-  for(int i=0; i <8; i++) begin
-    str = {str, $psprintf("%h ",key[i])};
-  end
-  str = {str,  $psprintf("\n\t ----| Input data:  \t %h |----\t ", data_in) };
-  str = {str,  $psprintf("\n\t ----| Output data: \t %h |----\t ", data_out) };
-  str = {str,  $psprintf("\n\t") };
+  // convert to string //
+  virtual function string convert2string();
+    string str;
+    str = super.convert2string();
+    str = {str,  $psprintf("\n\t ----| AES SEQUENCE ITEM                                  |----\t ")
+           };
+    str = {str,  $psprintf("\n\t ----| Item Type:    \t %s                          |----\t ",item_type.name()) };
+    str = {str,  $psprintf("\n\t ----| AES Mode:    \t %s                          |----\t ",mode.name()) };
+    str = {str,  $psprintf("\n\t ----| Operation:    \t %s                          |----\t ", operation.name() ) };
+    str = {str,  $psprintf("\n\t ----| Key len:    \t %s                             |----\t ",
+                           (key_len==3'b001) ? "128b" : (key_len == 3'b010) ? "192b" : "256b") };
+    str = {str,  $psprintf("\n\t ----| Key:         \t ") };
+    for(int i=0; i <8; i++) begin
+      str = {str, $psprintf("%h ",key[i])};
+    end
+    str = {str,  $psprintf("\n\t ----| Data Length: \t %d |----\t  \t", data_len) };
+    str = {str,  $psprintf("\n\t ----| Input data:  \t %h |----\t ", data_in) };
+    str = {str,  $psprintf("\n\t ----| Output data: \t %h |----\t ", data_out) };
+    str = {str,  $psprintf("\n\t") };
 
-  return str;
+    return str;
   endfunction // conver2string
 
   virtual function string bytes2string();
     string str="\n\t ----| data_out: ";
     for(int i=0; i<4; i++) begin
-        str = {str, $psprintf("%h", data_out[i][31:0])};
+      str = {str, $psprintf("%h", data_out[i][31:0])};
     end
     return str;
   endfunction
-
-`uvm_object_utils(aes_seq_item)
-
 endclass
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
index 04a74ce..a96c080 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_base_vseq.sv
@@ -2,48 +2,47 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-
 class aes_base_vseq extends cip_base_vseq #(
   .CFG_T               (aes_env_cfg),
   .RAL_T               (aes_reg_block),
   .COV_T               (aes_env_cov),
   .VIRTUAL_SEQUENCER_T (aes_virtual_sequencer)
-);
+  );
 
   `uvm_object_utils(aes_base_vseq)
   `uvm_object_new
 
-  parameter bit ENCRYPT = 1'b0;
-  parameter bit DECRYPT = 1'b1;
-
-  aes_reg2hw_t aes_reg;
-  aes_seq_item  aes_item;
+  aes_reg2hw_t       aes_reg;
+  aes_seq_item       aes_item;
+  aes_seq_item       aes_item_queue[$];
+  aes_message_item   aes_message;
+  aes_message_item   message_queue[$];
 
   // various knobs to enable certain routines
-  bit do_aes_init = 1'b1;
+  bit                do_aes_init = 1'b1;
 
   virtual task dut_init(string reset_kind = "HARD");
     super.dut_init();
     if (do_aes_init) aes_init();
-    aes_item_init();
+    aes_item = new();
+    aes_message_init();
   endtask
 
   virtual task dut_shutdown();
     // check for pending aes operations and wait for them to complete
     // TODO
-
   endtask
 
   // setup basic aes features
   virtual task aes_init();
+
     bit [31:0] aes_ctrl    = '0;
     bit [31:0] aes_trigger = '0;
 
-
     // initialize control register
-    aes_ctrl[0]   = 0;        // set to encryption
-    aes_ctrl[3:1] = 3'b001;   // set to 128b key
-    aes_ctrl[4]   = 0;        // start encryption automatically, don't overwrite output reg
+    aes_ctrl[0]    = 0;        // set to encryption
+    aes_ctrl[3:1] = aes_pkg::AES_ECB;   //3'b001;   // set to ECB MODE
+    aes_ctrl[6:4]  = aes_pkg::AES_128;   // set to 128b key
     csr_wr(.csr(ral.ctrl), .value(aes_ctrl));
     csr_wr(.csr(ral.trigger), .value(aes_trigger));
   endtask
@@ -52,6 +51,12 @@
   virtual task set_operation(bit operation);
     ral.ctrl.operation.set(operation);
     csr_update(.csr(ral.ctrl));
+  endtask // set_operation
+
+
+  virtual task set_mode(bit [2:0] mode);
+    ral.ctrl.mode.set(mode);
+    csr_update(.csr(ral.ctrl));
   endtask
 
 
@@ -76,43 +81,185 @@
     csr_wr(.csr(ral.key5), .value(key[5]));
     csr_wr(.csr(ral.key6), .value(key[6]));
     csr_wr(.csr(ral.key7), .value(key[7]));
+  endtask // write_key
+
+
+  virtual task write_iv(bit  [3:0][31:0] iv);
+    csr_wr(.csr(ral.iv0), .value(iv[0]));
+    csr_wr(.csr(ral.iv1), .value(iv[1]));
+    csr_wr(.csr(ral.iv2), .value(iv[2]));
+    csr_wr(.csr(ral.iv3), .value(iv[3]));
   endtask
 
 
-  virtual task add_data(ref bit [31:0] data[$]);
-    csr_wr(.csr(ral.data_in0), .value(data.pop_back()) );
-    csr_wr(.csr(ral.data_in1), .value(data.pop_back()) );
-    csr_wr(.csr(ral.data_in2), .value(data.pop_back()) );
-    csr_wr(.csr(ral.data_in3), .value(data.pop_back()) );
+  virtual task add_data(ref bit [3:0] [31:0] data);
+    `uvm_info(`gfn, $sformatf("\n\t ----| ADDING DATA TO DUT %h ", data), UVM_HIGH)
+    `uvm_info(`gfn, $sformatf("\n\t ----| DATA_in0: %h ", data[0][31:0]), UVM_HIGH)
+    `uvm_info(`gfn, $sformatf("\n\t ----| DATA_in1: %h ", data[1][31:0]), UVM_HIGH)
+    `uvm_info(`gfn, $sformatf("\n\t ----| DATA_in2: %h ", data[2][31:0]), UVM_HIGH)
+    `uvm_info(`gfn, $sformatf("\n\t ----| DATA_in3: %h ", data[3][31:0]), UVM_HIGH)     
+    csr_wr(.csr(ral.data_in0), .value(data[0][31:0]) );
+    csr_wr(.csr(ral.data_in1), .value(data[1][31:0]) );
+    csr_wr(.csr(ral.data_in2), .value(data[2][31:0]) );
+    csr_wr(.csr(ral.data_in3), .value(data[3][31:0]) );
   endtask
 
 
-  virtual task read_data(ref bit [31:0] cypher_txt[$]);
-    bit              data_rdy = 0;
-    bit [31:0]       rd_data;
+  ///////////////////////////////////////
+  // ADVANCED TASKS                    //
+  ///////////////////////////////////////
+
+  virtual task read_data(ref bit [3:0] [31:0] cypher_txt);
+    bit [3:0] [31:0] rd_txt;
+
     `uvm_info(`gfn, $sformatf("\n\t ----| POLLING FOR DATA"), UVM_DEBUG)
     csr_spinwait(.ptr(ral.status.output_valid) , .exp_data(1'b1));    // poll for data valid
 
-    csr_rd(.ptr(ral.data_out0), .value(rd_data));
-    cypher_txt.push_front(rd_data);
+    csr_rd(.ptr(ral.data_out0), .value(cypher_txt[0][31:0]));
+    csr_rd(.ptr(ral.data_out1), .value(cypher_txt[1][31:0]));
+    csr_rd(.ptr(ral.data_out2), .value(cypher_txt[2][31:0]));
+    csr_rd(.ptr(ral.data_out3), .value(cypher_txt[3][31:0]));
 
-    csr_rd(.ptr(ral.data_out1), .value(rd_data));
-    cypher_txt.push_front(rd_data);
-
-    csr_rd(.ptr(ral.data_out2), .value(rd_data));
-    cypher_txt.push_front(rd_data);
-
-    csr_rd(.ptr(ral.data_out3), .value(rd_data));
-    cypher_txt.push_front(rd_data);
-
-    `uvm_info(`gfn, $sformatf("\n\t ----| READ DATA"), UVM_DEBUG)
+    `uvm_info(`gfn, $sformatf("\n\t ----| READ OUPUT DATA"), UVM_MEDIUM)
+    `uvm_info(`gfn, $sformatf("\n\t ----| ADDING DATA TO DUT %h ", cypher_txt),  UVM_HIGH)
+    `uvm_info(`gfn, $sformatf("\n\t ----| DATA_out0: %h ", cypher_txt[0][31:0]), UVM_HIGH)
+    `uvm_info(`gfn, $sformatf("\n\t ----| DATA_out1: %h ", cypher_txt[1][31:0]), UVM_HIGH)
+    `uvm_info(`gfn, $sformatf("\n\t ----| DATA_out2: %h ", cypher_txt[2][31:0]), UVM_HIGH)
+    `uvm_info(`gfn, $sformatf("\n\t ----| DATA_out3: %h ", cypher_txt[3][31:0]), UVM_HIGH)       
   endtask
 
-  function void aes_item_init();
+
+  virtual task setup_dut(aes_seq_item item);
+    set_operation(item.operation);
+    set_mode(item.mode);
+    set_key_len(item.key_len);
+    write_key(item.key);
+    write_iv(item.iv);
+  endtask
+
+
+  // TODO add missing functions
+  virtual task generate_aes_item_queue(ref aes_message_item msg_item);
+    aes_seq_item item_clone;
+
+    // generate DUT cfg
+    aes_ctrl_item_init(msg_item);
+    generate_data_stream(msg_item);
+
+    // aes_generate_err_inj();
+
+    // aes_generate_rnd_rst();
+
+    aes_print_item_queue(aes_item_queue);
+  endtask
+
+
+  virtual task generate_data_stream(ref aes_message_item msg_item);
+    aes_seq_item item_clone;
+
+    // generate an item for each 128b message block
+    for (int n=0; n<msg_item.message_length - 15; n += 16 ) begin
+      `DV_CHECK_RANDOMIZE_FATAL(aes_item)
+      aes_item.item_type = AES_DATA;
+      `uvm_info(`gfn, $sformatf("\n ----| DATA AES ITEM %s", aes_item.convert2string()), UVM_FULL)
+      `downcast(item_clone, aes_item.clone());
+      aes_item_queue.push_front(item_clone);
+      `uvm_info(`gfn, $sformatf("\n ----| generating data item %d", n), UVM_MEDIUM)
+    end
+
+    // check if message length is not divisible by 16bytes
+    if( msg_item.message_length[3:0] != 4'd0) begin
+      `uvm_info(`gfn, $sformatf("\n ----| generating runt "), UVM_MEDIUM)
+      aes_item.data_len = msg_item.message_length[3:0];
+      `DV_CHECK_RANDOMIZE_FATAL(aes_item)
+      aes_item.item_type = AES_DATA;
+      `downcast(item_clone, aes_item.clone());
+      aes_item_queue.push_front(item_clone);
+    end
+  endtask
+
+
+  // TODO
+  // virtual task generate_err_inj(ref aes_message_item msg_item);
+  // endtask
+
+  // TODO
+  // virtual task generate_rnd_rst();
+  // endtask
+
+
+  // this function starst the transmission of items to the dut,
+  // while at the same time offloads the output when ready
+  virtual task transmit_message_with_rd_back();
+    aes_seq_item nxt_item = new();
+    nxt_item = aes_item_queue.pop_back();
+    setup_dut(aes_item);
+
+    while(aes_item_queue.size() > 0) begin
+      nxt_item = aes_item_queue.pop_back();
+      add_data(nxt_item.data_in);
+      read_data(nxt_item.data_out);
+    end
+
+  endtask // transmit_message_with_rd_back
+
+
+  // TODO think about how to randomize error objects vs normal that
+  // are not randomized at this level!
+  function void aes_ctrl_item_init(ref aes_message_item message_item);
+    aes_seq_item item_clone;
     aes_item = new();
-    aes_item.data_len_max = cfg.data_len_max;
-    aes_item.data_len_min = cfg.data_len_min;
-    aes_item.key_mask     = cfg.key_mask;
+
+    `uvm_info(`gfn, $sformatf("\n Generating configuration item for message of size %d", message_item.message_length), UVM_MEDIUM)
+    `uvm_info(`gfn, $sformatf("\n Message \n %s", message_item.convert2string()), UVM_MEDIUM)
+
+    aes_item.item_type = AES_CFG;
+    aes_item.operation = message_item.aes_operation;
+    aes_item.mode      = message_item.aes_mode;
+    aes_item.key_len   = message_item.aes_keylen;
+    aes_item.key       = message_item.aes_key;
+    `uvm_info(`gfn, $sformatf("----| CONFIG  AES ITEM %s", aes_item.convert2string()), UVM_MEDIUM)
+
+    `downcast(item_clone, aes_item.clone());
+    aes_item_queue.push_front(item_clone);
   endfunction
 
+
+  // init the first message - following will rerandomize with the same constraints
+  function void aes_message_init();
+    aes_message = new();
+    aes_message.ecb_weight        = cfg.ecb_weight;
+    aes_message.cbc_weight        = cfg.cbc_weight;
+    aes_message.ctr_weight        = cfg.ctr_weight;
+    aes_message.key_128b_weight   = cfg.key_128b_weight;
+    aes_message.key_192b_weight   = cfg.key_192b_weight;
+    aes_message.key_256b_weight   = cfg.key_256b_weight;
+    aes_message.message_len_max   = cfg.message_len_max;
+    aes_message.message_len_min   = cfg.message_len_min;
+    aes_message.config_error_pct  = cfg.config_error_pct;
+    aes_message.errors_en         = cfg.errors_en;
+  endfunction
+
+
+  function void generate_message_queue();
+    aes_message_item cloned_message;
+    for(int i=0; i < cfg.num_messages; i++) begin
+      `DV_CHECK_RANDOMIZE_FATAL(aes_message)
+      `downcast(cloned_message, aes_message.clone());
+      //`assert($cast(cloned_message, aes_message.clone());
+      message_queue.push_front(cloned_message);
+      `uvm_info(`gfn, $sformatf("\n message # %d \n %s",i, cloned_message.convert2string()), UVM_MEDIUM)
+    end
+  endfunction
+
+
+  function void aes_print_item_queue(ref aes_seq_item item_queue[$]);
+    aes_seq_item print_item;
+    `uvm_info(`gfn, $sformatf("----| Item queue size: %d", item_queue.size()), UVM_MEDIUM)
+    for(int n = 0; n<item_queue.size(); n++) begin
+      print_item = item_queue[n];
+      `uvm_info(`gfn, $sformatf("----|  ITEM #%d", n ), UVM_MEDIUM)
+      `uvm_info(`gfn, $sformatf("%s", print_item.convert2string()), UVM_MEDIUM)
+    end
+  endfunction
 endclass : aes_base_vseq
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_common_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_common_vseq.sv
index df33b6e..3e9e1e3 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_common_vseq.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_common_vseq.sv
@@ -10,9 +10,11 @@
   }
   `uvm_object_new
 
+
   virtual task pre_start();
     do_aes_init = 1'b0;
     super.pre_start();
+    cfg.en_scb = 0;    
   endtask
 
   virtual task body();
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_sanity_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_sanity_vseq.sv
deleted file mode 100644
index 8664f20..0000000
--- a/hw/ip/aes/dv/env/seq_lib/aes_sanity_vseq.sv
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-// basic sanity test vseq
-  class aes_sanity_vseq extends aes_base_vseq;
-  `uvm_object_utils(aes_sanity_vseq)
-
-  `uvm_object_new
-
-  task body();
-
-    `uvm_info(`gfn, $sformatf("STARTING AES SEQUENCE"), UVM_LOW);
-
-    `DV_CHECK_RANDOMIZE_WITH_FATAL(aes_item, key_size == 3'b001;)
-    set_operation(aes_item.operation);
-    set_key_len(aes_item.key_size);
-    // add key
-    write_key(aes_item.key);
-
-    // add data
-    add_data(aes_item.data_in_queue);
-
-    // get cypher
-    read_data(aes_item.data_out_queue);
-
-  endtask : body
-
-endclass : aes_sanity_vseq
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_stress_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_stress_vseq.sv
new file mode 100644
index 0000000..c0eea2c
--- /dev/null
+++ b/hw/ip/aes/dv/env/seq_lib/aes_stress_vseq.sv
@@ -0,0 +1,31 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// basic main test vseq
+class aes_stress_vseq extends aes_base_vseq;
+  `uvm_object_utils(aes_stress_vseq)
+
+  `uvm_object_new
+  aes_message_item my_message;
+
+  task body();
+    `uvm_info(`gfn, $sformatf("\n\t ----| STARTING AES MAIN SEQUENCE |----\n"), UVM_LOW);
+    `uvm_info(`gfn, $sformatf("\n\t cfg item \n %s", cfg.convert2string()), UVM_LOW)
+
+    // generate list of messages //
+    generate_message_queue();
+    // process all messages //
+    while( message_queue.size() > 0) begin
+      // get next message from queue
+      my_message = new();
+      my_message = message_queue.pop_back();
+
+      // for this message generate configuration
+      // and data items (split message into blocks)
+      generate_aes_item_queue(my_message);
+      // setup and transmit
+      transmit_message_with_rd_back();
+    end
+  endtask : body
+endclass
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv b/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
index 9b0187a..7d62c58 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_vseq_list.sv
@@ -4,5 +4,5 @@
 
 `include "aes_base_vseq.sv"
 `include "aes_wake_up_vseq.sv"
-`include "aes_sanity_vseq.sv"
 `include "aes_common_vseq.sv"
+`include "aes_stress_vseq.sv"
diff --git a/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv b/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
index 3289a4a..00c2989 100644
--- a/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
+++ b/hw/ip/aes/dv/env/seq_lib/aes_wake_up_vseq.sv
@@ -9,35 +9,34 @@
 
   `uvm_object_new
 
-  bit [31:0]  plain_text[$]   = {32'hDEADBEEF, 32'hEEDDBBAA, 32'hBAADBEEF, 32'hDEAFBEAD};
-  logic [255:0] init_key      = 256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF;
-  bit [31:0]    cypher_text[$];
-  bit [31:0]    decrypted_text[$];
-  logic [31:0]  read_text[$];
 
-  string  str="";
+  parameter bit       ENCRYPT = 1'b0;
+  parameter bit       DECRYPT = 1'b1;
 
-
-
-
+  bit [3:0] [31:0]    plain_text       = 128'hDEADBEEFEEDDBBAABAADBEEFDEAFBEAD;
+  logic [255:0]       init_key         = 256'h0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF;
+  bit [3:0] [31:0]    cypher_text;
+  bit [3:0] [31:0]    decrypted_text;
+  logic [3:0] [31:0]  read_text;
+  string              str="";
+  
 
   task body();
 
     `uvm_info(`gfn, $sformatf("STARTING AES SEQUENCE"), UVM_LOW)
+  
+    
     `DV_CHECK_RANDOMIZE_FATAL(this)
-    `uvm_info(`gfn, $sformatf("running aes sanity sequence"), UVM_LOW)
 
-    `uvm_info(`gfn, $sformatf(" \n\t ---|setting operation to encrypt"), UVM_LOW)
+    `uvm_info(`gfn, $sformatf(" \n\t ---|setting operation to encrypt"), UVM_HIGH)
     // set operation to encrypt
     set_operation(ENCRYPT);
 
-
-    `uvm_info(`gfn, $sformatf(" \n\t ---| WRITING INIT KEY  %02h", init_key), UVM_LOW)
-
+    `uvm_info(`gfn, $sformatf(" \n\t ---| WRITING INIT KEY  %02h", init_key), UVM_HIGH)
     write_key(init_key);
     cfg.clk_rst_vif.wait_clks(20);
 
-    `uvm_info(`gfn, $sformatf(" \n\t ---| ADDING PLAIN TEXT"), UVM_LOW)
+    `uvm_info(`gfn, $sformatf(" \n\t ---| ADDING PLAIN TEXT"), UVM_HIGH)
 
     add_data(plain_text);
 
@@ -48,37 +47,38 @@
                               ral.status.convert2string()), UVM_DEBUG)
 
     read_data(cypher_text);
-
     // read output
-    `uvm_info(`gfn, $sformatf("\n\t ------|WAIT 0 |-------"), UVM_LOW)
+    `uvm_info(`gfn, $sformatf("\n\t ------|WAIT 0 |-------"), UVM_HIGH)
     cfg.clk_rst_vif.wait_clks(20);
 
     // set aes to decrypt
     set_operation(DECRYPT);
     cfg.clk_rst_vif.wait_clks(20);
-    `uvm_info(`gfn, $sformatf("\n\t ---|WRITING INIT KEY FOR DECRYPT: %02h", init_key), UVM_LOW)
+    `uvm_info(`gfn, $sformatf("\n\t ---|WRITING INIT KEY FOR DECRYPT: %02h", init_key), UVM_HIGH)
     write_key(init_key);
     cfg.clk_rst_vif.wait_clks(20);
-    `uvm_info(`gfn, $sformatf("\n\t ---| WRITING CYPHER TEXT"), UVM_LOW)
+    `uvm_info(`gfn, $sformatf("\n\t ---| WRITING CYPHER TEXT"), UVM_HIGH)
     add_data(cypher_text);
 
+
     `uvm_info(`gfn, $sformatf("\n\t ---| Polling for data %s", ral.status.convert2string()),
               UVM_DEBUG)
 
     cfg.clk_rst_vif.wait_clks(20);
 
     read_data(decrypted_text);
-    foreach(decrypted_text[i]) begin
-      `uvm_info(`gfn, $sformatf("\n\t ----| decrypted text elememt [%d] : %02h", i, decrypted_text[i]), UVM_LOW)
-    end
-
+    //need scoreboard disable
     foreach(plain_text[i]) begin
       if(plain_text[i] != decrypted_text[i]) begin
         str = $sformatf(" \n\t ---| OH NOO TEST FAILED AT POS %d|--- \n \t DECRYPTED: \t %02h \n\t Plaintext: \t %02h ",
                         i, decrypted_text[i], plain_text[i]);
         `uvm_fatal(`gfn, $sformatf("%s",str));
       end
-
+    
+    end
+    foreach(decrypted_text[i]) begin
+      `uvm_info(`gfn,
+                $sformatf("\n\t ----| decrypted text elememt [%d] : %02h", i, decrypted_text[i]), UVM_HIGH)
     end
 
     `uvm_info(`gfn, $sformatf(" \n\t ---| YAY TEST PASSED |--- \n \t "), UVM_NONE)
diff --git a/hw/ip/aes/dv/tests/aes_base_test.sv b/hw/ip/aes/dv/tests/aes_base_test.sv
index 5f5e292..694a73b 100644
--- a/hw/ip/aes/dv/tests/aes_base_test.sv
+++ b/hw/ip/aes/dv/tests/aes_base_test.sv
@@ -9,14 +9,27 @@
   `uvm_component_utils(aes_base_test)
   `uvm_component_new
 
-  // the base class dv_base_test creates the following instances:
-  // aes_env_cfg: cfg
-  // aes_env:     env
+   virtual function void build_phase(uvm_phase phase);
+     super.build_phase(phase);
+     configure_env();
+   endfunction // build_phase
 
-  // the base class also looks up UVM_TEST_SEQ plusarg to create and run that seq in
-  // the run_phase; as such, nothing more needs to be done
 
-//    function configure_knobs()
-//      endfunction // configure_knobs
+  virtual function void configure_env();
+    // cfg.ref_model          = OpenSSL;
+    // env related knobs
+
+    cfg.errors_en          = 0;
+    cfg.num_messages_min   = 3;
+    cfg.num_messages_max   = 3;
+    // message related knobs
+    cfg.ecb_weight         = 100;
+    cfg.cbc_weight         = 0;
+    cfg.ctr_weight         = 0;
+    cfg.message_len_min    = 1;   // bytes
+    cfg.message_len_max    = 599; // bytes
+    `DV_CHECK_RANDOMIZE_FATAL(cfg)
+  endfunction
+
 
 endclass : aes_base_test
diff --git a/hw/ip/aes/dv/tests/aes_sanity_test.sv b/hw/ip/aes/dv/tests/aes_sanity_test.sv
new file mode 100644
index 0000000..6acdd89
--- /dev/null
+++ b/hw/ip/aes/dv/tests/aes_sanity_test.sv
@@ -0,0 +1,29 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class aes_sanity_test extends aes_base_test;
+
+  `uvm_component_utils(aes_sanity_test)
+  `uvm_component_new
+
+   virtual function void build_phase(uvm_phase phase);
+     super.build_phase(phase);
+     configure_env();
+  endfunction
+
+  function void configure_env();
+     super.configure_env();
+     cfg.errors_en          = 0;     // no errors in sanity test
+     cfg.num_messages_min   = 2;
+     cfg.num_messages_max   = 2;
+     // message related knobs
+     cfg.ecb_weight         = 100;   // only eCB
+     cfg.cbc_weight         = 0;
+     cfg.ctr_weight         = 0;
+     cfg.message_len_min    = 16;    // one block (16bytes=128bits)
+     cfg.message_len_max    = 16;    //
+
+    `DV_CHECK_RANDOMIZE_FATAL(cfg)
+  endfunction
+endclass : aes_sanity_test
diff --git a/hw/ip/aes/dv/tests/aes_stress_test.sv b/hw/ip/aes/dv/tests/aes_stress_test.sv
new file mode 100644
index 0000000..2b83103
--- /dev/null
+++ b/hw/ip/aes/dv/tests/aes_stress_test.sv
@@ -0,0 +1,29 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class aes_stress_test extends aes_base_test;
+  `uvm_component_utils(aes_stress_test)
+  `uvm_component_new
+
+   virtual function void build_phase(uvm_phase phase);
+     super.build_phase(phase);
+     configure_env();
+  endfunction
+
+  virtual function void configure_env();
+    //   cfg.ref_model          = OpenSSL;
+    // env related knobs
+
+    cfg.errors_en          = 0;
+    cfg.num_messages_min   = 5;
+    cfg.num_messages_max   = 5;
+    // message related knobs
+    cfg.ecb_weight         = 10;
+    cfg.cbc_weight         = 40;
+    cfg.ctr_weight         = 40;
+    cfg.message_len_min    = 7;   // bytes
+    cfg.message_len_max    = 251; // bytes
+    `DV_CHECK_RANDOMIZE_FATAL(cfg)
+  endfunction
+endclass : aes_stress_test
diff --git a/hw/ip/aes/dv/tests/aes_test.core b/hw/ip/aes/dv/tests/aes_test.core
index f6d54fa..17d13d8 100644
--- a/hw/ip/aes/dv/tests/aes_test.core
+++ b/hw/ip/aes/dv/tests/aes_test.core
@@ -11,6 +11,9 @@
     files:
       - aes_test_pkg.sv
       - aes_base_test.sv: {is_include_file: true}
+      - aes_wake_up_test.sv: {is_include_file: true}
+      - aes_sanity_test.sv: {is_include_file: true}
+      - aes_stress_test.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
 targets:
diff --git a/hw/ip/aes/dv/tests/aes_test_pkg.sv b/hw/ip/aes/dv/tests/aes_test_pkg.sv
index 325cf59..769a9e2 100644
--- a/hw/ip/aes/dv/tests/aes_test_pkg.sv
+++ b/hw/ip/aes/dv/tests/aes_test_pkg.sv
@@ -18,5 +18,8 @@
 
   // package sources
   `include "aes_base_test.sv"
+  `include "aes_wake_up_test.sv"
+  `include "aes_sanity_test.sv"
+  `include "aes_stress_test.sv"
 
 endpackage
diff --git a/hw/ip/aes/dv/tests/aes_wake_up_test.sv b/hw/ip/aes/dv/tests/aes_wake_up_test.sv
new file mode 100644
index 0000000..4679306
--- /dev/null
+++ b/hw/ip/aes/dv/tests/aes_wake_up_test.sv
@@ -0,0 +1,25 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class aes_wake_up_test extends aes_base_test;
+
+  `uvm_component_utils(aes_wake_up_test)
+  `uvm_component_new
+
+   virtual function void build_phase(uvm_phase phase);
+     super.build_phase(phase);
+     configure_env();
+  endfunction
+
+  virtual function void configure_env();
+    // cfg.en_scb = 0;
+     cfg.ecb_weight         = 100;
+     cfg.cbc_weight         = 0;
+     cfg.ctr_weight         = 0;
+     cfg.num_messages_min   = 2;
+     cfg.num_messages_max   = 2;
+
+    `DV_CHECK_RANDOMIZE_FATAL(cfg)
+  endfunction
+endclass : aes_wake_up_test