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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_fpu_intfloat_conv.v] - Blame information for rev 588

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 258 julius
/////////////////////////////////////////////////////////////////////
2
////                                                             ////
3
////  or1200_fpu_intfloat_conv                                   ////
4
////  Only conversion between 32-bit integer and single          ////
5
////  precision floating point format                            ////
6
////                                                             ////
7
////  Author: Rudolf Usselmann                                   ////
8
////          rudi@asics.ws                                      ////
9
////                                                             ////
10
//// Modified by Julius Baxter, July, 2010                       ////
11
////             julius.baxter@orsoc.se                          ////
12
////                                                             ////
13
//// TODO: Fix bug where 1.0f in round up goes to integer 2      ////
14
////                                                             ////
15
/////////////////////////////////////////////////////////////////////
16
////                                                             ////
17
//// Copyright (C) 2000 Rudolf Usselmann                         ////
18
////                    rudi@asics.ws                            ////
19
////                                                             ////
20
//// This source file may be used and distributed without        ////
21
//// restriction provided that this copyright statement is not   ////
22
//// removed from the file and that any derivative work contains ////
23
//// the original copyright notice and the associated disclaimer.////
24
////                                                             ////
25
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
26
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
27
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
28
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
29
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
30
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
31
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
32
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
33
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
34
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
35
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
36
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
37
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
38
////                                                             ////
39
/////////////////////////////////////////////////////////////////////
40
 
41
`timescale 1ns / 100ps
42
 
43
/*
44
 
45
 FPU Operations (fpu_op):
46
 ========================
47
 
48
 
49
 1 =
50
 2 =
51
 3 =
52
 4 = int to float
53
 5 = float to int
54
 6 =
55
 7 =
56
 
57
 Rounding Modes (rmode):
58
 =======================
59
 
60
 
61
 1 = round_to_zero
62
 2 = round_up
63
 3 = round_down
64
 
65
 */
66
 
67
 
68
module or1200_fpu_intfloat_conv
69
  (
70
    clk, rmode, fpu_op, opa, out, snan, ine, inv,
71
    overflow, underflow, zero
72
    );
73
   input                clk;
74
   input [1:0]           rmode;
75
   input [2:0]           fpu_op;
76
   input [31:0]  opa;
77
   output [31:0]         out;
78
   output               snan;
79
   output               ine;
80
   output               inv;
81
   output               overflow;
82
   output               underflow;
83
   output               zero;
84
 
85
 
86
   parameter    INF  = 31'h7f800000,
87
                  QNAN = 31'h7fc00001,
88
                  SNAN = 31'h7f800001;
89
 
90
   ////////////////////////////////////////////////////////////////////////
91
   //
92
   // Local Wires
93
   //
94
   reg                  zero;
95
   reg [31:0]            opa_r;  // Input operand registers
96
   reg [31:0]            out;            // Output register
97
   reg                  div_by_zero;    // Divide by zero output register
98
   wire [7:0]            exp_fasu;       // Exponent output from EQU block
99
   reg [7:0]             exp_r;          // Exponent output (registerd)
100
   wire                 co;             // carry output
101
   wire [30:0]           out_d;          // Intermediate final result output
102
   wire                 overflow_d, underflow_d;// Overflow/Underflow
103
   reg                  inf, snan, qnan;// Output Registers for INF, S/QNAN
104
   reg                  ine;            // Output Registers for INE
105
   reg [1:0]             rmode_r1, rmode_r2,// Pipeline registers for round mode
106
                        rmode_r3;
107
   reg [2:0]             fpu_op_r1, fpu_op_r2,// Pipeline registers for fp 
108
                                             // operation
109
                        fpu_op_r3;
110
 
111
   ////////////////////////////////////////////////////////////////////////
112
     //
113
   // Input Registers
114
   //
115
 
116
   always @(posedge clk)
117
     opa_r <=  opa;
118
 
119
 
120
   always @(posedge clk)
121
     rmode_r1 <=  rmode;
122
 
123
   always @(posedge clk)
124
     rmode_r2 <=  rmode_r1;
125
 
126
   always @(posedge clk)
127
     rmode_r3 <=  rmode_r2;
128
 
129
   always @(posedge clk)
130
     fpu_op_r1 <=  fpu_op;
131
 
132
   always @(posedge clk)
133
     fpu_op_r2 <=  fpu_op_r1;
134
 
135
   always @(posedge clk)
136
     fpu_op_r3 <=  fpu_op_r2;
137
 
138
   ////////////////////////////////////////////////////////////////////////
139
   //
140
   // Exceptions block
141
   //
142
   wire                 inf_d, ind_d, qnan_d, snan_d, opa_nan;
143
   wire                 opa_00;
144
   wire                 opa_inf;
145
   wire                 opa_dn;
146
 
147
   or1200_fpu_intfloat_conv_except u0
148
     (  .clk(clk),
149
        .opa(opa_r),
150
        .opb(),
151
        .inf(inf_d),
152
        .ind(ind_d),
153
        .qnan(qnan_d),
154
        .snan(snan_d),
155
        .opa_nan(opa_nan),
156
        .opb_nan(),
157
        .opa_00(opa_00),
158
        .opb_00(),
159
        .opa_inf(opa_inf),
160
        .opb_inf(),
161
        .opa_dn(opa_dn),
162
        .opb_dn()
163
        );
164
 
165
   ////////////////////////////////////////////////////////////////////////
166
   //
167
   // Pre-Normalize block
168
   // - Adjusts the numbers to equal exponents and sorts them
169
   // - determine result sign
170
   // - determine actual operation to perform (add or sub)
171
   //
172
 
173
   wire                 nan_sign_d, result_zero_sign_d;
174
   reg                  sign_fasu_r;
175
   wire [1:0]            exp_ovf;
176
   reg [1:0]             exp_ovf_r;
177
 
178
   // This is all we need from post-norm module for int-float conversion
179
   reg                  opa_sign_r;
180
   always @(posedge clk)
181
     opa_sign_r <= opa_r[31];
182
 
183
   always @(posedge clk)
184
     sign_fasu_r <=  opa_sign_r; //sign_fasu;
185
 
186
 
187
   ////////////////////////////////////////////////////////////////////////
188
   //
189
   // Normalize Result
190
   //
191
   wire                 ine_d;
192
   wire                 inv_d;
193
   wire                 sign_d;
194
   reg                  sign;
195
   reg [30:0]            opa_r1;
196
   reg [47:0]            fract_i2f;
197
   reg                  opas_r1, opas_r2;
198
   wire                 f2i_out_sign;
199
   wire [47:0]           fract_denorm;
200
 
201
   always @(posedge clk)  // Exponent must be once cycle delayed
202
     case(fpu_op_r2)
203
       //4:     exp_r <=  0;
204
       5:       exp_r <=  opa_r1[30:23];
205
       default: exp_r <=  0;
206
     endcase
207
 
208
   always @(posedge clk)
209
     opa_r1 <=  opa_r[30:0];
210
 
211
   always @(posedge clk)
212
     fract_i2f <=  (fpu_op_r2==5) ?
213
                   (sign_d ?  1-{24'h00, (|opa_r1[30:23]), opa_r1[22:0]}-1 :
214
                    {24'h0, (|opa_r1[30:23]), opa_r1[22:0]})
215
       : (sign_d ? 1 - {opa_r1, 17'h01} : {opa_r1, 17'h0});
216
 
217
   assign fract_denorm = fract_i2f;
218
 
219
   always @(posedge clk)
220
     opas_r1 <=  opa_r[31];
221
 
222
   always @(posedge clk)
223
     opas_r2 <=  opas_r1;
224
 
225
   assign sign_d = opa_sign_r; //sign_fasu;
226
 
227
   always @(posedge clk)
228
     sign <=  (rmode_r2==2'h3) ? !sign_d : sign_d;
229
 
230
 
231
   // Special case of largest negative integer we can convert to - usually
232
   // gets picked up as invalid, but really it's not, so deal with it as a
233
   // special case.
234
   wire                 f2i_special_case_no_inv;
235
   assign f2i_special_case_no_inv = (opa == 32'hcf000000);
236
 
237
 
238
   or1200_fpu_post_norm_intfloat_conv u4
239
     (
240
      .clk(clk),                        // System Clock
241
      .fpu_op(fpu_op_r3),               // Floating Point Operation
242
      .opas(opas_r2),                   // OPA Sign
243
      .sign(sign),                      // Sign of the result
244
      .rmode(rmode_r3),         // Rounding mode
245
      .fract_in(fract_denorm),  // Fraction Input
246
 
247
      .exp_in(exp_r),                   // Exponent Input
248
      .opa_dn(opa_dn),          // Operand A Denormalized
249
      .opa_nan(opa_nan),
250
      .opa_inf(opa_inf),
251
 
252
      .opb_dn(),                // Operand B Denormalized
253
      .out(out_d),              // Normalized output (un-registered)
254
      .ine(ine_d),              // Result Inexact output (un-registered)
255
      .inv(inv_d),            // Invalid input for f2i operation
256
      .overflow(overflow_d),    // Overflow output (un-registered)
257
      .underflow(underflow_d),// Underflow output (un-registered)
258
      .f2i_out_sign(f2i_out_sign)       // F2I Output Sign
259
      );
260
 
261
   ////////////////////////////////////////////////////////////////////////
262
     //
263
   // FPU Outputs
264
   //
265
   reg                  fasu_op_r1, fasu_op_r2;
266
   wire [30:0]           out_fixed;
267
   wire                 output_zero_fasu;
268
   wire                 overflow_fasu;
269
   wire                 out_d_00;
270
   wire                 ine_fasu;
271
   wire                 underflow_fasu;
272
 
273
 
274
   /*
275
    always @(posedge clk)
276
    fasu_op_r1 <=  fasu_op;
277
 
278
    always @(posedge clk)
279
    fasu_op_r2 <=  fasu_op_r1;
280
    */
281
   // Force pre-set values for non numerical output
282
 
283
   assign out_fixed = ( (qnan_d | snan_d) |
284
                        (ind_d /*& !fasu_op_r2*/))  ? QNAN : INF;
285
 
286
   always @(posedge clk)
287
     out[30:0] <=  /*((inf_d & (fpu_op_r3!=3'b101)) | snan_d | qnan_d)
288
                    & fpu_op_r3!=3'b100 ? out_fixed :*/ out_d;
289
 
290
   assign out_d_00 = !(|out_d);
291
 
292
 
293
   always @(posedge clk)
294
     out[31] <= (fpu_op_r3==3'b101) ?
295
                f2i_out_sign : sign_fasu_r;
296
 
297
 
298
 
299
   // Exception Outputs
300
   assign ine_fasu = (ine_d | overflow_d | underflow_d) &
301
                     !(snan_d | qnan_d | inf_d);
302
 
303
   always @(posedge  clk)
304
     ine <=      fpu_op_r3[2] ? ine_d : ine_fasu;
305
 
306
   assign overflow = overflow_d & !(snan_d | qnan_d | inf_d);
307
   assign underflow = underflow_d & !(inf_d | snan_d | qnan_d);
308
 
309
   always @(posedge clk)
310
     snan <=  snan_d & (fpu_op_r3==3'b101);  // Only signal sNaN when ftoi
311
 
312
   // Status Outputs   
313
   assign output_zero_fasu = out_d_00 & !(inf_d | snan_d | qnan_d);
314
 
315
   always @(posedge clk)
316
     zero <=    fpu_op_r3==3'b101 ? out_d_00 & !(snan_d | qnan_d) :
317
             output_zero_fasu ;
318
   assign inv = inv_d & !f2i_special_case_no_inv;
319
 
320
endmodule // or1200_fpu_intfloat_conv
321
 
322
 
323
module or1200_fpu_intfloat_conv_except
324
  (
325
        clk, opa, opb, inf, ind, qnan, snan, opa_nan, opb_nan,
326
        opa_00, opb_00, opa_inf, opb_inf, opa_dn, opb_dn
327
        );
328
   input                clk;
329
   input [31:0]  opa, opb;
330
   output               inf, ind, qnan, snan, opa_nan, opb_nan;
331
   output               opa_00, opb_00;
332
   output               opa_inf, opb_inf;
333
   output               opa_dn;
334
   output               opb_dn;
335
 
336
   ////////////////////////////////////////////////////////////////////////
337
   //
338
   // Local Wires and registers
339
   //
340
 
341
   wire [7:0]            expa, expb;             // alias to opX exponent
342
   wire [22:0]           fracta, fractb;         // alias to opX fraction
343
   reg                  expa_ff, infa_f_r, qnan_r_a, snan_r_a;
344
   reg                  expb_ff, infb_f_r, qnan_r_b, snan_r_b;
345
   reg                  inf, ind, qnan, snan;   // Output registers
346
   reg                  opa_nan, opb_nan;
347
   reg                  expa_00, expb_00, fracta_00, fractb_00;
348
   reg                  opa_00, opb_00;
349
   reg                  opa_inf, opb_inf;
350
   reg                  opa_dn, opb_dn;
351
 
352
   ////////////////////////////////////////////////////////////////////////
353
   //
354
   // Aliases
355
   //
356
 
357
   assign   expa = opa[30:23];
358
   assign   expb = opb[30:23];
359
   assign fracta = opa[22:0];
360
   assign fractb = opb[22:0];
361
 
362
   ////////////////////////////////////////////////////////////////////////
363
   //
364
   // Determine if any of the input operators is a INF or NAN or any other 
365
   // special number
366
   //
367
 
368
   always @(posedge clk)
369
     expa_ff <=  &expa;
370
 
371
   always @(posedge clk)
372
     expb_ff <=  &expb;
373
 
374
   always @(posedge clk)
375
     infa_f_r <=  !(|fracta);
376
 
377
   always @(posedge clk)
378
     infb_f_r <=  !(|fractb);
379
 
380
   always @(posedge clk)
381
     qnan_r_a <=   fracta[22];
382
 
383
   always @(posedge clk)
384
     snan_r_a <=  !fracta[22] & |fracta[21:0];
385
 
386
   always @(posedge clk)
387
     qnan_r_b <=   fractb[22];
388
 
389
   always @(posedge clk)
390
     snan_r_b <=  !fractb[22]; // & |fractb[21:0];
391
 
392
   always @(posedge clk)
393
     ind  <=  (expa_ff & infa_f_r); // & (expb_ff & infb_f_r);
394
 
395
   always @(posedge clk)
396
     inf  <=  (expa_ff & infa_f_r); // | (expb_ff & infb_f_r);
397
 
398
   always @(posedge clk)
399
     qnan <=  (expa_ff & qnan_r_a); // | (expb_ff & qnan_r_b);
400
 
401
   always @(posedge clk)
402
     snan <=  (expa_ff & snan_r_a); // | (expb_ff & snan_r_b);
403
 
404
   always @(posedge clk)
405
     opa_nan <=  &expa & (|fracta[22:0]);
406
 
407
   always @(posedge clk)
408
     opb_nan <=  &expb & (|fractb[22:0]);
409
 
410
   always @(posedge clk)
411
     opa_inf <=  (expa_ff & infa_f_r);
412
 
413
   always @(posedge clk)
414
     opb_inf <=  (expb_ff & infb_f_r);
415
 
416
   always @(posedge clk)
417
     expa_00 <=  !(|expa);
418
 
419
   always @(posedge clk)
420
     expb_00 <=  !(|expb);
421
 
422
   always @(posedge clk)
423
     fracta_00 <=  !(|fracta);
424
 
425
   always @(posedge clk)
426
     fractb_00 <=  !(|fractb);
427
 
428
   always @(posedge clk)
429
     opa_00 <=  expa_00 & fracta_00;
430
 
431
   always @(posedge clk)
432
     opb_00 <=  expb_00 & fractb_00;
433
 
434
   always @(posedge clk)
435
     opa_dn <=  expa_00;
436
 
437
   always @(posedge clk)
438
     opb_dn <=  expb_00;
439
 
440
endmodule // or1200_fpu_intfloat_conv_except
441
 
442
 

powered by: WebSVN 2.1.0

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