| /** |
| * Execution stage |
| * |
| * Execution block: Hosts ALU and MUL/DIV unit |
| */ |
| module brq_exu #( |
| parameter brq_pkg::rv32m_e RV32M = brq_pkg::RV32MFast, |
| parameter brq_pkg::rv32b_e RV32B = brq_pkg::RV32BNone, |
| parameter bit BranchTargetALU = 0 |
| ) ( |
| input logic clk_i, |
| input logic rst_ni, |
| |
| // ALU |
| input brq_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, |
| |
| // Branch Target ALU |
| // All of these signals are unusued when BranchTargetALU == 0 |
| input logic [31:0] bt_a_operand_i, |
| input logic [31:0] bt_b_operand_i, |
| |
| // Multiplier/Divider |
| input brq_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, |
| input logic multdiv_ready_id_i, |
| input logic data_ind_timing_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 brq_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; |
| |
| if (BranchTargetALU) begin : g_branch_target_alu |
| logic [32:0] bt_alu_result; |
| logic unused_bt_carry; |
| |
| assign bt_alu_result = bt_a_operand_i + bt_b_operand_i; |
| |
| assign unused_bt_carry = bt_alu_result[32]; |
| assign branch_target_o = bt_alu_result[31:0]; |
| end else begin : g_no_branch_target_alu |
| // Unused bt_operand signals cause lint errors, this avoids them |
| logic [31:0] unused_bt_a_operand, unused_bt_b_operand; |
| |
| assign unused_bt_a_operand = bt_a_operand_i; |
| assign unused_bt_b_operand = bt_b_operand_i; |
| |
| assign branch_target_o = alu_adder_result_ex_o; |
| end |
| |
| ///////// |
| // ALU // |
| ///////// |
| |
| brq_exu_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 |
| brq_exu_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 ), |
| .data_ind_timing_i ( data_ind_timing_i ), |
| .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 ( multdiv_ready_id_i ), |
| .multdiv_result_o ( multdiv_result ) |
| ); |
| end else if (RV32M == RV32MFast || RV32M == RV32MSingleCycle) begin : gen_multdiv_fast |
| brq_exu_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 ), |
| .data_ind_timing_i ( data_ind_timing_i ), |
| .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 ( multdiv_ready_id_i ), |
| .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 |