Updated tests and added intret test
diff --git a/openlane/user_project_wrapper/interactive.tcl b/openlane/user_project_wrapper/interactive.tcl
index 2c0afcb..3bcc382 100644
--- a/openlane/user_project_wrapper/interactive.tcl
+++ b/openlane/user_project_wrapper/interactive.tcl
@@ -15,12 +15,11 @@
 apply_def_template
 
 #add_macro_placement core0 1550  400 N
-add_macro_placement core1  300 1600 N
+add_macro_placement core1  300 1500 N
 add_macro_placement sram0  300 2800 N
 add_macro_placement sram1  950 2800 N
 add_macro_placement sram2 1550 2800 N
-add_macro_placement sram3 1700 1600 S
-#add_macro_placement sram3 2200 2800 N
+add_macro_placement sram3 2200 2800 N
 
 #add_macro_placement sram4 1700 1600 S;  # RX buffer for core1
 #add_macro_placement sram5 2250 1600 N;  # RX buffer for core0
diff --git a/verilog/dv/caravel/hs32_soc/Makefile b/verilog/dv/caravel/hs32_soc/Makefile
index 58ab91f..3a59f5e 100644
--- a/verilog/dv/caravel/hs32_soc/Makefile
+++ b/verilog/dv/caravel/hs32_soc/Makefile
@@ -19,7 +19,7 @@
 .SUFFIXES:
 .SILENT: clean all
 
-PATTERNS = core1test1 core1test2 core1test3 core1test4 core1test5 core1test6 core1test7 core1test8
+PATTERNS = test1 test2 test3 test4 test5 test6 test7 test8
 
 all:  ${PATTERNS}
 	for i in ${PATTERNS}; do \
diff --git a/verilog/dv/caravel/hs32_soc/test1/tb.gtkw b/verilog/dv/caravel/hs32_soc/test1/tb.gtkw
index cd40e11..c171b37 100644
--- a/verilog/dv/caravel/hs32_soc/test1/tb.gtkw
+++ b/verilog/dv/caravel/hs32_soc/test1/tb.gtkw
@@ -1,15 +1,15 @@
 [*]
 [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI
-[*] Thu Dec 17 01:48:51 2020
+[*] Tue Dec 22 22:53:36 2020
 [*]
-[dumpfile] "/data/caravel-hs32core/verilog/dv/caravel/hs32_soc/core1test2/dump.vcd"
-[dumpfile_mtime] "Thu Dec 17 00:46:37 2020"
-[dumpfile_size] 322055879
-[savefile] "/data/caravel-hs32core/verilog/dv/caravel/hs32_soc/core1test2/tb.gtkw"
-[timestart] 131606720
-[size] 1536 801
-[pos] -9 -33
-*-14.106964 131652000 131484000 131676000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[dumpfile] "/data/caravel-hs32core/verilog/dv/caravel/hs32_soc/test1/dump.fst"
+[dumpfile_mtime] "Tue Dec 22 22:50:44 2020"
+[dumpfile_size] 2251130
+[savefile] "/data/caravel-hs32core/verilog/dv/caravel/hs32_soc/test1/tb.gtkw"
+[timestart] 128968000
+[size] 1534 773
+[pos] -1 -1
+*-19.106964 130836000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
 [treeopen] tb.
 [treeopen] tb.uut.
 [treeopen] tb.uut.mprj.
@@ -18,7 +18,7 @@
 [treeopen] tb.uut.mprj.core1.core.EXEC.
 [treeopen] tb.uut.mprj.sram0.
 [sst_width] 265
-[signals_width] 269
+[signals_width] 279
 [sst_expanded] 1
 [sst_vpaned_height] 222
 @c00200
@@ -42,7 +42,6 @@
 -WBS
 @28
 tb.uut.mprj.core1.ram_ce
-tb.uut.mprj.core1.bsy
 tb.uut.mprj.sram0.csb0
 tb.uut.mprj.sram0.csb0_reg
 @22
@@ -61,7 +60,7 @@
 tb.uut.mprj.core1.core.FETCH.\fifo[7][31:0]
 @1401200
 -PQ
-@800200
+@c00200
 -BRAM CTL
 @22
 tb.uut.mprj.core1.bram_ctl.i_addr[11:0]
@@ -99,7 +98,7 @@
 tb.uut.mprj.core1.bram_ctl.dbuf1[31:0]
 tb.uut.mprj.core1.bram_ctl.dbuf2[31:0]
 tb.uut.mprj.core1.bram_ctl.dbuf3[31:0]
-@1000200
+@1401200
 -BRAM CTL
 @c00200
 -Decode
@@ -120,7 +119,6 @@
 tb.uut.mprj.core1.core.DECODE.reqe
 [color] 3
 tb.uut.mprj.core1.core.DECODE.rdye
-tb.uut.mprj.core1.core.DECODE.full
 @200
 -
 @22
@@ -153,6 +151,7 @@
 @28
 tb.uut.mprj.core1.core.EXEC.fault
 tb.uut.mprj.core1.core.EXEC.int_inval
+tb.uut.mprj.core1.core.EXEC.intrq
 @c00200
 -Module I/O
 @28
@@ -187,10 +186,6 @@
 @28
 [color] 3
 tb.uut.mprj.core1.core.EXEC.rw_mem
-@200
--
-@28
-tb.uut.mprj.core1.core.EXEC.intrq
 @1401200
 -Module I/O
 @c00200
@@ -330,7 +325,7 @@
 tb.uut.mprj.sram1.wmask0[3:0]
 @1401200
 -sram1
-@800200
+@c00200
 -sram3
 @22
 tb.uut.mprj.sram2.addr0[7:0]
@@ -343,7 +338,12 @@
 @28
 tb.uut.mprj.sram2.web0
 tb.uut.mprj.sram2.wmask0[3:0]
-@1000200
+@1401200
 -sram3
+@22
+tb.uut.mprj.core1.core.interrupts[23:0]
+@28
+tb.uut.mprj.core1.core.intrq
+tb.uut.mprj.core1.hw_irq[23:0]
 [pattern_trace] 1
 [pattern_trace] 0
diff --git a/verilog/dv/caravel/hs32_soc/test1/test1_tb.v b/verilog/dv/caravel/hs32_soc/test1/test1_tb.v
index 6e12574..ffd6b11 100644
--- a/verilog/dv/caravel/hs32_soc/test1/test1_tb.v
+++ b/verilog/dv/caravel/hs32_soc/test1/test1_tb.v
@@ -4,7 +4,6 @@
 `endif
 
 `default_nettype none
-
 `timescale 1 ns / 1 ns
 
 `include "caravel.v"
diff --git a/verilog/dv/caravel/hs32_soc/test7/Makefile b/verilog/dv/caravel/hs32_soc/test7/Makefile
index 49aa8c1..6b4c87c 100644
--- a/verilog/dv/caravel/hs32_soc/test7/Makefile
+++ b/verilog/dv/caravel/hs32_soc/test7/Makefile
@@ -1,7 +1,7 @@
-FIRMWARE_PATH = ../..
+FIRMWARE_PATH = ../../
 RTL_PATH = ../../../../rtl
-IP_PATH = ../../../../ip
 BEHAVIOURAL_MODELS = ../../ 
+VERILOG_PATH = ../../../../
 
 GCC_PATH?=/opt/riscv32i/bin
 GCC_PREFIX?=riscv32-unknown-elf
@@ -9,6 +9,8 @@
 
 .SUFFIXES:
 
+SIM?=RTL
+
 PATTERN = test7
 
 all:  ${PATTERN:=.vcd}
@@ -16,12 +18,18 @@
 hex:  ${PATTERN:=.hex}
 
 %.vvp: %_tb.v %.hex
+ifeq ($(SIM),RTL)
 	iverilog -DSIM -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
-	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) -I $(RTL_PATH)/hs32cpu \
-	-o $@ $<
+	-I $(PDK_PATH) -I $(RTL_PATH) \
+	-I $(RTL_PATH)/hs32cpu $< -o $@
+else
+	iverilog -DSIM -DFUNCTIONAL -DGL_SIM -I $(BEHAVIOURAL_MODELS) \
+	-I $(PDK_PATH) -I $(RTL_PATH) \
+	-I $(RTL_PATH)/hs32cpu -I $(VERILOG_PATH) $< -o $@
+endif
 
 %.vcd: %.vvp
-	vvp $<
+	vvp $< -fst-speed $(OPT)
 
 %.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
 	${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
@@ -37,6 +45,6 @@
 # ---- Clean ----
 
 clean:
-	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log *.idx
+	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log *.idx *.fst
 
 .PHONY: clean hex all
diff --git a/verilog/dv/caravel/hs32_soc/test7/test7_tb.v b/verilog/dv/caravel/hs32_soc/test7/test7_tb.v
index 7952d1a..665977f 100644
--- a/verilog/dv/caravel/hs32_soc/test7/test7_tb.v
+++ b/verilog/dv/caravel/hs32_soc/test7/test7_tb.v
@@ -1,23 +1,27 @@
-`define DBG1
+`ifdef GL_SIM
+	`define SRAM_LOG_READ
+	`define SRAM_LOG_WRITE
+`endif
+
 `define LOG_MEMORY_WRITE
 
 `default_nettype none
-
 `timescale 1 ns / 1 ns
 
 `include "caravel.v"
 `include "spiflash.v"
 
 module tb();
-	parameter TEST_ID = 5;
+	parameter TEST_ID = 7;
+	parameter FILENAME = "test7.hex";
 
 	reg clock;
-  reg RSTB;
+  	reg RSTB;
 	reg power1, power2;
 	reg power3, power4;
 
-  wire gpio;
-  wire [37:0] mprj_io;
+  	wire gpio;
+  	wire [37:0] mprj_io;
 	wire [7:0] mprj_io_0;
 
 	assign mprj_io_0 = mprj_io[7:0];
@@ -32,6 +36,8 @@
 		clock = 0;
 	end
 
+	reg failed = 1;
+
 	initial begin
 		$dumpfile("tb.vcd");
 		$dumpvars(0, tb);
@@ -40,16 +46,25 @@
 			repeat (1000) @(posedge clock);
 			// $display("+1000 cycles");
 		end
-		//$display("%c[1;31m",27);
-		//$display("Test 1: Failed (timed out)!");
-		//$display("%c[0m",27);
+`ifndef GL_SIM
+		if(failed) begin
+			$display("%c[1;31m",27);
+			$display("Test %d: Failed (timed out)!", TEST_ID);
+			$display("%c[0m",27);
+		end else begin
+			$display("%c[1;32m",27);
+			$display("Test %d: Passed weak cases.", TEST_ID);
+			$display("%c[0m",27);
+		end
+`endif
 		$finish;
 	end
 
 	initial begin
 		RSTB <= 1'b0;
-		#2000;
+		#1000;
 		RSTB <= 1'b1;	    // Release reset
+		#2000;
 	end
 
 	initial begin			// Power-up sequence
@@ -67,10 +82,24 @@
 		power4 <= 1'b1;
 	end
 
+`ifndef GL_SIM
 	initial begin
-	    // Test cases go here
-	end
+	    // MOV r0 <- 0xFF00
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[0] == 32'hFF00);
+		// LDR r1 <- [r0]
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[1] == 32'hFF00);
+		// MOV r2 <- 0x0BA0
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[2] == 32'h0BA0);
+		// MOV r3 <- 0x5000
+		wait(tb.uut.mprj.core1.core.EXEC.regfile_s.regs[3] == 32'h5000);
+		// etc...
 
+		// INT 3
+		wait(tb.uut.mprj.core1.core.EXEC.intrq &&
+			tb.uut.mprj.core1.core.EXEC.code == 3 &&
+			tb.uut.mprj.core1.core.EXEC.isr == 32'h0BA0);
+		failed = 0;
+	end
 	always @(*) begin
 		if(tb.uut.mprj.core1.core.EXEC.fault) begin
 			$display("%c[1;31m",27);
@@ -79,6 +108,7 @@
 			$finish;
 		end
 	end
+`endif
 
 	always @(mprj_io) begin
 		#1 $display("MPRJ-IO state = %b ", mprj_io[7:0]);
@@ -91,8 +121,8 @@
 
 	wire VDD3V3 = power1;
 	wire VDD1V8 = power2;
-	wire USER_VDD3V3 = power3;
-	wire USER_VDD1V8 = power4;
+	wire USER_VDD3V3 = power1;
+	wire USER_VDD1V8 = power2;
 	wire VSS = 1'b0;
 
 	caravel uut (
@@ -121,7 +151,7 @@
 	);
 
 	spiflash #(
-		.FILENAME("test7.hex")
+		.FILENAME(FILENAME)
 	) spiflash (
 		.csb(flash_csb),
 		.clk(flash_clk),
@@ -132,3 +162,14 @@
 	);
 endmodule
 `default_nettype wire
+
+module assert(input clk, input test);
+    always @(posedge clk)
+    begin
+        if (test !== 1)
+        begin
+            $display("ASSERTION FAILED in %m");
+            $finish;
+        end
+    end
+endmodule
diff --git a/verilog/dv/hs32_nocaravel/coretest/core_tb.v b/verilog/dv/hs32_nocaravel/coretest/core_tb.v
index 53d80e6..1932fa0 100644
--- a/verilog/dv/hs32_nocaravel/coretest/core_tb.v
+++ b/verilog/dv/hs32_nocaravel/coretest/core_tb.v
@@ -28,7 +28,7 @@
 	always #10 wb_clk_i = wb_clk_i === 1'b0;
 
 	// Memory array
-	localparam NUM_INSTR = 10;
+	localparam NUM_INSTR = 9;
 	reg[NUM_INSTR*32-1:0] instr = {
 		// Default Test
 		// { 32'h2400CAFE },
@@ -37,25 +37,16 @@
 		// { 32'h14210001 },
 		// { 32'h50000000 }
 
-		// Test 2
-		// { 32'h240003F1 },
-		// { 32'h20100080 },
-		// { 32'h202000A0 },
-		// { 32'h203000C0 },
-		// { 32'h204000E0 },
-		// { 32'h50000000 }
-
-		// Test 7
-		{ 32'h2400FF00 },
-		{ 32'h10100000 },
-		{ 32'h24200BA0 },
-		{ 32'h24305000 },
-		{ 32'h20303800 },
-		{ 32'h30320000 },
-		{ 32'h24400BA1 },
-		{ 32'h34400010 },
-		{ 32'h14500010 },
-		{ 32'h90000003 }
+		// Custom test
+		{ 32'h2400FF00 }, // MOV r0 <- 0xFF00
+		{ 32'h24100019 }, // MOV r1 <- (0x18 | 1)
+		{ 32'h34100010 }, // STR [r0+0x10] <- r1
+		{ 32'h90000003 }, // INT 3
+		{ 32'h2450CAFE }, // MOV r5 <- 0xCAFE
+		{ 32'h50000000 }, // B<0000> 0
+		{ 32'h2440C0DE }, // MOV r4 <- 0xC0DE
+		{ 32'h44EE0004 }, // ADD lr <- lr + 4
+		{ 32'h5F000000 }  // B<1111> 0 (return from interrupt)
 	};
 	
 	// Main block
diff --git a/verilog/dv/hs32_nocaravel/coretest/tb.gtkw b/verilog/dv/hs32_nocaravel/coretest/tb.gtkw
index 06e0a85..f5c9770 100644
--- a/verilog/dv/hs32_nocaravel/coretest/tb.gtkw
+++ b/verilog/dv/hs32_nocaravel/coretest/tb.gtkw
@@ -1,15 +1,15 @@
 [*]
 [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI
-[*] Tue Dec 22 01:21:25 2020
+[*] Tue Dec 22 23:21:05 2020
 [*]
-[dumpfile] "/data/caravel-hs32core/verilog/dv/hs32_nocaravel/dump.fst"
-[dumpfile_mtime] "Tue Dec 22 01:21:13 2020"
-[dumpfile_size] 14810
-[savefile] "/data/caravel-hs32core/verilog/dv/hs32_nocaravel/tb.gtkw"
-[timestart] 1270
-[size] 1536 801
+[dumpfile] "/data/caravel-hs32core/verilog/dv/hs32_nocaravel/coretest/dump.fst"
+[dumpfile_mtime] "Tue Dec 22 23:18:51 2020"
+[dumpfile_size] 13464
+[savefile] "/data/caravel-hs32core/verilog/dv/hs32_nocaravel/coretest/tb.gtkw"
+[timestart] 0
+[size] 1534 773
 [pos] -1 -1
-*-7.106964 1590 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-9.106964 1190 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
 [treeopen] tb.
 [treeopen] tb.mprj.
 [treeopen] tb.mprj.core1.
@@ -63,7 +63,7 @@
 tb.mprj.core1.ack
 @1401200
 -BUS
-@800200
+@c00200
 -Intercon
 @28
 tb.mprj.core1.mmio_conn.clk
@@ -81,21 +81,13 @@
 @200
 -
 @22
-tb.mprj.core1.mmio_conn.o_stb[4:0]
-@28
-tb.mprj.core1.mmio_conn.i_ack[4:0]
-@22
-tb.mprj.core1.mmio_conn.i_dtr[159:0]
 tb.mprj.core1.mmio_conn.o_addr[7:0]
 @200
 -
 @28
 tb.mprj.core1.mmio_conn.in_aict
-@29
 tb.mprj.core1.mmio_conn.in_base
-@28
 tb.mprj.core1.mmio_conn.none
-tb.mprj.core1.mmio_conn.sel[4:0]
 @22
 tb.mprj.core1.mmio_conn.r_dtr[31:0]
 @200
@@ -106,7 +98,7 @@
 tb.mprj.core1.mmio_conn.sdtr[31:0]
 @28
 tb.mprj.core1.mmio_conn.sstb
-@1000200
+@1401200
 -Intercon
 @c00200
 -PQ
@@ -212,7 +204,7 @@
 @28
 tb.mprj.core1.core.EXEC.fault
 tb.mprj.core1.core.EXEC.int_inval
-@c00200
+@800200
 -Module I/O
 @28
 tb.mprj.core1.core.EXEC.flush
@@ -250,7 +242,7 @@
 -
 @28
 tb.mprj.core1.core.EXEC.intrq
-@1401200
+@1000200
 -Module I/O
 @c00200
 -Internal Bus
@@ -404,5 +396,32 @@
 tb.mprj.sram2.wmask0[3:0]
 @1401200
 -sram3
+@800201
+-AICT
+@29
+tb.mprj.core1.aict.ack
+@23
+tb.mprj.core1.aict.addr[4:0]
+tb.mprj.core1.aict.aict_idx[4:0]
+@29
+tb.mprj.core1.aict.clk
+@23
+tb.mprj.core1.aict.dtr[31:0]
+tb.mprj.core1.aict.dtw[31:0]
+tb.mprj.core1.aict.handler[31:0]
+@421
+tb.mprj.core1.aict.i
+@23
+tb.mprj.core1.aict.interrupts[23:0]
+@29
+tb.mprj.core1.aict.intrq
+tb.mprj.core1.aict.nmi
+tb.mprj.core1.aict.reset
+tb.mprj.core1.aict.rw
+tb.mprj.core1.aict.stb
+@23
+tb.mprj.core1.aict.vec[4:0]
+@1000201
+-AICT
 [pattern_trace] 1
 [pattern_trace] 0
diff --git a/verilog/dv/hs32_nocaravel/mmiotest/mmio_tb.v b/verilog/dv/hs32_nocaravel/mmiotest/mmio_tb.v
index f4624ca..1d71588 100644
--- a/verilog/dv/hs32_nocaravel/mmiotest/mmio_tb.v
+++ b/verilog/dv/hs32_nocaravel/mmiotest/mmio_tb.v
@@ -73,9 +73,7 @@
 			state <= 3;
 		end
 		3: begin
-			if(wbs_stb_i) begin
-				wbs_stb_i <= 0;
-			end
+			wbs_stb_i <= 0;
 			if(wbs_ack_o) begin
 				ip <= ip+1;
 				if(ip+1 == NUM_TRANS) begin
diff --git a/verilog/rtl/hs32_user_proj/dev_exsram.v b/verilog/rtl/hs32_user_proj/dev_exsram.v
new file mode 100644
index 0000000..e388940
--- /dev/null
+++ b/verilog/rtl/hs32_user_proj/dev_exsram.v
@@ -0,0 +1,186 @@
+/**
+ * Copyright (c) 2020 The HSC Core Authors
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @file   sram.v
+ * @author Kevin Dai <kevindai02@outlook.com>
+ * @date   Created on December 09 2020, 11:48 AM
+ */
+
+module dev_exsram (
+    input clk, input reset,
+
+    // Request interface
+    output  reg  ack,
+    input   wire stb,
+    input   wire i_rw, // Write = 1
+    input   wire[31:0] i_addr,
+    input   wire[31:0] i_dtw,
+    output  reg [31:0] dtr,
+
+    // External IO, all active > HIGH <
+    input   wire[15:0] din,
+    output  reg [15:0] dout,
+    output  reg we,
+    output  reg oe,
+    output  reg oe_negedge,
+    output  reg ale0_negedge,
+    output  reg ale1_negedge,
+    output  reg bhe,
+    output  reg isout
+);
+    parameter SRAM_LATCH_LAZY = 1;
+
+    `define B0 7:0
+    `define B1 15:8
+    `define B2 23:16
+    `define B3 31:24
+
+    /*
+     * Byte aligned read and write:
+     * Mask = 0011, 1100
+     * BHLE = 11, 11
+     * Misaligned read and write:
+     * Mask = 0001, 0110, 1000
+     * BHLE = 10, 11, 01
+    */
+
+    // For byte addressing headaches
+    reg addrl, lastble, hasinit;
+    wire ble;
+    reg[3:0] mask;
+    reg[31:0] addr;
+    reg[2:0] state;
+
+    // Latched inputs
+    wire[31:0] addri, dtw;
+    wire rw;
+    reg[31:0] r_addr, r_dtw;
+    reg r_rw;
+    assign addri = state == 0 ? i_addr : r_addr;
+    assign dtw = state == 0 ? i_dtw : r_dtw;
+    assign rw = state == 0 ? i_rw : r_rw;
+
+    // Bleh
+    assign ble = !(mask[1] | !rw);
+
+    // Generate SRAM_LATCH_LAZY
+    // For waveforms and cycle names, see CPU.md
+    generate always @(posedge clk)
+    if(reset) begin
+        state   <= 0;
+        mask    <= 0;
+        addrl   <= 0;
+        addr    <= 0;
+        lastble <= 0;
+        hasinit <= 0;
+        isout <= 0;
+    end else case(state)
+        // T1
+        3'b000: begin
+            state   <= stb ?
+                // We can skip 1 cycle if the MSBs is the same
+                ({ ble, addr[31:17] } == { lastble, addri[31:17] }) && hasinit
+                ? 3'b010 : 3'b001 : 0;
+            dout    <= addri[16:1];
+            addrl   <= addri[0];
+            mask    <= addri[0] && !rw ? 4'b0001 : 4'b0011;
+            addr    <= addri;
+            r_addr  <= i_addr;
+            r_rw    <= i_rw;
+            r_dtw   <= i_dtw;
+            isout   <= stb;
+            oe      <= 0;
+            ack     <= 0;
+        end
+        // T2
+        3'b001: begin
+            state   <= reset ? 0 : 3'b010;
+            // BLE is active low and NOT inverted on the output
+            dout    <= { ble, addr[31:17] };
+            we      <= rw;
+            if(SRAM_LATCH_LAZY) begin
+                hasinit <= 1;
+            end
+        end
+        // TW (wait 1 cycle)
+        3'b010: begin
+            state   <= reset ? 0 : 3'b100;
+            // I/O output mode only in write mode
+            isout   <= rw;
+            // Dirty hack :(
+            dout    <= rw ?
+                mask == 4'b0001 ? { dtw[`B1], 8'b0 } :
+                mask == 4'b0011 ? dtw[15:0] :
+                mask == 4'b0110 ? dtw[23:8] :
+                mask == 4'b1100 ? dtw[31:16] :
+                { 8'b0, dtw[`B3] } : 16'b0;
+            // BHE is active low and INVERTED on the output
+            bhe     <= mask[0] | !rw;
+            // Output enable only in read mode
+            oe      <= !rw;
+        end
+        // T3 (wait for oe_negedge)
+        3'b100: begin
+            state   <= mask[3] || reset ? 3'b000 : 3'b101;
+            mask    <= mask[0] ? addrl  && !rw ? 4'b0110 : 4'b1100 : 4'b1000;
+            ack     <= !reset && mask[3];
+            we      <= 0;
+            addr    <= addr + 2;        
+            lastble <= ble;
+            // Write result to dtr (always)
+            dtr[`B0] <= mask[0] ? addrl ? din[`B1] : din[`B0] : dtr[`B0];
+            dtr[`B1] <= mask[1] ? addrl ? din[`B0] : din[`B1] : dtr[`B1];
+            dtr[`B2] <= mask[2] ? addrl ? din[`B1] : din[`B0] : dtr[`B2];
+            dtr[`B3] <= mask[3] ? addrl ? din[`B0] : din[`B1] : dtr[`B3];
+        end
+        3'b101: begin
+            state   <= reset ? 0 :
+                // We can skip 1 cycle if the MSBs is the same
+                { ble, addr[31:17] } == { lastble, addri[31:17] }
+                ? 3'b010 : 3'b001;
+            dout    <= addr[16:1];
+            isout   <= 1;
+            oe      <= 0;
+            ack     <= 0;
+        end
+        // So Anthony doesn't complain
+        default: begin
+            state   <= 3'd0;
+        end
+    endcase
+
+    // Negedge signals
+    always @(negedge clk) case(state)
+        // Before T1
+        3'b000, 3'b101: begin
+            oe_negedge   <= 0;
+            ale0_negedge <= 1;
+        end
+        // Before T2
+        3'b001: begin
+            ale0_negedge <= 0;
+            ale1_negedge <= 1;
+        end
+        // Before TW
+        3'b010: begin
+            ale0_negedge <= 0;
+            ale1_negedge <= 0;
+            oe_negedge   <= 1;
+        end
+        // So verilator doesn't complain
+        default: begin end
+    endcase
+    endgenerate
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/hs32_user_proj/dev_gpio.v b/verilog/rtl/hs32_user_proj/dev_gpio.v
index b8f94c4..e48e285 100644
--- a/verilog/rtl/hs32_user_proj/dev_gpio.v
+++ b/verilog/rtl/hs32_user_proj/dev_gpio.v
@@ -1,5 +1,4 @@
 `ifdef verilator
-    `include "defines.v"
     `include "hs32_user_proj/io_filter.v"
 `endif
 
@@ -8,9 +7,9 @@
     input   wire reset,
 
     // External IO
-    input  wire [`MPRJ_IO_PADS-1:0] io_in,
-    output wire [`MPRJ_IO_PADS-1:0] io_out,
-    output wire [`MPRJ_IO_PADS-1:0] io_oeb,
+    input  wire [TOTAL_IO-1:0] io_in,
+    output wire [TOTAL_IO-1:0] io_out,
+    output wire [TOTAL_IO-1:0] io_oeb,
 
     // Filtered signals
     output wire[31:0] io_in_sync,
@@ -29,6 +28,7 @@
     output wire io_irqr,
     output wire io_irqf
 );
+    parameter TOTAL_IO = 32;
     localparam NUM_IO = 32;
 
     assign ack = 1;
@@ -46,15 +46,15 @@
     io_filter filter[NUM_IO-1:0](
         .clk(clk),
         .rst(reset),
-        .a(io_in[37:6]),
+        .a(io_in[TOTAL_IO-1:(TOTAL_IO-NUM_IO)]),
         .b(io_in_sync),
         .rise(io_in_rise),
         .fall(io_in_fall)
     );
 
     // Assign outputs
-    assign io_out = { cfg[1], 6'b0 };
-    assign io_oeb = { cfg[0], 6'b0 }; // Output when NC
+    assign io_out = { cfg[1], {(TOTAL_IO-NUM_IO){1'b0}} };
+    assign io_oeb = { cfg[0], {(TOTAL_IO-NUM_IO){1'b0}} }; // Output when NC
 
     // Generate rising/falling interrupts
     wire[NUM_IO-1:0] io_ir, io_if;
diff --git a/verilog/rtl/hs32_user_proj/dev_intercon.v b/verilog/rtl/hs32_user_proj/dev_intercon.v
index d4e7d3f..b111207 100644
--- a/verilog/rtl/hs32_user_proj/dev_intercon.v
+++ b/verilog/rtl/hs32_user_proj/dev_intercon.v
@@ -17,6 +17,8 @@
 module dev_intercon (
     input   wire clk,
     input   wire reset,
+    // Usermode?
+    input wire userbit,
 
     // Controller interface
     // rw and dtw are connected to all devices
@@ -37,17 +39,20 @@
     output wire sstb,
     input  wire sack,
     input  wire[31:0] sdtr
+
+    // Interrupt (unknown address)
 );
     parameter NS = 1;
     parameter[MASK_LEN*NS-1:0] BASE = 0;
     parameter[MASK_LEN*NS-1:0] MASK = 0;
     parameter MASK_LEN = 8;
+    parameter LIMITS = 12;
 
     reg[31:0] aict_base;
     reg[31:0] r_dtr;
     wire[NS-1:0] sel;
-    wire none = ~(|sel);
-    wire in_aict = aict_base[31:MASK_LEN] == i_addr[31:MASK_LEN];
+    wire none = userbit || (~(|sel));
+    wire in_aict = !userbit && (aict_base[31:MASK_LEN] == i_addr[31:MASK_LEN]);
     wire in_base = in_aict && (i_addr[0+:MASK_LEN] == 0);
 
     // Address decoder
@@ -70,11 +75,13 @@
         for(j = 0; j < 32 * NS; j = j+1)
             r_dtr[j%32] = r_dtr[j%32] | (sel[j/32] & i_dtr[j]);
     end
-    assign o_dtr = none ? sdtr : (in_base ? aict_base : r_dtr);
 
-    // Other signals
+    // Assign outputs
     assign o_ack = none ? sack : (in_base ? 1'b1 : |(i_ack & sel));
     assign o_stb = { NS{ i_stb & ~in_base } } & sel;
+    assign o_dtr = none ? sdtr : (in_base ? aict_base : r_dtr);
+
+    // SRAM select
     assign sstb = none & i_stb & ~in_base;
 
     // AICT base register
diff --git a/verilog/rtl/hs32_user_proj/dev_timer.v b/verilog/rtl/hs32_user_proj/dev_timer.v
index cbf8d60..3352d93 100644
--- a/verilog/rtl/hs32_user_proj/dev_timer.v
+++ b/verilog/rtl/hs32_user_proj/dev_timer.v
@@ -1,3 +1,23 @@
+/**
+ * Copyright (c) 2020 The HSC Core Authors
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. SPDX-License-Identifier: Apache-2.0
+ * 
+ * @file   dev_timer.v
+ * @author Kevin Dai <kevindai02@outlook.com>
+ * @date   Created on December 17 2020, 12:31 AM
+ */
+
 module dev_timer (
     input   wire clk,
     input   wire reset,
@@ -158,4 +178,15 @@
             int_match <= 0;
         end
     end
+
+    // Interrupts, drive: int_ovf
+    always @(posedge clk) if(reset) begin
+        int_ovf <= 0;
+    end else begin
+        if(timer_ovf) begin
+            int_ovf <= 1;
+        end else begin
+            int_ovf <= 0;
+        end
+    end
 endmodule
\ No newline at end of file
diff --git a/verilog/rtl/hs32_user_proj/dev_wb.v b/verilog/rtl/hs32_user_proj/dev_wb.v
index 21000c8..cf42fbd 100644
--- a/verilog/rtl/hs32_user_proj/dev_wb.v
+++ b/verilog/rtl/hs32_user_proj/dev_wb.v
@@ -1,3 +1,23 @@
+/**
+ * Copyright (c) 2020 The HSC Core Authors
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. SPDX-License-Identifier: Apache-2.0
+ * 
+ * @file   dev_wb.v
+ * @author Kevin Dai <kevindai02@outlook.com>
+ * @date   Created on December 22 2020, 12:43 AM
+ */
+
 module dev_wb (
     input wire clk,
     input wire reset,
diff --git a/verilog/rtl/hs32_user_proj/hs32_aic.v b/verilog/rtl/hs32_user_proj/hs32_aic.v
index 4ce1e5b..2863197 100644
--- a/verilog/rtl/hs32_user_proj/hs32_aic.v
+++ b/verilog/rtl/hs32_user_proj/hs32_aic.v
@@ -76,7 +76,7 @@
         interrupts[20] ? 20 :

         interrupts[21] ? 21 :

         interrupts[22] ? 22 : 23;

-    assign handler = aict[vec] & (~32'b1111);

+    assign handler = aict[vec] & (~32'b11);

 

     // Calculate table index

     wire[4:0] aict_idx = addr-1;

diff --git a/verilog/rtl/hs32_user_proj/hs32_bram_ctl.v b/verilog/rtl/hs32_user_proj/hs32_bram_ctl.v
index f9d4ab3..ab7b32e 100644
--- a/verilog/rtl/hs32_user_proj/hs32_bram_ctl.v
+++ b/verilog/rtl/hs32_user_proj/hs32_bram_ctl.v
@@ -42,10 +42,6 @@
     input  wire [31:0] dbuf3
 );
     parameter addr_width = 12;
-    parameter data0 = "bram0.hex";
-    parameter data1 = "bram1.hex";
-    parameter data2 = "bram2.hex";
-    parameter data3 = "bram3.hex";
 
     // 4 addresses for each bram
     // Selects between current dword and next dword
diff --git a/verilog/rtl/hs32_user_proj/hs32_core0.v b/verilog/rtl/hs32_user_proj/hs32_core0.v
deleted file mode 100644
index b8b73fd..0000000
--- a/verilog/rtl/hs32_user_proj/hs32_core0.v
+++ /dev/null
@@ -1,126 +0,0 @@
-`ifdef verilator
-    `include "defines.v"
-    `include "cpu/hs32_cpu.v"
-    `include "frontend/sram.v"
-    `include "frontend/mmio.v"
-`endif
-
-`default_nettype none
-
-module hs32_user_proj (
-`ifdef USE_POWER_PINS
-    inout vdda1,	// User area 1 3.3V supply
-    inout vdda2,	// User area 2 3.3V supply
-    inout vssa1,	// User area 1 analog ground
-    inout vssa2,	// User area 2 analog ground
-    inout vccd1,	// User area 1 1.8V supply
-    inout vccd2,	// User area 2 1.8v supply
-    inout vssd1,	// User area 1 digital ground
-    inout vssd2,	// User area 2 digital ground
-`endif
-
-    // Wishbone Slave ports (WB MI A)
-    input  wire wb_clk_i,
-    input  wire wb_rst_i,
-    input  wire wbs_stb_i,
-    input  wire wbs_cyc_i,
-    input  wire wbs_we_i,
-    input  wire [3:0] wbs_sel_i,
-    input  wire [31:0] wbs_dat_i,
-    input  wire [31:0] wbs_adr_i,
-    output wire wbs_ack_o,
-    output wire [31:0] wbs_dat_o,
-
-    // Logic Analyzer Signals
-    input  wire [127:0] la_data_in,
-    output wire [127:0] la_data_out,
-    input  wire [127:0] la_oen,
-
-    // IOs
-    input  wire [`MPRJ_IO_PADS-1:0] io_in,
-    output wire [`MPRJ_IO_PADS-1:0] io_out,
-    output wire [`MPRJ_IO_PADS-1:0] io_oeb
-);
-    // Clock and reset
-    // wire clk = (~la_oen[64])? la_data_in[64] : wb_clk_i;
-    // wire rst = (~la_oen[65])? la_data_in[65] : wb_rst_i;
-    wire clk = wb_clk_i;
-    wire rst = wb_rst_i;
-
-    // Wishbone logic
-    wire valid;
-    wire [3:0] wstrb;
-    assign valid = wbs_cyc_i && wbs_stb_i; 
-    assign wstrb = wbs_sel_i & { 4 { wbs_we_i } };
-    // TODO
-    
-    // CPU Core 0 Connection
-    wire[31:0] adr0, dtr0, dtw0, isr0;
-    wire rw0, val0, rdy0, iack0, irq0, nmi0, usr0, fault0;
-    wire[23:0] int0;
-    wire[4:0] vec0;
-    hs32_cpu #(
-        .IMUL(1), .BARREL_SHIFTER(1), .PREFETCH_SIZE(3)
-    ) core0 (
-        .i_clk(clk), .reset(rst),
-        // Mem
-        .addr(adr0), .rw(rw0), .din(dtr0), .dout(dtw0),
-        .valid(val0), .ready(rdy0),
-        // Int
-        .interrupts(int0), .iack(iack0), .handler(isr0),
-        .intrq(irq0), .vec(vec0), .nmi(nmi0),
-        // Misc
-        .userbit(usr0), .fault(fault0)
-    );
-
-    // MMIO
-    mmio mmio_unit(
-        .clk(clk), .reset(rst),
-        // CPU
-        .valid(val0), .ready(rdy0),
-        .addr(adr0), .dtw(dtw0), .dtr(dtr0), .rw(rw0),
-        // SRAM
-        .sval(svalid), .srdy(sready),
-        .saddr(saddr), .sdtw(sdtw), .sdtr(sdtr), .srw(srw),
-        // Interrupt controller
-        .interrupts(int0), .handler(isr0), .intrq(irq0),
-        .vec(vec0), .nmi(nmi0)
-    );
-
-    // SRAM Controller
-    wire sready, svalid, srw;
-    wire [31:0] saddr, sdtw, sdtr;
-    // Output
-    wire[15:0] data_in;
-    wire[15:0] data_out;
-    wire we, oe, oe_neg, ale0_neg, ale1_neg, bhe, isout;
-    ext_sram #(
-        .SRAM_LATCH_LAZY(1)
-    ) sram (
-        .clk(clk), .reset(rst),
-        // Memory requests
-        .ready(sready), .valid(svalid), .rw(srw),
-        .addri(saddr), .dtw(sdtw), .dtr(sdtr),
-        // External IO interface, active >> HIGH <<
-        .din(data_in), .dout(data_out),
-        .we(we), .oe(oe), .oe_negedge(oe_neg),
-        .ale0_negedge(ale0_neg),
-        .ale1_negedge(ale1_neg),
-        .bhe(bhe), .isout(isout)
-    );
-
-    // SRAM GPIO Logic
-    assign io_out[36] = usr0;
-    assign data_in = io_in[35:20];
-    assign io_out[35:20] = data_out;
-    assign io_out[19] = !(oe & oe_neg);
-    assign io_out[18] = !we;
-    assign io_out[17] = ale0_neg;
-    assign io_out[16] = ale1_neg;
-    assign io_out[15] = !bhe;
-
-    // Output enables
-    assign io_oeb[36] = 0;
-    assign io_oeb[35:20] = { (16){ ~isout } };
-    assign io_oeb[19:15] = 0;
-endmodule
\ No newline at end of file
diff --git a/verilog/rtl/hs32_user_proj/hs32_core1.v b/verilog/rtl/hs32_user_proj/hs32_core1.v
index d95bc74..6f74749 100644
--- a/verilog/rtl/hs32_user_proj/hs32_core1.v
+++ b/verilog/rtl/hs32_user_proj/hs32_core1.v
@@ -144,7 +144,7 @@
     assign wbs_dat_o = bus_hold ? dread : wbs_dev_dtr;
     assign cpu_dread = dread;
     assign wbs_ack_o = bus_hold ? ack : wbs_dev_ack;
-    assign cpu_ack = bus_hold ? 0: ack;
+    assign cpu_ack = bus_hold ? 0 : ack;
 
     reg ram_bsy;
     assign ram_ce = ~(ram_stb | ram_bsy);
@@ -159,13 +159,18 @@
     end
 
     `ifdef SIM
-        //reg bsy;
-        always @(posedge clk) /*if(rst)
+        reg bsy;
+        wire dolog = (stb && ack) || (ack && bsy);
+
+        always @(posedge clk) if(rst)
             bsy <= 0;
-        else if(stb && !bsy) begin
+        else if(stb && !ack) begin
             bsy <= 1;
-        end*/
-        if(ack && stb) begin
+        end else if(ack && bsy) begin
+            bsy <= 0;
+        end
+
+        always @(posedge clk) if(dolog) begin
             `ifdef LOG_MEMORY_WRITE
                 if(rw) $display($time, " Writing [%X] <- %X", addr, dwrite);
             `endif
@@ -198,9 +203,10 @@
             { 1'b1, 2'b11, 1'b1, 4'b0 },
             { 1'b1, 2'b11, 1'b1, 4'b0 }
         }),
-        .MASK_LEN(8)
+        .MASK_LEN(8),
+        .LIMITS(12)
     ) mmio_conn (
-        .clk(clk), .reset(rst),
+        .clk(clk), .reset(rst), .userbit(userbit),
         
         // Input
         .i_stb(stb), .o_ack(ack),
@@ -246,7 +252,7 @@
     wire[23:0] hw_irq = {
         gpt_irqr | gpt_irqf,
         tn_ints,
-        dwb_irq,
+        dwb_irq & !bus_hold,
         16'b0
     };
 
@@ -261,7 +267,9 @@
     wire[31:0] io_in_sync, io_in_rise, io_in_fall;
     wire[37:0] io_out_buf, io_oeb_buf;
 
-    dev_gpio32 gpio32 (
+    dev_gpio32 #(
+        .TOTAL_IO(`MPRJ_IO_PADS)
+    ) gpio32 (
         .clk(clk), .reset(rst),
         .io_in(io_in),
         .io_out(io_out_buf),
diff --git a/verilog/rtl/hs32_user_proj/hs32_mpi.v b/verilog/rtl/hs32_user_proj/hs32_mpi.v
deleted file mode 100644
index e69de29..0000000
--- a/verilog/rtl/hs32_user_proj/hs32_mpi.v
+++ /dev/null
diff --git a/verilog/rtl/hs32_user_proj/hs32_wrapper.v b/verilog/rtl/hs32_user_proj/hs32_wrapper.v
index c6a9d10..5471a4d 100644
--- a/verilog/rtl/hs32_user_proj/hs32_wrapper.v
+++ b/verilog/rtl/hs32_user_proj/hs32_wrapper.v
@@ -1,3 +1,23 @@
+/**
+ * Copyright (c) 2020 The HSC Core Authors
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. SPDX-License-Identifier: Apache-2.0
+ * 
+ * @file   hs32_wrapper.v
+ * @author Kevin Dai <kevindai02@outlook.com>
+ * @date   Created on December 16 2020, 12:25 AM
+ */
+
 `ifdef verilator
     `include "defines.v"
     `include "hs32_user_proj/hs32_core1.v"
@@ -12,20 +32,6 @@
 `endif
 
 `default_nettype none
-/*
- *-------------------------------------------------------------
- *
- * user_project_wrapper
- *
- * This wrapper enumerates all of the pins available to the
- * user for the user project.
- *
- * An example user project is provided in this wrapper.  The
- * example should be removed and replaced with the actual
- * user project.
- *
- *-------------------------------------------------------------
- */
 
 module user_project_wrapper (
 `ifdef USE_POWER_PINS
diff --git a/verilog/rtl/hs32_user_proj/io_filter.v b/verilog/rtl/hs32_user_proj/io_filter.v
index d5720a9..ba5d1e4 100644
--- a/verilog/rtl/hs32_user_proj/io_filter.v
+++ b/verilog/rtl/hs32_user_proj/io_filter.v
@@ -1,3 +1,23 @@
+/**
+ * Copyright (c) 2020 The HSC Core Authors
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. SPDX-License-Identifier: Apache-2.0
+ * 
+ * @file   io_filter.v
+ * @author Kevin Dai <kevindai02@outlook.com>
+ * @date   Created on December 17 2020, 8:36 PM
+ */
+
 // TODO: Hahaha too lazy to do it
 module io_filter (
     input wire clk,