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

Subversion Repositories fpu_double

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

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
        library work;
41
        use work.comppack.all;
42
        use work.fpupack.all;
43
 
44
        ENTITY fpu_double IS
45
 
46
   PORT(
47
      clk, rst, enable : IN     std_logic;
48
      rmode : IN     std_logic_vector (1 DOWNTO 0);
49
      fpu_op : IN     std_logic_vector (2 DOWNTO 0);
50
      opa, opb : IN     std_logic_vector (63 DOWNTO 0);
51
      out_fp: OUT    std_logic_vector (63 DOWNTO 0);
52
      ready, underflow, overflow, inexact : OUT    std_logic;
53
      exception, invalid : OUT    std_logic
54
   );
55
 
56
        END fpu_double;
57
 
58
-- FPU Operations (fpu_op):
59
--========================
60
--      0 = add
61
--      1 = sub
62
--      2 = mul
63
--      3 = div
64
 
65
--Rounding Modes (rmode):
66
--=======================
67
--      0 = round_nearest_even
68
--      1 = round_to_zero
69
--      2 = round_up
70
--      3 = round_down  
71
 
72
        architecture rtl of fpu_double is
73
 
74
        signal  opa_reg : std_logic_vector(63 downto 0);
75
        signal  opb_reg : std_logic_vector(63 downto 0);
76
        signal  fpu_op_reg : std_logic_vector(2 downto 0);
77
        signal  rmode_reg : std_logic_vector(1 downto 0);
78
        signal  enable_reg : std_logic;
79
        signal  enable_reg_1 : std_logic; -- high for one clock cycle
80
        signal  enable_reg_2 : std_logic; -- high for one clock cycle            
81
        signal  enable_reg_3 : std_logic; -- high for two clock cycles
82
        signal  op_enable : std_logic;
83
        signal  count_cycles : std_logic_vector(6 downto 0);
84
        signal  count_ready : std_logic_vector(6 downto 0);
85
        signal  count_busy : std_logic;
86
        signal  ready_0 : std_logic;
87
        signal  ready_1 : std_logic;
88
        signal  underflow_0 : std_logic;
89
        signal  overflow_0 : std_logic;
90
        signal  inexact_0 : std_logic;
91
        signal  exception_0 : std_logic;
92
        signal  invalid_0 : std_logic;
93
 
94
        signal  add_enable_0 : std_logic;
95
        signal  add_enable_1 : std_logic;
96
        signal  add_enable : std_logic;
97
        signal  sub_enable_0 : std_logic;
98
        signal  sub_enable_1 : std_logic;
99
        signal  sub_enable : std_logic;
100
        signal  mul_enable : std_logic;
101
        signal  div_enable : std_logic;
102
        signal  except_enable : std_logic;
103
        signal  sum_out : std_logic_vector(55 downto 0);
104
        signal  diff_out : std_logic_vector(55 downto 0);
105
        signal  addsub_out : std_logic_vector(55 downto 0);
106
        signal  mul_out : std_logic_vector(55 downto 0);
107
        signal  div_out : std_logic_vector(55 downto 0);
108
        signal  mantissa_round : std_logic_vector(55 downto 0);
109
        signal  exp_add_out : std_logic_vector(10 downto 0);
110
        signal  exp_sub_out : std_logic_vector(10 downto 0);
111
        signal  exp_mul_out : std_logic_vector(11 downto 0);
112
        signal  exp_div_out : std_logic_vector(11 downto 0);
113
        signal  exponent_round : std_logic_vector(11 downto 0);
114
        signal  exp_addsub : std_logic_vector(11 downto 0);
115
        signal  exponent_post_round : std_logic_vector(11 downto 0);
116
        signal  add_sign : std_logic;
117
        signal  sub_sign : std_logic;
118
        signal  mul_sign : std_logic;
119
        signal  div_sign : std_logic;
120
        signal  addsub_sign : std_logic;
121
        signal  sign_round : std_logic;
122
        signal  out_round : std_logic_vector(63 downto 0);
123
        signal  out_except : std_logic_vector(63 downto 0);
124
 
125
        begin
126
 
127
        i_fpu_add: fpu_add
128
                port map (
129
                clk => clk , rst => rst , enable => add_enable , opa => opa_reg , opb => opb_reg ,
130
                sign => add_sign , sum_3 => sum_out , exponent_2 => exp_add_out);
131
 
132
        i_fpu_sub: fpu_sub
133
                port map (
134
                clk => clk , rst => rst , enable => sub_enable , opa => opa_reg , opb => opb_reg ,
135
                fpu_op => fpu_op_reg , sign => sub_sign , diff_2 => diff_out ,
136
                exponent_2 => exp_sub_out);
137
 
138
        i_fpu_mul: fpu_mul
139
                port map (
140
                clk => clk , rst => rst , enable => mul_enable , opa => opa_reg , opb => opb_reg ,
141
                sign => mul_sign , product_7 => mul_out , exponent_5 => exp_mul_out);
142
 
143
        i_fpu_div: fpu_div
144
                port map (
145
                clk => clk , rst => rst , enable => div_enable , opa => opa_reg , opb => opb_reg ,
146
                sign => div_sign , mantissa_7 => div_out , exponent_out => exp_div_out);
147
 
148
        i_fpu_round: fpu_round
149
                port map (
150
                clk => clk , rst => rst , enable => op_enable ,         round_mode => rmode_reg ,
151
                sign_term => sign_round , mantissa_term => mantissa_round ,  exponent_term => exponent_round ,
152
                round_out => out_round , exponent_final => exponent_post_round);
153
 
154
        i_fpu_exceptions: fpu_exceptions
155
                port map (
156
                clk => clk , rst => rst , enable => op_enable , rmode => rmode_reg ,
157
                opa => opa_reg , opb => opb_reg ,
158
                in_except => out_round ,  exponent_in => exponent_post_round ,
159
                mantissa_in => mantissa_round(1 downto 0) , fpu_op => fpu_op_reg , out_fp => out_except ,
160
                ex_enable => except_enable , underflow => underflow_0 , overflow => overflow_0 ,
161
                inexact => inexact_0 , exception => exception_0 , invalid => invalid_0);
162
 
163
        count_busy <= '1' when (count_ready <= count_cycles) else '0';
164
 
165
        add_enable_0  <= '1' when fpu_op_reg = "000" and (opa_reg(63) xor opb_reg(63)) = '0' else '0';
166
        add_enable_1  <= '1' when (fpu_op_reg = "001") and (opa_reg(63) xor opb_reg(63)) = '1' else '0';
167
        sub_enable_0  <= '1' when (fpu_op_reg = "000") and (opa_reg(63) xor opb_reg(63)) = '1' else '0';
168
        sub_enable_1  <= '1' when (fpu_op_reg = "001") and (opa_reg(63) xor opb_reg(63)) = '0' else '0';
169
 
170
        process
171
        begin
172
        wait until clk'event and clk = '1';
173
                if (rst = '1') then
174
                        mantissa_round <= (others =>'0');
175
                        exponent_round <= (others =>'0');
176
                        sign_round <= '0';
177
                        count_cycles <= (others =>'0');
178
                else
179
                        if (fpu_op_reg = "000") then -- add
180
                                mantissa_round <= addsub_out;
181
                                exponent_round <= exp_addsub;
182
                                sign_round <= addsub_sign;
183
                                count_cycles <= "0010100"; -- 20
184
                        elsif (fpu_op_reg = "001") then -- subtract
185
                                mantissa_round <= addsub_out;
186
                                exponent_round <= exp_addsub;
187
                                sign_round <= addsub_sign;
188
                                count_cycles <= "0010101"; -- 21
189
                        elsif (fpu_op_reg = "010") then
190
                                mantissa_round <= mul_out;
191
                                exponent_round <= exp_mul_out;
192
                                sign_round <= mul_sign;
193
                                count_cycles <= "0011000"; -- 24        
194
                        elsif (fpu_op_reg = "011") then
195
                                mantissa_round <= div_out;
196
                                exponent_round <= exp_div_out;
197
                                sign_round <= div_sign;
198
                                count_cycles <= "1000111"; -- 71
199
                        else
200
                                mantissa_round <= (others =>'0');
201
                                exponent_round <= (others =>'0');
202
                                sign_round <= '0';
203
                                count_cycles <= (others =>'0');
204
                        end if;
205
                end if;
206
        end process;
207
 
208
 
209
 
210
        process
211
        begin
212
        wait until clk'event and clk = '1';
213
                if (rst = '1') then
214
                        add_enable <= '0';
215
                        sub_enable <= '0';
216
                        mul_enable <= '0';
217
                        div_enable <= '0';
218
                        addsub_out <= (others =>'0');
219
                        addsub_sign <= '0';
220
                        exp_addsub <= (others =>'0');
221
                else
222
                        if ((add_enable_0 = '1' or add_enable_1 = '1') and op_enable= '1') then
223
                                add_enable <= '1';
224
                        else
225
                                add_enable <= '0';
226
                        end if;
227
                        if ((sub_enable_0 = '1' or sub_enable_1 = '1') and op_enable = '1') then
228
                                sub_enable <= '1';
229
                        else
230
                                sub_enable <= '0';
231
                        end if;
232
                        if fpu_op_reg = "010" and op_enable = '1' then
233
                                mul_enable <= '1';
234
                        else
235
                                mul_enable <= '0';
236
                        end if;
237
                        if fpu_op_reg = "011" and op_enable = '1' and enable_reg_3 = '1' then
238
                                div_enable <= '1';
239
                        else
240
                                div_enable <= '0';
241
                        end if;  -- div_enable needs to be high for two clock cycles
242
                        if add_enable = '1' then
243
                                addsub_out <= sum_out;
244
                                addsub_sign <= add_sign;
245
                                exp_addsub <= '0' & exp_add_out;
246
                        else
247
                                addsub_out <= diff_out;
248
                                addsub_sign <= sub_sign;
249
                                exp_addsub <= '0' & exp_sub_out;
250
                        end if;
251
                end if;
252
        end process;
253
 
254
        process
255
        begin
256
        wait until clk'event and clk = '1';
257
                if (rst = '1') then
258
                        count_ready <= (others =>'0');
259
                elsif (enable_reg_1 = '1') then
260
                        count_ready <= (others =>'0');
261
                elsif (count_busy = '1') then
262
                        count_ready <= count_ready + "0000001";
263
                end if;
264
        end process;
265
 
266
        process
267
        begin
268
        wait until clk'event and clk = '1';
269
                if (rst = '1') then
270
                        enable_reg <= '0';
271
                        enable_reg_1 <= '0';
272
                        enable_reg_2 <= '0';
273
                        enable_reg_3 <= '0';
274
                else
275
                        enable_reg <= enable;
276
                        if enable = '1' and enable_reg = '0' then
277
                                enable_reg_1 <= '1';
278
                        else
279
                                enable_reg_1 <= '0';
280
                        end if;
281
                        enable_reg_2 <= enable_reg_1;
282
                        if enable_reg_1 = '1' or enable_reg_2 = '1' then
283
                                enable_reg_3 <= '1';
284
                        else
285
                                enable_reg_3 <= '0';
286
                        end if;
287
                end if;
288
        end process;
289
 
290
        process
291
        begin
292
        wait until clk'event and clk = '1';
293
                if (rst = '1') then
294
                        opa_reg <= (others =>'0');
295
                        opb_reg <= (others =>'0');
296
                        fpu_op_reg <= (others =>'0');
297
                        rmode_reg <= (others =>'0');
298
                        op_enable <= '0';
299
                elsif (enable_reg_1 = '1') then
300
                        opa_reg <= opa;
301
                        opb_reg <= opb;
302
                        fpu_op_reg <= fpu_op;
303
                        rmode_reg <= rmode;
304
                        op_enable <= '1';
305
                end if;
306
        end process;
307
 
308
        process
309
        begin
310
        wait until clk'event and clk = '1';
311
                if (rst = '1') then
312
                        ready_0 <= '0';
313
                        ready_1 <= '0';
314
                        ready <= '0';
315
                elsif (enable_reg_1 = '1') then
316
                        ready_0 <= '0';
317
                        ready_1 <= '0';
318
                        ready <= '0';
319
                else
320
                        ready_0 <= not count_busy;
321
                        ready_1 <= ready_0;
322
                        ready <= ready_1;
323
                end if;
324
        end process;
325
 
326
        process
327
        begin
328
        wait until clk'event and clk = '1';
329
                if (rst = '1') then
330
                        underflow <= '0';
331
                        overflow <= '0';
332
                        inexact <= '0';
333
                        exception <= '0';
334
                        invalid <= '0';
335
                        out_fp <= (others =>'0');
336
                elsif (ready_1 = '1') then
337
                        underflow <= underflow_0;
338
                        overflow <= overflow_0;
339
                        inexact <= inexact_0;
340
                        exception <= exception_0;
341
                        invalid <= invalid_0;
342
                        if except_enable = '1' then
343
                                out_fp <= out_except;
344
                        else
345
                                out_fp <= out_round;
346
                        end if;
347
                end if;
348
        end process;
349
        end rtl;

powered by: WebSVN 2.1.0

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