diff --git a/flist/nanosoc/nanosoc_chip_ip.flist b/flist/nanosoc/nanosoc_chip_ip.flist
index 8d2c24005978687ce2aa4b046799ea00c2f074b4..1b370a073a069aaa5d493ab642197f4e01f646cf 100644
--- a/flist/nanosoc/nanosoc_chip_ip.flist
+++ b/flist/nanosoc/nanosoc_chip_ip.flist
@@ -34,6 +34,6 @@ $(SOCLABS_NANOSOC_TECH_DIR)/system/src/verilog/nanosoc_apb_usrt.v
 $(SOCLABS_NANOSOC_TECH_DIR)/system/src/verilog/nanosoc_ahb_bootrom.v
 $(SOCLABS_NANOSOC_TECH_DIR)/system/src/bootrom/verilog/bootrom.v
 
-$(SOCLABS_NANOSOC_TECH_DIR)/system/aes/src/nanosoc_exp_wrapper.v
-+incdir+$(PROJECT_DIR)/secworks-aes/src/rtl
-$(SOCLABS_NANOSOC_TECH_DIR)/system/aes/src/soclabs_ahb_aes128_ctrl.v
+//$(NANOSOC_TECH_DIR)/system/aes/src/nanosoc_exp_wrapper.v
+//+incdir+$(PROJECT_DIR)/secworks-aes/src/rtl
+//$(NANOSOC_TECH_DIR)/system/aes/src/soclabs_ahb_aes128_ctrl.v
diff --git a/flist/project/accelerator.flist b/flist/project/accelerator.flist
index a9d3db2dc3a46ea5ef527b4cfe2415f01681e1a4..43f32420a234f41c198806c82b092c93d6d2e8be 100644
--- a/flist/project/accelerator.flist
+++ b/flist/project/accelerator.flist
@@ -12,3 +12,6 @@
 +libext+.v+.vlib
 
 // =============    Accelerator Module search path    =============
+$(PROJECT_DIR)/system/src/nanosoc_exp_wrapper.v
++incdir+$(PROJECT_DIR)/secworks-aes/src/rtl
+$(PROJECT_DIR)/system/src/soclabs_ahb_aes128_ctrl.v
diff --git a/simulate/socsim/system_secworks_aes128.sh b/simulate/socsim/system_secworks_aes128.sh
old mode 100644
new mode 100755
diff --git a/system/cpu_software/aes128_tests/aes128.h b/system/cpu_software/aes128_tests/aes128.h
new file mode 100644
index 0000000000000000000000000000000000000000..202adf42b9efc670fa80c6c2b5335b9352b41cd0
--- /dev/null
+++ b/system/cpu_software/aes128_tests/aes128.h
@@ -0,0 +1,71 @@
+#ifndef _AES128_H_
+#define _AES128_H_
+
+#include <stdint.h>
+
+// define the API addresses here. 
+
+#define AES128_BASE        (0x60000000)
+
+// byte address I/O buffers
+#define AES128_BUF_SIZE   (0x4000)
+
+typedef struct {
+     __I  uint32_t CORE_NAME[2];   /* 0x0000-0007 */
+     __I  uint32_t CORE_VERSION;   /* 0x0008-000B */
+          uint32_t RESRV0C;        /* 0x000C */
+     __IO uint32_t CTRL;           /* 0x0010 */
+     __O  uint32_t CTRL_SET;       /* 0x0014 */
+     __O  uint32_t CTRLL_CLR;      /* 0x0018 */
+     __I  uint32_t STATUS;         /* 0x001c */
+     __IO uint32_t QUAL;           /* 0x0020 */
+          uint32_t RESRV24[3];     /* 0x0024 - 2F*/
+     __IO uint32_t DRQ_MSK;        /* 0x0030 */
+     __O  uint32_t DRQ_MSK_SET;    /* 0x0034 */
+     __O  uint32_t DRQ_MSK_CLR;    /* 0x0038 */
+     __I  uint32_t DRQ_STATUS;     /* 0x003C */
+     __IO uint32_t IRQ_MSK;        /* 0x0040 */
+     __O  uint32_t IRQ_MSK_SET;    /* 0x0044 */
+     __O  uint32_t IRQ_MSK_CLR;    /* 0x0048 */
+     __I  uint32_t IRQ_STATUS;     /* 0x004C */
+          uint8_t RESRV50[AES128_BUF_SIZE - 0x50];/* 0x0050-0x3FFC (4096-20 words) */
+     __IO uint8_t KEY128[AES128_BUF_SIZE];   /* 0x4000-7FFF (0x3FFF is last alias) */
+     __IO uint8_t TXTIP128[AES128_BUF_SIZE]; /* 0x8000-BFFF (0x3FFF is last alias) */
+     __I  uint8_t TXTOP128[AES128_BUF_SIZE]; /* 0xC000-FFFF (0x3FFF is last alias) */
+} AES128_TypeDef;
+
+#define AES128             ((AES128_TypeDef *) AES128_BASE )
+
+#define AES_BLOCK_SIZE 16
+
+#define AES_KEY_LEN_128 16
+
+#define HW32_REG(ADDRESS)  (*((volatile unsigned long  *)(ADDRESS)))
+
+#define  AES128_CTRL_REG_WIDTH   ( 8)
+#define  AES128_CTRL_BIT_MAX     ( (CTRL_REG_WIDTH-1)
+#define  AES128_CTRL_KEY_REQ_BIT (1<<0)
+#define  AES128_CTRL_IP_REQ_BIT  (1<<1)
+#define  AES128_CTRL_OP_REQ_BIT  (1<<2)
+#define  AES128_CTRL_ERR_REQ_BIT (1<<3)
+#define  AES128_CTRL_BYPASS_BIT  (1<<6)
+#define  AES128_CTRL_ENCODE_BIT  (1<<7)
+#define  AES128_STAT_REG_WIDTH   ( 8)
+#define  AES128_STAT_KEY_REQ_BIT (1<<0)
+#define  AES128_STAT_IP_REQ_BIT  (1<<1)
+#define  AES128_STAT_OP_REQ_BIT  (1<<2)
+#define  AES128_STAT_ERR_REQ_BIT (1<<3)
+#define  AES128_STAT_KEYOK_BIT   (1<<4)
+#define  AES128_STAT_VALID_BIT   (1<<5)
+#define  AES128_STAT_BYPASS_BIT  (1<<6)
+#define  AES128_STAT_ENCODE_BIT  (1<<7)
+#define  AES128_KEY_REQ_BIT (1<<0)
+#define  AES128_IP_REQ_BIT  (1<<1)
+#define  AES128_OP_REQ_BIT  (1<<2)
+#define  AES128_ERR_REQ_BIT (1<<3)
+#define  AES128_KEYOK_BIT   (1<<4)
+#define  AES128_VALID_BIT   (1<<5)
+#define  AES128_BYPASS_BIT  (1<<6)
+#define  AES128_ENCODE_BIT  (1<<7)
+
+#endif // _AES128_H_
diff --git a/system/cpu_software/aes128_tests/aes128_tests.c b/system/cpu_software/aes128_tests/aes128_tests.c
new file mode 100644
index 0000000000000000000000000000000000000000..3dbccadfc9d7cd668f4eabbe1bd18a84fcdaec6b
--- /dev/null
+++ b/system/cpu_software/aes128_tests/aes128_tests.c
@@ -0,0 +1,688 @@
+#include "CMSDK_CM0.h"
+#include "aes128.h"
+#include <string.h>
+#include "uart_stdout.h"
+#include <stdio.h>
+// memcopy implememtation
+#define os_memcpy memcpy
+#define os_memset memset
+// PL230DMA implementation
+#include "dma_pl230_driver.h"
+
+
+static volatile dma_pl230_channel_data aes_ip_chain[2];
+static volatile dma_pl230_channel_data aes_op_chain[2];
+
+// associate DMA channel numbers
+#define DMA_CHAN_AES128_IP (0)
+#define DMA_CHAN_AES128_OP (1)
+
+volatile int dma_done_irq_occurred;
+volatile int dma_done_irq_expected;
+volatile int dma_error_irq_occurred;
+volatile int dma_error_irq_expected;
+volatile int aes_key_irq_occurred;
+volatile int aes_key_irq_expected;
+volatile int aes_ip_irq_occurred;
+volatile int aes_ip_irq_expected;
+volatile int aes_op_irq_occurred;
+volatile int aes_op_irq_expected;
+volatile int aes_err_irq_occurred;
+volatile int aes_err_irq_expected;
+
+  uint8_t _test_key128[AES_KEY_LEN_128] = {  
+    0x75, 0x46, 0x20, 0x67,
+    0x6e, 0x75, 0x4b, 0x20,
+    0x79, 0x6d, 0x20, 0x73,
+    0x74, 0x61, 0x68, 0x54 };
+
+  uint8_t test_key128[AES_KEY_LEN_128] = {  
+    0x54, 0x68, 0x61, 0x74,
+    0x73, 0x20, 0x6d, 0x79,
+    0x20, 0x4b, 0x75, 0x6e,
+    0x67, 0x20, 0x46, 0x75 };
+	
+  uint8_t buf128[AES_BLOCK_SIZE] = {
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00 };
+
+  uint8_t _test_text128[AES_BLOCK_SIZE] = {
+    0x6f, 0x77, 0x54, 0x20,
+    0x65, 0x6e, 0x69, 0x4e,
+    0x20, 0x65, 0x6e, 0x4f,
+    0x20, 0x6f, 0x77, 0x54 };
+
+  uint8_t test_text128[AES_BLOCK_SIZE] = {
+    0x54, 0x77, 0x6f, 0x20,
+    0x4f, 0x6e, 0x65, 0x20,
+    0x4e, 0x69, 0x6e, 0x65,
+    0x20, 0x54, 0x77, 0x6f };
+
+  uint8_t test_exp128[AES_BLOCK_SIZE] = {
+    0x29, 0xc3, 0x50, 0x5f,
+    0x57, 0x14, 0x20, 0xf6,
+    0x40, 0x22, 0x99, 0xb3,
+    0x1a, 0x02, 0xd7, 0x3a };
+
+// add extra block[128] with all zeros to toggle bits low
+  uint8_t shift_patt[129*16] = {
+ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//127
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//128
+ };    
+
+  uint8_t shift_buf1[sizeof(shift_patt)];
+  uint8_t shift_buf2[sizeof(shift_patt)];
+
+
+/* Note:  Hardware supports byte, half-word or word accesses
+   So memcpy() can be used to load/save data
+   And memset() can be used to pad out data-in to 128-bits
+   mode =0 (bypass), =1 (encode) or =2 (decode)
+*/
+void aes128_driver_memcpy(uint8_t *key, uint32_t nbytes, uint8_t *input,
+                          uint8_t *result, uint8_t mode)
+{
+    // Reset engine
+    AES128->DRQ_MSK = 0;
+    AES128->IRQ_MSK = 0;
+    AES128->QUAL    = 0;
+    AES128->CTRL    = AES128_CTRL_KEY_REQ_BIT | AES128_CTRL_IP_REQ_BIT | AES128_CTRL_OP_REQ_BIT | AES128_CTRL_ERR_REQ_BIT;
+
+    // Set up parameters
+    if (mode == 1)
+      AES128->CTRL_SET = AES128_ENCODE_BIT; // ENCODE mode
+    if (mode == 0)
+      AES128->CTRL_SET = AES128_BYPASS_BIT; // BYPASS mode
+
+    AES128->IRQ_MSK_SET = (AES128_ERR_REQ_BIT | AES128_KEY_REQ_BIT | AES128_IP_REQ_BIT | AES128_OP_REQ_BIT);
+    
+    // Program Key
+    os_memcpy((uint8_t *)AES128->KEY128, key, AES_KEY_LEN_128);
+    while (!(AES128->STATUS & AES128_KEYOK_BIT))
+         ;
+
+    /* payload */
+    while(nbytes) {
+       uint8_t len = (nbytes > AES_BLOCK_SIZE) ? AES_BLOCK_SIZE : nbytes;            
+       /* Align/pad input and load into hardware */
+       os_memcpy((uint8_t *)AES128->TXTIP128, input, len);
+       //patch up any zero-padding
+       if (len < AES_BLOCK_SIZE)
+           os_memset((uint8_t *)&(AES128->TXTIP128[len]), 0, AES_BLOCK_SIZE-len);
+       /* Auto-started! - no need for manual start */
+       /* Poll until completed */
+       while (!(AES128->STATUS & AES128_VALID_BIT))
+         ;
+       os_memcpy(result, (uint8_t *)AES128->TXTOP128, AES_BLOCK_SIZE);
+       /* Accounting */
+       input   += len;
+       result  += len;
+       nbytes -= len;
+       AES128->IRQ_MSK_SET = (AES128_IP_REQ_BIT | AES128_OP_REQ_BIT);
+    }
+    AES128->CTRL    = 0;
+}
+
+// wrapper functions
+
+void aes128_bypass_memcpy(uint8_t *key, uint32_t nbytes, uint8_t *input, uint8_t *result)
+       { aes128_driver_memcpy(key, nbytes, input, result, 0); }
+
+void aes128_encrypt_memcpy(uint8_t *key, uint32_t nbytes, uint8_t *input, uint8_t *result)
+       { aes128_driver_memcpy(key, nbytes, input, result, 1); }
+
+void aes128_decrypt_memcpy(uint8_t *key, uint32_t nbytes, uint8_t *input, uint8_t *result)
+       { aes128_driver_memcpy(key, nbytes, input, result, 2); }
+
+
+int aes128_buffer_verify(uint32_t buflen, uint8_t *buf_A, uint8_t *buf_B)
+{
+    int i, j, fail = 0;
+        for (i=0 ; i < buflen; i++) {
+            if (buf_A[i] != buf_B[i]){
+                fail = 1;
+                break;
+            }
+        }
+        if (fail) {
+            j=i; // print offending block
+            for (i=(j - (j%16)) ; i < (j-(j%16)+16); i++) {
+               if (i%16==0)
+                   printf(" //%03d\n", (i>>4));
+               printf("0x%02x,", buf_A[i]);
+           }
+        }
+        if (fail){
+            i=j;
+            printf("Verify compare FAIL\n      EXPECTED_RESULT[%2d]= 0x%02x, ACTUAL_RESULT= 0x%02x \n",i, buf_B[i], buf_A[i]);
+            return(-1);
+        }
+        return(0);
+}
+
+void aes128_driver_aligned_dma32(uint8_t *key, uint32_t nbytes, uint8_t *input,
+                                 uint8_t *result, uint8_t mode)
+{
+    int c;
+    // Reset engine
+    AES128->DRQ_MSK = 0;
+    AES128->IRQ_MSK = 0;
+    AES128->QUAL    = 0;
+    AES128->CTRL    = AES128_CTRL_KEY_REQ_BIT | AES128_CTRL_IP_REQ_BIT | AES128_CTRL_OP_REQ_BIT;
+
+    // Set up parameters
+    if (mode == 1)
+      AES128->CTRL_SET = AES128_ENCODE_BIT; // ENCODE mode
+    if (mode == 0)
+      AES128->CTRL_SET = AES128_BYPASS_BIT; // BYPASS mode
+    
+    dma_pl230_data_struct_init(); // initialize
+    
+    // program DMA transfers in multiples of 4 words (nbytes scaled >>2 for words)
+    aes_ip_chain[0].SrcEndPointer = DMA_PL230_PTR_END(key,PL230_XFER_W,4);
+    aes_ip_chain[0].DstEndPointer = DMA_PL230_PTR_END(&(AES128->KEY128[AES128_BUF_SIZE-16]),PL230_XFER_W,4);
+    aes_ip_chain[0].Control = DMA_PL230_CTRL(PL230_CTRL_CYCLE_DEV_CHAIN_ALT,PL230_XFER_W,4,PL230_CTRL_RPWR_4);
+
+    aes_ip_chain[1].SrcEndPointer = DMA_PL230_PTR_END(input,PL230_XFER_W,(nbytes>>2));
+    aes_ip_chain[1].DstEndPointer = DMA_PL230_PTR_END(&(AES128->TXTIP128[AES128_BUF_SIZE-nbytes]),PL230_XFER_W,(nbytes>>2));
+    aes_ip_chain[1].Control = DMA_PL230_CTRL(PL230_CTRL_CYCLE_BASIC,PL230_XFER_W,(nbytes>>2),PL230_CTRL_RPWR_4);
+
+    c=DMA_CHAN_AES128_IP;
+    dma_pl230_table->Primary[c].SrcEndPointer  = DMA_PL230_PTR_END(&(aes_ip_chain[0].SrcEndPointer), PL230_XFER_W,(2*4));
+    dma_pl230_table->Primary[c].DstEndPointer  = DMA_PL230_PTR_END(&(dma_pl230_table->Alternate[c]), PL230_XFER_W,(1*4));
+    dma_pl230_table->Primary[c].Control= DMA_PL230_CTRL_DSTFIX(PL230_CTRL_CYCLE_DEV_CHAIN_PRI,PL230_XFER_W,(2*4),PL230_CTRL_RPWR_4);
+
+    aes_op_chain[0].SrcEndPointer = DMA_PL230_PTR_END(&(AES128->TXTOP128[AES128_BUF_SIZE-nbytes]),PL230_XFER_W,(nbytes>>2));
+    aes_op_chain[0].DstEndPointer = DMA_PL230_PTR_END(result,PL230_XFER_W,(nbytes>>2));
+    aes_op_chain[0].Control = DMA_PL230_CTRL(PL230_CTRL_CYCLE_BASIC,PL230_XFER_W,(nbytes>>2),PL230_CTRL_RPWR_4);
+
+    c=DMA_CHAN_AES128_OP;        
+    dma_pl230_table->Primary[c].SrcEndPointer  = DMA_PL230_PTR_END(&(aes_op_chain[0].SrcEndPointer), PL230_XFER_W,(1*4));
+    dma_pl230_table->Primary[c].DstEndPointer  = DMA_PL230_PTR_END(&(dma_pl230_table->Alternate[c]), PL230_XFER_W,(1*4));
+    dma_pl230_table->Primary[c].Control= DMA_PL230_CTRL_DSTFIX(PL230_CTRL_CYCLE_DEV_CHAIN_PRI,PL230_XFER_W,(1*4),PL230_CTRL_RPWR_4);
+ 
+    // enable DMA controller channels
+    dma_pl230_init((1<<DMA_CHAN_AES128_OP) | (1<<DMA_CHAN_AES128_IP)); // two active
+
+    // and enable DMA requests
+    AES128->DRQ_MSK_SET = (AES128_KEY_REQ_BIT | AES128_IP_REQ_BIT | AES128_OP_REQ_BIT);
+    AES128->IRQ_MSK_SET = (AES128_ERR_REQ_BIT | AES128_KEY_REQ_BIT | AES128_IP_REQ_BIT | AES128_OP_REQ_BIT);
+    // test to ensure output DMA has started                            
+    while (!(dma_pl230_channel_active((1<<DMA_CHAN_AES128_OP))))
+      ;
+    while (dma_pl230_channel_active((1<<DMA_CHAN_AES128_OP)))
+      ;
+    while (dma_pl230_channel_active((1<<DMA_CHAN_AES128_OP)))
+      ;
+    AES128->DRQ_MSK = 0;
+    AES128->IRQ_MSK = 0;
+    DMA_PL230_DMAC->DMA_CFG = 0; /* Disable DMA controller for initialization */
+    dma_pl230_init(0); // none active
+    return;
+}
+
+void aes128_driver_dma8(uint8_t *key, uint32_t nbytes, uint8_t *input,
+                          uint8_t *result, uint8_t mode)
+{
+    int c;
+    // Reset engine
+    AES128->DRQ_MSK = 0;
+    AES128->IRQ_MSK = 0;
+    AES128->QUAL    = 0;
+    AES128->CTRL    = AES128_CTRL_KEY_REQ_BIT | AES128_CTRL_IP_REQ_BIT | AES128_CTRL_OP_REQ_BIT;
+
+    // Set up parameters
+    if (mode == 1)
+      AES128->CTRL_SET = AES128_ENCODE_BIT; // ENCODE mode
+    if (mode == 0)
+      AES128->CTRL_SET = AES128_BYPASS_BIT; // BYPASS mode
+    
+    dma_pl230_data_struct_init(); // initialize
+    
+    // program DMA transfers in multiples of 16 bytes
+    aes_ip_chain[0].SrcEndPointer = DMA_PL230_PTR_END(key,PL230_XFER_B,16);
+    aes_ip_chain[0].DstEndPointer = DMA_PL230_PTR_END(&(AES128->KEY128[AES128_BUF_SIZE-16]),PL230_XFER_B,16);
+    aes_ip_chain[0].Control = DMA_PL230_CTRL(PL230_CTRL_CYCLE_DEV_CHAIN_ALT,PL230_XFER_B,16,PL230_CTRL_RPWR_16);
+
+    aes_ip_chain[1].SrcEndPointer = DMA_PL230_PTR_END(input,PL230_XFER_B,(nbytes));
+    aes_ip_chain[1].DstEndPointer = DMA_PL230_PTR_END(&(AES128->TXTIP128[AES128_BUF_SIZE-nbytes]),PL230_XFER_B,(nbytes));
+    aes_ip_chain[1].Control = DMA_PL230_CTRL(PL230_CTRL_CYCLE_BASIC,PL230_XFER_B,(nbytes),PL230_CTRL_RPWR_16);
+
+    c=DMA_CHAN_AES128_IP;
+    dma_pl230_table->Primary[c].SrcEndPointer  = DMA_PL230_PTR_END(&(aes_ip_chain[0].SrcEndPointer), PL230_XFER_W, (2*4));
+    dma_pl230_table->Primary[c].DstEndPointer  = DMA_PL230_PTR_END(&(dma_pl230_table->Alternate[c]), PL230_XFER_W, (1*4));
+    dma_pl230_table->Primary[c].Control= DMA_PL230_CTRL_DSTFIX(PL230_CTRL_CYCLE_DEV_CHAIN_PRI,PL230_XFER_W,(2*4),PL230_CTRL_RPWR_4);
+
+    aes_op_chain[0].SrcEndPointer = DMA_PL230_PTR_END(&(AES128->TXTOP128[AES128_BUF_SIZE-nbytes]),PL230_XFER_B,(nbytes));
+    aes_op_chain[0].DstEndPointer = DMA_PL230_PTR_END(result,PL230_XFER_B,(nbytes));
+    aes_op_chain[0].Control = DMA_PL230_CTRL(PL230_CTRL_CYCLE_BASIC,PL230_XFER_B,(nbytes),PL230_CTRL_RPWR_16);
+
+    c=DMA_CHAN_AES128_OP;        
+    dma_pl230_table->Primary[c].SrcEndPointer  = DMA_PL230_PTR_END(&(aes_op_chain[0].SrcEndPointer), PL230_XFER_W,(1*4));
+    dma_pl230_table->Primary[c].DstEndPointer  = DMA_PL230_PTR_END(&(dma_pl230_table->Alternate[c]), PL230_XFER_W,(1*4));
+    dma_pl230_table->Primary[c].Control= DMA_PL230_CTRL_DSTFIX(PL230_CTRL_CYCLE_DEV_CHAIN_PRI,PL230_XFER_W,(1*4),PL230_CTRL_RPWR_4);
+ 
+    // enable DMA controller channels
+    dma_pl230_init((1<<DMA_CHAN_AES128_OP) | (1<<DMA_CHAN_AES128_IP)); // two active
+
+    // and enable DMA requests
+    AES128->DRQ_MSK_SET = (AES128_KEY_REQ_BIT | AES128_IP_REQ_BIT | AES128_OP_REQ_BIT);
+    AES128->IRQ_MSK_SET = (AES128_ERR_REQ_BIT | AES128_KEY_REQ_BIT | AES128_IP_REQ_BIT | AES128_OP_REQ_BIT);
+    // test to ensure output DMA has started                            
+    while (!(dma_pl230_channel_active(1<<DMA_CHAN_AES128_OP)))
+      ;
+    while (dma_pl230_channel_active(1<<DMA_CHAN_AES128_OP))
+      ;
+    while (dma_pl230_channel_active(1<<DMA_CHAN_AES128_OP))
+      ;
+    AES128->DRQ_MSK = 0;
+    AES128->IRQ_MSK = 0;
+    DMA_PL230_DMAC->DMA_CFG = 0; /* Disable DMA controller for initialization */
+    dma_pl230_init(0); // none active
+    return;
+}
+
+// wrapper functions
+
+void aes128_alignchk_block_dma(uint8_t *key, uint32_t nbytes, uint8_t *input, uint8_t *result, uint8_t mode)
+       { uint32_t dma_max = DMA_PL230_MAX_XFERS; // default to 1 K bytes
+         if (((((long)key) & 3)==0) && ((((long)input) & 3)==0) && ((((long)result) & 3)==0)) dma_max=(DMA_PL230_MAX_XFERS<<2);
+         while (nbytes >dma_max) {
+            if (dma_max == DMA_PL230_MAX_XFERS) // 1K bytes DMA
+              aes128_driver_dma8(key, dma_max, input, result, mode);
+            else // 1K words DMA
+              aes128_driver_aligned_dma32(key, dma_max, input, result, mode);
+           nbytes -= dma_max; input  += dma_max; result += dma_max;
+         }
+         if (dma_max == DMA_PL230_MAX_XFERS) // up to 1K bytes remaining
+           aes128_driver_dma8(key, nbytes, input, result, mode);
+         else // up to 1K words remaining
+           aes128_driver_aligned_dma32(key, nbytes, input, result, mode);
+       }
+
+void aes128_bypass_dma(uint8_t *key, uint32_t nbytes, uint8_t *input, uint8_t *result) 
+       { aes128_alignchk_block_dma (key, nbytes, input, result, 0); }
+
+void aes128_encrypt_dma(uint8_t *key, uint32_t nbytes, uint8_t *input, uint8_t *result)
+       { aes128_alignchk_block_dma (key, nbytes, input, result, 1); }
+
+void aes128_decrypt_dma(uint8_t *key, uint32_t nbytes, uint8_t *input, uint8_t *result)
+       { aes128_alignchk_block_dma (key, nbytes, input, result, 2); }
+
+
+int main(void) {
+	char rx_char [256] = "soclabs AES128v1"; // init to 0
+	unsigned char id_string [16] = {0};
+	int  i, fail=0;
+        unsigned char * p;
+        
+		UartStdOutInit();
+		printf("%s\n",rx_char);
+		printf("AES128 test program\n");
+		printf("  AES128 ID: ");
+ 	        // iterate over 3 32-bit fields
+                p = (unsigned char *)AES128->CORE_NAME;
+	        for (i = 0; i < 12; i++) {
+                  id_string[i^3]=*p; // fix byte ordering per word
+                  p+=1;
+                  }
+                id_string[12] = 0; 
+		printf("%s\n",id_string);
+
+                aes_key_irq_occurred = 0;
+                aes_key_irq_expected = 1;
+                NVIC_ClearPendingIRQ(EXP0_IRQn);
+                NVIC_EnableIRQ(EXP0_IRQn);
+                aes_ip_irq_occurred = 0;
+                aes_ip_irq_expected = 1;
+                NVIC_ClearPendingIRQ(EXP1_IRQn);
+                NVIC_EnableIRQ(EXP1_IRQn);
+                aes_op_irq_occurred = 0;
+                aes_op_irq_expected = 1;
+                NVIC_ClearPendingIRQ(EXP2_IRQn);
+                NVIC_EnableIRQ(EXP2_IRQn);
+                aes_err_irq_occurred = 0;
+                aes_err_irq_expected = 1;
+                NVIC_ClearPendingIRQ(EXP3_IRQn);
+                NVIC_EnableIRQ(EXP3_IRQn);
+
+		printf("AES128 SW (memcpy) tests...\n");
+ 		printf("  AES128 reference pattern test\n");
+
+ 		printf("    AES128 input/output bypass test\n");
+                aes128_bypass_memcpy(test_key128, sizeof(test_text128), test_text128, buf128);
+                fail += aes128_buffer_verify(AES_BLOCK_SIZE, buf128, test_text128);
+
+               if (aes_key_irq_occurred != 1){ fail++;
+                   printf("    ++ AES key request IRQ count = %d\n", aes_key_irq_occurred); }
+               if (aes_ip_irq_occurred != 2){ fail++;
+                   printf("    ++ AES inp request missing: IRQ count = %d\n", aes_ip_irq_occurred); }
+               if (aes_op_irq_occurred != 1){ fail++;
+                   printf("    ++ AES out request missing: IRQ count = %d\n", aes_op_irq_occurred); }
+               if (aes_err_irq_occurred != 0){ fail++;
+                   printf("    ++ AES err request missing: IRQ count = %d\n", aes_err_irq_occurred); }
+
+		printf("    AES128 encrypt test\n");
+                aes128_encrypt_memcpy(test_key128, sizeof(test_text128), test_text128, buf128); 
+                fail += aes128_buffer_verify(AES_BLOCK_SIZE, buf128, test_exp128);
+
+ 		printf("    AES128 decrypt test\n");
+                aes128_decrypt_memcpy(test_key128, sizeof(buf128), buf128, buf128);
+                fail += aes128_buffer_verify(AES_BLOCK_SIZE, buf128, test_text128);
+
+                aes_key_irq_occurred = 0;
+                aes_ip_irq_occurred = 0;
+                aes_op_irq_occurred = 0;
+                aes_err_irq_occurred = 0;
+
+ 		printf("  AES128 logic toggle test\n");
+		printf("    AES128 input/output pattern test\n");
+                aes128_bypass_memcpy(test_key128, sizeof(shift_patt), shift_patt, shift_buf1); 
+                fail += aes128_buffer_verify(sizeof(shift_patt), shift_buf1, shift_patt);
+
+               if (aes_key_irq_occurred != 1){ fail++;
+                   printf("    ++ AES key request IRQ count = %d\n", aes_key_irq_occurred); }
+               if (aes_ip_irq_occurred != (129+1)){ fail++;
+                   printf("    ++ AES inp request missing: IRQ count = %d\n", aes_ip_irq_occurred); }
+               if (aes_op_irq_occurred != 129){ fail++;
+                   printf("    ++ AES out request missing: IRQ count = %d\n", aes_op_irq_occurred); }
+               if (aes_err_irq_occurred != 0){ fail++;
+                   printf("    ++ AES err request missing: IRQ count = %d\n", aes_err_irq_occurred); }
+
+		printf("    AES128 pattern encrypt test\n");
+                aes128_encrypt_memcpy(test_key128, sizeof(shift_patt), shift_patt, shift_buf1); 
+ 		printf("    AES128 pattern decrypt test\n");
+                aes128_decrypt_memcpy(test_key128, sizeof(shift_patt), shift_buf1, shift_buf2); 
+                fail += aes128_buffer_verify(sizeof(shift_patt), shift_buf2, shift_patt);
+
+		printf("AES128 DMA tests...\n");
+
+                aes_key_irq_occurred = 0;
+                aes_ip_irq_occurred = 0;
+                aes_op_irq_occurred = 0;
+                aes_err_irq_occurred = 0;
+                dma_error_irq_expected = 0;
+                dma_error_irq_occurred = 0;
+                dma_done_irq_expected = 1;
+                dma_done_irq_occurred = 0;
+                NVIC_ClearPendingIRQ(DMA_IRQn);
+                NVIC_EnableIRQ(DMA_IRQn);
+
+ 		printf("  AES128 dma input/output bypass test\n");
+                aes128_bypass_dma(test_key128, sizeof(test_text128), test_text128, buf128);
+                fail += aes128_buffer_verify(AES_BLOCK_SIZE, buf128, test_text128);
+
+               if (dma_done_irq_occurred < 2){
+                  puts ("ERROR: DMA err IRQ missing");
+                  fail++;
+                 } else
+                   printf("    ++ DMA_DONE IRQ count = %d\n", dma_done_irq_occurred);
+
+		printf("  AES128 dma encrypt test\n");
+                aes128_encrypt_dma(test_key128, sizeof(test_text128), test_text128, buf128); 
+                fail += aes128_buffer_verify(AES_BLOCK_SIZE, buf128, test_exp128);
+
+ 		printf("  AES128 dma decrypt test\n");
+                aes128_decrypt_dma(test_key128, sizeof(buf128), buf128, buf128);
+                fail += aes128_buffer_verify(AES_BLOCK_SIZE, buf128, test_text128);
+
+               if (dma_done_irq_occurred < 6){
+                  puts ("ERROR: DMA err IRQ missing");
+                  fail++;
+                 } else
+                   printf("    ++ DMA_DONE IRQ count = %d\n", dma_done_irq_occurred);
+
+		printf("  AES128 dma unaligned pattern test\n");
+                aes128_bypass_dma(test_key128,(16*63), shift_patt, shift_buf1+3); 
+                fail += aes128_buffer_verify((16*63), shift_buf1+3, shift_patt);
+
+		printf("  AES128 dma input/output pattern test\n");
+                aes128_bypass_dma(test_key128, sizeof(shift_patt), shift_patt, shift_buf1); 
+                fail += aes128_buffer_verify(sizeof(shift_patt), shift_buf1, shift_patt);
+		printf("  AES128 dma pattern encrypt test\n");
+                aes128_encrypt_dma(test_key128, sizeof(shift_patt), shift_patt, shift_buf1); 
+ 		printf("  AES128 dma pattern decrypt test\n");
+                aes128_decrypt_dma(test_key128, sizeof(shift_patt), shift_buf1, shift_buf2); 
+                fail += aes128_buffer_verify(sizeof(shift_patt), shift_buf2, shift_patt);
+
+               if (dma_done_irq_occurred < (2*7)){
+                  puts ("ERROR: DMA err IRQ missing");
+                  fail++;
+                 } else
+                   printf("    ++ DMA_DONE IRQ count = %d\n", dma_done_irq_occurred);
+
+               // check IRQ masked by DRQs - except when Iinput buffer empty after DMA done
+               if (aes_key_irq_occurred != 0){ fail++;
+                   printf("    ++ AES key request IRQ count = %d\n", aes_key_irq_occurred); }
+               if (aes_ip_irq_occurred != 7){ fail++;
+                   printf("    ++ AES inp request missing: IRQ count = %d\n", aes_ip_irq_occurred); }
+               if (aes_op_irq_occurred != 0){ fail++;
+                   printf("    ++ AES out request missing: IRQ count = %d\n", aes_op_irq_occurred); }
+               if (aes_err_irq_occurred != 0){ fail++;
+                   printf("    ++ AES err request missing: IRQ count = %d\n", aes_err_irq_occurred); }
+
+                NVIC_DisableIRQ(DMA_IRQn);
+                NVIC_DisableIRQ(EXP0_IRQn);
+                NVIC_DisableIRQ(EXP1_IRQn);
+                NVIC_DisableIRQ(EXP2_IRQn);
+                NVIC_DisableIRQ(EXP3_IRQn);
+
+  		printf ("Data retrieved from the AES is: %s\n", id_string);
+		printf ("Data expected from the AES is: %s\n", rx_char);
+		if (fail >0)
+		  printf("** AES TESTS FAILED (%d)  **\n", fail);
+                else
+		  printf("** AES TEST PASSED **\n");
+		// End simulation
+
+
+  		UartEndSimulation();
+
+  	return 0;
+
+}
+	
+/* --------------------------------------------------------------- */
+/*  Interrupt handlers                                         */
+/* --------------------------------------------------------------- */
+
+void DMA_Handler(void)
+{
+if ((DMA_PL230_DMAC->ERR_CLR & 1) != 0)  {
+  /* DMA interrupt is caused by DMA error */
+  dma_error_irq_occurred ++;
+  DMA_PL230_DMAC->ERR_CLR = 1; /* Clear dma_err */
+  if (dma_error_irq_expected==0) {
+    puts ("ERROR : Unexpected DMA error interrupt occurred.\n");
+    UartEndSimulation();
+    while (1);
+    }
+  }
+else {
+  // DMA interrupt is caused by DMA done
+  dma_done_irq_occurred ++;
+  if (dma_done_irq_expected==0) {
+    puts ("ERROR : Unexpected DMA done interrupt occurred.\n");
+    UartEndSimulation();
+    while (1);
+    }
+  }
+}
+
+void EXP0_Handler(void)
+{
+  // AES128 interrupt is caused by Key buffer empty IRQ
+  aes_key_irq_occurred ++;
+  AES128->IRQ_MSK_CLR = AES128_KEY_REQ_BIT;
+  if (aes_key_irq_expected==0) {
+    puts ("ERROR : Unexpected AES128 Key buffer empty request interrupt occurred.\n");
+    UartEndSimulation();
+    while (1);
+    }
+}
+
+void EXP1_Handler(void)
+{
+  // AES128 interrupt is caused by Input buffer empty IRQ
+  aes_ip_irq_occurred ++;
+  AES128->IRQ_MSK_CLR = AES128_IP_REQ_BIT;
+  if (aes_ip_irq_expected==0) {
+    puts ("ERROR : Unexpected AES128 Input buffer empty reqest interrupt occurred.\n");
+    UartEndSimulation();
+    while (1);
+    }
+}
+
+void EXP2_Handler(void)
+{
+  // AES128 interrupt is caused by Output buffer full IRQ
+  aes_op_irq_occurred ++;
+  AES128->IRQ_MSK_CLR = AES128_OP_REQ_BIT;
+  if (aes_op_irq_expected==0) {
+    puts ("ERROR : Unexpected AES128 Output buffer full reqest interrupt occurred.\n");
+    UartEndSimulation();
+    while (1);
+    }
+}
+
+void EXP3_Handler(void)
+{
+  // AES128 interrupt is caused by Error IRQ
+  aes_err_irq_occurred ++;
+  AES128->IRQ_MSK_CLR = AES128_ERR_REQ_BIT;
+  if (aes_err_irq_expected==0) {
+    puts ("ERROR : Unexpected AES128 Error interrupt occurred.\n");
+    UartEndSimulation();
+    while (1);
+    }
+}
+
diff --git a/system/cpu_software/aes128_tests/dma_pl230_driver.c b/system/cpu_software/aes128_tests/dma_pl230_driver.c
new file mode 100644
index 0000000000000000000000000000000000000000..878146502e4b9f1d44f686d3f9f0df121ffcfe74
--- /dev/null
+++ b/system/cpu_software/aes128_tests/dma_pl230_driver.c
@@ -0,0 +1,163 @@
+#include <stdio.h>
+#include <string.h>
+#include "dma_pl230_driver.h"
+
+#define DEBUG_PRINTF(...) do {} while(0); 
+//#define cpu_to_be32(__x) __x
+//#define be32_to_cpu(__x) __x
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static int g_dma_pl230_initialised = 0;
+
+static dma_pl230_data_structure priv_dma __attribute__((aligned(256)));
+//
+dma_pl230_data_structure *dma_pl230_table = &priv_dma; 
+
+/* --------------------------------------------------------------- */
+/*  Initialize DMA data structure                                  */
+/* --------------------------------------------------------------- */
+void dma_pl230_data_struct_init(void)
+{
+  int          i;   /* loop counter */
+
+//  printf ("dma structure block address = %x\n", dma_pl230_table);
+  for (i=0; i<MAX_NUM_OF_DMA_CHANNELS; i++) {
+    dma_pl230_table->Primary[i].SrcEndPointer   = 0;
+    dma_pl230_table->Primary[i].DstEndPointer   = 0;
+    dma_pl230_table->Primary[i].Control         = 0;
+    dma_pl230_table->Alternate[i].SrcEndPointer = 0;
+    dma_pl230_table->Alternate[i].DstEndPointer = 0;
+    dma_pl230_table->Alternate[i].Control       = 0;
+    }
+  g_dma_pl230_initialised = 1;
+  return;
+}
+
+void dma_pl230_data_struct_init_dbg(void)
+{
+  int          i;   /* loop counter */
+  unsigned int ptr;
+
+  int          ch_num;         /* number of channels */
+  unsigned int blksize;        /* Size of DMA data structure in bytes */
+  unsigned int blkmask;        /* address mask */
+
+
+  ch_num  = (((DMA_PL230_DMAC->DMA_STATUS) >> 16) & 0x1F)+1;
+  blksize = ch_num * 32;
+  if      (ch_num > 16) blkmask = 0x3FF; /* 17 to 32 */
+  else if (ch_num > 8)  blkmask = 0x1FF; /*  9 to 16 */
+  else if (ch_num > 4)  blkmask = 0x0FF; /*  5 to 8 */
+  else if (ch_num > 2)  blkmask = 0x07F; /*  3 to 4 */
+  else if (ch_num > 1)  blkmask = 0x03F; /*       2 */
+  else                  blkmask = 0x01F; /*       1 */
+
+
+  /* Create DMA data structure in RAM after stack
+  In the linker script, a 1KB memory stack above stack is reserved
+  so we can use this space for putting the DMA data structure.
+  */
+
+//  ptr     = HW32_REG(0);                     /* Read Top of Stack */
+  ptr     = (0x80000000); // force for now as no reserved RAM available
+  
+  /* the DMA data structure must be aligned to the size of the data structure */
+  if ((ptr & blkmask) != 0x0)
+    ptr     = (ptr + blksize) & ~blkmask;
+
+///  if ((ptr + blksize) > (RAM_ADDRESS_MAX + 1)) {
+///    puts ("ERROR : Not enough RAM space for DMA data structure.");
+///    UartEndSimulation();
+///    }
+
+  /* Set pointer to the reserved space */
+  dma_pl230_table = (dma_pl230_data_structure *) ptr;
+  ptr = (unsigned long) &(dma_pl230_table->Primary[0].SrcEndPointer);
+
+  printf ("dma structure block address = %x\n", ptr);
+
+  for (i=0; i<MAX_NUM_OF_DMA_CHANNELS; i++) {
+    dma_pl230_table->Primary[i].SrcEndPointer   = 0;
+    dma_pl230_table->Primary[i].DstEndPointer   = 0;
+    dma_pl230_table->Primary[i].Control         = 0;
+    dma_pl230_table->Alternate[i].SrcEndPointer = 0;
+    dma_pl230_table->Alternate[i].DstEndPointer = 0;
+    dma_pl230_table->Alternate[i].Control       = 0;
+    }
+  g_dma_pl230_initialised = 1;
+  return;
+}
+/* --------------------------------------------------------------- */
+/*  Initialize DMA PL230                                           */
+/* --------------------------------------------------------------- */
+void dma_pl230_init_dbg(unsigned int chan_mask)
+{
+  unsigned int current_state;
+  puts ("Initialize PL230");
+  current_state = DMA_PL230_DMAC->DMA_STATUS;
+  printf ("- # of channels allowed : %d\n",(((current_state) >> 16) & 0x1F)+1);
+  /* Debugging printfs: */
+  printf ("- Current status        : %x\n",(((current_state) >> 4)  & 0xF));
+  printf ("- Current master enable : %x\n",(((current_state) >> 0)  & 0x1));
+
+  /* Wait until current DMA complete */
+  current_state = (DMA_PL230_DMAC->DMA_STATUS >> 4)  & 0xF;
+  if (!((current_state==0) || (current_state==0x8) || (current_state==0x9))) {
+    puts ("- wait for DMA IDLE/STALLED/DONE");
+    current_state = (DMA_PL230_DMAC->DMA_STATUS >> 4)  & 0xF;
+    printf ("- Current status        : %x\n",(((current_state) >> 4)  & 0xF));
+
+    }
+  while (!((current_state==0) || (current_state==0x8) || (current_state==0x9))){
+    /* Wait if not IDLE/STALLED/DONE */
+    current_state = (DMA_PL230_DMAC->DMA_STATUS >> 4)  & 0xF;
+    printf ("- Current status        : %x\n",(((current_state) >> 4)  & 0xF));
+    }
+  DMA_PL230_DMAC->DMA_CFG = 0; /* Disable DMA controller for initialization */
+  DMA_PL230_DMAC->CTRL_BASE_PTR = (unsigned long) &(dma_pl230_table->Primary->SrcEndPointer);
+                           /* Set DMA data structure address */
+  DMA_PL230_DMAC->CHNL_ENABLE_CLR = 0xFFFFFFFF; /* Disable all channels */
+  DMA_PL230_DMAC->CHNL_PRI_ALT_CLR = ((1<<MAX_NUM_OF_DMA_CHANNELS)-1); /* Disable all alt channels */
+  DMA_PL230_DMAC->CHNL_ENABLE_SET = (chan_mask & ((1<<MAX_NUM_OF_DMA_CHANNELS)-1)); /* Enable channel */
+  DMA_PL230_DMAC->CHNL_USEBURST_SET = (chan_mask & ((1<<MAX_NUM_OF_DMA_CHANNELS)-1)); /* Enable bursts */
+  if (chan_mask)
+    DMA_PL230_DMAC->DMA_CFG = 1;              /* Enable DMA controller if enabled channel*/
+  return;
+}
+
+void dma_pl230_init(unsigned int chan_mask)
+{
+  unsigned int current_state;
+  if (g_dma_pl230_initialised ==0)
+    dma_pl230_data_struct_init();
+  /* Wait until current DMA complete */
+  current_state = (DMA_PL230_DMAC->DMA_STATUS >> 4)  & 0xF;
+  while (!((current_state==0) || (current_state==0x8) || (current_state==0x9))){
+    /* Wait if not IDLE/STALLED/DONE */
+    puts ("- wait for DMA IDLE/STALLED/DONE");
+    current_state = (DMA_PL230_DMAC->DMA_STATUS >> 4)  & 0xF;
+    }
+  DMA_PL230_DMAC->DMA_CFG = 0; /* Disable DMA controller for initialization */
+  DMA_PL230_DMAC->CTRL_BASE_PTR = (unsigned long) &(dma_pl230_table->Primary->SrcEndPointer);
+                           /* Set DMA data structure address */
+  DMA_PL230_DMAC->CHNL_ENABLE_CLR  = ((1<<MAX_NUM_OF_DMA_CHANNELS)-1); /* Disable all channels */
+  DMA_PL230_DMAC->CHNL_PRI_ALT_CLR = ((1<<MAX_NUM_OF_DMA_CHANNELS)-1); /* Disable all alt channels */
+  DMA_PL230_DMAC->CHNL_ENABLE_SET  = (chan_mask & ((1<<MAX_NUM_OF_DMA_CHANNELS)-1)); /* Enable channel */
+  DMA_PL230_DMAC->CHNL_USEBURST_SET = (chan_mask & ((1<<MAX_NUM_OF_DMA_CHANNELS)-1)); /* Enable bursts */
+  g_dma_pl230_initialised = 2;
+  if (chan_mask)
+    DMA_PL230_DMAC->DMA_CFG = 1;              /* Enable DMA controller if enabled channel*/
+  return;
+}
+
+unsigned int dma_pl230_channel_active(unsigned int chan_mask)
+{
+  return(DMA_PL230_DMAC->CHNL_ENABLE_SET & chan_mask & ((1<<MAX_NUM_OF_DMA_CHANNELS)-1)); /* Enabled channels */
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/system/cpu_software/aes128_tests/dma_pl230_driver.h b/system/cpu_software/aes128_tests/dma_pl230_driver.h
new file mode 100644
index 0000000000000000000000000000000000000000..082b196ab13b993867815b4ff5f91ff5cf1588a0
--- /dev/null
+++ b/system/cpu_software/aes128_tests/dma_pl230_driver.h
@@ -0,0 +1,198 @@
+#ifndef __DMA_PL230_MCU_H
+#define __DMA_PL230_MCU_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include  "CMSDK_CM0.h"
+
+#define DMA_PL230_BASE        (CMSDK_APB_BASE + 0xF000UL)
+
+#define MAX_NUM_OF_DMA_CHANNELS   2
+
+/*------------- PL230 uDMA (PL230) --------------------------------------*/
+/** @addtogroup DMA_PL230 CMSDK uDMA controller
+  @{
+*/
+typedef struct
+{
+  __I    uint32_t  DMA_STATUS;           /*!< Offset: 0x000 DMA status Register (R/W) */
+  __O    uint32_t  DMA_CFG;              /*!< Offset: 0x004 DMA configuration Register ( /W) */
+  __IO   uint32_t  CTRL_BASE_PTR;        /*!< Offset: 0x008 Channel Control Data Base Pointer Register  (R/W) */
+  __I    uint32_t  ALT_CTRL_BASE_PTR;    /*!< Offset: 0x00C Channel Alternate Control Data Base Pointer Register  (R/ ) */
+  __I    uint32_t  DMA_WAITONREQ_STATUS; /*!< Offset: 0x010 Channel Wait On Request Status Register  (R/ ) */
+  __O    uint32_t  CHNL_SW_REQUEST;      /*!< Offset: 0x014 Channel Software Request Register  ( /W) */
+  __IO   uint32_t  CHNL_USEBURST_SET;    /*!< Offset: 0x018 Channel UseBurst Set Register  (R/W) */
+  __O    uint32_t  CHNL_USEBURST_CLR;    /*!< Offset: 0x01C Channel UseBurst Clear Register  ( /W) */
+  __IO   uint32_t  CHNL_REQ_MASK_SET;    /*!< Offset: 0x020 Channel Request Mask Set Register  (R/W) */
+  __O    uint32_t  CHNL_REQ_MASK_CLR;    /*!< Offset: 0x024 Channel Request Mask Clear Register  ( /W) */
+  __IO   uint32_t  CHNL_ENABLE_SET;      /*!< Offset: 0x028 Channel Enable Set Register  (R/W) */
+  __O    uint32_t  CHNL_ENABLE_CLR;      /*!< Offset: 0x02C Channel Enable Clear Register  ( /W) */
+  __IO   uint32_t  CHNL_PRI_ALT_SET;     /*!< Offset: 0x030 Channel Primary-Alterante Set Register  (R/W) */
+  __O    uint32_t  CHNL_PRI_ALT_CLR;     /*!< Offset: 0x034 Channel Primary-Alterante Clear Register  ( /W) */
+  __IO   uint32_t  CHNL_PRIORITY_SET;    /*!< Offset: 0x038 Channel Priority Set Register  (R/W) */
+  __O    uint32_t  CHNL_PRIORITY_CLR;    /*!< Offset: 0x03C Channel Priority Clear Register  ( /W) */
+         uint32_t  RESERVED0[3];
+  __IO   uint32_t  ERR_CLR;              /*!< Offset: 0x04C Bus Error Clear Register  (R/W) */
+
+} DMA_PL230_TypeDef;
+
+#define PL230_DMA_CHNL_BITS 0
+
+#define DMA_PL230_DMA_STATUS_MSTREN_Pos          0                                                          /*!< DMA_PL230 DMA STATUS: MSTREN Position */
+#define DMA_PL230_DMA_STATUS_MSTREN_Msk          (0x00000001ul << DMA_PL230_DMA_STATUS_MSTREN_Pos)        /*!< DMA_PL230 DMA STATUS: MSTREN Mask */
+
+#define DMA_PL230_DMA_STATUS_STATE_Pos           0                                                          /*!< DMA_PL230 DMA STATUS: STATE Position */
+#define DMA_PL230_DMA_STATUS_STATE_Msk           (0x0000000Ful << DMA_PL230_DMA_STATUS_STATE_Pos)         /*!< DMA_PL230 DMA STATUS: STATE Mask */
+
+#define DMA_PL230_DMA_STATUS_CHNLS_MINUS1_Pos    0                                                          /*!< DMA_PL230 DMA STATUS: CHNLS_MINUS1 Position */
+#define DMA_PL230_DMA_STATUS_CHNLS_MINUS1_Msk    (0x0000001Ful << DMA_PL230_DMA_STATUS_CHNLS_MINUS1_Pos)  /*!< DMA_PL230 DMA STATUS: CHNLS_MINUS1 Mask */
+
+#define DMA_PL230_DMA_STATUS_TEST_STATUS_Pos     0                                                          /*!< DMA_PL230 DMA STATUS: TEST_STATUS Position */
+#define DMA_PL230_DMA_STATUS_TEST_STATUS_Msk     (0x00000001ul << DMA_PL230_DMA_STATUS_TEST_STATUS_Pos)   /*!< DMA_PL230 DMA STATUS: TEST_STATUS Mask */
+
+#define DMA_PL230_DMA_CFG_MSTREN_Pos             0                                                          /*!< DMA_PL230 DMA CFG: MSTREN Position */
+#define DMA_PL230_DMA_CFG_MSTREN_Msk             (0x00000001ul << DMA_PL230_DMA_CFG_MSTREN_Pos)           /*!< DMA_PL230 DMA CFG: MSTREN Mask */
+
+#define DMA_PL230_DMA_CFG_CPCCACHE_Pos           2                                                          /*!< DMA_PL230 DMA CFG: CPCCACHE Position */
+#define DMA_PL230_DMA_CFG_CPCCACHE_Msk           (0x00000001ul << DMA_PL230_DMA_CFG_CPCCACHE_Pos)         /*!< DMA_PL230 DMA CFG: CPCCACHE Mask */
+
+#define DMA_PL230_DMA_CFG_CPCBUF_Pos             1                                                          /*!< DMA_PL230 DMA CFG: CPCBUF Position */
+#define DMA_PL230_DMA_CFG_CPCBUF_Msk             (0x00000001ul << DMA_PL230_DMA_CFG_CPCBUF_Pos)           /*!< DMA_PL230 DMA CFG: CPCBUF Mask */
+
+#define DMA_PL230_DMA_CFG_CPCPRIV_Pos            0                                                          /*!< DMA_PL230 DMA CFG: CPCPRIV Position */
+#define DMA_PL230_DMA_CFG_CPCPRIV_Msk            (0x00000001ul << DMA_PL230_DMA_CFG_CPCPRIV_Pos)          /*!< DMA_PL230 DMA CFG: CPCPRIV Mask */
+
+#define DMA_PL230_CTRL_BASE_PTR_Pos              PL230_DMA_CHNL_BITS + 5                                    /*!< DMA_PL230 STATUS: BASE_PTR Position */
+#define DMA_PL230_CTRL_BASE_PTR_Msk              (0x0FFFFFFFul << DMA_PL230_CTRL_BASE_PTR_Pos)            /*!< DMA_PL230 STATUS: BASE_PTR Mask */
+
+#define DMA_PL230_ALT_CTRL_BASE_PTR_Pos          0                                                          /*!< DMA_PL230 STATUS: MSTREN Position */
+#define DMA_PL230_ALT_CTRL_BASE_PTR_Msk          (0xFFFFFFFFul << DMA_PL230_ALT_CTRL_BASE_PTR_Pos)        /*!< DMA_PL230 STATUS: MSTREN Mask */
+
+#define DMA_PL230_DMA_WAITONREQ_STATUS_Pos       0                                                          /*!< DMA_PL230 DMA_WAITONREQ_STATUS: DMA_WAITONREQ_STATUS Position */
+#define DMA_PL230_DMA_WAITONREQ_STATUS_Msk       (0xFFFFFFFFul << DMA_PL230_DMA_WAITONREQ_STATUS_Pos)     /*!< DMA_PL230 DMA_WAITONREQ_STATUS: DMA_WAITONREQ_STATUS Mask */
+
+#define DMA_PL230_CHNL_SW_REQUEST_Pos            0                                                          /*!< DMA_PL230 CHNL_SW_REQUEST: CHNL_SW_REQUEST Position */
+#define DMA_PL230_CHNL_SW_REQUEST_Msk            (0xFFFFFFFFul << DMA_PL230_CHNL_SW_REQUEST_Pos)          /*!< DMA_PL230 CHNL_SW_REQUEST: CHNL_SW_REQUEST Mask */
+
+#define DMA_PL230_CHNL_USEBURST_SET_Pos          0                                                          /*!< DMA_PL230 CHNL_USEBURST: SET Position */
+#define DMA_PL230_CHNL_USEBURST_SET_Msk          (0xFFFFFFFFul << DMA_PL230_CHNL_USEBURST_SET_Pos)        /*!< DMA_PL230 CHNL_USEBURST: SET Mask */
+
+#define DMA_PL230_CHNL_USEBURST_CLR_Pos          0                                                          /*!< DMA_PL230 CHNL_USEBURST: CLR Position */
+#define DMA_PL230_CHNL_USEBURST_CLR_Msk          (0xFFFFFFFFul << DMA_PL230_CHNL_USEBURST_CLR_Pos)        /*!< DMA_PL230 CHNL_USEBURST: CLR Mask */
+
+#define DMA_PL230_CHNL_REQ_MASK_SET_Pos          0                                                          /*!< DMA_PL230 CHNL_REQ_MASK: SET Position */
+#define DMA_PL230_CHNL_REQ_MASK_SET_Msk          (0xFFFFFFFFul << DMA_PL230_CHNL_REQ_MASK_SET_Pos)        /*!< DMA_PL230 CHNL_REQ_MASK: SET Mask */
+
+#define DMA_PL230_CHNL_REQ_MASK_CLR_Pos          0                                                          /*!< DMA_PL230 CHNL_REQ_MASK: CLR Position */
+#define DMA_PL230_CHNL_REQ_MASK_CLR_Msk          (0xFFFFFFFFul << DMA_PL230_CHNL_REQ_MASK_CLR_Pos)        /*!< DMA_PL230 CHNL_REQ_MASK: CLR Mask */
+
+#define DMA_PL230_CHNL_ENABLE_SET_Pos            0                                                          /*!< DMA_PL230 CHNL_ENABLE: SET Position */
+#define DMA_PL230_CHNL_ENABLE_SET_Msk            (0xFFFFFFFFul << DMA_PL230_CHNL_ENABLE_SET_Pos)          /*!< DMA_PL230 CHNL_ENABLE: SET Mask */
+
+#define DMA_PL230_CHNL_ENABLE_CLR_Pos            0                                                          /*!< DMA_PL230 CHNL_ENABLE: CLR Position */
+#define DMA_PL230_CHNL_ENABLE_CLR_Msk            (0xFFFFFFFFul << DMA_PL230_CHNL_ENABLE_CLR_Pos)          /*!< DMA_PL230 CHNL_ENABLE: CLR Mask */
+
+#define DMA_PL230_CHNL_PRI_ALT_SET_Pos           0                                                          /*!< DMA_PL230 CHNL_PRI_ALT: SET Position */
+#define DMA_PL230_CHNL_PRI_ALT_SET_Msk           (0xFFFFFFFFul << DMA_PL230_CHNL_PRI_ALT_SET_Pos)         /*!< DMA_PL230 CHNL_PRI_ALT: SET Mask */
+
+#define DMA_PL230_CHNL_PRI_ALT_CLR_Pos           0                                                          /*!< DMA_PL230 CHNL_PRI_ALT: CLR Position */
+#define DMA_PL230_CHNL_PRI_ALT_CLR_Msk           (0xFFFFFFFFul << DMA_PL230_CHNL_PRI_ALT_CLR_Pos)         /*!< DMA_PL230 CHNL_PRI_ALT: CLR Mask */
+
+#define DMA_PL230_CHNL_PRIORITY_SET_Pos          0                                                          /*!< DMA_PL230 CHNL_PRIORITY: SET Position */
+#define DMA_PL230_CHNL_PRIORITY_SET_Msk          (0xFFFFFFFFul << DMA_PL230_CHNL_PRIORITY_SET_Pos)        /*!< DMA_PL230 CHNL_PRIORITY: SET Mask */
+
+#define DMA_PL230_CHNL_PRIORITY_CLR_Pos          0                                                          /*!< DMA_PL230 CHNL_PRIORITY: CLR Position */
+#define DMA_PL230_CHNL_PRIORITY_CLR_Msk          (0xFFFFFFFFul << DMA_PL230_CHNL_PRIORITY_CLR_Pos)        /*!< DMA_PL230 CHNL_PRIORITY: CLR Mask */
+
+#define DMA_PL230_ERR_CLR_Pos                    0                                                          /*!< DMA_PL230 ERR: CLR Position */
+#define DMA_PL230_ERR_CLR_Msk                    (0x00000001ul << DMA_PL230_ERR_CLR_Pos)                  /*!< DMA_PL230 ERR: CLR Mask */
+
+
+#define HW32_REG(ADDRESS)  (*((volatile unsigned long  *)(ADDRESS)))
+
+                              /* Maximum to 32 DMA channel */
+                              /* SRAM in example system is 64K bytes */
+#define RAM_ADDRESS_MAX       0x80001fff
+
+typedef struct /* 4 words */
+{
+  volatile unsigned char* SrcEndPointer;
+  volatile unsigned char* DstEndPointer;
+  volatile unsigned long Control;
+  volatile unsigned long unused;
+} dma_pl230_channel_data;
+
+
+typedef struct /* 8 words per channel */
+{ /* was one channel in the example uDMA setup */
+  volatile dma_pl230_channel_data Primary[MAX_NUM_OF_DMA_CHANNELS];
+  volatile dma_pl230_channel_data Alternate[MAX_NUM_OF_DMA_CHANNELS];
+} dma_pl230_data_structure;
+
+
+extern dma_pl230_data_structure *dma_pl230_table;
+
+#define DMA_PL230_DMAC   ((DMA_PL230_TypeDef *)  DMA_PL230_BASE)
+
+#define DMA_PL230_PTR_END(__ptr, __siz, __num) \
+	((unsigned char *) __ptr + ((1<<__siz)*(__num-1)))
+
+#define DMA_PL230_CTRL(__cyc, __siz, __num, __rpwr) \
+	(((unsigned long) __siz << 30)|(__siz << 28)|(__siz << 26)|(__siz << 24)| \
+         (1     << 21)|(1     << 18)|(__rpwr << 14)|(((__num-1)&0x3ff)<<4)| \
+         (1     <<  3)|(__cyc <<  0) )
+
+#define DMA_PL230_CTRL_SRCFIX(__cyc, __siz, __num, __rpwr) \
+	(((unsigned long) __siz << 30)|(__siz << 28)|(0x0c000000UL)|(__siz << 24)| \
+         (1     << 21)|(1     << 18)|(__rpwr << 14)|(((__num-1)&0x3ff)<<4)| \
+         (1     <<  3)|(__cyc <<  0) )
+
+#define DMA_PL230_CTRL_DSTFIX(__cyc, __siz, __num, __rpwr) \
+	((0xc0000000UL)|(__siz << 28)|(__siz << 26)|(__siz << 24)| \
+         (1     << 21)|(1     << 18)|(__rpwr << 14)|(((__num-1)&0x3ff)<<4)| \
+         (1     <<  3)|(__cyc <<  0) )
+
+#define DMA_PL230_MAX_XFERS (0x400)
+
+#define PL230_CTRL_CYCLE_STOP    0
+#define PL230_CTRL_CYCLE_BASIC   1
+#define PL230_CTRL_CYCLE_AUTO    2
+#define PL230_CTRL_CYCLE_PPONG   3
+#define PL230_CTRL_CYCLE_MEM_CHAIN_PRI 4
+#define PL230_CTRL_CYCLE_MEM_CHAIN_ALT 5
+#define PL230_CTRL_CYCLE_DEV_CHAIN_PRI 6
+#define PL230_CTRL_CYCLE_DEV_CHAIN_ALT 7
+
+#define PL230_CTRL_RPWR_1  0
+#define PL230_CTRL_RPWR_2  1
+#define PL230_CTRL_RPWR_4  2
+#define PL230_CTRL_RPWR_8  3
+#define PL230_CTRL_RPWR_16 4
+
+#define PL230_XFER_B    0
+#define PL230_XFER_H    1
+#define PL230_XFER_W    2
+
+/* --------------------------------------------------------------- */
+/*  Initialize DMA data structure                                  */
+/* --------------------------------------------------------------- */
+void dma_pl230_data_struct_init(void);
+
+/* --------------------------------------------------------------- */
+/*  Initialize DMA PL230                                           */
+/* --------------------------------------------------------------- */
+void dma_pl230_init_dbg(unsigned int chan_mask);
+void dma_pl230_init(unsigned int chan_mask);
+
+/* --------------------------------------------------------------- */
+/*  Check DMA PL230 DMA channel(s) active (return 0 when finishes) */
+/* --------------------------------------------------------------- */
+unsigned int dma_pl230_channel_active(unsigned int chan_mask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DMA_PL230_MCU_H */
+
diff --git a/system/cpu_software/aes128_tests/makefile b/system/cpu_software/aes128_tests/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..965b6ef9ee7d004b7db2c4c65f740aa979634c60
--- /dev/null
+++ b/system/cpu_software/aes128_tests/makefile
@@ -0,0 +1,258 @@
+#-----------------------------------------------------------------------------
+# The confidential and proprietary information contained in this file may
+# only be used by a person authorised under and to the extent permitted
+# by a subsisting licensing agreement from Arm Limited or its affiliates.
+#
+#            (C) COPYRIGHT 2010-2013 Arm Limited or its affiliates.
+#                ALL RIGHTS RESERVED
+#
+# This entire notice must be reproduced on all copies of this file
+# and copies of this file may only be made by a person if such person is
+# permitted to do so under the terms of a subsisting license agreement
+# from Arm Limited or its affiliates.
+#
+#      SVN Information
+#
+#      Checked In          : $Date: 2017-10-10 15:55:38 +0100 (Tue, 10 Oct 2017) $
+#
+#      Revision            : $Revision: 371321 $
+#
+#      Release Information : Cortex-M System Design Kit-r1p1-00rel0
+#-----------------------------------------------------------------------------
+#
+# Cortex-M System Design Kit software compilation make file
+#
+#-----------------------------------------------------------------------------
+#
+#  Configurations
+#
+# Choose the core instantiated, can be
+#  - CORTEX_M0
+#  - CORTEX_M0PLUS
+CPU_PRODUCT = CORTEX_M0
+
+# Shared software directory
+SOFTWARE_DIR = $(NANOSOC_TECH_DIR)/software
+CMSIS_DIR    = $(SOFTWARE_DIR)/cmsis
+CORE_DIR     = $(CMSIS_DIR)/CMSIS/Include
+
+ifeq ($(CPU_PRODUCT),CORTEX_M0PLUS)
+  DEVICE_DIR   = $(CMSIS_DIR)/Device/ARM/CMSDK_CM0plus
+else
+  DEVICE_DIR   = $(CMSIS_DIR)/Device/ARM/CMSDK_CM0
+endif
+
+# Program file
+TESTNAME     = aes128_tests
+
+# Endian Option
+COMPILE_BIGEND = 0
+
+# Configuration
+ifeq ($(CPU_PRODUCT),CORTEX_M0PLUS)
+  USER_DEFINE    = -DCORTEX_M0PLUS
+else
+  USER_DEFINE    = -DCORTEX_M0
+endif
+
+DEPS_LIST       = makefile
+
+# Tool chain : ds5 / gcc / keil
+TOOL_CHAIN      = ds5
+
+ifeq ($(TOOL_CHAIN),ds5)
+  ifeq ($(CPU_PRODUCT),CORTEX_M0PLUS)
+    CPU_TYPE        = --cpu Cortex-M0plus
+  else
+    CPU_TYPE        = --cpu Cortex-M0
+  endif
+endif
+
+ifeq ($(TOOL_CHAIN),gcc)
+  ifeq ($(CPU_PRODUCT),CORTEX_M0PLUS)
+    CPU_TYPE        = -mcpu=cortex-m0plus
+  else
+    CPU_TYPE        = -mcpu=cortex-m0
+  endif
+endif
+
+# Startup code directory for DS-5
+ifeq ($(TOOL_CHAIN),ds5)
+ STARTUP_DIR  = $(DEVICE_DIR)/Source/ARM
+endif
+
+# Startup code directory for gcc
+ifeq ($(TOOL_CHAIN),gcc)
+ STARTUP_DIR  = $(DEVICE_DIR)/Source/GCC
+endif
+
+ifeq ($(CPU_PRODUCT),CORTEX_M0PLUS)
+  STARTUP_FILE = startup_CMSDK_CM0plus
+  SYSTEM_FILE  = system_CMSDK_CM0plus
+else
+  STARTUP_FILE = startup_CMSDK_CM0
+  SYSTEM_FILE  = system_CMSDK_CM0
+endif
+
+# ---------------------------------------------------------------------------------------
+# DS-5 options
+
+# MicroLIB option
+COMPILE_MICROLIB = 0
+
+# Small Multiply (Cortex-M0/M0+ has small multiplier option)
+COMPILE_SMALLMUL = 0
+
+#ARM_CC_OPTIONS   = -c -O3 -g -Otime -I $(DEVICE_DIR)/Include  -I $(CORE_DIR) \
+#		   -I $(SOFTWARE_DIR)/common/retarget $(USER_DEFINE)
+#ARM_ASM_OPTIONS  = -g
+#ARM_LINK_OPTIONS = "--keep=$(STARTUP_FILE).o(RESET)" "--first=$(STARTUP_FILE).o(RESET)" \
+#		   --rw_base 0x30000000 --ro_base 0x00000000 --map  --info sizes
+
+ARM_CC_OPTIONS   = -c -O3 -Ospace -I $(DEVICE_DIR)/Include  -I $(CORE_DIR) \
+		   -I $(SOFTWARE_DIR)/common/retarget $(USER_DEFINE)
+ARM_ASM_OPTIONS  = 
+ARM_LINK_OPTIONS = "--keep=$(STARTUP_FILE).o(RESET)" "--first=$(STARTUP_FILE).o(RESET)" \
+		   --no_debug --rw_base 0x30000000 --ro_base 0x00000000 --map  --info sizes
+
+ifeq ($(COMPILE_BIGEND),1)
+ # Big Endian
+ ARM_CC_OPTIONS   += --bigend
+ ARM_ASM_OPTIONS  += --bigend
+ ARM_LINK_OPTIONS += --be8
+endif
+
+ifeq ($(COMPILE_MICROLIB),1)
+ # MicroLIB
+ ARM_CC_OPTIONS   += --library_type=microlib
+ ARM_ASM_OPTIONS  += --library_type=microlib --pd "__MICROLIB SETA 1"
+ ARM_LINK_OPTIONS += --library_type=microlib
+endif
+
+ifeq ($(COMPILE_SMALLMUL),1)
+ # In Cortex-M0, small multiply takes 32 cycles
+ ARM_CC_OPTIONS   += --multiply_latency=32
+endif
+
+# ---------------------------------------------------------------------------------------
+# gcc options
+
+GNG_CC      = arm-none-eabi-gcc
+GNU_OBJDUMP = arm-none-eabi-objdump
+GNU_OBJCOPY = arm-none-eabi-objcopy
+
+LINKER_SCRIPT_PATH = $(SOFTWARE_DIR)/common/scripts
+LINKER_SCRIPT = $(LINKER_SCRIPT_PATH)/cmsdk_cm0.ld
+
+GNU_CC_FLAGS = -g -O3 -mthumb $(CPU_TYPE)
+
+ifeq ($(COMPILE_BIGEND),1)
+ # Big Endian
+ GNU_CC_FLAGS   += -mbig-endian
+endif
+
+# ---------------------------------------------------------------------------------------
+all: all_$(TOOL_CHAIN)
+
+# ---------------------------------------------------------------------------------------
+# DS-5
+all_ds5 : $(TESTNAME).hex $(TESTNAME).lst
+
+$(TESTNAME).o :  $(TESTNAME).c $(DEPS_LIST)
+	armcc $(ARM_CC_OPTIONS) $(CPU_TYPE) $< -o  $@
+
+dma_pl230_driver.o :  dma_pl230_driver.c $(DEPS_LIST)
+	armcc $(ARM_CC_OPTIONS) $(CPU_TYPE) $< -o $@
+
+$(SYSTEM_FILE).o : $(DEVICE_DIR)/Source/$(SYSTEM_FILE).c $(DEPS_LIST)
+	armcc $(ARM_CC_OPTIONS) $(CPU_TYPE) $< -o  $@
+
+retarget.o : $(SOFTWARE_DIR)/common/retarget/retarget.c $(DEPS_LIST)
+	armcc $(ARM_CC_OPTIONS) $(CPU_TYPE) $< -o  $@
+
+uart_stdout.o : $(SOFTWARE_DIR)/common/retarget/uart_stdout.c $(DEPS_LIST)
+	armcc $(ARM_CC_OPTIONS) $(CPU_TYPE) $< -o  $@
+
+$(STARTUP_FILE).o : $(STARTUP_DIR)/$(STARTUP_FILE).s $(DEPS_LIST)
+	armasm $(ARM_ASM_OPTIONS) $(CPU_TYPE) $< -o  $@
+
+$(TESTNAME).ELF : $(TESTNAME).o dma_pl230_driver.o $(SYSTEM_FILE).o $(STARTUP_FILE).o retarget.o uart_stdout.o
+	armlink $(ARM_LINK_OPTIONS) -o $@ $(TESTNAME).o dma_pl230_driver.o $(SYSTEM_FILE).o $(STARTUP_FILE).o retarget.o uart_stdout.o
+
+$(TESTNAME).hex : $(TESTNAME).ELF
+	fromelf --vhx --8x1 $< --output $@
+
+$(TESTNAME).lst : $(TESTNAME).ELF
+	fromelf -c -d -e -s -z -v $< --output $@
+
+# ---------------------------------------------------------------------------------------
+# gcc
+all_gcc:
+	$(GNG_CC) $(GNU_CC_FLAGS) $(STARTUP_DIR)/$(STARTUP_FILE).s \
+		$(TESTNAME).c \
+		$(SOFTWARE_DIR)/common/retarget/retarget.c \
+		$(SOFTWARE_DIR)/common/retarget/uart_stdout.c \
+		$(DEVICE_DIR)/Source/$(SYSTEM_FILE).c \
+		-I $(DEVICE_DIR)/Include -I $(CORE_DIR) \
+                -I $(SOFTWARE_DIR)/common/retarget  \
+		-L $(LINKER_SCRIPT_PATH) \
+		-D__STACK_SIZE=0x200 \
+		-D__HEAP_SIZE=0x1000 \
+		$(USER_DEFINE) -T $(LINKER_SCRIPT) -o $(TESTNAME).o
+	# Generate disassembly code
+	$(GNU_OBJDUMP) -S $(TESTNAME).o > $(TESTNAME).lst
+	# Generate binary file
+	$(GNU_OBJCOPY) -S $(TESTNAME).o -O binary $(TESTNAME).bin
+	# Generate hex file
+	$(GNU_OBJCOPY) -S $(TESTNAME).o -O verilog $(TESTNAME).hex
+
+# Note:
+# If the version of object copy you are using does not support verilog hex file output,
+# you can generate the hex file from binary file using the following command
+#       od -v -A n -t x1 --width=1  $(TESTNAME).bin > $(TESTNAME).hex
+
+
+# ---------------------------------------------------------------------------------------
+# Keil MDK
+
+all_keil:
+	@echo "Please compile your project code and press ENTER when ready"
+	@read dummy
+
+# ---------------------------------------------------------------------------------------
+# Binary
+
+all_bin: $(TESTNAME).bin
+	# Generate hex file from binary
+	od -v -A n -t x1 --width=1  $(TESTNAME).bin > $(TESTNAME).hex
+
+# ---------------------------------------------------------------------------------------
+# Clean
+clean :
+	@rm -rf *.o
+	@if [ -e $(TESTNAME).hex ] ; then \
+	  rm -rf $(TESTNAME).hex ; \
+	fi
+	@if [ -e $(TESTNAME).lst ] ; then \
+	  rm -rf $(TESTNAME).lst ; \
+	fi
+	@if [ -e $(TESTNAME).ELF ] ; then \
+	  rm -rf $(TESTNAME).ELF ; \
+	fi
+	@if [ -e $(TESTNAME).bin ] ; then \
+	  rm -rf $(TESTNAME).bin ; \
+	fi
+	@rm -rf *.crf
+	@rm -rf *.plg
+	@rm -rf *.tra
+	@rm -rf *.htm
+	@rm -rf *.map
+	@rm -rf *.dep
+	@rm -rf *.d
+	@rm -rf *.lnp
+	@rm -rf *.bak
+	@rm -rf *.lst
+	@rm -rf *.axf
+	@rm -rf *.sct
+	@rm -rf *.__i
+	@rm -rf *._ia
diff --git a/system/src/nanosoc_acc_wrapper.v b/system/src/nanosoc_acc_wrapper.v
new file mode 100644
index 0000000000000000000000000000000000000000..4a3d1af40ebf97a18b7a3cfec6309e886888d6e6
--- /dev/null
+++ b/system/src/nanosoc_acc_wrapper.v
@@ -0,0 +1,75 @@
+//-----------------------------------------------------------------------------
+// SoC Labs Basic Example Accelerator Wrapper
+// A joint work commissioned on behalf of SoC Labs; under Arm Academic Access license.
+//
+// Contributors
+//
+// David Mapstone (d.a.mapstone@soton.ac.uk)
+// David Flynn    (d.w.flynn@soton.ac.uk)
+//
+// Copyright (C) 2023; SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+module nanosoc_acc_wrapper #(
+  parameter AHBADDRWIDTH=16,
+  parameter INPACKETWIDTH=128,
+  parameter CFGSIZEWIDTH=64,
+  parameter CFGSCHEMEWIDTH=2,
+  parameter OUTPACKETWIDTH=128,
+  parameter CFGNUMIRQ=4
+  ) (
+    input  wire                      HCLK,       // Clock
+    input  wire                      HRESETn,    // Reset
+
+    // AHB connection to Initiator
+    input  wire                      HSELS,
+    input  wire   [AHBADDRWIDTH-1:0] HADDRS,
+    input  wire   [1:0]              HTRANSS,
+    input  wire   [2:0]              HSIZES,
+    input  wire   [3:0]              HPROTS,
+    input  wire                      HWRITES,
+    input  wire                      HREADYS,
+    input  wire   [31:0]             HWDATAS,
+
+    output wire                      HREADYOUTS,
+    output wire                      HRESPS,
+    output wire   [31:0]             HRDATAS,
+
+    // Input Data Request Signal to DMAC
+    output wire                      exp_drq_ip_o,
+    input  wire                      exp_dlast_ip_i,
+
+    // Output Data Request Signal to DMAC
+    output wire                      exp_drq_op_o,
+    input  wire                      exp_dlast_op_i,
+    
+    // Interrupts
+    output wire   [CFGNUMIRQ-1:0]    exp_irq_o
+  );
+  
+  soclabs_ahb_aes128_ctrl u_exp_aes128 (
+    .ahb_hclk        (HCLK),
+    .ahb_hresetn     (HRESETn),
+    .ahb_hsel        (HSELS),
+    .ahb_haddr16     (HADDRS[15:0]),
+    .ahb_htrans      (HTRANSS),
+    .ahb_hwrite      (HWRITES),
+    .ahb_hsize       (HSIZES),
+    .ahb_hprot       (HPROTS),
+    .ahb_hwdata      (HWDATAS),
+    .ahb_hready      (HREADYS),
+    .ahb_hrdata      (HRDATAS),
+    .ahb_hreadyout   (HREADYOUTS),
+    .ahb_hresp       (HRESPS),
+    .drq_ipdma128    (exp_drq_ip_o),
+    .dlast_ipdma128  (1'b0),
+    .drq_opdma128    (exp_drq_op_o),
+    .dlast_opdma128  (1'b0),
+    .irq_key128      (exp_irq_o[0]),
+    .irq_ip128       (exp_irq_o[1]),
+    .irq_op128       (exp_irq_o[2]),
+    .irq_error       (exp_irq_o[3]),
+    .irq_merged      ( )
+  );
+
+endmodule
diff --git a/system/src/nanosoc_exp_wrapper.v b/system/src/nanosoc_exp_wrapper.v
new file mode 100644
index 0000000000000000000000000000000000000000..860ed3b9b9df1b9ca93f9cfea8f453fe2d0ce561
--- /dev/null
+++ b/system/src/nanosoc_exp_wrapper.v
@@ -0,0 +1,76 @@
+//-----------------------------------------------------------------------------
+// SoC Labs Basic Example Accelerator Wrapper
+// A joint work commissioned on behalf of SoC Labs; under Arm Academic Access license.
+//
+// Contributors
+//
+// David Mapstone (d.a.mapstone@soton.ac.uk)
+// David Flynn    (d.w.flynn@soton.ac.uk)
+//
+// Copyright (C) 2023; SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+module nanosoc_exp_wrapper #(
+  parameter AHBADDRWIDTH=16,
+  parameter INPACKETWIDTH=128,
+  parameter CFGSIZEWIDTH=64,
+  parameter CFGSCHEMEWIDTH=2,
+  parameter OUTPACKETWIDTH=128,
+  parameter CFGNUMIRQ=4
+  ) (
+    input  wire                      HCLK,       // Clock
+    input  wire                      HRESETn,    // Reset
+
+    // AHB connection to Initiator
+    input  wire                      HSEL_i,
+    input  wire   [AHBADDRWIDTH-1:0] HADDR_i,
+    input  wire   [1:0]              HTRANS_i,
+    input  wire   [2:0]              HSIZE_i,
+    input  wire   [3:0]              HPROT_i,
+    input  wire                      HWRITE_i,
+    input  wire                      HREADY_i,
+    input  wire   [31:0]             HWDATA_i,
+
+    output wire                      HREADYOUT_o,
+    output wire                      HRESP_o,
+    output wire   [31:0]             HRDATA_o,
+
+    // Input Data Request Signal to DMAC
+    output wire                      exp_drq_ip_o,
+    input  wire                      exp_dlast_ip_i,
+
+    // Output Data Request Signal to DMAC
+    output wire                      exp_drq_op_o,
+    input  wire                      exp_dlast_op_i,
+    
+    // Interrupts
+    output wire   [CFGNUMIRQ-1:0]    exp_irq_o
+
+  );
+  
+  soclabs_ahb_aes128_ctrl u_exp_aes128 (
+    .ahb_hclk        (HCLK),
+    .ahb_hresetn     (HRESETn),
+    .ahb_hsel        (HSEL_i),
+    .ahb_haddr16     (HADDR_i[15:0]),
+    .ahb_htrans      (HTRANS_i),
+    .ahb_hwrite      (HWRITE_i),
+    .ahb_hsize       (HSIZE_i),
+    .ahb_hprot       (HPROT_i),
+    .ahb_hwdata      (HWDATA_i),
+    .ahb_hready      (HREADY_i),
+    .ahb_hrdata      (HRDATA_o),
+    .ahb_hreadyout   (HREADYOUT_o),
+    .ahb_hresp       (HRESP_o),
+    .drq_ipdma128    (exp_drq_ip_o),
+    .dlast_ipdma128  (1'b0),
+    .drq_opdma128    (exp_drq_op_o),
+    .dlast_opdma128  (1'b0),
+    .irq_key128      (exp_irq_o[0]),
+    .irq_ip128       (exp_irq_o[1]),
+    .irq_op128       (exp_irq_o[2]),
+    .irq_error       (exp_irq_o[3]),
+    .irq_merged      ( )
+  );
+
+endmodule
diff --git a/system/src/soclabs_ahb_aes128_ctrl.v b/system/src/soclabs_ahb_aes128_ctrl.v
new file mode 100644
index 0000000000000000000000000000000000000000..63b2bc31851807b3e5122ec4a1e9f2872d41a21c
--- /dev/null
+++ b/system/src/soclabs_ahb_aes128_ctrl.v
@@ -0,0 +1,583 @@
+ //-----------------------------------------------------------------------------
+// top-level soclabs example AHB interface
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Flynn (d.w.flynn@soton.ac.uk)
+//
+// Copyright (C) 2023, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+module soclabs_ahb_aes128_ctrl(
+// -------------------------------------------------------
+// MCU interface
+// -------------------------------------------------------
+  input  wire        ahb_hclk,      // Clock
+  input  wire        ahb_hresetn,   // Reset
+  input  wire        ahb_hsel,      // Device select
+  input  wire [15:0] ahb_haddr16,   // Address for byte select
+  input  wire  [1:0] ahb_htrans,    // Transfer control
+  input  wire  [2:0] ahb_hsize,     // Transfer size
+  input  wire  [3:0] ahb_hprot,     // Protection control
+  input  wire        ahb_hwrite,    // Write control
+  input  wire        ahb_hready,    // Transfer phase done
+  input  wire [31:0] ahb_hwdata,    // Write data
+  output wire        ahb_hreadyout, // Device ready
+  output wire [31:0] ahb_hrdata,    // Read data output
+  output wire        ahb_hresp,     // Device response
+// stream data
+  output wire        drq_ipdma128,  // (to) DMAC input burst request
+  input  wire        dlast_ipdma128,// (from) DMAC input burst end (last transfer)
+  output wire        drq_opdma128,  // (to) DMAC output dma burst request
+  input  wire        dlast_opdma128,// (from) DMAC output burst end (last transfer)
+  output wire        irq_key128,
+  output wire        irq_ip128,
+  output wire        irq_op128,
+  output wire        irq_error,
+  output wire        irq_merged     // combined interrrupt request (to CPU)
+  );
+
+  //----------------------------------------------------------------
+  // Internal parameter definitions.
+  //----------------------------------------------------------------
+
+///typedef struct {
+///     __I  uint32_t CORE_NAME[2];   /* 0x0000-0007 */
+///     __I  uint32_t CORE_VERSION;   /* 0x0008-000B */
+///          uint32_t RESRV0C;        /* 0x000C */
+///     __IO uint32_t CTRL;           /* 0x0010 */
+///     __O  uint32_t CTRL_SET;       /* 0x0014 */
+///     __O  uint32_t CTRLL_CLR;      /* 0x0018 */
+///     __I  uint32_t STATUS;         /* 0x001c */
+///     __IO uint32_t QUAL;           /* 0x0020 */
+///          uint32_t RESRV24[3];     /* 0x0024 - 2F*/
+///     __IO uint32_t DRQ_MSK;        /* 0x0030 */
+///     __O  uint32_t DRQ_MSK_SET;    /* 0x0034 */
+///     __O  uint32_t DRQ_MSK_CLR;    /* 0x0038 */
+///     __I  uint32_t DRQ_STATUS;     /* 0x003C */
+///     __IO uint32_t IRQ_MSK;        /* 0x0040 */
+///     __O  uint32_t IRQ_MSK_SET;    /* 0x0044 */
+///     __O  uint32_t IRQ_MSK_CLR;    /* 0x0048 */
+///     __I  uint32_t IRQ_STATUS;     /* 0x004C */
+///          uint32_t RESRV50[4076];  /* 0x0050-0x3FFC (4096-20 words) */
+///     __IO uint8_t KEY128[0x4000];   /* 0x4000-7FFF (0x3FFF is last alias) */
+///     __IO uint8_t TXTIP128[0x4000]; /* 0x8000-BFFF (0x3FFF is last alias) */
+///     __I  uint8_t TXTOP128[0x4000]; /* 0xC000-FFFF (0x3FFF is last alias) */
+///} AES128_TypeDef;
+
+
+// CORE ID
+  localparam ADDR_CORE_NAME0  = 16'h0000;
+  localparam ADDR_CORE_NAME1  = 16'h0004;
+  localparam ADDR_CORE_VERSION= 16'h0008;
+  localparam CORE_NAME0       = 32'h61657331; // "aes1"
+  localparam CORE_NAME1       = 32'h32382020; // "28  "
+  localparam CORE_VERSION     = 32'h302e3031; // "0.01"
+
+// CTRL control register with bit-set/bit-clear options
+  localparam ADDR_CTRL        = 16'h0010;
+  localparam ADDR_CTRL_SET    = 16'h0014;
+  localparam ADDR_CTRL_CLR    = 16'h0018;
+  localparam CTRL_REG_WIDTH   = 8;
+  localparam CTRL_BIT_MAX     = (CTRL_REG_WIDTH-1);
+  localparam CTRL_KEY_REQ_BIT = 0;
+  localparam CTRL_IP_REQ_BIT  = 1;
+  localparam CTRL_OP_REQ_BIT  = 2;
+  localparam CTRL_ERR_REQ_BIT = 3;
+  localparam CTRL_KEYOK_BIT   = 4;
+  localparam CTRL_VALID_BIT   = 5;
+  localparam CTRL_BYPASS_BIT  = 6;
+  localparam CTRL_ENCODE_BIT  = 7;
+// STAT status regisyer 
+  localparam ADDR_STAT        = 16'h001c;
+  localparam STAT_REG_WIDTH   = 8;
+  localparam STAT_BIT_MAX     = (STAT_REG_WIDTH-1);
+  localparam STAT_KEYREQ_BIT  = 0;
+  localparam STAT_INPREQ_BIT  = 1;
+  localparam STAT_OUTREQ_BIT  = 2;
+  localparam STAT_ERROR_BIT   = 3;
+  localparam STAT_KEYOK_BIT   = 4;
+  localparam STAT_VALID_BIT   = 5;
+
+// QUAL qualifier field
+  localparam ADDR_QUAL        = 16'h0020;
+  localparam QUAL_REG_WIDTH   = 32;
+  localparam QUAL_BIT_MAX     = (QUAL_REG_WIDTH-1);
+
+// DREQ DMAC request control with bit-set/bit-clear options
+  localparam ADDR_DREQ        = 16'h0030;
+  localparam ADDR_DREQ_SET    = 16'h0034;
+  localparam ADDR_DREQ_CLR    = 16'h0038;
+  localparam ADDR_DREQ_ACT    = 16'h003c;
+  localparam DREQ_REG_WIDTH   = 3;
+  localparam DREQ_BIT_MAX     = (DREQ_REG_WIDTH-1);
+  localparam  REQ_KEYBUF_BIT  = 0;
+  localparam  REQ_IP_BUF_BIT  = 1;
+  localparam  REQ_OP_BUF_BIT  = 2;
+
+// IREQ CPU interrupt request control with bit-set/bit-clear options
+  localparam ADDR_IREQ        = 16'h0040;
+  localparam ADDR_IREQ_SET    = 16'h0044;
+  localparam ADDR_IREQ_CLR    = 16'h0048;
+  localparam ADDR_IREQ_ACT    = 16'h004c;
+  localparam IREQ_REG_WIDTH   = 4;
+  localparam IREQ_BIT_MAX     = (IREQ_REG_WIDTH-1);
+  localparam  REQ_ERROR_BIT   = 3;
+
+  localparam ADDR_KEY_BASE    = 16'h4000;
+  localparam ADDR_KEY0        = 16'h4000;
+  localparam ADDR_KEY3        = 16'h400c;
+  localparam ADDR_KEY7        = 16'h401c;
+
+  localparam ADDR_IBUF_BASE   = 16'h8000;
+  localparam ADDR_IBUF_0      = 16'h8000;
+  localparam ADDR_IBUF_3      = 16'h800c;
+
+  localparam ADDR_OBUF_BASE   = 16'hc000;
+  localparam ADDR_OBUF_3      = 16'hc00c;
+
+ 
+ // --------------------------------------------------------------------------
+  // Internal regs/wires
+  // --------------------------------------------------------------------------
+
+  reg   [15:0] addr16_r;
+  reg          sel_r;
+  reg          wcyc_r;
+  reg          rcyc_r;
+  reg    [3:0] byte4_r;
+
+  wire         key128_load_ack;
+  wire         ip128_load_ack;
+  wire         op128_load_ack;
+
+  // --------------------------------------------------------------------------
+  // AHB slave byte buffer interface, support for unaligned data transfers
+  // --------------------------------------------------------------------------
+
+  wire   [1:0] byt_adr = ahb_haddr16[1:0];
+  // generate next byte enable decodes for Word/Half/Byte CPU/DMA accesses
+  wire   [3:0] byte_nxt;
+  assign byte_nxt[0] = (ahb_hsize[1])|((ahb_hsize[0])&(!byt_adr[1]))|(byt_adr[1:0]==2'b00);
+  assign byte_nxt[1] = (ahb_hsize[1])|((ahb_hsize[0])&(!byt_adr[1]))|(byt_adr[1:0]==2'b01);
+  assign byte_nxt[2] = (ahb_hsize[1])|((ahb_hsize[0])&( byt_adr[1]))|(byt_adr[1:0]==2'b10);
+  assign byte_nxt[3] = (ahb_hsize[1])|((ahb_hsize[0])&( byt_adr[1]))|(byt_adr[1:0]==2'b11);
+
+  // de-pipelined registered access signals
+  always @(posedge ahb_hclk or negedge ahb_hresetn)
+    if (!ahb_hresetn)
+    begin
+      addr16_r <= 16'h0000;
+      sel_r    <= 1'b0;
+      wcyc_r   <= 1'b0;
+      rcyc_r   <= 1'b0;
+      byte4_r  <= 4'b0000;
+    end else if (ahb_hready)
+    begin
+      addr16_r <= (ahb_hsel & ahb_htrans[1]) ?  ahb_haddr16 : addr16_r;
+      sel_r    <= (ahb_hsel & ahb_htrans[1]);
+      wcyc_r   <= (ahb_hsel & ahb_htrans[1]  &  ahb_hwrite);
+      rcyc_r   <= (ahb_hsel & ahb_htrans[1]  & !ahb_hwrite);
+      byte4_r  <= (ahb_hsel & ahb_htrans[1]) ?  byte_nxt[3:0] : 4'b0000;
+    end 
+
+
+// pipelined "early" last access decodes, for PL230 dma_ack timing to deassert dma requests
+//  wire ahb128_last  = ahb_hsel &  ahb_htrans[1] & ahb_hready & ahb_haddr16[3] & ahb_haddr16[2] & byte_nxt[3];
+//  wire ahb128_wlast = ahb_last &  ahb_hwrite & |ahb_haddr[15:14]; // address phase of last write transfer
+//  wire ahb128_rlast = ahb_last & !ahb_hwrite & |ahb_haddr[15:14]; // address phase of last read transfer
+  
+  wire wlast128     = |ahb_haddr16[15:14] & addr16_r[3] & addr16_r[2] & byte4_r[3] & wcyc_r; // write last pulse
+  wire rlast128     = &ahb_haddr16[15:14] & addr16_r[3] & addr16_r[2] & byte4_r[3] & rcyc_r; // read last pulse
+
+  //----------------------------------------------------------------
+  // API register state and wiring
+  //
+  //----------------------------------------------------------------
+
+  reg   [CTRL_BIT_MAX:0] control;
+  reg   [QUAL_BIT_MAX:0] param;
+  reg   [DREQ_BIT_MAX:0] drq_enable;
+  reg   [IREQ_BIT_MAX:0] irq_enable;
+
+  wire  [STAT_BIT_MAX:0] status;
+  wire  [DREQ_BIT_MAX:0] drq_active;
+  wire  [IREQ_BIT_MAX:0] irq_active;
+
+  wire [31:0] rd_keybuf;
+  wire [31:0] rd_ipbuf;
+  wire [31:0] rd_opbuf;
+ 
+  //----------------------------------------------------------------
+  // API write decoder
+  //
+  //----------------------------------------------------------------
+
+  wire sel_mode   = sel_r & (addr16_r[15: 8] == 0);
+  wire sel_keybuf = sel_r & (addr16_r[15:14] == 1);
+  wire sel_ipbuf  = sel_r & (addr16_r[15:14] == 2);
+  wire sel_opbuf  = sel_r & (addr16_r[15:14] == 3);
+// add address map "last" transfer signalling when last (byte) of alias map is written 
+  wire alast_key128 = sel_keybuf & wcyc_r & (&addr16_r[13:2]) & byte4_r[3];
+  wire alast_ip128  = sel_ipbuf  & wcyc_r & (&addr16_r[13:2]) & byte4_r[3];
+  wire alast_op128  = sel_opbuf  & rcyc_r & (&addr16_r[13:2]) & byte4_r[3];
+
+  always @(posedge ahb_hclk or negedge ahb_hresetn)
+   if (!ahb_hresetn) begin
+     control    <= {CTRL_REG_WIDTH{1'b0}};
+     param      <= {QUAL_REG_WIDTH{1'b0}};
+     drq_enable <= {DREQ_REG_WIDTH{1'b0}};
+     irq_enable <= {IREQ_REG_WIDTH{1'b0}};
+     end
+   else if (sel_mode & wcyc_r & byte4_r[0])
+     case ({addr16_r[15:2],2'b00})
+       ADDR_CTRL    : control    <=  ahb_hwdata[CTRL_BIT_MAX:0];              // overwrite ctl reg
+       ADDR_CTRL_SET: control    <=  ahb_hwdata[CTRL_BIT_MAX:0] | control;    // bit set ctl mask pattern
+       ADDR_CTRL_CLR: control    <= ~ahb_hwdata[CTRL_BIT_MAX:0] & control;    // bit clear ctl mask pattern
+       ADDR_QUAL    : param      <=  ahb_hwdata[QUAL_BIT_MAX:0];              // write qual pattern
+       ADDR_DREQ    : drq_enable <=  ahb_hwdata[DREQ_BIT_MAX:0];              // overwrite dreq reg
+       ADDR_DREQ_SET: drq_enable <=  ahb_hwdata[DREQ_BIT_MAX:0] | drq_enable; // bit set dreq mask pattern
+       ADDR_DREQ_CLR: drq_enable <= ~ahb_hwdata[DREQ_BIT_MAX:0] & drq_enable; // bit clear dreq mask pattern
+       ADDR_IREQ    : irq_enable <=  ahb_hwdata[IREQ_BIT_MAX:0];              // overwrite ireq reg
+       ADDR_IREQ_SET: irq_enable <=  ahb_hwdata[IREQ_BIT_MAX:0] | irq_enable; // bit set ireq mask pattern
+       ADDR_IREQ_CLR: irq_enable <= ~ahb_hwdata[IREQ_BIT_MAX:0] & irq_enable; // bit clear ireq mask pattern
+       default: ;
+     endcase
+   else if (sel_keybuf & wcyc_r & (dlast_ipdma128 | alast_key128)) // key terminate
+     drq_enable[0] <= 1'b0;
+   else if (sel_ipbuf  & wcyc_r & (dlast_ipdma128 | alast_ip128)) // ip-buffer terminate
+     drq_enable[1] <= 1'b0;
+   else if (sel_opbuf & rcyc_r  & (dlast_opdma128 | alast_op128)) // op-buffer complete
+     drq_enable[2] <= 1'b0;
+
+  //----------------------------------------------------------------
+  // API read decoder
+  //
+  //----------------------------------------------------------------
+
+reg [31:0] rdata32; // mux read data
+
+  always @*
+    begin : read_decoder
+      rdata32  = 32'hbad0bad;
+      if (sel_r & rcyc_r)
+        case ({addr16_r[15:2],2'b00})
+          ADDR_CORE_NAME0   : rdata32 = CORE_NAME0; 
+          ADDR_CORE_NAME1   : rdata32 = CORE_NAME1; 
+          ADDR_CORE_VERSION : rdata32 = CORE_VERSION;
+          ADDR_CTRL     : rdata32 = {{(32-CTRL_REG_WIDTH){1'b0}}, control};
+          ADDR_STAT     : rdata32 = {{(32-STAT_REG_WIDTH){1'b0}}, status};
+          ADDR_QUAL     : rdata32 = {{(32-QUAL_REG_WIDTH){1'b0}}, param};
+          ADDR_DREQ     : rdata32 = {{(32-DREQ_REG_WIDTH){1'b0}}, drq_enable};
+          ADDR_DREQ_ACT : rdata32 = {{(32-DREQ_REG_WIDTH){1'b0}}, drq_active};
+          ADDR_IREQ     : rdata32 = {{(32-IREQ_REG_WIDTH){1'b0}}, irq_enable};
+          ADDR_IREQ_ACT : rdata32 = {{(32-DREQ_REG_WIDTH){1'b0}}, irq_active};
+        default:
+          if      (sel_keybuf) rdata32 = rd_keybuf;
+          else if (sel_ipbuf)  rdata32 = rd_ipbuf;
+          else if (sel_opbuf)  rdata32 = rd_opbuf;
+        endcase
+    end // read_decoder
+
+  assign ahb_hrdata = rdata32;
+
+  assign ahb_hreadyout = 1'b1; // zero wait state interface
+  assign ahb_hresp     = 1'b0;
+    
+  // --------------------------------------------------------------------------
+  // Key Input Buffer - keybuf
+  // --------------------------------------------------------------------------
+
+  wire [127:0] key128_be;
+
+  soclabs_iobuf_reg128
+  #(.WRITE_ONLY     (1),
+    .WRITE_ZPAD     (0))
+  u_reg128_key
+  (
+    .clk         (ahb_hclk        ), // Clock
+    .rst_b       (ahb_hresetn     ), // Reset
+    .sel_r       (sel_keybuf      ), // Bank decode select
+    .wcyc_r      (wcyc_r          ), // Write cycle (wdata32 valid)
+    .rcyc_r      (rcyc_r          ), // Read cycle (return rdata32)
+    .word2_r     (addr16_r[3:2]   ), // Address for word select
+    .byte4_r     (byte4_r[3:0]    ), // Byte select decoded (up to 4 enabled)
+    .wdata32     (ahb_hwdata[31:0]), // Write data (byte lane qualified)
+    .rdata32     (rd_keybuf       ), // Read data output
+    .dma128_ack  (key128_load_ack ), // DMA burst acknowledge
+    .out128_le   (                ), // Big-Endian 128-bit value
+    .out128_be   (key128_be       )  // Big-Endian 128-bit value
+  );
+
+  // --------------------------------------------------------------------------
+  // Data Input Buffer - ipbuf
+  // --------------------------------------------------------------------------
+
+  wire [127:0] ip128_le;
+  wire [127:0] ip128_be;
+
+  soclabs_iobuf_reg128
+  #(.WRITE_ONLY     (0),
+    .WRITE_ZPAD     (1))
+  u_reg128_ip
+  (
+    .clk         (ahb_hclk        ), // Clock
+    .rst_b       (ahb_hresetn     ), // Reset
+    .sel_r       (sel_ipbuf       ), // Bank decode select
+    .wcyc_r      (wcyc_r          ), // Write cycle (wdata32 valid)
+    .rcyc_r      (rcyc_r          ), // Read cycle (return rdata32)
+    .word2_r     (addr16_r[3:2]   ), // Address for word select
+    .byte4_r     (byte4_r[3:0]    ), // Byte select decoded (up to 4 enabled)
+    .wdata32     (ahb_hwdata[31:0]), // Write data (byte lane qualified)
+    .rdata32     (rd_ipbuf        ), // Read data output
+    .dma128_ack  (ip128_load_ack  ), // DMA burst acknowledge
+    .out128_le   (ip128_le        ), // Big-Endian 128-bit value
+    .out128_be   (ip128_be        )  // Big-Endian 128-bit value
+  );
+
+  // --------------------------------------------------------------------------
+  // Data Output Buffer - opbufsel_keybuf
+  // --------------------------------------------------------------------------
+
+  wire [127:0] op128_be;
+  wire [127:0] op128_muxed = (control[CTRL_BYPASS_BIT]) ? ip128_be : op128_be;
+  
+  wire [31:0] op_slice32 [0:3];
+  assign op_slice32[3] = {op128_muxed[  7:  0],op128_muxed[ 15:  8],op128_muxed[ 23: 16],op128_muxed[ 31: 24]};
+  assign op_slice32[2] = {op128_muxed[ 39: 32],op128_muxed[ 47: 40],op128_muxed[ 55: 48],op128_muxed[ 63: 56]};
+  assign op_slice32[1] = {op128_muxed[ 71: 64],op128_muxed[ 79: 72],op128_muxed[ 87: 80],op128_muxed[ 95: 88]};
+  assign op_slice32[0] = {op128_muxed[103: 96],op128_muxed[111:104],op128_muxed[119:112],op128_muxed[127:120]};
+
+  // 32-bit addressed read data
+  assign rd_opbuf = op_slice32[addr16_r[3:2]];
+
+  assign op128_load_ack = (sel_opbuf & rcyc_r & addr16_r[3] & addr16_r[2] & byte4_r[3]);
+
+  // --------------------------------------------------------------------------
+  // example aes128 engine timing
+  // --------------------------------------------------------------------------
+  // --------------------------------------------------------------------------
+  // AES-specific control interface
+  // --------------------------------------------------------------------------
+
+wire aes128_encode = control[CTRL_ENCODE_BIT];
+wire aes256_keysize = 1'b0;
+
+wire aes_keyloaded_pulse = key128_load_ack; // pulse on last byte load of key128
+wire aes_dataloaded_pulse= ip128_load_ack;  // pulse on last byte load of text128
+wire aes_ready;
+wire aes_valid;
+
+// state machine control
+reg  aes_ready_del;
+reg  aes_init;
+reg  aes_next;
+reg  aes_key_busy;
+reg  aes_key_rdy;
+reg  aes_res_busy;
+reg  aes_res_rdy;
+reg  aes_err;
+
+  always @(posedge ahb_hclk or negedge ahb_hresetn)
+    if (!ahb_hresetn) begin
+      aes_ready_del <= 1'b0;
+      aes_init      <= 1'b0;
+      aes_next      <= 1'b0;
+      aes_key_busy  <= 1'b0;
+      aes_key_rdy   <= 1'b0;
+      aes_res_busy  <= 1'b0;
+      aes_res_rdy   <= 1'b0;
+      aes_err       <= 1'b0;
+    end else begin
+      aes_ready_del <= aes_ready; // delay for rising edge detect
+      aes_init      <= aes_keyloaded_pulse;
+      aes_next      <= aes_dataloaded_pulse;
+      aes_key_busy  <= (aes_init) | (aes_key_busy & !(aes_ready & !aes_ready_del)); // hold until key expansion done
+      aes_key_rdy   <= (aes_key_busy & aes_ready & !aes_ready_del) // expanded key ready
+                     | (aes_key_rdy & !(sel_keybuf & wcyc_r));     // hold until any key update
+      aes_res_busy  <= (aes_next) | (aes_res_busy & !(aes_ready & !aes_ready_del)); // hold until block processing done
+      aes_res_rdy   <= (aes_res_busy & aes_ready & !aes_ready_del) // block ready
+                     | (aes_res_rdy & !op128_load_ack);           // hold until output transferred
+      aes_err       <= (!aes_key_rdy & ((sel_ipbuf & wcyc_r) | (sel_opbuf & rcyc_r)))
+                     | (aes_err & !(sel_keybuf & wcyc_r));
+    end
+
+  assign drq_active[REQ_KEYBUF_BIT] = control[CTRL_KEY_REQ_BIT] & (!aes_keyloaded_pulse & !aes_init & !aes_key_busy & !aes_key_rdy);
+  assign drq_active[REQ_IP_BUF_BIT] = control[CTRL_IP_REQ_BIT] & (!aes_dataloaded_pulse & !aes_next & !aes_res_busy & !aes_res_rdy & aes_key_rdy);
+  assign drq_active[REQ_OP_BUF_BIT] = control[CTRL_OP_REQ_BIT] & (!aes_res_busy &  aes_res_rdy);
+
+// input DMA channel shared by Key and Data-In
+  assign drq_ipdma128 = (drq_enable[REQ_KEYBUF_BIT] & drq_active[REQ_KEYBUF_BIT] & !wlast128) // if key DMA enabled
+                      | (drq_enable[REQ_IP_BUF_BIT] & drq_active[REQ_IP_BUF_BIT] & !wlast128) // if ip128 DMA requested
+                      ;
+                      
+// output DMA channel for Data-Out
+  assign drq_opdma128 = (drq_enable[REQ_OP_BUF_BIT]  & drq_active[REQ_OP_BUF_BIT] & !rlast128); // if op128 DMA requested
+
+// and Interrupt requests are masked out if corresponding DMA requests are enabled
+  assign irq_active[REQ_KEYBUF_BIT] = drq_active[REQ_KEYBUF_BIT] & !drq_enable[REQ_KEYBUF_BIT];
+  assign irq_active[REQ_IP_BUF_BIT] = drq_active[REQ_IP_BUF_BIT] & !drq_enable[REQ_IP_BUF_BIT];
+  assign irq_active[REQ_OP_BUF_BIT] = drq_active[REQ_OP_BUF_BIT] & !drq_enable[REQ_OP_BUF_BIT];
+  assign irq_active[REQ_ERROR_BIT ] = control[CTRL_ERR_REQ_BIT]   & aes_err; // error raised in SW
+
+  assign irq_key128 = irq_active[REQ_KEYBUF_BIT] & irq_enable[REQ_KEYBUF_BIT];
+  assign irq_ip128  = irq_active[REQ_IP_BUF_BIT] & irq_enable[REQ_IP_BUF_BIT];
+  assign irq_op128  = irq_active[REQ_OP_BUF_BIT] & irq_enable[REQ_OP_BUF_BIT];
+  assign irq_error  = irq_active[REQ_ERROR_BIT ] & irq_enable[REQ_ERROR_BIT ];
+// merge and mask if not DRQ
+  assign irq_merged = irq_key128 | irq_ip128 | irq_op128 | irq_error;
+  
+
+// wire up status port  
+  assign status[2:0]            = control [2:0];
+  assign status[STAT_ERROR_BIT] = (!aes_res_busy & !aes_key_rdy);
+  assign status[STAT_KEYOK_BIT] = aes_key_rdy;
+  assign status[STAT_VALID_BIT] = aes_res_rdy;
+  assign status[7:6]            = control [7:6];
+
+  //----------------------------------------------------------------
+  // core instantiation.
+  //----------------------------------------------------------------
+  aes_core core(
+                .clk(ahb_hclk),
+                .reset_n(ahb_hresetn),
+
+                .encdec(aes128_encode),
+                .init(aes_init),
+                .next(aes_next),
+                .ready(aes_ready),
+
+                .key({key128_be,key128_be}),
+                .keylen(aes256_keysize),
+
+                .block(ip128_be),
+                .result(op128_be),
+                .result_valid(aes_valid)
+               );
+                             
+endmodule
+
+module soclabs_iobuf_reg128
+ #(
+  parameter  WRITE_ONLY = 0,
+  parameter  WRITE_ZPAD = 0
+  ) (
+// -------------------------------------------------------
+// de-pipelined register interface
+// -------------------------------------------------------
+// ahb
+  input  wire         clk,        // Clock
+  input  wire         rst_b,      // Reset
+  input  wire         sel_r,      // Bank decode select
+  input  wire         wcyc_r,     // Write cycle (wdata32 valid)
+  input  wire         rcyc_r,     // Read cycle (return rdata32)
+  input  wire   [1:0] word2_r,    // Address for word select
+  input  wire   [3:0] byte4_r,    // Byte select decoded (up to 4 enabled)
+  input  wire  [31:0] wdata32,    // Write data (byte lae qualified)
+  output wire  [31:0] rdata32,    // Read data output
+  output wire         dma128_ack, // DMA burst acknowledge
+  output wire [127:0] out128_le,  // Litte-Endian 128-bit value
+  output wire [127:0] out128_be   // Big-Endian 128-bit value
+) ;
+
+  reg   [7:0] byte0 [0:3];
+  reg   [7:0] byte1 [0:3];
+  reg   [7:0] byte2 [0:3];
+  reg   [7:0] byte3 [0:3];
+  reg         ack128;
+
+  wire zpad_cfg = (WRITE_ZPAD==0) ? 1'b0 : 1'b1;
+
+// byte-0 array; flush on write to word-0, byte-0
+// else addressed word byte-0 write
+  always @(posedge clk or negedge rst_b)
+    if (!rst_b)
+      begin byte0[0] <= 8'h00; byte0[1] <= 8'h00; byte0[2] <= 8'h00; byte0[3] <= 8'h00; end
+    else if (zpad_cfg & sel_r & wcyc_r & byte4_r[0] & !word2_r[1] & !word2_r[0]) // Z-PAD rest
+      begin byte0[0] <= wdata32[ 7: 0]; byte0[1] <= 8'h00; byte0[2] <= 8'h00; byte0[3] <= 8'h00; end
+    else if (sel_r & wcyc_r & byte4_r[0])
+      byte0[word2_r[1:0]] <= wdata32[ 7: 0];
+   
+// byte-1 array; flush on write to word-0, byte-0 if byte-1 not also written
+// flush rest on write to word-0, byte-0 and byte-1 also written
+// else address word byte-1 write
+  always @(posedge clk or negedge rst_b)
+    if (!rst_b)
+      begin byte1[0] <= 8'h00; byte1[1] <= 8'h00; byte1[2] <= 8'h00; byte1[3] <= 8'h00; end
+    else if (zpad_cfg & sel_r & wcyc_r & !byte4_r[1] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD
+      begin byte1[0] <= 8'h00; byte1[1] <= 8'h00; byte1[2] <= 8'h00; byte1[3] <= 8'h00; end
+    else if (zpad_cfg & sel_r & wcyc_r &  byte4_r[1] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD rest
+      begin byte1[0] <= wdata32[15: 8]; byte1[1] <= 8'h00; byte1[2] <= 8'h00; byte1[3] <= 8'h00; end
+    else if (sel_r & wcyc_r & byte4_r[1])
+      byte1[word2_r[1:0]] <= wdata32[15: 8];
+   
+// byte-2 array; flush on write to word-0, byte-0 if byte-2 not also written
+// flush rest on write to word-0, byte-0 and byte-2 also written
+// else address word byte-2 write
+  always @(posedge clk or negedge rst_b)
+    if (!rst_b)
+      begin byte2[0] <= 8'h00; byte2[1] <= 8'h00; byte2[2] <= 8'h00; byte2[3] <= 8'h00; end
+    else if (zpad_cfg & sel_r & wcyc_r & !byte4_r[2] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD
+      begin byte2[0] <= 8'h00; byte2[1] <= 8'h00; byte2[2] <= 8'h00; byte2[3] <= 8'h00; end
+    else if (zpad_cfg & sel_r & wcyc_r &  byte4_r[2] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD rest
+      begin byte2[0] <= wdata32[23:16]; byte2[1] <= 8'h00; byte2[2] <= 8'h00; byte2[3] <= 8'h00; end
+    else if (sel_r & wcyc_r & byte4_r[2])
+      byte2[word2_r[1:0]] <= wdata32[23:16];
+   
+// byte-3 array; flush on write to word-0, byte-0 if byte-3 not also written
+// flush rest on write to word-0, byte-0 and byte-3 also written
+// else address word byte-3 write
+  always @(posedge clk or negedge rst_b)
+    if (!rst_b)
+      begin byte3[0] <= 8'h00; byte3[1] <= 8'h00; byte3[2] <= 8'h00; byte3[3] <= 8'h00; end
+    else if (zpad_cfg & sel_r & wcyc_r & !byte4_r[3] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD
+      begin byte3[0] <= 8'h00; byte3[1] <= 8'h00; byte3[2] <= 8'h00; byte3[3] <= 8'h00; end
+    else if (zpad_cfg & sel_r & wcyc_r &  byte4_r[3] & !word2_r[1] & !word2_r[0] & byte4_r[0]) // Z-PAD rest
+      begin byte3[0] <= wdata32[31:24]; byte3[1] <= 8'h00; byte3[2] <= 8'h00; byte3[3] <= 8'h00; end
+    else if (sel_r & wcyc_r & byte4_r[3])
+      byte3[word2_r[1:0]] <= wdata32[31:24];
+
+  // ack on write to final byte [15]   
+  always @(posedge clk or negedge rst_b)
+    if (!rst_b)
+      ack128 <= 1'b0;
+    else
+      ack128 <= sel_r & wcyc_r & word2_r[1] & word2_r[0] & byte4_r[3];
+
+  assign dma128_ack = ack128;
+
+// byte reverse per word for Big Endian AES engine
+  assign out128_be = {byte0[0], byte1[0], byte2[0], byte3[0],
+                      byte0[1], byte1[1], byte2[1], byte3[1],
+                      byte0[2], byte1[2], byte2[2], byte3[2],
+                      byte0[3], byte1[3], byte2[3], byte3[3]};
+                   
+// byte reverse per word for Big Endian AES engine
+  assign out128_le = {byte3[3], byte2[3], byte1[3], byte0[3],
+                      byte3[2], byte2[2], byte1[2], byte0[2],
+                      byte3[1], byte2[1], byte1[1], byte0[1],
+                      byte3[0], byte2[0], byte1[0], byte0[0]};
+                   
+// little-endian read data (if not Write-Only)
+  assign rdata32   = (sel_r & rcyc_r & (WRITE_ONLY == 0))
+                   ? {byte3[word2_r[1:0]], byte2[word2_r[1:0]],
+                      byte1[word2_r[1:0]], byte0[word2_r[1:0]]}
+                   : 32'h00000000;
+
+endmodule
+
+// include SecWorks IP but fix up default_nettype issues that breaks elsewhere
+
+`include "aes_core.v"
+`default_nettype wire
+`include "aes_encipher_block.v"
+`default_nettype wire
+`include "aes_decipher_block.v"
+`default_nettype wire
+`include "aes_key_mem.v"
+`default_nettype wire
+`include "aes_sbox.v"
+`default_nettype wire
+`include "aes_inv_sbox.v"
+`default_nettype wire