source: XOpenSparcT1/trunk/T1-CPU/exu/sparc_exu_ecl_divcntl.v @ 6

Revision 6, 17.7 KB checked in by pntsvt00, 14 years ago (diff)

versione iniziale opensparc

RevLine 
[6]1// ========== 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
37module 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
405endmodule // sparc_exu_divcntl
Note: See TracBrowser for help on using the repository browser.