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
This commit is contained in:
Olof Kindgren 2019-09-26 20:21:36 +02:00
parent ab39209773
commit 75decc8251
4 changed files with 49 additions and 31 deletions

View file

@ -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

View file

@ -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
(

View file

@ -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

View file

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