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

Subversion Repositories fpu_double

[/] [fpu_double/] [trunk/] [fpu_exceptions.vhd] - Blame information for rev 13

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 davidklun
---------------------------------------------------------------------
2
----                                                             ----
3 12 davidklun
----                                                         ----
4 2 davidklun
----  Floating Point Unit (Double precision)                     ----
5
----                                                             ----
6
----  Author: David Lundgren                                     ----
7
----          davidklun@gmail.com                                ----
8
----                                                             ----
9
---------------------------------------------------------------------
10
----                                                             ----
11
---- Copyright (C) 2009 David Lundgren                           ----
12
----                  davidklun@gmail.com                        ----
13
----                                                             ----
14
---- This source file may be used and distributed without        ----
15
---- restriction provided that this copyright statement is not   ----
16
---- removed from the file and that any derivative work contains ----
17
---- the original copyright notice and the associated disclaimer.----
18
----                                                             ----
19 13 davidklun
----     THIS SOFTWARE IS PROVIDED `AS IS' AND WITHOUT ANY     ----
20 2 davidklun
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ----
21
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ----
22
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ----
23
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ----
24
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ----
25
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ----
26
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ----
27
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ----
28
---- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ----
29
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ----
30
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ----
31
---- POSSIBILITY OF SUCH DAMAGE.                                 ----
32
----                                                             ----
33
---------------------------------------------------------------------
34
 
35
        LIBRARY ieee;
36
        USE ieee.std_logic_1164.all;
37
        USE ieee.std_logic_arith.all;
38
        use ieee.std_logic_unsigned.all;
39
        use ieee.std_logic_misc.all;
40
 
41
        ENTITY fpu_exceptions IS
42
 
43
   PORT(
44
      clk, rst, enable : IN     std_logic;
45
      rmode : IN     std_logic_vector (1 DOWNTO 0);
46
      opa, opb, in_except : IN     std_logic_vector (63 DOWNTO 0);
47
      exponent_in : IN     std_logic_vector (11 DOWNTO 0);
48
      mantissa_in : IN     std_logic_vector (1 DOWNTO 0);
49
      fpu_op : IN     std_logic_vector (2 DOWNTO 0);
50
      out_fp : OUT    std_logic_vector (63 DOWNTO 0);
51
      ex_enable, underflow, overflow, inexact : OUT    std_logic;
52
      exception, invalid : OUT    std_logic
53
   );
54
 
55
        END fpu_exceptions;
56
 
57
        architecture rtl of fpu_exceptions is
58
 
59
        signal  in_et_zero : std_logic;
60
        signal  opa_et_zero : std_logic;
61
        signal  opb_et_zero : std_logic;
62
        signal  add : std_logic;
63
        signal  subtract : std_logic;
64
        signal  multiply : std_logic;
65
        signal  divide : std_logic;
66
        signal  opa_QNaN : std_logic;
67
        signal  opb_QNaN : std_logic;
68
        signal  opa_SNaN : std_logic;
69
        signal  opb_SNaN : std_logic;
70
        signal  opa_pos_inf : std_logic;
71
        signal  opb_pos_inf : std_logic;
72
        signal  opa_neg_inf : std_logic;
73
        signal  opb_neg_inf : std_logic;
74
        signal  opa_inf : std_logic;
75
        signal  opb_inf : std_logic;
76
        signal  NaN_input : std_logic;
77
        signal  SNaN_input : std_logic;
78
        signal  a_NaN : std_logic;
79
        signal  div_by_0 : std_logic;
80
        signal  div_0_by_0 : std_logic;
81
        signal  div_inf_by_inf : std_logic;
82
        signal  div_by_inf : std_logic;
83
        signal  mul_0_by_inf : std_logic;
84
        signal  mul_inf : std_logic;
85
        signal  div_inf : std_logic;
86
        signal  add_inf : std_logic;
87
        signal  sub_inf : std_logic;
88
        signal  addsub_inf_invalid : std_logic;
89
        signal  addsub_inf : std_logic;
90
        signal  out_inf_trigger : std_logic;
91
        signal  out_pos_inf : std_logic;
92
        signal  out_neg_inf : std_logic;
93
        signal  round_nearest : std_logic;
94
        signal  round_to_zero : std_logic;
95
        signal  round_to_pos_inf : std_logic;
96
        signal  round_to_neg_inf : std_logic;
97
        signal  inf_round_down_trigger : std_logic;
98
        signal  mul_uf : std_logic;
99
        signal  div_uf : std_logic;
100
        signal  underflow_trigger : std_logic;
101
        signal  invalid_trigger : std_logic;
102
        signal  overflow_trigger : std_logic;
103
        signal  inexact_trigger : std_logic;
104
        signal  except_trigger : std_logic;
105
        signal  enable_trigger : std_logic;
106
        signal  NaN_out_trigger : std_logic;
107
        signal  SNaN_trigger : std_logic;
108
 
109
 
110
        signal  exp_2047 : std_logic_vector(10 downto 0);
111
        signal  exp_2046 : std_logic_vector(10 downto 0);
112
        signal  NaN_output_0 : std_logic_vector(62 downto 0);
113
        signal  NaN_output : std_logic_vector(62 downto 0);
114
        signal  mantissa_max : std_logic_vector(51 downto 0);
115
        signal  inf_round_down : std_logic_vector(62 downto 0);
116
        signal  out_inf : std_logic_vector(62 downto 0);
117
        signal  out_0 : std_logic_vector(63 downto 0);
118
        signal  out_1 : std_logic_vector(63 downto 0);
119
        signal  out_2 : std_logic_vector(63 downto 0);
120
 
121
        begin
122
 
123
                exp_2047 <= "11111111111";
124
                exp_2046 <= "11111111110";
125
                mantissa_max <= "1111111111111111111111111111111111111111111111111111";
126
 
127
        process
128
        begin
129
        wait until clk'event and clk = '1';
130
                if (rst = '1') then
131
                        in_et_zero <=    '0';
132
                        opa_et_zero <=   '0';
133
                        opb_et_zero <=   '0';
134
                        add     <=      '0';
135
                        subtract <= '0';
136
                        multiply <= '0';
137
                        divide  <=      '0';
138
                        opa_QNaN <= '0';
139
                        opb_QNaN <= '0';
140
                        opa_SNaN <= '0';
141
                        opb_SNaN <= '0';
142
                        opa_pos_inf <= '0';
143
                        opb_pos_inf <= '0';
144
                        opa_neg_inf <= '0';
145
                        opb_neg_inf <= '0';
146
                        opa_inf <= '0';
147
                        opb_inf <= '0';
148
                        NaN_input <= '0';
149
                        SNaN_input <= '0';
150
                        a_NaN <= '0';
151
                        div_by_0 <= '0';
152
                        div_0_by_0 <= '0';
153
                        div_inf_by_inf <= '0';
154
                        div_by_inf <= '0';
155
                        mul_0_by_inf <= '0';
156
                        mul_inf <= '0';
157
                        div_inf <= '0';
158
                        add_inf <= '0';
159
                        sub_inf <= '0';
160
                        addsub_inf_invalid <= '0';
161
                        addsub_inf <= '0';
162
                        out_inf_trigger <= '0';
163
                        out_pos_inf <= '0';
164
                        out_neg_inf <= '0';
165
                        round_nearest <= '0';
166
                        round_to_zero <= '0';
167
                        round_to_pos_inf <= '0';
168
                        round_to_neg_inf <= '0';
169
                        inf_round_down_trigger <= '0';
170
                        mul_uf <= '0';
171
                        div_uf <= '0';
172
                        underflow_trigger <= '0';
173
                        invalid_trigger <= '0';
174
                        overflow_trigger <= '0';
175
                        inexact_trigger <= '0';
176
                        except_trigger <= '0';
177
                        enable_trigger <= '0';
178
                        NaN_out_trigger <= '0';
179
                        SNaN_trigger <= '0';
180
                        NaN_output_0 <= (others =>'0');
181
                        NaN_output <= (others =>'0');
182
                        inf_round_down <= (others =>'0');
183
                        out_inf <= (others =>'0');
184
                        out_0 <= (others =>'0');
185
                        out_1 <= (others =>'0');
186
                        out_2 <= (others =>'0');
187
                elsif (enable = '1') then
188
                        if or_reduce(in_except(62 downto 0)) = '0' then
189
                                in_et_zero <= '1';
190
                        else
191
                                in_et_zero <= '0';
192
                        end if;
193
                        if or_reduce(opa(62 downto 0)) = '0' then
194
                                opa_et_zero <= '1';
195
                        else
196
                                opa_et_zero <= '0';
197
                        end if;
198
                        if or_reduce(opb(62 downto 0)) = '0' then
199
                                opb_et_zero <= '1';
200
                        else
201
                                opb_et_zero <= '0';
202
                        end if;
203
                        if fpu_op = "000" then
204
                                add <= '1';
205
                        else
206
                                add <= '0';
207
                        end if;
208
                        if fpu_op = "001" then
209
                                subtract <= '1';
210
                        else
211
                                subtract <= '0';
212
                        end if;
213
                        if fpu_op = "010" then
214
                                multiply <= '1';
215
                        else
216
                                multiply <= '0';
217
                        end if;
218
                        if fpu_op = "011" then
219
                                divide <= '1';
220
                        else
221
                                divide <= '0';
222
                        end if;
223
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '1' and
224
                                        opa(51) = '1' then
225
                                opa_QNaN <= '1';
226
                        else
227
                                opa_QNaN <= '0';
228
                        end if;
229
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '1' and
230
                                        opb(51) = '1' then
231
                                opb_QNaN <= '1';
232
                        else
233
                                opb_QNaN <= '0';
234
                        end if;
235
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '1' and
236
                                        opa(51) = '0' then
237
                                opa_SNaN <= '1';
238
                        else
239
                                opa_SNaN <= '0';
240
                        end if;
241
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '1' and
242
                                        opb(51) = '0' then
243
                                opb_SNaN <= '1';
244
                        else
245
                                opb_SNaN <= '0';
246
                        end if;
247
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' and
248
                                        opa(63) = '0' then
249
                                opa_pos_inf <= '1';
250
                        else
251
                                opa_pos_inf <= '0';
252
                        end if;
253
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' and
254
                                        opb(63) = '0' then
255
                                opb_pos_inf <= '1';
256
                        else
257
                                opb_pos_inf <= '0';
258
                        end if;
259
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' and
260
                                        opa(63) = '1' then
261
                                opa_neg_inf <= '1';
262
                        else
263
                                opa_neg_inf <= '0';
264
                        end if;
265
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' and
266
                                        opb(63) = '1' then
267
                                opb_neg_inf <= '1';
268
                        else
269
                                opb_neg_inf <= '0';
270
                        end if;
271
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' then
272
                                opa_inf <= '1';
273
                        else
274
                                opa_inf <= '0';
275
                        end if;
276
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' then
277
                                opb_inf <= '1';
278
                        else
279
                                opb_inf <= '0';
280
                        end if;
281
                        if opa_QNaN = '1' or opb_QNaN = '1' or opa_SNaN = '1' or opb_SNaN = '1' then
282
                                NaN_input <= '1';
283
                        else
284
                                NaN_input <= '0';
285
                        end if;
286
                        if opa_SNaN = '1' or opb_SNaN = '1' then
287
                                SNaN_input <= '1';
288
                        else
289
                                SNaN_input <= '0';
290
                        end if;
291
                        if opa_SNaN = '1' or opa_QNaN = '1' then
292
                                a_NaN <= '1';
293
                        else
294
                                a_NaN <= '0';
295
                        end if;
296
                        if divide = '1' and opb_et_zero = '1' and opa_et_zero = '0' then
297
                                div_by_0 <= '1';
298
                        else
299
                                div_by_0 <= '0';
300
                        end if;
301
                        if divide = '1' and opb_et_zero = '1' and opa_et_zero = '1' then
302
                                div_0_by_0 <= '1';
303
                        else
304
                                div_0_by_0 <= '0';
305
                        end if;
306
                        if divide = '1' and opa_inf = '1' and opb_inf = '1' then
307
                                div_inf_by_inf <= '1';
308
                        else
309
                                div_inf_by_inf <= '0';
310
                        end if;
311
                        if divide = '1' and opa_inf = '0' and opb_inf = '1' then
312
                                div_by_inf <= '1';
313
                        else
314
                                div_by_inf <= '0';
315
                        end if;
316
                        if multiply = '1' and ((opa_inf = '1' and opb_et_zero = '1') or
317
                         (opa_et_zero = '1' and opb_inf = '1')) then
318
                                mul_0_by_inf <= '1';
319
                        else
320
                                mul_0_by_inf <= '0';
321
                        end if;
322
                        if multiply = '1' and (opa_inf = '1' or opb_inf = '1') and
323
                          mul_0_by_inf = '0' then
324
                                mul_inf <= '1';
325
                        else
326
                                mul_inf <= '0';
327
                        end if;
328
                        if divide = '1' and opa_inf = '1' and opb_inf = '0' then
329
                                div_inf <= '1';
330
                        else
331
                                div_inf <= '0';
332
                        end if;
333
                        if add = '1' and (opa_inf = '1' or opb_inf = '1') then
334
                                add_inf <= '1';
335
                        else
336
                                add_inf <= '0';
337
                        end if;
338
                        if subtract = '1' and (opa_inf = '1' or opb_inf = '1') then
339
                                sub_inf <= '1';
340
                        else
341
                                sub_inf <= '0';
342
                        end if;
343
                        if (add = '1' and opa_pos_inf = '1' and opb_neg_inf = '1') or
344
                          (add = '1' and opa_neg_inf = '1' and opb_pos_inf = '1') or
345
                          (subtract = '1' and opa_pos_inf = '1' and opb_pos_inf = '1') or
346
                          (subtract = '1' and opa_neg_inf = '1' and opb_neg_inf = '1') then
347
                                addsub_inf_invalid <= '1';
348
                        else
349
                                addsub_inf_invalid <= '0';
350
                        end if;
351
                        if (add_inf = '1' or sub_inf = '1') and addsub_inf_invalid = '0' then
352
                                addsub_inf <= '1';
353
                        else
354
                                addsub_inf <= '0';
355
                        end if;
356
                        if addsub_inf = '1' or mul_inf = '1' or div_inf = '1' or div_by_0 = '1'
357
                          or (exponent_in > "011111111110") then -- 2046
358
                                out_inf_trigger <= '1';
359
                        else
360
                                out_inf_trigger <= '0';
361
                        end if;
362
                        if out_inf_trigger = '1' and in_except(63) = '0' then
363
                                out_pos_inf <= '1';
364
                        else
365
                                out_pos_inf <= '0';
366
                        end if;
367
                        if out_inf_trigger = '1' and in_except(63) = '1' then
368
                                out_neg_inf <= '1';
369
                        else
370
                                out_neg_inf <= '0';
371
                        end if;
372
                        if rmode = "00" then
373
                                round_nearest <= '1';
374
                        else
375
                                round_nearest <= '0';
376
                        end if;
377
                        if rmode = "01" then
378
                                round_to_zero <= '1';
379
                        else
380
                                round_to_zero <= '0';
381
                        end if;
382
                        if rmode = "10" then
383
                                round_to_pos_inf <= '1';
384
                        else
385
                                round_to_pos_inf <= '0';
386
                        end if;
387
                        if rmode = "11" then
388
                                round_to_neg_inf <= '1';
389
                        else
390
                                round_to_neg_inf <= '0';
391
                        end if;
392
                        if (out_pos_inf = '1' and round_to_neg_inf = '1') or
393
                           (out_neg_inf = '1' and round_to_pos_inf = '1') or
394
                           (out_inf_trigger = '1' and round_to_zero = '1') then
395
                                inf_round_down_trigger <= '1';
396
                        else
397
                                inf_round_down_trigger <= '0';
398
                        end if;
399
                        if multiply = '1' and opa_et_zero = '0' and opb_et_zero = '0' and
400
                          in_et_zero = '1' then
401
                                mul_uf <= '1';
402
                        else
403
                                mul_uf <= '0';
404
                        end if;
405
                        if divide = '1' and opa_et_zero = '0' and in_et_zero = '1' then
406
                                div_uf <= '1';
407
                        else
408
                                div_uf <= '0';
409
                        end if;
410
                        if div_by_inf = '1' or mul_uf = '1' or div_uf = '1' then
411
                                underflow_trigger <= '1';
412
                        else
413
                                underflow_trigger <= '0';
414
                        end if;
415
                        if SNaN_input = '1' or addsub_inf_invalid = '1' or mul_0_by_inf = '1' or
416
                                div_0_by_0 = '1' or div_inf_by_inf = '1' then
417
                                invalid_trigger <= '1';
418
                        else
419
                                invalid_trigger <= '0';
420 10 davidklun
                        end if;
421 2 davidklun
                        if out_inf_trigger = '1' and NaN_input = '0' then
422
                                overflow_trigger <= '1';
423
                        else
424
                                overflow_trigger <= '0';
425
                        end if;
426
                        if (or_reduce(mantissa_in(1 downto 0)) = '1' or out_inf_trigger = '1' or
427
                          underflow_trigger = '1') and NaN_input = '0' then
428
                                inexact_trigger <= '1';
429
                        else
430
                                inexact_trigger <= '0';
431
                        end if;
432
                        if (invalid_trigger = '1' or overflow_trigger = '1' or
433
                          underflow_trigger = '1' or inexact_trigger = '1') then
434
                                except_trigger <= '1';
435
                        else
436
                                except_trigger <= '0';
437
                        end if;
438
                        if (except_trigger = '1' or out_inf_trigger = '1' or
439
                          NaN_input = '1') then
440
                                enable_trigger <= '1';
441
                        else
442
                                enable_trigger <= '0';
443
                        end if;
444
                        if (NaN_input = '1' or invalid_trigger = '1') then
445
                                NaN_out_trigger <= '1';
446
                        else
447
                                NaN_out_trigger <= '0';
448
                        end if;
449
                        if (invalid_trigger = '1' and SNaN_input = '0') then
450
                                SNaN_trigger <= '1';
451
                        else
452
                                SNaN_trigger <= '0';
453
                        end if;
454
                        if a_NaN = '1' then
455
                                NaN_output_0 <= exp_2047 & '1' & opa(50 downto 0);
456
                        else
457
                                NaN_output_0 <= exp_2047 & '1' & opb(50 downto 0);
458
                        end if;
459
                        if SNaN_trigger = '1' then
460
                                NaN_output <= exp_2047 & "01" & opa(49 downto 0);
461
                        else
462
                                NaN_output <= NaN_output_0;
463
                        end if;
464
                        inf_round_down <= exp_2046 & mantissa_max;
465
                        if inf_round_down_trigger = '1' then
466
                                out_inf <= inf_round_down;
467
                        else
468
                                out_inf <=  exp_2047 & "0000000000000000000000000000000000000000000000000000";
469
                        end if;
470
                        if underflow_trigger = '1' then
471
                                out_0 <= in_except(63) & "000000000000000000000000000000000000000000000000000000000000000";
472
                        else
473
                                out_0 <=  in_except;
474
                        end if;
475
                        if out_inf_trigger = '1' then
476
                                out_1 <= in_except(63) & out_inf;
477
                        else
478
                                out_1 <= out_0;
479
                        end if;
480
                        if NaN_out_trigger = '1' then
481
                                out_2 <= in_except(63) & NaN_output;
482
                        else
483
                                out_2 <= out_1;
484
                        end if;
485
                end if;
486
        end process;
487
 
488
 
489
        process
490
        begin
491
        wait until clk'event and clk = '1';
492
                if (rst = '1') then
493
                        ex_enable <= '0';
494
                        underflow <= '0';
495
                        overflow <= '0';
496
                        inexact <= '0';
497
                        exception <= '0';
498
                        invalid <= '0';
499
                        out_fp <= (others =>'0');
500
                elsif (enable = '1') then
501
                        ex_enable <= enable_trigger;
502
                        underflow <= underflow_trigger;
503
                        overflow <= overflow_trigger;
504
                        inexact <= inexact_trigger;
505
                        exception <= except_trigger;
506
                        invalid <= invalid_trigger;
507
                        out_fp <= out_2;
508
                end if;
509
        end process;
510
        end rtl;

powered by: WebSVN 2.1.0

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