1 |
11 |
dinesha |
/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
|
2 |
|
|
/// @file
|
3 |
|
|
/// @brief Integer Arithmetic Logic Unit (IALU)
|
4 |
|
|
///
|
5 |
|
|
|
6 |
|
|
//-------------------------------------------------------------------------------
|
7 |
|
|
//
|
8 |
|
|
// Functionality:
|
9 |
|
|
// - Performs addition/subtraction and arithmetic and branch comparisons
|
10 |
|
|
// - Performs logical operations (AND(I), OR(I), XOR(I))
|
11 |
|
|
// - Performs address calculation for branch, jump, DMEM load and store and AUIPC
|
12 |
|
|
// instructions
|
13 |
|
|
// - Performs shift operations
|
14 |
|
|
// - Performs MUL/DIV operations
|
15 |
|
|
//
|
16 |
|
|
// Structure:
|
17 |
|
|
// - Main adder
|
18 |
|
|
// - Address adder
|
19 |
|
|
// - Shift logic
|
20 |
|
|
// - MUL/DIV logic
|
21 |
|
|
// - Output result multiplexer
|
22 |
|
|
//
|
23 |
|
|
//-------------------------------------------------------------------------------
|
24 |
|
|
|
25 |
|
|
`include "scr1_arch_description.svh"
|
26 |
|
|
`include "scr1_riscv_isa_decoding.svh"
|
27 |
|
|
`include "scr1_search_ms1.svh"
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
module scr1_pipe_ialu (
|
31 |
|
|
`ifdef SCR1_RVM_EXT
|
32 |
|
|
// Common
|
33 |
|
|
input logic clk, // IALU clock
|
34 |
|
|
input logic rst_n, // IALU reset
|
35 |
|
|
input logic exu2ialu_rvm_cmd_vd_i, // MUL/DIV command valid
|
36 |
|
|
output logic ialu2exu_rvm_res_rdy_o, // MUL/DIV result ready
|
37 |
|
|
`endif // SCR1_RVM_EXT
|
38 |
|
|
|
39 |
|
|
// Main adder
|
40 |
|
|
input logic [`SCR1_XLEN-1:0] exu2ialu_main_op1_i, // main ALU 1st operand
|
41 |
|
|
input logic [`SCR1_XLEN-1:0] exu2ialu_main_op2_i, // main ALU 2nd operand
|
42 |
|
|
input type_scr1_ialu_cmd_sel_e exu2ialu_cmd_i, // IALU command
|
43 |
|
|
output logic [`SCR1_XLEN-1:0] ialu2exu_main_res_o, // main ALU result
|
44 |
|
|
output logic ialu2exu_cmp_res_o, // IALU comparison result
|
45 |
|
|
|
46 |
|
|
// Address adder
|
47 |
|
|
input logic [`SCR1_XLEN-1:0] exu2ialu_addr_op1_i, // Address adder 1st operand
|
48 |
|
|
input logic [`SCR1_XLEN-1:0] exu2ialu_addr_op2_i, // Address adder 2nd operand
|
49 |
|
|
output logic [`SCR1_XLEN-1:0] ialu2exu_addr_res_o // Address adder result
|
50 |
|
|
);
|
51 |
|
|
|
52 |
|
|
//-------------------------------------------------------------------------------
|
53 |
|
|
// Local parameters declaration
|
54 |
|
|
//-------------------------------------------------------------------------------
|
55 |
|
|
|
56 |
|
|
`ifdef SCR1_RVM_EXT
|
57 |
|
|
`ifdef SCR1_FAST_MUL
|
58 |
|
|
localparam SCR1_MUL_WIDTH = `SCR1_XLEN;
|
59 |
|
|
localparam SCR1_MUL_RES_WIDTH = 2 * `SCR1_XLEN;
|
60 |
|
|
localparam SCR1_MDU_SUM_WIDTH = `SCR1_XLEN + 1;
|
61 |
|
|
`else
|
62 |
|
|
localparam SCR1_MUL_STG_NUM = 32;
|
63 |
|
|
localparam SCR1_MUL_WIDTH = 32 / SCR1_MUL_STG_NUM;
|
64 |
|
|
localparam SCR1_MUL_CNT_INIT = 32'b1 << (`SCR1_XLEN/SCR1_MUL_WIDTH - 2);
|
65 |
|
|
localparam SCR1_MDU_SUM_WIDTH = `SCR1_XLEN + SCR1_MUL_WIDTH;
|
66 |
|
|
`endif // ~SCR1_FAST_MUL
|
67 |
|
|
localparam SCR1_DIV_WIDTH = 1;
|
68 |
|
|
localparam SCR1_DIV_CNT_INIT = 32'b1 << (`SCR1_XLEN/SCR1_DIV_WIDTH - 2);
|
69 |
|
|
`endif // SCR1_RVM_EXT
|
70 |
|
|
|
71 |
|
|
//-------------------------------------------------------------------------------
|
72 |
|
|
// Local types declaration
|
73 |
|
|
//-------------------------------------------------------------------------------
|
74 |
|
|
|
75 |
|
|
typedef struct packed {
|
76 |
|
|
logic z; // Zero
|
77 |
|
|
logic s; // Sign
|
78 |
|
|
logic o; // Overflow
|
79 |
|
|
logic c; // Carry
|
80 |
|
|
} type_scr1_ialu_flags_s;
|
81 |
|
|
|
82 |
|
|
`ifdef SCR1_RVM_EXT
|
83 |
|
|
typedef enum logic [1:0] {
|
84 |
|
|
SCR1_IALU_MDU_FSM_IDLE,
|
85 |
|
|
SCR1_IALU_MDU_FSM_ITER,
|
86 |
|
|
SCR1_IALU_MDU_FSM_CORR
|
87 |
|
|
} type_scr1_ialu_fsm_state;
|
88 |
|
|
|
89 |
|
|
typedef enum logic [1:0] {
|
90 |
|
|
SCR1_IALU_MDU_NONE,
|
91 |
|
|
SCR1_IALU_MDU_MUL,
|
92 |
|
|
SCR1_IALU_MDU_DIV
|
93 |
|
|
} type_scr1_ialu_mdu_cmd;
|
94 |
|
|
`endif // SCR1_RVM_EXT
|
95 |
|
|
|
96 |
|
|
//-------------------------------------------------------------------------------
|
97 |
|
|
// Local signals declaration
|
98 |
|
|
//-------------------------------------------------------------------------------
|
99 |
|
|
|
100 |
|
|
// Main adder signals
|
101 |
|
|
logic [`SCR1_XLEN:0] main_sum_res; // Main adder result
|
102 |
|
|
type_scr1_ialu_flags_s main_sum_flags; // Main adder flags
|
103 |
|
|
logic main_sum_pos_ovflw; // Main adder positive overflow
|
104 |
|
|
logic main_sum_neg_ovflw; // Main adder negative overflow
|
105 |
|
|
logic main_ops_diff_sgn; // Main adder operands have different signs
|
106 |
|
|
logic main_ops_non_zero; // Both main adder operands are NOT 0
|
107 |
|
|
|
108 |
|
|
// Shifter signals
|
109 |
|
|
logic ialu_cmd_shft; // IALU command is shift
|
110 |
|
|
logic signed [`SCR1_XLEN-1:0] shft_op1; // SHIFT operand 1
|
111 |
|
|
logic [4:0] shft_op2; // SHIFT operand 2
|
112 |
|
|
logic [1:0] shft_cmd; // SHIFT command: 00 - logical left, 10 - logical right, 11 - arithmetical right
|
113 |
|
|
logic [`SCR1_XLEN-1:0] shft_res; // SHIFT result
|
114 |
|
|
|
115 |
|
|
// MUL/DIV signals
|
116 |
|
|
`ifdef SCR1_RVM_EXT
|
117 |
|
|
// MUL/DIV FSM control signals
|
118 |
|
|
logic mdu_cmd_is_iter; // MDU Command is iterative
|
119 |
|
|
logic mdu_iter_req; // Request iterative stage
|
120 |
|
|
logic mdu_iter_rdy; // Iteration is ready
|
121 |
|
|
logic mdu_corr_req; // DIV/REM(U) correction request
|
122 |
|
|
logic div_corr_req; // Correction request for DIV operation
|
123 |
|
|
logic rem_corr_req; // Correction request for REM(U) operations
|
124 |
|
|
|
125 |
|
|
// MUL/DIV FSM signals
|
126 |
|
|
type_scr1_ialu_fsm_state mdu_fsm_ff; // Current FSM state
|
127 |
|
|
type_scr1_ialu_fsm_state mdu_fsm_next; // Next FSM state
|
128 |
|
|
logic mdu_fsm_idle; // MDU FSM is in IDLE state
|
129 |
|
|
`ifdef SCR1_TRGT_SIMULATION
|
130 |
|
|
logic mdu_fsm_iter; // MDU FSM is in ITER state
|
131 |
|
|
`endif // SCR1_TRGT_SIMULATION
|
132 |
|
|
logic mdu_fsm_corr; // MDU FSM is in CORR state
|
133 |
|
|
|
134 |
|
|
// MDU command signals
|
135 |
|
|
type_scr1_ialu_mdu_cmd mdu_cmd; // MDU command: 00 - NONE, 01 - MUL, 10 - DIV
|
136 |
|
|
logic mdu_cmd_mul; // MDU command is MUL(HSU)
|
137 |
|
|
logic mdu_cmd_div; // MDU command is DIV(U)/REM(U)
|
138 |
|
|
logic [1:0] mul_cmd; // MUL command: 00 - MUL, 01 - MULH, 10 - MULHSU, 11 - MULHU
|
139 |
|
|
logic mul_cmd_hi; // High part of MUL result is requested
|
140 |
|
|
logic [1:0] div_cmd; // DIV command: 00 - DIV, 01 - DIVU, 10 - REM, 11 - REMU
|
141 |
|
|
logic div_cmd_div; // DIV command is DIV
|
142 |
|
|
logic div_cmd_rem; // DIV command is REM(U)
|
143 |
|
|
|
144 |
|
|
// Multiplier signals
|
145 |
|
|
logic mul_op1_is_sgn; // First MUL operand is signed
|
146 |
|
|
logic mul_op2_is_sgn; // Second MUL operand is signed
|
147 |
|
|
logic mul_op1_sgn; // First MUL operand is negative
|
148 |
|
|
logic mul_op2_sgn; // Second MUL operand is negative
|
149 |
|
|
logic signed [`SCR1_XLEN:0] mul_op1; // MUL operand 1
|
150 |
|
|
logic signed [SCR1_MUL_WIDTH:0] mul_op2; // MUL operand 1
|
151 |
|
|
`ifdef SCR1_FAST_MUL
|
152 |
|
|
logic signed [SCR1_MUL_RES_WIDTH-1:0] mul_res; // MUL result
|
153 |
|
|
`else // ~SCR1_FAST_MUL
|
154 |
|
|
logic signed [SCR1_MDU_SUM_WIDTH:0] mul_part_prod;
|
155 |
|
|
logic [`SCR1_XLEN-1:0] mul_res_hi;
|
156 |
|
|
logic [`SCR1_XLEN-1:0] mul_res_lo;
|
157 |
|
|
`endif // ~SCR1_FAST_MUL
|
158 |
|
|
|
159 |
|
|
// Divisor signals
|
160 |
|
|
logic div_ops_are_sgn;
|
161 |
|
|
logic div_op1_is_neg;
|
162 |
|
|
logic div_op2_is_neg;
|
163 |
|
|
logic div_res_rem_c;
|
164 |
|
|
logic [`SCR1_XLEN-1:0] div_res_rem;
|
165 |
|
|
logic [`SCR1_XLEN-1:0] div_res_quo;
|
166 |
|
|
logic div_quo_bit;
|
167 |
|
|
logic div_dvdnd_lo_upd;
|
168 |
|
|
logic [`SCR1_XLEN-1:0] div_dvdnd_lo_ff;
|
169 |
|
|
logic [`SCR1_XLEN-1:0] div_dvdnd_lo_next;
|
170 |
|
|
|
171 |
|
|
// MDU adder signals
|
172 |
|
|
logic mdu_sum_sub; // MDU adder operation: 0 - add, 1 - sub
|
173 |
|
|
logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_op1; // MDU adder operand 1
|
174 |
|
|
logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_op2; // MDU adder operand 2
|
175 |
|
|
logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_res; // MDU adder result
|
176 |
|
|
|
177 |
|
|
// MDU iteration counter signals
|
178 |
|
|
logic mdu_iter_cnt_en;
|
179 |
|
|
logic [`SCR1_XLEN-1:0] mdu_iter_cnt;
|
180 |
|
|
logic [`SCR1_XLEN-1:0] mdu_iter_cnt_next;
|
181 |
|
|
|
182 |
|
|
// Intermediate results registers
|
183 |
|
|
logic mdu_res_upd;
|
184 |
|
|
logic mdu_res_c_ff;
|
185 |
|
|
logic mdu_res_c_next;
|
186 |
|
|
logic [`SCR1_XLEN-1:0] mdu_res_hi_ff;
|
187 |
|
|
logic [`SCR1_XLEN-1:0] mdu_res_hi_next;
|
188 |
|
|
logic [`SCR1_XLEN-1:0] mdu_res_lo_ff;
|
189 |
|
|
logic [`SCR1_XLEN-1:0] mdu_res_lo_next;
|
190 |
|
|
`endif // SCR1_RVM_EXT
|
191 |
|
|
|
192 |
|
|
//-------------------------------------------------------------------------------
|
193 |
|
|
// Main adder
|
194 |
|
|
//-------------------------------------------------------------------------------
|
195 |
|
|
//
|
196 |
|
|
// Main adder is used for the following types of operations:
|
197 |
|
|
// - Addition/subtraction (ADD/ADDI/SUB)
|
198 |
|
|
// - Branch comparisons (BEQ/BNE/BLT(U)/BGE(U))
|
199 |
|
|
// - Arithmetic comparisons (SLT(U)/SLTI(U))
|
200 |
|
|
//
|
201 |
|
|
|
202 |
|
|
// Carry out (MSB of main_sum_res) is evaluated correctly because the result
|
203 |
|
|
// width equals to the maximum width of both the right-hand and left-hand side variables
|
204 |
|
|
always_comb begin
|
205 |
|
|
main_sum_res = (exu2ialu_cmd_i != SCR1_IALU_CMD_ADD)
|
206 |
|
|
? (exu2ialu_main_op1_i - exu2ialu_main_op2_i) // Subtraction and comparison
|
207 |
|
|
: (exu2ialu_main_op1_i + exu2ialu_main_op2_i); // Addition
|
208 |
|
|
|
209 |
|
|
main_sum_pos_ovflw = ~exu2ialu_main_op1_i[`SCR1_XLEN-1]
|
210 |
|
|
& exu2ialu_main_op2_i[`SCR1_XLEN-1]
|
211 |
|
|
& main_sum_res[`SCR1_XLEN-1];
|
212 |
|
|
main_sum_neg_ovflw = exu2ialu_main_op1_i[`SCR1_XLEN-1]
|
213 |
|
|
& ~exu2ialu_main_op2_i[`SCR1_XLEN-1]
|
214 |
|
|
& ~main_sum_res[`SCR1_XLEN-1];
|
215 |
|
|
|
216 |
|
|
// FLAGS1 - flags for comparison (result of subtraction)
|
217 |
|
|
main_sum_flags.c = main_sum_res[`SCR1_XLEN];
|
218 |
|
|
main_sum_flags.z = ~|main_sum_res[`SCR1_XLEN-1:0];
|
219 |
|
|
main_sum_flags.s = main_sum_res[`SCR1_XLEN-1];
|
220 |
|
|
main_sum_flags.o = main_sum_pos_ovflw | main_sum_neg_ovflw;
|
221 |
|
|
end
|
222 |
|
|
|
223 |
|
|
//-------------------------------------------------------------------------------
|
224 |
|
|
// Address adder
|
225 |
|
|
//-------------------------------------------------------------------------------
|
226 |
|
|
//
|
227 |
|
|
// Additional adder is used for the following types of operations:
|
228 |
|
|
// - PC-based address calculation (AUIPC)
|
229 |
|
|
// - IMEM branch address calculation (BEQ/BNE/BLT(U)/BGE(U))
|
230 |
|
|
// - IMEM jump address calculation (JAL/JALR)
|
231 |
|
|
// - DMEM load address calculation (LB(U)/LH(U)/LW)
|
232 |
|
|
// - DMEM store address calculation (SB/SH/SW)
|
233 |
|
|
//
|
234 |
|
|
|
235 |
|
|
assign ialu2exu_addr_res_o = exu2ialu_addr_op1_i + exu2ialu_addr_op2_i;
|
236 |
|
|
|
237 |
|
|
//-------------------------------------------------------------------------------
|
238 |
|
|
// Shift logic
|
239 |
|
|
//-------------------------------------------------------------------------------
|
240 |
|
|
//
|
241 |
|
|
// Shift logic supports the following types of shift operations:
|
242 |
|
|
// - Logical left shift (SLLI/SLL)
|
243 |
|
|
// - Logical right shift (SRLI/SRL)
|
244 |
|
|
// - Arithmetic right shift (SRAI/SRA)
|
245 |
|
|
//
|
246 |
|
|
|
247 |
|
|
assign ialu_cmd_shft = (exu2ialu_cmd_i == SCR1_IALU_CMD_SLL)
|
248 |
|
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_SRL)
|
249 |
|
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_SRA);
|
250 |
|
|
assign shft_cmd = ialu_cmd_shft
|
251 |
|
|
? {(exu2ialu_cmd_i != SCR1_IALU_CMD_SLL),
|
252 |
|
|
(exu2ialu_cmd_i == SCR1_IALU_CMD_SRA)}
|
253 |
|
|
: 2'b00;
|
254 |
|
|
|
255 |
|
|
always_comb begin
|
256 |
|
|
shft_op1 = exu2ialu_main_op1_i;
|
257 |
|
|
shft_op2 = exu2ialu_main_op2_i[4:0];
|
258 |
|
|
case (shft_cmd)
|
259 |
|
|
2'b10 : shft_res = shft_op1 >> shft_op2;
|
260 |
|
|
2'b11 : shft_res = shft_op1 >>> shft_op2;
|
261 |
|
|
default : shft_res = shft_op1 << shft_op2;
|
262 |
|
|
endcase
|
263 |
|
|
end
|
264 |
|
|
|
265 |
|
|
`ifdef SCR1_RVM_EXT
|
266 |
|
|
//-------------------------------------------------------------------------------
|
267 |
|
|
// MUL/DIV logic
|
268 |
|
|
//-------------------------------------------------------------------------------
|
269 |
|
|
//
|
270 |
|
|
// MUL/DIV instructions use the following functional units:
|
271 |
|
|
// - MUL/DIV FSM control logic, including iteration number counter
|
272 |
|
|
// - MUL/DIV FSM
|
273 |
|
|
// - MUL logic
|
274 |
|
|
// - DIV logic
|
275 |
|
|
// - MDU adder to produce an intermediate result
|
276 |
|
|
// - 2 registers to save the intermediate result (shared between MUL and DIV
|
277 |
|
|
// operations)
|
278 |
|
|
//
|
279 |
|
|
|
280 |
|
|
//-------------------------------------------------------------------------------
|
281 |
|
|
// MUL/DIV FSM Control logic
|
282 |
|
|
//-------------------------------------------------------------------------------
|
283 |
|
|
|
284 |
|
|
assign mdu_cmd_div = (exu2ialu_cmd_i == SCR1_IALU_CMD_DIV)
|
285 |
|
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_DIVU)
|
286 |
|
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_REM)
|
287 |
|
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_REMU);
|
288 |
|
|
assign mdu_cmd_mul = (exu2ialu_cmd_i == SCR1_IALU_CMD_MUL)
|
289 |
|
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_MULH)
|
290 |
|
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU)
|
291 |
|
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHSU);
|
292 |
|
|
|
293 |
|
|
assign mdu_cmd = mdu_cmd_div ? SCR1_IALU_MDU_DIV
|
294 |
|
|
: mdu_cmd_mul ? SCR1_IALU_MDU_MUL
|
295 |
|
|
: SCR1_IALU_MDU_NONE;
|
296 |
|
|
|
297 |
|
|
assign main_ops_non_zero = |exu2ialu_main_op1_i & |exu2ialu_main_op2_i;
|
298 |
|
|
assign main_ops_diff_sgn = exu2ialu_main_op1_i[`SCR1_XLEN-1]
|
299 |
|
|
^ exu2ialu_main_op2_i[`SCR1_XLEN-1];
|
300 |
|
|
|
301 |
|
|
`ifdef SCR1_FAST_MUL
|
302 |
|
|
assign mdu_cmd_is_iter = mdu_cmd_div;
|
303 |
|
|
`else // ~SCR1_FAST_MUL
|
304 |
|
|
assign mdu_cmd_is_iter = mdu_cmd_mul | mdu_cmd_div;
|
305 |
|
|
`endif // ~SCR1_FAST_MUL
|
306 |
|
|
|
307 |
|
|
assign mdu_iter_req = mdu_cmd_is_iter ? (main_ops_non_zero & mdu_fsm_idle) : 1'b0;
|
308 |
|
|
assign mdu_iter_rdy = mdu_iter_cnt[0];
|
309 |
|
|
|
310 |
|
|
assign div_cmd_div = (div_cmd == 2'b00);
|
311 |
|
|
assign div_cmd_rem = div_cmd[1];
|
312 |
|
|
|
313 |
|
|
// Correction request signals
|
314 |
|
|
assign div_corr_req = div_cmd_div & main_ops_diff_sgn;
|
315 |
|
|
assign rem_corr_req = div_cmd_rem & |div_res_rem & (div_op1_is_neg ^ div_res_rem_c);
|
316 |
|
|
assign mdu_corr_req = mdu_cmd_div & (div_corr_req | rem_corr_req);
|
317 |
|
|
|
318 |
|
|
// MDU iteration counter
|
319 |
|
|
//------------------------------------------------------------------------------
|
320 |
|
|
|
321 |
|
|
assign mdu_iter_cnt_en = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
|
322 |
|
|
|
323 |
|
|
always_ff @(posedge clk) begin
|
324 |
|
|
if (mdu_iter_cnt_en) begin
|
325 |
|
|
mdu_iter_cnt <= mdu_iter_cnt_next;
|
326 |
|
|
end
|
327 |
|
|
end
|
328 |
|
|
|
329 |
|
|
assign mdu_iter_cnt_next = ~mdu_fsm_idle ? mdu_iter_cnt >> 1
|
330 |
|
|
: mdu_cmd_div ? SCR1_DIV_CNT_INIT
|
331 |
|
|
`ifndef SCR1_FAST_MUL
|
332 |
|
|
: mdu_cmd_mul ? SCR1_MUL_CNT_INIT
|
333 |
|
|
`endif // ~SCR1_FAST_MUL
|
334 |
|
|
: mdu_iter_cnt;
|
335 |
|
|
|
336 |
|
|
//-------------------------------------------------------------------------------
|
337 |
|
|
// MUL/DIV FSM
|
338 |
|
|
//-------------------------------------------------------------------------------
|
339 |
|
|
|
340 |
|
|
always_ff @(posedge clk, negedge rst_n) begin
|
341 |
|
|
if (~rst_n) begin
|
342 |
|
|
mdu_fsm_ff <= SCR1_IALU_MDU_FSM_IDLE;
|
343 |
|
|
end else begin
|
344 |
|
|
mdu_fsm_ff <= mdu_fsm_next;
|
345 |
|
|
end
|
346 |
|
|
end
|
347 |
|
|
|
348 |
|
|
always_comb begin
|
349 |
|
|
mdu_fsm_next = SCR1_IALU_MDU_FSM_IDLE;
|
350 |
|
|
|
351 |
|
|
if (exu2ialu_rvm_cmd_vd_i) begin
|
352 |
|
|
case (mdu_fsm_ff)
|
353 |
|
|
SCR1_IALU_MDU_FSM_IDLE : begin
|
354 |
|
|
mdu_fsm_next = mdu_iter_req ? SCR1_IALU_MDU_FSM_ITER
|
355 |
|
|
: SCR1_IALU_MDU_FSM_IDLE;
|
356 |
|
|
end
|
357 |
|
|
SCR1_IALU_MDU_FSM_ITER : begin
|
358 |
|
|
mdu_fsm_next = ~mdu_iter_rdy ? SCR1_IALU_MDU_FSM_ITER
|
359 |
|
|
: mdu_corr_req ? SCR1_IALU_MDU_FSM_CORR
|
360 |
|
|
: SCR1_IALU_MDU_FSM_IDLE;
|
361 |
|
|
end
|
362 |
|
|
SCR1_IALU_MDU_FSM_CORR : begin
|
363 |
|
|
mdu_fsm_next = SCR1_IALU_MDU_FSM_IDLE;
|
364 |
|
|
end
|
365 |
|
|
endcase
|
366 |
|
|
end
|
367 |
|
|
end
|
368 |
|
|
|
369 |
|
|
assign mdu_fsm_idle = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_IDLE);
|
370 |
|
|
`ifdef SCR1_TRGT_SIMULATION
|
371 |
|
|
assign mdu_fsm_iter = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_ITER);
|
372 |
|
|
`endif // SCR1_TRGT_SIMULATION
|
373 |
|
|
assign mdu_fsm_corr = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_CORR);
|
374 |
|
|
|
375 |
|
|
//-------------------------------------------------------------------------------
|
376 |
|
|
// Multiplier logic
|
377 |
|
|
//-------------------------------------------------------------------------------
|
378 |
|
|
//
|
379 |
|
|
// Multiplication has 2 options: fast (1 cycle) and Radix-2 (32 cycles) multiplication.
|
380 |
|
|
//
|
381 |
|
|
// 1. Fast multiplication uses the straightforward approach when 2 operands are
|
382 |
|
|
// multiplied in one cycle
|
383 |
|
|
//
|
384 |
|
|
// 2. Radix-2 multiplication uses 2 registers (high and low part of multiplication)
|
385 |
|
|
//
|
386 |
|
|
// Radix-2 algorithm:
|
387 |
|
|
// 1. Initialize registers
|
388 |
|
|
// 2. Create a partial product by multiplying multiplicand by the LSB of multiplier
|
389 |
|
|
// 3. Add the partial product to the previous (intermediate) value of multiplication
|
390 |
|
|
// result (stored into high and low parts of multiplication result register)
|
391 |
|
|
// 4. Shift the low part of multiplication result register right
|
392 |
|
|
// 4. Store the addition result into the high part of multiplication result register
|
393 |
|
|
// 6. If iteration is not ready, go to step 2. Otherwise multiplication is done
|
394 |
|
|
//
|
395 |
|
|
//
|
396 |
|
|
|
397 |
|
|
assign mul_cmd = {((exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHSU)),
|
398 |
|
|
((exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULH))};
|
399 |
|
|
|
400 |
|
|
assign mul_cmd_hi = |mul_cmd;
|
401 |
|
|
assign mul_op1_is_sgn = ~&mul_cmd;
|
402 |
|
|
assign mul_op2_is_sgn = ~mul_cmd[1];
|
403 |
|
|
assign mul_op1_sgn = mul_op1_is_sgn & exu2ialu_main_op1_i[`SCR1_XLEN-1];
|
404 |
|
|
assign mul_op2_sgn = mul_op2_is_sgn & exu2ialu_main_op2_i[`SCR1_XLEN-1];
|
405 |
|
|
|
406 |
|
|
`ifdef SCR1_FAST_MUL
|
407 |
|
|
assign mul_op1 = mdu_cmd_mul ? $signed({mul_op1_sgn, exu2ialu_main_op1_i}) : '0;
|
408 |
|
|
assign mul_op2 = mdu_cmd_mul ? $signed({mul_op2_sgn, exu2ialu_main_op2_i}) : '0;
|
409 |
|
|
assign mul_res = mdu_cmd_mul ? mul_op1 * mul_op2 : 'sb0;
|
410 |
|
|
`else // ~SCR1_FAST_MUL
|
411 |
|
|
assign mul_op1 = mdu_cmd_mul ? $signed({mul_op1_sgn, exu2ialu_main_op1_i}) : '0;
|
412 |
|
|
assign mul_op2 = ~mdu_cmd_mul ? '0
|
413 |
|
|
: mdu_fsm_idle ? $signed({1'b0, exu2ialu_main_op2_i[SCR1_MUL_WIDTH-1:0]})
|
414 |
|
|
: $signed({(mdu_iter_cnt[0] & mul_op2_is_sgn & mdu_res_lo_ff[SCR1_MUL_WIDTH-1]),
|
415 |
|
|
mdu_res_lo_ff[SCR1_MUL_WIDTH-1:0]});
|
416 |
|
|
|
417 |
|
|
assign mul_part_prod = mdu_cmd_mul ? mul_op1 * mul_op2 : 'sb0;
|
418 |
|
|
assign {mul_res_hi, mul_res_lo} = ~mdu_cmd_mul ? '0
|
419 |
|
|
: mdu_fsm_idle ? ({mdu_sum_res, exu2ialu_main_op2_i[`SCR1_XLEN-1:SCR1_MUL_WIDTH]})
|
420 |
|
|
: ({mdu_sum_res, mdu_res_lo_ff[`SCR1_XLEN-1:SCR1_MUL_WIDTH]});
|
421 |
|
|
`endif // ~SCR1_FAST_MUL
|
422 |
|
|
|
423 |
|
|
//-------------------------------------------------------------------------------
|
424 |
|
|
// Divider logic
|
425 |
|
|
//-------------------------------------------------------------------------------
|
426 |
|
|
//
|
427 |
|
|
// Division uses a non-restoring algorithm. 3 registers are used:
|
428 |
|
|
// - Remainder register
|
429 |
|
|
// - Quotient register
|
430 |
|
|
// - Dividend low part register (for corner case quotient bit calculation)
|
431 |
|
|
//
|
432 |
|
|
// Algorithm:
|
433 |
|
|
// 1. Initialize registers
|
434 |
|
|
// 2. Shift remainder and dividend low part registers left
|
435 |
|
|
// 3. Compare remainder register with the divisor (taking previous quotient bit
|
436 |
|
|
// and operands signs into account) and calculate quotient bit based on the
|
437 |
|
|
// comparison results
|
438 |
|
|
// 4. Shift quotient register left, append quotient bit to the quotient register
|
439 |
|
|
// 5. If iteration is not ready, go to step 2. Otherwise go to step 6
|
440 |
|
|
// 6. Do correction if necessary, otherwise division is done
|
441 |
|
|
//
|
442 |
|
|
// Quotient bit calculation has a corner case:
|
443 |
|
|
// When dividend is negative result carry bit check takes into account only
|
444 |
|
|
// the case of remainder register been greater than divisor. To handle
|
445 |
|
|
// equality case we should check if both the comparison result and the
|
446 |
|
|
// lower part of dividend are zero
|
447 |
|
|
//
|
448 |
|
|
|
449 |
|
|
assign div_cmd = {((exu2ialu_cmd_i == SCR1_IALU_CMD_REM) | (exu2ialu_cmd_i == SCR1_IALU_CMD_REMU)),
|
450 |
|
|
((exu2ialu_cmd_i == SCR1_IALU_CMD_REMU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_DIVU))};
|
451 |
|
|
|
452 |
|
|
assign div_ops_are_sgn = ~div_cmd[0];
|
453 |
|
|
assign div_op1_is_neg = div_ops_are_sgn & exu2ialu_main_op1_i[`SCR1_XLEN-1];
|
454 |
|
|
assign div_op2_is_neg = div_ops_are_sgn & exu2ialu_main_op2_i[`SCR1_XLEN-1];
|
455 |
|
|
|
456 |
|
|
always_comb begin
|
457 |
|
|
div_res_rem_c = '0;
|
458 |
|
|
div_res_rem = '0;
|
459 |
|
|
div_res_quo = '0;
|
460 |
|
|
div_quo_bit = 1'b0;
|
461 |
|
|
if (mdu_cmd_div & ~mdu_fsm_corr) begin
|
462 |
|
|
div_res_rem_c = mdu_sum_res[SCR1_MDU_SUM_WIDTH-1];
|
463 |
|
|
div_res_rem = mdu_sum_res[SCR1_MDU_SUM_WIDTH-2:0];
|
464 |
|
|
div_quo_bit = ~(div_op1_is_neg ^ div_res_rem_c)
|
465 |
|
|
| (div_op1_is_neg & ({mdu_sum_res, div_dvdnd_lo_next} == '0));
|
466 |
|
|
div_res_quo = mdu_fsm_idle
|
467 |
|
|
? {'0, div_quo_bit}
|
468 |
|
|
: {mdu_res_lo_ff[`SCR1_XLEN-2:0], div_quo_bit};
|
469 |
|
|
end
|
470 |
|
|
end
|
471 |
|
|
|
472 |
|
|
// Dividend low part register
|
473 |
|
|
//------------------------------------------------------------------------------
|
474 |
|
|
|
475 |
|
|
assign div_dvdnd_lo_upd = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
|
476 |
|
|
|
477 |
|
|
always_ff @(posedge clk) begin
|
478 |
|
|
if (div_dvdnd_lo_upd) begin
|
479 |
|
|
div_dvdnd_lo_ff <= div_dvdnd_lo_next;
|
480 |
|
|
end
|
481 |
|
|
end
|
482 |
|
|
|
483 |
|
|
assign div_dvdnd_lo_next = (~mdu_cmd_div | mdu_fsm_corr) ? '0
|
484 |
|
|
: mdu_fsm_idle ? exu2ialu_main_op1_i << 1
|
485 |
|
|
: div_dvdnd_lo_ff << 1;
|
486 |
|
|
|
487 |
|
|
//-------------------------------------------------------------------------------
|
488 |
|
|
// MDU adder
|
489 |
|
|
//-------------------------------------------------------------------------------
|
490 |
|
|
logic sgn;
|
491 |
|
|
logic inv;
|
492 |
|
|
|
493 |
|
|
always_comb begin
|
494 |
|
|
mdu_sum_sub = 1'b0;
|
495 |
|
|
mdu_sum_op1 = '0;
|
496 |
|
|
mdu_sum_op2 = '0;
|
497 |
|
|
sgn = '0; // yosys - latch fix
|
498 |
|
|
inv = '0; // yosys - latch fix
|
499 |
|
|
case (mdu_cmd)
|
500 |
|
|
SCR1_IALU_MDU_DIV : begin
|
501 |
|
|
sgn = mdu_fsm_corr ? div_op1_is_neg ^ mdu_res_c_ff
|
502 |
|
|
: mdu_fsm_idle ? 1'b0
|
503 |
|
|
: ~mdu_res_lo_ff[0];
|
504 |
|
|
inv = div_ops_are_sgn & main_ops_diff_sgn;
|
505 |
|
|
mdu_sum_sub = ~inv ^ sgn;
|
506 |
|
|
mdu_sum_op1 = mdu_fsm_corr ? $signed({1'b0, mdu_res_hi_ff})
|
507 |
|
|
: mdu_fsm_idle ? $signed({div_op1_is_neg, exu2ialu_main_op1_i[`SCR1_XLEN-1]})
|
508 |
|
|
: $signed({mdu_res_hi_ff, div_dvdnd_lo_ff[`SCR1_XLEN-1]});
|
509 |
|
|
mdu_sum_op2 = $signed({div_op2_is_neg, exu2ialu_main_op2_i});
|
510 |
|
|
end
|
511 |
|
|
`ifndef SCR1_FAST_MUL
|
512 |
|
|
SCR1_IALU_MDU_MUL : begin
|
513 |
|
|
mdu_sum_op1 = mdu_fsm_idle
|
514 |
|
|
? '0
|
515 |
|
|
: $signed({(mul_op1_is_sgn & mdu_res_hi_ff[`SCR1_XLEN-1]), mdu_res_hi_ff});
|
516 |
|
|
mdu_sum_op2 = mul_part_prod;
|
517 |
|
|
end
|
518 |
|
|
`endif // SCR1_FAST_MUL
|
519 |
|
|
default : begin end
|
520 |
|
|
endcase
|
521 |
|
|
mdu_sum_res = mdu_sum_sub
|
522 |
|
|
? (mdu_sum_op1 - mdu_sum_op2)
|
523 |
|
|
: (mdu_sum_op1 + mdu_sum_op2);
|
524 |
|
|
end
|
525 |
|
|
|
526 |
|
|
//-------------------------------------------------------------------------------
|
527 |
|
|
// MUL/DIV intermediate results registers
|
528 |
|
|
//-------------------------------------------------------------------------------
|
529 |
|
|
|
530 |
|
|
assign mdu_res_upd = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
|
531 |
|
|
|
532 |
|
|
always_ff @(posedge clk) begin
|
533 |
|
|
if (mdu_res_upd) begin
|
534 |
|
|
mdu_res_c_ff <= mdu_res_c_next;
|
535 |
|
|
mdu_res_hi_ff <= mdu_res_hi_next;
|
536 |
|
|
mdu_res_lo_ff <= mdu_res_lo_next;
|
537 |
|
|
end
|
538 |
|
|
end
|
539 |
|
|
|
540 |
|
|
assign mdu_res_c_next = mdu_cmd_div ? div_res_rem_c : mdu_res_c_ff;
|
541 |
|
|
assign mdu_res_hi_next = mdu_cmd_div ? div_res_rem
|
542 |
|
|
`ifndef SCR1_FAST_MUL
|
543 |
|
|
: mdu_cmd_mul ? mul_res_hi
|
544 |
|
|
`endif // SCR1_FAST_MUL
|
545 |
|
|
: mdu_res_hi_ff;
|
546 |
|
|
assign mdu_res_lo_next = mdu_cmd_div ? div_res_quo
|
547 |
|
|
`ifndef SCR1_FAST_MUL
|
548 |
|
|
: mdu_cmd_mul ? mul_res_lo
|
549 |
|
|
`endif // SCR1_FAST_MUL
|
550 |
|
|
: mdu_res_lo_ff;
|
551 |
|
|
`endif // SCR1_RVM_EXT
|
552 |
|
|
|
553 |
|
|
//-------------------------------------------------------------------------------
|
554 |
|
|
// Operation result forming
|
555 |
|
|
//-------------------------------------------------------------------------------
|
556 |
|
|
|
557 |
|
|
always_comb begin
|
558 |
|
|
ialu2exu_main_res_o = '0;
|
559 |
|
|
ialu2exu_cmp_res_o = 1'b0;
|
560 |
|
|
`ifdef SCR1_RVM_EXT
|
561 |
|
|
ialu2exu_rvm_res_rdy_o = 1'b1;
|
562 |
|
|
`endif // SCR1_RVM_EXT
|
563 |
|
|
|
564 |
|
|
case (exu2ialu_cmd_i)
|
565 |
|
|
SCR1_IALU_CMD_AND : begin
|
566 |
|
|
ialu2exu_main_res_o = exu2ialu_main_op1_i & exu2ialu_main_op2_i;
|
567 |
|
|
end
|
568 |
|
|
SCR1_IALU_CMD_OR : begin
|
569 |
|
|
ialu2exu_main_res_o = exu2ialu_main_op1_i | exu2ialu_main_op2_i;
|
570 |
|
|
end
|
571 |
|
|
SCR1_IALU_CMD_XOR : begin
|
572 |
|
|
ialu2exu_main_res_o = exu2ialu_main_op1_i ^ exu2ialu_main_op2_i;
|
573 |
|
|
end
|
574 |
|
|
SCR1_IALU_CMD_ADD : begin
|
575 |
|
|
ialu2exu_main_res_o = main_sum_res[`SCR1_XLEN-1:0];
|
576 |
|
|
end
|
577 |
|
|
SCR1_IALU_CMD_SUB : begin
|
578 |
|
|
ialu2exu_main_res_o = main_sum_res[`SCR1_XLEN-1:0];
|
579 |
|
|
end
|
580 |
|
|
SCR1_IALU_CMD_SUB_LT : begin
|
581 |
|
|
ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.s ^ main_sum_flags.o);
|
582 |
|
|
ialu2exu_cmp_res_o = main_sum_flags.s ^ main_sum_flags.o;
|
583 |
|
|
end
|
584 |
|
|
SCR1_IALU_CMD_SUB_LTU : begin
|
585 |
|
|
ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.c);
|
586 |
|
|
ialu2exu_cmp_res_o = main_sum_flags.c;
|
587 |
|
|
end
|
588 |
|
|
SCR1_IALU_CMD_SUB_EQ : begin
|
589 |
|
|
ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.z);
|
590 |
|
|
ialu2exu_cmp_res_o = main_sum_flags.z;
|
591 |
|
|
end
|
592 |
|
|
SCR1_IALU_CMD_SUB_NE : begin
|
593 |
|
|
ialu2exu_main_res_o = `SCR1_XLEN'(~main_sum_flags.z);
|
594 |
|
|
ialu2exu_cmp_res_o = ~main_sum_flags.z;
|
595 |
|
|
end
|
596 |
|
|
SCR1_IALU_CMD_SUB_GE : begin
|
597 |
|
|
ialu2exu_main_res_o = `SCR1_XLEN'(~(main_sum_flags.s ^ main_sum_flags.o));
|
598 |
|
|
ialu2exu_cmp_res_o = ~(main_sum_flags.s ^ main_sum_flags.o);
|
599 |
|
|
end
|
600 |
|
|
SCR1_IALU_CMD_SUB_GEU : begin
|
601 |
|
|
ialu2exu_main_res_o = `SCR1_XLEN'(~main_sum_flags.c);
|
602 |
|
|
ialu2exu_cmp_res_o = ~main_sum_flags.c;
|
603 |
|
|
end
|
604 |
|
|
SCR1_IALU_CMD_SLL,
|
605 |
|
|
SCR1_IALU_CMD_SRL,
|
606 |
|
|
SCR1_IALU_CMD_SRA: begin
|
607 |
|
|
ialu2exu_main_res_o = shft_res;
|
608 |
|
|
end
|
609 |
|
|
`ifdef SCR1_RVM_EXT
|
610 |
|
|
SCR1_IALU_CMD_MUL,
|
611 |
|
|
SCR1_IALU_CMD_MULHU,
|
612 |
|
|
SCR1_IALU_CMD_MULHSU,
|
613 |
|
|
SCR1_IALU_CMD_MULH : begin
|
614 |
|
|
`ifdef SCR1_FAST_MUL
|
615 |
|
|
ialu2exu_main_res_o = mul_cmd_hi
|
616 |
|
|
? mul_res[SCR1_MUL_RES_WIDTH-1:`SCR1_XLEN]
|
617 |
|
|
: mul_res[`SCR1_XLEN-1:0];
|
618 |
|
|
`else // ~SCR1_FAST_MUL
|
619 |
|
|
case (mdu_fsm_ff)
|
620 |
|
|
SCR1_IALU_MDU_FSM_IDLE : begin
|
621 |
|
|
ialu2exu_main_res_o = '0;
|
622 |
|
|
ialu2exu_rvm_res_rdy_o = ~mdu_iter_req;
|
623 |
|
|
end
|
624 |
|
|
SCR1_IALU_MDU_FSM_ITER : begin
|
625 |
|
|
ialu2exu_main_res_o = mul_cmd_hi ? mul_res_hi : mul_res_lo;
|
626 |
|
|
ialu2exu_rvm_res_rdy_o = mdu_iter_rdy;
|
627 |
|
|
end
|
628 |
|
|
endcase
|
629 |
|
|
`endif // ~SCR1_FAST_MUL
|
630 |
|
|
end
|
631 |
|
|
SCR1_IALU_CMD_DIV,
|
632 |
|
|
SCR1_IALU_CMD_DIVU,
|
633 |
|
|
SCR1_IALU_CMD_REM,
|
634 |
|
|
SCR1_IALU_CMD_REMU : begin
|
635 |
|
|
case (mdu_fsm_ff)
|
636 |
|
|
SCR1_IALU_MDU_FSM_IDLE : begin
|
637 |
|
|
ialu2exu_main_res_o = (|exu2ialu_main_op2_i | div_cmd_rem)
|
638 |
|
|
? exu2ialu_main_op1_i
|
639 |
|
|
: '1;
|
640 |
|
|
ialu2exu_rvm_res_rdy_o = ~mdu_iter_req;
|
641 |
|
|
end
|
642 |
|
|
SCR1_IALU_MDU_FSM_ITER : begin
|
643 |
|
|
ialu2exu_main_res_o = div_cmd_rem ? div_res_rem : div_res_quo;
|
644 |
|
|
ialu2exu_rvm_res_rdy_o = mdu_iter_rdy & ~mdu_corr_req;
|
645 |
|
|
end
|
646 |
|
|
SCR1_IALU_MDU_FSM_CORR : begin
|
647 |
|
|
ialu2exu_main_res_o = div_cmd_rem
|
648 |
|
|
? mdu_sum_res[`SCR1_XLEN-1:0]
|
649 |
|
|
: -mdu_res_lo_ff[`SCR1_XLEN-1:0];
|
650 |
|
|
ialu2exu_rvm_res_rdy_o = 1'b1;
|
651 |
|
|
end
|
652 |
|
|
endcase
|
653 |
|
|
end
|
654 |
|
|
`endif // SCR1_RVM_EXT
|
655 |
|
|
default : begin end
|
656 |
|
|
endcase
|
657 |
|
|
end
|
658 |
|
|
|
659 |
|
|
|
660 |
|
|
`ifdef SCR1_TRGT_SIMULATION
|
661 |
|
|
//-------------------------------------------------------------------------------
|
662 |
|
|
// Assertion
|
663 |
|
|
//-------------------------------------------------------------------------------
|
664 |
|
|
|
665 |
|
|
`ifdef SCR1_RVM_EXT
|
666 |
|
|
|
667 |
|
|
// X checks
|
668 |
|
|
|
669 |
|
|
SCR1_SVA_IALU_XCHECK : assert property (
|
670 |
|
|
@(negedge clk) disable iff (~rst_n)
|
671 |
|
|
!$isunknown({exu2ialu_rvm_cmd_vd_i, mdu_fsm_ff})
|
672 |
|
|
) else $error("IALU Error: unknown values");
|
673 |
|
|
|
674 |
|
|
SCR1_SVA_IALU_XCHECK_QUEUE : assert property (
|
675 |
|
|
@(negedge clk) disable iff (~rst_n)
|
676 |
|
|
exu2ialu_rvm_cmd_vd_i |->
|
677 |
|
|
!$isunknown({exu2ialu_main_op1_i, exu2ialu_main_op2_i, exu2ialu_cmd_i})
|
678 |
|
|
) else $error("IALU Error: unknown values in queue");
|
679 |
|
|
|
680 |
|
|
// Behavior checks
|
681 |
|
|
|
682 |
|
|
SCR1_SVA_IALU_ILL_STATE : assert property (
|
683 |
|
|
@(negedge clk) disable iff (~rst_n)
|
684 |
|
|
$onehot0({~exu2ialu_rvm_cmd_vd_i, mdu_fsm_iter, mdu_fsm_corr})
|
685 |
|
|
) else $error("IALU Error: illegal state");
|
686 |
|
|
|
687 |
|
|
`ifndef VERILATOR
|
688 |
|
|
SCR1_SVA_IALU_JUMP_FROM_IDLE : assert property (
|
689 |
|
|
@(negedge clk) disable iff (~rst_n)
|
690 |
|
|
(mdu_fsm_idle & (~exu2ialu_rvm_cmd_vd_i | ~mdu_iter_req)) |=> mdu_fsm_idle
|
691 |
|
|
) else $error("EXU Error: illegal jump from IDLE state");
|
692 |
|
|
|
693 |
|
|
SCR1_SVA_IALU_IDLE_TO_ITER : assert property (
|
694 |
|
|
@(negedge clk) disable iff (~rst_n)
|
695 |
|
|
(mdu_fsm_idle & exu2ialu_rvm_cmd_vd_i & mdu_iter_req) |=> mdu_fsm_iter
|
696 |
|
|
) else $error("EXU Error: illegal change state form IDLE to ITER");
|
697 |
|
|
|
698 |
|
|
SCR1_SVA_IALU_JUMP_FROM_ITER : assert property (
|
699 |
|
|
@(negedge clk) disable iff (~rst_n)
|
700 |
|
|
(mdu_fsm_iter & ~mdu_iter_rdy) |=> mdu_fsm_iter
|
701 |
|
|
) else $error("EXU Error: illegal jump from ITER state");
|
702 |
|
|
|
703 |
|
|
SCR1_SVA_IALU_ITER_TO_IDLE : assert property (
|
704 |
|
|
@(negedge clk) disable iff (~rst_n)
|
705 |
|
|
(mdu_fsm_iter & mdu_iter_rdy & ~mdu_corr_req) |=> mdu_fsm_idle
|
706 |
|
|
) else $error("EXU Error: illegal state change ITER to IDLE");
|
707 |
|
|
|
708 |
|
|
SCR1_SVA_IALU_ITER_TO_CORR : assert property (
|
709 |
|
|
@(negedge clk) disable iff (~rst_n)
|
710 |
|
|
(mdu_fsm_iter & mdu_iter_rdy & mdu_corr_req) |=> mdu_fsm_corr
|
711 |
|
|
) else $error("EXU Error: illegal state change ITER to CORR");
|
712 |
|
|
|
713 |
|
|
SCR1_SVA_IALU_CORR_TO_IDLE : assert property (
|
714 |
|
|
@(negedge clk) disable iff (~rst_n)
|
715 |
|
|
mdu_fsm_corr |=> mdu_fsm_idle
|
716 |
|
|
) else $error("EXU Error: illegal state stay in CORR");
|
717 |
|
|
`endif // VERILATOR
|
718 |
|
|
|
719 |
|
|
`endif // SCR1_RVM_EXT
|
720 |
|
|
|
721 |
|
|
`endif // SCR1_TRGT_SIMULATION
|
722 |
|
|
|
723 |
|
|
endmodule : scr1_pipe_ialu
|