Added CSR registers to core. These include the basic counters and status registers.
diff --git a/verilog/includes/includes.rtl.caravel_user_project b/verilog/includes/includes.rtl.caravel_user_project
index f9e86c2..0051722 100644
--- a/verilog/includes/includes.rtl.caravel_user_project
+++ b/verilog/includes/includes.rtl.caravel_user_project
@@ -6,6 +6,11 @@
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/ExperiarCore_top.v 
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/CoreManagement.v 
 -v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/RV32ICore.v 
+-v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/CSR/CSR.v 
+-v $(USER_PROJECT_VERILOG)/rtl/ExperiarCore/CSR/CSR_ConfigurationRegister.v 
+-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/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
new file mode 100644
index 0000000..0e714d9
--- /dev/null
+++ b/verilog/rtl/ExperiarCore/CSR/CSR.v
@@ -0,0 +1,150 @@
+module CSR (
+		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,
+
+		// System interface
+		input wire[7:0] coreIndex,
+		input wire[10:0] manufacturerID,
+		input wire[15:0] partID,
+		input wire[3:0] versionID,
+		input wire[25:0] extensions,
+		input wire instructionCompleted
+	);
+
+	// Cylce
+	wire[63:0] cycleCount;
+	wire[31:0] cycleTimerReadData;
+	wire cycleTimerRequestOutput;
+	CSR_TimerRegister #(.ADDRESS_LOWER(12'hC00), .ADDRESS_UPPER(12'hC80)) cycleTimer (
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(cycleTimerReadData),
+		.csrRequestOutput(cycleTimerRequestOutput),
+		.count(1'b1),
+		.value(cycleCount));
+
+	// Time
+	// Time register is duplicate of cycle register
+	wire[31:0] timeTimerReadDataLower;
+	wire timeTimerRequestOutputLower;
+	CSR_ReadRegister #(.ADDRESS(12'hC01)) timeTimerLower(
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(timeTimerReadDataLower),
+		.csrRequestOutput(timeTimerRequestOutputLower),
+		.value(cycleCount[31:0]));
+
+	wire[31:0] timeTimerReadDataUpper;
+	wire timeTimerRequestOutputUpper;
+	CSR_ReadRegister #(.ADDRESS(12'hC81)) timeTimerUpper(
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(timeTimerReadDataUpper),
+		.csrRequestOutput(timeTimerRequestOutputUpper),
+		.value(cycleCount[63:32]));
+
+	// Instret
+	wire[31:0] instretTimerReadData;
+	wire instretTimerRequestOutput;
+	CSR_TimerRegister #(.ADDRESS_LOWER(12'hC02), .ADDRESS_UPPER(12'hC82)) instretTimer (
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(instretTimerReadData),
+		.csrRequestOutput(instretTimerRequestOutput),
+		.count(instructionCompleted));
+
+	// Vendor ID
+	wire[31:0] vendorIDReadData;
+	wire vendorIDRequestOutput;
+	CSR_ReadRegister #(.ADDRESS(12'hC01)) vendorID(
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(vendorIDReadData),
+		.csrRequestOutput(vendorIDRequestOutput),
+		.value({ 21'b0, manufacturerID }));
+
+	// Architecture ID
+	wire[31:0] archIDReadData;
+	wire archIDRequestOutput;
+	CSR_ReadRegister #(.ADDRESS(12'hC01)) archID(
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(archIDReadData),
+		.csrRequestOutput(archIDRequestOutput),
+		.value({ 16'b0, partID }));
+
+	// Implementation ID
+	wire[31:0] implIDReadData;
+	wire implIDRequestOutput;
+	CSR_ReadRegister #(.ADDRESS(12'hC01)) implID(
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(implIDReadData),
+		.csrRequestOutput(implIDRequestOutput),
+		.value({ 28'b0, versionID }));
+
+	// Hardware thread ID
+	wire[31:0] coreIDReadData;
+	wire coreIDRequestOutput;
+	CSR_ReadRegister #(.ADDRESS(12'hC01)) coreID(
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(coreIDReadData),
+		.csrRequestOutput(coreIDRequestOutput),
+		.value({ 24'b0, coreIndex }));
+
+	// ISA
+	wire[31:0] misaReadData;
+	wire misaRequestOutput;
+	CSR_ReadRegister #(.ADDRESS(12'hC01)) misa(
+		.clk(clk),
+		.rst(rst),
+		.csrReadEnable(csrReadEnable),
+		.csrAddress(csrAddress),
+		.csrReadData(misaReadData),
+		.csrRequestOutput(misaRequestOutput),
+		.value({ 2'b01, 4'b0, extensions }));
+
+	always @(*) begin
+		case (1'b1)
+			// Timers
+			cycleTimerRequestOutput: csrReadData <= cycleTimerReadData;
+			timeTimerRequestOutputLower: csrReadData <= timeTimerReadDataLower;
+			timeTimerRequestOutputUpper: csrReadData <= timeTimerReadDataUpper;
+			instretTimerRequestOutput: csrReadData <= instretTimerReadData;
+			
+			// Machine info
+			vendorIDRequestOutput: csrReadData <= vendorIDReadData;
+			archIDRequestOutput: csrReadData <= archIDReadData;
+			implIDRequestOutput: csrReadData <= implIDReadData;
+			coreIDRequestOutput: csrReadData <= coreIDReadData;
+			misaRequestOutput: csrReadData <= misaReadData;
+
+			default: csrReadData <= 32'b0;
+		endcase
+	end
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/ExperiarCore/CSR/CSR_ConfigurationRegister.v b/verilog/rtl/ExperiarCore/CSR/CSR_ConfigurationRegister.v
new file mode 100644
index 0000000..973c079
--- /dev/null
+++ b/verilog/rtl/ExperiarCore/CSR/CSR_ConfigurationRegister.v
@@ -0,0 +1,37 @@
+module CSR_ConfigurationRegister #(
+		parameter ADDRESS = 12'h000,
+		parameter DEFAULT = 32'b0
+	)(
+		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 csrRequestOutput,
+
+		// System interface
+		output wire[31:0] value
+	);
+	
+	wire csrEnabled = csrAddress == ADDRESS;
+
+	reg[31:0] currentValue = DEFAULT;
+
+	always @(posedge clk) begin
+		if (rst) begin
+			currentValue <= DEFAULT;
+		end else begin
+			if (csrEnabled && csrWriteEnable) currentValue <= csrWriteData;
+		end
+	end
+
+	assign csrReadData = csrEnabled && csrReadEnable ? currentValue : 32'b0;
+	assign csrRequestOutput = csrEnabled && csrReadEnable;
+
+	assign value = currentValue;
+	
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/ExperiarCore/CSR/CSR_DataRegister.v b/verilog/rtl/ExperiarCore/CSR/CSR_DataRegister.v
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/verilog/rtl/ExperiarCore/CSR/CSR_DataRegister.v
diff --git a/verilog/rtl/ExperiarCore/CSR/CSR_ReadRegister.v b/verilog/rtl/ExperiarCore/CSR/CSR_ReadRegister.v
new file mode 100644
index 0000000..a09e2ce
--- /dev/null
+++ b/verilog/rtl/ExperiarCore/CSR/CSR_ReadRegister.v
@@ -0,0 +1,21 @@
+module CSR_ReadRegister #(
+		parameter ADDRESS = 12'h000
+	)(
+		input wire clk,
+		input wire rst,
+
+		// CSR interface
+		input wire csrReadEnable,
+		input wire[11:0] csrAddress,
+		output wire[31:0] csrReadData,
+		output wire csrRequestOutput,
+
+		// System interface
+		input wire[31:0] value
+	);
+	
+	wire csrEnabled = csrAddress == ADDRESS;
+	assign csrReadData = csrEnabled && csrReadEnable ? value : 32'b0;
+	assign csrRequestOutput = csrEnabled && csrReadEnable;
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/ExperiarCore/CSR/CSR_TimerRegister.v b/verilog/rtl/ExperiarCore/CSR/CSR_TimerRegister.v
new file mode 100644
index 0000000..fba2a89
--- /dev/null
+++ b/verilog/rtl/ExperiarCore/CSR/CSR_TimerRegister.v
@@ -0,0 +1,46 @@
+module CSR_TimerRegister #(
+		parameter ADDRESS_LOWER = 12'h000,
+		parameter ADDRESS_UPPER = 12'h000
+	)(
+		input wire clk,
+		input wire rst,
+
+		// CSR interface
+		input wire csrReadEnable,
+		input wire[11:0] csrAddress,
+		output reg[31:0] csrReadData,
+		output wire csrRequestOutput,
+
+		// System interface
+		input wire count,
+		output wire[63:0] value
+	);
+	
+	wire csrEnabledLower = csrAddress == ADDRESS_LOWER;
+	wire csrEnabledUpper = csrAddress == ADDRESS_UPPER;
+
+	reg[63:0] currentValue = 64'b0;
+
+	always @(posedge clk) begin
+		if (rst) begin
+			currentValue <= 64'b0;
+		end else begin
+			if (count) currentValue <= currentValue + 1;
+		end
+	end
+
+	always @(*) begin
+		if (csrReadEnable) begin
+			if (csrEnabledLower) csrReadData <= currentValue[31:0];
+			else if (csrEnabledUpper) csrReadData <= currentValue[63:32];
+			else csrReadData <= 32'b0;
+		end else begin
+			csrReadData <= 32'b0;
+		end 
+	end
+
+	assign csrRequestOutput = (csrEnabledLower || csrEnabledUpper) && csrReadEnable;
+	
+	assign value = currentValue;
+	
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/ExperiarCore/ExperiarCore_top.v b/verilog/rtl/ExperiarCore/ExperiarCore_top.v
index 80c12e1..12ea0d4 100644
--- a/verilog/rtl/ExperiarCore/ExperiarCore_top.v
+++ b/verilog/rtl/ExperiarCore/ExperiarCore_top.v
@@ -92,7 +92,8 @@
 	// 18			 | 12 	   | S 		   | Supervisor mode implemented
 	// 20			 | 13 	   | U 		   | User mode implemented
 	localparam CORE_MXL = 2'h1;
-	localparam CORE_EXTENSIONS = 14'b00_0001_0000_0000;
+	localparam CORE_EXTENSIONS = 26'b00_0000_0000_0000_0001_0000_0000;
+	localparam CORE_EXTENSIONS_SHORT = 14'b00_0001_0000_0000;
 	localparam CORE_VERSION = 8'h00;
 
 	wire management_run;
@@ -120,7 +121,7 @@
 	JTAG jtag(
 		.clk(wb_clk_i),
 		.rst(wb_rst_i),
-		.coreID({ coreIndex, CORE_VERSION, CORE_MXL, CORE_EXTENSIONS }),
+		.coreID({ coreIndex, CORE_VERSION, CORE_MXL, CORE_EXTENSIONS_SHORT }),
 		.manufacturerID(manufacturerID),
 		.partID(partID),
 		.versionID(versionID),
@@ -217,6 +218,11 @@
 		.management_address(management_address),
 		.management_writeData(management_writeData),
 		.management_readData(management_readData),
+		.coreIndex(coreIndex),
+		.manufacturerID(manufacturerID),
+		.partID(partID),
+		.versionID(versionID),
+		.extensions(CORE_EXTENSIONS),
 		.probe_state(probe_state),
 		.probe_programCounter(probe_programCounter),
 		.probe_opcode(probe_opcode),
diff --git a/verilog/rtl/ExperiarCore/RV32ICore.v b/verilog/rtl/ExperiarCore/RV32ICore.v
index 397a732..9df8d12 100644
--- a/verilog/rtl/ExperiarCore/RV32ICore.v
+++ b/verilog/rtl/ExperiarCore/RV32ICore.v
@@ -24,6 +24,13 @@
 		input wire[31:0] management_writeData,
 		output wire[31:0] management_readData,
 
+		// System info
+		input wire[7:0] coreIndex,
+		input wire[10:0] manufacturerID,
+		input wire[15:0] partID,
+		input wire[3:0] versionID,
+		input wire[25:0] extensions,
+
 		// Logic probes
 		output wire[1:0] probe_state,
 		output wire[31:0] probe_programCounter,
@@ -55,7 +62,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_selectRegister            = (management_address[15:14] == MANAGMENT_ADDRESS_REGISTERS) && (management_address[13:7] == 7'h00);
-	//wire management_selectCSR = management_address[15:14] == MANAGMENT_ADDRESS_CSR;
+	wire management_selectCSR 				  = management_address[15:14] == MANAGMENT_ADDRESS_CSR;
 
 	wire management_writeValid = !management_run && management_writeEnable;
 	wire management_writeProgramCounter = management_writeValid && management_selectProgramCounter;
@@ -63,17 +70,18 @@
 	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_writeRegister = management_writeValid && management_selectRegister;
-	//wire management_writeCSR = management_writeValid && management_selectCSR;
+	wire management_writeCSR = management_writeValid && management_selectCSR;
 
 	wire management_readValid = !management_run && !management_writeEnable;
 	wire management_readProgramCounter = management_readValid && management_selectProgramCounter;
 	wire management_readInstructionRegister = management_readValid && management_selectInstructionRegister;
 	wire management_readRegister = management_readValid && management_selectRegister;
-	//wire management_readCSR = management_readValid && management_selectCSR;
+	wire management_readCSR = management_readValid && management_selectCSR;
 
 	wire management_allowInstruction = management_run || management_writeProgramCounter_step;
 
 	wire[4:0] management_registerIndex = management_address[6:2];
+	wire[11:0] management_csrIndex = management_address[13:2];
 	wire[31:0] management_jumpTarget = programCounter + management_writeData;
 
 	reg[31:0] management_dataOut;
@@ -82,8 +90,8 @@
 		case (1'b1)
 			management_readProgramCounter: management_dataOut <= programCounter;
 			management_readInstructionRegister : management_dataOut <= currentInstruction;
-			management_readRegister: management_dataOut <= registers[management_registerIndex];
-			//management_readCSR: management_dataOut <= csr[management_registerIndex];
+			management_readRegister: management_dataOut <= !management_registerIndex ? registers[management_registerIndex] : 32'b0;
+			management_readCSR: management_dataOut <= csrReadData;
 			default: management_dataOut <= 32'b0;
 		endcase
 	end
@@ -95,6 +103,34 @@
 		management_byteSelect[0] ? management_dataOut[7:0]   : 8'h00
 	};
 
+	// CSR
+	// Core 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[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));
+
 	// Immediate Decode
 	wire[31:0] imm_I = {currentInstruction[31] ? 21'h1F_FFFF : 21'h00_0000, currentInstruction[30:25], currentInstruction[24:21], currentInstruction[20]};
 	wire[31:0] imm_S = {currentInstruction[31] ? 21'h1F_FFFF : 21'h00_0000, currentInstruction[30:25], currentInstruction[11:8] , currentInstruction[7]};
@@ -123,9 +159,15 @@
 	wire isALU 	  = (opcode == 7'b0110011) && (funct7 == 7'b0000000 || ((funct7 == 7'b0100000) && (funct3 == 3'b000 || funct3 == 3'b101)));
 	wire isFENCE  = (opcode == 7'b0001111) && (funct3 == 3'b000);
 	wire isSystem = (opcode == 7'b1110011);
-
-	wire isECALL  = isSystem && (currentInstruction == 32'b00000000000000000000000001110011);
-	wire isEBREAK = isSystem && (currentInstruction == 32'b00000000000100000000000001110011);
+	
+	// System commands
+	wire isCSR = isSystem && (funct3 != 3'b000);
+	wire isCSRIMM = isCSR && funct3[2];
+	wire isCSRRW = isCSR && (funct3[1:0] == 2'b01);
+	wire isCSRRS = isCSR && (funct3[1:0] == 2'b10);
+	wire isCSRRC = isCSR && (funct3[1:0] == 2'b11);
+	wire isECALL  = isSystem && (currentInstruction[31:7] == 25'b0000000000000000000000000);
+	wire isEBREAK = isSystem && (currentInstruction[31:7] == 25'b0000000000010000000000000);
 
 	reg invalidInstruction;
 
@@ -226,8 +268,24 @@
 		endcase
 	end
 
-	// Memory connections
+	// CSR data connections
+	assign coreCSRWrite = isCSRRW || (isCSR && |rs1Index);
+	assign coreCSRRead = isCSRRC || isCSRRS || (isCSR && |rdIndex);
 
+	wire csrRS1Data = isCSRIMM ? { 27'b0, rs1Index} : rs1;
+
+	always @(*) begin
+		if (isCSR) begin			
+			if (isCSRRW) coreCSRWriteData <= csrRS1Data;
+			else if (isCSRRS) coreCSRWriteData <= csrReadData | csrRS1Data;
+			else if (isCSRRC) coreCSRWriteData <= csrReadData & ~csrRS1Data;
+			else coreCSRWriteData <= 32'b0;
+		end else begin
+			coreCSRWriteData <= 32'b0;
+		end 
+	end
+
+	// Memory connections
 	wire[31:0] targetMemoryAddress = state == STATE_FETCH   ? programCounter : 
 									 state == STATE_EXECUTE ? aluAPlusB:
 									 						  32'b0;
@@ -333,7 +391,6 @@
 	end
 
 	// Debug
-
 	assign probe_state = state;
 	assign probe_programCounter = programCounter;
 	assign probe_opcode = opcode;