1 |
2 |
dmitryr |
// ========== Copyright Header Begin ==========================================
|
2 |
|
|
//
|
3 |
|
|
// OpenSPARC T1 Processor File: sparc_exu_ecl_divcntl.v
|
4 |
|
|
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
|
5 |
|
|
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
|
6 |
|
|
//
|
7 |
|
|
// The above named program is free software; you can redistribute it and/or
|
8 |
|
|
// modify it under the terms of the GNU General Public
|
9 |
|
|
// License version 2 as published by the Free Software Foundation.
|
10 |
|
|
//
|
11 |
|
|
// The above named program is distributed in the hope that it will be
|
12 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
|
|
// General Public License for more details.
|
15 |
|
|
//
|
16 |
|
|
// You should have received a copy of the GNU General Public
|
17 |
|
|
// License along with this work; if not, write to the Free Software
|
18 |
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
19 |
|
|
//
|
20 |
|
|
// ========== Copyright Header End ============================================
|
21 |
|
|
////////////////////////////////////////////////////////////////////////
|
22 |
|
|
/*
|
23 |
|
|
// Module Name: sparc_exu_divcntl
|
24 |
|
|
// Description: Control block for div. Division takes 1 cycle to load
|
25 |
|
|
// the values, 65 cycles to calculate the result, and 1 cycle to
|
26 |
|
|
// calculate the ccs and check for overflow.
|
27 |
|
|
// Controlled by a one hot state machine and a 6 bit counter.
|
28 |
|
|
*/
|
29 |
|
|
|
30 |
|
|
`define IDLE 0
|
31 |
|
|
`define RUN 1
|
32 |
|
|
`define LAST_CALC 2
|
33 |
|
|
`define CHK_OVFL 3
|
34 |
|
|
`define FIX_OVFL 4
|
35 |
|
|
`define DONE 5
|
36 |
|
|
|
37 |
|
|
module sparc_exu_ecl_divcntl (/*AUTOARG*/
|
38 |
|
|
// Outputs
|
39 |
|
|
ecl_div_xinmask, ecl_div_keep_d, ecl_div_ld_inputs,
|
40 |
|
|
ecl_div_sel_adder, ecl_div_last_cycle, ecl_div_almostlast_cycle,
|
41 |
|
|
ecl_div_sel_div, divcntl_wb_req_g, divcntl_ccr_cc_w2,
|
42 |
|
|
ecl_div_sel_64b, ecl_div_sel_u32, ecl_div_sel_pos32,
|
43 |
|
|
ecl_div_sel_neg32, ecl_div_upper32_zero, ecl_div_upper33_one,
|
44 |
|
|
ecl_div_upper33_zero, ecl_div_dividend_sign, ecl_div_newq,
|
45 |
|
|
ecl_div_subtract_l, ecl_div_keepx, ecl_div_cin,
|
46 |
|
|
// Inputs
|
47 |
|
|
clk, se, reset, mdqctl_divcntl_input_vld, wb_divcntl_ack_g,
|
48 |
|
|
mdqctl_divcntl_reset_div, div_ecl_gencc_in_msb_l,
|
49 |
|
|
div_ecl_gencc_in_31, div_ecl_upper32_equal, div_ecl_low32_nonzero,
|
50 |
|
|
ecl_div_signed_div, div_ecl_dividend_msb, div_ecl_xin_msb_l,
|
51 |
|
|
div_ecl_x_msb, div_ecl_d_msb, div_ecl_cout64,
|
52 |
|
|
div_ecl_divisorin_31, ecl_div_div64, mdqctl_divcntl_muldone,
|
53 |
|
|
ecl_div_muls, div_ecl_adder_out_31, muls_rs1_31_m_l,
|
54 |
|
|
div_ecl_cout32, rs2_data_31_m, div_ecl_detect_zero_high,
|
55 |
|
|
div_ecl_detect_zero_low, div_ecl_d_62
|
56 |
|
|
) ;
|
57 |
|
|
input clk;
|
58 |
|
|
input se;
|
59 |
|
|
input reset;
|
60 |
|
|
input mdqctl_divcntl_input_vld;
|
61 |
|
|
input wb_divcntl_ack_g;
|
62 |
|
|
input mdqctl_divcntl_reset_div;
|
63 |
|
|
input div_ecl_gencc_in_msb_l;
|
64 |
|
|
input div_ecl_gencc_in_31;
|
65 |
|
|
input div_ecl_upper32_equal;
|
66 |
|
|
input div_ecl_low32_nonzero;
|
67 |
|
|
input ecl_div_signed_div;
|
68 |
|
|
input div_ecl_dividend_msb;
|
69 |
|
|
input div_ecl_xin_msb_l;
|
70 |
|
|
input div_ecl_x_msb;
|
71 |
|
|
input div_ecl_d_msb;
|
72 |
|
|
input div_ecl_cout64;
|
73 |
|
|
input div_ecl_divisorin_31;
|
74 |
|
|
input ecl_div_div64;
|
75 |
|
|
input mdqctl_divcntl_muldone;
|
76 |
|
|
input ecl_div_muls;
|
77 |
|
|
input div_ecl_adder_out_31;
|
78 |
|
|
input muls_rs1_31_m_l;
|
79 |
|
|
input div_ecl_cout32;
|
80 |
|
|
input rs2_data_31_m;
|
81 |
|
|
input div_ecl_detect_zero_high;
|
82 |
|
|
input div_ecl_detect_zero_low;
|
83 |
|
|
input div_ecl_d_62;
|
84 |
|
|
|
85 |
|
|
output ecl_div_xinmask;
|
86 |
|
|
output ecl_div_keep_d;
|
87 |
|
|
output ecl_div_ld_inputs;
|
88 |
|
|
output ecl_div_sel_adder;
|
89 |
|
|
output ecl_div_last_cycle; // last cycle of calculation
|
90 |
|
|
output ecl_div_almostlast_cycle;//
|
91 |
|
|
output ecl_div_sel_div;
|
92 |
|
|
output divcntl_wb_req_g;
|
93 |
|
|
output [7:0] divcntl_ccr_cc_w2;
|
94 |
|
|
output ecl_div_sel_64b;
|
95 |
|
|
output ecl_div_sel_u32;
|
96 |
|
|
output ecl_div_sel_pos32;
|
97 |
|
|
output ecl_div_sel_neg32;
|
98 |
|
|
output ecl_div_upper32_zero;
|
99 |
|
|
output ecl_div_upper33_one;
|
100 |
|
|
output ecl_div_upper33_zero;
|
101 |
|
|
output ecl_div_dividend_sign;
|
102 |
|
|
output ecl_div_newq;
|
103 |
|
|
output ecl_div_subtract_l;
|
104 |
|
|
output ecl_div_keepx;
|
105 |
|
|
output ecl_div_cin;
|
106 |
|
|
|
107 |
|
|
wire firstq;
|
108 |
|
|
wire q_next; // next q bit
|
109 |
|
|
wire adderin1_64; // msbs for adder
|
110 |
|
|
wire adderin2_64;
|
111 |
|
|
wire firstlast_sub; // subtract for first and last cycle
|
112 |
|
|
wire sub_next; // next cycle will subtract
|
113 |
|
|
wire subtract;
|
114 |
|
|
wire bit64_halfadd; // partial result for qpredict
|
115 |
|
|
wire partial_qpredict;
|
116 |
|
|
wire [1:0] q_next_nocout;
|
117 |
|
|
wire [1:0] sub_next_nocout;
|
118 |
|
|
wire partial_qpredict_l;
|
119 |
|
|
wire divisor_sign;
|
120 |
|
|
wire detect_zero;
|
121 |
|
|
wire new_zero_rem_with_zero;
|
122 |
|
|
wire new_zero_rem_no_zero;
|
123 |
|
|
wire zero_rem_d;
|
124 |
|
|
wire zero_rem_q;
|
125 |
|
|
wire last_cin_with_zero;
|
126 |
|
|
wire last_cin_no_zero;
|
127 |
|
|
wire last_cin;
|
128 |
|
|
wire last_cin_next;
|
129 |
|
|
|
130 |
|
|
// overflow correction wires
|
131 |
|
|
wire upper32_equal_d1;
|
132 |
|
|
wire gencc_in_msb_l_d1;
|
133 |
|
|
wire gencc_in_31_d1;
|
134 |
|
|
wire sel_div_d1;
|
135 |
|
|
wire low32_nonzero_d1;
|
136 |
|
|
|
137 |
|
|
// Condition code generation wires
|
138 |
|
|
wire [3:0] xcc;
|
139 |
|
|
wire [3:0] icc;
|
140 |
|
|
wire unsign_ovfl;
|
141 |
|
|
wire pos_ovfl;
|
142 |
|
|
wire neg_ovfl;
|
143 |
|
|
wire muls_c;
|
144 |
|
|
wire next_muls_c;
|
145 |
|
|
wire muls_v;
|
146 |
|
|
wire next_muls_v;
|
147 |
|
|
wire muls_rs1_data_31_m;
|
148 |
|
|
wire div_adder_out_31_w;
|
149 |
|
|
wire rs2_data_31_w;
|
150 |
|
|
wire muls_rs1_data_31_w;
|
151 |
|
|
wire ovfl_32;
|
152 |
|
|
wire div_v;
|
153 |
|
|
|
154 |
|
|
wire [5:0] div_state;
|
155 |
|
|
wire [5:0] next_state;
|
156 |
|
|
wire go_idle,
|
157 |
|
|
stay_idle,
|
158 |
|
|
go_run,
|
159 |
|
|
stay_run,
|
160 |
|
|
go_last_calc,
|
161 |
|
|
go_chk_ovfl,
|
162 |
|
|
go_fix_ovfl,
|
163 |
|
|
go_done,
|
164 |
|
|
stay_done;
|
165 |
|
|
|
166 |
|
|
|
167 |
|
|
wire reset_cnt;
|
168 |
|
|
wire [5:0] cntr;
|
169 |
|
|
wire cntris63;
|
170 |
|
|
|
171 |
|
|
/////////////////////////////////
|
172 |
|
|
// G arbitration between MUL/DIV
|
173 |
|
|
/////////////////////////////////
|
174 |
|
|
assign divcntl_wb_req_g = div_state[`DONE] |
|
175 |
|
|
(~(div_state[`DONE] | div_state[`CHK_OVFL] | div_state[`FIX_OVFL]) &mdqctl_divcntl_muldone);
|
176 |
|
|
assign ecl_div_sel_div = ~(~(div_state[`DONE] | div_state[`CHK_OVFL] | div_state[`FIX_OVFL]) &
|
177 |
|
|
mdqctl_divcntl_muldone);
|
178 |
|
|
|
179 |
|
|
// state flop
|
180 |
|
|
dff_s #(6) divstate_dff(.din(next_state[5:0]), .clk(clk), .q(div_state[5:0]), .se(se), .si(),
|
181 |
|
|
.so());
|
182 |
|
|
|
183 |
|
|
// output logic and state decode
|
184 |
|
|
assign ecl_div_almostlast_cycle = go_last_calc & ~ecl_div_ld_inputs;
|
185 |
|
|
assign ecl_div_sel_adder = (div_state[`RUN] | div_state[`LAST_CALC]) & ~ecl_div_ld_inputs;
|
186 |
|
|
assign ecl_div_last_cycle = div_state[`LAST_CALC];
|
187 |
|
|
assign ecl_div_ld_inputs = mdqctl_divcntl_input_vld;
|
188 |
|
|
assign ecl_div_keep_d = ~(ecl_div_sel_adder | ecl_div_ld_inputs);
|
189 |
|
|
assign reset_cnt = ~div_state[`RUN];
|
190 |
|
|
|
191 |
|
|
// next state logic
|
192 |
|
|
assign stay_idle = div_state[`IDLE] & ~mdqctl_divcntl_input_vld;
|
193 |
|
|
assign go_idle = div_state[`DONE] & wb_divcntl_ack_g;
|
194 |
|
|
assign next_state[`IDLE] = go_idle | stay_idle | mdqctl_divcntl_reset_div | reset;
|
195 |
|
|
|
196 |
|
|
assign stay_run = div_state[`RUN] & ~cntris63 & ~ecl_div_muls;
|
197 |
|
|
assign go_run = (div_state[`IDLE] & mdqctl_divcntl_input_vld);
|
198 |
|
|
assign next_state[`RUN] = (go_run | stay_run) &
|
199 |
|
|
~mdqctl_divcntl_reset_div & ~reset;
|
200 |
|
|
|
201 |
|
|
assign go_last_calc = div_state[`RUN] & (cntris63);
|
202 |
|
|
assign next_state[`LAST_CALC] = go_last_calc & ~mdqctl_divcntl_reset_div & ~reset;
|
203 |
|
|
|
204 |
|
|
// chk_ovfl and fix_ovfl are place holders to guarantee that the overflow checking
|
205 |
|
|
// takes place on the result. No special logic occurs in them compared to the done state.
|
206 |
|
|
assign go_chk_ovfl = div_state[`LAST_CALC];
|
207 |
|
|
assign next_state[`CHK_OVFL] = go_chk_ovfl & ~mdqctl_divcntl_reset_div & ~reset;
|
208 |
|
|
|
209 |
|
|
assign go_fix_ovfl = div_state[`CHK_OVFL] | (div_state[`RUN] & ecl_div_muls);
|
210 |
|
|
assign next_state[`FIX_OVFL] = go_fix_ovfl & ~mdqctl_divcntl_reset_div & ~reset;
|
211 |
|
|
|
212 |
|
|
assign go_done = div_state[`FIX_OVFL];
|
213 |
|
|
assign stay_done = div_state[`DONE] & ~wb_divcntl_ack_g;
|
214 |
|
|
assign next_state[`DONE] = (go_done | stay_done) & ~mdqctl_divcntl_reset_div & ~reset;
|
215 |
|
|
|
216 |
|
|
// counter
|
217 |
|
|
sparc_exu_ecl_cnt6 cnt6(.reset (reset_cnt),
|
218 |
|
|
/*AUTOINST*/
|
219 |
|
|
// Outputs
|
220 |
|
|
.cntr (cntr[5:0]),
|
221 |
|
|
// Inputs
|
222 |
|
|
.clk (clk),
|
223 |
|
|
.se (se));
|
224 |
|
|
|
225 |
|
|
assign cntris63 = cntr[5] & cntr[4] & cntr[3] & cntr[2] & cntr[1] & cntr[0];
|
226 |
|
|
|
227 |
|
|
|
228 |
|
|
///////////////////////////////
|
229 |
|
|
// Random logic for divider
|
230 |
|
|
///////////////////////////////
|
231 |
|
|
// Generation of sign extension of dividend and divisor
|
232 |
|
|
assign ecl_div_dividend_sign = ecl_div_signed_div & div_ecl_dividend_msb;
|
233 |
|
|
assign ecl_div_xinmask = div_ecl_divisorin_31 & ecl_div_signed_div;
|
234 |
|
|
|
235 |
|
|
assign divisor_sign = div_ecl_x_msb & ecl_div_signed_div;
|
236 |
|
|
|
237 |
|
|
// Generation of next bit of quotient
|
238 |
|
|
////////////////////////////////////////////////////////////////
|
239 |
|
|
// Calculate the next q. Requires calculating the result
|
240 |
|
|
// of the 65th bit of the adder and xoring it with the sign of
|
241 |
|
|
// the divisor. The order of these xors is switched for critical
|
242 |
|
|
// path considerations.
|
243 |
|
|
////////////////////////////////////////////////////////////////
|
244 |
|
|
assign adderin1_64 = div_ecl_d_msb;
|
245 |
|
|
assign adderin2_64 = (ecl_div_signed_div & div_ecl_x_msb) ^ subtract;
|
246 |
|
|
assign bit64_halfadd = adderin1_64 ^ adderin2_64;
|
247 |
|
|
assign partial_qpredict = bit64_halfadd ^ ~(div_ecl_x_msb & ecl_div_signed_div);
|
248 |
|
|
assign partial_qpredict_l = ~partial_qpredict;
|
249 |
|
|
//assign qpredict = partial_qpredict ^ div_ecl_cout64;
|
250 |
|
|
//assign firstq = ~ecl_div_signed_div | div_ecl_xin_msb_l;
|
251 |
|
|
assign firstq = ecl_div_dividend_sign;
|
252 |
|
|
|
253 |
|
|
mux2ds #(2) qnext_mux(.dout(q_next_nocout[1:0]),
|
254 |
|
|
.in0({partial_qpredict, partial_qpredict_l}),
|
255 |
|
|
.in1({2{firstq}}),
|
256 |
|
|
.sel0(~ecl_div_ld_inputs),
|
257 |
|
|
.sel1(ecl_div_ld_inputs));
|
258 |
|
|
dp_mux2es qnext_cout_mux(.dout(q_next),
|
259 |
|
|
.in0(q_next_nocout[1]),
|
260 |
|
|
.in1(q_next_nocout[0]),
|
261 |
|
|
.sel(div_ecl_cout64));
|
262 |
|
|
|
263 |
|
|
dff_s q_dff(.din(q_next), .clk(clk), .q(ecl_div_newq), .se(se), .si(),
|
264 |
|
|
.so());
|
265 |
|
|
|
266 |
|
|
|
267 |
|
|
////////////////////////////
|
268 |
|
|
// Subtraction logic and subtract flop
|
269 |
|
|
//-------------------------------------
|
270 |
|
|
// To take the subtraction calc out of the critical path,
|
271 |
|
|
// it is done in the previous cycle and part is done with a
|
272 |
|
|
// mux. The result is put into a flop.
|
273 |
|
|
////////////////////////////
|
274 |
|
|
assign firstlast_sub = ~ecl_div_almostlast_cycle & ~ecl_div_muls &
|
275 |
|
|
(~ecl_div_signed_div | ~(div_ecl_dividend_msb ^ ~div_ecl_xin_msb_l));
|
276 |
|
|
|
277 |
|
|
assign ecl_div_keepx = ~(ecl_div_ld_inputs |
|
278 |
|
|
ecl_div_almostlast_cycle);
|
279 |
|
|
|
280 |
|
|
mux2ds #(2) subnext_mux(.dout(sub_next_nocout[1:0]),
|
281 |
|
|
.in0({2{firstlast_sub}}),
|
282 |
|
|
.in1({partial_qpredict, partial_qpredict_l}),
|
283 |
|
|
.sel0(~ecl_div_keepx),
|
284 |
|
|
.sel1(ecl_div_keepx));
|
285 |
|
|
dp_mux2es subtract_cout_mux(.dout(sub_next),
|
286 |
|
|
.in0(sub_next_nocout[1]),
|
287 |
|
|
.in1(sub_next_nocout[0]),
|
288 |
|
|
.sel(div_ecl_cout64));
|
289 |
|
|
|
290 |
|
|
dff_s sub_dff(.din(sub_next), .clk(clk), .q(subtract), .se(se), .si(),
|
291 |
|
|
.so());
|
292 |
|
|
|
293 |
|
|
assign ecl_div_subtract_l = ~subtract;
|
294 |
|
|
|
295 |
|
|
|
296 |
|
|
/////////////////////////////////////////////
|
297 |
|
|
// Carry in logic
|
298 |
|
|
//--------------------------------------------
|
299 |
|
|
// The carry is usually just subtract. The
|
300 |
|
|
// quotient correction for signed division
|
301 |
|
|
// sometimes has to adjust it though.
|
302 |
|
|
/////////////////////////////////////////////
|
303 |
|
|
assign detect_zero = div_ecl_detect_zero_low & div_ecl_detect_zero_high;
|
304 |
|
|
|
305 |
|
|
assign ecl_div_cin = (ecl_div_last_cycle)? last_cin: subtract;
|
306 |
|
|
// stores if the partial remainder was ever zero.
|
307 |
|
|
/* -----\/----- EXCLUDED -----\/-----
|
308 |
|
|
// changed for timing
|
309 |
|
|
assign zero_rem_d = ~ecl_div_ld_inputs & (div_ecl_detect_zero | zero_rem_q) &
|
310 |
|
|
(~div_ecl_d_62 | ecl_div_almostlast_cycle);
|
311 |
|
|
-----/\----- EXCLUDED -----/\----- */
|
312 |
|
|
assign new_zero_rem_with_zero = ~ecl_div_ld_inputs & (~div_ecl_d_62 | ecl_div_almostlast_cycle);
|
313 |
|
|
assign new_zero_rem_no_zero = zero_rem_q & new_zero_rem_with_zero;
|
314 |
|
|
assign zero_rem_d = (detect_zero)? new_zero_rem_with_zero: new_zero_rem_no_zero;
|
315 |
|
|
dff_s zero_rem_dff(.din(zero_rem_d), .clk(clk), .q(zero_rem_q),
|
316 |
|
|
.se(se), .si(), .so());
|
317 |
|
|
|
318 |
|
|
/* -----\/----- EXCLUDED -----\/-----
|
319 |
|
|
// changed for timing
|
320 |
|
|
assign last_cin_next = ecl_div_signed_div & (divisor_sign & ~div_ecl_d_62 |
|
321 |
|
|
~divisor_sign &div_ecl_d_62&~zero_rem_d |
|
322 |
|
|
divisor_sign &div_ecl_d_62&zero_rem_d);
|
323 |
|
|
-----/\----- EXCLUDED -----/\----- */
|
324 |
|
|
assign last_cin_with_zero = ecl_div_signed_div & (divisor_sign & ~div_ecl_d_62 |
|
325 |
|
|
~divisor_sign &div_ecl_d_62&~new_zero_rem_with_zero |
|
326 |
|
|
divisor_sign &div_ecl_d_62&new_zero_rem_with_zero);
|
327 |
|
|
assign last_cin_no_zero = ecl_div_signed_div & (divisor_sign & ~div_ecl_d_62 |
|
328 |
|
|
~divisor_sign &div_ecl_d_62&~new_zero_rem_no_zero |
|
329 |
|
|
divisor_sign &div_ecl_d_62&new_zero_rem_no_zero);
|
330 |
|
|
assign last_cin_next = (detect_zero)? last_cin_with_zero: last_cin_no_zero;
|
331 |
|
|
dff_s last_cin_dff(.din(last_cin_next), .clk(clk), .q(last_cin),
|
332 |
|
|
.se(se), .si(), .so());
|
333 |
|
|
|
334 |
|
|
///////////////////////////////
|
335 |
|
|
// Condition code generation
|
336 |
|
|
///////////////////////////////
|
337 |
|
|
// There is a special case:
|
338 |
|
|
// For 64 bit signed division largest neg/-1 = largest neg
|
339 |
|
|
// However for 32 bit division this will give us positive overflow.
|
340 |
|
|
// This is detected by a sign switch on this case.
|
341 |
|
|
wire inputs_neg_d;
|
342 |
|
|
wire inputs_neg_q;
|
343 |
|
|
wire large_neg_ovfl;
|
344 |
|
|
assign inputs_neg_d = div_ecl_dividend_msb & div_ecl_divisorin_31;
|
345 |
|
|
assign large_neg_ovfl = inputs_neg_q & ~gencc_in_msb_l_d1;
|
346 |
|
|
dffe_s inputs_neg_dff(.din(inputs_neg_d), .clk(clk), .q(inputs_neg_q),
|
347 |
|
|
.en(ecl_div_ld_inputs), .se(se), .si(), .so());
|
348 |
|
|
dff_s #(5) cc_sig_dff(.din({div_ecl_upper32_equal, div_ecl_gencc_in_msb_l,
|
349 |
|
|
div_ecl_gencc_in_31, ecl_div_sel_div, div_ecl_low32_nonzero}),
|
350 |
|
|
.q({upper32_equal_d1, gencc_in_msb_l_d1,
|
351 |
|
|
gencc_in_31_d1, sel_div_d1, low32_nonzero_d1}),
|
352 |
|
|
.clk(clk), .se(se), .si(), .so());
|
353 |
|
|
// selects for correcting divide overflow
|
354 |
|
|
assign ecl_div_sel_64b = ecl_div_div64 | ecl_div_muls;
|
355 |
|
|
assign ecl_div_sel_u32 = ~ecl_div_sel_64b & ~ecl_div_signed_div;
|
356 |
|
|
assign ecl_div_sel_pos32 = (~ecl_div_sel_64b & ecl_div_signed_div &
|
357 |
|
|
(gencc_in_msb_l_d1 | large_neg_ovfl));
|
358 |
|
|
assign ecl_div_sel_neg32 = (~ecl_div_sel_64b & ecl_div_signed_div &
|
359 |
|
|
~gencc_in_msb_l_d1 & ~large_neg_ovfl);
|
360 |
|
|
|
361 |
|
|
// results of checking are staged one cycle for timing reasons
|
362 |
|
|
// this is the reason for the chk and fix ovfl states
|
363 |
|
|
assign ecl_div_upper32_zero = upper32_equal_d1 & gencc_in_msb_l_d1;
|
364 |
|
|
assign ecl_div_upper33_zero = (upper32_equal_d1 & gencc_in_msb_l_d1 &
|
365 |
|
|
~gencc_in_31_d1);
|
366 |
|
|
assign ecl_div_upper33_one = (upper32_equal_d1 & ~gencc_in_msb_l_d1 &
|
367 |
|
|
gencc_in_31_d1);
|
368 |
|
|
|
369 |
|
|
// divide overflow
|
370 |
|
|
assign unsign_ovfl = ecl_div_sel_u32 & ~ecl_div_upper32_zero & sel_div_d1;
|
371 |
|
|
assign pos_ovfl = ecl_div_sel_pos32 & ~ecl_div_upper33_zero & sel_div_d1;
|
372 |
|
|
assign neg_ovfl = ecl_div_sel_neg32 & ~ecl_div_upper33_one & sel_div_d1;
|
373 |
|
|
assign div_v = pos_ovfl | unsign_ovfl | neg_ovfl;
|
374 |
|
|
|
375 |
|
|
// muls carry and overflow
|
376 |
|
|
assign next_muls_c = (div_state[`RUN]) ? div_ecl_cout32: muls_c;
|
377 |
|
|
|
378 |
|
|
assign muls_rs1_data_31_m = ~muls_rs1_31_m_l;
|
379 |
|
|
dff_s #(3) muls_overlow_dff(.din({muls_rs1_data_31_m, rs2_data_31_m, div_ecl_adder_out_31}),
|
380 |
|
|
.q({muls_rs1_data_31_w, rs2_data_31_w, div_adder_out_31_w}),
|
381 |
|
|
.clk(clk), .se(se), .si(), .so());
|
382 |
|
|
assign ovfl_32 = ((muls_rs1_data_31_w & rs2_data_31_w & ~div_adder_out_31_w) |
|
383 |
|
|
(~muls_rs1_data_31_w & ~rs2_data_31_w & div_adder_out_31_w));
|
384 |
|
|
assign next_muls_v = (div_state[`FIX_OVFL]) ? ovfl_32: muls_v;
|
385 |
|
|
dff_s muls_c_dff(.din(next_muls_c), .clk(clk), .q(muls_c),
|
386 |
|
|
.se(se), .si(), .so());
|
387 |
|
|
dff_s muls_v_dff(.din(next_muls_v), .clk(clk), .q(muls_v),
|
388 |
|
|
.se(se), .si(), .so());
|
389 |
|
|
|
390 |
|
|
// negative
|
391 |
|
|
assign xcc[3] = ~gencc_in_msb_l_d1 & ~unsign_ovfl & ~pos_ovfl;
|
392 |
|
|
assign icc[3] = (gencc_in_31_d1 & ~pos_ovfl) | neg_ovfl | unsign_ovfl;
|
393 |
|
|
// zero
|
394 |
|
|
assign xcc[2] = upper32_equal_d1 & gencc_in_msb_l_d1 & ~low32_nonzero_d1;
|
395 |
|
|
assign icc[2] = ~low32_nonzero_d1 & ~div_v; // nonzero checks before ovfl
|
396 |
|
|
//overflow
|
397 |
|
|
assign xcc[1] = 1'b0;
|
398 |
|
|
assign icc[1] = (ecl_div_muls & sel_div_d1) ? muls_v: div_v;
|
399 |
|
|
// carry
|
400 |
|
|
assign xcc[0] = 1'b0;
|
401 |
|
|
assign icc[0] = ecl_div_muls & sel_div_d1 & muls_c;
|
402 |
|
|
|
403 |
|
|
assign divcntl_ccr_cc_w2 = {xcc, icc};
|
404 |
|
|
|
405 |
|
|
endmodule // sparc_exu_divcntl
|