diff --git a/rtl/core/csr_reg.v b/rtl/core/csr_reg.v new file mode 100644 index 0000000..5e59bb6 --- /dev/null +++ b/rtl/core/csr_reg.v @@ -0,0 +1,68 @@ + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +`include "defines.v" + +// csr reg module +module csr_reg( + + input wire clk, + input wire rst, + + input wire we_i, + input wire[`MemAddrBus] raddr_i, + input wire[`MemAddrBus] waddr_i, + input wire[`RegBus] data_i, + + output reg[`RegBus] data_o + + ); + + + localparam CSR_CYCLE = 12'hc00; + localparam CSR_CYCLEH = 12'hc80; + + reg[63:0] cycle; + + + always @ (posedge clk) begin + if (rst == `RstEnable) begin + cycle <= 64'h0; + end else begin + cycle <= cycle + 1'b1; + end + end + + // read reg + always @ (*) begin + if (rst == `RstEnable) begin + data_o <= `ZeroWord; + end else begin + case (raddr_i[11:0]) + CSR_CYCLE: begin + data_o <= cycle[31:0]; + end + CSR_CYCLEH: begin + data_o <= cycle[63:32]; + end + default: begin + data_o <= `ZeroWord; + end + endcase + end + end + +endmodule diff --git a/rtl/core/defines.v b/rtl/core/defines.v index 500f86a..8d26a9d 100644 --- a/rtl/core/defines.v +++ b/rtl/core/defines.v @@ -123,6 +123,15 @@ `define INST_BLTU 3'b110 `define INST_BGEU 3'b111 +// CSR inst +`define INST_CSR 7'b1110011 +`define INST_CSRRW 3'b001 +`define INST_CSRRS 3'b010 +`define INST_CSRRC 3'b011 +`define INST_CSRRWI 3'b101 +`define INST_CSRRSI 3'b110 +`define INST_CSRRCI 3'b111 + `define RomNum 2048 // rom depth(how many words) `define MemNum 2048 // memory depth(how many words) diff --git a/rtl/core/ex.v b/rtl/core/ex.v index 7f18a35..51f8251 100644 --- a/rtl/core/ex.v +++ b/rtl/core/ex.v @@ -28,6 +28,9 @@ module ex( input wire[`RegAddrBus] reg_waddr_i, input wire[`RegBus] reg1_rdata_i, // reg1 read data input wire[`RegBus] reg2_rdata_i, // reg2 read data + input wire csr_we_i, + input wire[`MemAddrBus] csr_waddr_i, + input wire[`RegBus] csr_rdata_i, // from mem input wire[`MemBus] mem_rdata_i, // mem read data @@ -57,6 +60,11 @@ module ex( output wire reg_we_o, // reg write enable output wire[`RegAddrBus] reg_waddr_o, // reg write addr + // to csr reg + output reg[`RegBus] csr_wdata_o, // reg write data + output wire csr_we_o, // reg write enable + output wire[`MemAddrBus] csr_waddr_o, + // to div output reg div_start_o, output reg[`RegBus] div_dividend_o, @@ -90,6 +98,7 @@ module ex( wire[2:0] funct3; wire[6:0] funct7; wire[4:0] rd; + wire[4:0] uimm; reg[`RegBus] reg_wdata; reg reg_we; reg[`RegAddrBus] reg_waddr; @@ -107,6 +116,7 @@ module ex( assign funct3 = inst_i[14:12]; assign funct7 = inst_i[31:25]; assign rd = inst_i[11:7]; + assign uimm = inst_i[19:15]; assign sign_extend_tmp = {{20{inst_i[31]}}, inst_i[31:20]}; assign shift_bits = inst_i[24:20]; @@ -125,6 +135,9 @@ module ex( assign jump_flag_o = jump_flag || div_jump_flag; assign jump_addr_o = jump_addr | div_jump_addr; + assign csr_we_o = csr_we_i; + assign csr_waddr_o = csr_waddr_i; + // handle interrupt always @ (*) begin @@ -307,10 +320,12 @@ module ex( reg_wdata <= `ZeroWord; reg_we <= `WriteDisable; reg_waddr <= `ZeroWord; + csr_wdata_o <= `ZeroWord; end else begin reg_we <= reg_we_i; reg_waddr <= reg_waddr_i; mem_req_o <= `RIB_NREQ; + csr_wdata_o <= `ZeroWord; case (opcode) `INST_TYPE_I: begin @@ -1073,6 +1088,51 @@ module ex( jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + 4'h4; end + `INST_CSR: begin + jump_flag <= `JumpDisable; + hold_flag <= `HoldDisable; + jump_addr <= `ZeroWord; + mem_wdata_o <= `ZeroWord; + mem_raddr_o <= `ZeroWord; + mem_waddr_o <= `ZeroWord; + mem_we_o <= `WriteDisable; + case (funct3) + `INST_CSRRW: begin + csr_wdata_o <= reg1_rdata_i; + reg_wdata <= csr_rdata_i; + end + `INST_CSRRS: begin + csr_wdata_o <= reg1_rdata_i | csr_rdata_i; + reg_wdata <= csr_rdata_i; + end + `INST_CSRRC: begin + csr_wdata_o <= csr_rdata_i & (~reg1_rdata_i); + reg_wdata <= csr_rdata_i; + end + `INST_CSRRWI: begin + csr_wdata_o <= {27'h0, uimm}; + reg_wdata <= csr_rdata_i; + end + `INST_CSRRSI: begin + csr_wdata_o <= {27'h0, uimm} | csr_rdata_i; + reg_wdata <= csr_rdata_i; + end + `INST_CSRRCI: begin + csr_wdata_o <= (~{27'h0, uimm}) & csr_rdata_i; + reg_wdata <= csr_rdata_i; + end + default: begin + jump_flag <= `JumpDisable; + hold_flag <= `HoldDisable; + jump_addr <= `ZeroWord; + mem_wdata_o <= `ZeroWord; + mem_raddr_o <= `ZeroWord; + mem_waddr_o <= `ZeroWord; + mem_we_o <= `WriteDisable; + reg_wdata <= `ZeroWord; + end + endcase + end default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; diff --git a/rtl/core/id.v b/rtl/core/id.v index dd80d16..5feaedb 100644 --- a/rtl/core/id.v +++ b/rtl/core/id.v @@ -29,6 +29,9 @@ module id( input wire[`RegBus] reg1_rdata_i, // reg1 read data input wire[`RegBus] reg2_rdata_i, // reg2 read data + // from csr reg + input wire[`RegBus] csr_rdata_i, + // from ex input wire ex_jump_flag_i, input wire[`INT_BUS] ex_int_flag_i, @@ -37,6 +40,9 @@ module id( output reg[`RegAddrBus] reg1_raddr_o, // reg1 read addr output reg[`RegAddrBus] reg2_raddr_o, // reg2 read addr + // to csr reg + output reg[`MemAddrBus] csr_raddr_o, + output wire mem_req_o, // to ex @@ -45,7 +51,10 @@ module id( output reg[`RegBus] reg1_rdata_o, // reg1 read data output reg[`RegBus] reg2_rdata_o, // reg2 read data output reg reg_we_o, // reg write enable - output reg[`RegAddrBus] reg_waddr_o // reg write addr + output reg[`RegAddrBus] reg_waddr_o, // reg write addr + output reg csr_we_o, + output reg[`RegBus] csr_rdata_o, + output reg[`MemAddrBus] csr_waddr_o ); @@ -65,19 +74,27 @@ module id( if (rst == `RstEnable) begin reg1_raddr_o <= `ZeroWord; reg2_raddr_o <= `ZeroWord; + csr_raddr_o <= `ZeroWord; inst_o <= `INST_NOP; inst_addr_o <= `ZeroWord; reg1_rdata_o <= `ZeroWord; reg2_rdata_o <= `ZeroWord; + csr_rdata_o <= `ZeroWord; reg_we_o <= `WriteDisable; + csr_we_o <= `WriteDisable; reg_waddr_o <= `ZeroWord; + csr_waddr_o <= `ZeroWord; mem_req <= `RIB_NREQ; end else begin inst_o <= inst_i; inst_addr_o <= inst_addr_i; reg1_rdata_o <= reg1_rdata_i; reg2_rdata_o <= reg2_rdata_i; + csr_rdata_o <= csr_rdata_i; mem_req <= `RIB_NREQ; + csr_raddr_o <= `ZeroWord; + csr_waddr_o <= `ZeroWord; + csr_we_o <= `WriteDisable; case (opcode) `INST_TYPE_I: begin @@ -418,6 +435,65 @@ module id( reg1_raddr_o <= `ZeroWord; reg2_raddr_o <= `ZeroWord; end + `INST_CSR: begin + reg_we_o <= `WriteDisable; + reg_waddr_o <= `ZeroWord; + reg1_raddr_o <= `ZeroWord; + reg2_raddr_o <= `ZeroWord; + csr_raddr_o <= {20'h0, inst_i[31:20]}; + csr_waddr_o <= {20'h0, inst_i[31:20]}; + case (funct3) + `INST_CSRRW: begin + reg1_raddr_o <= rs1; + reg2_raddr_o <= `ZeroWord; + reg_we_o <= `WriteEnable; + reg_waddr_o <= rd; + csr_we_o <= `WriteEnable; + end + `INST_CSRRS: begin + reg1_raddr_o <= rs1; + reg2_raddr_o <= `ZeroWord; + reg_we_o <= `WriteEnable; + reg_waddr_o <= rd; + csr_we_o <= `WriteEnable; + end + `INST_CSRRC: begin + reg1_raddr_o <= rs1; + reg2_raddr_o <= `ZeroWord; + reg_we_o <= `WriteEnable; + reg_waddr_o <= rd; + csr_we_o <= `WriteEnable; + end + `INST_CSRRWI: begin + reg1_raddr_o <= `ZeroWord; + reg2_raddr_o <= `ZeroWord; + reg_we_o <= `WriteEnable; + reg_waddr_o <= rd; + csr_we_o <= `WriteEnable; + end + `INST_CSRRSI: begin + reg1_raddr_o <= `ZeroWord; + reg2_raddr_o <= `ZeroWord; + reg_we_o <= `WriteEnable; + reg_waddr_o <= rd; + csr_we_o <= `WriteEnable; + end + `INST_CSRRCI: begin + reg1_raddr_o <= `ZeroWord; + reg2_raddr_o <= `ZeroWord; + reg_we_o <= `WriteEnable; + reg_waddr_o <= rd; + csr_we_o <= `WriteEnable; + end + default: begin + reg_we_o <= `WriteDisable; + reg_waddr_o <= `ZeroWord; + reg1_raddr_o <= `ZeroWord; + reg2_raddr_o <= `ZeroWord; + csr_we_o <= `WriteDisable; + end + endcase + end default: begin reg_we_o <= `WriteDisable; reg_waddr_o <= `ZeroWord; diff --git a/rtl/core/id_ex.v b/rtl/core/id_ex.v index 21d77d5..aeb8693 100644 --- a/rtl/core/id_ex.v +++ b/rtl/core/id_ex.v @@ -28,6 +28,9 @@ module id_ex( input wire[`RegAddrBus] reg_waddr_i, input wire[`RegBus] reg1_rdata_i, // reg1 read data input wire[`RegBus] reg2_rdata_i, // reg2 read data + input wire csr_we_i, + input wire[`MemAddrBus] csr_waddr_i, + input wire[`RegBus] csr_rdata_i, input wire[`Hold_Flag_Bus] hold_flag_i, @@ -36,7 +39,10 @@ module id_ex( output reg reg_we_o, output reg[`RegAddrBus] reg_waddr_o, output reg[`RegBus] reg1_rdata_o, // reg1 read data - output reg[`RegBus] reg2_rdata_o // reg2 read data + output reg[`RegBus] reg2_rdata_o, // reg2 read data + output reg csr_we_o, + output reg[`MemAddrBus] csr_waddr_o, + output reg[`RegBus] csr_rdata_o ); @@ -48,6 +54,9 @@ module id_ex( reg_waddr_o <= `ZeroWord; reg1_rdata_o <= `ZeroWord; reg2_rdata_o <= `ZeroWord; + csr_we_o <= `WriteDisable; + csr_waddr_o <= `ZeroWord; + csr_rdata_o <= `ZeroWord; end else begin if (hold_flag_i >= `Hold_Id) begin inst_o <= `INST_NOP; @@ -56,6 +65,9 @@ module id_ex( reg_waddr_o <= `ZeroWord; reg1_rdata_o <= `ZeroWord; reg2_rdata_o <= `ZeroWord; + csr_we_o <= `WriteDisable; + csr_waddr_o <= `ZeroWord; + csr_rdata_o <= `ZeroWord; end else begin inst_o <= inst_i; inst_addr_o <= inst_addr_i; @@ -63,6 +75,9 @@ module id_ex( reg_waddr_o <= reg_waddr_i; reg1_rdata_o <= reg1_rdata_i; reg2_rdata_o <= reg2_rdata_i; + csr_we_o <= csr_we_i; + csr_waddr_o <= csr_waddr_i; + csr_rdata_o <= csr_rdata_i; end end end diff --git a/rtl/core/tinyriscv.v b/rtl/core/tinyriscv.v index 5298fad..31dfd20 100644 --- a/rtl/core/tinyriscv.v +++ b/rtl/core/tinyriscv.v @@ -61,6 +61,10 @@ module tinyriscv( wire[`RegBus] id_reg2_rdata_o; wire id_reg_we_o; wire[`RegAddrBus] id_reg_waddr_o; + wire[`MemAddrBus] id_csr_raddr_o; + wire id_csr_we_o; + wire[`RegBus] id_csr_rdata_o; + wire[`MemAddrBus] id_csr_waddr_o; // id_ex wire[`InstBus] ie_inst_o; @@ -69,6 +73,9 @@ module tinyriscv( wire[`RegAddrBus] ie_reg_waddr_o; wire[`RegBus] ie_reg1_rdata_o; wire[`RegBus] ie_reg2_rdata_o; + wire ie_csr_we_o; + wire[`MemAddrBus] ie_csr_waddr_o; + wire[`RegBus] ie_csr_rdata_o; // ex wire[`MemBus] ex_mem_wdata_o; @@ -92,11 +99,17 @@ module tinyriscv( wire ex_clint_we_o; wire[`RegAddrBus] ex_clint_addr_o; wire[`RegBus] ex_clint_data_o; + wire[`RegBus] ex_csr_wdata_o; + wire ex_csr_we_o; + wire[`MemAddrBus] ex_csr_waddr_o; // regs wire[`RegBus] regs_rdata1_o; wire[`RegBus] regs_rdata2_o; + // csr reg + wire[`RegBus] csr_data_o; + // ctrl wire[`Hold_Flag_Bus] ctrl_hold_flag_o; wire ctrl_jump_flag_o; @@ -161,6 +174,16 @@ module tinyriscv( .jtag_data_o(jtag_reg_data_o) ); + csr_reg u_csr_reg( + .clk(clk), + .rst(rst), + .we_i(ex_csr_we_o), + .raddr_i(id_csr_raddr_o), + .waddr_i(ex_csr_waddr_o), + .data_i(ex_csr_wdata_o), + .data_o(csr_data_o) + ); + if_id u_if_id( .clk(clk), .rst(rst), @@ -187,7 +210,12 @@ module tinyriscv( .reg1_rdata_o(id_reg1_rdata_o), .reg2_rdata_o(id_reg2_rdata_o), .reg_we_o(id_reg_we_o), - .reg_waddr_o(id_reg_waddr_o) + .reg_waddr_o(id_reg_waddr_o), + .csr_rdata_i(csr_data_o), + .csr_raddr_o(id_csr_raddr_o), + .csr_we_o(id_csr_we_o), + .csr_rdata_o(id_csr_rdata_o), + .csr_waddr_o(id_csr_waddr_o) ); id_ex u_id_ex( @@ -205,7 +233,13 @@ module tinyriscv( .reg_we_o(ie_reg_we_o), .reg_waddr_o(ie_reg_waddr_o), .reg1_rdata_o(ie_reg1_rdata_o), - .reg2_rdata_o(ie_reg2_rdata_o) + .reg2_rdata_o(ie_reg2_rdata_o), + .csr_we_i(id_csr_we_o), + .csr_waddr_i(id_csr_waddr_o), + .csr_rdata_i(id_csr_rdata_o), + .csr_we_o(ie_csr_we_o), + .csr_waddr_o(ie_csr_waddr_o), + .csr_rdata_o(ie_csr_rdata_o) ); ex u_ex( @@ -244,7 +278,13 @@ module tinyriscv( .div_dividend_o(ex_div_dividend_o), .div_divisor_o(ex_div_divisor_o), .div_op_o(ex_div_op_o), - .div_reg_waddr_o(ex_div_reg_waddr_o) + .div_reg_waddr_o(ex_div_reg_waddr_o), + .csr_we_i(ie_csr_we_o), + .csr_waddr_i(ie_csr_waddr_o), + .csr_rdata_i(ie_csr_rdata_o), + .csr_wdata_o(ex_csr_wdata_o), + .csr_we_o(ex_csr_we_o), + .csr_waddr_o(ex_csr_waddr_o) ); div u_div(