diff --git a/rtl/serv_alu.v b/rtl/serv_alu.v index d6c2176..842c9a2 100644 --- a/rtl/serv_alu.v +++ b/rtl/serv_alu.v @@ -105,7 +105,7 @@ module serv_alu assign o_rd = (i_rd_sel == ALU_RESULT_ADD) ? result_add : (i_rd_sel == ALU_RESULT_SR) ? result_sh : - (i_rd_sel == ALU_RESULT_LT) ? result_lt_r : + (i_rd_sel == ALU_RESULT_LT) ? result_lt_r & plus_1: (i_rd_sel == ALU_RESULT_BOOL) ? result_bool : 1'bx; @@ -117,8 +117,6 @@ module serv_alu eq_r <= result_eq; end else begin eq_r <= 1'b1; - if (result_lt_r) - result_lt_r <= 1'b0; end en_r <= i_en; end diff --git a/rtl/serv_mpram.v b/rtl/serv_mpram.v index cf93f45..b80bb13 100644 --- a/rtl/serv_mpram.v +++ b/rtl/serv_mpram.v @@ -6,6 +6,7 @@ module serv_mpram input wire i_run, //Trap interface input wire i_trap, + input wire i_mret, input wire i_mepc, input wire i_mtval, output wire o_csr_pc, @@ -19,6 +20,7 @@ module serv_mpram input wire [4:0] i_rd_waddr, input wire i_rd, + input wire i_wreq, input wire i_rreq, output reg o_rgnt, //RS1 read port @@ -30,29 +32,24 @@ module serv_mpram `include "serv_params.vh" - wire [8:0] waddr; + /* + ********** Write side *********** + */ - reg [4:0] wdata0; - reg [5:0] wdata1; + reg [4:0] wcnt; + reg wgo; - wire [3:0] wdata; + wire [3:0] wslot = wcnt[4:1]; + wire wport = wcnt[0]; - wire wen; - reg [1:0] wen_r; - - reg [3:0] wcnt_lo; - reg [2:0] wcnt_hi; - reg wgo_r; - - reg trap_r; - reg trap_2r; - reg trap_3r; - - assign wdata = wcnt_lo[0] ? wdata0[3:0] : wdata1[3:0]; - - assign wen = !wgo_r & |(wen_r & wcnt_lo[1:0]); - - reg [4:0] rd_waddr; + wire wdata0 = i_trap ? i_mtval : i_rd; + wire wdata1 = i_trap ? i_mepc : i_csr; + reg wdata0_r; + reg wdata1_r; + reg wdata1_2r; + wire [1:0] wdata = !wport ? + {wdata0 , wdata0_r} : + {wdata1_r, wdata1_2r}; //port 0 rd mtval //port 1 csr mepc @@ -60,105 +57,90 @@ module serv_mpram //mtval 100011 //csr 1000xx //rd 0xxxxx - wire [5:0] waddr0 = trap_3r ? {4'b1000,CSR_MTVAL} : {1'b0,rd_waddr}; - wire [5:0] waddr1 = trap_3r ? {4'b1000,CSR_MEPC} : {4'b1000,i_csr_addr}; + wire [5:0] wreg0 = i_trap ? {4'b1000,CSR_MTVAL} : {1'b0,i_rd_waddr}; + wire [5:0] wreg1 = i_trap ? {4'b1000,CSR_MEPC} : {4'b1000,i_csr_addr}; + wire [5:0] wreg = wport ? wreg1 : wreg0; + wire [9:0] waddr = {wreg, wslot}; - assign waddr[8:3] = wcnt_lo[0] ? waddr0 : waddr1; + wire wen = wgo & (i_trap | (wport ? i_csr_en : i_rd_wen & run_r)); -// assign waddr[8] = wcnt_lo[1] | i_trap; -// assign waddr[7:5] = (wcnt_lo[1] | i_trap) ? 3'b000 : rd_waddr[4:2]; -// assign waddr[4:3] = wcnt_lo[0] ? (i_trap ? CSR_MTVAL : rd_waddr[1:0]) : -// (i_trap ? CSR_MEPC : i_csr_addr); - assign waddr[2:0] = wcnt_hi; - - wire wgo = !(|wcnt_lo) & ((i_run & (i_rd_wen | i_csr_en)) | i_trap); + reg wreq_r; + reg run_r; always @(posedge i_clk) begin - trap_r <= i_trap; - trap_2r <= trap_r; - trap_3r <= trap_2r; + wreq_r <= i_wreq | o_rgnt; + wdata0_r <= wdata0; + wdata1_r <= wdata1; + wdata1_2r <= wdata1_r; + run_r <= i_run; + + + if (wgo) + wcnt <= wcnt+5'd1; + + if (wreq_r) + wgo <= 1'b1; + if (wcnt == 5'b11111) + wgo <= 1'b0; - if (wgo) begin - wgo_r <= 1'b1; - wen_r <= {(i_run & i_csr_en)|i_trap,(i_rd_wen & i_run)|i_trap}; - rd_waddr <= i_rd_waddr; - end - wdata0 <= {i_trap ? i_mtval : i_rd ,wdata0[4:1]}; - wdata1 <= {i_trap ? i_mepc : i_csr,wdata1[5:1]}; - wcnt_lo <= {wcnt_lo[2:0],wcnt_lo[3] | wgo}; - if (wcnt_lo[3]) begin - wcnt_hi <= wcnt_hi + 1; - if (wcnt_hi == 3'd7) begin - wgo_r <= !wgo_r; - wcnt_lo[0] <= wgo_r; - wcnt_hi <= wcnt_hi + {2'b00,wgo_r}; - end - end if (i_rst) begin - wgo_r <= 1'b0; - wcnt_lo <= 4'd0; - wcnt_hi <= 3'd7; + wcnt <= 5'd0; end end + /* + ********** Read side *********** + */ + //0 : RS1 - //1 : RS2 - //2 : CSR - reg [2:0] rcnt_hi; - reg [3:0] rcnt_lo; + //1 : RS2 / CSR - wire [8:0] raddr; + reg [4:0] rcnt; + wire [3:0] rslot = rcnt[4:1]; + wire rport = rcnt[0]; - reg [3:0] rdata; + wire [5:0] rreg0 = {1'b0, i_rs1_raddr}; + wire [5:0] rreg1 = + i_trap ? {4'b1000, CSR_MTVEC} : + (i_csr_en | i_mret) ? {4'b1000, i_csr_addr} : + {1'b0,i_rs2_raddr}; + wire [5:0] rreg = rport ? rreg1 : rreg0; + wire [9:0] raddr = {rreg, rslot}; - reg [5:0] rdata0; - reg [4:0] rdata1; - reg [3:0] rdata2; - //reg [3:0] rdata3; + reg [1:0] rdata; + reg [1:0] rdata0; + reg rdata1; - reg [2:0] rreq; + assign o_rs1 = !rport ? rdata0[0] : rdata0[1]; + assign o_rs2 = rport ? rdata1 : rdata[0]; + assign o_csr = o_rs2 & i_csr_en; + assign o_csr_pc = o_rs2; + + + reg rreq_r; always @(posedge i_clk) begin - {o_rgnt,rreq} <= {rreq[2:0],i_rreq}; - if (rcnt_lo[3]) - rcnt_hi <= rcnt_hi + 1; - if (i_rreq) begin - rcnt_lo <= 4'd1; - rcnt_hi <= 3'd0; - end else - rcnt_lo <= {rcnt_lo[2:0],rcnt_lo[3]}; + rcnt <= rcnt+5'd1; + if (i_rreq) + rcnt <= 5'd0; - rdata0[4:0] <= rdata0[5:1]; - rdata1[3:0] <= rdata1[4:1]; - rdata2[2:0] <= rdata2[3:1]; - //rdata3[2:0] <= rdata3[3:1]; + rreq_r <= i_rreq; + o_rgnt <= rreq_r; - if (rcnt_lo[1]) rdata0[5:2] <= rdata; - if (rcnt_lo[2]) rdata1[4:1] <= rdata; - if (rcnt_lo[3]) rdata2[3:0] <= rdata; - //if (rcnt_lo[0]) rdata3[3:0] <= rdata; + if (rport) + rdata0 <= rdata; + if (!rport) + rdata1 <= rdata[1]; if (i_rst) begin o_rgnt <= 1'b0; - rreq <= 3'd0; + rreq_r <= 1'b0; end end - assign raddr[8] = rcnt_lo[2]; - 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_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]; + reg [1:0] memory [0:1023]; always @(posedge i_clk) begin if (wen) @@ -176,8 +158,8 @@ module serv_mpram `ifdef SERV_CLEAR_RAM integer i; initial - for (i=0;i<256;i=i+1) - memory[i] = 4'd0; + for (i=0;i<512;i=i+1) + memory[i] = 2'd0; `endif endmodule diff --git a/rtl/serv_state.v b/rtl/serv_state.v index eec07cb..7aee37b 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -6,6 +6,7 @@ module serv_state input wire i_dbus_ack, input wire i_ibus_ack, output wire o_rf_rreq, + output wire o_rf_wreq, input wire i_rf_ready, input wire i_take_branch, input wire i_branch_op, @@ -32,7 +33,7 @@ module serv_state input wire i_mem_misalign, output reg [3:0] o_csr_mcause, output wire o_cnt_done, - output reg o_bufreg_hold, + output wire o_bufreg_hold, output wire o_csr_imm); localparam [1:0] @@ -44,6 +45,7 @@ module serv_state reg [1:0] state; reg cnt_done; + reg stage_two_req; wire cnt_en; wire running; @@ -86,12 +88,22 @@ module serv_state assign o_dbus_cyc = (state == IDLE) & stage_two_pending & i_mem_op & !mem_misalign; - assign o_rf_rreq = i_ibus_ack; + wire trap_pending = (o_ctrl_jump & i_ctrl_misalign) | mem_misalign; + + //Prepare RF for reads when a new instruction is fetched + // or when stage one caused an exception (rreq implies a write request too) + assign o_rf_rreq = i_ibus_ack | (stage_two_req & trap_pending); + + //Prepare RF for writes when everything is ready to enter stage two + assign o_rf_wreq = ((i_shift_op & i_alu_sh_done & stage_two_pending) | (i_mem_op & i_dbus_ack) | (stage_two_req & (i_slt_op | i_branch_op))) & !trap_pending; + + //Shift operations require bufreg to hold for one cycle between INIT and RUN before shifting + assign o_bufreg_hold = !cnt_en & (stage_two_req | ~i_shift_op); always @(posedge i_clk) begin if (state == INIT) o_ctrl_jump <= i_take_branch; - if (state == IDLE) + if (o_ctrl_pc_en & cnt_done) o_ctrl_jump <= 1'b0; if (cnt_en) @@ -102,41 +114,37 @@ module serv_state cnt_done <= (o_cnt[4:2] == 3'b111) & o_cnt_r[2]; - //Shift operations require bufreg to hold for one cycle before shifting - o_bufreg_hold <= i_shift_op & cnt_done; + //Need a strobe for the first cycle in the IDLE state after INIT + stage_two_req <= cnt_done & (state == INIT); case (state) IDLE : begin - if (i_rf_ready | i_dbus_ack) begin - state <= RUN; - if (two_stage_op & !stage_two_pending) - state <= INIT; - if (i_e_op | pending_irq) + if (stage_two_pending) begin + if (o_rf_wreq) + state <= RUN; + if (trap_pending & i_rf_ready) state <= TRAP; - end else if (i_alu_sh_done & i_shift_op & stage_two_pending) - state <= RUN; - end + end else begin + if (i_rf_ready) + if (i_e_op | pending_irq) + state <= TRAP; + else if (two_stage_op) + state <= INIT; + else + state <= RUN; + end + end INIT : begin - - if (cnt_done) - if (mem_misalign | (i_take_branch & i_ctrl_misalign)) - state <= TRAP; - else if (i_mem_op | i_shift_op ) - state <= IDLE; - else - state <= RUN; end RUN : begin - if (cnt_done) - state <= IDLE; end TRAP : begin pending_irq <= 1'b0; - if (cnt_done) - state <= IDLE; end default : state <= IDLE; endcase + if (cnt_done) + state <= IDLE; o_cnt <= o_cnt + {4'd0,cnt_en}; if (cnt_en) diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 2984b83..90676a6 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -99,6 +99,7 @@ module serv_top wire [1:0] alu_rd_sel; wire rf_rreq; + wire rf_wreq; wire rf_ready; wire rs1; wire rs2; @@ -144,6 +145,7 @@ module serv_top .i_dbus_ack (i_dbus_ack), .i_ibus_ack (i_ibus_ack), .o_rf_rreq (rf_rreq), + .o_rf_wreq (rf_wreq), .i_rf_ready (rf_ready), .i_take_branch (take_branch), .i_branch_op (branch_op), @@ -240,7 +242,7 @@ module serv_top .i_rst (i_rst), .i_cnt (cnt[4:2]), .i_cnt_r (cnt_r[1:0]), - .i_en (!(bufreg_hold | o_dbus_cyc)), + .i_en (!bufreg_hold), .i_init (init), .i_loop (bufreg_loop), .i_rs1 (rs1), @@ -318,6 +320,7 @@ module serv_top .i_run (run), //Trap interface .i_trap (trap), + .i_mret (mret), .i_mepc (o_ibus_adr[0]), .i_mtval ((mem_misalign & mem_op) ? bufreg_q : bad_pc), .o_csr_pc (csr_pc), @@ -331,6 +334,7 @@ module serv_top .i_rd (rd), .i_rreq (rf_rreq), + .i_wreq (rf_wreq), .o_rgnt (rf_ready), //RS1 read port .i_rs1_raddr (rs1_addr),