diff --git a/controller/verilog/nanosoc_stream_adp_io.v b/controller/verilog/nanosoc_stream_adp_io.v
new file mode 100755
index 0000000000000000000000000000000000000000..0b27e1807d11173560bd16ebcaa3c7b6b9e3880a
--- /dev/null
+++ b/controller/verilog/nanosoc_stream_adp_io.v
@@ -0,0 +1,89 @@
+//-----------------------------------------------------------------------------
+// NanoSoC ASCII Debug Protocol Controller
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Flynn (d.w.flynn@soton.ac.uk)
+//
+// Copyright � 2021-2, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+// TODO: DM - I think this file is redundant if we move to nanosoc_manager_adp
+
+module nanosoc_stream_adp_io #(
+    parameter PROMPT_CHAR          = "]"
+	)(
+		// Ports of Axi Slave Bus Interface com_rx
+		input wire       ahb_hclk,
+		input wire       ahb_hresetn,
+		
+		output wire      com_rx_tready,
+		input wire [7:0] com_rx_tdata,
+		input wire       com_rx_tvalid,
+
+		// Ports of Axi Master Bus Interface com_tx
+		output wire       com_tx_tvalid,
+		output wire [7:0] com_tx_tdata,
+		input wire        com_tx_tready,
+
+		// Ports of Axi Slave Bus Interface stdio_rx
+		output wire      stdio_rx_tready,
+		input wire [7:0] stdio_rx_tdata,
+		input wire       stdio_rx_tvalid,
+
+		// Ports of Axi Master Bus Interface stdio_tx
+		output wire        stdio_tx_tvalid,
+		output wire [7:0]  stdio_tx_tdata,
+		input wire         stdio_tx_tready,
+
+		output wire [7 : 0]  gpo8,
+		input  wire [7 : 0]  gpi8,
+		
+    output wire [31:0]   ahb_haddr,
+    output wire [ 2:0]   ahb_hburst,
+    output wire          ahb_hmastlock,
+    output wire [ 3:0]   ahb_hprot,
+    output wire [ 2:0]   ahb_hsize,
+    output wire [ 1:0]   ahb_htrans,
+    output wire [31:0]   ahb_hwdata,
+    output wire          ahb_hwrite,
+    input  wire [31:0]   ahb_hrdata,
+    input  wire          ahb_hready,
+    input  wire          ahb_hresp    
+	);
+
+  nanosoc_adp_control #(
+    .PROMPT_CHAR (PROMPT_CHAR)
+  ) u_adp_control (
+    .HCLK        (ahb_hclk      ),
+    .HRESETn     (ahb_hresetn   ),
+    .HADDR32_o   (ahb_haddr     ),
+    .HBURST3_o   (ahb_hburst    ),
+    .HMASTLOCK_o (ahb_hmastlock ),
+    .HPROT4_o    (ahb_hprot     ),
+    .HSIZE3_o    (ahb_hsize     ),
+    .HTRANS2_o   (ahb_htrans    ),
+    .HWDATA32_o  (ahb_hwdata    ),
+    .HWRITE_o    (ahb_hwrite    ),
+    .HRDATA32_i  (ahb_hrdata    ),
+    .HREADY_i    (ahb_hready    ),
+    .HRESP_i     (ahb_hresp     ),
+    .GPO8_o      (gpo8          ),
+    .GPI8_i      (gpi8          ),
+    .COMRX_TREADY_o(com_rx_tready),
+    .COMRX_TDATA_i(com_rx_tdata),
+    .COMRX_TVALID_i(com_rx_tvalid),
+    .STDRX_TREADY_o(stdio_rx_tready),
+    .STDRX_TDATA_i(stdio_rx_tdata),
+    .STDRX_TVALID_i(stdio_rx_tvalid),
+    .COMTX_TVALID_o(com_tx_tvalid),
+    .COMTX_TDATA_o(com_tx_tdata),
+    .COMTX_TREADY_i(com_tx_tready),
+    .STDTX_TVALID_o(stdio_tx_tvalid),
+    .STDTX_TDATA_o(stdio_tx_tdata),
+    .STDTX_TREADY_i(stdio_tx_tready)
+  );
+
+
+endmodule
diff --git a/controller/verilog/socshute_adp_control.v b/controller/verilog/socshute_adp_control.v
new file mode 100755
index 0000000000000000000000000000000000000000..27b51296b3ba78eda6bedd582a375004b862315c
--- /dev/null
+++ b/controller/verilog/socshute_adp_control.v
@@ -0,0 +1,746 @@
+//-----------------------------------------------------------------------------
+// SoCShute ASCII Debug Protocol Controller
+// 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) 2021-3, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+//`define ADPBASIC 1
+`define ADPFSMDESIGN 1
+
+module socshute_adp_control #(
+  parameter PROMPT_CHAR = "]"
+)(  
+  // AHB-lite interface
+  input  wire        HCLK,
+  input  wire        HRESETn,
+  output wire [31:0] HADDR32_o,
+  output wire [ 2:0] HBURST3_o,
+  output wire        HMASTLOCK_o,
+  output wire [ 3:0] HPROT4_o,
+  output wire [ 2:0] HSIZE3_o,
+  output wire [ 1:0] HTRANS2_o,
+  output wire [31:0] HWDATA32_o,
+  output wire        HWRITE_o,
+  input  wire [31:0] HRDATA32_i,
+  input  wire        HREADY_i,
+  input  wire        HRESP_i,
+  
+  // COMIO interface
+  output wire [ 7:0] GPO8_o,
+  input  wire [ 7:0] GPI8_i,
+  input  wire [ 7:0] COMRX_TDATA_i,
+  input  wire        COMRX_TVALID_i,
+  output wire        COMRX_TREADY_o,
+  output wire [ 7:0] COMTX_TDATA_o,
+  output wire        COMTX_TVALID_o,
+  input  wire        COMTX_TREADY_i,
+  
+  // STDIO interface
+  input  wire [ 7:0] STDRX_TDATA_i,
+  input  wire        STDRX_TVALID_i,
+  output wire        STDRX_TREADY_o,
+  output wire [ 7:0] STDTX_TDATA_o,
+  output wire        STDTX_TVALID_o,
+  input  wire        STDTX_TREADY_i
+);
+
+wire COM_RXE_i = !COMRX_TVALID_i;
+wire COM_TXF_i = !COMTX_TREADY_i;
+
+//wire adp_rx_req = COMRX_TVALID_i & COMRX_TREADY_o;
+//wire std_rx_req = STDRX_TVALID_i & STDRX_TREADY_o;
+
+
+wire STD_TXF_i = !STDTX_TREADY_i;
+wire STD_RXE_i = !STDRX_TVALID_i;
+
+`ifdef ADPBASIC
+  localparam BANNERHEX = 32'h50c1ab01;
+`else
+  localparam BANNERHEX = 32'h50c1ab04;
+`endif
+
+localparam CMD_bad = 4'b0000;
+localparam CMD_A   = 4'b0001;  // set Address
+localparam CMD_C   = 4'b0010;  // Control
+localparam CMD_R   = 4'b0011;  // Read word, addr++
+localparam CMD_S   = 4'b0100;  // Status/STDIN
+localparam CMD_W   = 4'b0101;  // Write word, addr++
+localparam CMD_X   = 4'b0110;  // eXit
+`ifndef ADPBASIC
+localparam CMD_F   = 4'b1000;  // Fill (wordocunt) from addr++
+localparam CMD_M   = 4'b1001;  // set read Mask
+localparam CMD_P   = 4'b1010;  // Poll hardware  (count)
+localparam CMD_U   = 4'b1011;  // (Binary) Upload (wordocunt) from addr++
+localparam CMD_V   = 4'b1100;  // match Value
+`endif
+
+
+function FNvalid_adp_entry; // Escape char
+input [7:0] char8;
+  FNvalid_adp_entry = (char8[7:0] ==  8'h1b);
+endfunction
+
+function [3:0] FNvalid_cmd;
+input [7:0] char8;
+case (char8[7:0])
+"A": FNvalid_cmd = CMD_A;
+"a": FNvalid_cmd = CMD_A;
+"C": FNvalid_cmd = CMD_C;
+"c": FNvalid_cmd = CMD_C;
+"R": FNvalid_cmd = CMD_R;
+"r": FNvalid_cmd = CMD_R;
+"S": FNvalid_cmd = CMD_S;
+"s": FNvalid_cmd = CMD_S;
+"W": FNvalid_cmd = CMD_W;
+"w": FNvalid_cmd = CMD_W;
+"X": FNvalid_cmd = CMD_X;
+"x": FNvalid_cmd = CMD_X;
+`ifndef ADPBASIC
+"F": FNvalid_cmd = CMD_F;
+"f": FNvalid_cmd = CMD_F;
+"M": FNvalid_cmd = CMD_M;
+"m": FNvalid_cmd = CMD_M;
+"P": FNvalid_cmd = CMD_P;
+"p": FNvalid_cmd = CMD_P;
+"U": FNvalid_cmd = CMD_U;
+"u": FNvalid_cmd = CMD_U;
+"V": FNvalid_cmd = CMD_V;
+"v": FNvalid_cmd = CMD_V;
+`endif
+default:
+      FNvalid_cmd = 0;
+endcase
+endfunction
+
+function FNvalid_space; // space or tab char
+input [7:0] char8;
+  FNvalid_space = ((char8[7:0] == 8'h20) || (char8[7:0] == 8'h09));
+endfunction
+
+function FNnull; // space or tab char
+input [7:0] char8;
+  FNnull = (char8[7:0] == 8'h00);
+endfunction
+
+function FNexit; // EOF
+input [7:0] char8;
+  FNexit = ((char8[7:0] == 8'h04) || (char8[7:0] == 8'h00));
+endfunction
+
+function FNvalid_EOL; // CR or LF
+input [7:0] char8;
+  FNvalid_EOL = ((char8[7:0] == 8'h0a) || (char8[7:0] == 8'h0d));
+endfunction
+
+function FNuppercase;
+input [7:0] char8;
+  FNuppercase = (char8[6]) ? (char8 & 8'h5f) : (char8);
+endfunction
+
+
+function [2:0] FNsize_inc;
+// top 2 bits encode 01 (byte), 10 (halfword), 11 (word) 00 - no parameter
+input [2:0] cnt8;
+case (cnt8[2:0])
+3'b000: FNsize_inc = 3'b010;
+3'b010: FNsize_inc = 3'b011;
+3'b011: FNsize_inc = 3'b100;
+3'b100: FNsize_inc = 3'b101;
+default:
+  FNsize_inc = 3'b111;
+endcase
+endfunction
+
+function [1:0] FNparam2size;
+// top 2 bits encode 01 (byte), 10 (halfword), 11 (word) 00 - no parameter
+input [1:0] parm2;
+case (parm2[1:0])
+2'b01: FNparam2size = 2'b00; // 8-bit
+2'b10: FNparam2size = 2'b01; // 16-bit
+2'b11: FNparam2size = 2'b10; // 32-bit
+default:
+  FNparam2size = 2'b10;// default to 32-bit
+endcase
+endfunction
+
+function [34:0] FNBuild_size3_param32_hexdigit;
+input [34:0] param32;
+input [7:0] char8;
+case (char8[7:0])
+"\t":FNBuild_size3_param32_hexdigit = 35'b0; // tab starts new (zeroed) param32
+" ": FNBuild_size3_param32_hexdigit = 35'b0; // space starts new (zeroed) param32
+"x": FNBuild_size3_param32_hexdigit = 35'b0; // hex prefix starts new (zeroed) param32
+"X": FNBuild_size3_param32_hexdigit = 35'b0; // hex prefix starts new (zeroed) param32
+"0": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b0000};
+"1": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b0001};
+"2": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b0010};
+"3": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b0011};
+"4": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b0100};
+"5": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b0101};
+"6": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b0110};
+"7": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b0111};
+"8": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1000};
+"9": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1001};
+"A": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1010};
+"B": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1011};
+"C": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1100};
+"D": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1101};
+"E": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1110};
+"F": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1111};
+"a": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1010};
+"b": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1011};
+"c": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1100};
+"d": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1101};
+"e": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1110};
+"f": FNBuild_size3_param32_hexdigit = {FNsize_inc(param32[34:32]),param32[27:0],4'b1111};
+default: FNBuild_size3_param32_hexdigit = param32; // EOL etc returns param32 unchanged
+endcase
+endfunction
+
+
+function [7:0] FNmap_hex_digit;
+input [3:0] nibble;
+case (nibble[3:0])
+4'b0000: FNmap_hex_digit = "0";
+4'b0001: FNmap_hex_digit = "1";
+4'b0010: FNmap_hex_digit = "2";
+4'b0011: FNmap_hex_digit = "3";
+4'b0100: FNmap_hex_digit = "4";
+4'b0101: FNmap_hex_digit = "5";
+4'b0110: FNmap_hex_digit = "6";
+4'b0111: FNmap_hex_digit = "7";
+4'b1000: FNmap_hex_digit = "8";
+4'b1001: FNmap_hex_digit = "9";
+4'b1010: FNmap_hex_digit = "a";
+4'b1011: FNmap_hex_digit = "b";
+4'b1100: FNmap_hex_digit = "c";
+4'b1101: FNmap_hex_digit = "d";
+4'b1110: FNmap_hex_digit = "e";
+4'b1111: FNmap_hex_digit = "f";
+default: FNmap_hex_digit = "0";
+endcase
+endfunction
+
+// as per Vivado synthesis mapping
+`ifdef ADPFSMDESIGN
+localparam   ADP_WRITEHEX = 6'b000000 ;
+localparam  ADP_WRITEHEXS = 6'b000001 ;
+localparam  ADP_WRITEHEX9 = 6'b000010 ;
+localparam  ADP_WRITEHEX8 = 6'b000011 ;
+localparam  ADP_WRITEHEX7 = 6'b000100 ;
+localparam  ADP_WRITEHEX6 = 6'b000101 ;
+localparam  ADP_WRITEHEX5 = 6'b000110 ;
+localparam  ADP_WRITEHEX4 = 6'b000111 ;
+localparam  ADP_WRITEHEX3 = 6'b001000 ;
+localparam  ADP_WRITEHEX2 = 6'b001001 ;
+localparam  ADP_WRITEHEX1 = 6'b001010 ;
+localparam  ADP_WRITEHEX0 = 6'b001011 ;
+localparam    ADP_LINEACK = 6'b001100 ;
+localparam   ADP_LINEACK2 = 6'b001101 ;
+localparam     ADP_PROMPT = 6'b001110 ;
+localparam      ADP_IOCHK = 6'b001111 ;
+localparam     ADP_STDOUT = 6'b010000 ;
+localparam    ADP_STDOUT1 = 6'b010001 ;
+localparam    ADP_STDOUT2 = 6'b010010 ;
+localparam    ADP_STDOUT3 = 6'b010011 ;
+localparam      ADP_RXCMD = 6'b010100 ;
+localparam    ADP_RXPARAM = 6'b010101 ;
+localparam     ADP_ACTION = 6'b010110 ;
+localparam     ADP_SYSCTL = 6'b010111 ;
+localparam       ADP_READ = 6'b011000 ;
+localparam     ADP_SYSCHK = 6'b011001 ;
+localparam      ADP_STDIN = 6'b011010 ;
+localparam      ADP_WRITE = 6'b011011 ;
+localparam       ADP_EXIT = 6'b011100 ;
+localparam      STD_IOCHK = 6'b011101 ;
+localparam       STD_RXD1 = 6'b011110 ;
+localparam       STD_RXD2 = 6'b011111 ;
+localparam       STD_TXD1 = 6'b100000 ;
+localparam       STD_TXD2 = 6'b100001 ;
+localparam      ADP_UCTRL = 6'b100010 ;
+localparam     ADP_UREADB = 6'b100011 ;
+localparam     ADP_UWRITE = 6'b100100 ;
+localparam       ADP_POLL = 6'b100101 ;
+localparam      ADP_POLL1 = 6'b100110 ;
+localparam      ADP_POLL2 = 6'b100111 ;
+localparam      ADP_FCTRL = 6'b101000 ;
+localparam     ADP_FWRITE = 6'b101001 ;
+localparam    ADP_ECHOCMD = 6'b101010 ;
+localparam    ADP_ECHOBUS = 6'b101011 ;
+localparam    ADP_UNKNOWN = 6'b101100 ;
+reg  [5:0] adp_state   ;
+`else
+// one-hot encoded explicitly
+localparam   ADP_WRITEHEX = 45'b000000000000000000000000000000000000000000001 ; // = 6'b000000 ;
+localparam  ADP_WRITEHEXS = 45'b000000000000000000000000000000000000000000010 ; // = 6'b000001 ;
+localparam  ADP_WRITEHEX9 = 45'b000000000000000000000000000000000000000000100 ; // = 6'b000010 ;
+localparam  ADP_WRITEHEX8 = 45'b000000000000000000000000000000000000000001000 ; // = 6'b000011 ;
+localparam  ADP_WRITEHEX7 = 45'b000000000000000000000000000000000000000010000 ; // = 6'b000100 ;
+localparam  ADP_WRITEHEX6 = 45'b000000000000000000000000000000000000000100000 ; // = 6'b000101 ;
+localparam  ADP_WRITEHEX5 = 45'b000000000000000000000000000000000000001000000 ; // = 6'b000110 ;
+localparam  ADP_WRITEHEX4 = 45'b000000000000000000000000000000000000010000000 ; // = 6'b000111 ;
+localparam  ADP_WRITEHEX3 = 45'b000000000000000000000000000000000000100000000 ; // = 6'b001000 ;
+localparam  ADP_WRITEHEX2 = 45'b000000000000000000000000000000000001000000000 ; // = 6'b001001 ;
+localparam  ADP_WRITEHEX1 = 45'b000000000000000000000000000000000010000000000 ; // = 6'b001010 ;
+localparam  ADP_WRITEHEX0 = 45'b000000000000000000000000000000000100000000000 ; // = 6'b001011 ;
+localparam    ADP_LINEACK = 45'b000000000000000000000000000000001000000000000 ; // = 6'b001100 ;
+localparam   ADP_LINEACK2 = 45'b000000000000000000000000000000010000000000000 ; // = 6'b001101 ;
+localparam     ADP_PROMPT = 45'b000000000000000000000000000000100000000000000 ; // = 6'b001110 ;
+localparam      ADP_IOCHK = 45'b000000000000000000000000000001000000000000000 ; // = 6'b001111 ;
+localparam     ADP_STDOUT = 45'b000000000000000000000000000010000000000000000 ; // = 6'b010000 ;
+localparam    ADP_STDOUT1 = 45'b000000000000000000000000000100000000000000000 ; // = 6'b010001 ;
+localparam    ADP_STDOUT2 = 45'b000000000000000000000000001000000000000000000 ; // = 6'b010010 ;
+localparam    ADP_STDOUT3 = 45'b000000000000000000000000010000000000000000000 ; // = 6'b010011 ;
+localparam      ADP_RXCMD = 45'b000000000000000000000000100000000000000000000 ; // = 6'b010100 ;
+localparam    ADP_RXPARAM = 45'b000000000000000000000001000000000000000000000 ; // = 6'b010101 ;
+localparam     ADP_ACTION = 45'b000000000000000000000010000000000000000000000 ; // = 6'b010110 ;
+localparam     ADP_SYSCTL = 45'b000000000000000000000100000000000000000000000 ; // = 6'b010111 ;
+localparam       ADP_READ = 45'b000000000000000000001000000000000000000000000 ; // = 6'b011000 ;
+localparam     ADP_SYSCHK = 45'b000000000000000000010000000000000000000000000 ; // = 6'b011001 ;
+localparam      ADP_STDIN = 45'b000000000000000000100000000000000000000000000 ; // = 6'b011010 ;
+localparam      ADP_WRITE = 45'b000000000000000001000000000000000000000000000 ; // = 6'b011011 ;
+localparam       ADP_EXIT = 45'b000000000000000010000000000000000000000000000 ; // = 6'b011100 ;
+localparam      STD_IOCHK = 45'b000000000000000100000000000000000000000000000 ; // = 6'b011101 ;
+localparam       STD_RXD1 = 45'b000000000000001000000000000000000000000000000 ; // = 6'b011110 ;
+localparam       STD_RXD2 = 45'b000000000000010000000000000000000000000000000 ; // = 6'b011111 ;
+localparam       STD_TXD1 = 45'b000000000000100000000000000000000000000000000 ; // = 6'b100000 ;
+localparam       STD_TXD2 = 45'b000000000001000000000000000000000000000000000 ; // = 6'b100001 ;
+localparam      ADP_UCTRL = 45'b000000000010000000000000000000000000000000000 ; // = 6'b100010 ;
+localparam     ADP_UREADB = 45'b000000000100000000000000000000000000000000000 ; // = 6'b100011 ;
+localparam     ADP_UWRITE = 45'b000000001000000000000000000000000000000000000 ; // = 6'b100100 ;
+localparam       ADP_POLL = 45'b000000010000000000000000000000000000000000000 ; // = 6'b100101 ;
+localparam      ADP_POLL1 = 45'b000000100000000000000000000000000000000000000 ; // = 6'b100110 ;
+localparam      ADP_POLL2 = 45'b000001000000000000000000000000000000000000000 ; // = 6'b100111 ;
+localparam      ADP_FCTRL = 45'b000010000000000000000000000000000000000000000 ; // = 6'b101000 ;
+localparam     ADP_FWRITE = 45'b000100000000000000000000000000000000000000000 ; // = 6'b101001 ;
+localparam    ADP_ECHOCMD = 45'b001000000000000000000000000000000000000000000 ; // = 6'b101010 ;
+localparam    ADP_ECHOBUS = 45'b010000000000000000000000000000000000000000000 ; // = 6'b101011 ;
+localparam    ADP_UNKNOWN = 45'b100000000000000000000000000000000000000000000 ; // = 6'b101100 ;
+reg [44:0] adp_state   ;
+`endif
+
+reg [31:0] adp_bus_data;
+reg        banner      ;
+reg        com_tx_req  ;
+reg  [7:0] com_tx_byte ;
+reg        com_rx_ack  ;
+reg        std_tx_req  ;
+reg [ 7:0] std_tx_byte;
+reg        std_rx_ack  ;
+reg        adp_bus_req ;
+reg        adp_bus_write ;
+reg        adp_bus_err ;
+reg  [7:0] adp_cmd     ;
+reg  [7:0] adp_cmdwid  ;
+reg [34:0] adp_param   ;
+reg [31:0] adp_addr    ;
+reg  [1:0] adp_size    ;
+reg        adp_addr_inc;
+reg [31:0] adp_sys     ;
+
+assign GPO8_o = adp_sys[7:0];
+
+// ADP RX stream
+wire        com_rx_req = COMRX_TVALID_i;
+wire [ 7:0] com_rx_byte = COMRX_TDATA_i;
+assign      COMRX_TREADY_o = com_rx_ack;
+// ADP TX stream
+wire        com_tx_ack = COMTX_TREADY_i;
+assign      COMTX_TDATA_o = com_tx_byte;
+assign      COMTX_TVALID_o = com_tx_req;
+// STD RX stream (from STDOUT)
+wire        std_rx_req  = STDRX_TVALID_i;
+wire [ 7:0] std_rx_byte = STDRX_TDATA_i;
+assign      STDRX_TREADY_o = std_rx_ack;
+// STD TX stream (to STDIN)
+wire         std_tx_ack = STDTX_TREADY_i;
+assign       STDTX_TDATA_o = std_tx_byte;
+assign       STDTX_TVALID_o = std_tx_req;
+
+//AMBA AHB master as "stream" interface
+reg        ahb_dphase;
+wire       ahb_aphase = adp_bus_req & !ahb_dphase;
+wire       adp_bus_ack = ahb_dphase & HREADY_i;
+// control pipe
+always @(posedge HCLK or negedge HRESETn)
+  if(!HRESETn)
+    ahb_dphase    <= 0;
+  else if (HREADY_i)
+    ahb_dphase    <= (ahb_aphase);
+
+wire [1:0] byteaddr;
+
+assign byteaddr =  (adp_size[1]) ? 2'b00 :  (adp_size[0]) ? {adp_addr[1], 1'b0} : adp_addr[1:0];
+
+assign HADDR32_o[31:2] =  adp_addr[31:2];
+assign HADDR32_o[ 1:0] =  byteaddr[1:0];
+assign HBURST3_o     =  3'b001; // "INCR" burst signalled whenever transfer;
+assign HMASTLOCK_o   =  1'b0;
+assign HPROT4_o[3:0] = {1'b0, 1'b0, 1'b1, 1'b1};
+assign HSIZE3_o[2:0] = {1'b0, adp_size};
+assign HTRANS2_o     = {ahb_aphase,1'b0}; // non-seq
+assign HWDATA32_o    =  (adp_size[1]) ? adp_bus_data
+                                     : (adp_size[0]) ? {2{adp_bus_data[15:0]}}
+                                     : {4{adp_bus_data[7:0]}} ;
+assign HWRITE_o      =  adp_bus_write;
+
+
+`ifndef ADPBASIC
+reg  [34:0] adp_val;
+reg  [31:0] adp_mask;
+reg  [31:0] adp_poll;
+reg  [31:0] adp_count;
+reg         adp_count_dec ;
+wire        adp_delay_done;
+wire        poll2_loop_next;
+`endif
+
+// ADP_control flags in the 'C' control field
+wire        adp_disable;
+wire        adp_stdin_wait;
+
+// commnon interface handshake terms
+wire com_rx_done   = COMRX_TVALID_i & COMRX_TREADY_o;
+wire com_tx_done   = COMTX_TVALID_o & COMTX_TREADY_i;
+wire std_rx_done   = STDRX_TVALID_i & STDRX_TREADY_o;
+wire std_tx_done   = STDTX_TVALID_o & STDTX_TREADY_i;
+wire adp_bus_done  = (adp_bus_req & adp_bus_ack);
+
+// common task to set up for next state
+task ADP_LINEACK_next; // prepare newline TX (and cancel any startup banner)
+//  begin com_tx_req <= 1; com_tx_byte <= 8'h0A; banner <= 0; adp_state <= ADP_LINEACK; end
+  begin com_tx_req <= 1; com_tx_byte <= 8'h0A; adp_state <= ADP_LINEACK; end
+endtask
+task ADP_PROMPT_next; // prepare prompt TX
+  begin com_tx_req <= 1; com_tx_byte <= PROMPT_CHAR; adp_state <= ADP_PROMPT; end
+endtask
+task ADP_BUSWRITEINC_next; // prepare bus write and addr++ on completion
+  begin adp_bus_req <=1; adp_bus_write <=1; adp_addr_inc <=1; end
+endtask
+task ADP_BUSREADINC_next; // prepare bus read and addr++ on completion
+  begin adp_bus_req <=1; adp_bus_write <=0; adp_addr_inc <=1; end
+endtask
+
+task ADP_hexdigit_next; // output nibble
+input [3:0] nibble;
+  begin com_tx_req <= 1; com_tx_byte <= FNmap_hex_digit(nibble[3:0]); end
+endtask
+task ADP_txchar_next; // output char
+input [7:0] octet;
+  begin com_tx_req<= 1; com_tx_byte <= octet; end
+endtask
+
+task com_rx_nxt; com_rx_ack <=1; endtask
+
+function FNcount_down_zero_next; // param about to be zero
+input [31:0] counter;
+  FNcount_down_zero_next = !(|counter[31:1]);
+endfunction
+
+always @(posedge HCLK or negedge HRESETn)
+  if(!HRESETn) begin
+      adp_state    <= ADP_WRITEHEX ;
+      adp_bus_data <= BANNERHEX;
+      banner       <= 1; // start-up HEX message
+      com_tx_req   <= 0; // default no TX req
+      com_rx_ack   <= 0; // default no RX ack
+      std_tx_req   <= 0; // default no TX req
+      std_rx_ack   <= 0; // default no RX ack
+      adp_bus_req  <= 0; // default no bus transaction
+      adp_bus_err  <= 0; // default no bus error
+      adp_cmd      <= 0;
+      adp_param    <= 0;
+      adp_size     <= 2'b10; // default to 32-bit word size
+      adp_addr     <= 0;
+      adp_addr_inc <= 0;
+      adp_bus_write<= 0;
+`ifndef ADPBASIC
+      adp_count    <= 0;
+      adp_count_dec<= 0;
+      adp_val      <= 0;
+      adp_mask     <= 0;
+      adp_sys      <= 0;
+`endif
+  end else begin // default states
+      adp_state    <= adp_state; // default to hold current state
+      com_tx_req   <= 0; // default no TX req
+      com_rx_ack   <= 0; // default no RX ack
+      std_tx_req   <= 0; // default no TX req
+      std_rx_ack   <= 0; // default no RX ack
+      adp_bus_req  <= 0; // default no bus transaction
+      adp_addr     <= (adp_addr_inc & adp_bus_done) ? adp_addr + (1 << adp_size) : adp_addr; // address++
+      adp_addr_inc <= 0;
+`ifndef ADPBASIC
+      adp_count    <= (adp_count_dec & adp_bus_done & |adp_count) ? adp_count - 1 : adp_count; // param--
+      adp_count_dec<= 0;
+`endif
+    case (adp_state)
+// >>>>>>>>>>>>>>>> STDIO BYPASS >>>>>>>>>>>>>>>>>>>>>>
+       STD_IOCHK:  // check for commsrx or STDOUT and not busy service, else loop back
+         if (com_rx_req) begin com_rx_ack <= 1; adp_state <= STD_RXD1; end // input char pending for STDIN
+//         else if (com_tx_ack & std_rx_req) begin std_rx_ack <= 1; adp_state <= STD_TXD1; end // STDOUT char pending and not busy
+         else if (std_rx_req) begin std_rx_ack <= 1; adp_state <= STD_TXD1; end // STDOUT char pending
+       STD_TXD1:  // get STD out char
+         if (std_rx_done)
+           begin com_tx_byte <= std_rx_byte; com_tx_req <= 1; adp_state <= STD_TXD2; end
+         else std_rx_ack <= 1; // extend
+       STD_TXD2:  // output char to ADP channel
+         if (com_tx_done) begin adp_state <= STD_IOCHK; end
+         else com_tx_req <= 1;  // extend
+       STD_RXD1:  // read rx char and check for ADP entry else STDIN **
+         if (com_rx_done) begin
+           if (FNvalid_adp_entry(com_rx_byte))
+             begin ADP_txchar_next(8'h0A); adp_state <= ADP_LINEACK; end // ADP prompt
+           else if (std_tx_ack)
+             begin std_tx_byte <= com_rx_byte; std_tx_req <= 1; adp_state <= STD_RXD2; end
+           else adp_state <= STD_IOCHK; // otherwise discard STDIN char and process OP data if blocked
+         end else com_rx_ack <= 1;  // extend
+       STD_RXD2:  // get STD in char
+         if (std_tx_done) begin adp_state <= STD_IOCHK; end
+         else std_tx_req <= 1; // extend
+
+// >>>>>>>>>>>>>>>> ADP Monitor >>>>>>>>>>>>>>>>>>>>>>
+       ADP_PROMPT:  // transition after reset deassertion
+         if (com_tx_done) begin adp_state <= ADP_IOCHK; end
+         else com_tx_req <= 1;  // extend
+
+       ADP_IOCHK:  // check for commsrx or STDOUT and not busy service, else loop back
+         if (std_rx_req) begin com_tx_byte <= "<"; com_tx_req <= 1; adp_state <= ADP_STDOUT; end
+         else if (com_rx_req) begin com_rx_ack <= 1; adp_state <= ADP_RXCMD; end
+
+// >>>>>>>>>>>>>>>> ADP <STDOUT> >>>>>>>>>>>>>>>>>>>>>>
+       ADP_STDOUT:  // output "<"
+         if (com_tx_done) begin std_rx_ack <= 1; adp_state <= ADP_STDOUT1; end
+         else com_tx_req <= 1; // extend stream request if not ready
+       ADP_STDOUT1:  // get STD out char
+         if (std_rx_done) begin com_tx_byte <= std_rx_byte; com_tx_req <= 1; adp_state <= ADP_STDOUT2; end
+         else std_rx_ack <= 1; // else extend
+       ADP_STDOUT2:  // output char
+         if (com_tx_done) begin com_tx_byte <= ">"; com_tx_req <= 1; adp_state <= ADP_STDOUT3; end
+         else com_tx_req <= 1;  // else extend
+       ADP_STDOUT3:  // output ">"
+         if (com_tx_done) begin if (com_rx_req) begin com_rx_ack <= 1; adp_state <= ADP_RXCMD; end else adp_state <= ADP_IOCHK; end
+         else com_tx_req <= 1; // else extend
+
+// >>>>>>>>>>>>>>>> ADP COMMAND PARSING >>>>>>>>>>>>>>>>>>>>>>
+       ADP_RXCMD:  // read and save ADP command
+         if (com_rx_done) begin
+           if (FNexit(com_rx_byte)) adp_state <= STD_IOCHK; // immediate exit
+           else if (FNvalid_space(com_rx_byte)) com_rx_ack <= 1; // retry for a command
+           else if (FNvalid_EOL(com_rx_byte)) begin adp_cmd <= "?"; adp_state <= ADP_LINEACK; end // no command, skip param
+           else begin adp_cmd <= com_rx_byte; adp_param <= 35'h0_00000000; com_rx_ack <= 1; adp_state <= ADP_RXPARAM; end // get optional parameter
+         end
+         else com_rx_ack <= 1; // extend stream request if not ready
+       ADP_RXPARAM:  // read and build hex parameter
+         if (com_rx_done) begin  // RX byte
+           if (FNexit(com_rx_byte)) adp_state <= STD_IOCHK; // exit
+           else if (FNvalid_EOL(com_rx_byte))
+`ifndef ADPBASIC
+            begin adp_count <= adp_param[31:0]; adp_state <= ADP_ACTION;
+                  adp_size  <= FNparam2size(adp_param[34:33]); end // parameter complete on EOL
+`else
+            begin adp_state <= ADP_ACTION;
+                  adp_size  <= FNparam2size(adp_param[34:33]); end // parameter complete on EOL
+`endif
+           else
+             begin adp_param <= FNBuild_size3_param32_hexdigit(adp_param[34:0], com_rx_byte); com_rx_ack <= 1; end // build parameter
+           end
+         else com_rx_ack <= 1;
+
+       ADP_ACTION:  // parse command and action with parameter
+         if (FNexit(com_rx_byte))
+           adp_state <= STD_IOCHK;
+         else if (FNvalid_cmd(adp_cmd) == CMD_A)
+           begin if (|adp_param[34:32]) adp_addr <= adp_param[31:0]; else adp_param <= {3'b111, adp_addr} ;
+             adp_state <= ADP_ECHOCMD; end
+         else if (FNvalid_cmd(adp_cmd) == CMD_C) begin
+           if (|adp_param[34:32] == 1'b0) // report GPO
+             begin adp_state <= ADP_SYSCTL; end
+           else if (adp_param[31:8] == 1) // clear selected bits in GPO
+             begin adp_sys[7:0] <= adp_sys[7:0] & ~adp_param[7:0]; adp_state <= ADP_SYSCTL; end
+           else if (adp_param[31:8] == 2) // set selected bits in GPO
+             begin adp_sys[7:0] <= adp_sys[7:0] | adp_param[7:0]; adp_state <= ADP_SYSCTL; end
+           else if (adp_param[31:8] == 3) // overwrite bits in GPO
+             begin adp_sys[7:0] <= adp_param[7:0]; adp_state <= ADP_SYSCTL; end
+           else // 4 etc, report GPO
+             begin adp_state <= ADP_SYSCTL; end
+           end
+         else if (FNvalid_cmd(adp_cmd) == CMD_R)
+           begin adp_size <= FNparam2size(adp_param[34:33]); ADP_BUSREADINC_next; adp_state <= ADP_READ;
+`ifndef ADPBASIC
+             adp_count_dec <= 1'b1; // optional loop param
+`endif
+           end // no param required
+         else if (FNvalid_cmd(adp_cmd) == CMD_S)
+           begin adp_state <= ADP_SYSCHK; end
+         else if (FNvalid_cmd(adp_cmd) == CMD_W)
+           begin adp_size <= FNparam2size(adp_param[34:33]); adp_bus_data <= adp_param[31:0]; ADP_BUSWRITEINC_next; adp_state <= ADP_WRITE; end
+         else if (FNvalid_cmd(adp_cmd) == CMD_X)
+           begin com_tx_byte <= 8'h0a; com_tx_req <= 1; adp_state <= ADP_EXIT; end
+`ifndef ADPBASIC
+         else if (FNvalid_cmd(adp_cmd) == CMD_U)
+           if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_UCTRL; // non-zero count
+         else if (FNvalid_cmd(adp_cmd) == CMD_M)
+           begin if (|adp_param[34:32]) adp_mask <= adp_param[31:0]; else adp_param <= {3'b111,adp_mask};
+             adp_state <= ADP_ECHOCMD; end
+         else if (FNvalid_cmd(adp_cmd) == CMD_P)
+           if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_POLL; // non-zero count
+         else if (FNvalid_cmd(adp_cmd) == CMD_V)
+           begin if (|adp_param[34:32]) begin adp_size <= FNparam2size(adp_param[34:33]); adp_val <= adp_param[34:0]; end
+                 else adp_param <= adp_val;
+             adp_state <= ADP_ECHOCMD; end
+         else if (FNvalid_cmd(adp_cmd) == CMD_F)
+           if (FNcount_down_zero_next(adp_param[31:0])) adp_state <= ADP_ECHOCMD; else adp_state <= ADP_FCTRL; // non-zero count
+`endif
+         else
+           begin ADP_txchar_next("?"); adp_state <= ADP_UNKNOWN; end // unrecognised/invald
+
+// >>>>>>>>>>>>>>>> ADP BUS WRITE and READ >>>>>>>>>>>>>>>>>>>>>>
+
+       ADP_WRITE:  // perform bus write at current address pointer (and auto increment)
+         if (adp_bus_done) begin adp_state <= ADP_ECHOCMD; adp_bus_err <= HRESP_i; end
+         else begin ADP_BUSWRITEINC_next; end // extend request
+
+       ADP_READ:  // perform bus read at current adp address (and auto increment)  - and report in hex
+         if (adp_bus_done) begin adp_bus_data <= (byteaddr[1:0] == 2'b01) ? {HRDATA32_i[ 7: 0],HRDATA32_i[31: 8]} 
+                                               : (byteaddr[1:0] == 2'b10) ? {HRDATA32_i[15: 0],HRDATA32_i[31:16]} 
+                                               : (byteaddr[1:0] == 2'b11) ? {HRDATA32_i[23: 0],HRDATA32_i[31:24]}
+                                               : HRDATA32_i;
+                                 adp_bus_err <= HRESP_i; ADP_txchar_next("R"); adp_state <= ADP_ECHOBUS;
+                           end
+         else begin
+             ADP_BUSREADINC_next;
+`ifndef ADPBASIC
+           adp_count_dec<= 1'b1;
+`endif
+         end // extend request
+
+`ifndef ADPBASIC
+
+// >>>>>>>>>>>>>>>> ADP BINARY UPLOAD >>>>>>>>>>>>>>>>>>>>>>
+       ADP_UCTRL:  // set control value
+         begin com_rx_ack <= 1; adp_size <= 2'b00; adp_state <= ADP_UREADB; end  // read next byte
+       ADP_UREADB: // read raw binary byte
+         if (com_rx_done)
+           begin adp_bus_data[31:0] <= {4{com_rx_byte}}; ADP_BUSWRITEINC_next; adp_count_dec <= 1; adp_state <= ADP_UWRITE; end
+         else com_rx_ack <= 1;  // extend stream request if not ready
+       ADP_UWRITE:  // Write word to Addr++
+         if (adp_bus_done) begin // auto address++, count--
+           if (FNcount_down_zero_next(adp_count)) adp_state <= ADP_ECHOCMD; else begin adp_state <= ADP_UREADB; adp_bus_err <= adp_bus_err | HRESP_i; end
+         end else begin  ADP_BUSWRITEINC_next; adp_count_dec <= 1; end // extend request
+
+// >>>>>>>>>>>>>>>> ADP BUS READ LOOP >>>>>>>>>>>>>>>>>>>>>>
+       ADP_POLL:  // set poll value
+         begin adp_bus_req <= 1; adp_bus_write <= 0; adp_state <= ADP_POLL1; end
+       ADP_POLL1:  // wait for read data, no addr++
+         if (adp_bus_done) begin adp_bus_data <= HRDATA32_i; adp_count_dec <=1; adp_state <= ADP_POLL2; adp_bus_err <= adp_bus_err | HRESP_i; end
+         else begin adp_bus_req <= 1; adp_count_dec <=1; end
+       ADP_POLL2:
+         if (FNcount_down_zero_next(adp_count)) begin adp_state <= ADP_ECHOCMD; adp_bus_err <= 1'b1; end // timeout
+         else if (((adp_bus_data  & adp_mask) ^ adp_val[31:0]) == 0) begin adp_state <= ADP_ECHOCMD; adp_param <= {1'b0, (adp_param[31:0] - adp_count)}; end // exact match
+         else adp_state <= ADP_POLL;
+
+// >>>>>>>>>>>>>>>> ADP (ZERO) FILL MEMORY >>>>>>>>>>>>>>>>>>>>>>
+       ADP_FCTRL:  // set control value
+           begin adp_size <= FNparam2size(adp_val[34:33]); adp_bus_data <= adp_val[31:0]; ADP_BUSWRITEINC_next; adp_count_dec <= 1; adp_state <= ADP_FWRITE; end
+       ADP_FWRITE:  // Write word to Addr++
+         if (adp_bus_done) begin // auto address++, count--
+           if (FNcount_down_zero_next(adp_count)) adp_state <= ADP_ECHOCMD; else begin adp_state <= ADP_FCTRL;  adp_bus_err <= adp_bus_err | HRESP_i; end
+         end else begin  ADP_BUSWRITEINC_next; adp_count_dec <= 1; end // extend request
+`endif
+
+        // >>>>>>>>>>>>>>>> ADP MISC >>>>>>>>>>>>>>>>>>>>>>
+
+       ADP_UNKNOWN:  // output "?"
+         if (com_tx_done) begin ADP_LINEACK_next; end
+         else com_tx_req <= 1;  // extend stream request if not ready
+
+       ADP_EXIT:  // exit ADP mode
+         if (com_tx_done) adp_state <= STD_IOCHK;
+         else com_tx_req <= 1;  // extend stream request if not ready
+
+       ADP_SYSCHK:  // check STDIN fifo
+         begin // no upper flags so STDIN char
+           if (std_tx_ack) begin std_tx_req <=1; std_tx_byte <= adp_param[7:0]; adp_state <= ADP_STDIN; end
+           else begin adp_bus_err <= 1'b1; adp_state <= ADP_ECHOCMD; end // signal error then echo comand
+         end
+       ADP_STDIN:  // push char into STDIN
+         if (std_tx_done) begin adp_bus_data <= {24'b0,adp_param[7:0]}; ADP_txchar_next("S"); adp_state <= ADP_ECHOBUS;  end
+         else std_tx_req <= 1; // extend
+
+       ADP_SYSCTL:  // read current status - and report in hex
+         begin adp_bus_data <= {GPI8_i[7:0],adp_sys[7:0],adp_param[15:0]}; ADP_txchar_next("C"); adp_state <= ADP_ECHOBUS;  end
+
+       ADP_ECHOCMD:  // output command and (param) data
+         begin ADP_txchar_next(adp_cmd & 8'h5f); adp_bus_data <= adp_param[31:0]; adp_state <= ADP_ECHOBUS; end // output command char
+       ADP_ECHOBUS:  // output command space and (bus) data
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEXS; ADP_txchar_next(adp_bus_err ? "!" : " "); end // output space char, or "!" on bus error
+         else com_tx_req <= 1;  // extend
+
+       ADP_WRITEHEX:  // output hex word with prefix
+         begin adp_state <= ADP_WRITEHEXS; ADP_txchar_next(adp_bus_err ? "!" : " "); end // output space char, or "!" on bus error
+
+       ADP_WRITEHEXS:
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX9; ADP_txchar_next("0"); end // output "0" hex prefix
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX9:
+         if (com_tx_done & adp_size[1]) begin adp_state <= ADP_WRITEHEX8; ADP_txchar_next("x"); end // output "x" hex prefix
+         else if (com_tx_done & adp_size[0]) begin adp_state <= ADP_WRITEHEX4; ADP_txchar_next("x"); end // output "x" hex prefix
+         else if (com_tx_done) begin adp_state <= ADP_WRITEHEX2; ADP_txchar_next("x"); end // output "x" hex prefix
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX8:
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX7; ADP_hexdigit_next(adp_bus_data[31:28]); end // hex nibble 7
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX7:  // output hex nibble 7
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX6; ADP_hexdigit_next(adp_bus_data[27:24]); end // hex nibble 6
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX6:  // output hex nibble 6
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX5; ADP_hexdigit_next(adp_bus_data[23:20]); end // hex nibble 5
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX5:  // output hex nibble 5
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX4; ADP_hexdigit_next(adp_bus_data[19:16]); end // hex nibble 4
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX4:  // output hex nibble 4
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX3; ADP_hexdigit_next(adp_bus_data[15:12]); end // hex nibble 3
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX3:  // output hex nibble 3
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX2; ADP_hexdigit_next(adp_bus_data[11: 8]); end // hex nibble 2
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX2:  // output hex nibble 2
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX1; ADP_hexdigit_next(adp_bus_data[ 7: 4]); end // hex nibble 1
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX1:  // output hex nibble 1
+         if (com_tx_done) begin adp_state <= ADP_WRITEHEX0; ADP_hexdigit_next(adp_bus_data[ 3: 0]); end // hex nibble 0
+         else com_tx_req <= 1;  // extend
+       ADP_WRITEHEX0:  // output hex nibble 0 (if not startup banner then scan to end of line before lineack
+         if (com_tx_done) begin
+           adp_bus_err <= 1'b0; // clear sticky bus error flag
+           if (banner) begin ADP_LINEACK_next; end
+           else begin ADP_txchar_next(8'h0A); com_tx_req <= 1; adp_state <= ADP_LINEACK; end // newline and prompt
+         end else com_tx_req <= 1;  // extend
+
+       ADP_LINEACK:  // write EOLN
+         if (com_tx_done) begin
+           begin ADP_txchar_next(8'h0D); adp_state <= ADP_LINEACK2; end
+         end else com_tx_req <= 1;  // extend
+       ADP_LINEACK2: // CR
+         if (com_tx_done) begin
+           if (banner) begin banner <= 0; adp_state <= STD_IOCHK; end
+`ifndef ADPBASIC
+           else if ((FNvalid_cmd(adp_cmd) == CMD_R) & |adp_count) //// non-zero count
+             begin ADP_BUSREADINC_next; adp_count_dec <= 1'b1; adp_state <= ADP_READ; end //
+`endif
+           else begin ADP_txchar_next(PROMPT_CHAR); adp_state <= ADP_PROMPT; end
+         end else com_tx_req <= 1;  // extend
+      default:
+        begin ADP_txchar_next("#"); adp_state <= ADP_UNKNOWN; end // default error
+    endcase
+  end
+
+endmodule
\ No newline at end of file
diff --git a/controller/verilog/socshute_ahb.v b/controller/verilog/socshute_ahb.v
new file mode 100644
index 0000000000000000000000000000000000000000..a8c97312ab5d71ecc3aa331008b20899bf5afa26
--- /dev/null
+++ b/controller/verilog/socshute_ahb.v
@@ -0,0 +1,104 @@
+//-----------------------------------------------------------------------------
+// SoCShute Top-level FT1248-AHB Debug Controller
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Mapstone (d.a.mapstone@soton.ac.uk)
+//
+// Copyright � 2021-3, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+module socshute_ahb #(
+    parameter PROMPT_CHAR = "]"
+)(  
+    // AHB-lite Master Interface
+    input  wire        HCLK,
+    input  wire        HRESETn,
+    output wire [31:0] HADDR32_o,
+    output wire [ 2:0] HBURST3_o,
+    output wire        HMASTLOCK_o,
+    output wire [ 3:0] HPROT4_o,
+    output wire [ 2:0] HSIZE3_o,
+    output wire [ 1:0] HTRANS2_o,
+    output wire [31:0] HWDATA32_o,
+    output wire        HWRITE_o,
+    input  wire [31:0] HRDATA32_i,
+    input  wire        HREADY_i,
+    input  wire        HRESP_i,
+    
+    // APB Slave Interface
+    input  wire        PCLK,     // Clock
+    input  wire        PCLKG,    // Gated Clock
+    input  wire        PRESETn,  // Reset
+
+    input  wire        PSEL,     // Device select
+    input  wire [11:2] PADDR,    // Address
+    input  wire        PENABLE,  // Transfer control
+    input  wire        PWRITE,   // Write control
+    input  wire [31:0] PWDATA,   // Write data
+    
+    output wire [31:0] PRDATA,   // Read data
+    output wire        PREADY,   // Device ready
+    output wire        PSLVERR,  // Device error response
+    
+    // GPIO interface
+    output wire [ 7:0] GPO8_o,
+    input  wire [ 7:0] GPI8_i
+);
+
+    // COMIO interface
+    wire [ 7:0] COMRX_TDATA_i;
+    wire        COMRX_TVALID_i;
+    wire        COMRX_TREADY_o;
+    wire [ 7:0] COMTX_TDATA_o;
+    wire        COMTX_TVALID_o;
+    wire        COMTX_TREADY_i;
+
+    // STDIO interface
+    wire [ 7:0] STDRX_TDATA_i;
+    wire        STDRX_TVALID_i;
+    wire        STDRX_TREADY_o;
+    wire [ 7:0] STDTX_TDATA_o;
+    wire        STDTX_TVALID_o;
+    wire        STDTX_TREADY_i;
+    
+    // Instantiation of USRT Device
+    socshute_apb_usrt u_apb_usrt_com (
+        .PCLK              (PCLK),     // Peripheral clock
+        .PCLKG             (PCLKG),    // Gated PCLK for bus
+        .PRESETn           (PRESETn),  // Reset
+
+        .PSEL              (PSEL),     // APB interface inputs
+        .PADDR             (PADDR),
+        .PENABLE           (PENABLE),
+        .PWRITE            (PWRITE),
+        .PWDATA            (PWDATA),
+
+        .PRDATA            (PRDATA),   // APB interface outputs
+        .PREADY            (PREADY),
+        .PSLVERR           (PSLVERR),
+
+        .ECOREVNUM         (4'h0),     // Engineering-change-order revision bits
+
+        .TX_VALID_o        (stdio_rx_valid),
+        .TX_DATA8_o        (stdio_rx_data8),
+        .TX_READY_i        (stdio_rx_ready),
+
+        .RX_VALID_i        (stdio_tx_valid),
+        .RX_DATA8_i        (stdio_tx_data8),
+        .RX_READY_o        (stdio_tx_ready),
+
+        .TXINT             ( ),       // Transmit Interrupt
+        .RXINT             ( ),       // Receive  Interrupt
+        .TXOVRINT          ( ),       // Transmit Overrun Interrupt
+        .RXOVRINT          ( ),       // Receive  Overrun Interrupt
+        .UARTINT           ( )        // Combined Interrupt
+    );
+
+    // Instantiation of FT1248 Bus Master
+
+    // Instantiation of ADP AHB Controller
+
+    
+endmodule
\ No newline at end of file
diff --git a/controller/verilog/socshute_apb_usrt.v b/controller/verilog/socshute_apb_usrt.v
new file mode 100644
index 0000000000000000000000000000000000000000..8da2951ba09e63ecb71a8638f6899c72f2d3d1d1
--- /dev/null
+++ b/controller/verilog/socshute_apb_usrt.v
@@ -0,0 +1,1159 @@
+//-----------------------------------------------------------------------------
+// SoCShute APB USRT adapted from Arm CMSDK APB UART
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Flynn (d.w.flynn@soton.ac.uk)
+//
+// Copyright � 2021-3, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// 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-2011 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
+//
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Abstract : Simple APB UART
+//-----------------------------------------------------------------------------
+//-------------------------------------
+// Programmer's model
+// 0x00 R     RXD[7:0]    Received Data
+//      W     TXD[7:0]    Transmit data
+// 0x04 RW    STAT[3:0]
+//              [3] RX buffer overrun (write 1 to clear)
+//              [2] TX buffer overrun (write 1 to clear)
+//              [1] RX buffer full (Read only)
+//              [0] TX buffer full (Read only)
+// 0x08 RW    CTRL[3:0]   TxIntEn, RxIntEn, TxEn, RxEn
+//              [6] High speed test mode Enable
+//              [5] RX overrun interrupt enable
+//              [4] TX overrun interrupt enable
+//              [3] RX Interrupt Enable
+//              [2] TX Interrupt Enable
+//              [1] RX Enable
+//              [0] TX Enable
+// 0x0C R/Wc  intr_status/INTCLEAR
+//              [3] RX overrun interrupt
+//              [2] TX overrun interrupt
+//              [1] RX interrupt
+//              [0] TX interrupt
+// 0x10 RW    BAUDDIV[19:0] Baud divider
+//            (minimum value is 16)
+// 0x3E0 - 0x3FC  ID registers
+//-------------------------------------
+
+module socshute_apb_usrt (
+// --------------------------------------------------------------------------
+// Port Definitions
+// --------------------------------------------------------------------------
+  input  wire        PCLK,     // Clock
+  input  wire        PCLKG,    // Gated Clock
+  input  wire        PRESETn,  // Reset
+
+  input  wire        PSEL,     // Device select
+  input  wire [11:2] PADDR,    // Address
+  input  wire        PENABLE,  // Transfer control
+  input  wire        PWRITE,   // Write control
+  input  wire [31:0] PWDATA,   // Write data
+
+  input  wire [3:0]  ECOREVNUM,// Engineering-change-order revision bits
+
+  output wire [31:0] PRDATA,   // Read data
+  output wire        PREADY,   // Device ready
+  output wire        PSLVERR,  // Device error response
+
+  output wire        TX_VALID_o,
+  output wire [7:0]  TX_DATA8_o,
+  input  wire        TX_READY_i,
+
+  input  wire        RX_VALID_i,
+  input  wire [7:0]  RX_DATA8_i,
+  output wire        RX_READY_o,
+
+  output wire        TXINT,    // Transmit Interrupt
+  output wire        RXINT,    // Receive Interrupt
+  output wire        TXOVRINT, // Transmit overrun Interrupt
+  output wire        RXOVRINT, // Receive overrun Interrupt
+  output wire        UARTINT); // Combined interrupt
+
+// Local ID parameters, APB UART part number is 0x821
+localparam  ARM_CMSDK_APB_UART_PID4 = 8'h04;
+localparam  ARM_CMSDK_APB_UART_PID5 = 8'h00;
+localparam  ARM_CMSDK_APB_UART_PID6 = 8'h00;
+localparam  ARM_CMSDK_APB_UART_PID7 = 8'h00;
+localparam  ARM_CMSDK_APB_UART_PID0 = 8'h21;
+localparam  ARM_CMSDK_APB_UART_PID1 = 8'hB8;
+localparam  ARM_CMSDK_APB_UART_PID2 = 8'h1B;
+localparam  ARM_CMSDK_APB_UART_PID3 = 4'h0;
+localparam  ARM_CMSDK_APB_UART_CID0 = 8'h0D;
+localparam  ARM_CMSDK_APB_UART_CID1 = 8'hF0;
+localparam  ARM_CMSDK_APB_UART_CID2 = 8'h05;
+localparam  ARM_CMSDK_APB_UART_CID3 = 8'hB1;
+
+// original external IOs
+wire        RXD = 1'b1; // Serial input
+wire        TXD;      // Transmit data output
+wire        TXEN;     // Transmit enabled
+wire        BAUDTICK; // Baud rate (x16) Tick
+  
+
+  // --------------------------------------------------------------------------
+  // Internal wires
+  // --------------------------------------------------------------------------
+// Signals for read/write controls
+wire          read_enable;
+wire          write_enable;
+wire          write_enable00; // Write enable for data register
+wire          write_enable04; // Write enable for Status register
+wire          write_enable08; // Write enable for control register
+wire          write_enable0c; // Write enable for interrupt status register
+wire          write_enable10; // Write enable for Baud rate divider
+reg     [7:0] read_mux_byte0; // Read data multiplexer for lower 8-bit
+reg     [7:0] read_mux_byte0_reg; // Register read data for lower 8-bit
+wire   [31:0] read_mux_word;  // Read data multiplexer for whole 32-bit
+wire    [3:0] pid3_value;     // constant value for lower 4-bit in perpherial ID3
+
+// Signals for Control registers
+reg     [6:0] reg_ctrl;       // Control register
+reg     [7:0] reg_tx_buf;     // Transmit data buffer
+reg     [7:0] reg_rx_buf;     // Receive data buffer
+reg    [19:0] reg_baud_div;   // Baud rate setting
+
+// Internal signals
+  // Baud rate divider
+reg    [15:0] reg_baud_cntr_i; // baud rate divider counter i (integer)
+wire   [15:0] nxt_baud_cntr_i;
+reg     [3:0] reg_baud_cntr_f; // baud rate divider counter f (fraction)
+wire    [3:0] nxt_baud_cntr_f;
+wire    [3:0] mapped_cntr_f;   // remapped counter f value
+reg           reg_baud_tick;   // Register baud rate tick (16 times of baud rate)
+reg           baud_updated;    // baud rate value has bee updated from APB
+wire          reload_i;        // baud rate divider counter i reload
+wire          reload_f;        // baud rate divider counter f reload
+wire          baud_div_en;     // enable baud rate counter
+
+  // Status
+wire    [3:0] uart_status;     // UART status
+reg           reg_rx_overrun;  // Receive overrun status register
+wire          rx_overrun;      // Receive overrun detection
+reg           reg_tx_overrun;  // Transmit overrun status register
+wire          tx_overrun;      // Transmit overrun detection
+wire          nxt_rx_overrun;  // next state for reg_rx_overrun
+wire          nxt_tx_overrun;  // next state for reg_tx_overrun
+  // Interrupts
+reg           reg_txintr;      // Transmit interrupt register
+reg           reg_rxintr;      // Receive interrupt register
+wire          tx_overflow_intr;// Transmit overrun/overflow interrupt
+wire          rx_overflow_intr;// Receive overrun/overflow interrupt
+wire    [3:0] intr_state;      // UART interrupt status
+wire    [1:0] intr_stat_set;   // Set TX/RX interrupt
+wire    [1:0] intr_stat_clear; // Clear TX/RX interrupt
+
+  // transmit
+reg     [3:0] tx_state;    // Transmit FSM state
+reg     [4:0] nxt_tx_state;
+wire          tx_state_update;
+wire          tx_state_inc; // Bit pulse
+reg     [3:0] tx_tick_cnt;  // Transmit Tick counter
+wire    [4:0] nxt_tx_tick_cnt;
+reg     [7:0] tx_shift_buf;      // Transmit shift register
+wire    [7:0] nxt_tx_shift_buf;  // next state    for tx_shift_buf
+wire          tx_buf_ctrl_shift; // shift control for tx_shift_buf
+wire          tx_buf_ctrl_load;  // load  control for tx_shift_buf
+reg           tx_buf_full;  // TX Buffer full
+reg           reg_txd;      // Tx Data
+wire          nxt_txd;      // next state of reg_txd
+wire          update_reg_txd; // update reg_txd
+wire          tx_buf_clear; // Clear buffer full status when data is load into TX shift register
+
+  // Receive data sync and filter
+reg           rxd_sync_1;  // Double flip-flop syncrhoniser
+reg           rxd_sync_2;  // Double flip-flop syncrhoniser
+reg     [2:0] rxd_lpf;     // Averaging Low Pass Filter
+wire    [2:0] nxt_rxd_lpf;
+wire          rx_shift_in; // Shift Register Input
+
+  // Receiver
+reg     [3:0] rx_state;   // Receiver FSM state
+reg     [4:0] nxt_rx_state;
+wire          rx_state_update;
+reg     [3:0] rx_tick_cnt; // Receiver Tick counter
+wire    [4:0] nxt_rx_tick_cnt;
+wire          update_rx_tick_cnt;
+wire          rx_state_inc;// Bit pulse
+reg     [6:0] rx_shift_buf;// Receiver shift data register
+wire    [6:0] nxt_rx_shift_buf;
+reg           rx_buf_full;  // Receive buffer full status
+wire          nxt_rx_buf_full;
+wire          rxbuf_sample; // Sample received data into receive data buffer
+wire          rx_data_read; // Receive data buffer read by APB interface
+wire    [7:0] nxt_rx_buf;
+
+// Start of main code
+// Read and write control signals
+assign  read_enable  = PSEL & (~PWRITE); // assert for whole APB read transfer
+assign  write_enable = PSEL & (~PENABLE) & PWRITE; // assert for 1st cycle of write transfer
+assign  write_enable00 = write_enable & (PADDR[11:2] == 10'h000);
+assign  write_enable04 = write_enable & (PADDR[11:2] == 10'h001);
+assign  write_enable08 = write_enable & (PADDR[11:2] == 10'h002);
+assign  write_enable0c = write_enable & (PADDR[11:2] == 10'h003);
+assign  write_enable10 = write_enable & (PADDR[11:2] == 10'h004);
+
+// Write operations
+  // Transmit data register
+  always @(posedge PCLKG or negedge PRESETn)
+  begin
+    if (~PRESETn)
+        reg_tx_buf <= {8{1'b0}};
+    else if (write_enable00)
+      reg_tx_buf <= PWDATA[7:0];
+  end
+
+  assign TX_DATA8_o = reg_tx_buf[7:0];
+  
+  // Status register overrun registers
+  assign nxt_rx_overrun = (reg_rx_overrun & (~((write_enable04|write_enable0c) & PWDATA[3]))) | rx_overrun;
+  assign nxt_tx_overrun = (reg_tx_overrun & (~((write_enable04|write_enable0c) & PWDATA[2]))) | tx_overrun;
+
+  // RX OverRun status
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_rx_overrun <= 1'b0;
+    else if (rx_overrun | write_enable04 | write_enable0c)
+      reg_rx_overrun <= nxt_rx_overrun;
+  end
+
+  // TX OverRun status
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_tx_overrun <= 1'b0;
+    else if (tx_overrun | write_enable04 | write_enable0c)
+      reg_tx_overrun <= nxt_tx_overrun;
+  end
+
+  // Control register
+  always @(posedge PCLKG or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_ctrl <= {7{1'b0}};
+    else if (write_enable08)
+      reg_ctrl <= PWDATA[6:0];
+  end
+
+  // Baud rate divider - integer
+  always @(posedge PCLKG or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_baud_div <= {20{1'b0}};
+    else if (write_enable10)
+      reg_baud_div <= PWDATA[19:0];
+  end
+
+// Read operation
+  assign uart_status = {reg_rx_overrun, reg_tx_overrun, rx_buf_full, tx_buf_full};
+
+  assign pid3_value  = ARM_CMSDK_APB_UART_PID3;
+
+  // First level of read mux
+ always @(PADDR or reg_rx_buf or uart_status or reg_ctrl or intr_state or reg_baud_div
+   or ECOREVNUM or pid3_value)
+  begin
+   if (PADDR[11:5] == 7'h00) begin
+     case (PADDR[4:2])
+     3'h0: read_mux_byte0 =  reg_rx_buf;
+     3'h1: read_mux_byte0 =  {{4{1'b0}},uart_status};
+     3'h2: read_mux_byte0 =  {{1{1'b0}},reg_ctrl};
+     3'h3: read_mux_byte0 =  {{4{1'b0}},intr_state};
+     3'h4: read_mux_byte0 =  reg_baud_div[7:0];
+     3'h5, 3'h6, 3'h7: read_mux_byte0 =   {8{1'b0}};     //default read out value
+     default:  read_mux_byte0 =   {8{1'bx}};// x propogation
+     endcase
+   end
+   else if (PADDR[11:6] == 6'h3F) begin
+     case  (PADDR[5:2])
+       4'h0, 4'h1,4'h2,4'h3: read_mux_byte0 =   {8{1'b0}}; //default read out value
+   // ID register - constant values
+       4'h4: read_mux_byte0 = ARM_CMSDK_APB_UART_PID4; // 0xFD0 : PID 4
+       4'h5: read_mux_byte0 = ARM_CMSDK_APB_UART_PID5; // 0xFD4 : PID 5
+       4'h6: read_mux_byte0 = ARM_CMSDK_APB_UART_PID6; // 0xFD8 : PID 6
+       4'h7: read_mux_byte0 = ARM_CMSDK_APB_UART_PID7; // 0xFDC : PID 7
+       4'h8: read_mux_byte0 = ARM_CMSDK_APB_UART_PID0; // 0xFE0 : PID 0  APB UART part number[7:0]
+       4'h9: read_mux_byte0 = ARM_CMSDK_APB_UART_PID1; // 0xFE0 : PID 1 [7:4] jep106_id_3_0. [3:0] part number [11:8]
+       4'hA: read_mux_byte0 = ARM_CMSDK_APB_UART_PID2; // 0xFE0 : PID 2 [7:4] revision, [3] jedec_used. [2:0] jep106_id_6_4
+       4'hB: read_mux_byte0 = {ECOREVNUM[3:0],pid3_value[3:0]};
+                                                       // 0xFE0 : PID 3 [7:4] ECO revision, [3:0] modification number
+       4'hC: read_mux_byte0 = ARM_CMSDK_APB_UART_CID0; // 0xFF0 : CID 0
+       4'hD: read_mux_byte0 = ARM_CMSDK_APB_UART_CID1; // 0xFF4 : CID 1 PrimeCell class
+       4'hE: read_mux_byte0 = ARM_CMSDK_APB_UART_CID2; // 0xFF8 : CID 2
+       4'hF: read_mux_byte0 = ARM_CMSDK_APB_UART_CID3; // 0xFFC : CID 3
+       default : read_mux_byte0 = {8{1'bx}}; // x propogation
+      endcase
+    end
+    else begin
+       read_mux_byte0 =   {8{1'b0}};     //default read out value
+    end
+  end
+
+
+
+  // Register read data
+  always @(posedge PCLKG or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      read_mux_byte0_reg      <= {8{1'b0}};
+    else if (read_enable)
+      read_mux_byte0_reg      <= read_mux_byte0;
+  end
+
+  // Second level of read mux
+  assign read_mux_word[ 7: 0] = read_mux_byte0_reg;
+  assign read_mux_word[19: 8] = (PADDR[11:2]==10'h004) ? reg_baud_div[19:8] : {12{1'b0}};
+  assign read_mux_word[31:20] = {12{1'b0}};
+
+
+  // Output read data to APB
+  assign PRDATA[31: 0] = (read_enable) ? read_mux_word : {32{1'b0}};
+  assign PREADY  = 1'b1; // Always ready
+  assign PSLVERR = 1'b0; // Always okay
+
+// --------------------------------------------
+// Baud rate generator
+  // Baud rate generator enable
+  assign baud_div_en    = (reg_ctrl[1:0] != 2'b00);
+  assign mapped_cntr_f  = {reg_baud_cntr_f[0],reg_baud_cntr_f[1],
+                           reg_baud_cntr_f[2],reg_baud_cntr_f[3]};
+  // Reload Integer divider
+  // when UART enabled and (reg_baud_cntr_f < reg_baud_div[3:0])
+  // then count to 1, or
+  // when UART enabled then count to 0
+  assign reload_i      = (baud_div_en &
+         (((mapped_cntr_f >= reg_baud_div[3:0]) &
+         (reg_baud_cntr_i[15:1] == {15{1'b0}})) |
+         (reg_baud_cntr_i[15:0] == {16{1'b0}})));
+
+  // Next state for Baud rate divider
+  assign nxt_baud_cntr_i = (baud_updated | reload_i) ? reg_baud_div[19:4] :
+                           (reg_baud_cntr_i - 16'h0001);
+  // Update at reload or decrement
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_baud_cntr_i   <= {16{1'b0}};
+    else if (baud_updated | baud_div_en)
+      reg_baud_cntr_i   <= nxt_baud_cntr_i;
+  end
+
+  // Reload fraction divider
+  assign reload_f      = baud_div_en & (reg_baud_cntr_f==4'h0) &
+                        reload_i;
+  // Next state for fraction part of Baud rate divider
+  assign nxt_baud_cntr_f =
+                        (reload_f|baud_updated) ? 4'hF :
+                        (reg_baud_cntr_f - 4'h1);
+
+  // Update at reload or decrement
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_baud_cntr_f   <= {4{1'b0}};
+    else if (baud_updated | reload_f | reload_i)
+      reg_baud_cntr_f   <= nxt_baud_cntr_f;
+  end
+
+  // Generate control signal to update baud rate counters
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      baud_updated    <= 1'b0;
+    else if (write_enable10 | baud_updated)
+      // Baud rate updated - to load new value to counters
+      baud_updated    <= write_enable10;
+  end
+
+  // Generate Tick signal for external logic
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_baud_tick    <= 1'b0;
+    else if (reload_i | reg_baud_tick)
+      reg_baud_tick    <= reload_i;
+  end
+
+  // Connect to external
+  assign BAUDTICK = reg_baud_tick;
+
+// --------------------------------------------
+// Transmit
+
+  // Buffer full status
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      tx_buf_full     <= 1'b0;
+    else if (write_enable00) // | tx_buf_clear)
+      tx_buf_full     <= write_enable00;
+    else if (tx_buf_full & TX_READY_i) // AXI stream ack
+      tx_buf_full <= 0;
+  end
+
+  assign TX_VALID_o = tx_buf_full;
+
+  // Increment TickCounter
+  assign nxt_tx_tick_cnt = ((tx_state==4'h1) & reg_baud_tick) ? {5{1'b0}} :
+                        tx_tick_cnt + {{3{1'b0}},reg_baud_tick};
+
+  // Registering TickCounter
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      tx_tick_cnt     <= {4{1'b0}};
+    else if (reg_baud_tick)
+      tx_tick_cnt     <= nxt_tx_tick_cnt[3:0];
+  end
+
+  // Increment state (except Idle(0) and Wait for Tick(1))
+  assign tx_state_inc   = (((&tx_tick_cnt)|(tx_state==4'h1)) & reg_baud_tick)|reg_ctrl[6];
+          // state increment every cycle of high speed test mode is enabled
+  // Clear buffer full status when data is load into shift register
+  assign tx_buf_clear   = ((tx_state==4'h0) & tx_buf_full) |
+                        ((tx_state==4'hB) & tx_buf_full & tx_state_inc);
+
+  // tx_state machine
+  // 0 = Idle, 1 =  Wait for Tick,
+  // 2 = Start bit, 3 = D0 .... 10 = D7
+  // 11 = Stop bit
+  always @(tx_state or tx_buf_full or tx_state_inc or reg_ctrl)
+  begin
+  case (tx_state)
+    0: begin
+       nxt_tx_state = (tx_buf_full & reg_ctrl[0]) ? 5'h01 : 5'h00;  // New data is written to buffer
+       end
+    1,                         // State 1   : Wait for next Tick
+    2,3,4,5,6,7,8,9,10: begin  // State 2-10: Start bit, D0 - D7
+       nxt_tx_state = tx_state + {3'b000,tx_state_inc};
+       end
+    11: begin // Stop bit , goto next start bit or Idle
+       nxt_tx_state = (tx_state_inc) ? ( tx_buf_full ? 5'h02:5'h00) : {1'b0, tx_state};
+       end
+    default:
+       nxt_tx_state = {5{1'bx}};
+  endcase
+  end
+
+  assign tx_state_update = tx_state_inc | ((tx_state==4'h0) & tx_buf_full & reg_ctrl[0]) | (tx_state>4'd11);
+
+  // Registering outputs
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      tx_state        <= {4{1'b0}};
+    else if (tx_state_update)
+      tx_state        <= nxt_tx_state[3:0];
+  end
+
+  // Load/shift TX register
+  assign tx_buf_ctrl_load  = (((tx_state==4'h0) & tx_buf_full) |
+                              ((tx_state==4'hB) & tx_buf_full & tx_state_inc));
+  assign tx_buf_ctrl_shift =  ((tx_state>4'h2) & tx_state_inc);
+
+  assign nxt_tx_shift_buf = tx_buf_ctrl_load ? reg_tx_buf[7:0] : {1'b1,tx_shift_buf[7:1]};
+
+  // Registering TX shift register
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      tx_shift_buf    <= {8{1'b0}};
+    else if (tx_buf_ctrl_shift | tx_buf_ctrl_load)
+      tx_shift_buf    <= nxt_tx_shift_buf;
+  end
+
+  // Data output
+  assign nxt_txd = (tx_state==4'h2) ? 1'b0 :
+                   (tx_state>4'h2) ? tx_shift_buf[0] : 1'b1;
+
+  assign update_reg_txd = (nxt_txd != reg_txd);
+
+  // Registering outputs
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_txd         <= 1'b1;
+    else if (update_reg_txd)
+      reg_txd         <= nxt_txd;
+  end
+
+  // Generate TX overrun error status
+  assign tx_overrun = tx_buf_full & (~tx_buf_clear) & write_enable00;
+
+  // Connect to external
+  assign TXD  = reg_txd;
+  assign TXEN = reg_ctrl[0];
+
+// --------------------------------------------
+// Receive synchronizer and low pass filter
+
+  // Doubling Flip-flop synxt_rx_tick_cntnchroniser
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      begin
+      rxd_sync_1 <= 1'b1;
+      rxd_sync_2 <= 1'b1;
+      end
+    else if (reg_ctrl[1]) // Turn off synchronizer if receive is not enabled
+      begin
+      rxd_sync_1 <= RXD;
+      rxd_sync_2 <= rxd_sync_1;
+      end
+  end
+
+  // Averaging low pass filter
+  assign nxt_rxd_lpf = {rxd_lpf[1:0], rxd_sync_2};
+  // Registering stage for low pass filter
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      rxd_lpf <= 3'b111;
+    else if (reg_baud_tick)
+      rxd_lpf <= nxt_rxd_lpf;
+  end
+
+  // Averaging values
+  assign rx_shift_in = (rxd_lpf[1] & rxd_lpf[0]) |
+                       (rxd_lpf[1] & rxd_lpf[2]) |
+                       (rxd_lpf[0] & rxd_lpf[2]);
+
+// --------------------------------------------
+// Receive
+
+  // Increment TickCounter
+  assign nxt_rx_tick_cnt = ((rx_state==4'h0) & (~rx_shift_in)) ? 5'h08 :
+                        rx_tick_cnt + {{3{1'b0}},reg_baud_tick};
+
+  assign update_rx_tick_cnt = ((rx_state==4'h0) & (~rx_shift_in)) | reg_baud_tick;
+
+  // Registering other register
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      rx_tick_cnt    <= {4{1'b0}};
+    else if (update_rx_tick_cnt)
+      rx_tick_cnt    <= nxt_rx_tick_cnt[3:0];
+  end
+
+  // Increment state
+  assign rx_state_inc   = ((&rx_tick_cnt) & reg_baud_tick);
+  // Buffer full status
+  assign nxt_rx_buf_full = rxbuf_sample | (rx_buf_full & (~rx_data_read));
+
+  // Sample shift register when D7 is sampled
+///  assign rxbuf_sample  = ((rx_state==4'h9) & rx_state_inc);
+  assign rxbuf_sample  = RX_VALID_i & !rx_buf_full;
+
+  // Reading receive buffer (Set at 1st cycle of APB transfer
+  // because read mux is registered before output)
+  assign rx_data_read   = (PSEL & (~PENABLE) & (PADDR[11:2]==10'h000) & (~PWRITE));
+  // Generate RX overrun error status
+  assign rx_overrun = rx_buf_full & rxbuf_sample & (~rx_data_read);
+
+  // rx_state machine
+  // 0 = Idle, 1 =  Start of Start bit detected
+  // 2 = Sample Start bit, 3 = D0 .... 10 = D7
+  // 11 = Stop bit
+  // 11, 12, 13, 14, 15: illegal/unused states
+  always @(rx_state or rx_shift_in or rx_state_inc or reg_ctrl)
+  begin
+  case (rx_state)
+    0: begin
+       nxt_rx_state = ((~rx_shift_in) & reg_ctrl[1]) ? 5'h01 : 5'h00;  // Wait for Start bit
+       end
+    1,                      // State 1  : Wait for middle of start bit
+    2,3,4,5,6,7,8,9: begin  // State 2-9: D0 - D7
+       nxt_rx_state = rx_state + {3'b000,rx_state_inc};
+       end
+    10: begin // Stop bit , goto back to Idle
+       nxt_rx_state = (rx_state_inc) ? 5'h00 : 5'h0A;
+       end
+    default:
+       nxt_rx_state = {5{1'bx}};
+  endcase
+  end
+
+  assign rx_state_update = rx_state_inc |  ((~rx_shift_in) & reg_ctrl[1]);
+
+  // Registering rx_state
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      rx_state       <= {4{1'b0}};
+    else if (rx_state_update)
+      rx_state       <= nxt_rx_state[3:0];
+  end
+
+  // Buffer full status
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      rx_buf_full     <= 1'b0;
+    else if (rxbuf_sample | rx_data_read)
+      rx_buf_full     <= nxt_rx_buf_full;
+  end
+
+  // Sample receive buffer
+///  assign nxt_rx_buf     = {rx_shift_in, rx_shift_buf};
+  assign nxt_rx_buf     = RX_DATA8_i[7:0];
+  
+  // Registering receive data buffer
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_rx_buf      <= {8{1'b0}};
+    else if  (rxbuf_sample)
+      reg_rx_buf      <= nxt_rx_buf;
+  end
+
+  // Shift register
+  assign nxt_rx_shift_buf= {rx_shift_in, rx_shift_buf[6:1]};
+  // Registering shift buffer
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      rx_shift_buf    <= {7{1'b0}};
+    else if (rx_state_inc)
+      rx_shift_buf    <= nxt_rx_shift_buf;
+  end
+
+
+
+// --------------------------------------------
+// Interrupts
+  // Set by event
+  assign intr_stat_set[1] = reg_ctrl[3] & rxbuf_sample; // A new receive data is sampled
+  assign intr_stat_set[0] = reg_ctrl[2] & reg_ctrl[0] & tx_buf_full & tx_buf_clear;
+                            // Falling edge of buffer full
+  // Clear by write to IntClear register
+  assign intr_stat_clear[1:0] = {2{write_enable0c}} & PWDATA[1:0];
+
+  // Registering outputs
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_txintr    <= 1'b0;
+    else if (intr_stat_set[0] | intr_stat_clear[0])
+      reg_txintr    <= intr_stat_set[0];
+  end
+
+  always @(posedge PCLK or negedge PRESETn)
+  begin
+    if (~PRESETn)
+      reg_rxintr    <= 1'b0;
+    else if (intr_stat_set[1] | intr_stat_clear[1])
+      reg_rxintr    <= intr_stat_set[1];
+  end
+
+  assign rx_overflow_intr = reg_rx_overrun & reg_ctrl[5];
+  assign tx_overflow_intr = reg_tx_overrun & reg_ctrl[4];
+
+  // Interrupt status for read back
+  assign intr_state = {rx_overflow_intr, tx_overflow_intr, reg_rxintr, reg_txintr};
+
+  // Connect to external
+  assign TXINT    = reg_txintr;
+  assign RXINT    = reg_rxintr;
+  assign TXOVRINT = tx_overflow_intr;
+  assign RXOVRINT = rx_overflow_intr;
+  assign UARTINT  = reg_txintr | reg_rxintr | tx_overflow_intr | rx_overflow_intr;
+
+
+`ifdef ARM_APB_ASSERT_ON
+   // ------------------------------------------------------------
+   // Assertions
+   // ------------------------------------------------------------
+`include "std_ovl_defines.h"
+
+   // Prepare signals for OVL checking
+   reg [15:0] ovl_last_reg_baud_cntr_i;
+   reg  [3:0] ovl_last_reg_baud_cntr_f;
+   reg        ovl_last_baud_div_en;
+   reg        ovl_last_baud_updated;
+   always @(posedge PCLK or negedge PRESETn)
+   begin
+     if (~PRESETn)
+       begin
+       ovl_last_reg_baud_cntr_i <= {16{1'b0}};
+       ovl_last_reg_baud_cntr_f <= {4{1'b0}};
+       ovl_last_baud_div_en     <= 1'b0;
+       ovl_last_baud_updated    <= 1'b0;
+       end
+     else
+       begin
+       ovl_last_reg_baud_cntr_i <= reg_baud_cntr_i;
+       ovl_last_reg_baud_cntr_f <= reg_baud_cntr_f;
+       ovl_last_baud_div_en     <= baud_div_en;
+       ovl_last_baud_updated    <= baud_updated;
+       end
+   end
+
+   reg        ovl_reg_hs_test_mode_triggered; // Indicate if HighSpeed testmode has been activated
+   wire       ovl_nxt_hs_test_mode_triggered;
+   reg  [7:0] ovl_reg_tx_tick_count;  // For measuring width of TX state
+   wire [7:0] ovl_nxt_tx_tick_count;
+   reg  [7:0] ovl_reg_rx_tick_count;  // For measuring width of RX state
+   wire [7:0] ovl_nxt_rx_tick_count;
+   reg  [3:0] ovl_reg_last_tx_state;  // last state
+   reg  [3:0] ovl_reg_last_rx_state;
+   reg  [6:0] ovl_last_reg_ctrl;
+
+   // Clear test mode indicator each time state is changed, set to 1 if high speed test mode is
+   // enabled
+   assign ovl_nxt_hs_test_mode_triggered =
+     (tx_state!=ovl_reg_last_tx_state) ? reg_ctrl[6]: (reg_ctrl[6] | ovl_reg_hs_test_mode_triggered);
+
+   // Counter clear at each state change, increasement at each reg_baud_tick
+   assign ovl_nxt_tx_tick_count = (tx_state!=ovl_reg_last_tx_state) ? (8'h00) :
+     (ovl_reg_tx_tick_count + {{7{1'b0}}, reg_baud_tick});
+
+   // Counter clear at each state change, increasement at each reg_baud_tick
+   assign ovl_nxt_rx_tick_count = (rx_state!=ovl_reg_last_rx_state) ? (8'h00) :
+     (ovl_reg_rx_tick_count + {{7{1'b0}}, reg_baud_tick});
+
+   always@(posedge PCLK or negedge PRESETn)
+     begin
+     if (~PRESETn)
+       begin
+       ovl_reg_hs_test_mode_triggered <= 1'b0;
+       ovl_reg_last_tx_state          <= 4'h0;
+       ovl_reg_last_rx_state          <= 4'h0;
+       ovl_reg_tx_tick_count          <= 8'h00;
+       ovl_reg_rx_tick_count          <= 8'h00;
+       ovl_last_reg_ctrl              <= 7'h00;
+       end
+     else
+       begin
+       ovl_reg_hs_test_mode_triggered <= ovl_nxt_hs_test_mode_triggered;
+       ovl_reg_last_tx_state          <= tx_state;
+       ovl_reg_last_rx_state          <= rx_state;
+       ovl_reg_tx_tick_count          <= ovl_nxt_tx_tick_count;
+       ovl_reg_rx_tick_count          <= ovl_nxt_rx_tick_count;
+       ovl_last_reg_ctrl              <= reg_ctrl;
+       end
+     end
+
+   // Signals for checking clearing of interrupts
+   reg          ovl_last_txint;
+   reg          ovl_last_rxint;
+   reg          ovl_last_psel;
+   reg          ovl_last_penable;
+   reg          ovl_last_pwrite;
+   reg  [31:0]  ovl_last_pwdata;
+   reg  [11:2]  ovl_last_paddr;
+   reg          ovl_last_rx_buf_full;
+   reg          ovl_last_tx_shift_buf_0;
+
+
+   always@(posedge PCLK or negedge PRESETn)
+     begin
+     if (~PRESETn)
+       begin
+       ovl_last_txint   <= 1'b0;
+       ovl_last_rxint   <= 1'b0;
+       ovl_last_psel    <= 1'b0;
+       ovl_last_penable <= 1'b0;
+       ovl_last_pwrite  <= 1'b0;
+       ovl_last_paddr   <= {10{1'b0}};
+       ovl_last_pwdata  <= {32{1'b0}};
+       ovl_last_rx_buf_full  <= 1'b0;
+       ovl_last_tx_shift_buf_0 <= 1'b0;
+       end
+     else
+       begin
+       ovl_last_txint   <= TXINT;
+       ovl_last_rxint   <= RXINT;
+       ovl_last_psel    <= PSEL;
+       ovl_last_penable <= PENABLE;
+       ovl_last_pwrite  <= PWRITE;
+       ovl_last_paddr   <= PADDR;
+       ovl_last_pwdata  <= PWDATA;
+       ovl_last_rx_buf_full  <= rx_buf_full;
+       ovl_last_tx_shift_buf_0 <= tx_shift_buf[0];
+       end
+     end
+
+   // Ensure rx_state must not be 11, 12, 13, 14, 15
+   assert_never
+     #(`OVL_ERROR,`OVL_ASSERT,
+       "rx_state in illegal state")
+   u_ovl_rx_state_illegal
+     (.clk(PCLK), .reset_n(PRESETn),
+      .test_expr((rx_state==4'hB)|(rx_state==4'hC)|(rx_state==4'hD)|
+      (rx_state==4'hE)|(rx_state==4'hF)));
+
+   // Ensure tx_state must not be 12, 13, 14, 15
+   assert_never
+     #(`OVL_ERROR,`OVL_ASSERT,
+       "tx_state in illegal state")
+   u_ovl_tx_state_illegal
+     (.clk(PCLK), .reset_n(PRESETn),
+      .test_expr((tx_state==4'hC)|(tx_state==4'hD)|
+      (tx_state==4'hE)|(tx_state==4'hF)));
+
+   // Ensure reg_baud_cntr_i change only if UART is enabled
+   // or if write to baud rate divider
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+       "Unexpected baud rate divider change")
+   u_ovl_reg_baud_cntr_i_change
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr(ovl_last_reg_baud_cntr_i!=reg_baud_cntr_i),
+      .consequent_expr(ovl_last_baud_div_en | ovl_last_baud_updated )
+      );
+
+   // Ensure reg_baud_div[19:4] >= reg_baud_cntr_i unless reg_baud_div just been programmed
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+       "Unexpected baud rate divided change")
+   u_ovl_reg_baud_cntr_i_range
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr(reg_baud_cntr_i>reg_baud_div[19:4]),
+      .consequent_expr(baud_updated)
+      );
+
+   // Ensure reg_baud_cntr_f change only if UART is enabled
+   // or if write to baud rate divider
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+       "Unexpected baud rate divider change")
+   u_ovl_reg_baud_cntr_f_change
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr(ovl_last_reg_baud_cntr_f!=reg_baud_cntr_f),
+      .consequent_expr(ovl_last_baud_div_en | ovl_last_baud_updated )
+      );
+
+   // Ensure tx_buf_full is set to 1 after write to TX buffer (PADDR[11:2]==0)
+   assert_next
+     #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+      "tx_buf_full should be asserted after write to TX buffer")
+   u_ovl_tx_buf_full
+    (.clk(PCLK),  .reset_n(PRESETn),
+     .start_event (PSEL & (~PENABLE) & PWRITE & (PADDR[11:2] == 10'h000)),
+     .test_expr   (tx_buf_full)
+     );
+
+   // If last tx_state=0 (idle) or 1 (wait for tick), TXD = 1.
+   assert_next
+     #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+      "TXD should be 1 when idle or just before data transmission")
+   u_ovl_txd_state_0_1
+    (.clk(PCLK),  .reset_n(PRESETn),
+     .start_event ((tx_state==4'd0)|(tx_state==4'd1)),
+     .test_expr   (TXD==1'b1)
+     );
+
+   // If last tx_state=2 (start bit), TXD = 0.
+   assert_next
+     #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+      "TXD should be 0 when output start bit")
+   u_ovl_txd_state_2
+    (.clk(PCLK),  .reset_n(PRESETn),
+     .start_event (tx_state==4'd2),
+     .test_expr   (TXD==1'b0)
+     );
+
+   // If last tx_state=3-10 (D0 to D7), TXD = anything (tx_shift_buf[0]).
+   assert_next
+     #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+      "TXD should be same as first bit of shift register during transfer")
+   u_ovl_txd_state_3_to_10
+    (.clk(PCLK),  .reset_n(PRESETn),
+     .start_event ((tx_state>4'd2) & (tx_state<4'd11)),
+     .test_expr   (TXD==ovl_last_tx_shift_buf_0)
+     );
+
+   // If last tx_state=11 (stop bit), TXD = 1.
+   assert_next
+     #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+      "TXD should be 1 when output stop bit")
+   u_ovl_txd_state_11
+    (.clk(PCLK),  .reset_n(PRESETn),
+     .start_event (tx_state==4'd11),
+     .test_expr   (TXD==1'b1)
+     );
+
+   // Duration of tx_state in 2 to 11 must have 16 reg_baud_tick
+   // (unless high speed test mode has been active)
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "Duration of tx_state when in state 2 to state 11 should have 16 ticks")
+   u_ovl_width_of_tx_state
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr((tx_state!=ovl_reg_last_tx_state) &      // at state change
+       (ovl_reg_last_tx_state>4'd1)&(ovl_reg_last_tx_state<4'd12) & // from state 2 to 11
+       (ovl_reg_hs_test_mode_triggered==1'b0)), // high speed test mode not triggered
+      .consequent_expr((ovl_reg_tx_tick_count==8'd15) | (ovl_reg_tx_tick_count==8'd16))
+        // count from 0 to 15 (16 ticks)
+     );
+
+
+   // In high speed test mode, tx_state must change if it is in range of 2 to 11
+   assert_next
+     #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+       "Duration of tx_state should be 1 cycle if high speed test mode is enabled")
+   u_ovl_width_of_tx_state_in_high_speed_test_mode
+     (.clk(PCLK), .reset_n(PRESETn),
+      .start_event((tx_state>4'd1)&(tx_state<4'd12) & reg_ctrl[6]),
+      .test_expr  (tx_state != ovl_reg_last_tx_state)
+      );
+
+   // Duration of rx_state in 1 must have 8 reg_baud_tick
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "Duration of rx_state when state 1 should have 8 ticks")
+   u_ovl_width_of_rx_state_1
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr((rx_state!=ovl_reg_last_rx_state) & // at state change
+       (ovl_reg_last_rx_state==4'd1)), // last state was state 1
+      .consequent_expr((ovl_reg_rx_tick_count==8'd7)|(ovl_reg_rx_tick_count==8'd8))
+        // count from 0 to 7 (8 ticks)
+     );
+
+   // Duration of rx_state in 2 to 10 must have 16 reg_baud_tick
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "Duration of rx_state when in state 2 to state 10 should have 16 ticks")
+   u_ovl_width_of_rx_state_data
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr((rx_state!=ovl_reg_last_rx_state) &    // at state change
+       (ovl_reg_last_rx_state>4'd1)&(ovl_reg_last_rx_state<4'd11)),  // from state 2 to 9
+      .consequent_expr((ovl_reg_rx_tick_count==8'd15)|(ovl_reg_rx_tick_count==8'd16))
+         // count from 0 to 15 (16 ticks)
+     );
+
+   // UARTINT must be 0 if TXINT, RXINT, TXOVRINT and RXOVRINT are all 0
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "UARTINT must be 0 if TXINT, RXINT, TXOVRINT and RXOVRINT are all 0")
+   u_ovl_uartint_mismatch
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr((TXINT | RXINT | TXOVRINT | RXOVRINT) == 1'b0), // No interrupt
+      .consequent_expr(UARTINT==1'b0) // Combined interrupt = 0
+     );
+
+    // TXINT should be asserted when TX interrupt enabled and transmit buffer is available
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "TXINT should be triggered when enabled")
+    u_ovl_txint_enable
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event (reg_ctrl[0] & reg_ctrl[2] & tx_buf_full & tx_buf_clear),
+     .test_expr   (TXINT == 1'b1)
+     );
+
+   // There should be no rising edge of TXINT if transmit is disabled or transmit interrupt is disabled
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "TXINT should not be triggered when disabled")
+    u_ovl_txint_disable
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event (((reg_ctrl[0]==1'b0) | (reg_ctrl[2]==1'b0)) & (TXINT == 1'b0)),
+     .test_expr   (TXINT == 1'b0)
+     );
+
+   // if TXINT falling edge, there must has been a write to INTCLEAR register with bit[0]=1
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "When there is a falling edge of TXINT, there must has been a write to INTCLEAR")
+   u_ovl_txint_clear
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr(ovl_last_txint & (~TXINT)), // Falling edge of TXINT
+      .consequent_expr(ovl_last_psel & ovl_last_pwrite &
+      (ovl_last_paddr==10'h003) & (ovl_last_pwdata[0]) ) // There must has been a write to INTCLEAR
+     );
+
+    // RXINT should be asserted when RX interrupt enabled and a new data is received
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "RXINT should be triggered when enabled")
+    u_ovl_rxint_enable
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event (reg_ctrl[3] & (rx_state==9) & (nxt_rx_state==10)),
+     .test_expr   (RXINT == 1'b1)
+     );
+
+   // There should be no rising edge of RXINT if receive interrupt is disabled
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "RXINT should not be triggered when disabled")
+    u_ovl_rxint_disable
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event ((reg_ctrl[3]==1'b0) & (RXINT == 1'b0)),
+     .test_expr   (RXINT == 1'b0)
+     );
+
+   // if RXINT falling edge, there must has been a write to INTCLEAR register with bit[1]=1
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "When there is a falling edge of RXINT, there must has been a write to INTCLEAR")
+   u_ovl_rxint_clear
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr(ovl_last_rxint & (~RXINT)), // Falling edge of TXINT
+      .consequent_expr(ovl_last_psel & ovl_last_pwrite &
+      (ovl_last_paddr==10'h003) & (ovl_last_pwdata[1]) ) // There must has been a write to INTCLEAR
+     );
+
+   // rx_buf_full should rise if rx_state change from 9 to 10
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "rx_buf_full should be asserted when a new character is received")
+    u_ovl_rx_buf_full
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event ((rx_state==9) & (nxt_rx_state==10)),
+     .test_expr   (rx_buf_full == 1'b1)
+     );
+
+   // if rx_buf_full falling edge, there must has been a read to the receive buffer
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "When there is a falling edge of RXINT, there must has been a read to receive buffer")
+   u_ovl_rx_buf_full_clear
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr((~rx_buf_full) & ovl_last_rx_buf_full), // Falling edge of rx_buf_full
+      .consequent_expr(ovl_last_psel & (~ovl_last_pwrite) &
+      (ovl_last_paddr==10'h000)  ) // There must has been a read to rx data
+     );
+
+   // TXOVRINT must be 0 if reg_ctrl[4]=0
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "When there is a falling edge of RXINT, there must has been a write to INTCLEAR")
+   u_ovl_txovrint_disable
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr(~reg_ctrl[4]),
+      .consequent_expr(~TXOVRINT)
+     );
+
+   // RXOVRINT must be 0 if reg_ctrl[5]=0
+   assert_implication
+     #(`OVL_ERROR,`OVL_ASSERT,
+     "When there is a falling edge of RXINT, there must has been a write to INTCLEAR")
+   u_ovl_rxovrint_disable
+     (.clk(PCLK), .reset_n(PRESETn),
+      .antecedent_expr(~reg_ctrl[5]),
+      .consequent_expr(~RXOVRINT)
+     );
+
+   // if a write take place to TX data buffer and tx_buf_full was 1, reg_tx_overrun will be set
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "tx buffer overrun should be asserted when a new character is write to buffer and buffer is already full")
+    u_ovl_tx_buffer_overrun
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event (write_enable00 & tx_buf_full & (~tx_buf_clear)),
+     .test_expr   (reg_tx_overrun == 1'b1)
+     );
+
+   // if rx_buf_full is high and rx_state change from 9 to 10, reg_rx_overrun will be set
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "rx buffer overrun should be asserted when a new character is received and rx buffer is already full")
+    u_ovl_rx_buffer_overrun
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event (rx_buf_full & (~rx_data_read) & (rx_state==9) & (nxt_rx_state==10)),
+     .test_expr   (reg_rx_overrun == 1'b1)
+     );
+
+   // if write to INTCLEAR  with bit[2]=1, reg_tx_overrun will be cleared,
+    // Cannot have new overrun at the same time because the APB can only do onething at a time
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "tx buffer overrun should be clear when write to INTCLEAR")
+    u_ovl_tx_buffer_overrun_clear_a
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event (write_enable0c & (PWDATA[2])),
+     .test_expr   (reg_tx_overrun==1'b0)
+     );
+
+   // if write to STATUS  with bit[2]=1, reg_tx_overrun will be cleared,
+    // Cannot have new overrun at the same time because the APB can only do onething at a time
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "tx buffer overrun should be clear when write to INTCLEAR")
+    u_ovl_tx_buffer_overrun_clear_b
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event (write_enable04 & (PWDATA[2])),
+     .test_expr   (reg_tx_overrun==1'b0)
+     );
+
+   // if write to INTCLEAR  with bit[3]=1, reg_rx_overrun will be cleared, unless a new overrun take place
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "rx buffer overrun should be clear when write to INTCLEAR, unless new overrun")
+    u_ovl_rx_buffer_overrun_clear_a
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event (write_enable0c & (PWDATA[3]) & (~(rx_buf_full & (rx_state==9) & (nxt_rx_state==10)))),
+     .test_expr   (reg_rx_overrun==1'b0)
+     );
+
+   // If rx buffer is not full, it cannot have new overrun
+    assert_next
+    #(`OVL_ERROR, 1,1,0, `OVL_ASSERT,
+    "rx buffer overrun should be clear when write to INTCLEAR, unless new overrun")
+    u_ovl_rx_buffer_overrun_when_empty
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event ((~rx_buf_full) & (reg_rx_overrun==1'b0)),
+     .test_expr   (reg_rx_overrun==1'b0)
+     );
+
+
+   // Reading of reg_baud_div (worth checking due to two stage read mux)
+    assert_next
+    #(`OVL_ERROR, 1, 1, 0, `OVL_ASSERT,
+    "Reading of baud rate divider value")
+    u_ovl_read_baud_rate_divide_cfg
+      (.clk(PCLK ), .reset_n (PRESETn),
+     .start_event   (PSEL & (~PENABLE) & (~PWRITE) & (PADDR[11:2]==10'h004)),
+     .test_expr     (PRDATA=={{12{1'b0}}, reg_baud_div})
+     );
+
+   // Recommended Baud Rate divider value is at least 16
+   assert_never
+     #(`OVL_ERROR,`OVL_ASSERT,
+       "UART enabled with baud rate less than 16")
+   u_ovl_baud_rate_divider_illegal
+     (.clk(PCLK), .reset_n(PRESETn),
+      .test_expr(((reg_ctrl[0]) & (reg_ctrl[6]==1'b0) & (reg_baud_div[19:4]=={16{1'b0}}) ) |
+                 ((reg_ctrl[1]) &                       (reg_baud_div[19:4]=={16{1'b0}}) ) )
+      );
+
+   // Test mode never changes from hi-speed to normal speed unless TX is idle
+   assert_never
+     #(`OVL_ERROR,`OVL_ASSERT,
+       "High speed test mode has been changed when TX was not idle")
+   u_ovl_change_speed_tx_illegal
+     (.clk(PCLK), .reset_n(PRESETn),
+      .test_expr((tx_state != 4'd00) & (reg_ctrl[6] != ovl_last_reg_ctrl[6]))
+      );
+
+`endif
+
+endmodule
diff --git a/controller/verilog/socshute_ft1248_stream.v b/controller/verilog/socshute_ft1248_stream.v
new file mode 100755
index 0000000000000000000000000000000000000000..1030636ae197d099430a22fac96eecd400e0723c
--- /dev/null
+++ b/controller/verilog/socshute_ft1248_stream.v
@@ -0,0 +1,291 @@
+//-----------------------------------------------------------------------------
+// SoCShute FTDI FT1248 Interface to AXI-Stream Controller
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Flynn (d.w.flynn@soton.ac.uk)
+//
+// Copyright � 2022, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+module socshute_ft1248_stream #(
+  parameter integer FT1248_WIDTH	= 1, // FTDI Interface 1,2,4 width supported
+  parameter integer FT1248_CLKON	= 1  // FTDI clock always on - else quiet when no access
+)(
+  // IO pad interface - to FT232R configured in 1/2/4/8 mode
+  output wire  ft_clk_o,         // SCLK
+  output wire  ft_ssn_o,         // SS_N
+  input  wire  ft_miso_i,        // MISO
+  output wire [FT1248_WIDTH-1:0] ft_miosio_o,   // MIOSIO tristate output when enabled
+  output wire [FT1248_WIDTH-1:0] ft_miosio_e,   // MIOSIO tristate output enable (active hi)
+  output wire [FT1248_WIDTH-1:0] ft_miosio_z,   // MIOSIO tristate output enable (active lo)
+  input  wire [FT1248_WIDTH-1:0] ft_miosio_i,   // MIOSIO tristate input
+  
+  input  wire [7:0] ft_clkdiv,    // divider prescaler to ensure SCLK <1MHz
+
+  input  wire  clk,
+  input  wire  resetn,
+
+  // Ports of Axi Master Bus Interface TXD - To ADP Controller
+  output wire       txd_tvalid,
+  output wire [7:0] txd_tdata,
+  output wire       txd_tlast,
+  input  wire       txd_tready,
+
+  // Ports of Axi Slave Bus Interface RXD - To 
+  output wire       rxd_tready,
+  input  wire [7:0] rxd_tdata,
+  input  wire       rxd_tlast,
+  input  wire       rxd_tvalid
+);
+
+	//----------------------------------------------
+	//-- State Machine encoding
+	//----------------------------------------------
+
+// Explicit FSM state bit assignment
+//  bit [0] SCLK
+//  bit [1] MIO_OE
+//  bit [2] CMD/W
+//  bit [3] DAT/R
+//  bit [4] SSEL
+
+  localparam FT_0_IDLE       = 5'b00000;
+  localparam FT_1_IDLE       = 5'b00001;
+  localparam FT_ZCMD_CLKLO   = 5'b10100;
+  localparam FT_CMD_CLKHI    = 5'b10111;
+  localparam FT_CMD_CLKLO    = 5'b10110;
+  localparam FT_ZBT_CLKHI    = 5'b10001;
+  localparam FT_ZBT_CLKLO    = 5'b10000;
+  localparam FT_WD_CLKHI     = 5'b11111;
+  localparam FT_WD_CLKLO     = 5'b11110;
+  localparam FT_ZWD_CLKLO    = 5'b11100;
+  localparam FT_RD_CLKHI     = 5'b11001;
+  localparam FT_RD_CLKLO     = 5'b11000;
+
+  reg [4:0] ft_state;
+  // 9- bit shift register to support 8-bit data + 1 sequence control flag
+  // write data uses bits[7:0], with bit[8] set to flag length for serialized transfers
+  // read  data uses bits[8:1], with bit[0] set to flag continuation for serialized transfers
+  reg [8:0] ft_reg;
+
+  //----------------------------------------------
+  //-- IO PAD control, parameterized on WIDTH param
+  //----------------------------------------------
+    
+  wire bwid8 = (FT1248_WIDTH==8);
+  wire bwid4 = (FT1248_WIDTH==4);
+  wire bwid2 = (FT1248_WIDTH==2);
+  wire bwid1 = (FT1248_WIDTH==1);
+
+  wire [7:0] ft_rdmasked;
+
+  generate 
+    if (FT1248_WIDTH == 8) begin
+      assign ft_rdmasked[7:1] =  ft_miosio_i[7:1];
+      assign ft_miosio_o[7:1] =  ft_reg[7:1];
+      assign ft_miosio_e[7:1] =  {7{ft_state[1]}};
+      assign ft_miosio_z[7:1] = ~{7{ft_state[1]}};
+    end 
+  endgenerate
+
+  generate 
+    if (FT1248_WIDTH == 4) begin
+      assign ft_rdmasked[7:1] =  {4'b1111, ft_miosio_i[3:1]};
+      assign ft_miosio_o[3:1] =  ft_reg[3:1];
+      assign ft_miosio_e[3:1] =  {3{ft_state[1]}};
+      assign ft_miosio_z[3:1] = ~{3{ft_state[1]}};
+    end
+  endgenerate
+
+  generate 
+    if (FT1248_WIDTH == 2) begin
+      assign ft_rdmasked[7:1] =  {6'b111111, ft_miosio_i[1]};
+      assign ft_miosio_o[1] =  ft_reg[1];
+      assign ft_miosio_e[1] =  ft_state[1];
+      assign ft_miosio_z[1] = ~ft_state[1];
+    end
+  endgenerate
+
+  generate 
+    if (FT1248_WIDTH == 1) begin
+      assign ft_rdmasked[7:1] =  7'b1111111;
+    end
+  endgenerate
+
+  assign ft_rdmasked[0] = ft_miosio_i[0];
+  assign ft_miosio_o[0] =  ft_reg[0];
+  assign ft_miosio_e[0]  =  ft_state[1];
+  assign ft_miosio_z[0] = ~ft_state[1];
+
+  assign ft_clk_o =  ft_state[0];
+  assign ft_ssn_o = !ft_state[4];
+
+  // diagnostic decodes
+  //wire   ft_cmd = !ft_state[3] &  ft_state[2];
+  //wire   ft_dwr =  ft_state[3] &  ft_state[2];
+  //wire   ft_drd =  ft_state[3] & !ft_state[2];
+
+
+  //----------------------------------------------
+  //-- Internal clock prescaler
+  //----------------------------------------------
+
+  // clock prescaler, ft_clken enables serial IO engine clocking
+  reg [7:0] ft_clkcnt_r;
+  reg       ft_clken;
+
+  always @(posedge clk or negedge resetn )
+  begin
+    if (!resetn) begin
+      ft_clkcnt_r <= 0;
+      ft_clken    <= 0;
+      end
+    else begin
+      ft_clken    <= (ft_clkcnt_r == ft_clkdiv);
+      ft_clkcnt_r <= (ft_clkcnt_r == ft_clkdiv) ? 0 : (ft_clkcnt_r +1);
+      end
+  end
+
+  //----------------------------------------------
+  //-- Internal "synchronizers" (dual stage)
+  //----------------------------------------------
+  // synchronizers for channel ready flags when idle
+  // (treat these signals as synchronous during transfer sequencing)
+  reg ft_miso_i_sync;
+  reg ft_miosio_i0_sync;
+  reg ft_miso_i_sync_1;
+  reg ft_miosio_i0_sync_1;
+
+  always @(posedge clk or negedge resetn )
+  begin
+    if (!resetn) begin
+      ft_miso_i_sync_1   <= 1;
+      ft_miosio_i0_sync_1 <= 1;
+      ft_miso_i_sync     <= 1;
+      ft_miosio_i0_sync   <= 1;
+      end
+    else begin
+      ft_miso_i_sync_1   <= ft_miso_i;
+      ft_miosio_i0_sync_1 <= ft_miosio_i[0];
+      ft_miso_i_sync     <= ft_miso_i_sync_1;
+      ft_miosio_i0_sync   <= ft_miosio_i0_sync_1;
+      end
+  end
+
+  //----------------------------------------------
+  //-- AXI Stream interface handshakes
+  //----------------------------------------------
+
+  reg ft_txf;  // FTDI Transmit channel Full
+  reg ft_rxe;  // FTDO Receive channel Empty
+  reg ft_wcyc; // read access committed
+  reg ft_nak;  // check for NAK terminate
+
+  // TX stream delivers valid FT1248 read data transfer
+  // 8-bit write port with extra top-bit used as valid qualifer
+  reg [8:0] txdata;
+  assign txd_tdata = txdata[7:0];
+  assign txd_tvalid = txdata[8];
+
+  // activate if RX channel data and the stream buffer is not full
+  wire ft_rxreq = !ft_rxe & !txdata[8];
+
+
+  // RX stream handshakes on valid FT1248 write data transfer
+  reg       rxdone;
+  reg       rxrdy;
+  assign    rxd_tready = rxdone;
+
+  // activate if TX channel not full and and the stream buffer data valid
+  wire ft_txreq = !ft_txf & rxd_tvalid; // & !rxdone; // FTDI TX data ready and rxstream ready
+
+  // FTDI1248 commands
+  wire [3:0] wcmd = 4'b0000; // write request
+  wire [3:0] rcmd = 4'b0001; // read  request
+  wire [3:0] fcmd = 4'b0100; // write flush request
+  //wire [3:0] rcmd = 4'b1000; // read  request BE bit-pattern
+  //wire [3:0] fcmd = 4'b0010; // write flush request BE bit-pattern
+  // and full FT1248 command bit patterns (using top-bits for shift sequencing)
+  wire [8:0] wcmdpatt = {2'b11, wcmd[0], wcmd[1], 1'b0, wcmd[2], 1'b0, 1'b0, wcmd[3]};
+  wire [8:0] rcmdpatt = {2'b11, rcmd[0], rcmd[1], 1'b0, rcmd[2], 1'b0, 1'b0, rcmd[3]};
+
+  reg ssn_del;
+  always @(posedge clk or negedge resetn)
+    if (!resetn)
+      ssn_del  <= 1'b1;
+    else if (ft_clken)
+        ssn_del  <= ft_ssn_o;
+  wire ssn_start = ft_ssn_o & ssn_del;
+
+  // FTDI1248 state machine
+
+  always @(posedge clk or negedge resetn)
+    if (!resetn) begin
+      ft_state <= FT_0_IDLE;
+      ft_reg   <= 0;
+      txdata   <= 0;
+      rxdone   <= 0;
+      ft_wcyc  <= 0;
+      ft_txf   <= 1; // ftdi channel  TXE# ('1' full)
+      ft_rxe   <= 1; // ftdi channel  RXF# ('1' empty)
+      ft_nak   <= 0;
+    end else begin
+      ft_txf <= (ft_state==FT_0_IDLE) ? (ft_miosio_i[0] | ft_miosio_i0_sync) : 1'b1; //ft_txf & !( ft_wcyc &(ft_state==FT_ZBT_CLKHI) & ft_miso_i);
+      ft_rxe <= (ft_state==FT_0_IDLE) ? (ft_miso_i | ft_miso_i_sync)  : 1'b1; //ft_rxe & !(!ft_wcyc & (ft_state==FT_ZBT_CLKHI) & ft_miso_i);
+      txdata[8] <= txdata[8] & !txd_tready; // tx_valid handshake
+      rxdone   <= (ft_clken & (ft_state==FT_ZWD_CLKLO) & !ft_nak) | (rxdone & !rxd_tvalid); // hold until acknowledged
+      if (ft_clken)
+        case (ft_state)
+        FT_0_IDLE: begin // RX req priority
+          if (ssn_start & ft_rxreq) begin ft_reg <= rcmdpatt; ft_state <= FT_ZCMD_CLKLO; end
+          else if (ssn_start & ft_txreq) begin ft_reg <= wcmdpatt; ft_state <= FT_ZCMD_CLKLO; ft_wcyc <= 1; end
+          else ft_state <= (!ft_txf | !ft_rxe | (FT1248_CLKON!=0)) ? FT_1_IDLE : FT_0_IDLE;
+          end
+        FT_1_IDLE:
+          ft_state <= FT_0_IDLE;
+        FT_ZCMD_CLKLO:
+          ft_state <= FT_CMD_CLKHI;
+        FT_CMD_CLKHI:
+          ft_state <= FT_CMD_CLKLO;
+        FT_CMD_CLKLO: // 2, 4 or 7 shifts
+          if      (bwid8) begin ft_reg <= FT_ZBT_CLKHI; end 
+          else if (bwid4) begin ft_reg <= {4'b0000,ft_reg[8:4]}; ft_state <= (|ft_reg[8:5]) ? FT_CMD_CLKHI : FT_ZBT_CLKHI; end 
+          else if (bwid2) begin ft_reg <= {  2'b00,ft_reg[8:2]}; ft_state <= (|ft_reg[8:3]) ? FT_CMD_CLKHI : FT_ZBT_CLKHI; end 
+          else            begin ft_reg <= {   1'b0,ft_reg[8:1]}; ft_state <= (|ft_reg[8:3]) ? FT_CMD_CLKHI : FT_ZBT_CLKHI; end 
+        FT_ZBT_CLKHI:
+          ft_state <= FT_ZBT_CLKLO;
+        FT_ZBT_CLKLO:
+          if    (ft_wcyc) begin ft_reg <= {1'b1,rxd_tdata}; ft_state <= FT_WD_CLKHI; end
+          else            begin ft_reg <=  9'b011111111;    ft_state <= FT_RD_CLKHI; end
+        FT_WD_CLKHI:
+          if (ft_miso_i & ft_reg[8]) begin ft_nak <= 1'b1; ft_state <= FT_ZWD_CLKLO; end // NAK terminate on first cycle
+          else if (bwid8) ft_state <=  (ft_reg[8])   ? FT_WD_CLKLO : FT_ZWD_CLKLO; // special case repeat on write data
+          else if (bwid4) ft_state <= (|ft_reg[8:5]) ? FT_WD_CLKLO : FT_ZWD_CLKLO; 
+          else if (bwid2) ft_state <= (|ft_reg[8:3]) ? FT_WD_CLKLO : FT_ZWD_CLKLO; 
+          else            ft_state <= (|ft_reg[8:2]) ? FT_WD_CLKLO : FT_ZWD_CLKLO; 
+        FT_WD_CLKLO:
+          if      (bwid8) begin ft_reg <= {   1'b0,ft_reg[7:0]}; ft_state <= FT_WD_CLKHI; end // clear top flag
+          else if (bwid4) begin ft_reg <= {4'b0000,ft_reg[8:4]}; ft_state <= FT_WD_CLKHI; end // shift 4 bits right
+          else if (bwid2) begin ft_reg <= {  2'b00,ft_reg[8:2]}; ft_state <= FT_WD_CLKHI; end // shift 2 bits right
+          else            begin ft_reg <= {   1'b0,ft_reg[8:1]}; ft_state <= FT_WD_CLKHI; end // shift 1 bit right
+        FT_ZWD_CLKLO:
+          if (ft_nak) begin ft_nak<= 1'b0; ft_state <= FT_0_IDLE;  ft_wcyc <= 1'b0; end // terminate without TX handshake
+          else begin ft_state <= FT_0_IDLE;  ft_wcyc <= 1'b0; end
+        FT_RD_CLKHI: // capture iodata pins end of CLKHI phase
+          if (ft_miso_i & (&ft_reg[7:0])) begin ft_nak <= 1'b1; ft_state <= FT_RD_CLKLO; end // NAK terminate on first cycle
+          else if (bwid8) begin ft_reg <= (ft_reg[0]) ? {ft_rdmasked[7:0],1'b1} : {ft_reg[8:1],1'b0}; ft_state <= FT_RD_CLKLO; end // 8-bit read twice
+          else if (bwid4) begin ft_reg <= {ft_rdmasked[3:0],ft_reg[8:4]}; ft_state <= FT_RD_CLKLO; end 
+          else if (bwid2) begin ft_reg <= {ft_rdmasked[1:0],ft_reg[8:2]}; ft_state <= FT_RD_CLKLO; end 
+          else            begin ft_reg <= {ft_rdmasked[  0],ft_reg[8:1]}; ft_state <= FT_RD_CLKLO; end 
+        FT_RD_CLKLO:
+          if (ft_nak) begin ft_nak<= 1'b0; ft_state <= FT_0_IDLE; txdata <= 9'b0; end // terminate without TX handshake
+          else if (ft_reg[0]) begin ft_state <= FT_RD_CLKHI; ft_reg[0] <= !(bwid8); end // loop until all 8 bits shifted in (or 8-bit read repeated)
+          else begin ft_state <= FT_0_IDLE; txdata <= {1'b1,ft_reg[8:1]}; end
+        default:
+          ft_state <= FT_0_IDLE;
+        endcase
+      end
+    
+endmodule
diff --git a/socket/verilog/axi_stream_io_v1_0.v b/socket/verilog/axi_stream_io_v1_0.v
new file mode 100755
index 0000000000000000000000000000000000000000..0c52be8420c4f63ab7eab0db84cc185a5073bcc6
--- /dev/null
+++ b/socket/verilog/axi_stream_io_v1_0.v
@@ -0,0 +1,114 @@
+
+`timescale 1 ns / 1 ps
+
+	module axi_stream_io_v1_0 #
+	(
+		// Users to add parameters here
+
+		// User parameters ends
+		// Do not modify the parameters beyond this line
+
+
+		// Parameters of Axi Slave Bus Interface axi
+		parameter integer C_axi_DATA_WIDTH	= 32,
+		parameter integer C_axi_ADDR_WIDTH	= 4,
+
+		// Parameters of Axi Master Bus Interface tx
+		parameter integer C_tx_TDATA_WIDTH	= 8,
+		parameter integer C_tx_START_COUNT	= 3,
+
+		// Parameters of Axi Slave Bus Interface rx
+		parameter integer C_rx_TDATA_WIDTH	= 8
+	)
+	(
+		// Users to add ports here
+
+		// User ports ends
+		// Do not modify the ports beyond this line
+
+
+		// Ports of Axi Slave Bus Interface axi
+		input wire  axi_aclk,
+		input wire  axi_aresetn,
+		input wire [C_axi_ADDR_WIDTH-1 : 0] axi_awaddr,
+		input wire [2 : 0] axi_awprot,
+		input wire  axi_awvalid,
+		output wire  axi_awready,
+		input wire [C_axi_DATA_WIDTH-1 : 0] axi_wdata,
+		input wire [(C_axi_DATA_WIDTH/8)-1 : 0] axi_wstrb,
+		input wire  axi_wvalid,
+		output wire  axi_wready,
+		output wire [1 : 0] axi_bresp,
+		output wire  axi_bvalid,
+		input wire  axi_bready,
+		input wire [C_axi_ADDR_WIDTH-1 : 0] axi_araddr,
+		input wire [2 : 0] axi_arprot,
+		input wire  axi_arvalid,
+		output wire  axi_arready,
+		output wire [C_axi_DATA_WIDTH-1 : 0] axi_rdata,
+		output wire [1 : 0] axi_rresp,
+		output wire  axi_rvalid,
+		input wire  axi_rready,
+
+        output wire interrupt,
+		// Ports of Axi Master Bus Interface tx
+		output wire  tx_tvalid,
+		output wire [C_tx_TDATA_WIDTH-1 : 0] tx_tdata,
+		output wire [(C_tx_TDATA_WIDTH/8)-1 : 0] tx_tstrb,
+		output wire  tx_tlast,
+		input wire  tx_tready,
+
+		// Ports of Axi Slave Bus Interface rx
+		output wire  rx_tready,
+		input wire [C_rx_TDATA_WIDTH-1 : 0] rx_tdata,
+		input wire [(C_rx_TDATA_WIDTH/8)-1 : 0] rx_tstrb,
+		input wire  rx_tlast,
+		input wire  rx_tvalid
+	);
+// Instantiation of Axi Bus Interface axi
+	iostream_v1_0_axi # ( 
+		.C_S_AXI_DATA_WIDTH(C_axi_DATA_WIDTH),
+		.C_S_AXI_ADDR_WIDTH(C_axi_ADDR_WIDTH)
+	) iostream_v1_0_axi_inst (
+		.S_AXI_ACLK(axi_aclk),
+		.S_AXI_ARESETN(axi_aresetn),
+		.tx_tvalid(tx_tvalid),
+		.tx_tdata(tx_tdata),
+//		output wire [0 : 0] tx_tstrb,
+//		output wire  tx_tlast,
+		.tx_tready(tx_tready),
+		.rx_tvalid(rx_tvalid),
+		.rx_tdata(rx_tdata),
+//		input wire [0 : 0] tx_tstrb,
+//		input wire  tx_tlast,
+		.tx_tready(rx_tready),
+		.interrupt(interrupt),
+		.S_AXI_AWADDR(axi_awaddr),
+		.S_AXI_AWPROT(axi_awprot),
+		.S_AXI_AWVALID(axi_awvalid),
+		.S_AXI_AWREADY(axi_awready),
+		.S_AXI_WDATA(axi_wdata),
+		.S_AXI_WSTRB(axi_wstrb),
+		.S_AXI_WVALID(axi_wvalid),
+		.S_AXI_WREADY(axi_wready),
+		.S_AXI_BRESP(axi_bresp),
+		.S_AXI_BVALID(axi_bvalid),
+		.S_AXI_BREADY(axi_bready),
+		.S_AXI_ARADDR(axi_araddr),
+		.S_AXI_ARPROT(axi_arprot),
+		.S_AXI_ARVALID(axi_arvalid),
+		.S_AXI_ARREADY(axi_arready),
+		.S_AXI_RDATA(axi_rdata),
+		.S_AXI_RRESP(axi_rresp),
+		.S_AXI_RVALID(axi_rvalid),
+		.S_AXI_RREADY(axi_rready)
+	);
+
+assign tx_tstrb[0:0] = tx_tvalid;
+assign tx_tlast      = 1'b0;
+
+	// Add user logic here
+
+	// User logic ends
+
+	endmodule
diff --git a/socket/verilog/axi_stream_io_v1_0_axi_s.v b/socket/verilog/axi_stream_io_v1_0_axi_s.v
new file mode 100755
index 0000000000000000000000000000000000000000..303780efefce184c1f353751c71280794b5348bd
--- /dev/null
+++ b/socket/verilog/axi_stream_io_v1_0_axi_s.v
@@ -0,0 +1,424 @@
+
+`timescale 1 ns / 1 ps
+
+	module axi_stream_io_v1_0_axi_s #
+	(
+		// Users to add parameters here
+
+		// User parameters ends
+		// Do not modify the parameters beyond this line
+
+		// Width of S_AXI data bus
+		parameter integer C_S_AXI_DATA_WIDTH	= 32,
+		// Width of S_AXI address bus
+		parameter integer C_S_AXI_ADDR_WIDTH	= 4
+	)
+	(
+		// Users to add ports here
+		output wire interrupt,
+		
+		// Ports of Axi Master Bus Interface tx
+//		input wire  tx_aclk,
+//		input wire  tx_aresetn,
+		output wire  tx_tvalid,
+		output wire [7 : 0] tx_tdata,
+//		output wire [0 : 0] tx_tstrb,
+//		output wire  tx_tlast,
+		input wire  tx_tready,
+
+		// Ports of Axi Slave Bus Interface rx
+//		input wire  rx_aclk,
+//		input wire  rx_aresetn,
+		output wire  rx_tready,
+		input wire [7 : 0] rx_tdata,
+//		input wire [0 : 0] rx_tstrb,
+//		input wire  rx_tlast,
+		input wire  rx_tvalid,
+
+		// User ports ends
+		// Do not modify the ports beyond this line
+
+		// Global Clock Signal
+		input wire  S_AXI_ACLK,
+		// Global Reset Signal. This Signal is Active LOW
+		input wire  S_AXI_ARESETN,
+		// Write address (issued by master, acceped by Slave)
+		input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
+		// Write channel Protection type. This signal indicates the
+    		// privilege and security level of the transaction, and whether
+    		// the transaction is a data access or an instruction access.
+		input wire [2 : 0] S_AXI_AWPROT,
+		// Write address valid. This signal indicates that the master signaling
+    		// valid write address and control information.
+		input wire  S_AXI_AWVALID,
+		// Write address ready. This signal indicates that the slave is ready
+    		// to accept an address and associated control signals.
+		output wire  S_AXI_AWREADY,
+		// Write data (issued by master, acceped by Slave) 
+		input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
+		// Write strobes. This signal indicates which byte lanes hold
+    		// valid data. There is one write strobe bit for each eight
+    		// bits of the write data bus.    
+		input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
+		// Write valid. This signal indicates that valid write
+    		// data and strobes are available.
+		input wire  S_AXI_WVALID,
+		// Write ready. This signal indicates that the slave
+    		// can accept the write data.
+		output wire  S_AXI_WREADY,
+		// Write response. This signal indicates the status
+    		// of the write transaction.
+		output wire [1 : 0] S_AXI_BRESP,
+		// Write response valid. This signal indicates that the channel
+    		// is signaling a valid write response.
+		output wire  S_AXI_BVALID,
+		// Response ready. This signal indicates that the master
+    		// can accept a write response.
+		input wire  S_AXI_BREADY,
+		// Read address (issued by master, acceped by Slave)
+		input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
+		// Protection type. This signal indicates the privilege
+    		// and security level of the transaction, and whether the
+    		// transaction is a data access or an instruction access.
+		input wire [2 : 0] S_AXI_ARPROT,
+		// Read address valid. This signal indicates that the channel
+    		// is signaling valid read address and control information.
+		input wire  S_AXI_ARVALID,
+		// Read address ready. This signal indicates that the slave is
+    		// ready to accept an address and associated control signals.
+		output wire  S_AXI_ARREADY,
+		// Read data (issued by slave)
+		output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
+		// Read response. This signal indicates the status of the
+    		// read transfer.
+		output wire [1 : 0] S_AXI_RRESP,
+		// Read valid. This signal indicates that the channel is
+    		// signaling the required read data.
+		output wire  S_AXI_RVALID,
+		// Read ready. This signal indicates that the master can
+    		// accept the read data and response information.
+		input wire  S_AXI_RREADY
+	);
+
+	// AXI4LITE signals
+	reg [C_S_AXI_ADDR_WIDTH-1 : 0] 	axi_awaddr;
+	reg  	axi_awready;
+	reg  	axi_wready;
+	reg [1 : 0] 	axi_bresp;
+	reg  	axi_bvalid;
+	reg [C_S_AXI_ADDR_WIDTH-1 : 0] 	axi_araddr;
+	reg  	axi_arready;
+	reg [C_S_AXI_DATA_WIDTH-1 : 0] 	axi_rdata;
+	reg [1 : 0] 	axi_rresp;
+	reg  	axi_rvalid;
+
+	// Example-specific design signals
+	// local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
+	// ADDR_LSB is used for addressing 32/64 bit registers/memories
+	// ADDR_LSB = 2 for 32 bits (n downto 2)
+	// ADDR_LSB = 3 for 64 bits (n downto 3)
+	localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
+	localparam integer OPT_MEM_ADDR_BITS = 1;
+
+	//----------------------------------------------
+	//-- Signals for user logic register space example
+	//------------------------------------------------
+	//-- Number of Slave Registers 4
+	reg [8:0]	tx_reg; // TX data
+	reg [8:0]	rx_reg; // RX data
+	reg [7:0]	ctrl_reg; // ctrl
+	wire	 slv_reg_rden;
+	wire	 slv_reg_wren;
+	reg [7:0]	 reg_data_out;
+	integer	 byte_index;
+	reg	 aw_en;
+	
+	wire	tx_req = tx_reg[8];  // request to transmit
+	wire	tx_ack = tx_tready;    // acknowledge when stream ready
+    wire	tx_rdy = !tx_reg[8];
+	wire	rx_req = rx_tvalid;    // request to receive
+	wire	rx_ack = !rx_reg[8];
+    wire    rx_rdy = rx_reg[8];
+    
+	//assign	rx_reg[7:0] <= rx_tdata;
+
+	// I/O Connections assignments
+
+    assign interrupt = ctrl_reg[4] & (!tx_req | rx_req);
+	
+    // TX stream interface
+	assign	tx_tdata = tx_reg[7:0];
+	assign  tx_tvalid = tx_req;
+
+	// RX stream interface
+	assign  rx_tready = rx_ack;
+    
+	//AXI Slave
+	assign S_AXI_AWREADY	= axi_awready;
+	assign S_AXI_WREADY	= axi_wready;
+	assign S_AXI_BRESP	= axi_bresp;
+	assign S_AXI_BVALID	= axi_bvalid;
+	assign S_AXI_ARREADY	= axi_arready;
+	assign S_AXI_RDATA	= axi_rdata;
+	assign S_AXI_RRESP	= axi_rresp;
+	assign S_AXI_RVALID	= axi_rvalid;
+	// Implement axi_awready generation
+	// axi_awready is asserted for one S_AXI_ACLK clock cycle when both
+	// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
+	// de-asserted when reset is low.
+
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+	    begin
+	      axi_awready <= 1'b0;
+	      aw_en <= 1'b1;
+	    end 
+	  else
+	    begin    
+	      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
+	        begin
+	          // slave is ready to accept write address when 
+	          // there is a valid write address and write data
+	          // on the write address and data bus. This design 
+	          // expects no outstanding transactions. 
+	          axi_awready <= 1'b1;
+	          aw_en <= 1'b0;
+	        end
+	        else if (S_AXI_BREADY && axi_bvalid)
+	            begin
+	              aw_en <= 1'b1;
+	              axi_awready <= 1'b0;
+	            end
+	      else           
+	        begin
+	          axi_awready <= 1'b0;
+	        end
+	    end 
+	end       
+
+	// Implement axi_awaddr latching
+	// This process is used to latch the address when both 
+	// S_AXI_AWVALID and S_AXI_WVALID are valid. 
+
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+	    begin
+	      axi_awaddr <= 0;
+	    end 
+	  else
+	    begin    
+	      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
+	        begin
+	          // Write Address latching 
+	          axi_awaddr <= S_AXI_AWADDR;
+	        end
+	    end 
+	end       
+
+	// Implement axi_wready generation
+	// axi_wready is asserted for one S_AXI_ACLK clock cycle when both
+	// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is 
+	// de-asserted when reset is low. 
+
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+	    begin
+	      axi_wready <= 1'b0;
+	    end 
+	  else
+	    begin    
+	      if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
+	        begin
+	          // slave is ready to accept write data when 
+	          // there is a valid write address and write data
+	          // on the write address and data bus. This design 
+	          // expects no outstanding transactions. 
+	          axi_wready <= 1'b1;
+	        end
+	      else
+	        begin
+	          axi_wready <= 1'b0;
+	        end
+	    end 
+	end       
+
+	// Implement memory mapped register select and write logic generation
+	// The write data is accepted and written to memory mapped registers when
+	// axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
+	// select byte enables of slave registers while writing.
+	// These registers are cleared when reset (active low) is applied.
+	// Slave register write enable is asserted when valid address and data are available
+	// and the slave is ready to accept the write address and write data.
+	assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
+
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+		rx_reg <= 0;
+      else if ((ctrl_reg[1] == 1'b1))
+        rx_reg <= 0;
+	  else if (slv_reg_wren && (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == 2'h0))
+		rx_reg[8:0] <= {1'b1, S_AXI_WDATA[7:0]};
+	  else if (slv_reg_rden && (axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == 2'h0))
+		rx_reg[8] <= 1'b0;
+      else if (rx_req & rx_ack) // check precedence (rx_req)
+		rx_reg[8:0] <= {1'b1, rx_tdata[7:0]};
+	end    
+
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+		tx_reg <= 0;
+      else if ((ctrl_reg[0] == 1'b1))
+        tx_reg <= 0;
+	  else if (slv_reg_wren && (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == 2'h1))
+		tx_reg[8:0] <= {1'b1, S_AXI_WDATA[7:0]};
+      else if (tx_req & tx_ack)
+		tx_reg[8] <= 1'b0;
+	end    
+
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+		ctrl_reg <= 8'b00000100;
+	  else if (slv_reg_wren && (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == 2'h3))
+		ctrl_reg[7:0] <= S_AXI_WDATA[7:0];
+	end    
+
+	// Implement write response logic generation
+	// The write response and response valid signals are asserted by the slave 
+	// when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.  
+	// This marks the acceptance of address and indicates the status of 
+	// write transaction.
+
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+	    begin
+	      axi_bvalid  <= 0;
+	      axi_bresp   <= 2'b0;
+	    end 
+	  else
+	    begin    
+	      if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
+	        begin
+	          // indicates a valid write response is available
+	          axi_bvalid <= 1'b1;
+	          axi_bresp  <= 2'b0; // 'OKAY' response 
+	        end                   // work error responses in future
+	      else
+	        begin
+	          if (S_AXI_BREADY && axi_bvalid) 
+	            //check if bready is asserted while bvalid is high) 
+	            //(there is a possibility that bready is always asserted high)   
+	            begin
+	              axi_bvalid <= 1'b0; 
+	            end  
+	        end
+	    end
+	end   
+
+	// Implement axi_arready generation
+	// axi_arready is asserted for one S_AXI_ACLK clock cycle when
+	// S_AXI_ARVALID is asserted. axi_awready is 
+	// de-asserted when reset (active low) is asserted. 
+	// The read address is also latched when S_AXI_ARVALID is 
+	// asserted. axi_araddr is reset to zero on reset assertion.
+
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+	    begin
+	      axi_arready <= 1'b0;
+	      axi_araddr  <= 32'b0;
+	    end 
+	  else
+	    begin    
+	      if (~axi_arready && S_AXI_ARVALID)
+	        begin
+	          // indicates that the slave has acceped the valid read address
+	          axi_arready <= 1'b1;
+	          // Read address latching
+	          axi_araddr  <= S_AXI_ARADDR;
+	        end
+	      else
+	        begin
+	          axi_arready <= 1'b0;
+	        end
+	    end 
+	end       
+
+	// Implement axi_arvalid generation
+	// axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both 
+	// S_AXI_ARVALID and axi_arready are asserted. The slave registers 
+	// data are available on the axi_rdata bus at this instance. The 
+	// assertion of axi_rvalid marks the validity of read data on the 
+	// bus and axi_rresp indicates the status of read transaction.axi_rvalid 
+	// is deasserted on reset (active low). axi_rresp and axi_rdata are 
+	// cleared to zero on reset (active low).  
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+	    begin
+	      axi_rvalid <= 0;
+	      axi_rresp  <= 0;
+	    end
+	  else
+	    begin    
+	      if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
+	        begin
+	          // Valid read data is available at the read data bus
+	          axi_rvalid <= 1'b1;
+	          axi_rresp  <= 2'b0; // 'OKAY' response
+	        end   
+	      else if (axi_rvalid && S_AXI_RREADY)
+	        begin
+	          // Read data is accepted by the master
+	          axi_rvalid <= 1'b0;
+	        end                
+	    end
+	end    
+
+	// Implement memory mapped register select and read logic generation
+	// Slave register read enable is asserted when valid address is available
+	// and the slave is ready to accept the read address.
+	assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
+	always @(*)
+	begin
+	      // Address decoding for reading registers
+	      case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
+	        2'h0   : reg_data_out <= rx_reg[7:0];
+	        2'h1   : reg_data_out <= tx_reg[7:0];
+	        2'h2   : reg_data_out <= {3'b000, ctrl_reg[4], !tx_rdy, tx_rdy, rx_rdy, rx_rdy};
+	        2'h3   : reg_data_out <= ctrl_reg;
+	        default : reg_data_out <= 0;
+	      endcase
+	end
+
+	// Output register or memory read data
+	always @( posedge S_AXI_ACLK )
+	begin
+	  if ( S_AXI_ARESETN == 1'b0 )
+	    begin
+	      axi_rdata  <= 0;
+	    end 
+	  else
+	    begin    
+	      // When there is a valid read address (S_AXI_ARVALID) with 
+	      // acceptance of read address by the slave (axi_arready), 
+	      // output the read dada 
+	      if (slv_reg_rden)
+	        begin
+	          axi_rdata <= {24'h000000, reg_data_out};     // register read data
+	        end   
+	    end
+	end    
+
+	// Add user logic here
+
+	// User logic ends
+
+	endmodule
diff --git a/socket/verilog/ft232h_ft1248_x1.v b/socket/verilog/ft232h_ft1248_x1.v
new file mode 100644
index 0000000000000000000000000000000000000000..e125ea3a0ca03bce2fccdd816606fb5c2017438c
--- /dev/null
+++ b/socket/verilog/ft232h_ft1248_x1.v
@@ -0,0 +1,157 @@
+//-----------------------------------------------------------------------------
+// NanoSoC FT1248 ADP UART file logging
+// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
+//
+// Contributors
+//
+// David Flynn (d.w.flynn@soton.ac.uk)
+//
+// Copyright � 2022, SoC Labs (www.soclabs.org)
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Abstract : FT1248 1-bit data off-chip interface (emulate FT232H device)
+// and allows cmsdk_uart_capture testbench models to log ADP ip, op streams
+//-----------------------------------------------------------------------------
+
+
+module ft232h_ft1248_x1 #(
+  parameter ADPFILENAME = "adp.cmd",
+  parameter VERBOSE = 0
+)(
+  input  wire  ft_clk_i,         // SCLK
+  input  wire  ft_ssn_i,         // SS_N
+  output wire  ft_miso_o,        // MISO
+  inout  wire  ft_miosio_io,     // MIOSIO tristate output when enabled
+
+  output wire  FTDI_CLK2UART_o,  // Clock (baud rate)
+  output wire  FTDI_OP2UART_o,   // Received data to UART capture
+  output wire  FTDI_IP2UART_o    // Transmitted data to UART capture
+);
+
+
+ //----------------------------------------------
+ //-- File I/O
+ //----------------------------------------------
+
+
+   integer        fdcmd;       // channel descriptor for cmd file input
+   integer        ch;
+`define EOF -1
+
+   reg       ft_rxreq;
+   wire      ft_rxack;
+   reg [7:0] ft_adpbyte;
+   
+   initial
+     begin
+       ft_rxreq <= 0;
+       $timeformat(-9, 0, " ns", 14);
+       fdcmd= $fopen(ADPFILENAME,"r");
+       if (fdcmd == 0)
+          $write("** FT1248x1 : no command file **\n");
+       else begin
+         ch =  $fgetc(fdcmd);
+         while (ch != `EOF) begin
+           ft_adpbyte <= (ch & 8'hff);
+           ft_rxreq <= 1'b1;
+           while (ft_ssn_i == 1'b0)
+             @(posedge ft_ssn_i);
+           @(posedge ft_rxack);
+           ft_rxreq <=0;
+           @(negedge ft_rxack);
+           ch =  $fgetc(fdcmd);
+         end
+       end
+       $fclose(fdcmd);
+       ft_rxreq <= 0;
+     end
+     
+
+//----------------------------------------------
+//-- State Machine
+//----------------------------------------------
+
+wire ft_miosio_i;
+wire ft_miosio_o;
+wire ft_miosio_z;
+
+// tri-state pad control for MIOSIO
+assign ft_miosio_io = (ft_miosio_z) ? 1'bz : ft_miosio_o;
+// add notinal delay on inout to ensure last "half-bit" on FT1248TXD is sampled before tri-stated
+assign #1 ft_miosio_i  = ft_miosio_io;
+
+reg [4:0] ft_state; // 17-state for bit-serial
+wire [5:0] ft_nextstate = ft_state + 5'b00001;
+
+always @(posedge ft_clk_i or posedge ft_ssn_i)
+  if (ft_ssn_i)
+    ft_state <= 5'b11111;
+  else // loop if multi-data
+//    ft_state <= (ft_state == 5'b01111) ? 5'b01000 : ft_nextstate;
+    ft_state <= ft_nextstate;
+
+// 16: bus turnaround (or bit[5])
+// 0 for CMD3
+// 3 for CMD2
+// 5 for CMD1
+// 6 for CMD0
+// 7 for cmd turnaround
+// 8 for data bit0
+// 9 for data bit1
+// 10 for data bit2
+// 11 for data bit3
+// 12 for data bit4
+// 13 for data bit5
+// 14 for data bit6
+// 15 for data bit7
+
+// ft_miso_o reflects RXE when deselected
+assign ft_miso_o = (ft_ssn_i) ? !ft_rxreq : (ft_state == 5'b00111);
+
+// capture CMD on falling edge of clock (mid-data)
+// - valid sample ready after 7th edge (ready RX or TX data phase functionality)
+reg [7:0] ft_cmd;
+always @(negedge ft_clk_i or posedge ft_ssn_i)
+  if (ft_ssn_i)
+    ft_cmd <= 8'b00000001;
+  else // shift in data
+    ft_cmd <= (!ft_state[3] & !ft_nextstate[3]) ? {ft_cmd[6:0],ft_miosio_i} : ft_cmd;
+
+wire ft_cmd_valid = ft_cmd[7];
+wire ft_cmd_rxd =  ft_cmd[7] & !ft_cmd[6] & !ft_cmd[3] & !ft_cmd[1] &  ft_cmd[0];
+wire ft_cmd_txd =  ft_cmd[7] & !ft_cmd[6] & !ft_cmd[3] & !ft_cmd[1] & !ft_cmd[0];
+
+// tristate enable for miosio (deselected status or serialized data for read command)
+wire ft_miosio_e = ft_ssn_i | (ft_cmd_rxd & !ft_state[4] & ft_state[3]);
+assign ft_miosio_z = !ft_miosio_e;
+
+// serial data formatted with start bit for UART capture (on rising uart-clock)
+assign   FTDI_CLK2UART_o = !ft_clk_i;
+// suitable for CMSDK UART capture IO
+// inject a start bit low else mark high
+assign FTDI_OP2UART_o = (ft_cmd_txd & (ft_state[4:3]) == 2'b01) ? ft_miosio_i : !(ft_cmd_txd & (ft_state == 5'b00111)); 
+assign FTDI_IP2UART_o = (ft_cmd_rxd & (ft_state[4:3]) == 2'b01) ? ft_miosio_io : !(ft_cmd_rxd & (ft_state == 5'b00111));
+
+// capture RXD on falling edge of clock
+reg [8:0] ft_rxd;
+always @(negedge ft_clk_i or posedge ft_ssn_i)
+  if (ft_ssn_i)
+    ft_rxd <= 9'b111111111;
+  else if (ft_cmd_txd & !(ft_miosio_i & (&ft_rxd[8:0])))  //only on valid start-bit
+    ft_rxd <= {ft_miosio_i, ft_rxd[8:1]};
+
+// shift TXD on rising edge of clock
+reg [8:0] ft_txd;
+always @(posedge ft_clk_i or posedge ft_ssn_i)
+  if (ft_ssn_i)
+    ft_txd <= {1'b1,ft_adpbyte};
+  else if (ft_rxreq & ft_cmd_rxd & (ft_state[4:3] == 2'b01))  //valid TX shift
+    ft_txd <= {1'b0,ft_txd[8:1]};
+
+assign ft_rxack = (ft_cmd_rxd & (ft_state==5'b01111));
+  
+// ft_miso_o reflects TXF when deselected (never full for simulation output)
+assign ft_miosio_o =  (ft_ssn_i) ? 1'b0 : ft_txd[0];
+
+endmodule