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;