blob: 5be272369e1b0ebf9681d2aa936d35e7d5ab605f [file] [log] [blame]
module ibex_id_stage (
clk,
rst_n,
test_en_i,
fetch_enable_i,
ctrl_busy_o,
core_ctrl_firstfetch_o,
is_decoding_o,
instr_valid_i,
instr_rdata_i,
instr_req_o,
branch_decision_i,
clear_instr_valid_o,
pc_set_o,
pc_mux_o,
exc_pc_mux_o,
illegal_c_insn_i,
is_compressed_i,
pc_id_i,
halt_if_o,
id_ready_o,
ex_ready_i,
id_valid_o,
alu_operator_ex_o,
alu_operand_a_ex_o,
alu_operand_b_ex_o,
mult_en_ex_o,
div_en_ex_o,
multdiv_operator_ex_o,
multdiv_signed_mode_ex_o,
multdiv_operand_a_ex_o,
multdiv_operand_b_ex_o,
eFPGA_en_o,
eFPGA_operator_o,
eFPGA_operand_a_o,
eFPGA_operand_b_o,
eFPGA_delay_o,
csr_access_ex_o,
csr_op_ex_o,
csr_cause_o,
csr_save_if_o,
csr_save_id_o,
csr_restore_mret_id_o,
csr_restore_dret_id_o,
csr_save_cause_o,
data_req_ex_o,
data_we_ex_o,
data_type_ex_o,
data_sign_ext_ex_o,
data_reg_offset_ex_o,
data_wdata_ex_o,
data_misaligned_i,
misaligned_addr_i,
irq_i,
irq_id_i,
m_irq_enable_i,
irq_ack_o,
irq_id_o,
exc_cause_o,
lsu_load_err_i,
lsu_store_err_i,
debug_cause_o,
debug_csr_save_o,
debug_req_i,
debug_single_step_i,
debug_ebreakm_i,
regfile_wdata_lsu_i,
regfile_wdata_ex_i,
csr_rdata_i,
perf_jump_o,
perf_branch_o,
perf_tbranch_o
);
parameter [0:0] RV32M = 1;
parameter [0:0] RV32E = 0;
input wire clk;
input wire rst_n;
input wire test_en_i;
input wire fetch_enable_i;
output wire ctrl_busy_o;
output wire core_ctrl_firstfetch_o;
output wire is_decoding_o;
input wire instr_valid_i;
input wire [31:0] instr_rdata_i;
output wire instr_req_o;
input wire branch_decision_i;
output wire clear_instr_valid_o;
output wire pc_set_o;
output wire [2:0] pc_mux_o;
output wire [2:0] exc_pc_mux_o;
input wire illegal_c_insn_i;
input wire is_compressed_i;
input wire [31:0] pc_id_i;
output wire halt_if_o;
output wire id_ready_o;
input wire ex_ready_i;
output wire id_valid_o;
output wire [4:0] alu_operator_ex_o;
output wire [31:0] alu_operand_a_ex_o;
output wire [31:0] alu_operand_b_ex_o;
output wire mult_en_ex_o;
output wire div_en_ex_o;
output wire [1:0] multdiv_operator_ex_o;
output wire [1:0] multdiv_signed_mode_ex_o;
output wire [31:0] multdiv_operand_a_ex_o;
output wire [31:0] multdiv_operand_b_ex_o;
output wire eFPGA_en_o;
output wire [1:0] eFPGA_operator_o;
output wire [31:0] eFPGA_operand_a_o;
output wire [31:0] eFPGA_operand_b_o;
output wire [3:0] eFPGA_delay_o;
output wire csr_access_ex_o;
output wire [1:0] csr_op_ex_o;
output wire [5:0] csr_cause_o;
output wire csr_save_if_o;
output wire csr_save_id_o;
output wire csr_restore_mret_id_o;
output wire csr_restore_dret_id_o;
output wire csr_save_cause_o;
output wire data_req_ex_o;
output wire data_we_ex_o;
output wire [1:0] data_type_ex_o;
output wire data_sign_ext_ex_o;
output wire [1:0] data_reg_offset_ex_o;
output wire [31:0] data_wdata_ex_o;
input wire data_misaligned_i;
input wire [31:0] misaligned_addr_i;
input wire irq_i;
input wire [4:0] irq_id_i;
input wire m_irq_enable_i;
output wire irq_ack_o;
output wire [4:0] irq_id_o;
output wire [5:0] exc_cause_o;
input wire lsu_load_err_i;
input wire lsu_store_err_i;
output wire [2:0] debug_cause_o;
output wire debug_csr_save_o;
input wire debug_req_i;
input wire debug_single_step_i;
input wire debug_ebreakm_i;
input wire [31:0] regfile_wdata_lsu_i;
input wire [31:0] regfile_wdata_ex_i;
input wire [31:0] csr_rdata_i;
output wire perf_jump_o;
output reg perf_branch_o;
output wire perf_tbranch_o;
wire [31:0] instr;
wire deassert_we;
wire illegal_insn_dec;
wire illegal_reg_rv32e;
wire ebrk_insn;
wire mret_insn_dec;
wire dret_insn_dec;
wire ecall_insn_dec;
wire pipe_flush_dec;
wire branch_in_id;
reg branch_set_n;
reg branch_set_q;
reg branch_mux_dec;
reg jump_set;
reg jump_mux_dec;
wire jump_in_id;
reg instr_multicyle;
reg load_stall;
reg multdiv_stall;
reg branch_stall;
reg jump_stall;
reg eFPGA_stall;
wire halt_id;
reg regfile_we;
reg select_data_rf;
wire [31:0] imm_i_type;
wire [31:0] imm_s_type;
wire [31:0] imm_b_type;
wire [31:0] imm_u_type;
wire [31:0] imm_j_type;
wire [31:0] zimm_rs1_type;
wire [31:0] imm_a;
reg [31:0] imm_b;
wire irq_req_ctrl;
wire [4:0] irq_id_ctrl;
wire exc_ack;
wire exc_kill;
wire [4:0] regfile_addr_ra_id;
wire [4:0] regfile_addr_rb_id;
wire [4:0] regfile_alu_waddr_id;
wire regfile_we_id;
wire [31:0] regfile_data_ra_id;
wire [31:0] regfile_data_rb_id;
wire [4:0] alu_operator;
wire [1:0] alu_op_a_mux_sel;
wire alu_op_b_mux_sel;
wire imm_a_mux_sel;
wire [2:0] imm_b_mux_sel;
wire mult_int_en;
wire div_int_en;
wire multdiv_int_en;
wire [1:0] multdiv_operator;
wire [1:0] multdiv_signed_mode;
wire eFPGA_en;
wire eFPGA_int_en;
wire [1:0] eFPGA_operator;
wire [3:0] eFPGA_delay;
assign eFPGA_en_o = eFPGA_int_en;
wire data_we_id;
wire [1:0] data_type_id;
wire data_sign_ext_id;
wire [1:0] data_reg_offset_id;
wire data_req_id;
wire csr_access;
wire [1:0] csr_op;
wire csr_status;
wire operand_a_fw_mux_sel;
wire [31:0] operand_a_fw_id;
reg [31:0] alu_operand_a;
wire [31:0] alu_operand_b;
assign instr = instr_rdata_i;
assign imm_i_type = {{20 {instr[31]}}, instr[31:20]};
assign imm_s_type = {{20 {instr[31]}}, instr[31:25], instr[11:7]};
assign imm_b_type = {{19 {instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0};
assign imm_u_type = {instr[31:12], 12'b000000000000};
assign imm_j_type = {{12 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0};
assign zimm_rs1_type = {27'b000000000000000000000000000, instr[19:15]};
assign regfile_addr_ra_id = instr[19:15];
assign regfile_addr_rb_id = instr[24:20];
assign regfile_alu_waddr_id = instr[11:7];
assign illegal_reg_rv32e = 1'b0;
assign clear_instr_valid_o = id_ready_o | halt_id;
localparam [1:0] ibex_defines_OP_A_CURRPC = 1;
localparam [1:0] ibex_defines_OP_A_IMM = 2;
localparam [1:0] ibex_defines_OP_A_REGA_OR_FWD = 0;
always @(*) begin : alu_operand_a_mux
case (alu_op_a_mux_sel)
ibex_defines_OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id;
ibex_defines_OP_A_CURRPC: alu_operand_a = pc_id_i;
ibex_defines_OP_A_IMM: alu_operand_a = imm_a;
default: alu_operand_a = operand_a_fw_id;
endcase
end
localparam [0:0] ibex_defines_IMM_A_Z = 0;
assign imm_a = (imm_a_mux_sel == ibex_defines_IMM_A_Z ? zimm_rs1_type : {32 {1'sb0}});
localparam [0:0] ibex_defines_SEL_MISALIGNED = 1;
assign operand_a_fw_id = (operand_a_fw_mux_sel == ibex_defines_SEL_MISALIGNED ? misaligned_addr_i : regfile_data_ra_id);
localparam [2:0] ibex_defines_IMM_B_B = 2;
localparam [2:0] ibex_defines_IMM_B_I = 0;
localparam [2:0] ibex_defines_IMM_B_J = 4;
localparam [2:0] ibex_defines_IMM_B_PCINCR = 5;
localparam [2:0] ibex_defines_IMM_B_S = 1;
localparam [2:0] ibex_defines_IMM_B_U = 3;
always @(*) begin : immediate_b_mux
case (imm_b_mux_sel)
ibex_defines_IMM_B_I: imm_b = imm_i_type;
ibex_defines_IMM_B_S: imm_b = imm_s_type;
ibex_defines_IMM_B_B: imm_b = imm_b_type;
ibex_defines_IMM_B_U: imm_b = imm_u_type;
ibex_defines_IMM_B_J: imm_b = imm_j_type;
ibex_defines_IMM_B_PCINCR: imm_b = (is_compressed_i && !data_misaligned_i ? 32'h00000002 : 32'h00000004);
default: imm_b = imm_i_type;
endcase
end
localparam [0:0] ibex_defines_OP_B_IMM = 1;
assign alu_operand_b = (alu_op_b_mux_sel == ibex_defines_OP_B_IMM ? imm_b : regfile_data_rb_id);
reg [31:0] regfile_wdata_mux;
reg regfile_we_mux;
reg [4:0] regfile_waddr_mux;
localparam [0:0] RF_LSU = 0;
always @(*) begin
regfile_we_mux = regfile_we;
regfile_waddr_mux = regfile_alu_waddr_id;
if (select_data_rf == RF_LSU)
regfile_wdata_mux = regfile_wdata_lsu_i;
else if (csr_access)
regfile_wdata_mux = csr_rdata_i;
else
regfile_wdata_mux = regfile_wdata_ex_i;
end
ibex_register_file #(.RV32E(RV32E)) registers_i(
.clk(clk),
.rst_n(rst_n),
.test_en_i(test_en_i),
.raddr_a_i(regfile_addr_ra_id),
.rdata_a_o(regfile_data_ra_id),
.raddr_b_i(regfile_addr_rb_id),
.rdata_b_o(regfile_data_rb_id),
.waddr_a_i(regfile_waddr_mux),
.wdata_a_i(regfile_wdata_mux),
.we_a_i(regfile_we_mux)
);
assign multdiv_int_en = mult_int_en | div_int_en;
ibex_decoder #(.RV32M(RV32M)) decoder_i(
.deassert_we_i(deassert_we),
.data_misaligned_i(data_misaligned_i),
.branch_mux_i(branch_mux_dec),
.jump_mux_i(jump_mux_dec),
.illegal_insn_o(illegal_insn_dec),
.ebrk_insn_o(ebrk_insn),
.mret_insn_o(mret_insn_dec),
.dret_insn_o(dret_insn_dec),
.ecall_insn_o(ecall_insn_dec),
.pipe_flush_o(pipe_flush_dec),
.instr_rdata_i(instr),
.illegal_c_insn_i(illegal_c_insn_i),
.alu_operator_o(alu_operator),
.alu_op_a_mux_sel_o(alu_op_a_mux_sel),
.alu_op_b_mux_sel_o(alu_op_b_mux_sel),
.imm_a_mux_sel_o(imm_a_mux_sel),
.imm_b_mux_sel_o(imm_b_mux_sel),
.mult_int_en_o(mult_int_en),
.div_int_en_o(div_int_en),
.multdiv_operator_o(multdiv_operator),
.multdiv_signed_mode_o(multdiv_signed_mode),
.regfile_we_o(regfile_we_id),
.csr_access_o(csr_access),
.csr_op_o(csr_op),
.csr_status_o(csr_status),
.data_req_o(data_req_id),
.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_in_id_o(jump_in_id),
.branch_in_id_o(branch_in_id),
.eFPGA_operator_o(eFPGA_operator),
.eFPGA_int_en_o(eFPGA_int_en),
.eFPGA_delay_o(eFPGA_delay)
);
assign eFPGA_operator_o = eFPGA_operator;
assign eFPGA_delay_o = eFPGA_delay;
ibex_controller controller_i(
.clk(clk),
.rst_n(rst_n),
.fetch_enable_i(fetch_enable_i),
.ctrl_busy_o(ctrl_busy_o),
.first_fetch_o(core_ctrl_firstfetch_o),
.is_decoding_o(is_decoding_o),
.deassert_we_o(deassert_we),
.illegal_insn_i(illegal_insn_dec | illegal_reg_rv32e),
.ecall_insn_i(ecall_insn_dec),
.mret_insn_i(mret_insn_dec),
.dret_insn_i(dret_insn_dec),
.pipe_flush_i(pipe_flush_dec),
.ebrk_insn_i(ebrk_insn),
.csr_status_i(csr_status),
.instr_valid_i(instr_valid_i),
.instr_req_o(instr_req_o),
.pc_set_o(pc_set_o),
.pc_mux_o(pc_mux_o),
.exc_pc_mux_o(exc_pc_mux_o),
.exc_cause_o(exc_cause_o),
.data_misaligned_i(data_misaligned_i),
.branch_in_id_i(branch_in_id),
.branch_set_i(branch_set_q),
.jump_set_i(jump_set),
.instr_multicyle_i(instr_multicyle),
.irq_i(irq_i),
.irq_req_ctrl_i(irq_req_ctrl),
.irq_id_ctrl_i(irq_id_ctrl),
.m_IE_i(m_irq_enable_i),
.irq_ack_o(irq_ack_o),
.irq_id_o(irq_id_o),
.exc_ack_o(exc_ack),
.exc_kill_o(exc_kill),
.csr_save_cause_o(csr_save_cause_o),
.csr_cause_o(csr_cause_o),
.csr_save_if_o(csr_save_if_o),
.csr_save_id_o(csr_save_id_o),
.csr_restore_mret_id_o(csr_restore_mret_id_o),
.csr_restore_dret_id_o(csr_restore_dret_id_o),
.debug_cause_o(debug_cause_o),
.debug_csr_save_o(debug_csr_save_o),
.debug_req_i(debug_req_i),
.debug_single_step_i(debug_single_step_i),
.debug_ebreakm_i(debug_ebreakm_i),
.operand_a_fw_mux_sel_o(operand_a_fw_mux_sel),
.halt_if_o(halt_if_o),
.halt_id_o(halt_id),
.id_ready_i(id_ready_o),
.perf_jump_o(perf_jump_o),
.perf_tbranch_o(perf_tbranch_o)
);
ibex_int_controller int_controller_i(
.clk(clk),
.rst_n(rst_n),
.irq_req_ctrl_o(irq_req_ctrl),
.irq_id_ctrl_o(irq_id_ctrl),
.ctrl_ack_i(exc_ack),
.ctrl_kill_i(exc_kill),
.irq_i(irq_i),
.irq_id_i(irq_id_i),
.m_IE_i(m_irq_enable_i)
);
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;
assign alu_operand_a_ex_o = alu_operand_a;
assign alu_operand_b_ex_o = alu_operand_b;
assign csr_access_ex_o = csr_access;
assign csr_op_ex_o = csr_op;
assign mult_en_ex_o = mult_int_en;
assign div_en_ex_o = div_int_en;
assign multdiv_operator_ex_o = multdiv_operator;
assign multdiv_signed_mode_ex_o = multdiv_signed_mode;
assign multdiv_operand_a_ex_o = regfile_data_ra_id;
assign multdiv_operand_b_ex_o = regfile_data_rb_id;
assign eFPGA_operand_a_o = regfile_data_ra_id;
assign eFPGA_operand_b_o = regfile_data_rb_id;
reg id_wb_fsm_cs;
reg id_wb_fsm_ns;
localparam [0:0] IDLE = 0;
always @(posedge clk or negedge rst_n) begin : EX_WB_Pipeline_Register
if (!rst_n) begin
id_wb_fsm_cs <= IDLE;
branch_set_q <= 1'b0;
end
else begin
id_wb_fsm_cs <= id_wb_fsm_ns;
branch_set_q <= branch_set_n;
end
end
localparam [0:0] RF_EX = 1;
localparam [0:0] WAIT_MULTICYCLE = 1;
always @(*) begin
id_wb_fsm_ns = id_wb_fsm_cs;
regfile_we = regfile_we_id;
load_stall = 1'b0;
multdiv_stall = 1'b0;
eFPGA_stall = 1'b0;
jump_stall = 1'b0;
branch_stall = 1'b0;
select_data_rf = RF_EX;
instr_multicyle = 1'b0;
branch_set_n = 1'b0;
branch_mux_dec = 1'b0;
jump_set = 1'b0;
jump_mux_dec = 1'b0;
perf_branch_o = 1'b0;
case (id_wb_fsm_cs)
IDLE: begin
jump_mux_dec = 1'b1;
branch_mux_dec = 1'b1;
case (1'b1)
data_req_id: begin
regfile_we = 1'b0;
id_wb_fsm_ns = WAIT_MULTICYCLE;
load_stall = 1'b1;
instr_multicyle = 1'b1;
end
branch_in_id: begin
id_wb_fsm_ns = (branch_decision_i ? WAIT_MULTICYCLE : IDLE);
branch_stall = branch_decision_i;
instr_multicyle = branch_decision_i;
branch_set_n = branch_decision_i;
perf_branch_o = 1'b1;
end
multdiv_int_en: begin
regfile_we = 1'b0;
id_wb_fsm_ns = WAIT_MULTICYCLE;
multdiv_stall = 1'b1;
instr_multicyle = 1'b1;
end
eFPGA_int_en: begin
regfile_we = 1'b0;
id_wb_fsm_ns = WAIT_MULTICYCLE;
eFPGA_stall = 1'b1;
instr_multicyle = 1'b1;
end
jump_in_id: begin
regfile_we = 1'b0;
id_wb_fsm_ns = WAIT_MULTICYCLE;
jump_stall = 1'b1;
instr_multicyle = 1'b1;
jump_set = 1'b1;
end
default:
;
endcase
end
WAIT_MULTICYCLE:
if (ex_ready_i) begin
regfile_we = regfile_we_id;
id_wb_fsm_ns = IDLE;
load_stall = 1'b0;
multdiv_stall = 1'b0;
eFPGA_stall = 1'b0;
select_data_rf = (data_req_id ? RF_LSU : RF_EX);
end
else begin
regfile_we = 1'b0;
instr_multicyle = 1'b1;
case (1'b1)
data_req_id: load_stall = 1'b1;
multdiv_int_en: multdiv_stall = 1'b1;
eFPGA_int_en: eFPGA_stall = 1'b1;
default:
;
endcase
end
default:
;
endcase
end
assign id_ready_o = (((~load_stall & ~branch_stall) & ~jump_stall) & ~multdiv_stall) & ~eFPGA_stall;
assign id_valid_o = ~halt_id & id_ready_o;
endmodule