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 10

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

Line No. Rev Author Line
1 2 davidklun
---------------------------------------------------------------------
2
----                                                             ----
3
----  FPU                                                        ----
4
----  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
----     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ----
20
---- 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
 
58
        architecture rtl of fpu_exceptions is
59
 
60
        signal  in_et_zero : std_logic;
61
        signal  opa_et_zero : std_logic;
62
        signal  opb_et_zero : std_logic;
63
        signal  add : std_logic;
64
        signal  subtract : std_logic;
65
        signal  multiply : std_logic;
66
        signal  divide : std_logic;
67
        signal  opa_QNaN : std_logic;
68
        signal  opb_QNaN : std_logic;
69
        signal  opa_SNaN : std_logic;
70
        signal  opb_SNaN : std_logic;
71
        signal  opa_pos_inf : std_logic;
72
        signal  opb_pos_inf : std_logic;
73
        signal  opa_neg_inf : std_logic;
74
        signal  opb_neg_inf : std_logic;
75
        signal  opa_inf : std_logic;
76
        signal  opb_inf : std_logic;
77
        signal  NaN_input : std_logic;
78
        signal  SNaN_input : std_logic;
79
        signal  a_NaN : std_logic;
80
        signal  div_by_0 : std_logic;
81
        signal  div_0_by_0 : std_logic;
82
        signal  div_inf_by_inf : std_logic;
83
        signal  div_by_inf : std_logic;
84
        signal  mul_0_by_inf : std_logic;
85
        signal  mul_inf : std_logic;
86
        signal  div_inf : std_logic;
87
        signal  add_inf : std_logic;
88
        signal  sub_inf : std_logic;
89
        signal  addsub_inf_invalid : std_logic;
90
        signal  addsub_inf : std_logic;
91
        signal  out_inf_trigger : std_logic;
92
        signal  out_pos_inf : std_logic;
93
        signal  out_neg_inf : std_logic;
94
        signal  round_nearest : std_logic;
95
        signal  round_to_zero : std_logic;
96
        signal  round_to_pos_inf : std_logic;
97
        signal  round_to_neg_inf : std_logic;
98
        signal  inf_round_down_trigger : std_logic;
99
        signal  mul_uf : std_logic;
100
        signal  div_uf : std_logic;
101
        signal  underflow_trigger : std_logic;
102
        signal  invalid_trigger : std_logic;
103
        signal  overflow_trigger : std_logic;
104
        signal  inexact_trigger : std_logic;
105
        signal  except_trigger : std_logic;
106
        signal  enable_trigger : std_logic;
107
        signal  NaN_out_trigger : std_logic;
108
        signal  SNaN_trigger : std_logic;
109
 
110
 
111
        signal  exp_2047 : std_logic_vector(10 downto 0);
112
        signal  exp_2046 : std_logic_vector(10 downto 0);
113
        signal  NaN_output_0 : std_logic_vector(62 downto 0);
114
        signal  NaN_output : std_logic_vector(62 downto 0);
115
        signal  mantissa_max : std_logic_vector(51 downto 0);
116
        signal  inf_round_down : std_logic_vector(62 downto 0);
117
        signal  out_inf : std_logic_vector(62 downto 0);
118
        signal  out_0 : std_logic_vector(63 downto 0);
119
        signal  out_1 : std_logic_vector(63 downto 0);
120
        signal  out_2 : std_logic_vector(63 downto 0);
121
 
122
        begin
123
 
124
                exp_2047 <= "11111111111";
125
                exp_2046 <= "11111111110";
126
                mantissa_max <= "1111111111111111111111111111111111111111111111111111";
127
 
128
        process
129
        begin
130
        wait until clk'event and clk = '1';
131
                if (rst = '1') then
132
                        in_et_zero <=    '0';
133
                        opa_et_zero <=   '0';
134
                        opb_et_zero <=   '0';
135
                        add     <=      '0';
136
                        subtract <= '0';
137
                        multiply <= '0';
138
                        divide  <=      '0';
139
                        opa_QNaN <= '0';
140
                        opb_QNaN <= '0';
141
                        opa_SNaN <= '0';
142
                        opb_SNaN <= '0';
143
                        opa_pos_inf <= '0';
144
                        opb_pos_inf <= '0';
145
                        opa_neg_inf <= '0';
146
                        opb_neg_inf <= '0';
147
                        opa_inf <= '0';
148
                        opb_inf <= '0';
149
                        NaN_input <= '0';
150
                        SNaN_input <= '0';
151
                        a_NaN <= '0';
152
                        div_by_0 <= '0';
153
                        div_0_by_0 <= '0';
154
                        div_inf_by_inf <= '0';
155
                        div_by_inf <= '0';
156
                        mul_0_by_inf <= '0';
157
                        mul_inf <= '0';
158
                        div_inf <= '0';
159
                        add_inf <= '0';
160
                        sub_inf <= '0';
161
                        addsub_inf_invalid <= '0';
162
                        addsub_inf <= '0';
163
                        out_inf_trigger <= '0';
164
                        out_pos_inf <= '0';
165
                        out_neg_inf <= '0';
166
                        round_nearest <= '0';
167
                        round_to_zero <= '0';
168
                        round_to_pos_inf <= '0';
169
                        round_to_neg_inf <= '0';
170
                        inf_round_down_trigger <= '0';
171
                        mul_uf <= '0';
172
                        div_uf <= '0';
173
                        underflow_trigger <= '0';
174
                        invalid_trigger <= '0';
175
                        overflow_trigger <= '0';
176
                        inexact_trigger <= '0';
177
                        except_trigger <= '0';
178
                        enable_trigger <= '0';
179
                        NaN_out_trigger <= '0';
180
                        SNaN_trigger <= '0';
181
                        NaN_output_0 <= (others =>'0');
182
                        NaN_output <= (others =>'0');
183
                        inf_round_down <= (others =>'0');
184
                        out_inf <= (others =>'0');
185
                        out_0 <= (others =>'0');
186
                        out_1 <= (others =>'0');
187
                        out_2 <= (others =>'0');
188
                elsif (enable = '1') then
189
                        if or_reduce(in_except(62 downto 0)) = '0' then
190
                                in_et_zero <= '1';
191
                        else
192
                                in_et_zero <= '0';
193
                        end if;
194
                        if or_reduce(opa(62 downto 0)) = '0' then
195
                                opa_et_zero <= '1';
196
                        else
197
                                opa_et_zero <= '0';
198
                        end if;
199
                        if or_reduce(opb(62 downto 0)) = '0' then
200
                                opb_et_zero <= '1';
201
                        else
202
                                opb_et_zero <= '0';
203
                        end if;
204
                        if fpu_op = "000" then
205
                                add <= '1';
206
                        else
207
                                add <= '0';
208
                        end if;
209
                        if fpu_op = "001" then
210
                                subtract <= '1';
211
                        else
212
                                subtract <= '0';
213
                        end if;
214
                        if fpu_op = "010" then
215
                                multiply <= '1';
216
                        else
217
                                multiply <= '0';
218
                        end if;
219
                        if fpu_op = "011" then
220
                                divide <= '1';
221
                        else
222
                                divide <= '0';
223
                        end if;
224
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '1' and
225
                                        opa(51) = '1' then
226
                                opa_QNaN <= '1';
227
                        else
228
                                opa_QNaN <= '0';
229
                        end if;
230
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '1' and
231
                                        opb(51) = '1' then
232
                                opb_QNaN <= '1';
233
                        else
234
                                opb_QNaN <= '0';
235
                        end if;
236
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '1' and
237
                                        opa(51) = '0' then
238
                                opa_SNaN <= '1';
239
                        else
240
                                opa_SNaN <= '0';
241
                        end if;
242
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '1' and
243
                                        opb(51) = '0' then
244
                                opb_SNaN <= '1';
245
                        else
246
                                opb_SNaN <= '0';
247
                        end if;
248
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' and
249
                                        opa(63) = '0' then
250
                                opa_pos_inf <= '1';
251
                        else
252
                                opa_pos_inf <= '0';
253
                        end if;
254
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' and
255
                                        opb(63) = '0' then
256
                                opb_pos_inf <= '1';
257
                        else
258
                                opb_pos_inf <= '0';
259
                        end if;
260
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' and
261
                                        opa(63) = '1' then
262
                                opa_neg_inf <= '1';
263
                        else
264
                                opa_neg_inf <= '0';
265
                        end if;
266
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' and
267
                                        opb(63) = '1' then
268
                                opb_neg_inf <= '1';
269
                        else
270
                                opb_neg_inf <= '0';
271
                        end if;
272
                        if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' then
273
                                opa_inf <= '1';
274
                        else
275
                                opa_inf <= '0';
276
                        end if;
277
                        if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' then
278
                                opb_inf <= '1';
279
                        else
280
                                opb_inf <= '0';
281
                        end if;
282
                        if opa_QNaN = '1' or opb_QNaN = '1' or opa_SNaN = '1' or opb_SNaN = '1' then
283
                                NaN_input <= '1';
284
                        else
285
                                NaN_input <= '0';
286
                        end if;
287
                        if opa_SNaN = '1' or opb_SNaN = '1' then
288
                                SNaN_input <= '1';
289
                        else
290
                                SNaN_input <= '0';
291
                        end if;
292
                        if opa_SNaN = '1' or opa_QNaN = '1' then
293
                                a_NaN <= '1';
294
                        else
295
                                a_NaN <= '0';
296
                        end if;
297
                        if divide = '1' and opb_et_zero = '1' and opa_et_zero = '0' then
298
                                div_by_0 <= '1';
299
                        else
300
                                div_by_0 <= '0';
301
                        end if;
302
                        if divide = '1' and opb_et_zero = '1' and opa_et_zero = '1' then
303
                                div_0_by_0 <= '1';
304
                        else
305
                                div_0_by_0 <= '0';
306
                        end if;
307
                        if divide = '1' and opa_inf = '1' and opb_inf = '1' then
308
                                div_inf_by_inf <= '1';
309
                        else
310
                                div_inf_by_inf <= '0';
311
                        end if;
312
                        if divide = '1' and opa_inf = '0' and opb_inf = '1' then
313
                                div_by_inf <= '1';
314
                        else
315
                                div_by_inf <= '0';
316
                        end if;
317
                        if multiply = '1' and ((opa_inf = '1' and opb_et_zero = '1') or
318
                         (opa_et_zero = '1' and opb_inf = '1')) then
319
                                mul_0_by_inf <= '1';
320
                        else
321
                                mul_0_by_inf <= '0';
322
                        end if;
323
                        if multiply = '1' and (opa_inf = '1' or opb_inf = '1') and
324
                          mul_0_by_inf = '0' then
325
                                mul_inf <= '1';
326
                        else
327
                                mul_inf <= '0';
328
                        end if;
329
                        if divide = '1' and opa_inf = '1' and opb_inf = '0' then
330
                                div_inf <= '1';
331
                        else
332
                                div_inf <= '0';
333
                        end if;
334
                        if add = '1' and (opa_inf = '1' or opb_inf = '1') then
335
                                add_inf <= '1';
336
                        else
337
                                add_inf <= '0';
338
                        end if;
339
                        if subtract = '1' and (opa_inf = '1' or opb_inf = '1') then
340
                                sub_inf <= '1';
341
                        else
342
                                sub_inf <= '0';
343
                        end if;
344
                        if (add = '1' and opa_pos_inf = '1' and opb_neg_inf = '1') or
345
                          (add = '1' and opa_neg_inf = '1' and opb_pos_inf = '1') or
346
                          (subtract = '1' and opa_pos_inf = '1' and opb_pos_inf = '1') or
347
                          (subtract = '1' and opa_neg_inf = '1' and opb_neg_inf = '1') then
348
                                addsub_inf_invalid <= '1';
349
                        else
350
                                addsub_inf_invalid <= '0';
351
                        end if;
352
                        if (add_inf = '1' or sub_inf = '1') and addsub_inf_invalid = '0' then
353
                                addsub_inf <= '1';
354
                        else
355
                                addsub_inf <= '0';
356
                        end if;
357
                        if addsub_inf = '1' or mul_inf = '1' or div_inf = '1' or div_by_0 = '1'
358
                          or (exponent_in > "011111111110") then -- 2046
359
                                out_inf_trigger <= '1';
360
                        else
361
                                out_inf_trigger <= '0';
362
                        end if;
363
                        if out_inf_trigger = '1' and in_except(63) = '0' then
364
                                out_pos_inf <= '1';
365
                        else
366
                                out_pos_inf <= '0';
367
                        end if;
368
                        if out_inf_trigger = '1' and in_except(63) = '1' then
369
                                out_neg_inf <= '1';
370
                        else
371
                                out_neg_inf <= '0';
372
                        end if;
373
                        if rmode = "00" then
374
                                round_nearest <= '1';
375
                        else
376
                                round_nearest <= '0';
377
                        end if;
378
                        if rmode = "01" then
379
                                round_to_zero <= '1';
380
                        else
381
                                round_to_zero <= '0';
382
                        end if;
383
                        if rmode = "10" then
384
                                round_to_pos_inf <= '1';
385
                        else
386
                                round_to_pos_inf <= '0';
387
                        end if;
388
                        if rmode = "11" then
389
                                round_to_neg_inf <= '1';
390
                        else
391
                                round_to_neg_inf <= '0';
392
                        end if;
393
                        if (out_pos_inf = '1' and round_to_neg_inf = '1') or
394
                           (out_neg_inf = '1' and round_to_pos_inf = '1') or
395
                           (out_inf_trigger = '1' and round_to_zero = '1') then
396
                                inf_round_down_trigger <= '1';
397
                        else
398
                                inf_round_down_trigger <= '0';
399
                        end if;
400
                        if multiply = '1' and opa_et_zero = '0' and opb_et_zero = '0' and
401
                          in_et_zero = '1' then
402
                                mul_uf <= '1';
403
                        else
404
                                mul_uf <= '0';
405
                        end if;
406
                        if divide = '1' and opa_et_zero = '0' and in_et_zero = '1' then
407
                                div_uf <= '1';
408
                        else
409
                                div_uf <= '0';
410
                        end if;
411
                        if div_by_inf = '1' or mul_uf = '1' or div_uf = '1' then
412
                                underflow_trigger <= '1';
413
                        else
414
                                underflow_trigger <= '0';
415
                        end if;
416
                        if SNaN_input = '1' or addsub_inf_invalid = '1' or mul_0_by_inf = '1' or
417
                                div_0_by_0 = '1' or div_inf_by_inf = '1' then
418
                                invalid_trigger <= '1';
419
                        else
420
                                invalid_trigger <= '0';
421 10 davidklun
                        end if;
422 2 davidklun
                        if out_inf_trigger = '1' and NaN_input = '0' then
423
                                overflow_trigger <= '1';
424
                        else
425
                                overflow_trigger <= '0';
426
                        end if;
427
                        if (or_reduce(mantissa_in(1 downto 0)) = '1' or out_inf_trigger = '1' or
428
                          underflow_trigger = '1') and NaN_input = '0' then
429
                                inexact_trigger <= '1';
430
                        else
431
                                inexact_trigger <= '0';
432
                        end if;
433
                        if (invalid_trigger = '1' or overflow_trigger = '1' or
434
                          underflow_trigger = '1' or inexact_trigger = '1') then
435
                                except_trigger <= '1';
436
                        else
437
                                except_trigger <= '0';
438
                        end if;
439
                        if (except_trigger = '1' or out_inf_trigger = '1' or
440
                          NaN_input = '1') then
441
                                enable_trigger <= '1';
442
                        else
443
                                enable_trigger <= '0';
444
                        end if;
445
                        if (NaN_input = '1' or invalid_trigger = '1') then
446
                                NaN_out_trigger <= '1';
447
                        else
448
                                NaN_out_trigger <= '0';
449
                        end if;
450
                        if (invalid_trigger = '1' and SNaN_input = '0') then
451
                                SNaN_trigger <= '1';
452
                        else
453
                                SNaN_trigger <= '0';
454
                        end if;
455
                        if a_NaN = '1' then
456
                                NaN_output_0 <= exp_2047 & '1' & opa(50 downto 0);
457
                        else
458
                                NaN_output_0 <= exp_2047 & '1' & opb(50 downto 0);
459
                        end if;
460
                        if SNaN_trigger = '1' then
461
                                NaN_output <= exp_2047 & "01" & opa(49 downto 0);
462
                        else
463
                                NaN_output <= NaN_output_0;
464
                        end if;
465
                        inf_round_down <= exp_2046 & mantissa_max;
466
                        if inf_round_down_trigger = '1' then
467
                                out_inf <= inf_round_down;
468
                        else
469
                                out_inf <=  exp_2047 & "0000000000000000000000000000000000000000000000000000";
470
                        end if;
471
                        if underflow_trigger = '1' then
472
                                out_0 <= in_except(63) & "000000000000000000000000000000000000000000000000000000000000000";
473
                        else
474
                                out_0 <=  in_except;
475
                        end if;
476
                        if out_inf_trigger = '1' then
477
                                out_1 <= in_except(63) & out_inf;
478
                        else
479
                                out_1 <= out_0;
480
                        end if;
481
                        if NaN_out_trigger = '1' then
482
                                out_2 <= in_except(63) & NaN_output;
483
                        else
484
                                out_2 <= out_1;
485
                        end if;
486
                end if;
487
        end process;
488
 
489
 
490
        process
491
        begin
492
        wait until clk'event and clk = '1';
493
                if (rst = '1') then
494
                        ex_enable <= '0';
495
                        underflow <= '0';
496
                        overflow <= '0';
497
                        inexact <= '0';
498
                        exception <= '0';
499
                        invalid <= '0';
500
                        out_fp <= (others =>'0');
501
                elsif (enable = '1') then
502
                        ex_enable <= enable_trigger;
503
                        underflow <= underflow_trigger;
504
                        overflow <= overflow_trigger;
505
                        inexact <= inexact_trigger;
506
                        exception <= except_trigger;
507
                        invalid <= invalid_trigger;
508
                        out_fp <= out_2;
509
                end if;
510
        end process;
511
        end rtl;

powered by: WebSVN 2.1.0

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