mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-19 19:47:27 -04:00
175 lines
6.4 KiB
Systemverilog
175 lines
6.4 KiB
Systemverilog
// Copyright lowRISC contributors.
|
|
// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
|
|
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
/**
|
|
* Execution stage
|
|
*
|
|
* Execution block: Hosts ALU and MUL/DIV unit
|
|
*/
|
|
module cve2_ex_block #(
|
|
parameter cve2_pkg::rv32m_e RV32M = cve2_pkg::RV32MFast,
|
|
parameter cve2_pkg::rv32b_e RV32B = cve2_pkg::RV32BNone
|
|
) (
|
|
input logic clk_i,
|
|
input logic rst_ni,
|
|
|
|
// ALU
|
|
input cve2_pkg::alu_op_e alu_operator_i,
|
|
input logic [31:0] alu_operand_a_i,
|
|
input logic [31:0] alu_operand_b_i,
|
|
input logic alu_instr_first_cycle_i,
|
|
|
|
// Multiplier/Divider
|
|
input cve2_pkg::md_op_e multdiv_operator_i,
|
|
input logic mult_en_i, // dynamic enable signal, for FSM control
|
|
input logic div_en_i, // dynamic enable signal, for FSM control
|
|
input logic mult_sel_i, // static decoder output, for data muxes
|
|
input logic div_sel_i, // static decoder output, for data muxes
|
|
input logic [1:0] multdiv_signed_mode_i,
|
|
input logic [31:0] multdiv_operand_a_i,
|
|
input logic [31:0] multdiv_operand_b_i,
|
|
|
|
// intermediate val reg
|
|
output logic [1:0] imd_val_we_o,
|
|
output logic [33:0] imd_val_d_o[2],
|
|
input logic [33:0] imd_val_q_i[2],
|
|
|
|
// Outputs
|
|
output logic [31:0] alu_adder_result_ex_o, // to LSU
|
|
output logic [31:0] result_ex_o,
|
|
output logic [31:0] branch_target_o, // to IF
|
|
output logic branch_decision_o, // to ID
|
|
|
|
output logic ex_valid_o // EX has valid output
|
|
);
|
|
|
|
import cve2_pkg::*;
|
|
|
|
logic [31:0] alu_result, multdiv_result;
|
|
|
|
logic [32:0] multdiv_alu_operand_b, multdiv_alu_operand_a;
|
|
logic [33:0] alu_adder_result_ext;
|
|
logic alu_cmp_result, alu_is_equal_result;
|
|
logic multdiv_valid;
|
|
logic multdiv_sel;
|
|
logic [31:0] alu_imd_val_q[2];
|
|
logic [31:0] alu_imd_val_d[2];
|
|
logic [ 1:0] alu_imd_val_we;
|
|
logic [33:0] multdiv_imd_val_d[2];
|
|
logic [ 1:0] multdiv_imd_val_we;
|
|
|
|
/*
|
|
The multdiv_i output is never selected if RV32M=RV32MNone
|
|
At synthesis time, all the combinational and sequential logic
|
|
from the multdiv_i module are eliminated
|
|
*/
|
|
if (RV32M != RV32MNone) begin : gen_multdiv_m
|
|
assign multdiv_sel = mult_sel_i | div_sel_i;
|
|
end else begin : gen_multdiv_no_m
|
|
assign multdiv_sel = 1'b0;
|
|
end
|
|
|
|
// Intermediate Value Register Mux
|
|
assign imd_val_d_o[0] = multdiv_sel ? multdiv_imd_val_d[0] : {2'b0, alu_imd_val_d[0]};
|
|
assign imd_val_d_o[1] = multdiv_sel ? multdiv_imd_val_d[1] : {2'b0, alu_imd_val_d[1]};
|
|
assign imd_val_we_o = multdiv_sel ? multdiv_imd_val_we : alu_imd_val_we;
|
|
|
|
assign alu_imd_val_q = '{imd_val_q_i[0][31:0], imd_val_q_i[1][31:0]};
|
|
|
|
assign result_ex_o = multdiv_sel ? multdiv_result : alu_result;
|
|
|
|
// branch handling
|
|
assign branch_decision_o = alu_cmp_result;
|
|
|
|
// Unused bt_operand signals cause lint errors, this avoids them
|
|
//logic [31:0] unused_bt_a_operand, unused_bt_b_operand;
|
|
|
|
assign branch_target_o = alu_adder_result_ex_o;
|
|
|
|
/////////
|
|
// ALU //
|
|
/////////
|
|
|
|
cve2_alu #(
|
|
.RV32B(RV32B)
|
|
) alu_i (
|
|
.operator_i (alu_operator_i),
|
|
.operand_a_i (alu_operand_a_i),
|
|
.operand_b_i (alu_operand_b_i),
|
|
.instr_first_cycle_i(alu_instr_first_cycle_i),
|
|
.imd_val_q_i (alu_imd_val_q),
|
|
.imd_val_we_o (alu_imd_val_we),
|
|
.imd_val_d_o (alu_imd_val_d),
|
|
.multdiv_operand_a_i(multdiv_alu_operand_a),
|
|
.multdiv_operand_b_i(multdiv_alu_operand_b),
|
|
.multdiv_sel_i (multdiv_sel),
|
|
.adder_result_o (alu_adder_result_ex_o),
|
|
.adder_result_ext_o (alu_adder_result_ext),
|
|
.result_o (alu_result),
|
|
.comparison_result_o(alu_cmp_result),
|
|
.is_equal_result_o (alu_is_equal_result)
|
|
);
|
|
|
|
////////////////
|
|
// Multiplier //
|
|
////////////////
|
|
|
|
if (RV32M == RV32MSlow) begin : gen_multdiv_slow
|
|
cve2_multdiv_slow multdiv_i (
|
|
.clk_i (clk_i),
|
|
.rst_ni (rst_ni),
|
|
.mult_en_i (mult_en_i),
|
|
.div_en_i (div_en_i),
|
|
.mult_sel_i (mult_sel_i),
|
|
.div_sel_i (div_sel_i),
|
|
.operator_i (multdiv_operator_i),
|
|
.signed_mode_i (multdiv_signed_mode_i),
|
|
.op_a_i (multdiv_operand_a_i),
|
|
.op_b_i (multdiv_operand_b_i),
|
|
.alu_adder_ext_i (alu_adder_result_ext),
|
|
.alu_adder_i (alu_adder_result_ex_o),
|
|
.equal_to_zero_i (alu_is_equal_result),
|
|
.valid_o (multdiv_valid),
|
|
.alu_operand_a_o (multdiv_alu_operand_a),
|
|
.alu_operand_b_o (multdiv_alu_operand_b),
|
|
.imd_val_q_i (imd_val_q_i),
|
|
.imd_val_d_o (multdiv_imd_val_d),
|
|
.imd_val_we_o (multdiv_imd_val_we),
|
|
.multdiv_ready_id_i(1'b1),
|
|
.multdiv_result_o (multdiv_result)
|
|
);
|
|
end else if (RV32M == RV32MFast || RV32M == RV32MSingleCycle) begin : gen_multdiv_fast
|
|
cve2_multdiv_fast #(
|
|
.RV32M(RV32M)
|
|
) multdiv_i (
|
|
.clk_i (clk_i),
|
|
.rst_ni (rst_ni),
|
|
.mult_en_i (mult_en_i),
|
|
.div_en_i (div_en_i),
|
|
.mult_sel_i (mult_sel_i),
|
|
.div_sel_i (div_sel_i),
|
|
.operator_i (multdiv_operator_i),
|
|
.signed_mode_i (multdiv_signed_mode_i),
|
|
.op_a_i (multdiv_operand_a_i),
|
|
.op_b_i (multdiv_operand_b_i),
|
|
.alu_operand_a_o (multdiv_alu_operand_a),
|
|
.alu_operand_b_o (multdiv_alu_operand_b),
|
|
.alu_adder_ext_i (alu_adder_result_ext),
|
|
.alu_adder_i (alu_adder_result_ex_o),
|
|
.equal_to_zero_i (alu_is_equal_result),
|
|
.imd_val_q_i (imd_val_q_i),
|
|
.imd_val_d_o (multdiv_imd_val_d),
|
|
.imd_val_we_o (multdiv_imd_val_we),
|
|
.valid_o (multdiv_valid),
|
|
.multdiv_result_o (multdiv_result)
|
|
);
|
|
end
|
|
|
|
// Multiplier/divider may require multiple cycles. The ALU output is valid in the same cycle
|
|
// unless the intermediate result register is being written (which indicates this isn't the
|
|
// final cycle of ALU operation).
|
|
assign ex_valid_o = multdiv_sel ? multdiv_valid : ~(|alu_imd_val_we);
|
|
|
|
endmodule
|