../src/lowrisc_ibex_ibex_core_0.1/rtl/ibex_ex_block.sv Cov: 63.9%

   1: // Copyright lowRISC contributors.
   2: // Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
   3: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   4: // SPDX-License-Identifier: Apache-2.0
   5: 
   6: /**
   7:  * Execution stage
   8:  *
   9:  * Execution block: Hosts ALU and MUL/DIV unit
  10:  */
  11: module ibex_ex_block #(
  12:     parameter bit RV32M                    = 1,
  13:     parameter bit RV32B                    = 0,
  14:     parameter bit BranchTargetALU          = 0,
  15:     parameter     MultiplierImplementation = "fast"
  16: ) (
  17:     input  logic                  clk_i,
  18:     input  logic                  rst_ni,
  19: 
  20:     // ALU
  21:     input  ibex_pkg::alu_op_e     alu_operator_i,
  22:     input  logic [31:0]           alu_operand_a_i,
  23:     input  logic [31:0]           alu_operand_b_i,
  24:     input  logic                  alu_instr_first_cycle_i,
  25: 
  26:     // Branch Target ALU
  27:     // All of these signals are unusued when BranchTargetALU == 0
  28:     input  logic [31:0]           bt_a_operand_i,
  29:     input  logic [31:0]           bt_b_operand_i,
  30: 
  31:     // Multiplier/Divider
  32:     input  ibex_pkg::md_op_e      multdiv_operator_i,
  33:     input  logic                  mult_en_i,             // dynamic enable signal, for FSM control
  34:     input  logic                  div_en_i,              // dynamic enable signal, for FSM control
  35:     input  logic                  mult_sel_i,            // static decoder output, for data muxes
  36:     input  logic                  div_sel_i,             // static decoder output, for data muxes
  37:     input  logic  [1:0]           multdiv_signed_mode_i,
  38:     input  logic [31:0]           multdiv_operand_a_i,
  39:     input  logic [31:0]           multdiv_operand_b_i,
  40:     input  logic                  multdiv_ready_id_i,
  41:     input  logic                  data_ind_timing_i,
  42: 
  43:     // intermediate val reg
  44:     output logic                  imd_val_we_o,
  45:     output logic [33:0]           imd_val_d_o,
  46:     input  logic [33:0]           imd_val_q_i,
  47: 
  48:     // Outputs
  49:     output logic [31:0]           alu_adder_result_ex_o, // to LSU
  50:     output logic [31:0]           result_ex_o,
  51:     output logic [31:0]           branch_target_o,       // to IF
  52:     output logic                  branch_decision_o,     // to ID
  53: 
  54:     output logic                  ex_valid_o             // EX has valid output
  55: );
  56: 
  57:   import ibex_pkg::*;
  58: 
  59:   logic [31:0] alu_result, multdiv_result;
  60: 
  61:   logic [32:0] multdiv_alu_operand_b, multdiv_alu_operand_a;
  62:   logic [33:0] alu_adder_result_ext;
  63:   logic        alu_cmp_result, alu_is_equal_result;
  64:   logic        multdiv_valid;
  65:   logic        multdiv_sel;
  66:   logic [31:0] alu_imd_val_d;
  67:   logic        alu_imd_val_we;
  68:   logic [33:0] multdiv_imd_val_d;
  69:   logic        multdiv_imd_val_we;
  70: 
  71:   /*
  72:     The multdiv_i output is never selected if RV32M=0
  73:     At synthesis time, all the combinational and sequential logic
  74:     from the multdiv_i module are eliminated
  75:   */
  76:   if (RV32M) begin : gen_multdiv_m
  77:     assign multdiv_sel = mult_sel_i | div_sel_i;
  78:   end else begin : gen_multdiv_no_m
  79:     assign multdiv_sel = 1'b0;
  80:   end
  81: 
  82:   // Intermediate Value Register Mux
  83:   assign imd_val_d_o  = multdiv_sel ? multdiv_imd_val_d : {2'b0, alu_imd_val_d};
  84:   assign imd_val_we_o = multdiv_sel ? multdiv_imd_val_we : alu_imd_val_we;
  85: 
  86:   assign result_ex_o  = multdiv_sel ? multdiv_result : alu_result;
  87: 
  88:   // branch handling
  89:   assign branch_decision_o  = alu_cmp_result;
  90: 
  91:   if (BranchTargetALU) begin : g_branch_target_alu
  92:     logic [32:0] bt_alu_result;
  93:     logic        unused_bt_carry;
  94: 
  95:     assign bt_alu_result   = bt_a_operand_i + bt_b_operand_i;
  96: 
  97:     assign unused_bt_carry = bt_alu_result[32];
  98:     assign branch_target_o = bt_alu_result[31:0];
  99:   end else begin : g_no_branch_target_alu
 100:     // Unused bt_operand signals cause lint errors, this avoids them
 101:     logic [31:0] unused_bt_a_operand, unused_bt_b_operand;
 102: 
 103:     assign unused_bt_a_operand = bt_a_operand_i;
 104:     assign unused_bt_b_operand = bt_b_operand_i;
 105: 
 106:     assign branch_target_o = alu_adder_result_ex_o;
 107:   end
 108: 
 109:   /////////
 110:   // ALU //
 111:   /////////
 112: 
 113:   ibex_alu #(
 114:     .RV32B(RV32B)
 115:   ) alu_i                  (
 116:       .operator_i          ( alu_operator_i          ),
 117:       .operand_a_i         ( alu_operand_a_i         ),
 118:       .operand_b_i         ( alu_operand_b_i         ),
 119:       .instr_first_cycle_i ( alu_instr_first_cycle_i ),
 120:       .imd_val_q_i         ( imd_val_q_i[31:0]       ),
 121:       .imd_val_we_o        ( alu_imd_val_we          ),
 122:       .imd_val_d_o         ( alu_imd_val_d           ),
 123:       .multdiv_operand_a_i ( multdiv_alu_operand_a   ),
 124:       .multdiv_operand_b_i ( multdiv_alu_operand_b   ),
 125:       .multdiv_sel_i       ( multdiv_sel             ),
 126:       .adder_result_o      ( alu_adder_result_ex_o   ),
 127:       .adder_result_ext_o  ( alu_adder_result_ext    ),
 128:       .result_o            ( alu_result              ),
 129:       .comparison_result_o ( alu_cmp_result          ),
 130:       .is_equal_result_o   ( alu_is_equal_result     )
 131:   );
 132: 
 133:   ////////////////
 134:   // Multiplier //
 135:   ////////////////
 136: 
 137:   if (MultiplierImplementation == "slow") begin : gen_multdiv_slow
 138:     ibex_multdiv_slow multdiv_i (
 139:         .clk_i              ( clk_i                 ),
 140:         .rst_ni             ( rst_ni                ),
 141:         .mult_en_i          ( mult_en_i             ),
 142:         .div_en_i           ( div_en_i              ),
 143:         .mult_sel_i         ( mult_sel_i            ),
 144:         .div_sel_i          ( div_sel_i             ),
 145:         .operator_i         ( multdiv_operator_i    ),
 146:         .signed_mode_i      ( multdiv_signed_mode_i ),
 147:         .op_a_i             ( multdiv_operand_a_i   ),
 148:         .op_b_i             ( multdiv_operand_b_i   ),
 149:         .alu_adder_ext_i    ( alu_adder_result_ext  ),
 150:         .alu_adder_i        ( alu_adder_result_ex_o ),
 151:         .equal_to_zero_i    ( alu_is_equal_result   ),
 152:         .data_ind_timing_i  ( data_ind_timing_i     ),
 153:         .valid_o            ( multdiv_valid         ),
 154:         .alu_operand_a_o    ( multdiv_alu_operand_a ),
 155:         .alu_operand_b_o    ( multdiv_alu_operand_b ),
 156:         .imd_val_q_i        ( imd_val_q_i           ),
 157:         .imd_val_d_o        ( multdiv_imd_val_d     ),
 158:         .imd_val_we_o       ( multdiv_imd_val_we    ),
 159:         .multdiv_ready_id_i ( multdiv_ready_id_i    ),
 160:         .multdiv_result_o   ( multdiv_result        )
 161:     );
 162:   end else if (MultiplierImplementation == "fast") begin : gen_multdiv_fast
 163:     ibex_multdiv_fast #        (
 164:         .SingleCycleMultiply   (0)
 165:     ) multdiv_i                (
 166:         .clk_i                 ( clk_i                 ),
 167:         .rst_ni                ( rst_ni                ),
 168:         .mult_en_i             ( mult_en_i             ),
 169:         .div_en_i              ( div_en_i              ),
 170:         .mult_sel_i            ( mult_sel_i            ),
 171:         .div_sel_i             ( div_sel_i             ),
 172:         .operator_i            ( multdiv_operator_i    ),
 173:         .signed_mode_i         ( multdiv_signed_mode_i ),
 174:         .op_a_i                ( multdiv_operand_a_i   ),
 175:         .op_b_i                ( multdiv_operand_b_i   ),
 176:         .alu_operand_a_o       ( multdiv_alu_operand_a ),
 177:         .alu_operand_b_o       ( multdiv_alu_operand_b ),
 178:         .alu_adder_ext_i       ( alu_adder_result_ext  ),
 179:         .alu_adder_i           ( alu_adder_result_ex_o ),
 180:         .equal_to_zero_i       ( alu_is_equal_result   ),
 181:         .data_ind_timing_i     ( data_ind_timing_i     ),
 182:         .imd_val_q_i           ( imd_val_q_i           ),
 183:         .imd_val_d_o           ( multdiv_imd_val_d     ),
 184:         .imd_val_we_o          ( multdiv_imd_val_we    ),
 185:         .multdiv_ready_id_i    ( multdiv_ready_id_i    ),
 186:         .valid_o               ( multdiv_valid         ),
 187:         .multdiv_result_o      ( multdiv_result        )
 188:     );
 189:   end else if (MultiplierImplementation == "single-cycle") begin: gen_multdiv_single_cycle
 190:     ibex_multdiv_fast #(
 191:         .SingleCycleMultiply(1)
 192:     ) multdiv_i (
 193:         .clk_i                 ( clk_i                 ),
 194:         .rst_ni                ( rst_ni                ),
 195:         .mult_en_i             ( mult_en_i             ),
 196:         .div_en_i              ( div_en_i              ),
 197:         .mult_sel_i            ( mult_sel_i            ),
 198:         .div_sel_i             ( div_sel_i             ),
 199:         .operator_i            ( multdiv_operator_i    ),
 200:         .signed_mode_i         ( multdiv_signed_mode_i ),
 201:         .op_a_i                ( multdiv_operand_a_i   ),
 202:         .op_b_i                ( multdiv_operand_b_i   ),
 203:         .alu_operand_a_o       ( multdiv_alu_operand_a ),
 204:         .alu_operand_b_o       ( multdiv_alu_operand_b ),
 205:         .alu_adder_ext_i       ( alu_adder_result_ext  ),
 206:         .alu_adder_i           ( alu_adder_result_ex_o ),
 207:         .equal_to_zero_i       ( alu_is_equal_result   ),
 208:         .data_ind_timing_i     ( data_ind_timing_i     ),
 209:         .imd_val_q_i           ( imd_val_q_i           ),
 210:         .imd_val_d_o           ( multdiv_imd_val_d     ),
 211:         .imd_val_we_o          ( multdiv_imd_val_we    ),
 212:         .multdiv_ready_id_i    ( multdiv_ready_id_i    ),
 213:         .valid_o               ( multdiv_valid         ),
 214:         .multdiv_result_o      ( multdiv_result        )
 215:     );
 216:   end
 217: 
 218:   // Multiplier/divider may require multiple cycles. The ALU output is valid in the same cycle
 219:   // unless the intermediate result register is being written (which indicates this isn't the
 220:   // final cycle of ALU operation).
 221:   assign ex_valid_o = multdiv_sel ? multdiv_valid : !alu_imd_val_we;
 222: 
 223: endmodule
 224: