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

Subversion Repositories double_fpu

[/] [double_fpu/] [branches/] [avendor/] [fpu_exceptions.v] - Blame information for rev 13

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
 
36
`timescale 1ns / 100ps
37
 
38
module fpu_exceptions( clk, rst, enable, rmode, opa, opb, in_except,
39
exponent_in, mantissa_in, fpu_op, out, ex_enable, underflow, overflow,
40
inexact, exception, invalid);
41
input           clk;
42
input           rst;
43
input           enable;
44
input   [1:0]    rmode;
45
input   [63:0]   opa;
46
input   [63:0]   opb;
47
input   [63:0]   in_except;
48
input   [11:0]   exponent_in;
49
input   [1:0]    mantissa_in;
50
input   [2:0]    fpu_op;
51
output  [63:0]   out;
52
output          ex_enable;
53
output          underflow;
54
output          overflow;
55
output          inexact;
56
output          exception;
57
output          invalid;
58
 
59
reg             [63:0]   out;
60
reg             ex_enable;
61
reg             underflow;
62
reg             overflow;
63
reg             inexact;
64
reg             exception;
65
reg             invalid;
66
 
67
reg             in_et_zero;
68
reg             opa_et_zero;
69
reg             opb_et_zero;
70
reg             input_et_zero;
71
reg             add;
72
reg             subtract;
73
reg             multiply;
74
reg             divide;
75
reg             opa_QNaN;
76
reg             opb_QNaN;
77
reg             opa_SNaN;
78
reg             opb_SNaN;
79
reg             opa_pos_inf;
80
reg             opb_pos_inf;
81
reg             opa_neg_inf;
82
reg             opb_neg_inf;
83
reg             opa_inf;
84
reg             opb_inf;
85
reg             NaN_input;
86
reg             SNaN_input;
87
reg             a_NaN;
88
reg             div_by_0;
89
reg             div_0_by_0;
90
reg             div_inf_by_inf;
91
reg             div_by_inf;
92
reg             mul_0_by_inf;
93
reg             mul_inf;
94
reg             div_inf;
95
reg             add_inf;
96
reg             sub_inf;
97
reg             addsub_inf_invalid;
98
reg             addsub_inf;
99
reg             out_inf_trigger;
100
reg             out_pos_inf;
101
reg             out_neg_inf;
102
reg             round_nearest;
103
reg             round_to_zero;
104
reg             round_to_pos_inf;
105
reg             round_to_neg_inf;
106
reg             inf_round_down_trigger;
107
reg             mul_uf;
108
reg             div_uf;
109
reg             underflow_trigger;
110
reg             invalid_trigger;
111
reg             overflow_trigger;
112
reg             inexact_trigger;
113
reg             except_trigger;
114
reg             enable_trigger;
115
reg             NaN_out_trigger;
116
reg             SNaN_trigger;
117
 
118
 
119
wire    [10:0]  exp_2047 = 11'b11111111111;
120
wire    [10:0]  exp_2046 = 11'b11111111110;
121
reg             [62:0] NaN_output_0;
122
reg             [62:0] NaN_output;
123
wire    [51:0]  mantissa_max = 52'b1111111111111111111111111111111111111111111111111111;
124
reg             [62:0]   inf_round_down;
125
reg             [62:0]   out_inf;
126
reg             [63:0]   out_0;
127
reg             [63:0]   out_1;
128
reg             [63:0]   out_2;
129
 
130
always @(posedge clk)
131
begin
132
        if (rst) begin
133
                in_et_zero <=    0;
134
                opa_et_zero <=   0;
135
                opb_et_zero <=   0;
136
                input_et_zero <= 0;
137
                add     <=      0;
138
                subtract <= 0;
139
                multiply <= 0;
140
                divide  <=      0;
141
                opa_QNaN <= 0;
142
                opb_QNaN <= 0;
143
                opa_SNaN <= 0;
144
                opb_SNaN <= 0;
145
                opa_pos_inf <= 0;
146
                opb_pos_inf <= 0;
147
                opa_neg_inf <= 0;
148
                opb_neg_inf <= 0;
149
                opa_inf <= 0;
150
                opb_inf <= 0;
151
                NaN_input <= 0;
152
                SNaN_input <= 0;
153
                a_NaN <= 0;
154
                div_by_0 <= 0;
155
                div_0_by_0 <= 0;
156
                div_inf_by_inf <= 0;
157
                div_by_inf <= 0;
158
                mul_0_by_inf <= 0;
159
                mul_inf <= 0;
160
                div_inf <= 0;
161
                add_inf <= 0;
162
                sub_inf <= 0;
163
                addsub_inf_invalid <= 0;
164
                addsub_inf <= 0;
165
                out_inf_trigger <= 0;
166
                out_pos_inf <= 0;
167
                out_neg_inf <= 0;
168
                round_nearest <= 0;
169
                round_to_zero <= 0;
170
                round_to_pos_inf <= 0;
171
                round_to_neg_inf <= 0;
172
                inf_round_down_trigger <= 0;
173
                mul_uf <= 0;
174
                div_uf <= 0;
175
                underflow_trigger <= 0;
176
                invalid_trigger <= 0;
177
                overflow_trigger <= 0;
178
                inexact_trigger <= 0;
179
                except_trigger <= 0;
180
                enable_trigger <= 0;
181
                NaN_out_trigger <= 0;
182
                SNaN_trigger <= 0;
183
                NaN_output_0 <= 0;
184
                NaN_output <= 0;
185
                inf_round_down <= 0;
186
                out_inf <= 0;
187
                out_0 <= 0;
188
                out_1 <= 0;
189
                out_2 <= 0;
190
                end
191
        else if (enable) begin
192
                in_et_zero <= !(|in_except[62:0]);
193
                opa_et_zero <= !(|opa[62:0]);
194
                opb_et_zero <= !(|opb[62:0]);
195
                input_et_zero <= !(|in_except[62:0]);
196
                add     <=      fpu_op == 3'b000;
197
                subtract <=     fpu_op == 3'b001;
198
                multiply <=     fpu_op == 3'b010;
199
                divide  <=      fpu_op == 3'b011;
200
                opa_QNaN <= (opa[62:52] == 2047) & |opa[51:0] & opa[51];
201
                opb_QNaN <= (opb[62:52] == 2047) & |opb[51:0] & opb[51];
202
                opa_SNaN <= (opa[62:52] == 2047) & |opa[51:0] & !opa[51];
203
                opb_SNaN <= (opb[62:52] == 2047) & |opb[51:0] & !opb[51];
204
                opa_pos_inf <= !opa[63] & (opa[62:52] == 2047) & !(|opa[51:0]);
205
                opb_pos_inf <= !opb[63] & (opb[62:52] == 2047) & !(|opb[51:0]);
206
                opa_neg_inf <= opa[63] & (opa[62:52] == 2047) & !(|opa[51:0]);
207
                opb_neg_inf <= opb[63] & (opb[62:52] == 2047) & !(|opb[51:0]);
208
                opa_inf <= (opa[62:52] == 2047) & !(|opa[51:0]);
209
                opb_inf <= (opb[62:52] == 2047) & !(|opb[51:0]);
210
                NaN_input <= opa_QNaN | opb_QNaN | opa_SNaN | opb_SNaN;
211
                SNaN_input <= opa_SNaN | opb_SNaN;
212
                a_NaN <= opa_QNaN | opa_SNaN;
213
                div_by_0 <= divide & opb_et_zero & !opa_et_zero;
214
                div_0_by_0 <= divide & opb_et_zero & opa_et_zero;
215
                div_inf_by_inf <= divide & opa_inf & opb_inf;
216
                div_by_inf <= divide & !opa_inf & opb_inf;
217
                mul_0_by_inf <= multiply & ((opa_inf & opb_et_zero) | (opa_et_zero & opb_inf));
218
                mul_inf <= multiply & (opa_inf | opb_inf) & !mul_0_by_inf;
219
                div_inf <= divide & opa_inf & !opb_inf;
220
                add_inf <= (add & (opa_inf | opb_inf));
221
                sub_inf <= (subtract & (opa_inf | opb_inf));
222
                addsub_inf_invalid <= (add & opa_pos_inf & opb_neg_inf) | (add & opa_neg_inf & opb_pos_inf) |
223
                                        (subtract & opa_pos_inf & opb_pos_inf) | (subtract & opa_neg_inf & opb_neg_inf);
224
                addsub_inf <= (add_inf | sub_inf) & !addsub_inf_invalid;
225
                out_inf_trigger <= addsub_inf | mul_inf | div_inf | div_by_0 | (exponent_in > 2046);
226
                out_pos_inf <= out_inf_trigger & !in_except[63];
227
                out_neg_inf <= out_inf_trigger & in_except[63];
228
                round_nearest <= (rmode == 2'b00);
229
                round_to_zero <= (rmode == 2'b01);
230
                round_to_pos_inf <= (rmode == 2'b10);
231
                round_to_neg_inf <= (rmode == 2'b11);
232
                inf_round_down_trigger <= (out_pos_inf & round_to_neg_inf) |
233
                                                                (out_neg_inf & round_to_pos_inf) |
234
                                                                (out_inf_trigger & round_to_zero);
235
                mul_uf <= multiply & !opa_et_zero & !opb_et_zero & in_et_zero;
236
                div_uf <= divide & !opa_et_zero & in_et_zero;
237
                underflow_trigger <= div_by_inf | mul_uf | div_uf;
238
                invalid_trigger <= SNaN_input | addsub_inf_invalid | mul_0_by_inf |
239
                                                div_0_by_0 | div_inf_by_inf;
240
                overflow_trigger <= out_inf_trigger & !NaN_input;
241
                inexact_trigger <= (|mantissa_in[1:0] | out_inf_trigger | underflow_trigger) &
242
                                                !NaN_input;
243
                except_trigger <= invalid_trigger | overflow_trigger | underflow_trigger |
244
                                                inexact_trigger;
245
                enable_trigger <= except_trigger | out_inf_trigger | NaN_input;
246
                NaN_out_trigger <= NaN_input | invalid_trigger;
247
                SNaN_trigger <= invalid_trigger & !SNaN_input;
248
                NaN_output_0 <= a_NaN ? { exp_2047, 1'b1, opa[50:0]} : { exp_2047, 1'b1, opb[50:0]};
249
                NaN_output <= SNaN_trigger ? { exp_2047, 2'b01, opa[49:0]} : NaN_output_0;
250
                inf_round_down <= { exp_2046, mantissa_max };
251
                out_inf <= inf_round_down_trigger ? inf_round_down : { exp_2047, 52'b0 };
252
                out_0 <= underflow_trigger ? { in_except[63], 63'b0 } : in_except;
253
                out_1 <= out_inf_trigger ? { in_except[63], out_inf } : out_0;
254
                out_2 <= NaN_out_trigger ? { in_except[63], NaN_output} : out_1;
255
                end
256
end
257
 
258
always @(posedge clk)
259
begin
260
        if (rst) begin
261
                ex_enable <= 0;
262
                underflow <= 0;
263
                overflow <= 0;
264
                inexact <= 0;
265
                exception <= 0;
266
                invalid <= 0;
267
                out <= 0;
268
                end
269
        else if (enable) begin
270
                ex_enable <= enable_trigger;
271
                underflow <= underflow_trigger;
272
                overflow <= overflow_trigger;
273
                inexact <= inexact_trigger;
274
                exception <= except_trigger;
275
                invalid <= invalid_trigger;
276
                out <= out_2;
277
                end
278
end
279
 
280
endmodule

powered by: WebSVN 2.1.0

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