hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv Cov: 75.3%

   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        MultiplierImplementation = "fast"
  14: ) (
  15:     input  logic              clk_i,
  16:     input  logic              rst_ni,
  17: 
  18:     // ALU
  19:     input  ibex_pkg::alu_op_e alu_operator_i,
  20:     input  logic [31:0]       alu_operand_a_i,
  21:     input  logic [31:0]       alu_operand_b_i,
  22: 
  23:     // Multiplier/Divider
  24:     input  ibex_pkg::md_op_e  multdiv_operator_i,
  25:     input  logic              mult_en_i,
  26:     input  logic              div_en_i,
  27:     input  logic  [1:0]       multdiv_signed_mode_i,
  28:     input  logic [31:0]       multdiv_operand_a_i,
  29:     input  logic [31:0]       multdiv_operand_b_i,
  30: 
  31:     // Outputs
  32:     output logic [31:0]       alu_adder_result_ex_o, // to LSU
  33:     output logic [31:0]       regfile_wdata_ex_o,
  34:     output logic [31:0]       jump_target_o,         // to IF
  35:     output logic              branch_decision_o,     // to ID
  36: 
  37:     output logic              ex_valid_o             // EX has valid output
  38: );
  39: 
  40:   import ibex_pkg::*;
  41: 
  42:   logic [31:0] alu_result, multdiv_result;
  43: 
  44:   logic [32:0] multdiv_alu_operand_b, multdiv_alu_operand_a;
  45:   logic [33:0] alu_adder_result_ext;
  46:   logic        alu_cmp_result, alu_is_equal_result;
  47:   logic        multdiv_valid, multdiv_en_sel;
  48:   logic        multdiv_en;
  49: 
  50:   /*
  51:     The multdiv_i output is never selected if RV32M=0
  52:     At synthesis time, all the combinational and sequential logic
  53:     from the multdiv_i module are eliminated
  54:   */
  55:   if (RV32M) begin : gen_multdiv_m
  56:     assign multdiv_en_sel = MultiplierImplementation == "fast" ? div_en_i : mult_en_i | div_en_i;
  57:     assign multdiv_en     = mult_en_i | div_en_i;
  58:   end else begin : gen_multdiv_no_m
  59:     assign multdiv_en_sel = 1'b0;
  60:     assign multdiv_en     = 1'b0;
  61:   end
  62: 
  63:   assign regfile_wdata_ex_o = multdiv_en ? multdiv_result : alu_result;
  64: 
  65:   // branch handling
  66:   assign branch_decision_o  = alu_cmp_result;
  67:   assign jump_target_o      = alu_adder_result_ex_o;
  68: 
  69:   /////////
  70:   // ALU //
  71:   /////////
  72: 
  73:   ibex_alu alu_i (
  74:       .operator_i          ( alu_operator_i            ),
  75:       .operand_a_i         ( alu_operand_a_i           ),
  76:       .operand_b_i         ( alu_operand_b_i           ),
  77:       .multdiv_operand_a_i ( multdiv_alu_operand_a     ),
  78:       .multdiv_operand_b_i ( multdiv_alu_operand_b     ),
  79:       .multdiv_en_i        ( multdiv_en_sel            ),
  80:       .adder_result_o      ( alu_adder_result_ex_o     ),
  81:       .adder_result_ext_o  ( alu_adder_result_ext      ),
  82:       .result_o            ( alu_result                ),
  83:       .comparison_result_o ( alu_cmp_result            ),
  84:       .is_equal_result_o   ( alu_is_equal_result       )
  85:   );
  86: 
  87:   ////////////////
  88:   // Multiplier //
  89:   ////////////////
  90: 
  91:   if (MultiplierImplementation == "slow") begin : gen_multdiv_slow
  92:     ibex_multdiv_slow multdiv_i (
  93:         .clk_i              ( clk_i                 ),
  94:         .rst_ni             ( rst_ni                ),
  95:         .mult_en_i          ( mult_en_i             ),
  96:         .div_en_i           ( div_en_i              ),
  97:         .operator_i         ( multdiv_operator_i    ),
  98:         .signed_mode_i      ( multdiv_signed_mode_i ),
  99:         .op_a_i             ( multdiv_operand_a_i   ),
 100:         .op_b_i             ( multdiv_operand_b_i   ),
 101:         .alu_adder_ext_i    ( alu_adder_result_ext  ),
 102:         .alu_adder_i        ( alu_adder_result_ex_o ),
 103:         .equal_to_zero      ( alu_is_equal_result   ),
 104:         .valid_o            ( multdiv_valid         ),
 105:         .alu_operand_a_o    ( multdiv_alu_operand_a ),
 106:         .alu_operand_b_o    ( multdiv_alu_operand_b ),
 107:         .multdiv_result_o   ( multdiv_result        )
 108:     );
 109:   end else if (MultiplierImplementation == "fast") begin : gen_multdiv_fast
 110:     ibex_multdiv_fast multdiv_i (
 111:         .clk_i              ( clk_i                 ),
 112:         .rst_ni             ( rst_ni                ),
 113:         .mult_en_i          ( mult_en_i             ),
 114:         .div_en_i           ( div_en_i              ),
 115:         .operator_i         ( multdiv_operator_i    ),
 116:         .signed_mode_i      ( multdiv_signed_mode_i ),
 117:         .op_a_i             ( multdiv_operand_a_i   ),
 118:         .op_b_i             ( multdiv_operand_b_i   ),
 119:         .alu_operand_a_o    ( multdiv_alu_operand_a ),
 120:         .alu_operand_b_o    ( multdiv_alu_operand_b ),
 121:         .alu_adder_ext_i    ( alu_adder_result_ext  ),
 122:         .alu_adder_i        ( alu_adder_result_ex_o ),
 123:         .equal_to_zero      ( alu_is_equal_result   ),
 124:         .valid_o            ( multdiv_valid         ),
 125:         .multdiv_result_o   ( multdiv_result        )
 126:     );
 127:   end
 128: 
 129:   // ALU output valid in same cycle, multiplier/divider may require multiple cycles
 130:   assign ex_valid_o = multdiv_en ? multdiv_valid : 1'b1;
 131: 
 132: endmodule
 133: