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

Subversion Repositories fpu_double

[/] [fpu_double/] [trunk/] [fpu_div.vhd] - Blame information for rev 14

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
        use IEEE.numeric_std.all;
41
        library work;
42
        use work.fpupack.all;
43
 
44
        ENTITY fpu_div IS
45
 
46
   PORT(
47
      clk, rst, enable : IN     std_logic;
48
      opa, opb : IN     std_logic_vector (63 DOWNTO 0);
49
      sign : OUT    std_logic;
50
      mantissa_7 : OUT    std_logic_vector (55 DOWNTO 0);
51
      exponent_out : OUT    std_logic_vector (11 DOWNTO 0)
52
   );
53
 
54
        END fpu_div;
55
 
56
        architecture rtl of fpu_div is
57
 
58
        signal dividend_signal : std_logic_vector(53 downto 0);
59
        signal divisor_signal : std_logic_vector(53 downto 0);
60
        signal enable_signal : std_logic;
61
        signal enable_signal_2 : std_logic;
62
        signal enable_signal_a : std_logic;
63
        signal enable_signal_b : std_logic;
64
        signal enable_signal_c : std_logic;
65
        signal enable_signal_d : std_logic;
66
        signal enable_signal_e : std_logic;
67
        signal dividend_shift : std_logic_vector(5 downto 0);
68
        signal dividend_shift_2 : std_logic_vector(5 downto 0);
69
        signal divisor_shift : std_logic_vector(5 downto 0);
70
        signal divisor_shift_2 : std_logic_vector(5 downto 0);
71
        signal count_out : std_logic_vector(5 downto 0);
72
        signal mantissa_a : std_logic_vector(51 downto 0);
73
        signal mantissa_b : std_logic_vector(51 downto 0);
74
        signal expon_a : std_logic_vector(10 downto 0);
75
        signal expon_b : std_logic_vector(10 downto 0);
76
        signal a_is_norm : std_logic;
77
        signal b_is_norm : std_logic;
78
        signal a_is_zero : std_logic;
79
        signal exponent_a : std_logic_vector(11 downto 0);
80
        signal exponent_b : std_logic_vector(11 downto 0);
81
        signal dividend_a : std_logic_vector(51 downto 0);
82
        signal dividend_a_shifted : std_logic_vector(51 downto 0);
83
        signal dividend_denorm : std_logic_vector(52 downto 0);
84
        signal dividend_1 : std_logic_vector(53 downto 0);
85
        signal divisor_b : std_logic_vector(51 downto 0);
86
        signal divisor_b_shifted : std_logic_vector(51 downto 0);
87
        signal divisor_denorm : std_logic_vector(52 downto 0);
88
        signal divisor_1 : std_logic_vector(53 downto 0);
89
        signal count_index : std_logic_vector(5 downto 0);
90
        signal count_nonzero : std_logic;
91
        signal quotient : std_logic_vector(53 downto 0);
92
        signal quotient_out : std_logic_vector(53 downto 0);
93
        signal remainder : std_logic_vector(53 downto 0);
94
        signal remainder_out : std_logic_vector(53 downto 0);
95
        signal remainder_msb : std_logic;
96
        signal count_nonzero_signal : std_logic;
97
        signal count_nonzero_signal_2 : std_logic;
98
        signal expon_term : std_logic_vector(11 downto 0);
99
        signal expon_uf_1 : std_logic;
100
        signal expon_uf_term_1 : std_logic_vector(11 downto 0);
101
        signal expon_final_1 : std_logic_vector(11 downto 0);
102
        signal expon_final_2 : std_logic_vector(11 downto 0);
103
        signal expon_shift_a : std_logic_vector(11 downto 0);
104
        signal expon_shift_b : std_logic_vector(11 downto 0);
105
        signal expon_uf_2 : std_logic;
106
        signal expon_uf_term_2 : std_logic_vector(11 downto 0);
107
        signal expon_uf_term_3 : std_logic_vector(11 downto 0);
108
        signal expon_uf_gt_maxshift : std_logic;
109
        signal expon_uf_term_4 : std_logic_vector(11 downto 0);
110
        signal expon_final_3 : std_logic_vector(11 downto 0);
111
        signal expon_final_4 : std_logic_vector(11 downto 0);
112
        signal quotient_msb : std_logic;
113
        signal expon_final_4_et0 : std_logic;
114
        signal expon_final_4_term : std_logic;
115
        signal expon_final_5 : std_logic_vector(11 downto 0);
116
        signal mantissa_1 : std_logic_vector(51 downto 0);
117
        signal mantissa_2 : std_logic_vector(51 downto 0);
118
        signal mantissa_3 : std_logic_vector(51 downto 0);
119
        signal mantissa_4 : std_logic_vector(51 downto 0);
120
        signal mantissa_5 : std_logic_vector(51 downto 0);
121
        signal mantissa_6 : std_logic_vector(51 downto 0);
122
        signal remainder_a : std_logic_vector(107 downto 0);
123
        signal remainder_shift_term : std_logic_vector(11 downto 0);
124
        signal remainder_b : std_logic_vector(107 downto 0);
125
        signal remainder_1 : std_logic_vector(55 downto 0);
126
        signal remainder_2 : std_logic_vector(55 downto 0);
127
        signal remainder_3 : std_logic_vector(55 downto 0);
128
        signal remainder_4 : std_logic_vector(55 downto 0);
129
        signal remainder_5 : std_logic_vector(55 downto 0);
130
        signal remainder_6 : std_logic_vector(55 downto 0);
131
        signal m_norm : std_logic;
132
        signal rem_lsb : std_logic;
133
 
134
        begin
135
                sign  <= opa(63) xor opb(63);
136
                expon_a  <= opa(62 downto 52);
137
                expon_b  <= opb(62 downto 52);
138
                a_is_norm  <= or_reduce(expon_a);
139
                b_is_norm  <= or_reduce(expon_b);
140
                a_is_zero  <= not or_reduce(opa(62 downto 0));
141
                exponent_a  <=  '0' & expon_a;
142
                exponent_b  <=  '0' & expon_b;
143
                dividend_denorm <= dividend_a_shifted & '0';
144
                dividend_1  <= "01" & dividend_a when a_is_norm = '1' else '0' & dividend_denorm;
145
                divisor_denorm  <= divisor_b_shifted & '0';
146
                divisor_1  <= "01" & divisor_b when b_is_norm = '1' else '0' & divisor_denorm;
147
                count_nonzero  <= '0' when count_index = "000000" else '1';
148
                count_index <= count_out;
149
                quotient_msb  <= quotient_out(53);
150
                mantissa_2  <= quotient_out(52 downto 1);
151
                mantissa_3  <= quotient_out(51 downto 0);
152
                mantissa_4  <= mantissa_2 when quotient_msb = '1' else  mantissa_3;
153
                mantissa_5  <= mantissa_2 when expon_final_4 = "000000000001" else  mantissa_4;
154
        mantissa_6  <= mantissa_1 when expon_final_4_et0 = '1' else mantissa_5;
155
                remainder_a  <=  quotient_out(53 downto 0) & remainder_msb & remainder_out(52 downto 0);
156 14 davidklun
                remainder_1  <= remainder_b(107 downto 53) & or_reduce(remainder_b(52 downto 0));
157 2 davidklun
                remainder_2  <= quotient_out(0) & remainder_msb & remainder_out(52 downto 0) & '0' ;
158
                remainder_3  <=  remainder_msb & remainder_out(52 downto 0) & "00" ;
159
                remainder_4  <=  remainder_2 when quotient_msb = '1' else remainder_3;
160
                remainder_5  <=  remainder_2 when expon_final_4 = "000000000001" else remainder_4;
161
                remainder_6  <= remainder_1 when expon_final_4_et0 = '1' else remainder_5;
162
                m_norm  <= or_reduce(expon_final_5);
163
                rem_lsb <= or_reduce(remainder_6(54 downto 0));
164
                mantissa_7  <=  '0' & m_norm & mantissa_6 & remainder_6(55) & rem_lsb ;
165
 
166
process
167
        begin
168
        wait until clk'event and clk = '1';
169
                if (rst = '1') then
170
                        exponent_out <= (others =>'0');
171
                else
172
                        if (a_is_zero = '1') then
173
                                exponent_out <= "000000000000";
174
                        else
175
                                exponent_out <= expon_final_5;
176
                        end if;
177
                end if;
178
        end process;
179
 
180
process
181
        begin
182
        wait until clk'event and clk = '1';
183
                if (rst = '1') then
184
                        count_out <= (others =>'0');
185
                elsif (enable_signal = '1') then
186
                        count_out <= "110101"; -- 53
187
                elsif (count_nonzero = '1') then
188
                        count_out <= count_out - "000001";
189
                end if;
190
        end process;
191
 
192
process
193
        begin
194
        wait until clk'event and clk = '1';
195
                if (rst = '1') then
196
                        quotient_out <= (others =>'0');
197
                        remainder_out <= (others =>'0');
198
                else
199
                        quotient_out <= quotient;
200
                        remainder_out <= remainder;
201
                end if;
202
        end process;
203
 
204
 
205
process
206
        begin
207
        wait until clk'event and clk = '1';
208
                if (rst = '1') then
209
                        quotient <= (others =>'0');
210
                elsif (count_nonzero_signal = '1') then
211
                        if (divisor_signal > dividend_signal) then
212
                                quotient(conv_integer(count_index)) <= '0';
213
                        else
214
                                quotient(conv_integer(count_index)) <= '1';
215
                        end if;
216
                end if;
217
        end process;
218
 
219
process
220
        begin
221
        wait until clk'event and clk = '1';
222
                if (rst = '1') then
223
                        remainder <= (others =>'0');
224
                        remainder_msb <= '0';
225
                elsif ((not count_nonzero_signal and count_nonzero_signal_2) = '1') then
226
                    remainder <= dividend_signal;
227
                    if (divisor_signal > dividend_signal) then
228
                        remainder_msb <= '0';
229
                    else
230
                        remainder_msb <= '1';
231
                    end if;
232
                end if;
233
        end process;
234
 
235
process
236
        begin
237
        wait until clk'event and clk = '1';
238
                if (rst = '1') then
239
                        dividend_signal <= (others =>'0');
240
                        divisor_signal <= (others =>'0');
241
                elsif (enable_signal_e = '1') then
242
                        dividend_signal <= dividend_1;
243
                        divisor_signal <= divisor_1;
244
                elsif (count_nonzero_signal = '1') then
245
                        if (divisor_signal > dividend_signal) then
246
                                dividend_signal <= shl(dividend_signal, conv_std_logic_vector('1', 54));
247
                        else
248
                                dividend_signal <= shl(dividend_signal - divisor_signal, conv_std_logic_vector('1', 54));
249
                        end if;
250
                end if;
251
        end process;
252
 
253
process
254
        begin
255
        wait until clk'event and clk = '1';
256
                if (rst = '1') then
257
                        expon_term  <= (others =>'0');
258
                        expon_uf_1 <= '0';
259
                expon_uf_term_1 <= (others =>'0');
260
                expon_final_1 <= (others =>'0');
261
                expon_final_2 <= (others =>'0');
262
                expon_shift_a <= (others =>'0');
263
                expon_shift_b <= (others =>'0');
264
                        expon_uf_2 <= '0';
265
                expon_uf_term_2 <= (others =>'0');
266
                expon_uf_term_3 <= (others =>'0');
267
                        expon_uf_gt_maxshift <= '0';
268
                expon_uf_term_4 <= (others =>'0');
269
                expon_final_3 <= (others =>'0');
270
                expon_final_4 <= (others =>'0');
271
                        expon_final_4_et0 <= '0';
272
                        expon_final_4_term <= '0';
273
                expon_final_5 <= (others =>'0');
274
                mantissa_a <= (others =>'0');
275
                        mantissa_b <= (others =>'0');
276
                        dividend_a <= (others =>'0');
277
                        divisor_b <= (others =>'0');
278
                        dividend_shift <= (others =>'0');
279
                        divisor_shift <= (others =>'0');
280
                        dividend_shift_2 <= (others =>'0');
281
                        divisor_shift_2 <= (others =>'0');
282
                        remainder_shift_term <= (others =>'0');
283
                        remainder_b <= (others =>'0');
284
                        dividend_a_shifted <= (others =>'0');
285
                        divisor_b_shifted <=  (others =>'0');
286
                        mantissa_1 <= (others =>'0');
287
                elsif (enable_signal_2 = '1') then
288
                        expon_term  <= exponent_a + "001111111111"; -- 1023
289
                        if (exponent_b > expon_term) then
290
                                expon_uf_1 <= '1';
291
                        else
292
                                expon_uf_1 <= '0';
293
                        end if;
294
                        if (expon_uf_1 = '1') then
295
                                expon_uf_term_1 <= exponent_b - expon_term;
296
                                expon_final_2 <= (others =>'0');
297
                        else
298
                                expon_uf_term_1 <= (others =>'0');
299
                                expon_final_2 <= expon_final_1;
300
                        end if;
301
                expon_final_1 <= expon_term - exponent_b;
302
                if (expon_uf_1 = '1') then
303
                                expon_uf_term_1 <= exponent_b - expon_term;
304
                        else
305
                                expon_uf_term_1 <= (others =>'0');
306
                        end if;
307
                        if (a_is_norm = '1') then
308
                                expon_shift_a <= (others =>'0');
309
                        else
310
                                expon_shift_a <= "000000" & dividend_shift_2;
311
                        end if;
312
                if (b_is_norm = '1') then
313
                                expon_shift_b <= (others =>'0');
314
                        else
315
                                expon_shift_b <= "000000" & divisor_shift_2;
316
                        end if;
317
                        if (expon_shift_a > expon_final_2) then
318
                                expon_uf_2 <= '1';
319
                        else
320
                                expon_uf_2 <= '0';
321
                        end if;
322
                        if (expon_uf_2 = '1') then
323
                                expon_uf_term_2 <= expon_shift_a - expon_final_2;
324
                        else
325
                                expon_uf_term_2 <= (others =>'0');
326
                        end if;
327
                expon_uf_term_3 <= expon_uf_term_2 + expon_uf_term_1;
328
                if (expon_uf_term_3 > "000000110011") then -- 51
329
                                expon_uf_gt_maxshift <= '1';
330
                        else
331
                                expon_uf_gt_maxshift <= '0';
332
                        end if;
333
                        if (expon_uf_gt_maxshift = '1') then
334
                                expon_uf_term_4 <= "000000110100"; --52
335
                        else
336
                                expon_uf_term_4 <= expon_uf_term_3;
337
                        end if;
338
                        if (expon_uf_2 = '1') then
339
                                expon_final_3 <= (others =>'0');
340
                        else
341
                                expon_final_3 <= expon_final_2 - expon_shift_a;
342
                        end if;
343
                expon_final_4 <= expon_final_3 + expon_shift_b;
344
                if (expon_final_4 = "000000000000") then
345
                                expon_final_4_et0 <= '1';
346
                        else
347
                                expon_final_4_et0 <= '0';
348
                        end if;
349
                        if (expon_final_4_et0 = '1') then
350
                                expon_final_4_term <= '0';
351
                        else
352
                                expon_final_4_term <= '1';
353
                        end if;
354
                        if (quotient_msb = '1') then
355
                                expon_final_5 <= expon_final_4;
356
                        else
357
                                expon_final_5 <= expon_final_4 - expon_final_4_term;
358
                        end if;
359
                        mantissa_a <= opa(51 downto 0);
360
                        mantissa_b <= opb(51 downto 0);
361
                        dividend_a <= mantissa_a;
362
                        divisor_b <= mantissa_b;
363
                        dividend_shift <= count_l_zeros(dividend_a);
364
                        divisor_shift <= count_l_zeros(divisor_b);
365
                        dividend_shift_2 <= dividend_shift;
366
                        divisor_shift_2 <= divisor_shift;
367
                        remainder_shift_term <= "000000110100" - expon_uf_term_4; -- 52
368
                        remainder_b <= shl(remainder_a, remainder_shift_term);
369
                        dividend_a_shifted <= shl(dividend_a, dividend_shift_2);
370
                        divisor_b_shifted <= shl(divisor_b, divisor_shift_2);
371
                        mantissa_1 <= shr(quotient_out(53 downto 2), expon_uf_term_4);
372
                end if;
373
        end process;
374
 
375
process
376
        begin
377
        wait until clk'event and clk = '1';
378
                if (rst = '1') then
379
                        count_nonzero_signal <= '0';
380
                        count_nonzero_signal_2 <= '0';
381
                        enable_signal <= '0';
382
                        enable_signal_a <= '0';
383
                        enable_signal_b <= '0';
384
                        enable_signal_c <= '0';
385
                        enable_signal_d <= '0';
386
                        enable_signal_e <= '0';
387
                else
388
                        count_nonzero_signal <= count_nonzero;
389
                        count_nonzero_signal_2 <= count_nonzero_signal;
390
                        enable_signal <= enable_signal_e;
391
                        enable_signal_a <= enable;
392
                        enable_signal_b <= enable_signal_a;
393
                        enable_signal_c <= enable_signal_b;
394
                        enable_signal_d <= enable_signal_c;
395
                        enable_signal_e <= enable_signal_d;
396
                end if;
397
        end process;
398
 
399
process
400
        begin
401
        wait until clk'event and clk = '1';
402
                if (rst = '1') then
403
                        enable_signal_2 <= '0';
404
                elsif (enable = '1') then
405
                        enable_signal_2 <= '1';
406
                end if;
407
        end process;
408
 
409
        end rtl;

powered by: WebSVN 2.1.0

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