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));