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;