diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index 6b52aca..a717787 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -45,12 +45,13 @@ module serv_decode output wire o_mem_init, output wire [1:0] o_mem_bytecnt, input wire i_mem_misalign, + output wire o_rd_csr_en, output wire o_csr_en, output reg [1:0] o_csr_addr, output wire o_csr_mstatus_en, output wire o_csr_mie_en, output wire o_csr_mcause_en, - output reg [1:0] o_csr_source, + output wire [1:0] o_csr_source, output reg [3:0] o_csr_mcause, output wire o_csr_imm, output wire o_csr_d_sel, @@ -98,7 +99,9 @@ module serv_decode assign shift_op = op_or_opimm & (o_funct3[1:0] == 2'b01); assign slt_op = op_or_opimm & (o_funct3[2:1] == 2'b01); - assign e_op = (opcode[4:2] == 3'b111) & !op21 & !(|o_funct3); + //Matches system opcodes except CSR accesses (o_funct3 == 0) + //No idea anymore why the !op21 condition is needed here + assign e_op = opcode[4] & opcode[2] & !op21 & !(|o_funct3); //jal,branch = imm //jalr = rs1+imm @@ -160,9 +163,11 @@ module serv_decode //false for mstatus, mie, mcause, mip wire csr_valid = op20 | (op26 & !op22 & !op21); + //Matches system ops except eceall/ebreak wire csr_op = opcode[4] & opcode[2] & (|o_funct3); + assign o_rd_csr_en = csr_op; - assign o_csr_en = state[1] & (o_ctrl_mret | state[0] | (csr_op & csr_valid)); + assign o_csr_en = csr_op & (state == RUN) & csr_valid; assign o_csr_mstatus_en = csr_op & (state == RUN) & !op26 & !op22; assign o_csr_mie_en = csr_op & (state == RUN) & !op26 & op22 & !op20; assign o_csr_mcause_en = csr_op & (state == RUN) & op21 & !op20; @@ -170,7 +175,7 @@ module serv_decode assign o_alu_cmp_eq = o_funct3[2:1] == 2'b00; - always @(o_funct3, o_rf_rs1_addr, o_ctrl_trap, o_ctrl_mret) begin + always @(o_funct3) begin casez (o_funct3) 3'b00? : o_alu_cmp_uns = 1'b0; 3'b010 : o_alu_cmp_uns = 1'b0; @@ -179,18 +184,9 @@ module serv_decode 3'b11? : o_alu_cmp_uns = 1'b1; default : o_alu_cmp_uns = 1'bx; endcase - - casez(o_funct3[1:0]) - 2'b01 : o_csr_source = CSR_SOURCE_EXT; //Check for x0 - 2'b10 : o_csr_source = CSR_SOURCE_SET; - 2'b11 : o_csr_source = CSR_SOURCE_CLR; - default : o_csr_source = 2'bxx; - endcase - if (((o_rf_rs1_addr == 5'd0) & o_funct3[1]) | o_ctrl_trap | o_ctrl_mret) - o_csr_source = CSR_SOURCE_CSR; - end + assign o_csr_source = o_funct3[1:0]; assign o_csr_imm = (o_cnt < 5) ? o_rf_rs1_addr[o_cnt[2:0]] : 1'b0; assign o_csr_d_sel = o_funct3[2]; @@ -242,11 +238,11 @@ module serv_decode op26 <= i_wb_rdt[26]; //Default to mtvec to have the correct CSR address loaded in case of trap - o_csr_addr <= mret ? 2'b10 : //mepc - (i_wb_rdt[26] & !i_wb_rdt[20]) ? 2'b00 : //mscratch - (i_wb_rdt[26] & !i_wb_rdt[21]) ? 2'b10 : //mepc - (i_wb_rdt[26]) ? 2'b11 : //mtval - 2'b01; //mtvec + o_csr_addr <= mret ? CSR_MEPC : + (i_wb_rdt[26] & !i_wb_rdt[20]) ? CSR_MSCRATCH : + (i_wb_rdt[26] & !i_wb_rdt[21]) ? CSR_MEPC : + (i_wb_rdt[26]) ? CSR_MTVAL : + CSR_MTVEC; o_ctrl_mret <= mret; imm[31] <= sign_bit; imm[30:20] <= utype ? i_wb_rdt[30:20] : {11{sign_bit}}; diff --git a/rtl/serv_mpram.v b/rtl/serv_mpram.v index 2ed9a3b..d67afba 100644 --- a/rtl/serv_mpram.v +++ b/rtl/serv_mpram.v @@ -7,6 +7,7 @@ module serv_mpram input wire i_trap, input wire i_mepc, input wire i_mtval, + output wire o_csr_pc, //CSR interface input wire i_csr_en, input wire [1:0] i_csr_addr, @@ -26,6 +27,8 @@ module serv_mpram input wire [4:0] i_rs2_raddr, output wire o_rs2); +`include "serv_params.vh" + wire [8:0] waddr; reg [4:0] wdata0; @@ -57,7 +60,7 @@ module serv_mpram assign waddr[7:5] = wcnt_lo[3] ? rd_waddr[4:2] : 3'b000; assign waddr[4:3] = wcnt_lo[3] ? rd_waddr[1:0] : wcnt_lo[2] ? i_csr_addr : - wcnt_lo[1] ? 2'b11 : 2'b10; + wcnt_lo[1] ? CSR_MTVAL : CSR_MEPC; assign waddr[2:0] = wcnt_hi; wire wgo = !(|wcnt_lo) & |({i_rd_wen,i_csr_en,i_trap, i_trap}); @@ -137,12 +140,14 @@ module serv_mpram assign raddr[7:5] = rcnt_lo[0] ? i_rs1_raddr[4:2] : rcnt_lo[1] ? i_rs2_raddr[4:2] : 3'd0; assign raddr[4:3] = rcnt_lo[0] ? i_rs1_raddr[1:0] : - rcnt_lo[1] ? i_rs2_raddr[1:0] : i_csr_addr; + rcnt_lo[1] ? i_rs2_raddr[1:0] : + i_trap ? CSR_MTVEC : i_csr_addr; assign raddr[2:0] = rcnt_hi; assign o_rs1 = rdata0[0]; assign o_rs2 = rdata1[0]; assign o_csr = rdata2[0] & i_csr_en; + assign o_csr_pc = rdata2[0]; reg [3:0] memory [0:511]; diff --git a/rtl/serv_params.vh b/rtl/serv_params.vh index 3f74c5e..7d1e518 100644 --- a/rtl/serv_params.vh +++ b/rtl/serv_params.vh @@ -13,3 +13,9 @@ localparam [1:0] CSR_SOURCE_EXT = 2'b01, CSR_SOURCE_SET = 2'b10, CSR_SOURCE_CLR = 2'b11; + +localparam [1:0] + CSR_MSCRATCH = 2'b00, + CSR_MTVEC = 2'b01, + CSR_MEPC = 2'b10, + CSR_MTVAL = 2'b11; diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 20d39c9..dd7a07b 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -48,6 +48,7 @@ module serv_top wire rd_alu_en; wire rd_mem_en; + wire rd_csr_en; wire ctrl_rd; wire alu_rd; wire mem_rd; @@ -116,6 +117,8 @@ module serv_top wire csr_d_sel; wire csr_en; wire [1:0] csr_addr; + wire csr_pc; + wire [3:0] mcause; @@ -170,6 +173,7 @@ module serv_top .o_mem_init (mem_init), .o_mem_bytecnt (mem_bytecnt), .i_mem_misalign (mem_misalign), + .o_rd_csr_en (rd_csr_en), .o_csr_en (csr_en), .o_csr_addr (csr_addr), .o_csr_mstatus_en (csr_mstatus_en), @@ -225,7 +229,7 @@ module serv_top //Data .i_imm (imm), .i_buf (bufreg_q), - .i_csr_pc (csr_rd), + .i_csr_pc (csr_pc), .o_rd (ctrl_rd), .o_bad_pc (bad_pc), //External @@ -235,7 +239,7 @@ module serv_top assign rd = (ctrl_rd ) | (rd_alu_en & alu_rd ) | - (csr_rd ) | + (csr_rd & rd_csr_en) | (rd_mem_en & mem_rd); assign op_b = (op_b_source == OP_B_SOURCE_IMM) ? imm : rs2; @@ -287,6 +291,7 @@ module serv_top .i_trap (trap), .i_mepc (o_ibus_adr[0]), .i_mtval (mem_misalign ? bufreg_q : bad_pc), + .o_csr_pc (csr_pc), //CSR write port .i_csr_en (csr_en), .i_csr_addr (csr_addr),