From a550137453168156b796f4230d82ee95d861c269 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 22 Jan 2019 09:47:11 +0100 Subject: [PATCH] Use bufreg for shifter --- rtl/ser_shift.v | 39 +++++++++++++-------------------------- rtl/serv_alu.v | 16 +++++++++++++--- rtl/serv_bufreg.v | 3 ++- rtl/serv_decode.v | 25 ++++++++++++++++++++++--- rtl/serv_mem_if.v | 7 ++++--- rtl/serv_top.v | 24 +++++++++++++++++++----- 6 files changed, 73 insertions(+), 41 deletions(-) diff --git a/rtl/ser_shift.v b/rtl/ser_shift.v index 2326a15..81889c9 100644 --- a/rtl/ser_shift.v +++ b/rtl/ser_shift.v @@ -5,40 +5,27 @@ module ser_shift input wire i_rst, input wire i_load, input wire [4:0] i_shamt, - input wire i_signed, + input wire i_shamt_msb, + input wire i_signbit, input wire i_right, + output wire o_done, input wire i_d, output wire o_q); - wire [31:0] shiftreg; - - reg signbit = 1'b0; - reg wrapped = 1'b0; - reg [4:0] cnt = 5'd0; - - shift_reg #(.LEN (32)) sh_reg - (.clk (i_clk), - .i_rst (i_rst), - .i_en (i_load), - .i_d (i_d), - .o_q (shiftreg[0]), - .o_par (shiftreg[31:1])); - + reg signbit; + reg [5:0] cnt; + reg wrapped; + always @(posedge i_clk) begin - cnt <= cnt + 5'd1; - if (cnt == 31) begin - signbit <= shiftreg[cnt]; - wrapped <= 1'b1; - end + cnt <= cnt + 6'd1; if (i_load) begin - cnt <= i_shamt; - wrapped <= 1'b0; + cnt <= 6'd0; + signbit <= i_signbit & i_right; end - - + wrapped <= cnt[5] | (i_shamt_msb & !i_right); end - wire shiftreg_valid = (i_shamt == 0) | (wrapped^i_right); - assign o_q = shiftreg_valid ? shiftreg[cnt] : signbit & i_signed; + assign o_done = (cnt == i_shamt); + assign o_q = (i_right^wrapped) ? i_d : signbit; endmodule diff --git a/rtl/serv_alu.v b/rtl/serv_alu.v index 4679a7a..be41fc2 100644 --- a/rtl/serv_alu.v +++ b/rtl/serv_alu.v @@ -6,6 +6,7 @@ module serv_alu input wire i_en, input wire i_rs1, input wire i_op_b, + input wire i_buf, input wire i_init, input wire i_cnt_done, input wire i_sub, @@ -17,6 +18,7 @@ module serv_alu input wire i_shamt_en, input wire i_sh_right, input wire i_sh_signed, + output wire o_sh_done, input wire [1:0] i_rd_sel, output wire o_rd); @@ -30,6 +32,7 @@ module serv_alu reg result_lt_r; wire [4:0] shamt; + reg shamt_msb; reg en_r; wire v; @@ -54,11 +57,18 @@ module serv_alu .i_rst (i_rst), .i_load (i_init), .i_shamt (shamt), - .i_signed (i_sh_signed), + .i_shamt_msb (shamt_msb), + .i_signbit (i_sh_signed & i_rs1), .i_right (i_sh_right), - .i_d (i_rs1), + .o_done (o_sh_done), + .i_d (i_buf), .o_q (result_sh)); + wire b_inv_plus_1_cy; + + always @(posedge clk) + if (i_shamt_en) + shamt_msb <= b_inv_plus_1_cy; ser_add ser_add_inv_plus_1 ( @@ -68,7 +78,7 @@ module serv_alu .b (plus_1), .clr (!i_en), .q (b_inv_plus_1), - .o_v ()); + .o_v (b_inv_plus_1_cy)); wire add_b = i_sub ? b_inv_plus_1 : i_op_b; diff --git a/rtl/serv_bufreg.v b/rtl/serv_bufreg.v index cddb12b..da08881 100644 --- a/rtl/serv_bufreg.v +++ b/rtl/serv_bufreg.v @@ -6,6 +6,7 @@ module serv_bufreg input wire [3:0] i_cnt_r, input wire i_en, input wire i_clr, + input wire i_loop, input wire i_rs1, input wire i_rs1_en, input wire i_imm, @@ -26,7 +27,7 @@ module serv_bufreg if (i_rst) data <= 32'd0; else if (i_en) - data <= {q, data[31:1]}; + data <= {i_loop ? o_q : q, data[31:1]}; if ((i_cnt[4:2] == 3'd0) & i_cnt_r[0] & i_en) o_lsb[0] <= q; diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index ca79e04..7f1c428 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -11,6 +11,9 @@ module serv_decode output wire [4:0] o_cnt, output reg [3:0] o_cnt_r, output wire o_cnt_done, + output reg o_bufreg_hold, + output wire o_bufreg_imm_en, + output wire o_bufreg_loop, output wire o_ctrl_en, output wire o_ctrl_pc_en, output reg o_ctrl_jump, @@ -21,6 +24,7 @@ module serv_decode output wire o_ctrl_trap, output wire o_ctrl_mret, input wire i_ctrl_misalign, + output wire o_rf_rs_en, output wire o_rf_rd_en, output reg [4:0] o_rf_rd_addr, output reg [4:0] o_rf_rs1_addr, @@ -36,6 +40,7 @@ module serv_decode output wire o_alu_shamt_en, output wire o_alu_sh_signed, output wire o_alu_sh_right, + input wire i_alu_sh_done, output reg [1:0] o_alu_rd_sel, output wire o_mem_en, output wire o_mem_cmd, @@ -104,6 +109,9 @@ module serv_decode assign e_op = (opcode[4:2] == 3'b111) & !op21 & !(|o_funct3); + assign o_bufreg_imm_en = !opcode[2]; + assign o_bufreg_loop = op_or_opimm & !(state == INIT); + assign o_ctrl_pc_en = running | o_ctrl_trap; wire take_branch = (opcode[4:2] == 3'b110) & (opcode[0] | i_alu_cmp); @@ -273,6 +281,8 @@ module serv_decode o_csr_mcause <= {!op20,3'b011}; end + assign o_rf_rs_en = two_stage_op ? (state == INIT) : o_ctrl_pc_en; + //slt*, branch/jump, shift, load/store wire two_stage_op = slt_op | (opcode[4:2] == 3'b110) | (opcode[2:1] == 2'b00) | @@ -295,6 +305,8 @@ module serv_decode cnt_done <= (cnt[4:2] == 3'b111) & o_cnt_r[2]; + o_bufreg_hold <= 1'b0; + case (state) IDLE : begin if (i_rf_ready) begin @@ -303,14 +315,21 @@ module serv_decode state <= INIT; if (e_op | pending_irq) state <= TRAP; - end + end else if (i_alu_sh_done & shift_op & stage_one_done) + state <= RUN; end INIT : begin stage_one_done <= 1'b1; if (cnt_done) - state <= (i_mem_misalign | (take_branch & i_ctrl_misalign)) ? TRAP : - mem_op ? IDLE : RUN; + if (i_mem_misalign | (take_branch & i_ctrl_misalign)) + state <= TRAP; + else if (mem_op | shift_op ) begin + state <= IDLE; + o_bufreg_hold <= 1'b1; + end + else + state <= RUN; end RUN : begin stage_one_done <= 1'b0; diff --git a/rtl/serv_mem_if.v b/rtl/serv_mem_if.v index 9245186..0452bb1 100644 --- a/rtl/serv_mem_if.v +++ b/rtl/serv_mem_if.v @@ -60,7 +60,7 @@ module serv_mem_if assign o_wb_sel[0] = (bytepos == 2'b00); assign o_wb_we = i_cmd; - wire [1:0] bytepos; + reg [1:0] bytepos; wire wbyte0 = (i_bytecnt == 2'b00); @@ -77,9 +77,10 @@ module serv_mem_if wire [1:0] dat_sel = i_bytecnt[1] ? i_bytecnt : (i_bytecnt | bytepos); - assign bytepos = i_lsb; - always @(posedge i_clk) begin + if (i_init) + bytepos <= i_lsb; + if (dat0_en) dat0 <= {i_rs2, dat0[7:1]}; if (dat1_en) diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 9ed8524..bdbb53f 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -76,6 +76,10 @@ module serv_top wire cnt_done; wire [2:0] funct3; + wire bufreg_hold; + wire bufreg_imm_en; + wire bufreg_loop; + wire alu_en; wire alu_init; wire alu_sub; @@ -87,11 +91,13 @@ module serv_top wire alu_shamt_en; wire alu_sh_signed; wire alu_sh_right; + wire alu_sh_done; wire [1:0] alu_rd_sel; wire rf_ready; wire rs1; wire rs2; + wire rs_en; wire rd_en; wire op_b_source; @@ -136,10 +142,13 @@ module serv_top .i_timer_irq_en (timer_irq_en), .i_wb_rdt (i_ibus_rdt), .i_wb_en (o_ibus_cyc & i_ibus_ack), - .i_rf_ready (rf_ready), + .i_rf_ready (rf_ready | i_dbus_ack), .o_cnt (cnt), .o_cnt_r (cnt_r), .o_cnt_done (cnt_done), + .o_bufreg_hold (bufreg_hold), + .o_bufreg_imm_en (bufreg_imm_en), + .o_bufreg_loop (bufreg_loop), .o_ctrl_en (ctrl_en), .o_ctrl_pc_en (ctrl_pc_en), .o_ctrl_jump (jump), @@ -162,7 +171,9 @@ module serv_top .o_alu_shamt_en (alu_shamt_en), .o_alu_sh_signed (alu_sh_signed), .o_alu_sh_right (alu_sh_right), + .i_alu_sh_done (alu_sh_done), .o_alu_rd_sel (alu_rd_sel), + .o_rf_rs_en (rs_en), .o_rf_rd_en (rd_en), .o_rf_rd_addr (rd_addr), .o_rf_rs1_addr (rs1_addr), @@ -199,12 +210,13 @@ module serv_top .i_rst (i_rst), .i_cnt (cnt), .i_cnt_r (cnt_r), - .i_en (alu_en), + .i_en (!(bufreg_hold | o_dbus_cyc)), .i_clr (!mem_en), + .i_loop (bufreg_loop), .i_rs1 (rs1), .i_rs1_en (1'b1), .i_imm (imm), - .i_imm_en (1'b1), + .i_imm_en (bufreg_imm_en), .o_lsb (lsb), .o_reg (bufreg_out), .o_q (bad_adr)); @@ -250,6 +262,7 @@ module serv_top .i_en (alu_en), .i_rs1 (rs1), .i_op_b (op_b), + .i_buf (bad_adr), //FIXME .i_init (alu_init), .i_cnt_done (cnt_done), .i_sub (alu_sub), @@ -261,6 +274,7 @@ module serv_top .i_shamt_en (alu_shamt_en), .i_sh_right (alu_sh_right), .i_sh_signed (alu_sh_signed), + .o_sh_done (alu_sh_done), .i_rd_sel (alu_rd_sel), .o_rd (alu_rd)); @@ -268,7 +282,7 @@ module serv_top ( .i_clk (clk), .i_rst (i_rst), - .i_go (i_ibus_ack | i_dbus_ack), + .i_go (i_ibus_ack), .o_ready (rf_ready), .i_rd_en (rd_en), .i_rd_addr (rd_addr), @@ -345,7 +359,7 @@ module serv_top rvfi_insn <= i_ibus_rdt; ctrl_pc_en_r <= ctrl_pc_en; - if (alu_en) begin + if (rs_en) begin rs1_fv <= {rs1,rs1_fv[31:1]}; rs2_fv <= {rs2,rs2_fv[31:1]}; end