OpenCores
URL https://opencores.org/ocsvn/sparc64soc/sparc64soc/trunk

Subversion Repositories sparc64soc

[/] [sparc64soc/] [trunk/] [T1-CPU/] [exu/] [sparc_exu_ecl_divcntl.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.