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

Subversion Repositories double_fpu

[/] [double_fpu/] [trunk/] [fpu_double.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
/* FPU Operations (fpu_op):
38
========================
39
 
40
1 = sub
41
2 = mul
42
3 = div
43
 
44
Rounding Modes (rmode):
45
=======================
46
 
47
1 = round_to_zero
48
2 = round_up
49
3 = round_down  */
50
 
51
module fpu( clk, rst, enable, rmode, fpu_op, opa, opb, out, ready, underflow,
52
overflow, inexact, exception, invalid);
53
input           clk;
54
input           rst;
55
input           enable;
56
input   [1:0]    rmode;
57
input   [2:0]    fpu_op;
58
input   [63:0]   opa, opb;
59
output  [63:0]   out;
60
output          ready;
61
output          underflow;
62
output          overflow;
63
output          inexact;
64
output          exception;
65
output          invalid;
66
 
67
reg [63:0]       opa_reg;
68
reg [63:0]       opb_reg;
69
reg [2:0]        fpu_op_reg;
70
reg [1:0]        rmode_reg;
71
reg                     enable_reg;
72
reg                     enable_reg_1; // high for one clock cycle
73
reg                     enable_reg_2; // high for one clock cycle                
74
reg                     enable_reg_3; // high for two clock cycles
75
reg                     op_enable;
76
reg [63:0]       out;
77
reg [6:0]        count_cycles;
78
reg [6:0]        count_ready;
79
wire            count_busy = (count_ready <= count_cycles);
80
reg                     ready;
81
reg                     ready_0;
82
reg                     ready_1;
83
reg             underflow;
84
reg             overflow;
85
reg             inexact;
86
reg             exception;
87
reg             invalid;
88
wire            underflow_0;
89
wire            overflow_0;
90
wire            inexact_0;
91
wire            exception_0;
92
wire            invalid_0;
93
 
94
wire    add_enable_0 = (fpu_op_reg == 3'b000) & !(opa_reg[63] ^ opb_reg[63]);
95
wire    add_enable_1 = (fpu_op_reg == 3'b001) & (opa_reg[63] ^ opb_reg[63]);
96
reg             add_enable;
97
wire    sub_enable_0 = (fpu_op_reg == 3'b000) & (opa_reg[63] ^ opb_reg[63]);
98
wire    sub_enable_1 = (fpu_op_reg == 3'b001) & !(opa_reg[63] ^ opb_reg[63]);
99
reg             sub_enable;
100
reg             mul_enable;
101
reg             div_enable;
102
wire    [55:0]   sum_out;
103
wire    [55:0]   diff_out;
104
reg             [55:0]   addsub_out;
105
wire    [55:0]   mul_out;
106
wire    [55:0]   div_out;
107
reg             [55:0]   mantissa_round;
108
wire    [10:0]   exp_add_out;
109
wire    [10:0]   exp_sub_out;
110
wire    [11:0]   exp_mul_out;
111
wire    [11:0]   exp_div_out;
112
reg             [11:0]   exponent_round;
113
reg             [11:0]   exp_addsub;
114
wire    [11:0]   exponent_post_round;
115
wire    add_sign;
116
wire    sub_sign;
117
wire    mul_sign;
118
wire    div_sign;
119
reg             addsub_sign;
120
reg             sign_round;
121
wire    [63:0]   out_round;
122
wire    [63:0]   out_except;
123
 
124
fpu_add u1(
125
        .clk(clk),.rst(rst),.enable(add_enable),.opa(opa_reg),.opb(opb_reg),
126
        .sign(add_sign),.sum_2(sum_out),.exponent_2(exp_add_out));
127
 
128
fpu_sub u2(
129
        .clk(clk),.rst(rst),.enable(sub_enable),.opa(opa_reg),.opb(opb_reg),
130
        .fpu_op(fpu_op_reg),.sign(sub_sign),.diff_2(diff_out),
131
        .exponent_2(exp_sub_out));
132
 
133
fpu_mul u3(
134
        .clk(clk),.rst(rst),.enable(mul_enable),.opa(opa_reg),.opb(opb_reg),
135
        .sign(mul_sign),.product_7(mul_out),.exponent_5(exp_mul_out));
136
 
137
fpu_div u4(
138
        .clk(clk),.rst(rst),.enable(div_enable),.opa(opa_reg),.opb(opb_reg),
139
        .sign(div_sign),.mantissa_7(div_out),.exponent_out(exp_div_out));
140
 
141
fpu_round u5(.clk(clk),.rst(rst),.enable(op_enable),    .round_mode(rmode_reg),
142
        .sign_term(sign_round),.mantissa_term(mantissa_round), .exponent_term(exponent_round),
143
        .round_out(out_round),.exponent_final(exponent_post_round));
144
 
145
fpu_exceptions u6(.clk(clk),.rst(rst),.enable(op_enable),.rmode(rmode_reg),
146
        .opa(opa_reg),.opb(opb_reg),
147
        .in_except(out_round), .exponent_in(exponent_post_round),
148
        .mantissa_in(mantissa_round[1:0]),.fpu_op(fpu_op_reg),.out(out_except),
149
        .ex_enable(except_enable),.underflow(underflow_0),.overflow(overflow_0),
150
        .inexact(inexact_0),.exception(exception_0),.invalid(invalid_0));
151
 
152
 
153
always @(posedge clk)
154
begin
155
        case (fpu_op_reg)
156
        3'b000:         mantissa_round <= addsub_out;
157
        3'b001:         mantissa_round <= addsub_out;
158
        3'b010:         mantissa_round <= mul_out;
159
        3'b011:         mantissa_round <= div_out;
160
        default:        mantissa_round <= 0;
161
        endcase
162
end
163
 
164
always @(posedge clk)
165
begin
166
        case (fpu_op_reg)
167
        3'b000:         exponent_round <= exp_addsub;
168
        3'b001:         exponent_round <= exp_addsub;
169
        3'b010:         exponent_round <= exp_mul_out;
170
        3'b011:         exponent_round <= exp_div_out;
171
        default:        exponent_round <= 0;
172
        endcase
173
end
174
 
175
always @(posedge clk)
176
begin
177
        case (fpu_op_reg)
178
        3'b000:         sign_round <= addsub_sign;
179
        3'b001:         sign_round <= addsub_sign;
180
        3'b010:         sign_round <= mul_sign;
181
        3'b011:         sign_round <= div_sign;
182
        default:        sign_round <= 0;
183
        endcase
184
end
185
 
186
always @(posedge clk)
187
begin
188
        case (fpu_op_reg)
189
        3'b000:         count_cycles <= 20;
190
        3'b001:         count_cycles <= 21;
191
        3'b010:         count_cycles <= 24;
192
        3'b011:         count_cycles <= 71;
193
        default:        count_cycles <= 0;
194
        endcase
195
end
196
 
197
always @(posedge clk)
198
begin
199
        if (rst) begin
200
                add_enable <= 0;
201
                sub_enable <= 0;
202
                mul_enable <= 0;
203
                div_enable <= 0;
204
                addsub_out <= 0;
205
                addsub_sign <= 0;
206
                exp_addsub <= 0;
207
                end
208
        else begin
209
                add_enable <= (add_enable_0 | add_enable_1) & op_enable;
210
                sub_enable <= (sub_enable_0 | sub_enable_1) & op_enable;
211
                mul_enable <= (fpu_op_reg == 3'b010) & op_enable;
212
                div_enable <= (fpu_op_reg == 3'b011) & op_enable & enable_reg_3;
213
                        // div_enable needs to be high for two clock cycles
214
                addsub_out <= add_enable ? sum_out : diff_out;
215
                addsub_sign <= add_enable ? add_sign : sub_sign;
216
                exp_addsub <= add_enable ? { 1'b0, exp_add_out} : { 1'b0, exp_sub_out};
217
                end
218
end
219
 
220
always @ (posedge clk)
221
begin
222
        if (rst)
223
                count_ready <= 0;
224
        else if (enable_reg_1)
225
                count_ready <= 0;
226
        else if (count_busy)
227
                count_ready <= count_ready + 1;
228
end
229
 
230
always @(posedge clk)
231
begin
232
        if (rst) begin
233
                enable_reg <= 0;
234
                enable_reg_1 <= 0;
235
                enable_reg_2 <= 0;
236
                enable_reg_3 <= 0;
237
                end
238
        else begin
239
                enable_reg <= enable;
240
                enable_reg_1 <= enable & !enable_reg;
241
                enable_reg_2 <= enable_reg_1;
242
                enable_reg_3 <= enable_reg_1 | enable_reg_2;
243
                end
244
end
245
 
246
always @(posedge clk)
247
begin
248
        if (rst) begin
249
                opa_reg <= 0;
250
                opb_reg <= 0;
251
                fpu_op_reg <= 0;
252
                rmode_reg <= 0;
253
                op_enable <= 0;
254
                end
255
        else if (enable_reg_1) begin
256
                opa_reg <= opa;
257
                opb_reg <= opb;
258
                fpu_op_reg <= fpu_op;
259
                rmode_reg <= rmode;
260
                op_enable <= 1;
261
                end
262
end
263
 
264
always @(posedge clk)
265
begin
266
        if (rst) begin
267
                ready_0 <= 0;
268
                ready_1 <= 0;
269
                ready <= 0;
270
                end
271
        else if (enable_reg_1) begin
272
                ready_0 <= 0;
273
                ready_1 <= 0;
274
                ready <= 0;
275
                end
276
        else begin
277
                ready_0 <= !count_busy;
278
                ready_1 <= ready_0;
279
                ready <= ready_1;
280
                end
281
end
282
 
283
always @(posedge clk)
284
begin
285
        if (rst) begin
286
                underflow <= 0;
287
                overflow <= 0;
288
                inexact <= 0;
289
                exception <= 0;
290
                invalid <= 0;
291
                out <= 0;
292
                end
293
        else if (ready_1) begin
294
                underflow <= underflow_0;
295
                overflow <= overflow_0;
296
                inexact <= inexact_0;
297
                exception <= exception_0;
298
                invalid <= invalid_0;
299
                out <= except_enable ? out_except : out_round;
300
                end
301
end
302
endmodule

powered by: WebSVN 2.1.0

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