From 75decc8251febdafb0c619467159f24962fb687e Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 26 Sep 2019 20:21:36 +0200 Subject: [PATCH] Bring back old immediate decoder This was originally thrown out since it was slow and cost too much resources. Due to other changes in the core, it is now cheaper than the other one --- rtl/serv_bufreg.v | 5 +++- rtl/serv_ctrl.v | 2 +- rtl/serv_decode.v | 68 +++++++++++++++++++++++++++-------------------- rtl/serv_top.v | 5 ++++ 4 files changed, 49 insertions(+), 31 deletions(-) diff --git a/rtl/serv_bufreg.v b/rtl/serv_bufreg.v index df9a44e..c1e11e7 100644 --- a/rtl/serv_bufreg.v +++ b/rtl/serv_bufreg.v @@ -11,6 +11,7 @@ module serv_bufreg input wire i_rs1_en, input wire i_imm, input wire i_imm_en, + input wire i_clr_lsb, output reg [1:0] o_lsb, output wire [31:0] o_reg, output wire o_q); @@ -19,7 +20,9 @@ module serv_bufreg reg c_r; reg [31:0] data; - assign {c,q} = {1'b0,(i_rs1 & i_rs1_en)} + {1'b0,(i_imm & i_imm_en)} + c_r; + wire clr_lsb = (i_cnt[4:2] == 3'd0) & i_cnt_r[0] & i_clr_lsb; + + assign {c,q} = {1'b0,(i_rs1 & i_rs1_en)} + {1'b0,(i_imm & i_imm_en & !clr_lsb)} + c_r; always @(posedge i_clk) begin //Clear carry when not in INIT state diff --git a/rtl/serv_ctrl.v b/rtl/serv_ctrl.v index a095148..16bff1c 100644 --- a/rtl/serv_ctrl.v +++ b/rtl/serv_ctrl.v @@ -74,7 +74,7 @@ module serv_ctrl assign o_rd = (i_utype & pc_plus_offset_aligned) | (pc_plus_4 & i_jal_or_jalr); assign offset_a = i_pc_rel & pc; - assign offset_b = i_utype ? i_imm : i_buf; + assign offset_b = i_utype ? (i_imm & (i_cnt[4] | (i_cnt[3:2] == 2'b11))): i_buf; ser_add ser_add_pc_plus_offset ( diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index 9513478..84e8844 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -4,6 +4,7 @@ module serv_decode input wire clk, //Input input wire i_cnt_en, + input wire i_cnt_done, input wire [31:0] i_wb_rdt, input wire i_wb_en, input wire i_alu_cmp, @@ -19,6 +20,7 @@ module serv_decode output wire o_bufreg_loop, output wire o_bufreg_rs1_en, output wire o_bufreg_imm_en, + output wire o_bufreg_clr_lsb, //To ctrl output wire o_ctrl_jalr, output wire o_ctrl_jal_or_jalr, @@ -61,7 +63,6 @@ module serv_decode reg [4:0] opcode; reg [2:0] funct3; - reg [31:0] imm; reg op20; reg op21; reg op22; @@ -92,6 +93,11 @@ module serv_decode //Loop bufreg contents for shift operations assign o_bufreg_loop = op_or_opimm; + //Clear LSB of immediate for BRANCH and JAL ops + //True for BRANCH and JAL + //False for JALR/LOAD/STORE/OP/OPIMM? + assign o_bufreg_clr_lsb = opcode[4] & ((opcode[1:0] == 2'b00) | (opcode[1:0] == 2'b11)); + //Take branch for jump or branch instructions (opcode == 1x0xx) if //a) It's an unconditional branch (opcode[0] == 1) //b) It's a conditional branch (opcode[0] == 0) of type beq,blt,bltu (funct3[0] == 0) and ALU compare is true @@ -163,18 +169,13 @@ module serv_decode assign o_alu_bool_op = funct3[1:0]; - wire sign_bit = i_wb_rdt[31]; + reg signbit; - wire [4:0] op_code = i_wb_rdt[6:2]; - - wire btype = op_code[4] & !op_code[2] & !op_code[0]; - wire itype = (!op_code[3] & !op_code[0]) | (!op_code[2]&!op_code[1]&op_code[0]) | (!op_code[0]&op_code[2]); - wire jtype = op_code[1]; - wire stype = op_code[3] & ~op_code[2] & ~op_code[4]; - wire utype = !op_code[4] & op_code[0]; - - wire iorjtype = (op_code[0] & ~op_code[2]) | (op_code[2] & ~op_code[0]) | (~op_code[0] & ~op_code[3]); - wire sorbtype = op_code[3:0] == 4'b1000; + reg [8:0] imm19_12_20; + reg imm7; + reg [5:0] imm30_25; + reg [4:0] imm24_20; + reg [4:0] imm11_7; always @(funct3) casez(funct3) @@ -199,27 +200,36 @@ module serv_decode op22 <= i_wb_rdt[22]; op26 <= i_wb_rdt[26]; - imm[31] <= sign_bit; - imm[30:20] <= utype ? i_wb_rdt[30:20] : {11{sign_bit}}; - imm[19:12] <= (utype | jtype) ? i_wb_rdt[19:12] : {8{sign_bit}}; - imm[11] <= btype ? i_wb_rdt[7] : - utype ? 1'b0 : - jtype ? i_wb_rdt[20] : - sign_bit; - imm[10:5] <= utype ? 6'd0 : i_wb_rdt[30:25]; - imm[4:1] <= (sorbtype) ? i_wb_rdt[11:8] : - (iorjtype) ? i_wb_rdt[24:21] : - 4'd0; - imm[0] <= itype ? i_wb_rdt[20] : - stype ? i_wb_rdt[7] : - 1'b0; + //Immediate decoder + signbit <= i_wb_rdt[31]; + imm19_12_20 <= {i_wb_rdt[19:12],i_wb_rdt[20]}; + imm7 <= i_wb_rdt[7]; + imm30_25 <= i_wb_rdt[30:25]; + imm24_20 <= i_wb_rdt[24:20]; + imm11_7 <= i_wb_rdt[11:7]; + end + if (i_cnt_en) begin + imm19_12_20 <= {m3 ? signbit : imm24_20[0], imm19_12_20[8:1]}; + imm7 <= signbit; + imm30_25 <= {m2[1] ? imm7 : m2[0] ? signbit : imm19_12_20[0], imm30_25[5:1]}; + imm24_20 <= {imm30_25[0], imm24_20[4:1]}; + imm11_7 <= {imm30_25[0], imm11_7[4:1]}; end - if (i_cnt_en) - imm <= {imm[0], imm[31:1]}; end + //True for S (STORE) or B (BRANCH) type instructions + //False for J type instructions + wire m1 = opcode[3:0] == 4'b1000; - assign o_imm = imm[0]; + wire [1:0] m2; + assign m2[1] = opcode[4] & !opcode[0]; + + //True for OP-IMM, LOAD, STORE, JALR + //False for LUI, AUIPC, JAL + assign m2[0] = (opcode[1:0] == 2'b00) | (opcode[2:1] == 2'b00); + wire m3 = opcode[4]; + + assign o_imm = i_cnt_done ? signbit : m1 ? imm11_7[0] : imm24_20[0]; //0 (OP_B_SOURCE_IMM) when OPIMM //1 (OP_B_SOURCE_RS2) when BRANCH or OP diff --git a/rtl/serv_top.v b/rtl/serv_top.v index e098cec..d95a5fe 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -168,11 +168,14 @@ module serv_top .i_mem_misalign (mem_misalign), .o_csr_imm (csr_imm)); + wire bufreg_clr_lsb; + serv_decode decode ( .clk (clk), //Input .i_cnt_en (cnt_en), + .i_cnt_done (cnt_done), .i_wb_rdt (i_ibus_rdt), .i_wb_en (o_ibus_cyc & i_ibus_ack), .i_alu_cmp (alu_cmp), @@ -188,6 +191,7 @@ module serv_top .o_bufreg_loop (bufreg_loop), .o_bufreg_rs1_en (bufreg_rs1_en), .o_bufreg_imm_en (bufreg_imm_en), + .o_bufreg_clr_lsb (bufreg_clr_lsb), //To ctrl .o_ctrl_jalr (jalr), .o_ctrl_jal_or_jalr (jal_or_jalr), @@ -241,6 +245,7 @@ module serv_top .i_rs1_en (bufreg_rs1_en), .i_imm (imm), .i_imm_en (bufreg_imm_en), + .i_clr_lsb (bufreg_clr_lsb), .o_lsb (lsb), .o_reg (bufreg_out), .o_q (bufreg_q));