hw/vendor/lowrisc_ibex/rtl/ibex_ex_block.sv Cov: 75%
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: