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

Subversion Repositories s1_core

[/] [s1_core/] [trunk/] [hdl/] [rtl/] [sparc_core/] [sparc_exu_ecl_divcntl.v] - Blame information for rev 113

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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