Added trap handling to core.
diff --git a/docs/Design/MemoryMap.txt b/docs/Design/MemoryMap.txt
index 81fff28..aa237f4 100644
--- a/docs/Design/MemoryMap.txt
+++ b/docs/Design/MemoryMap.txt
@@ -12,6 +12,7 @@
 				0x1081_0004: Relative Jump
 				0x1081_0008: Step
 				0x1081_0010: Current Instruction
+				0x1081_0020: Clear error
 				0x1081_1000-0x1081_101F: Register
 				0x1081_2000-0x1081_2FFF: CSRs			
 	0x11xx_xxxx: Slave 1 (Core 1 local memory)
@@ -25,6 +26,7 @@
 				0x1181_0004: Relative Jump
 				0x1181_0008: Step
 				0x1181_0010: Current Instruction
+				0x1181_0020: Clear error
 				0x1181_1000-0x1181_101F: Register
 				0x1181_2000-0x1181_2FFF: CSRs		
 	0x12xx_xxxx: Slave 2 (Video SRAM)
diff --git a/verilog/dv/coreArch/Makefile b/verilog/dv/coreArch/Makefile
index 2e9a0b1..0d2b4a8 100644
--- a/verilog/dv/coreArch/Makefile
+++ b/verilog/dv/coreArch/Makefile
@@ -36,7 +36,7 @@
 
 SIGNATURE_START=$(shell readelf -s coreArch.elf | grep begin_signature | awk '{print $$2}')
 SIGNATURE_END=$(shell readelf -s coreArch.elf | grep end_signature | awk '{print $$2}')
-CODE_END=$(shell readelf -s coreArch.elf | grep rvtest_code_end | awk '{print $$2}')
+CODE_END=$(shell readelf -s coreArch.elf | grep write_tohost | awk '{print $$2}')
 
 .SUFFIXES:
 all:  ${BLOCKS:=.lst} ${BLOCKS:=.disass} ${BLOCKS:=.vcd}
diff --git a/verilog/dv/coreArch/coreArch_tb.v b/verilog/dv/coreArch/coreArch_tb.v
index db77d9b..c83f4aa 100644
--- a/verilog/dv/coreArch/coreArch_tb.v
+++ b/verilog/dv/coreArch/coreArch_tb.v
@@ -32,16 +32,21 @@
 	wire memoryBusy = 1'b0;
 	
 	wire management_run = 1'b1;
+	wire management_trapEnable = 1'b1;
 	wire management_writeEnable = 1'b0;
 	wire[3:0] management_byteSelect = 4'b0000;
 	wire[15:0] management_address = 'b0;
 	wire[31:0] management_writeData = 'b0;
 	wire[31:0] management_readData;
 
+	wire eCall;
+	wire eBreak;
+
 	wire[1:0] probe_state;
+	wire[1:0] probe_env;
 	wire[31:0] probe_programCounter;
 	wire[6:0] probe_opcode;
-	wire[3:0] probe_errorCode;
+	wire[1:0] probe_errorCode;
 	wire probe_isBranch;
 	wire probe_takeBranch;
 	wire probe_isStore;
@@ -66,6 +71,9 @@
 		$display("CODE_END: 0x%h", 32'h`CODE_END);
 
 		wait((probe_programCounter == 32'h`CODE_END) || (|probe_errorCode));
+		//wait(eBreak || (|probe_errorCode));
+
+		#50
 
 		if (|probe_errorCode) begin
 			$display("%c[1;31m",27);
@@ -162,6 +170,8 @@
 	assign VDD1V8 = power2;
 	assign VSS = 1'b0;
 
+	localparam CORE_EXTENSIONS = 26'b00_0000_0000_0000_0001_0000_0000;
+
 	RV32ICore core(
 		.vccd1 (VDD1V8),	// User area 1 1.8V supply
 		.vssd1 (VSS),		// User area 1 digital ground
@@ -175,12 +185,21 @@
 		.memoryDataRead(memoryDataRead),
 		.memoryBusy(memoryBusy),
 		.management_run(management_run),
+		.management_trapEnable(management_trapEnable),
 		.management_writeEnable(management_writeEnable),
 		.management_byteSelect(management_byteSelect),
 		.management_address(management_address),
 		.management_writeData(management_writeData),
 		.management_readData(management_readData),
+		.coreIndex(8'h00),
+		.manufacturerID(11'h000),
+		.partID(16'hCD55),
+		.versionID(4'h0),
+		.extensions(CORE_EXTENSIONS),
+		.eCall(eCall),
+		.eBreak(eBreak),
 		.probe_state(probe_state),
+		.probe_env(probe_env),
 		.probe_programCounter(probe_programCounter),
 		.probe_opcode(probe_opcode),
 		.probe_errorCode(probe_errorCode),
diff --git a/verilog/dv/coreArch/riscof/ExperiarSoC/ExperiarSoC_isa.yaml b/verilog/dv/coreArch/riscof/ExperiarSoC/ExperiarSoC_isa.yaml
index c985fd4..432e02d 100644
--- a/verilog/dv/coreArch/riscof/ExperiarSoC/ExperiarSoC_isa.yaml
+++ b/verilog/dv/coreArch/riscof/ExperiarSoC/ExperiarSoC_isa.yaml
@@ -1,26 +1,27 @@
 hart_ids: [0]
 hart0:
-  ISA: RV32IZicsr
+  ISA: RV32I_Zicsr
   physical_addr_sz: 32
   User_Spec_Version: '2.3'
   supported_xlen: [32]
+  hw_data_misaligned_support: false
   misa:
-   reset-val: 0x40000100
-   rv32:
-     accessible: true
-     mxl:
-       implemented: true
-       type:
-           warl:
+    reset-val: 0x40000100
+    rv32:
+      accessible: true
+      mxl:
+        implemented: true
+        type:
+            warl:
               dependency_fields: []
               legal:
                 - mxl[1:0] in [0x1]
               wr_illegal:
                 - Unchanged
-     extensions:
-       implemented: true
-       type:
-           warl:
+      extensions:
+        implemented: true
+        type:
+            warl:
               dependency_fields: []
               legal:
                 - extensions[25:0] bitmask [0x0001104, 0x0000000]
diff --git a/verilog/dv/coreArch/riscof/ExperiarSoC/env/model_test.h b/verilog/dv/coreArch/riscof/ExperiarSoC/env/model_test.h
index a55076e..d7be858 100644
--- a/verilog/dv/coreArch/riscof/ExperiarSoC/env/model_test.h
+++ b/verilog/dv/coreArch/riscof/ExperiarSoC/env/model_test.h
@@ -11,11 +11,11 @@
         .word 4;
 
 //RV_COMPLIANCE_HALT
-#define RVMODEL_HALT                                              \
-  li x1, 1;                                                                   \
-  write_tohost:                                                               \
-    sw x1, tohost, t5;                                                        \
-    j write_tohost;
+#define RVMODEL_HALT   \
+	li x1, 1;          \
+	write_tohost:      \
+	sw x1, tohost, t5; \
+	j write_tohost;
 
 #define RVMODEL_BOOT
 
diff --git a/verilog/dv/coreArch/runArchTest.py b/verilog/dv/coreArch/runArchTest.py
index eb7f177..0046f5a 100644
--- a/verilog/dv/coreArch/runArchTest.py
+++ b/verilog/dv/coreArch/runArchTest.py
@@ -10,17 +10,21 @@
 	process.wait()
 	if process.stdout != None:
 		for line in process.stdout:
-			print(str(line).replace("\\n", ""))
+			print(line.decode("utf-8"), end="")
 	return process.returncode
 
 def RunArchTest(elfFilePath:str, signatureFilePath:str):
 	# Run the simulator
 	print(f"Running simulation")
-	makeFilePath = os.path.dirname(os.path.abspath(__file__))
-	shutil.copy2(os.path.join(makeFilePath, "coreArch_tb.v"), os.getcwd())
-	shutil.copy2(os.path.join(makeFilePath, "Makefile"), os.getcwd())
-	RunShellCommand(["make"])
 
+	try:
+		makeFilePath = os.path.dirname(os.path.abspath(__file__))
+		shutil.copy2(os.path.join(makeFilePath, "coreArch_tb.v"), os.getcwd())
+		shutil.copy2(os.path.join(makeFilePath, "Makefile"), os.getcwd())
+		RunShellCommand(["make"])
+	except Exception as e:
+		print(e)
+		
 	print(f"Simulation completed")
 
 def main():
diff --git a/verilog/includes/includes.rtl.caravel_user_project b/verilog/includes/includes.rtl.caravel_user_project
index 66bdffb..5a9380f 100644
--- a/verilog/includes/includes.rtl.caravel_user_project
+++ b/verilog/includes/includes.rtl.caravel_user_project
@@ -12,6 +12,7 @@
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/CSR/CSR_DataRegister.v 
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/CSR/CSR_ReadRegister.v 
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/CSR/CSR_TimerRegister.v 
+-v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/CSR/Traps/Traps.v 
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/JTAG.v 
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/JTAGRegister.v 
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/Memory/LocalMemoryInterface.v 
diff --git a/verilog/rtl/ExperiarCore/CSR/CSR.v b/verilog/rtl/ExperiarCore/CSR/CSR.v
index 0e714d9..3003313 100644
--- a/verilog/rtl/ExperiarCore/CSR/CSR.v
+++ b/verilog/rtl/ExperiarCore/CSR/CSR.v
@@ -15,7 +15,28 @@
 		input wire[15:0] partID,
 		input wire[3:0] versionID,
 		input wire[25:0] extensions,
-		input wire instructionCompleted
+		input wire instructionCompleted,
+
+		// System trap interface
+		input wire[1:0] coreState,
+		input wire[31:0] programCounter,
+		input wire[31:0] currentInstruction,
+		input wire isLoad,
+		input wire isStore,
+		input wire isMachineTimerInterrupt,
+		input wire isMachineExternalInterrupt,
+		input wire isMachineSoftwareInterrupt,
+		input wire isAddressMisaligned,
+		input wire isAccessFault,
+		input wire isInvalidInstruction,
+		input wire isEBREAK,
+		input wire isECALL,
+		input wire isAddressBreakpoint,
+		input wire[15:0] userInterrupts,
+		input wire trapReturn,
+		output wire inTrap,
+		output wire[31:0] trapVector,
+		output wire[31:0] trapReturnVector
 	);
 
 	// Cylce
@@ -128,6 +149,38 @@
 		.csrRequestOutput(misaRequestOutput),
 		.value({ 2'b01, 4'b0, extensions }));
 
+	// Trap handling
+	wire[31:0] trapsReadData;
+	wire trapsRequestOutput;
+	Traps traps(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(trapsReadData),
+		.requestOutput(trapsRequestOutput),
+		.coreState(coreState),
+		.programCounter(programCounter),
+		.currentInstruction(currentInstruction),
+		.isLoad(isLoad),
+		.isStore(isStore),
+		.isMachineTimerInterrupt(isMachineTimerInterrupt),
+		.isMachineExternalInterrupt(isMachineExternalInterrupt),
+		.isMachineSoftwareInterrupt(isMachineSoftwareInterrupt),
+		.isAddressMisaligned(isAddressMisaligned),
+		.isAccessFault(isAccessFault),
+		.isInvalidInstruction(isInvalidInstruction),
+		.isEBREAK(isEBREAK),
+		.isECALL(isECALL),
+		.isAddressBreakpoint(isAddressBreakpoint),
+		.userInterrupts(userInterrupts),
+		.trapReturn(trapReturn),
+		.inTrap(inTrap),
+		.trapVector(trapVector),
+		.trapReturnVector(trapReturnVector));
+
 	always @(*) begin
 		case (1'b1)
 			// Timers
@@ -143,6 +196,9 @@
 			coreIDRequestOutput: csrReadData <= coreIDReadData;
 			misaRequestOutput: csrReadData <= misaReadData;
 
+			// Traps
+			trapsRequestOutput: csrReadData <= trapsReadData;
+
 			default: csrReadData <= 32'b0;
 		endcase
 	end
diff --git a/verilog/rtl/ExperiarCore/CSR/CSR_ConfigurationRegister.v b/verilog/rtl/ExperiarCore/CSR/CSR_ConfigurationRegister.v
index 973c079..8b77762 100644
--- a/verilog/rtl/ExperiarCore/CSR/CSR_ConfigurationRegister.v
+++ b/verilog/rtl/ExperiarCore/CSR/CSR_ConfigurationRegister.v
@@ -10,7 +10,7 @@
 		input wire csrReadEnable,
 		input wire[11:0] csrAddress,
 		input wire[31:0] csrWriteData,
-		output reg[31:0] csrReadData,
+		output wire[31:0] csrReadData,
 		output wire csrRequestOutput,
 
 		// System interface
diff --git a/verilog/rtl/ExperiarCore/CSR/CSR_DataRegister.v b/verilog/rtl/ExperiarCore/CSR/CSR_DataRegister.v
index e69de29..8cfce0b 100644
--- a/verilog/rtl/ExperiarCore/CSR/CSR_DataRegister.v
+++ b/verilog/rtl/ExperiarCore/CSR/CSR_DataRegister.v
@@ -0,0 +1,31 @@
+module CSR_DataRegister #(
+		parameter ADDRESS = 12'h000
+	)(
+		input wire clk,
+		input wire rst,
+
+		// CSR interface
+		input wire csrWriteEnable,
+		input wire csrReadEnable,
+		input wire[11:0] csrAddress,
+		input wire[31:0] csrWriteData,
+		output wire[31:0] csrReadData,
+		output wire csrRequestOutput,
+
+		// System interface
+		input wire[31:0] readData,
+		output wire readDataEnable,
+		output wire[31:0] writeData,
+		output wire writeDataEnable
+	);
+	
+	wire csrEnabled = csrAddress == ADDRESS;
+
+	assign csrReadData = csrEnabled && csrReadEnable ? readData : 32'b0;
+	assign readDataEnable = csrEnabled && csrReadEnable;
+	assign writeData = csrWriteData;
+	assign writeDataEnable = csrEnabled && csrWriteEnable;
+
+	assign csrRequestOutput = csrEnabled && csrReadEnable;
+	
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/ExperiarCore/CSR/Traps/Traps.v b/verilog/rtl/ExperiarCore/CSR/Traps/Traps.v
new file mode 100644
index 0000000..b116d6c
--- /dev/null
+++ b/verilog/rtl/ExperiarCore/CSR/Traps/Traps.v
@@ -0,0 +1,347 @@
+module Traps (
+		input wire clk,
+		input wire rst,
+
+		// CSR interface
+		input wire csrWriteEnable,
+		input wire csrReadEnable,
+		input wire[11:0] csrAddress,
+		input wire[31:0] csrWriteData,
+		output reg[31:0] csrReadData,
+		output wire requestOutput,
+
+		// System interface
+		input wire[1:0] coreState,
+		input wire[31:0] programCounter,
+		input wire[31:0] currentInstruction,
+		input wire isLoad,
+		input wire isStore,
+		input wire isMachineTimerInterrupt,
+		input wire isMachineExternalInterrupt,
+		input wire isMachineSoftwareInterrupt,
+		input wire isAddressMisaligned,
+		input wire isAccessFault,
+		input wire isInvalidInstruction,
+		input wire isEBREAK,
+		input wire isECALL,
+		input wire isAddressBreakpoint,
+		input wire[15:0] userInterrupts,
+		input wire trapReturn,
+		output wire inTrap,
+		output wire[31:0] trapVector,
+		output wire[31:0] trapReturnVector
+	);
+	
+	localparam CORE_STATE_HALT 	 	 = 2'b00;
+	localparam CORE_STATE_FETCH   	 = 2'b10;
+	localparam CORE_STATE_EXECUTE 	 = 2'b11;
+
+	reg machineInterruptEnable;
+	reg machinePreviousInterruptEnable;
+	wire[31:0] mieValue;
+	reg[31:0] mtvecValue;
+	reg[31:0] mepcValue;
+	reg[31:0] mcauseValue;
+	reg[31:0] mtvalValue;
+	reg[31:0] mipValue;
+
+	wire[11:0] systemInterrupts = { isMachineExternalInterrupt, 1'b0, 1'b0, 1'b0, 
+									isMachineTimerInterrupt, 1'b0, 1'b0, 1'b0, 
+									isMachineSoftwareInterrupt, 1'b0, 1'b0, 1'b0 };
+	wire[31:0] pendingInterrupts = { userInterrupts, 4'b0000, systemInterrupts } & mieValue;
+
+	wire misalignedInstructionFetch = isAddressMisaligned && (coreState == CORE_STATE_FETCH);
+
+	reg[30:0] trapCause;
+	always @(*) begin
+		if (isInterrupt) begin
+			case (1'b1)
+				isMachineSoftwareInterrupt: trapCause <= 30'd3;
+				isMachineTimerInterrupt: trapCause <= 30'd7;
+				|userInterrupts: trapCause <= 30'd8;
+				isMachineExternalInterrupt: trapCause <= 30'd11;
+				default: trapCause <= 30'b0;
+			endcase
+		end else begin
+			case (1'b1)
+				isAddressBreakpoint && (coreState == CORE_STATE_FETCH): trapCause <= 30'd3;
+				isAccessFault && (coreState == CORE_STATE_FETCH): trapCause <= 30'd1;
+				isInvalidInstruction: trapCause <= 30'd2;
+				misalignedInstructionFetch: trapCause <= 30'd0;
+				isECALL: trapCause <= 30'd11;
+				isEBREAK: trapCause <= 30'd3;
+				isAddressBreakpoint && (coreState == CORE_STATE_EXECUTE) && (isLoad || isStore): trapCause <= 30'd3;
+				isAddressMisaligned && (coreState == CORE_STATE_EXECUTE) && isStore: trapCause <= 30'd6;
+				isAddressMisaligned && (coreState == CORE_STATE_EXECUTE) && isLoad: trapCause <= 30'd4;
+				isAccessFault && (coreState == CORE_STATE_EXECUTE) && isStore: trapCause <= 30'd7;
+				isAccessFault && (coreState == CORE_STATE_EXECUTE) && isLoad: trapCause <= 30'd5;				
+				default: trapCause <= 30'b0;
+			endcase
+		end		
+	end
+
+	// Misaligned instruction fetch sets trap cause to zero, so needs to be triggered specifically
+	wire isException = |trapCause || misalignedInstructionFetch;
+	wire isInterrupt = |pendingInterrupts;
+	wire isBreakPoint = isEBREAK || isAddressBreakpoint;
+	wire isTrap = isException || isInterrupt;
+
+	assign inTrap = isTrap;
+
+	wire[31:0] mipLoadValue = machineInterruptEnable ? pendingInterrupts : 1'b0;
+
+	reg[31:0] mtvalLoadValue;
+	always @(*) begin
+		 if (isTrap) begin
+			 case (1'b1)
+				 isBreakPoint: mtvalLoadValue <= programCounter;
+				 isAddressMisaligned: mtvalLoadValue <= programCounter;
+				 isInvalidInstruction: mtvalLoadValue <= currentInstruction;
+				 default: mtvalLoadValue <= 32'b0;
+			 endcase			
+		 end else begin
+			 mtvalLoadValue <= 32'b0;
+		 end 
+	end
+
+	// mstatus
+	wire[31:0] mstatusReadData;
+	wire mstatusRequestOutput;
+	wire mstatusReadDataEnable_nc;
+	wire[31:0] mstatusWriteData;
+	wire mstatusWriteDataEnable;
+	CSR_DataRegister #(.ADDRESS(12'h300)) mstatus(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(mstatusReadData),
+		.csrRequestOutput(mstatusRequestOutput),
+		.readData( { 25'b0, machinePreviousInterruptEnable, 3'b0, machineInterruptEnable, 2'b0 } ),
+		.readDataEnable(mstatusReadDataEnable_nc),
+		.writeData(mstatusWriteData),
+		.writeDataEnable(mstatusWriteDataEnable));
+
+	always @(posedge clk) begin
+		if (rst) begin
+			machineInterruptEnable <= 1'b0;
+			machinePreviousInterruptEnable <= 1'b0;
+		end
+		else begin
+			if (trapReturn) begin
+				machineInterruptEnable <= machinePreviousInterruptEnable;
+				machinePreviousInterruptEnable <= 1'b0;
+			end else if (isTrap) begin
+				machineInterruptEnable <= 1'b0;
+				machinePreviousInterruptEnable <= machineInterruptEnable;
+			end else if (mstatusWriteDataEnable) begin
+				machineInterruptEnable <=  mstatusWriteData[3];
+				machinePreviousInterruptEnable <=  mstatusWriteData[7];
+			end
+		end
+	end
+
+	// mie
+	wire[31:0] mieReadData;
+	wire mieRequestOutput;
+	CSR_ConfigurationRegister #(.ADDRESS(12'h304), .DEFAULT(32'b0)) mie(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(mieReadData),
+		.csrRequestOutput(mieRequestOutput),
+		.value(mieValue));
+
+	// mtvec
+	// In theory this is a WARL register, so only legal values can be read,
+	// This means that some bits should always be zero, but 
+	wire[31:0] mtvecValueValid = mtvecValue;//{ mtvecValue[31:4] , 2'b00, 1'b0, mtvecValue[0] }; 
+	wire mtvecRequestOutput;
+	wire[31:0] mtvecReadData;
+	wire mtvecReadDataEnable_nc;
+	wire[31:0] mtvecWriteData;
+	wire mtvecWriteDataEnable;
+	CSR_DataRegister #(.ADDRESS(12'h305)) mtvec(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(mtvecReadData),
+		.csrRequestOutput(mtvecRequestOutput),
+		.readData(mtvecValueValid),
+		.readDataEnable(mtvecReadDataEnable_nc),
+		.writeData(mtvecWriteData),
+		.writeDataEnable(mtvecWriteDataEnable));
+
+	always @(posedge clk) begin
+		if (rst) mtvecValue <= 32'b0;
+		else begin
+			if (mtvecWriteDataEnable) mtvecValue <= mtvecWriteData;
+		end
+	end
+
+	wire[31:0] trapVectorBase = { mtvecValueValid[31:2], 2'b00 };
+	wire[1:0] trapVectorMode = mtvecValueValid[1:0];
+
+	assign trapVector = (trapVectorMode == 2'b01) && isInterrupt ? trapVectorBase + {mcauseValue[29:0], 2'b00} : trapVectorBase;
+
+	// mscratch
+	wire[31:0] mscratchReadData;
+	wire mscratchRequestOutput;
+	wire[31:0] mscratchValue_nc;
+	CSR_ConfigurationRegister #(.ADDRESS(12'h340), .DEFAULT(32'b0)) mscratch (
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(mscratchReadData),
+		.csrRequestOutput(mscratchRequestOutput),
+		.value(mscratchValue_nc));
+
+	// mepc
+	wire[31:0] mepcReadData;
+	wire mepcRequestOutput;
+	wire mepcReadDataEnable_nc;
+	wire[31:0] mepcWriteData;
+	wire mepcWriteDataEnable;
+	CSR_DataRegister #(.ADDRESS(12'h341)) mepc(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(mepcReadData),
+		.csrRequestOutput(mepcRequestOutput),
+		.readData({ mepcValue[31:1], 1'b0 }),
+		.readDataEnable(mepcReadDataEnable_nc),
+		.writeData(mepcWriteData),
+		.writeDataEnable(mepcWriteDataEnable));
+
+	always @(posedge clk) begin
+		if (rst) mepcValue <= 32'b0;
+		else begin
+			if (isTrap) mepcValue <= programCounter;
+			else if (mepcWriteDataEnable) mepcValue <= mepcWriteData;
+		end
+	end
+
+	assign trapReturnVector = mepcValue;
+
+	// mcause
+	wire[31:0] mcauseReadData;
+	wire mcauseRequestOutput;
+	wire mcauseReadDataEnable_nc;
+	wire[31:0] mcauseWriteData;
+	wire mcauseWriteDataEnable;
+	CSR_DataRegister #(.ADDRESS(12'h342)) mcause(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(mcauseReadData),
+		.csrRequestOutput(mcauseRequestOutput),
+		.readData(mcauseValue),
+		.readDataEnable(mcauseReadDataEnable_nc),
+		.writeData(mcauseWriteData),
+		.writeDataEnable(mcauseWriteDataEnable));
+
+	always @(posedge clk) begin
+		if (rst) mcauseValue <= 32'b0;
+		else begin
+			if (isTrap) mcauseValue <= { isInterrupt, trapCause };
+			else if (mcauseWriteDataEnable) mcauseValue <= mcauseWriteData;
+		end
+	end
+
+	// mtval
+	wire[31:0] mtvalReadData;
+	wire mtvalRequestOutput;
+	wire mtvalReadDataEnable_nc;
+	wire[31:0] mtvalWriteData;
+	wire mtvalWriteDataEnable;
+	CSR_DataRegister #(.ADDRESS(12'h343)) mtval(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(mtvalReadData),
+		.csrRequestOutput(mtvalRequestOutput),
+		.readData(mtvalValue),
+		.readDataEnable(mtvalReadDataEnable_nc),
+		.writeData(mtvalWriteData),
+		.writeDataEnable(mtvalWriteDataEnable));
+
+	always @(posedge clk) begin
+		if (rst) mtvalValue <= 32'b0;
+		else begin
+			if (isTrap) mtvalValue <= mtvalLoadValue;
+			else if (mtvalWriteDataEnable) mtvalValue <= mtvalWriteData;
+		end
+	end
+
+	// mip
+	wire[31:0] mipReadData;
+	wire mipRequestOutput;
+	wire mipReadDataEnable_nc;
+	wire[31:0] mipWriteData;
+	wire mipWriteDataEnable;
+	CSR_DataRegister #(.ADDRESS(12'h344)) mip(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(mipReadData),
+		.csrRequestOutput(mipRequestOutput),
+		.readData(mipValue),
+		.readDataEnable(mipReadDataEnable_nc),
+		.writeData(mipWriteData),
+		.writeDataEnable(mipWriteDataEnable));
+
+	always @(posedge clk) begin
+		if (rst) mipValue <= 32'b0;
+		else begin
+			if (isTrap && isInterrupt) mipValue <= mipLoadValue;
+			else if (mipWriteDataEnable) mipValue <= mipWriteData;
+		end
+	end
+
+	assign requestOutput = mstatusRequestOutput 
+						|| mieRequestOutput 
+						|| mtvecRequestOutput 
+						|| mscratchRequestOutput 
+						|| mepcRequestOutput
+						|| mcauseRequestOutput
+						|| mtvalRequestOutput
+						|| mipRequestOutput;
+
+	always @(*) begin
+		case (1'b1)
+			mstatusRequestOutput: csrReadData <= mstatusReadData;
+			mieRequestOutput: csrReadData <= mieReadData;
+			mtvecRequestOutput: csrReadData <= mtvecReadData;
+			mscratchRequestOutput: csrReadData <= mscratchReadData;
+			mepcRequestOutput: csrReadData <= mepcReadData;
+			mcauseRequestOutput: csrReadData <= mcauseReadData;
+			mtvalRequestOutput: csrReadData <= mtvalReadData;
+			mipRequestOutput: csrReadData <= mipReadData;
+			default: csrReadData <= 32'b0;
+		endcase
+	end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/ExperiarCore/CoreManagement.v b/verilog/rtl/ExperiarCore/CoreManagement.v
index 4130065..6b1748b 100644
--- a/verilog/rtl/ExperiarCore/CoreManagement.v
+++ b/verilog/rtl/ExperiarCore/CoreManagement.v
@@ -4,6 +4,7 @@
 
 		// Interface to core
 		output wire management_run,
+		output wire management_trapEnable,
 		output wire management_writeEnable,
 		output wire[3:0] management_byteSelect,
 		output wire[15:0] management_address,
@@ -11,7 +12,12 @@
 		input wire[31:0] management_readData,
 
 		// Core state
-		input wire[3:0] core_errorCode,
+		input wire[1:0] core_env,
+		input wire[1:0] core_errorCode,
+
+		// Address breakpoint
+		output wire isAddressBreakpoint,
+		input wire[31:0] coreAddress,
 
 		// Interface from jtag
 		input wire jtag_management_writeEnable,
@@ -31,6 +37,10 @@
 		output wire wb_management_busy
 	);
 
+	// TODO instruction breakpoints
+	assign isAddressBreakpoint = 0;
+	//assign isAddressBreakpoint = coreAddress == instructionBreakpointAddress;
+
 	// Master select
 	wire jtagSelect = jtag_management_writeEnable || jtag_management_readEnable;
 	wire wbRequest = wb_management_writeEnable || wb_management_readEnable;
@@ -55,11 +65,12 @@
 
 	// Registers
 	// Control register: Default 0x0
-	// b00: Run
-	wire control;
+	// b00: run
+	// b01: trapEnable
+	wire[1:0] control;
 	wire[31:0] controlOutputData;
 	wire controlOutputRequest;
-	ConfigurationRegister #(.WIDTH(1), .ADDRESS(12'h000), .DEFAULT(1'b0)) controlRegister(
+	ConfigurationRegister #(.WIDTH(2), .ADDRESS(12'h000), .DEFAULT(2'b0)) controlRegister(
 		.clk(clk),
 		.rst(rst),
 		.enable(registerEnable),
@@ -96,12 +107,13 @@
 		.writeData(stateWriteData_nc),
 		.writeData_en(stateWriteDataEnable_nc),
 		.writeData_busy(1'b0),
-		.readData({ management_run, core_errorCode }),
+		.readData({ management_run, core_env, core_errorCode }),
 		.readData_en(stateReadDataEnable_nc),
 		.readData_busy(1'b0));
 
 	// Core
-	assign management_run = control;
+	assign management_run = control[0];
+	assign management_trapEnable = control[1];
 	assign management_writeEnable = coreEnable && peripheralBus_we;
 	assign management_byteSelect = peripheralBus_byteSelect;
 	assign management_address = peripheralBus_address[15:0];
diff --git a/verilog/rtl/ExperiarCore/ExperiarCore_top.v b/verilog/rtl/ExperiarCore/ExperiarCore_top.v
index 12ea0d4..aaa6519 100644
--- a/verilog/rtl/ExperiarCore/ExperiarCore_top.v
+++ b/verilog/rtl/ExperiarCore/ExperiarCore_top.v
@@ -18,6 +18,9 @@
 		input wire jtag_tdi,
 		output wire jtag_tdo,
 
+		// Interrupts
+		//input wire[15:0] userInterrupts,
+
 		// Wishbone master interface from core
 		output wire core_wb_cyc_o,
 		output wire core_wb_stb_o,
@@ -59,9 +62,10 @@
 
 		// Logic probes
 		output wire[1:0] probe_state,
+		output wire[1:0] probe_env,
 		output wire[31:0] probe_programCounter,
 		output wire[6:0] probe_opcode,
-		output wire[3:0] probe_errorCode,
+		output wire[1:0] probe_errorCode,
 		output wire probe_isBranch,
 		output wire probe_takeBranch,
 		output wire probe_isStore,
@@ -96,7 +100,46 @@
 	localparam CORE_EXTENSIONS_SHORT = 14'b00_0001_0000_0000;
 	localparam CORE_VERSION = 8'h00;
 
+	// Core
+	// Memory interface from core
+	wire coreMemoryWriteEnable;
+	wire coreMemoryReadEnable;
+	wire[31:0] coreMemoryAddress;
+	wire[3:0] coreMemoryByteSelect;
+	wire[31:0] coreMemoryDataWrite;
+	wire[31:0] coreMemoryDataRead;
+	wire coreMemoryBusy;
+
+	// Memory interface from core to local memory
+	wire coreLocalMemoryWriteEnable;
+	wire coreLocalMemoryReadEnable;
+	wire[23:0] coreLocalMemoryAddress;
+	wire[3:0] coreLocalMemoryByteSelect;
+	wire[31:0] coreLocalMemoryDataWrite;
+	wire[31:0] coreLocalMemoryDataRead;
+	wire coreLocalMemoryBusy;
+
+	// Memory interface from core to wb
+	wire coreWBWriteEnable;
+	wire coreWBReadEnable;
+	wire[27:0] coreWBAddress;
+	wire[3:0] coreWBByteSelect;
+	wire[31:0] coreWBDataWrite;
+	wire[31:0] coreWBDataRead;
+	wire coreWBBusy;
+
+	// Memory interface from wb to local memory
+	wire wbLocalMemoryWriteEnable;
+	wire wbLocalMemoryReadEnable;
+	wire[23:0] wbLocalMemoryAddress;
+	wire[3:0] wbLocalMemoryByteSelect;
+	wire[31:0] wbLocalMemoryDataWrite;
+	wire[31:0] wbLocalMemoryDataRead;
+	wire wbLocalMemoryBusy;
+
+	// Core management
 	wire management_run;
+	wire management_trapEnable;
 	wire management_writeEnable;
 	wire[3:0] management_byteSelect;
 	wire[15:0] management_address;
@@ -137,15 +180,20 @@
 		.management_readData(jtag_management_readData),
 		.probe_jtagInstruction(probe_jtagInstruction));
 
+	wire isAddressBreakpoint;
 	CoreManagement coreManagement(
 		.clk(wb_clk_i),
 		.rst(wb_rst_i),
 		.management_run(management_run),
+		.management_trapEnable(management_trapEnable),
 		.management_writeEnable(management_writeEnable),
 		.management_byteSelect(management_byteSelect),
 		.management_address(management_address),
 		.management_writeData(management_writeData),
 		.management_readData(management_readData),
+		.isAddressBreakpoint(isAddressBreakpoint),
+		.coreAddress(coreMemoryAddress),
+		.core_env(probe_env),
 		.core_errorCode(probe_errorCode),
 		.jtag_management_writeEnable(jtag_management_writeEnable),
 		.jtag_management_readEnable(jtag_management_readEnable),
@@ -162,42 +210,7 @@
 		.wb_management_busy(wb_management_busy));
 
 	// Core
-	// Memory interface from core
-	wire coreMemoryWriteEnable;
-	wire coreMemoryReadEnable;
-	wire[31:0] coreMemoryAddress;
-	wire[3:0] coreMemoryByteSelect;
-	wire[31:0] coreMemoryDataWrite;
-	wire[31:0] coreMemoryDataRead;
-	wire coreMemoryBusy;
-
-	// Memory interface from core to local memory
-	wire coreLocalMemoryWriteEnable;
-	wire coreLocalMemoryReadEnable;
-	wire[23:0] coreLocalMemoryAddress;
-	wire[3:0] coreLocalMemoryByteSelect;
-	wire[31:0] coreLocalMemoryDataWrite;
-	wire[31:0] coreLocalMemoryDataRead;
-	wire coreLocalMemoryBusy;
-
-	// Memory interface from core to wb
-	wire coreWBWriteEnable;
-	wire coreWBReadEnable;
-	wire[27:0] coreWBAddress;
-	wire[3:0] coreWBByteSelect;
-	wire[31:0] coreWBDataWrite;
-	wire[31:0] coreWBDataRead;
-	wire coreWBBusy;
-
-	// Memory interface from wb to local memory
-	wire wbLocalMemoryWriteEnable;
-	wire wbLocalMemoryReadEnable;
-	wire[23:0] wbLocalMemoryAddress;
-	wire[3:0] wbLocalMemoryByteSelect;
-	wire[31:0] wbLocalMemoryDataWrite;
-	wire[31:0] wbLocalMemoryDataRead;
-	wire wbLocalMemoryBusy;
-
+	wire[15:0] userInterrupts = 16'b0;
 	RV32ICore core(
 `ifdef USE_POWER_PINS
 		.vccd1(vccd1),	// User area 1 1.8V power
@@ -213,6 +226,7 @@
 		.memoryDataRead(coreMemoryDataRead),
 		.memoryBusy(coreMemoryBusy),
 		.management_run(management_run),
+		.management_trapEnable(management_trapEnable),
 		.management_writeEnable(management_writeEnable),
 		.management_byteSelect(management_byteSelect),
 		.management_address(management_address),
@@ -223,7 +237,12 @@
 		.partID(partID),
 		.versionID(versionID),
 		.extensions(CORE_EXTENSIONS),
+		.eCall(eCall),
+		.eBreak(eBreak),
+		.isAddressBreakpoint(isAddressBreakpoint),
+		.userInterrupts(userInterrupts),
 		.probe_state(probe_state),
+		.probe_env(probe_env),
 		.probe_programCounter(probe_programCounter),
 		.probe_opcode(probe_opcode),
 		.probe_errorCode(probe_errorCode),
diff --git a/verilog/rtl/ExperiarCore/RV32ICore.v b/verilog/rtl/ExperiarCore/RV32ICore.v
index 4017da8..3fb2c65 100644
--- a/verilog/rtl/ExperiarCore/RV32ICore.v
+++ b/verilog/rtl/ExperiarCore/RV32ICore.v
@@ -18,6 +18,7 @@
 
 		// Management interface
 		input wire management_run,
+		input wire management_trapEnable,
 		input wire management_writeEnable,
 		input wire[3:0] management_byteSelect,
 		input wire[15:0] management_address,
@@ -31,11 +32,20 @@
 		input wire[3:0] versionID,
 		input wire[25:0] extensions,
 
+		// System commands
+		output wire eCall,
+		output wire eBreak,
+
+		// Traps
+		input wire isAddressBreakpoint,
+		input wire[15:0] userInterrupts,
+
 		// Logic probes
 		output wire[1:0] probe_state,
+		output wire[1:0] probe_env,
 		output wire[31:0] probe_programCounter,
 		output wire[6:0] probe_opcode,
-		output wire[3:0] probe_errorCode,
+		output wire[1:0] probe_errorCode,
 		output wire probe_isBranch,
 		output wire probe_takeBranch,
 		output wire probe_isStore,
@@ -43,13 +53,13 @@
 		output wire probe_isCompressed
     );
 
-	localparam STATE_HALT 	 = 2'b00;
-	localparam STATE_FETCH   = 2'b10;
-	localparam STATE_EXECUTE = 2'b11;
+	localparam STATE_HALT 	 	= 2'b00;
+	localparam STATE_FETCH   	= 2'b10;
+	localparam STATE_EXECUTE 	= 2'b11;
 
 	// System registers
 	reg[1:0] state = STATE_HALT;
-	reg[3:0] currentError = 4'b0;
+	reg[1:0] currentError = 2'b0;
 	reg[31:0] programCounter = 32'b0;
 	reg[31:0] currentInstruction = 32'b0;
 	reg[31:0] registers [0:31];
@@ -61,6 +71,7 @@
 
 	wire management_selectProgramCounter      = (management_address[15:14] == MANAGMENT_ADDRESS_SYSTEM) && (management_address[13:4] == 10'h000);
 	wire management_selectInstructionRegister = (management_address[15:14] == MANAGMENT_ADDRESS_SYSTEM) && (management_address[13:4] == 10'h001);
+	wire management_selectClearError		  = (management_address[15:14] == MANAGMENT_ADDRESS_SYSTEM) && (management_address[13:4] == 10'h002);
 	wire management_selectRegister            = (management_address[15:14] == MANAGMENT_ADDRESS_REGISTERS) && (management_address[13:7] == 7'h00);
 	wire management_selectCSR 				  = management_address[15:14] == MANAGMENT_ADDRESS_CSR;
 
@@ -69,6 +80,7 @@
 	wire management_writeProgramCounter_set = management_writeProgramCounter && (management_address[3:0] == 4'h0);
 	wire management_writeProgramCounter_jump = management_writeProgramCounter && (management_address[3:0] == 4'h4);
 	wire management_writeProgramCounter_step = management_writeProgramCounter && (management_address[3:0] == 4'h8);
+	wire management_writeClearError = management_writeValid && management_selectClearError;
 	wire management_writeRegister = management_writeValid && management_selectRegister;
 	wire management_writeCSR = management_writeValid && management_selectCSR;
 
@@ -103,33 +115,20 @@
 		management_byteSelect[0] ? management_dataOut[7:0]   : 8'h00
 	};
 
-	// CSR
-	// Core interface
+	// CSR interface
 	wire coreCSRWrite;
 	wire coreCSRRead;
 	wire[11:0] coreCSRIndex = currentInstruction[31:20];
 	reg[32:0] coreCSRWriteData;
-
-	// Combined interface
-	wire csrWriteEnable = management_writeCSR || (management_run && coreCSRWrite);
-	wire csrReadEnable = management_readCSR || (management_run && coreCSRRead);
+	wire csrWriteEnable = management_writeCSR || (management_run && coreCSRWrite && (state == STATE_EXECUTE));
+	wire csrReadEnable = management_readCSR || (management_run && coreCSRRead && (state == STATE_EXECUTE));
 	wire[11:0] csrAddress = !management_run ? management_csrIndex : coreCSRIndex;
 	wire[31:0] csrWriteData = !management_run ? management_writeData : coreCSRWriteData;
 	wire[31:0] csrReadData;
-	CSR csr(
-		.clk(clk),
-		.rst(rst),
-		.csrWriteEnable(csrWriteEnable),
-		.csrReadEnable(csrReadEnable),
-		.csrAddress(csrAddress),
-		.csrWriteData(csrWriteData),
-		.csrReadData(csrReadData),
-		.coreIndex(coreIndex),
-		.manufacturerID(manufacturerID),
-		.partID(partID),
-		.versionID(versionID),
-		.extensions(extensions),
-		.instructionCompleted(instructionCompleted));
+
+	wire[31:0] trapVector;
+	wire[31:0] trapReturnVector;
+	wire inTrap;
 
 	// Immediate Decode
 	wire[31:0] imm_I = {currentInstruction[31] ? 21'h1F_FFFF : 21'h00_0000, currentInstruction[30:25], currentInstruction[24:21], currentInstruction[20]};
@@ -171,9 +170,11 @@
 	wire isCSRRC = isCSR && (funct3[1:0] == 2'b11);
 	wire isECALL  = isSystem && (currentInstruction[31:7] == 25'b0000000000000000000000000);
 	wire isEBREAK = isSystem && (currentInstruction[31:7] == 25'b0000000000010000000000000);
+	wire isRET    = isSystem && (currentInstruction[31:7] == 25'b0011000000100000000000000);
+
+	wire validSystemCommand = isCSR || isECALL || isEBREAK || isRET;
 
 	reg invalidInstruction;
-
 	always @(*) begin
 		case ({ isLUI, isAUIPC, isJAL, isJALR, isBranch, isLoad, isStore, isALUImm, isALU, isFENCE, isSystem })
 			'b00000000001: invalidInstruction <= 1'b0;
@@ -186,11 +187,13 @@
 			'b00010000000: invalidInstruction <= 1'b0;
 			'b00100000000: invalidInstruction <= 1'b0;
 			'b01000000000: invalidInstruction <= 1'b0;
-			'b10000000000: invalidInstruction <= 1'b0;
+			'b10000000000: invalidInstruction <= validSystemCommand;
 			default: invalidInstruction <= 1'b1;
 		endcase
 	end
 
+	wire isInvalidInstruction = invalidInstruction && state == STATE_EXECUTE;
+
 	// Integer Registers
 	wire[31:0] rs1 = |rs1Index ? registers[rs1Index] : 32'b0;
 	wire[31:0] rs2 = |rs2Index ? registers[rs2Index] : 32'b0;
@@ -236,9 +239,10 @@
 										  isJALR		  		   ? imm_I :
 										  (isBranch && takeBranch) ? imm_B :
 																     32'b0;
-	wire[31:0] nextProgramCounterFull = nextProgramCounterBase + nextProgramCounterOffset;
+	wire[31:0] nextProgramCounterWord = nextProgramCounterBase + nextProgramCounterOffset;
 	wire[31:0] nextProgramCounterCompressed = programCounterLink; // TODO: Need to implement compressed branch and jump instructions
-	wire[31:0] nextProgramCounter = isCompressed ? nextProgramCounterCompressed : nextProgramCounterFull;
+	wire[31:0] nextProgramCounterFull = isCompressed ? nextProgramCounterCompressed : nextProgramCounterWord;
+	wire[31:0] nextProgramCounter = { nextProgramCounterFull[31:1] , 1'b0};
 
 	// ALU	
 	wire aluAlt = funct7 == 7'b0100000 && (isALU || isALUImmShift);
@@ -278,7 +282,7 @@
 	assign coreCSRWrite = isCSRRW || (isCSR && |rs1Index);
 	assign coreCSRRead = isCSRRC || isCSRRS || (isCSR && |rdIndex);
 
-	wire csrRS1Data = isCSRIMM ? { 27'b0, rs1Index} : rs1;
+	wire[31:0] csrRS1Data = isCSRIMM ? { 27'b0, rs1Index} : rs1;
 
 	always @(*) begin
 		if (isCSR) begin			
@@ -340,6 +344,7 @@
 	wire[6:0] loadStoreByteMask = {3'b0, baseByteMask} << targetMemoryAddress[1:0];
 	wire loadStoreByteMaskValid = |(loadStoreByteMask[3:0]);
 	wire addressMissaligned = |loadStoreByteMask[6:4];
+	wire isAddressMisaligned = addressMissaligned && ((state == STATE_FETCH) || ((state == STATE_EXECUTE) && (isLoad || isStore)));
 	wire shouldLoad  = loadStoreByteMaskValid && !addressMissaligned && ((state == STATE_FETCH) || ((state == STATE_EXECUTE) && isLoad));
 	wire shouldStore = loadStoreByteMaskValid && !addressMissaligned && ((state == STATE_EXECUTE) && isStore);
 	assign memoryAddress = shouldLoad || shouldStore ? { targetMemoryAddress[31:2], 2'b00 } : 32'b0;
@@ -424,13 +429,14 @@
 	wire memoryWriteDone = shouldStore ? !memoryBusy : 1'b0;
 
 	// Register Write
-	wire integerRegisterWriteEn = isLUI || isAUIPC || isJAL || isJALR || isALU || isALUImm || isLoad;
+	wire integerRegisterWriteEn = isLUI || isAUIPC || isJAL || isJALR || isALU || isALUImm || isLoad || csrReadEnable;
 	wire[31:0] integerRegisterWriteData = isLUI 			  ? imm_U			   :
 										  isAUIPC 			  ? aluAPlusB 		   :
 										  isJAL 			  ? programCounterLink :
 										  isJALR 			  ? programCounterLink :
 										  isLoad 			  ? loadData		   :
 										  (isALU || isALUImm) ? aluValue 		   :
+										  csrReadEnable		  ? csrReadData 	   :
 																32'b0;
 
 	wire progressExecute = isStore ? memoryWriteDone :
@@ -445,47 +451,100 @@
 			programCounter <= 32'b0;
 			currentInstruction <= 32'b0;
 		end else begin
-			if (!(|currentError)) begin
-				case (state)
-					STATE_HALT: begin
-						if (management_allowInstruction) state <= STATE_FETCH;
-						else begin
-							if (management_writeProgramCounter_set) programCounter <= { management_writeData[31:1] , 1'b0};
-							else if (management_writeProgramCounter_jump) programCounter <= { management_jumpTarget[31:1] , 1'b0};
-							else if (management_writeRegister) registers[management_registerIndex] <= management_writeData;
-						end
+			case (state)
+				STATE_HALT: begin
+					if (management_allowInstruction && !(|currentError)) state <= STATE_FETCH;
+					else begin
+						if (management_writeProgramCounter_set) programCounter <= { management_writeData[31:1] , 1'b0};
+						else if (management_writeProgramCounter_jump) programCounter <= { management_jumpTarget[31:1] , 1'b0};
+						else if (management_writeRegister) registers[management_registerIndex] <= management_writeData;
+						else if (management_writeClearError) currentError <= 2'b0;
 					end
+				end
 
-					STATE_FETCH: begin
-						if (memoryReadReady) begin
+				STATE_FETCH: begin
+					if (|currentError) begin
+						state <= STATE_HALT;
+					end else begin
+						if (inTrap) programCounter <= trapVector;
+						else if (memoryReadReady) begin
 							currentInstruction <= dataIn;
 							state <= STATE_EXECUTE;
 						end
 					end
+				end
 
-					STATE_EXECUTE: begin
-						if (addressMissaligned || invalidInstruction) begin
-							currentError <= { 1'b0, 1'b0, addressMissaligned, invalidInstruction };
-						end else begin
-							if (progressExecute) begin
-								if (integerRegisterWriteEn && |rdIndex) registers[rdIndex] <= integerRegisterWriteData;
+				STATE_EXECUTE: begin
+					if (!management_trapEnable && (isAddressMisaligned || isInvalidInstruction)) begin
+						currentError <= { isAddressMisaligned, isInvalidInstruction };
+						state <= STATE_HALT;
+					end else begin
+						if (progressExecute) begin
+							if (integerRegisterWriteEn && |rdIndex) registers[rdIndex] <= integerRegisterWriteData;
 
-								programCounter <= { nextProgramCounter[31:1] , 1'b0};
-
-								if (management_allowInstruction) state <= STATE_FETCH;
-								else state <= STATE_HALT;
+							if (management_trapEnable) begin
+								if (inTrap) programCounter <= trapVector;
+								else if (isRET) programCounter <= trapReturnVector;
+								else programCounter <= nextProgramCounter;
+							end else begin
+								programCounter <= nextProgramCounter;
 							end
+							
+							if (management_allowInstruction) state <= STATE_FETCH;
+							else state <= STATE_HALT;
 						end
 					end
+				end
 
-					default: state <= STATE_HALT;
-				endcase
-			end
+				default: state <= STATE_HALT;
+			endcase
 		end
 	end
 
+	// System commands 
+	assign eCall = isECALL && (state == STATE_EXECUTE);
+	assign eBreak = isEBREAK && (state == STATE_EXECUTE);
+	wire trapReturn = isRET && (state == STATE_EXECUTE);
+
+	// CSRs
+	wire instructionCompleted = (state == STATE_EXECUTE) && progressExecute;
+	CSR csr(
+		.clk(clk),
+		.rst(rst),
+		.csrWriteEnable(csrWriteEnable),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrWriteData(csrWriteData),
+		.csrReadData(csrReadData),
+		.coreIndex(coreIndex),
+		.manufacturerID(manufacturerID),
+		.partID(partID),
+		.versionID(versionID),
+		.extensions(extensions),
+		.instructionCompleted(instructionCompleted),
+		.coreState(state),
+		.programCounter(programCounter),
+		.currentInstruction(currentInstruction),
+		.isLoad(isLoad),
+		.isStore(isStore),
+		.isMachineTimerInterrupt(isMachineTimerInterrupt),
+		.isMachineExternalInterrupt(isMachineExternalInterrupt),
+		.isMachineSoftwareInterrupt(isMachineSoftwareInterrupt),
+		.isAddressMisaligned(isAddressMisaligned),
+		.isAccessFault(isAccessFault),
+		.isInvalidInstruction(isInvalidInstruction),
+		.isEBREAK(eBreak),
+		.isECALL(eCall),
+		.isAddressBreakpoint(isAddressBreakpoint),
+		.userInterrupts(userInterrupts),
+		.trapReturn(trapReturn),
+		.inTrap(inTrap),
+		.trapVector(trapVector),
+		.trapReturnVector(trapReturnVector));
+
 	// Debug
 	assign probe_state = state;
+	assign probe_env = { eCall, eBreak };
 	assign probe_programCounter = programCounter;
 	assign probe_opcode = opcode;
 	assign probe_errorCode = currentError;
diff --git a/verilog/rtl/ExperiarSoC/ExperiarSoC_top.v b/verilog/rtl/ExperiarSoC/ExperiarSoC_top.v
index 1521abc..ff06ba0 100644
--- a/verilog/rtl/ExperiarSoC/ExperiarSoC_top.v
+++ b/verilog/rtl/ExperiarSoC/ExperiarSoC_top.v
@@ -339,9 +339,10 @@
 
 	// Logic probes
 	wire[1:0] probe_core0_state;
+	wire[1:0] probe_core0_env;
 	wire[31:0] probe_core0_programCounter;
 	wire[6:0] probe_core0_opcode;
-	wire[3:0] probe_core0_errorCode;
+	wire[1:0] probe_core0_errorCode;
 	wire probe_core0_isBranch;
 	wire probe_core0_takeBranch;
 	wire probe_core0_isStore;
@@ -351,6 +352,7 @@
 
 	wire[54:0] probe_core0 = {
 		probe_core0_state,
+		probe_core0_env,
 		probe_core0_programCounter,
 		probe_core0_opcode,
 		probe_core0_errorCode,
@@ -409,6 +411,7 @@
 		.addr1(core0SRAM_addr1),
 		.dout1(core0SRAM_dout1),
 		.probe_state(probe_core0_state),
+		.probe_env(probe_core0_env),
 		.probe_programCounter(probe_core0_programCounter),
 		.probe_opcode(probe_core0_opcode),
 		.probe_errorCode(probe_core0_errorCode),
@@ -485,9 +488,10 @@
 
 	// Logic probes
 	wire[1:0] probe_core1_state;
+	wire[1:0] probe_core1_env;
 	wire[31:0] probe_core1_programCounter;
 	wire[6:0] probe_core1_opcode;
-	wire[3:0] probe_core1_errorCode;
+	wire[1:0] probe_core1_errorCode;
 	wire probe_core1_isBranch;
 	wire probe_core1_takeBranch;
 	wire probe_core1_isStore;
@@ -497,6 +501,7 @@
 
 	wire[54:0] probe_core1 = {
 		probe_core1_state,
+		probe_core1_env,
 		probe_core1_programCounter,
 		probe_core1_opcode,
 		probe_core1_errorCode,
@@ -555,6 +560,7 @@
 		.addr1(core1SRAM_addr1),
 		.dout1(core1SRAM_dout1),
 		.probe_state(probe_core1_state),
+		.probe_env(probe_core1_env),
 		.probe_programCounter(probe_core1_programCounter),
 		.probe_opcode(probe_core1_opcode),
 		.probe_errorCode(probe_core1_errorCode),