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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_fpu_post_norm_intfloat_conv.v] - Blame information for rev 364

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 258 julius
/////////////////////////////////////////////////////////////////////
2
////                                                             ////
3
////  or1200_fpu_post_norm_intfloat_conv                         ////
4
////  Floating Point Post Normalisation Unit                     ////
5
////                                                             ////
6
////  Author: Rudolf Usselmann                                   ////
7
////          rudi@asics.ws                                      ////
8
//// Modified by Julius Baxter, July, 2010                       ////
9
////             julius.baxter@orsoc.se                          ////
10
////                                                             ////
11
/////////////////////////////////////////////////////////////////////
12
////                                                             ////
13
//// Copyright (C) 2000 Rudolf Usselmann                         ////
14
////                    rudi@asics.ws                            ////
15
////                                                             ////
16
//// This source file may be used and distributed without        ////
17
//// restriction provided that this copyright statement is not   ////
18
//// removed from the file and that any derivative work contains ////
19
//// the original copyright notice and the associated disclaimer.////
20
////                                                             ////
21
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
22
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
23
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
24
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
25
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
26
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
27
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
28
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
29
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
30
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
31
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
32
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
33
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
34
////                                                             ////
35
/////////////////////////////////////////////////////////////////////
36
 
37
 
38
`timescale 1ns / 100ps
39
 
40
module or1200_fpu_post_norm_intfloat_conv
41
  (
42
    clk, fpu_op, opas, sign, rmode, fract_in,
43
    exp_in, opa_dn, opa_nan, opa_inf, opb_dn,  out,
44
    ine, inv, overflow, underflow, f2i_out_sign
45
    );
46
   input                clk;
47
   input [2:0]           fpu_op;
48
   input                opas;
49
   input                sign;
50
   input [1:0]           rmode;
51
   input [47:0]  fract_in;
52
   input [7:0]           exp_in;
53
   input                opa_dn, opb_dn;
54
   input                opa_nan, opa_inf;
55
 
56
   output [30:0]         out;
57
   output               ine, inv;
58
   output               overflow, underflow;
59
   output               f2i_out_sign;
60
 
61
   ////////////////////////////////////////////////////////////////////////
62
   //
63
   // Local Wires and registers
64
   //
65
 
66
   /*wire*/ reg [22:0]           fract_out;
67
   /*wire*/reg [7:0]             exp_out;
68
   wire [30:0]           out;
69
   wire                 exp_out1_co, overflow, underflow;
70
   wire [22:0]           fract_out_final;
71
   reg [22:0]            fract_out_rnd;
72
   wire [8:0]            exp_next_mi;
73
   wire                 dn;
74
   wire                 exp_rnd_adj;
75
   wire [7:0]            exp_out_final;
76
   reg [7:0]             exp_out_rnd;
77
   wire                 op_dn = opa_dn | opb_dn;
78
   wire                 op_mul = fpu_op[2:0]==3'b010;
79
   wire                 op_div = fpu_op[2:0]==3'b011;
80
   wire                 op_i2f = fpu_op[2:0]==3'b100;
81
   wire                 op_f2i = fpu_op[2:0]==3'b101;
82
   reg [5:0]             fi_ldz;
83
 
84
   wire                 g, r, s;
85
   wire                 round, round2, round2a, round2_fasu, round2_fmul;
86
   wire [7:0]            exp_out_rnd0, exp_out_rnd1, exp_out_rnd2, exp_out_rnd2a;
87
   wire [22:0]           fract_out_rnd0, fract_out_rnd1, fract_out_rnd2,
88
                        fract_out_rnd2a;
89
   wire                 exp_rnd_adj0, exp_rnd_adj2a;
90
   wire                 r_sign;
91
   wire                 ovf0, ovf1;
92
   wire [23:0]           fract_out_pl1;
93
   wire [7:0]            exp_out_pl1, exp_out_mi1;
94
   wire                 exp_out_00, exp_out_fe, exp_out_ff, exp_in_00,
95
                        exp_in_ff;
96
   wire                 exp_out_final_ff, fract_out_7fffff;
97
   /*wire*/reg [24:0]            fract_trunc;
98
   wire [7:0]            exp_out1;
99
   wire                 grs_sel;
100
   wire                 fract_out_00;
101
   reg                  fract_in_00;
102
   wire                 shft_co;
103
   wire [8:0]            exp_in_pl1, exp_in_mi1;
104
   wire [47:0]           fract_in_shftr;
105
   wire [47:0]           fract_in_shftl;
106
 
107
   wire [7:0]            shft2;
108
   wire [7:0]            exp_out1_mi1;
109
 
110
   wire [6:0]            fi_ldz_2a;
111
   wire [7:0]            fi_ldz_2;
112
 
113
   wire                 left_right;
114
   wire [7:0]            shift_right;
115
   wire [7:0]            shift_left;
116
   wire [7:0]            fasu_shift;
117
 
118
   wire [5:0]            fi_ldz_mi1;
119
   wire [5:0]            fi_ldz_mi22;
120
   wire [6:0]            ldz_all;
121
 
122
   wire [7:0]            f2i_shft;
123
   wire [55:0]           exp_f2i_1;
124
   wire                 f2i_zero, f2i_max;
125
   wire [7:0]            f2i_emin;
126
   wire                 f2i_exp_gt_max ,f2i_exp_lt_min;
127
   wire [7:0]            conv_shft;
128
   wire [7:0]            exp_i2f, exp_f2i, conv_exp;
129
   wire                 round2_f2i;
130
 
131
   ////////////////////////////////////////////////////////////////////////
132
   //
133
   // Normalize and Round Logic
134
   //
135
 
136
   // ---------------------------------------------------------------------
137
   // Count Leading zeros in fraction
138
 
139
   always @(/*fract_in*/ posedge clk)
140 364 julius
     casez(fract_in)    // synopsys full_case parallel_case
141 258 julius
       48'b1???????????????????????????????????????????????: fi_ldz <=  1;
142
       48'b01??????????????????????????????????????????????: fi_ldz <=  2;
143
       48'b001?????????????????????????????????????????????: fi_ldz <=  3;
144
       48'b0001????????????????????????????????????????????: fi_ldz <=  4;
145
       48'b00001???????????????????????????????????????????: fi_ldz <=  5;
146
       48'b000001??????????????????????????????????????????: fi_ldz <=  6;
147
       48'b0000001?????????????????????????????????????????: fi_ldz <=  7;
148
       48'b00000001????????????????????????????????????????: fi_ldz <=  8;
149
       48'b000000001???????????????????????????????????????: fi_ldz <=  9;
150
       48'b0000000001??????????????????????????????????????: fi_ldz <=  10;
151
       48'b00000000001?????????????????????????????????????: fi_ldz <=  11;
152
       48'b000000000001????????????????????????????????????: fi_ldz <=  12;
153
       48'b0000000000001???????????????????????????????????: fi_ldz <=  13;
154
       48'b00000000000001??????????????????????????????????: fi_ldz <=  14;
155
       48'b000000000000001?????????????????????????????????: fi_ldz <=  15;
156
       48'b0000000000000001????????????????????????????????: fi_ldz <=  16;
157
       48'b00000000000000001???????????????????????????????: fi_ldz <=  17;
158
       48'b000000000000000001??????????????????????????????: fi_ldz <=  18;
159
       48'b0000000000000000001?????????????????????????????: fi_ldz <=  19;
160
       48'b00000000000000000001????????????????????????????: fi_ldz <=  20;
161
       48'b000000000000000000001???????????????????????????: fi_ldz <=  21;
162
       48'b0000000000000000000001??????????????????????????: fi_ldz <=  22;
163
       48'b00000000000000000000001?????????????????????????: fi_ldz <=  23;
164
       48'b000000000000000000000001????????????????????????: fi_ldz <=  24;
165
       48'b0000000000000000000000001???????????????????????: fi_ldz <=  25;
166
       48'b00000000000000000000000001??????????????????????: fi_ldz <=  26;
167
       48'b000000000000000000000000001?????????????????????: fi_ldz <=  27;
168
       48'b0000000000000000000000000001????????????????????: fi_ldz <=  28;
169
       48'b00000000000000000000000000001???????????????????: fi_ldz <=  29;
170
       48'b000000000000000000000000000001??????????????????: fi_ldz <=  30;
171
       48'b0000000000000000000000000000001?????????????????: fi_ldz <=  31;
172
       48'b00000000000000000000000000000001????????????????: fi_ldz <=  32;
173
       48'b000000000000000000000000000000001???????????????: fi_ldz <=  33;
174
       48'b0000000000000000000000000000000001??????????????: fi_ldz <=  34;
175
       48'b00000000000000000000000000000000001?????????????: fi_ldz <=  35;
176
       48'b000000000000000000000000000000000001????????????: fi_ldz <=  36;
177
       48'b0000000000000000000000000000000000001???????????: fi_ldz <=  37;
178
       48'b00000000000000000000000000000000000001??????????: fi_ldz <=  38;
179
       48'b000000000000000000000000000000000000001?????????: fi_ldz <=  39;
180
       48'b0000000000000000000000000000000000000001????????: fi_ldz <=  40;
181
       48'b00000000000000000000000000000000000000001???????: fi_ldz <=  41;
182
       48'b000000000000000000000000000000000000000001??????: fi_ldz <=  42;
183
       48'b0000000000000000000000000000000000000000001?????: fi_ldz <=  43;
184
       48'b00000000000000000000000000000000000000000001????: fi_ldz <=  44;
185
       48'b000000000000000000000000000000000000000000001???: fi_ldz <=  45;
186
       48'b0000000000000000000000000000000000000000000001??: fi_ldz <=  46;
187
       48'b00000000000000000000000000000000000000000000001?: fi_ldz <=  47;
188
       48'b00000000000000000000000000000000000000000000000?: fi_ldz <=  48;
189
     endcase
190
 
191
 
192
   // ---------------------------------------------------------------------
193
   // Normalize
194
 
195
   wire                 exp_in_80;
196
   wire                 rmode_00, rmode_01, rmode_10, rmode_11;
197
 
198
   // Misc common signals
199
   assign exp_in_ff        = &exp_in;
200
   assign exp_in_00        = !(|exp_in);
201
   assign exp_in_80     = exp_in[7] & !(|exp_in[6:0]);
202
   assign exp_out_ff       = &exp_out;
203
   assign exp_out_00       = !(|exp_out);
204
   assign exp_out_fe       = &exp_out[7:1] & !exp_out[0];
205
   assign exp_out_final_ff = &exp_out_final;
206
 
207
   assign fract_out_7fffff = &fract_out;
208
   assign fract_out_00     = !(|fract_out);
209
   //assign fract_in_00      = !(|fract_in);
210
   always @(posedge clk)
211
     fract_in_00  <= !(|fract_in);
212
 
213
   assign rmode_00 = (rmode==2'b00);
214
   assign rmode_01 = (rmode==2'b01);
215
   assign rmode_10 = (rmode==2'b10);
216
   assign rmode_11 = (rmode==2'b11);
217
 
218
   // Fasu Output will be denormalized ...
219
   assign dn = !op_mul & !op_div &
220
               (exp_in_00 | (exp_next_mi[8] & !fract_in[47]) );
221
 
222
   // ---------------------------------------------------------------------
223
   // Fraction Normalization
224
   parameter    f2i_emax = 8'h9d;
225
 
226
   // Special Signals for f2i
227
   assign f2i_emin = rmode_00 ? 8'h7e : 8'h7f;
228
 
229
   assign f2i_exp_gt_max = (exp_in > f2i_emax);
230
   assign f2i_exp_lt_min = (exp_in < f2i_emin);
231
 
232
   // Incremented fraction for rounding
233
   assign fract_out_pl1 = fract_out + 1;
234
 
235
   /*
236
    assign f2i_zero = (!opas & (exp_in<f2i_emin)) |
237
    (opas & (exp_in>f2i_emax)) |
238
    (opas & (exp_in<f2i_emin) & (fract_in_00 | !rmode_11));
239
 
240
    assign f2i_max = (!opas & (exp_in>f2i_emax)) |
241
    (opas & (exp_in<f2i_emin) & !fract_in_00 & rmode_11);
242
    */
243
   // Zero when :
244
   // a) too small exp. and positive sign - result will be 0
245
   // b) too big exp. and negative sign - result will be largest possible -int
246
   // c) -infinity: largest possible -int
247
   // d) -0.0: give positive 0
248
   assign f2i_zero = (
249
                      ( (f2i_exp_lt_min & (opas & (!rmode_11 | fract_in_00))) |
250
                        (f2i_exp_lt_min & !opas) |
251
                        (f2i_exp_gt_max & opas) )
252
                      & !(&exp_in)
253
                      ) |
254
                     // -inf case
255
                     (opa_inf & opas) |
256
                       // -0.0 case
257
                       (fract_in_00 & exp_in_00);
258
 
259
   // Maximum :
260
   // a) too big exp and positive sign - result will be maximum int.
261
   // b) rounding negative down and less than minimum expon. for int = -1
262
   // c) +/- NaN or +inf - result will be maximum int
263
   // d) disabled when the -0.0 case comes up
264
   assign f2i_max = (
265
                     ( ((!opas & f2i_exp_gt_max) |
266
                        (f2i_exp_lt_min & !fract_in_00 & rmode_11 & opas))
267
                       & !(&exp_in)) |
268
                     // Either +/- NaN, or +inf
269
                     (opa_nan | (opa_inf & !opas))) &
270
                    // .. and NOT -0.0( 0x80000000)
271
                    !(opas & fract_in_00 & exp_in_00);
272
 
273
   // Claculate various shifting options
274
   assign f2i_shft  = exp_in-8'h7d;
275
 
276
   assign conv_shft = op_f2i ? f2i_shft : {2'h0, fi_ldz};
277
 
278
   assign fract_in_shftl   = (|conv_shft[7:6] | (f2i_zero & op_f2i)) ?
279
 
280
 
281
   // Final fraction output
282
   always @(posedge clk)
283
     {fract_out,fract_trunc} <= fract_in_shftl;
284
 
285
 
286
   // ---------------------------------------------------------------------
287
   // Exponent Normalization
288
 
289
   assign fi_ldz_mi1    = fi_ldz - 1;
290
   assign fi_ldz_mi22   = fi_ldz - 22;
291
   assign exp_out_pl1   = exp_out + 1;
292
   assign exp_out_mi1   = exp_out - 1;
293
   assign exp_in_pl1    = exp_in  + 1;  // 9 bits - includes carry out
294
   assign exp_in_mi1    = exp_in  - 1;  // 9 bits - includes carry out
295
   assign exp_out1_mi1  = exp_out1 - 1;
296
 
297 364 julius
   assign exp_next_mi  = exp_in_pl1 -
298
                         {3'd0,fi_ldz_mi1}; // 9 bits - includes carry out
299 258 julius
 
300
   assign {exp_out1_co, exp_out1} = fract_in[47] ? exp_in_pl1 : exp_next_mi;
301
 
302
   // Only ever force positive if:
303
   // i) It's a NaN
304
   // ii) It's zero and not -inf
305
   // iii) We've rounded to 0 (both fract and exp out are 0 and not forced)
306
   // Force to 1 (negative) when have negative sign with too big exponent
307
   assign f2i_out_sign = (opas & (exp_in>f2i_emax) & f2i_zero) ?
308
                         1 : opa_nan | (f2i_zero & !f2i_max & !(opa_inf & opas))
309
                           | (!(|out) & !f2i_zero)
310
                             ?
311
 
312
 
313 364 julius
   assign exp_i2f   = fract_in_00 ? (opas ? 8'h9e : 0) : (8'h9e-{2'd0,fi_ldz});
314 258 julius
   assign exp_f2i_1 = {{8{fract_in[47]}}, fract_in }<<f2i_shft;
315
   assign exp_f2i   = f2i_zero ? 0 : f2i_max ? 8'hff : exp_f2i_1[55:48];
316
   assign conv_exp  = op_f2i ? exp_f2i : exp_i2f;
317
 
318
   //assign exp_out = conv_exp;
319
   always @(posedge clk)
320
     exp_out <= conv_exp;
321
 
322
 
323 364 julius
   assign ldz_all   = {1'b0,fi_ldz};
324 258 julius
   assign fi_ldz_2a = 6'd23 - fi_ldz;
325
   assign fi_ldz_2  = {fi_ldz_2a[6], fi_ldz_2a[6:0]};
326
 
327
 
328
   // ---------------------------------------------------------------------
329
   // Round
330
 
331
   // Extract rounding (GRS) bits
332
   assign g = fract_out[0];
333
   assign r = fract_trunc[24];
334
   assign s = |fract_trunc[23:0];
335
 
336
   // Round to nearest even
337
   assign round = (g & r) | (r & s) ;
338
   assign {exp_rnd_adj0, fract_out_rnd0} = round ?
339
                                           fract_out_pl1 : {1'b0, fract_out};
340
 
341
   assign exp_out_rnd0 =  exp_rnd_adj0 ? exp_out_pl1 : exp_out;
342
 
343
   assign ovf0 = exp_out_final_ff & !rmode_01 & !op_f2i;
344
 
345
   // round to zero
346
   // Added detection of sign and rounding up in case of negative ftoi! - JPB
347
   assign fract_out_rnd1 = (exp_out_ff  & !dn & !op_f2i) ?
348
                           23'h7fffff :
349
                           (op_f2i & (|fract_trunc) & opas) ?
350
                           fract_out_pl1[22:0] : fract_out ;
351
 
352
   assign exp_out_rnd1 = (g & r & s & exp_in_ff) ?
353
                         exp_next_mi[7:0] : (exp_out_ff & !op_f2i) ?
354
                         exp_in :
355
                         (op_f2i & opas & (|fract_trunc) & fract_out_pl1[23]) ?
356
                         exp_out_pl1: exp_out;
357
 
358
   assign ovf1 = exp_out_ff & !dn;
359
 
360
   // round to +inf (UP) and -inf (DOWN)
361
   assign r_sign = sign;
362
 
363
   assign round2a = !exp_out_fe | !fract_out_7fffff |
364
                    (exp_out_fe & fract_out_7fffff);
365
 
366
   assign round2_fasu = ((r | s) & !r_sign) & (!exp_out[7] |
367
                                               (exp_out[7] & round2a));
368
 
369
   assign round2_f2i = rmode_10 &
370
                       (( |fract_in[23:0] & !opas & (exp_in<8'h80 )) |
371
                        (|fract_trunc));
372
 
373
   assign round2 = op_f2i ? round2_f2i : round2_fasu;
374
 
375
   assign {exp_rnd_adj2a, fract_out_rnd2a} = round2 ? fract_out_pl1 :
376
                                             {1'b0, fract_out};
377
 
378
   assign exp_out_rnd2a  = exp_rnd_adj2a ?  exp_out_pl1 : exp_out;
379
 
380
   assign fract_out_rnd2 = (r_sign & exp_out_ff & !op_div & !dn & !op_f2i) ?
381
                           23'h7fffff : fract_out_rnd2a;
382
 
383
   assign exp_out_rnd2   = (r_sign & exp_out_ff & !op_f2i) ?
384
                           8'hfe      : exp_out_rnd2a;
385
 
386
 
387
   // Choose rounding mode
388
   always @(rmode or exp_out_rnd0 or exp_out_rnd1 or exp_out_rnd2)
389
     case(rmode)        // synopsys full_case parallel_case
390
       0: exp_out_rnd = exp_out_rnd0;
391
       1: exp_out_rnd = exp_out_rnd1;
392
       2,3: exp_out_rnd = exp_out_rnd2;
393
     endcase
394
 
395
   always @(rmode or fract_out_rnd0 or fract_out_rnd1 or fract_out_rnd2)
396
     case(rmode)        // synopsys full_case parallel_case
397
       0: fract_out_rnd = fract_out_rnd0;
398
       1: fract_out_rnd = fract_out_rnd1;
399
       2,3: fract_out_rnd = fract_out_rnd2;
400
     endcase
401
 
402
   // ---------------------------------------------------------------------
403
   // Final Output Mux
404
   // Fix Output for denormalized and special numbers
405
 
406
   assign fract_out_final = ovf0 ? 23'h0 :
407
                            (f2i_max & op_f2i) ? 23'h7fffff :
408
                            fract_out_rnd;
409
 
410
   assign exp_out_final = (f2i_max & op_f2i) ? 8'hff :  exp_out_rnd;
411
 
412
   // ---------------------------------------------------------------------
413
   // Pack Result
414
 
415
   assign out = {exp_out_final, fract_out_final};
416
 
417
   // ---------------------------------------------------------------------
418
   // Exceptions
419
 
420
 
421
   assign underflow = (!fract_in[47] & exp_out1_co) & !dn;
422
 
423
 
424
   assign overflow  = ovf0 | ovf1;
425
 
426
   wire                 f2i_ine;
427
   wire                 exp_in_lt_half = (exp_in<8'h80);
428
 
429
   assign f2i_ine = (f2i_zero & !fract_in_00 & !opas) |
430
                    (|fract_trunc) |
431
                    (f2i_zero & exp_in_lt_half  & opas & !fract_in_00) |
432
                    (f2i_max & rmode_11 & (exp_in<8'h80));
433
 
434
   assign ine = op_f2i ? f2i_ine :
435
               op_i2f ? (|fract_trunc) :
436
               ((r & !dn) | (s & !dn) );
437
 
438
   assign inv = op_f2i & (exp_in > f2i_emax);
439
 
440
 
441
 
442
endmodule // or1200_fpu_post_norm_intfloat_conv
443
 

powered by: WebSVN 2.1.0

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