diff --git a/flow/stimgen.py b/flow/stimgen.py
deleted file mode 100644
index 578df0b9f8bd9b49230656bfdd0a031311194790..0000000000000000000000000000000000000000
--- a/flow/stimgen.py
+++ /dev/null
@@ -1,210 +0,0 @@
-import csv, os, tabulate
-from enum import Enum
-
-soclabs_header = """;#-----------------------------------------------------------------------------
-;# SoC Labs Basic Hashing Accelerator Wrapper Input Stimulus File
-;# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
-;#
-;# Contributors
-;#
-;# David Mapstone (d.a.mapstone@soton.ac.uk)
-;#
-;# Copyright  2023, SoC Labs (www.soclabs.org)
-;#-----------------------------------------------------------------------------"""
-
-class TransactionType(Enum):
-    """ Enumerated Types for Transaction Types for ASCII Debug """
-    READ  = 1
-    WRITE = 2
-    def __str__(self):
-        if (self == TransactionType.READ):
-            return "R"
-        elif (self == TransactionType.WRITE):
-            return "W"
-
-class TransactionSize(Enum):
-    """ Enumerated Types for Transaction Types for ASCII Debug """
-    WORD     = 1
-    HALFWORD = 2
-    def __str__(self):
-        if (self == TransactionSize.WORD):
-            return "word"
-        elif (self == TransactionSize.HALFWORD):
-            return "halfword"
-
-class InputBlockStruct:
-    def __init__(self):
-        self.word_list = []
-    
-    def word_append(self, word):
-        self.word_list.append(word)
-
-class InputPacketStruct:
-    def __init__(self):
-        self.block_list = []
-    
-    def block_append(self, block):
-        self.block_list.append(block)
-
-class WordStruct:
-    def __init__(self, data, addr, trans, packet_num = 0, block_num = 0, size = TransactionSize.WORD):
-        self.data = data
-        self.addr = addr
-        self.trans = trans
-        self.packet_num = packet_num
-        self.block_num = block_num
-        self.size = size
-
-def adp_output(out_file, word_list):
-    """ 
-    This function takes a list of 32 bit words and addresses and formats 
-    the data into .cmd format for the ADP module
-    testbench
-    """
-    
-    data = []
-    for word in word_list:
-        if (word.data > 0):
-            data.append(["a", "{0:#0{1}x}".format(word.addr,10)])
-            data.append([str(word.trans).lower(), "{0:#0{1}x}".format(word.data,10)])
-    
-    table_str = tabulate.tabulate(data, tablefmt="plain")
-
-    with open(out_file, "w", encoding="UTF8", newline='') as f:
-        f.write("A\n")
-        f.write(table_str)
-        f.write("\n  A")
-        f.write("\nX")
-        f.write("\n!")
-
-def fri_output(out_file, word_list):
-    """ 
-    This function takes a list of 32 bit words and addresses and formats 
-    the data into .fri format to be fed into fml2conv.pl script to stimulate
-    testbench
-    """
-    
-    # Column Names
-    col_names = ["Transaction", "Address", "Data", "Size"]
-
-    data = []
-    for word in word_list:
-        if (word.data > 0):
-            data.append([str(word.trans), "{0:#0{1}x}".format(word.addr,10), "{0:#0{1}x}".format(word.data,10), str(word.size)])
-    
-    table_str = tabulate.tabulate(data, headers=col_names, tablefmt="plain")
-
-    with open(out_file, "w", encoding="UTF8", newline='') as f:
-        f.write(soclabs_header + "\n;")
-        f.write(table_str)
-        f.write("\nQ") # Add End of Simulation Flag
-
-def stimulus_generation(stim_file, ref_file, input_start_address, input_size, output_start_address, output_size):
-    """ 
-    This function takes 32 bit input stimulus file from accelerator model,
-    calculates write addresses for each word and generates a .fri file which
-    can be used to stimulate an AHB testbench
-    """
-    # Calculate End Address
-    input_end_address = input_start_address + input_size - 0x4
-    # print(f"End Address is {hex(end_address)}")
-
-    # Open Files
-    with open(stim_file, "r") as stim:
-        csvreader = csv.reader(stim, delimiter=",")
-        stim_list = list(csvreader)
-
-    with open(ref_file, "r") as ref:
-        csvreader = csv.reader(ref, delimiter=",")
-        ref_list = list(csvreader)
-
-    # Initialise Packet Lists
-    write_packet_list = []
-    read_packet_list  = []
-
-    # Initialise Temporary Structures
-    temppacketstruct = InputPacketStruct()
-    tempblockstruct = InputBlockStruct()
-
-    # Put Write Data into Structs
-    for i in stim_list:
-        tempblockstruct.word_append(int(i[0],16))
-        # If Last Word in Block, Append to Packet and Reset Temporary block structure
-        if (int(i[1])):
-            temppacketstruct.block_append(tempblockstruct)
-            tempblockstruct = InputBlockStruct()
-            # If Last Block in Packet , Append Packet to Packet List and Reset Temp Packet
-            if (int(i[2])):
-                write_packet_list.append(temppacketstruct)
-                temppacketstruct = InputPacketStruct()
-
-    # Put Read Data into Structs
-    for i in ref_list:
-        tempblockstruct.word_append(int(i[0],16))
-        # If Last Word in Block, Append to Packet and Reset Temporary block structure
-        if (int(i[1])):
-            temppacketstruct.block_append(tempblockstruct)
-            tempblockstruct = InputBlockStruct()
-            # If Last Block in Packet , Append Packet to Packet List and Reset Temp Packet
-            if (int(i[2])):
-                read_packet_list.append(temppacketstruct)
-                temppacketstruct = InputPacketStruct()
-        
-    
-    # List of Ouptut Transactions
-    output_word_list = []
-
-    # Generate Address for Packet
-    for packet_num, write_packet in enumerate(write_packet_list):
-        # Calculate Number of Blocks in First Packet
-        num_blocks = len(write_packet.block_list)
-        # Each Write Block Can Contain 16 32-bit Words (512 bits) (0x4 * 16 = 0x40)
-        # - Work Out Required Size = (0x40 * NumBlocks)
-        # - Work Out Beginning Address = (end_address + 0x4) - Size
-        req_write_size = 0x40 * num_blocks
-        start_write_addr = input_start_address + input_size - req_write_size
-        # Each Read Block Contains 8 32-bit Words (256 bits) (0x4 * 8 = 0x20)
-        req_read_size  = 0x20
-        start_read_addr  = output_start_address + output_size - req_read_size
-        # print(f"Packet: {int(packet_num)} | Start Address: {hex(start_write_addr)}")
-        write_addr = start_write_addr
-        read_addr  = start_read_addr
-        # Write out Packet containing multiple 512 bit Blocks to Input Port
-        for block_num, block in enumerate(write_packet.block_list):
-            for word in block.word_list:
-                word_data = WordStruct(word, write_addr, TransactionType.WRITE, packet_num, block_num)
-                output_word_list.append(word_data)
-                # Increment Address
-                write_addr += 0x4
-        # Set Read Packet
-        read_packet = read_packet_list[packet_num]
-        # Read Back 256 Bit Packet from Output Port
-        for block_num, block in enumerate(read_packet.block_list):
-            for word in block.word_list:
-                word_data = WordStruct(word, read_addr, TransactionType.READ, packet_num, 0)
-                output_word_list.append(word_data)
-                # Increment Address
-                read_addr += 0x4
-
-
-    # Generate ADP Command File with Write Transactions
-    adp_file = os.environ["PROJECT_DIR"] + "/system/stimulus/" + "adp_hash_stim.cmd"
-    adp_output(adp_file, output_word_list)
-
-    # Generate FRI File with Write Transactions
-    fri_file = os.environ["PROJECT_DIR"] + "/wrapper/stimulus/" + "ahb_input_hash_stim.fri"
-    fri_output(fri_file, output_word_list)
-
-    # Call fm2conv.pl script
-    m2d_file = os.environ["PROJECT_DIR"] + "/wrapper/stimulus/" + "ahb_input_hash_stim.m2d"
-    os.system(f"fm2conv.pl -busWidth=32 -infile={fri_file} -outfile={m2d_file}")
-
-
-if __name__ == "__main__":
-    accelerator_input_address = 0x6001_0000
-    accelerator_input_size = 0x0000_0800
-    accelerator_output_address = 0x6001_0800
-    accelerator_output_size = 0x0000_0800
-    stim_file = os.environ["PROJECT_DIR"] + "/wrapper/stimulus/" + "input_block_32bit_stim.csv"
-    ref_file = os.environ["PROJECT_DIR"] + "/wrapper/stimulus/" + "output_hash_32bit_ref.csv"
-    stimulus_generation(stim_file, ref_file, accelerator_input_address, accelerator_input_size, accelerator_output_address, accelerator_output_size)
\ No newline at end of file
diff --git a/hdl/src/wrapper_ahb_packet_constructor.sv b/hdl/src/wrapper_ahb_packet_constructor.sv
index 47546ac47491696915abb4660701471e950c5d9a..e6f877a2ffe20c336ea5a93d72f5fcf7953a3139 100644
--- a/hdl/src/wrapper_ahb_packet_constructor.sv
+++ b/hdl/src/wrapper_ahb_packet_constructor.sv
@@ -13,21 +13,21 @@ module wrapper_ahb_packet_constructor #(
   parameter   ADDRWIDTH=11,
   parameter   PACKETWIDTH=512
 )(
-  input  logic                  hclk,       // clock
-  input  logic                  hresetn,    // reset
-
-  // AHB Input Port
-  input  logic                  hsels,
-  input  logic [ADDRWIDTH-1:0]  haddrs,
-  input  logic [1:0]            htranss,
-  input  logic [2:0]            hsizes,
-  input  logic                  hwrites,
-  input  logic                  hreadys,
-  input  logic [31:0]           hwdatas,
-
-  output logic                  hreadyouts,
-  output logic                  hresps,
-  output logic [31:0]           hrdatas,
+  input  logic                   hclk,       // clock
+  input  logic                   hresetn,    // reset
+ 
+  // AHB Input Port 
+  input  logic                   hsels,
+  input  logic [ADDRWIDTH-1:0]   haddrs,
+  input  logic [1:0]             htranss,
+  input  logic [2:0]             hsizes,
+  input  logic                   hwrites,
+  input  logic                   hreadys,
+  input  logic [31:0]            hwdatas,
+ 
+  output logic                   hreadyouts,
+  output logic                   hresps,
+  output logic [31:0]            hrdatas,
 
   // Valid/Ready Output Port
   output logic [PACKETWIDTH-1:0] packet_data,
diff --git a/hdl/src/wrapper_dmac_req.sv b/hdl/src/wrapper_dmac_req.sv
new file mode 100644
index 0000000000000000000000000000000000000000..ee9be3953dc86c407dbc7b3a51bff4dc71838414
--- /dev/null
+++ b/hdl/src/wrapper_dmac_req.sv
@@ -0,0 +1,55 @@
+//-----------------------------------------------------------------------------
+// SoC Labs DMAC Request Controller
+// - Adapted from ARM AHB-lite example slave interface module.
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Mapstone (d.a.mapstone@soton.ac.uk)
+//
+// Copyright  2023, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Abstract : Looks for last word address of packet during address phase 
+//            to de-assert accelerator ready signal.
+//-----------------------------------------------------------------------------
+module wrapper_dmac_req #(
+  parameter   ADDRWIDTH=11,
+  parameter   DATAWIDTH=32
+)(
+  input  logic                  hclk,       // clock
+  input  logic                  hresetn,    // reset
+  
+  // Request Channel 0
+  input  logic                 data_req_active_0,
+  input  logic                 data_req_en_0,
+  output logic                 data_req_0,
+
+  // Request Channel 1
+  input  logic                 data_req_active_1,
+  input  logic                 data_req_en_1,
+  output logic                 data_req_1,
+
+  // Request Channel 2
+  input  logic                 data_req_active_2,
+  input  logic                 data_req_en_2,
+  output logic                 data_req_2,
+
+  // Request Channel 3
+  input  logic                 data_req_active_3,
+  input  logic                 data_req_en_3,
+  output logic                 data_req_3,
+
+  // Request Channel 4
+  input  logic                 data_req_active_4,
+  input  logic                 data_req_en_4,
+  output logic                 data_req_4
+);
+
+  assign data_req_0 = data_req_active_0 & data_req_en_0;
+  assign data_req_1 = data_req_active_1 & data_req_en_1;
+  assign data_req_2 = data_req_active_2 & data_req_en_2;
+  assign data_req_3 = data_req_active_3 & data_req_en_3;
+  assign data_req_4 = data_req_active_4 & data_req_en_4;
+
+endmodule
\ No newline at end of file
diff --git a/hdl/src/wrapper_req_ctrl_reg.sv b/hdl/src/wrapper_req_ctrl_reg.sv
new file mode 100644
index 0000000000000000000000000000000000000000..6e8ce367cade6463b0f2e4673d24acf1e7e900e3
--- /dev/null
+++ b/hdl/src/wrapper_req_ctrl_reg.sv
@@ -0,0 +1,125 @@
+//-----------------------------------------------------------------------------
+// SoC Labs Interrupt and DMA Control Registers
+// - Adapted from ARM AHB-lite example slave interface module.
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Mapstone (d.a.mapstone@soton.ac.uk)
+//
+// Copyright  2023, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+module wrapper_req_ctrl_reg #(
+  // parameter for address width
+  parameter   ADDRWIDTH = 12,
+  parameter   DATAWIDTH = 32
+) (
+  input  logic                   hclk,       // clock
+  input  logic                   hresetn,    // reset
+
+  // Register interface
+  input  logic [ADDRWIDTH-1:0]   addr,
+  input  logic                   read_en,
+  input  logic                   write_en,
+  input  logic [DATAWIDTH-1:0]   wdata,
+  output logic [DATAWIDTH-1:0]   rdata,
+
+  // Request Active from I/O constructors
+  input  logic                   req_act_ch0,
+  input  logic                   req_act_ch1,
+  input  logic                   req_act_ch2,
+  input  logic                   req_act_ch3,
+  input  logic                   req_act_ch4,
+
+  // DMA Output Request Signals
+  output logic                   drq_ch0,
+  output logic                   drq_ch1,
+  output logic                   drq_ch2,
+  output logic                   drq_ch3,
+  output logic                   drq_ch4,
+
+  // Interrupt Output Request Signals
+  output logic                   irq_ch0,
+  output logic                   irq_ch1,
+  output logic                   irq_ch2,
+  output logic                   irq_ch3,
+  output logic                   irq_ch4,
+  output logic                   irq_merged
+);
+
+  localparam REQ_ACT_REG_WIDTH   = 5;
+  localparam REQ_ACT_BIT_MAX     = (REQ_ACT_REG_WIDTH-1);
+
+  localparam DREQ_EN_REG_WIDTH   = 5;
+  localparam DREQ_EN_BIT_MAX     = (DREQ_EN_REG_WIDTH-1);
+
+  localparam ADDR_DREQ_EN         = 'h000;
+  localparam ADDR_DREQ_EN_SET     = 'h004;
+  localparam ADDR_DREQ_EN_CLR     = 'h008;
+  localparam ADDR_REQ_ACT         = 'h010;
+
+  localparam DREQ_EN_CH0_BIT         = 0;
+  localparam DREQ_EN_CH1_BIT         = 1;
+  localparam DREQ_EN_CH2_BIT         = 2;
+  localparam DREQ_EN_CH3_BIT         = 3;
+  localparam DREQ_EN_CH4_BIT         = 4;
+
+  localparam DREQ_ACT_CH0_BIT         = 0;
+  localparam DREQ_ACT_CH1_BIT         = 1;
+  localparam DREQ_ACT_CH2_BIT         = 2;
+  localparam DREQ_ACT_CH3_BIT         = 3;
+  localparam DREQ_ACT_CH4_BIT         = 4;
+
+  logic [DREQ_EN_BIT_MAX:0]  drq_en;
+  logic [REQ_ACT_BIT_MAX:0] req_act;
+
+  // Register Declaration
+  assign req_act = {req_act_ch4,req_act_ch3,req_act_ch2,req_act_ch1,req_act_ch0};
+
+  // Write Logic
+  always_ff @(posedge hclk or negedge hresetn) begin
+    if (!hresetn) begin
+      drq_en <= {DREQ_EN_REG_WIDTH{1'b0}};
+    end else begin
+      if (write_en) begin
+        case (addr)
+          // Set appropriate DMAC Request Register
+          ADDR_DREQ_EN:     drq_en <= wdata[DREQ_EN_BIT_MAX:0];
+          ADDR_DREQ_EN_SET: drq_en <= drq_en | wdata[DREQ_EN_BIT_MAX:0];
+          ADDR_DREQ_EN_CLR: drq_en <= drq_en & wdata[DREQ_EN_BIT_MAX:0];
+          default: ;
+        endcase
+      end
+    end
+  end
+
+  // Read Logic
+  always_comb begin
+    rdata = 32'h0bad0bad;
+    if (read_en) begin
+      case (addr)
+        ADDR_DREQ_EN:  rdata = {{(32-DREQ_EN_REG_WIDTH){1'b0}},  drq_en[DREQ_EN_BIT_MAX:0]};
+        ADDR_REQ_ACT:  rdata = {{(32-REQ_ACT_REG_WIDTH){1'b0}}, req_act[REQ_ACT_BIT_MAX:0]};
+        default: rdata = 32'h0bad0bad;
+      endcase
+    end
+  end
+
+  // DMA Request Output Assignment
+  assign drq_ch0 = req_act[0] & drq_en[0];
+  assign drq_ch1 = req_act[1] & drq_en[1];
+  assign drq_ch2 = req_act[2] & drq_en[2];
+  assign drq_ch3 = req_act[3] & drq_en[3];
+  assign drq_ch4 = req_act[4] & drq_en[4];
+
+  // Interrupt Request Output Assignment
+  assign irq_ch0 = req_act[0] & !drq_en[0];
+  assign irq_ch1 = req_act[1] & !drq_en[1];
+  assign irq_ch2 = req_act[2] & !drq_en[2];
+  assign irq_ch3 = req_act[3] & !drq_en[3];
+  assign irq_ch4 = req_act[4] & !drq_en[4];
+
+  assign irq_merged = irq_ch0 | irq_ch1 | irq_ch2 | irq_ch3 | irq_ch4;
+
+endmodule
\ No newline at end of file