Move logic to ignore decoder output out of decoder into ID stage

The decoder shall decode the instruction only. The handling of stalls
is not related to instruction decoding.
This commit is contained in:
Pirmin Vogel 2019-07-01 13:10:29 +01:00
parent 6d09fb1060
commit d973618ce8
3 changed files with 77 additions and 87 deletions

View file

@ -514,8 +514,9 @@ module ibex_controller (
// Stall control //
///////////////////
// deassert WE when the core is not decoding instructions
// or in case of illegal instruction
// deassert write enable when the core is not decoding instructions, i.e., current instruction
// in ID stage done, but waiting for next instruction from IF stage, or in case of illegal
// instruction
assign deassert_we_o = ~is_decoding_o | illegal_insn_i;
// update registers

View file

@ -28,8 +28,6 @@ module ibex_decoder #(
parameter bit RV32M = 1
) (
// singals running to/from controller
input logic deassert_we_i, // deassert we, we are stalled or
// not active
input logic branch_mux_i,
input logic jump_mux_i,
output logic illegal_insn_o, // illegal instr encountered
@ -55,8 +53,8 @@ module ibex_decoder #(
output ibex_defines::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b
// MUL, DIV related control signals
output logic mult_int_en_o, // perform integer multiplication
output logic div_int_en_o, // perform integer division or
output logic mult_en_o, // perform integer multiplication
output logic div_en_o, // perform integer division or
// remainder
output ibex_defines::md_op_e multdiv_operator_o,
output logic [1:0] multdiv_signed_mode_o,
@ -79,21 +77,12 @@ module ibex_decoder #(
output logic [1:0] data_reg_offset_o, // register byte offset for stores
// jump/branches
output logic jump_in_id_o, // jump is being calculated in ALU
output logic branch_in_id_o
output logic jump_in_dec_o, // jump is being calculated in ALU
output logic branch_in_dec_o
);
import ibex_defines::*;
// write enable/request control
logic regfile_we;
logic data_req;
logic mult_int_en;
logic div_int_en;
logic branch_in_id;
logic jump_in_id;
logic csr_illegal;
opcode_e opcode;
@ -103,8 +92,8 @@ module ibex_decoder #(
/////////////
always_comb begin
jump_in_id = 1'b0;
branch_in_id = 1'b0;
jump_in_dec_o = 1'b0;
branch_in_dec_o = 1'b0;
alu_operator_o = ALU_SLTU;
alu_op_a_mux_sel_o = OP_A_REG_A;
alu_op_b_mux_sel_o = OP_B_REG_B;
@ -112,12 +101,12 @@ module ibex_decoder #(
imm_a_mux_sel_o = IMM_A_ZERO;
imm_b_mux_sel_o = IMM_B_I;
mult_int_en = 1'b0;
div_int_en = 1'b0;
mult_en_o = 1'b0;
div_en_o = 1'b0;
multdiv_operator_o = MD_OP_MULL;
multdiv_signed_mode_o = 2'b00;
regfile_we = 1'b0;
regfile_we_o = 1'b0;
csr_access_o = 1'b0;
csr_status_o = 1'b0;
@ -128,7 +117,7 @@ module ibex_decoder #(
data_type_o = 2'b00;
data_sign_extension_o = 1'b0;
data_reg_offset_o = 2'b00;
data_req = 1'b0;
data_req_o = 1'b0;
illegal_insn_o = 1'b0;
ebrk_insn_o = 1'b0;
@ -146,50 +135,50 @@ module ibex_decoder #(
///////////
OPCODE_JAL: begin // Jump and Link
jump_in_id = 1'b1;
jump_in_dec_o = 1'b1;
if (jump_mux_i) begin
// Calculate jump target
alu_op_a_mux_sel_o = OP_A_CURRPC;
alu_op_b_mux_sel_o = OP_B_IMM;
imm_b_mux_sel_o = IMM_B_J;
alu_operator_o = ALU_ADD;
regfile_we = 1'b0;
regfile_we_o = 1'b0;
end else begin
// Calculate and store PC+4
alu_op_a_mux_sel_o = OP_A_CURRPC;
alu_op_b_mux_sel_o = OP_B_IMM;
imm_b_mux_sel_o = IMM_B_INCR_PC;
alu_operator_o = ALU_ADD;
regfile_we = 1'b1;
regfile_we_o = 1'b1;
end
end
OPCODE_JALR: begin // Jump and Link Register
jump_in_id = 1'b1;
jump_in_dec_o = 1'b1;
if (jump_mux_i) begin
// Calculate jump target
alu_op_a_mux_sel_o = OP_A_REG_A;
alu_op_b_mux_sel_o = OP_B_IMM;
imm_b_mux_sel_o = IMM_B_I;
alu_operator_o = ALU_ADD;
regfile_we = 1'b0;
regfile_we_o = 1'b0;
end else begin
// Calculate and store PC+4
alu_op_a_mux_sel_o = OP_A_CURRPC;
alu_op_b_mux_sel_o = OP_B_IMM;
imm_b_mux_sel_o = IMM_B_INCR_PC;
alu_operator_o = ALU_ADD;
regfile_we = 1'b1;
regfile_we_o = 1'b1;
end
if (instr_rdata_i[14:12] != 3'b0) begin
jump_in_id = 1'b0;
regfile_we = 1'b0;
jump_in_dec_o = 1'b0;
regfile_we_o = 1'b0;
illegal_insn_o = 1'b1;
end
end
OPCODE_BRANCH: begin // Branch
branch_in_id = 1'b1;
branch_in_dec_o = 1'b1;
if (branch_mux_i) begin
unique case (instr_rdata_i[14:12])
3'b000: alu_operator_o = ALU_EQ;
@ -206,17 +195,16 @@ module ibex_decoder #(
alu_op_b_mux_sel_o = OP_B_IMM;
imm_b_mux_sel_o = IMM_B_B;
alu_operator_o = ALU_ADD;
regfile_we = 1'b0;
regfile_we_o = 1'b0;
end
end
////////////////
// Load/store //
////////////////
OPCODE_STORE: begin
data_req = 1'b1;
data_req_o = 1'b1;
data_we_o = 1'b1;
alu_operator_o = ALU_ADD;
@ -226,7 +214,7 @@ module ibex_decoder #(
alu_op_b_mux_sel_o = OP_B_IMM;
end else begin
// Register offset is illegal since no register c available
data_req = 1'b0;
data_req_o = 1'b0;
data_we_o = 1'b0;
illegal_insn_o = 1'b1;
end
@ -237,7 +225,7 @@ module ibex_decoder #(
2'b01: data_type_o = 2'b01; // SH
2'b10: data_type_o = 2'b00; // SW
default: begin
data_req = 1'b0;
data_req_o = 1'b0;
data_we_o = 1'b0;
illegal_insn_o = 1'b1;
end
@ -245,8 +233,8 @@ module ibex_decoder #(
end
OPCODE_LOAD: begin
data_req = 1'b1;
regfile_we = 1'b1;
data_req_o = 1'b1;
regfile_we_o = 1'b1;
data_type_o = 2'b00;
// offset from immediate
@ -292,7 +280,6 @@ module ibex_decoder #(
end
end
/////////
// ALU //
/////////
@ -303,7 +290,7 @@ module ibex_decoder #(
imm_a_mux_sel_o = IMM_A_ZERO;
imm_b_mux_sel_o = IMM_B_U;
alu_operator_o = ALU_ADD;
regfile_we = 1'b1;
regfile_we_o = 1'b1;
end
OPCODE_AUIPC: begin // Add Upper Immediate to PC
@ -311,13 +298,13 @@ module ibex_decoder #(
alu_op_b_mux_sel_o = OP_B_IMM;
imm_b_mux_sel_o = IMM_B_U;
alu_operator_o = ALU_ADD;
regfile_we = 1'b1;
regfile_we_o = 1'b1;
end
OPCODE_OPIMM: begin // Register-Immediate ALU Operations
alu_op_b_mux_sel_o = OP_B_IMM;
imm_b_mux_sel_o = IMM_B_I;
regfile_we = 1'b1;
regfile_we_o = 1'b1;
unique case (instr_rdata_i[14:12])
3'b000: alu_operator_o = ALU_ADD; // Add Immediate
@ -351,7 +338,7 @@ module ibex_decoder #(
end
OPCODE_OP: begin // Register-Register ALU operation
regfile_we = 1'b1;
regfile_we_o = 1'b1;
if (instr_rdata_i[31]) begin
illegal_insn_o = 1'b1;
@ -373,56 +360,56 @@ module ibex_decoder #(
{6'b00_0001, 3'b000}: begin // mul
alu_operator_o = ALU_ADD;
multdiv_operator_o = MD_OP_MULL;
mult_int_en = 1'b1;
mult_en_o = RV32M ? 1'b1 : 1'b0;
multdiv_signed_mode_o = 2'b00;
illegal_insn_o = RV32M ? 1'b0 : 1'b1;
end
{6'b00_0001, 3'b001}: begin // mulh
alu_operator_o = ALU_ADD;
multdiv_operator_o = MD_OP_MULH;
mult_int_en = 1'b1;
mult_en_o = RV32M ? 1'b1 : 1'b0;
multdiv_signed_mode_o = 2'b11;
illegal_insn_o = RV32M ? 1'b0 : 1'b1;
end
{6'b00_0001, 3'b010}: begin // mulhsu
alu_operator_o = ALU_ADD;
multdiv_operator_o = MD_OP_MULH;
mult_int_en = 1'b1;
mult_en_o = RV32M ? 1'b1 : 1'b0;
multdiv_signed_mode_o = 2'b01;
illegal_insn_o = RV32M ? 1'b0 : 1'b1;
end
{6'b00_0001, 3'b011}: begin // mulhu
alu_operator_o = ALU_ADD;
multdiv_operator_o = MD_OP_MULH;
mult_int_en = 1'b1;
mult_en_o = RV32M ? 1'b1 : 1'b0;
multdiv_signed_mode_o = 2'b00;
illegal_insn_o = RV32M ? 1'b0 : 1'b1;
end
{6'b00_0001, 3'b100}: begin // div
alu_operator_o = ALU_ADD;
multdiv_operator_o = MD_OP_DIV;
div_int_en = 1'b1;
div_en_o = RV32M ? 1'b1 : 1'b0;
multdiv_signed_mode_o = 2'b11;
illegal_insn_o = RV32M ? 1'b0 : 1'b1;
end
{6'b00_0001, 3'b101}: begin // divu
alu_operator_o = ALU_ADD;
multdiv_operator_o = MD_OP_DIV;
div_int_en = 1'b1;
div_en_o = RV32M ? 1'b1 : 1'b0;
multdiv_signed_mode_o = 2'b00;
illegal_insn_o = RV32M ? 1'b0 : 1'b1;
end
{6'b00_0001, 3'b110}: begin // rem
alu_operator_o = ALU_ADD;
multdiv_operator_o = MD_OP_REM;
div_int_en = 1'b1;
div_en_o = RV32M ? 1'b1 : 1'b0;
multdiv_signed_mode_o = 2'b11;
illegal_insn_o = RV32M ? 1'b0 : 1'b1;
end
{6'b00_0001, 3'b111}: begin // remu
alu_operator_o = ALU_ADD;
multdiv_operator_o = MD_OP_REM;
div_int_en = 1'b1;
div_en_o = RV32M ? 1'b1 : 1'b0;
multdiv_signed_mode_o = 2'b00;
illegal_insn_o = RV32M ? 1'b0 : 1'b1;
end
@ -446,7 +433,7 @@ module ibex_decoder #(
// an illegal instruction.
if (instr_rdata_i[14:12] == 3'b000) begin
alu_operator_o = ALU_ADD; // nop
regfile_we = 1'b0;
regfile_we_o = 1'b0;
end else begin
illegal_insn_o = 1'b1;
end
@ -480,7 +467,7 @@ module ibex_decoder #(
end else begin
// instruction to read/modify CSR
csr_access_o = 1'b1;
regfile_we = 1'b1;
regfile_we_o = 1'b1;
alu_op_b_mux_sel_o = OP_B_IMM;
imm_a_mux_sel_o = IMM_A_Z;
imm_b_mux_sel_o = IMM_B_I; // CSR address is encoded in I imm
@ -525,12 +512,4 @@ module ibex_decoder #(
end
end
// deassert we signals (in case of stalls)
assign regfile_we_o = (deassert_we_i) ? 1'b0 : regfile_we;
assign mult_int_en_o = RV32M ? ((deassert_we_i) ? 1'b0 : mult_int_en) : 1'b0;
assign div_int_en_o = RV32M ? ((deassert_we_i) ? 1'b0 : div_int_en ) : 1'b0;
assign data_req_o = (deassert_we_i) ? 1'b0 : data_req;
assign jump_in_id_o = (deassert_we_i) ? 1'b0 : jump_in_id;
assign branch_in_id_o = (deassert_we_i) ? 1'b0 : branch_in_id;
endmodule // controller

View file

@ -166,13 +166,12 @@ module ibex_id_stage #(
logic ecall_insn_dec;
logic pipe_flush_dec;
logic branch_in_id;
logic branch_set_n;
logic branch_set_q;
logic branch_in_id, branch_in_dec;
logic branch_set_n, branch_set_q;
logic branch_mux_dec;
logic jump_set;
logic jump_mux_dec;
logic jump_in_id;
logic jump_in_id, jump_in_dec;
logic instr_multicyle;
logic load_stall;
@ -222,9 +221,9 @@ module ibex_id_stage #(
imm_b_sel_e imm_b_mux_sel, imm_b_mux_sel_dec;
// Multiplier Control
logic mult_int_en; // use integer multiplier
logic div_int_en; // use integer division or reminder
logic multdiv_int_en;
logic mult_en_id, mult_en_dec; // use integer multiplier
logic div_en_id, div_en_dec; // use integer division or reminder
logic multdiv_en_id;
md_op_e multdiv_operator;
logic [1:0] multdiv_signed_mode;
@ -233,7 +232,7 @@ module ibex_id_stage #(
logic [1:0] data_type_id;
logic data_sign_ext_id;
logic [1:0] data_reg_offset_id;
logic data_req_id;
logic data_req_id, data_req_dec;
// CSR control
logic csr_access;
@ -291,7 +290,7 @@ module ibex_id_stage #(
assign imm_b_mux_sel = data_misaligned_i ? IMM_B_INCR_ADDR : imm_b_mux_sel_dec;
// do not write back the second address since the first calculated address was the correct one
assign regfile_we_id = data_misaligned_i ? 1'b0 : regfile_we_dec;
assign regfile_we_id = data_misaligned_i ? 1'b0 : regfile_we_dec & ~deassert_we;
///////////////
// Operand A //
@ -388,15 +387,12 @@ module ibex_id_stage #(
assign rfvi_reg_we_o = regfile_we;
`endif
assign multdiv_int_en = mult_int_en | div_int_en;
/////////////
// Decoder //
/////////////
ibex_decoder #( .RV32M ( RV32M ) ) decoder_i (
// controller related signals
.deassert_we_i ( deassert_we ),
.branch_mux_i ( branch_mux_dec ),
.jump_mux_i ( jump_mux_dec ),
@ -419,11 +415,12 @@ module ibex_id_stage #(
.imm_a_mux_sel_o ( imm_a_mux_sel ),
.imm_b_mux_sel_o ( imm_b_mux_sel_dec ),
.mult_int_en_o ( mult_int_en ),
.div_int_en_o ( div_int_en ),
.mult_en_o ( mult_en_dec ),
.div_en_o ( div_en_dec ),
.multdiv_operator_o ( multdiv_operator ),
.multdiv_signed_mode_o ( multdiv_signed_mode ),
// Register file control signals
// register file control signals
.regfile_we_o ( regfile_we_dec ),
// CSR control signals
@ -432,15 +429,15 @@ module ibex_id_stage #(
.csr_status_o ( csr_status ),
// Data bus interface
.data_req_o ( data_req_id ),
.data_req_o ( data_req_dec ),
.data_we_o ( data_we_id ),
.data_type_o ( data_type_id ),
.data_sign_extension_o ( data_sign_ext_id ),
.data_reg_offset_o ( data_reg_offset_id ),
// jump/branches
.jump_in_id_o ( jump_in_id ),
.branch_in_id_o ( branch_in_id )
.jump_in_dec_o ( jump_in_dec ),
.branch_in_dec_o ( branch_in_dec )
);
@ -569,15 +566,26 @@ module ibex_id_stage #(
.m_IE_i ( m_irq_enable_i )
);
//////////////
// ID-EX/WB //
//////////////
// Do not forward decoder output to EX or WB if:
// - current instr is already done, ID waiting for IF stage
// - current instr is illegal
assign data_req_id = deassert_we ? 1'b0 : data_req_dec;
assign mult_en_id = deassert_we ? 1'b0 : mult_en_dec;
assign div_en_id = deassert_we ? 1'b0 : div_en_dec;
assign jump_in_id = deassert_we ? 1'b0 : jump_in_dec;
assign branch_in_id = deassert_we ? 1'b0 : branch_in_dec;
///////////
// ID-EX //
///////////
assign data_req_ex_o = data_req_id;
assign data_we_ex_o = data_we_id;
assign data_type_ex_o = data_type_id;
assign data_sign_ext_ex_o = data_sign_ext_id;
assign data_wdata_ex_o = regfile_data_rb_id;
assign data_req_ex_o = data_req_id;
assign data_reg_offset_ex_o = data_reg_offset_id;
assign alu_operator_ex_o = alu_operator;
@ -586,8 +594,8 @@ module ibex_id_stage #(
assign csr_access_ex_o = csr_access;
assign mult_en_ex_o = mult_int_en;
assign div_en_ex_o = div_int_en;
assign mult_en_ex_o = mult_en_id;
assign div_en_ex_o = div_en_id;
assign multdiv_operator_ex_o = multdiv_operator;
assign multdiv_signed_mode_ex_o = multdiv_signed_mode;
@ -613,6 +621,8 @@ module ibex_id_stage #(
//////////////////
// ID-EX/WB FSM //
//////////////////
assign multdiv_en_id = mult_en_id | div_en_id;
always_comb begin : id_wb_fsm
id_wb_fsm_ns = id_wb_fsm_cs;
regfile_we = regfile_we_id;
@ -649,7 +659,7 @@ module ibex_id_stage #(
branch_set_n = branch_decision_i;
perf_branch_o = 1'b1;
end
multdiv_int_en: begin
multdiv_en_id: begin
//MUL or DIV operation
regfile_we = 1'b0;
id_wb_fsm_ns = WAIT_MULTICYCLE;
@ -681,7 +691,7 @@ module ibex_id_stage #(
unique case (1'b1)
data_req_id:
load_stall = 1'b1;
multdiv_int_en:
multdiv_en_id:
multdiv_stall = 1'b1;
default:;
endcase
@ -719,7 +729,7 @@ module ibex_id_stage #(
// make sure multicycles enable signals are unique
assert property (
@(posedge clk_i) ~(data_req_ex_o & multdiv_int_en )) else
@(posedge clk_i) ~(data_req_id & multdiv_en_id )) else
$display("Multicycles enable signals are not unique");
`endif