../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: