diff --git a/bench/serv_wrapper.v b/bench/serv_wrapper.v index 89c86c1..bb101b2 100644 --- a/bench/serv_wrapper.v +++ b/bench/serv_wrapper.v @@ -156,6 +156,7 @@ serv_arbiter serv_arbiter ( .clk (wb_clk), .i_rst (wb_rst), + .i_timer_irq (timer_irq), .o_ibus_adr (wb_cpu_ibus_adr), .o_ibus_cyc (wb_cpu_ibus_cyc), diff --git a/rtl/serv_csr.v b/rtl/serv_csr.v index e60cb48..7b61596 100644 --- a/rtl/serv_csr.v +++ b/rtl/serv_csr.v @@ -3,6 +3,9 @@ module serv_csr ( input wire i_clk, input wire i_en, + input wire [4:0] i_cnt, + input wire i_mtip, + output wire o_timer_irq_en, input wire [2:0] i_csr_sel, input wire [1:0] i_csr_source, input wire i_trap, @@ -14,17 +17,24 @@ module serv_csr `include "serv_params.vh" /* + 300 mstatus RWSC 304 mie SCWi 305 mtvec RW + 344 mip CWi + 340 mscratch 341 mepc RW - 300 mstatus RWSC 342 mcause R 343 mtval - 344 mip CWi */ - reg [31:0] mtvec = 32'h0; + reg mstatus; + reg mstatus_mie; + reg mie; + reg mie_mtie; + reg [31:0] mtvec = 32'h0; + reg mip; + reg [31:0] mscratch = 32'h0; reg [31:0] mepc = 32'h0; reg [31:0] mcause = 32'h0; @@ -55,7 +65,19 @@ module serv_csr assign o_q = csr_out; + wire o_timer_irq_en = mstatus_mie & mie_mtie; + always @(posedge i_clk) begin + if (i_en & (i_cnt == 3) & (i_csr_sel == CSR_SEL_MSTATUS)) + mstatus_mie <= csr_in; + + if (i_en & (i_cnt == 7) & (i_csr_sel == CSR_SEL_MIE)) + mie_mtie <= csr_in; + + mstatus <= (i_cnt == 2) ? mstatus_mie : 1'b0; + mie <= (i_cnt == 6) & mie_mtie; + mip <= (i_cnt == 6) & i_mtip; + if (i_trap) mcause[3:0] <= i_mcause; diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index 81ece3e..6d9f884 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -3,9 +3,11 @@ module serv_decode ( input wire clk, input wire i_rst, + input wire i_mtip, input wire [31:0] i_wb_rdt, input wire i_wb_en, input wire i_rf_ready, + output wire [4:0] o_cnt, output wire o_cnt_done, output wire o_ctrl_en, output wire o_ctrl_pc_en, @@ -75,6 +77,8 @@ module serv_decode reg [4:0] cnt; + assign o_cnt = cnt; + wire running; wire mem_op; wire shift_op; @@ -119,11 +123,15 @@ module serv_decode assign o_alu_init = (state == INIT); - assign o_alu_sub = (opcode == OP_OP) ? imm30 /* ? 1'b1*/ : - (branch_op & (o_funct3 == 3'b100)) ? 1'b1 : - (branch_op & (o_funct3 == 3'b101)) ? 1'b1 : - (branch_op & (o_funct3 == 3'b110)) ? 1'b1 : - 1'b0; + reg alu_sub_r; + assign o_alu_sub = alu_sub_r; + + always @(posedge clk) + alu_sub_r <= (opcode == OP_OP) ? imm30 /* ? 1'b1*/ : + (branch_op & (o_funct3 == 3'b100)) ? 1'b1 : + (branch_op & (o_funct3 == 3'b101)) ? 1'b1 : + (branch_op & (o_funct3 == 3'b110)) ? 1'b1 : + 1'b0; assign o_alu_cmp_neg = branch_op & o_funct3[0]; @@ -150,17 +158,6 @@ module serv_decode default : o_alu_cmp_uns = 1'bx; endcase - casez(o_funct3) - 3'b000 : o_alu_rd_sel = ALU_RESULT_ADD; - 3'b001 : o_alu_rd_sel = ALU_RESULT_SR; - 3'b01? : o_alu_rd_sel = ALU_RESULT_LT; - 3'b100 : o_alu_rd_sel = ALU_RESULT_XOR; - 3'b101 : o_alu_rd_sel = ALU_RESULT_SR; - 3'b110 : o_alu_rd_sel = ALU_RESULT_OR; - 3'b111 : o_alu_rd_sel = ALU_RESULT_AND; - default : o_alu_rd_sel = 3'bxx; - 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; @@ -171,14 +168,14 @@ module serv_decode o_csr_source = CSR_SOURCE_CSR; casez(csr_sel) - //4'b0_000 : o_csr_sel = CSR_SEL_MSTATUS; - //4'b0_100 : o_csr_sel = CSR_SEL_MIE; + 4'b0_000 : o_csr_sel = CSR_SEL_MSTATUS; + 4'b0_100 : o_csr_sel = CSR_SEL_MIE; 4'b0_101 : o_csr_sel = CSR_SEL_MTVEC; 4'b1_000 : o_csr_sel = CSR_SEL_MSCRATCH; 4'b1_001 : o_csr_sel = CSR_SEL_MEPC; 4'b1_010 : o_csr_sel = CSR_SEL_MCAUSE; 4'b1_011 : o_csr_sel = CSR_SEL_MTVAL; - //4'b1_100 : o_csr_sel = CSR_SEL_MIP; + 4'b1_100 : o_csr_sel = CSR_SEL_MIP; default : begin o_csr_sel = 3'bxxx; /*if (o_csr_en) begin @@ -219,6 +216,17 @@ module serv_decode reg [4:0] imm11_7; always @(posedge clk) begin + casez(o_funct3) + 3'b000 : o_alu_rd_sel <= ALU_RESULT_ADD; + 3'b001 : o_alu_rd_sel <= ALU_RESULT_SR; + 3'b01? : o_alu_rd_sel <= ALU_RESULT_LT; + 3'b100 : o_alu_rd_sel <= ALU_RESULT_XOR; + 3'b101 : o_alu_rd_sel <= ALU_RESULT_SR; + 3'b110 : o_alu_rd_sel <= ALU_RESULT_OR; + 3'b111 : o_alu_rd_sel <= ALU_RESULT_AND; + //default : o_alu_rd_sel <= 3'bxx; + endcase + if (i_wb_en) begin o_rf_rd_addr <= i_wb_rdt[11:7]; o_rf_rs1_addr <= i_wb_rdt[19:15]; @@ -274,17 +282,22 @@ module serv_decode wire cnt_en = (state != IDLE); - wire cnt_done = cnt == 31; + reg cnt_done; + assign running = (state == RUN); assign o_ctrl_trap = (state == TRAP); - always @(i_mem_misalign, o_mem_cmd, e_op, op) begin - o_csr_mcause[3:0] = 4'd0; - if (i_mem_misalign) - o_csr_mcause[3:0] = {2'b01, o_mem_cmd, 1'b0}; - if (e_op) - o_csr_mcause = {!op[20],3'b011}; + always @(posedge clk) begin + if (i_mtip) + o_csr_mcause[3:0] <= 4'd7; + else begin + o_csr_mcause[3:0] <= 4'd0; + if (i_mem_misalign) + o_csr_mcause[3:0] <= {2'b01, o_mem_cmd, 1'b0}; + if (e_op) + o_csr_mcause <= {!op[20],3'b011}; + end end wire two_stage_op = @@ -293,13 +306,15 @@ module serv_decode reg stage_one_done; always @(posedge clk) begin + cnt_done <= cnt == 30; + case (state) IDLE : begin if (i_rf_ready) begin state <= RUN; if (two_stage_op & !stage_one_done) state <= INIT; - if (e_op) + if (e_op | i_mtip) state <= TRAP; end end diff --git a/rtl/serv_params.vh b/rtl/serv_params.vh index 0b8e0ac..581eb0b 100644 --- a/rtl/serv_params.vh +++ b/rtl/serv_params.vh @@ -28,12 +28,26 @@ localparam [0:0] AND */ + /* + 300 mstatus RWSC + 304 mie SCWi + 305 mtvec RW + 344 mip CWi + + 340 mscratch + 341 mepc RW + 342 mcause R + 343 mtval + */ localparam [2:0] - CSR_SEL_MSCRATCH = 3'd0, - CSR_SEL_MEPC = 3'd1, - CSR_SEL_MCAUSE = 3'd2, - CSR_SEL_MTVAL = 3'd3, - CSR_SEL_MTVEC = 3'd4; + CSR_SEL_MSTATUS = 3'd0, + CSR_SEL_MIE = 3'd1, + CSR_SEL_MTVEC = 3'd2, + CSR_SEL_MIP = 3'd3, + CSR_SEL_MSCRATCH = 3'd4, + CSR_SEL_MEPC = 3'd5, + CSR_SEL_MCAUSE = 3'd6, + CSR_SEL_MTVAL = 3'd7; localparam [1:0] CSR_SOURCE_CSR = 2'b00, diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 3458414..c90c4a3 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -10,6 +10,7 @@ module serv_top ( input wire clk, input wire i_rst, + input wire i_timer_irq, `ifdef RISCV_FORMAL output reg rvfi_valid = 1'b0, output reg [63:0] rvfi_order = 64'd0, @@ -70,6 +71,8 @@ module serv_top wire imm; wire trap; + wire [4:0] cnt; + wire cnt_done; wire [2:0] funct3; @@ -116,13 +119,18 @@ module serv_top wire lui; + wire timer_irq_en; + wire timer_irq = i_timer_irq & timer_irq_en; + serv_decode decode ( .clk (clk), .i_rst (i_rst), + .i_mtip (timer_irq), .i_wb_rdt (i_ibus_rdt), .i_wb_en (o_ibus_cyc & i_ibus_ack), .i_rf_ready (rf_ready), + .o_cnt (cnt), .o_cnt_done (cnt_done), .o_ctrl_en (ctrl_en), .o_ctrl_pc_en (ctrl_pc_en), @@ -260,6 +268,9 @@ module serv_top ( .i_clk (clk), .i_en (csr_en), + .i_cnt (cnt), + .i_mtip (timer_irq), + .o_timer_irq_en ( timer_irq_en), .i_csr_sel (csr_sel), .i_csr_source (csr_source), .i_trap (trap),