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

Subversion Repositories openfpu64

[/] [openfpu64/] [trunk/] [fpu_mul.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 bro
--------------------------------------------------------------------------------
2
-- Project    : openFPU64 Multiplier Component
3
-------------------------------------------------------------------------------
4
-- File       : fpu_mul.vhd
5
-- Author     : Peter Huewe  <peterhuewe@gmx.de>
6
-- Created    : 2010-04-19
7
-- Last update: 2010-04-19
8
-- Standard   : VHDL'87
9
-------------------------------------------------------------------------------
10
-- Description: double precision floating point multiplier component
11
--                     for openFPU64, includes rounding and normalization
12
-- 
13
-------------------------------------------------------------------------------
14
-- Copyright (c) 2010 
15
-------------------------------------------------------------------------------
16
-- License: gplv3, see licence.txt
17
-------------------------------------------------------------------------------
18
library ieee;
19
use ieee.std_logic_1164.all;
20
use ieee.numeric_std.all;
21
use work.fpu_package.all;
22
-------------------------------------------------------------------------------
23
 
24
entity fpu_mul is
25
  port (
26
    clk, reset_n           : in  std_logic;  -- reset = standard active low
27
    cs                     : in  std_logic;  --  mode: 0 = add , 1= sub
28
    sign_a, sign_b         : in  std_logic;  -- sign bits
29
    exponent_a, exponent_b : in  std_logic_vector (11 downto 0);  -- exponents of the operands
30
    mantissa_a, mantissa_b : in  std_logic_vector (57 downto 0);  -- mantissa of operands
31
    sign_res               : out std_logic;
32
    exponent_res           : out std_logic_vector(11 downto 0);
33
    mantissa_res           : out std_logic_vector (57 downto 0);
34
    rounding_needed        : out std_logic;
35
    valid                  : out std_logic
36
    );
37
 
38
end fpu_mul;
39
 
40
-------------------------------------------------------------------------------
41
 
42
architecture rtl of fpu_mul is
43
  -----------------------------------------------------------------------------
44
  -- Internal signal declarations
45
  -----------------------------------------------------------------------------
46
-------------------------------------------------------------------------------
47
-------------------------------------------------------------------------------
48
  signal add_result, add_op_a : unsigned (54 downto 0);
49
  signal add_op_b             : unsigned (12 downto 0);
50
--  signal mul_result           : unsigned(35 downto 0);
51
--  signal mul_op_a, mul_op_b   : unsigned(17 downto 0);
52
  type t_state is (s_calc1, s_calc2, s_calc3, s_finished, s_normalize_right_1, s_load_for_round, s_round, s_load_normalizer_right_2, s_normalize_right_2, s_normalize_left);  -- possible states
53
  signal state                : t_state;  -- current state
54
 
55
  signal exponent_out : std_logic_vector(11 downto 0);
56
  signal tmp_result   : std_logic_vector (57 downto 0);
57
  signal tmp_result2  : std_logic_vector (107 downto 0);
58
 
59
  signal a_is_normal, b_is_normal : std_logic;
60
-----------------------------------------------------------------------------
61
-- Component declarations
62
-----------------------------------------------------------------------------
63
begin
64
----------------------------------------------------------------
65
  -- Component instantiations
66
  -----------------------------------------------------------------------------
67
 
68
  -- purpose: calculates the result of a multiplication
69
  -- type   : combinational
70
  -- inputs : sign_a, sign_b, exponent_a, exponent_b, mantissa_a, mantissa_b
71
  -- outputs: result
72
 
73
  add_result  <= add_op_a + add_op_b;
74
  a_is_normal <= '0' when unsigned(exponent_a(10 downto 0)) = ALL_ZEROS else '1';
75
  b_is_normal <= '0' when unsigned(exponent_b(10 downto 0)) = ALL_ZEROS else '1';
76
 
77
  state_trans : process (clk, reset_n, cs)
78
    variable tmp : unsigned(57 downto 0);
79
  begin  -- process state_trans
80
    rounding_needed <= '1';
81
    if reset_n = '0' then
82
      state        <= s_calc1;
83
      sign_res     <= '0';
84
      valid        <= '0';
85
      exponent_res <= (others => '0');
86
      mantissa_res <= (others => '0');
87
      tmp_result   <= (others => '0');
88
      tmp_result2  <= (others => '0');
89
      add_op_a     <= (others => '0');
90
      add_op_b     <= (others => '0');
91
    elsif rising_edge(clk) then
92
      if cs = '0' then
93
        state        <= s_calc1;
94
        sign_res     <= '0';
95
        valid        <= '0';
96
        exponent_res <= (others => '0');
97
        mantissa_res <= (others => '0');
98
        tmp_result   <= (others => '0');
99
        tmp_result2  <= (others => '0');
100
        add_op_a     <= (others => '0');
101
        add_op_b     <= (others => '0');
102
 
103
      else
104
        sign_res     <= sign_a xor sign_b;
105
        valid        <= '0';
106
        --    result       <= (others => '0');
107
        exponent_res <= exponent_out(11 downto 0);
108
        mantissa_res <= (others => '0');
109
        mantissa_res <= tmp_result;
110
        tmp_result   <= tmp_result;
111
        tmp_result2  <= tmp_result2;
112
        case state is
113
 
114
          -- calculate new exponent and load multiplier
115
          when s_calc1 =>
116
            add_op_a              <= (others => '0');
117
            add_op_b              <= (others => '0');
118
            add_op_a(10 downto 0) <= unsigned(exponent_a(10 downto 0));
119
            add_op_b(10 downto 0) <= unsigned(exponent_b(10 downto 0));
120
            tmp_result2           <= std_logic_vector(unsigned(mantissa_a(56 downto 3)) * unsigned(mantissa_b(56 downto 3)));
121
 
122
            state <= s_calc2;
123
            -- check if one of the operands is zero
124
            if (unsigned(exponent_a (10 downto 0)) = ZEROS(10 downto 0) and unsigned(mantissa_a (56 downto 3)) = ZEROS(56 downto 3))
125
              or (unsigned(exponent_b (10 downto 0)) = ZEROS(10 downto 0) and unsigned(mantissa_b (56 downto 3)) = ZEROS(56 downto 3))
126
            then
127
              exponent_out <= (others => '0');
128
              tmp_result   <= (others => '0');
129
              state        <= s_finished;
130
            end if;
131
 
132
            -- Nan bu Nan :) is A NotANumber
133
            if (unsigned(exponent_a (10 downto 0)) = ONES(10 downto 0) and unsigned(mantissa_a (56 downto 3)) /= ZEROS(56 downto 3))
134
            then
135
              exponent_out <= (others => '1');
136
              tmp_result   <= mantissa_a;
137
              state        <= s_finished;
138
            end if;
139
            -- is B NotANumber
140
            if (unsigned(exponent_b (10 downto 0)) = ONES(10 downto 0) and unsigned(mantissa_b (56 downto 3)) /= ZEROS(56 downto 3))
141
            then
142
              exponent_out <= (others => '1');
143
              tmp_result   <= mantissa_b;
144
              state        <= s_finished;
145
            end if;
146
 
147
 
148
          -- calculate new exponent, part II, subtract bias
149
          when s_calc2 =>
150
            add_op_a (12 downto 0) <= '0'&add_result(11 downto 0);
151
            add_op_b (12 downto 0) <= DOUBLE_BIAS_2COMPLEMENT(12 downto 0);
152
 
153
            state <= s_calc3;
154
 
155
          -- check if new exponent has to be zero, this happens if result is zero or subnormal
156
          -- also select upper 57 bits of multiplication and generate stickybit of lower result
157
          when s_calc3 =>
158
            state <= s_load_for_round;
159
            -- if lower bits != zero, sticky bit is 1
160
            if (unsigned(tmp_result2(49 downto 0)) /= ZEROS(49 downto 0))
161
            then
162
              tmp_result <= std_logic_vector(tmp_result2(106 downto 50)) &'1';
163
            else
164
              tmp_result <= std_logic_vector(tmp_result2(106 downto 50)) &'0';
165
            end if;
166
 
167
            -- Is normalization needed?
168
            if tmp_result2 (105) = '1' then
169
              state <= s_normalize_right_1;
170
            end if;
171
 
172
 
173
            -- check if exponent is out of range
174
            -- if it is in preload adder, maybe we need exponent +1 in next state
175
            exponent_out <= std_logic_vector(add_result(11 downto 0));
176
            add_op_a     <= (others => '0');
177
            add_op_b     <= (others => '0');
178
 
179
            add_op_a(11 downto 0) <= add_result(11 downto 0);
180
            add_op_b(0)           <= '1';
181
            -- overflow
182
            if (add_result(12) = '0' and add_result(11) = '1')
183
            then
184
              exponent_out <= (others => '1');
185
              tmp_result   <= (others => '0');
186
              state        <= s_finished;
187
            end if;
188
            -- lower than subnormal - underflow to zero
189
            if (add_result(12) = '1')
190
              --and (a_is_normal = '0' or b_is_normal = '0'))
191
              or (a_is_normal = '0' and b_is_normal = '0')
192
            then
193
              exponent_out <= (others => '0');
194
              add_op_a     <= (others => '0');
195
              add_op_b     <= (others => '0');
196
              add_op_b(0)  <= '1';
197
              tmp_result   <= (others => '0');
198
              state        <= s_finished;
199
            else
200
            end if;
201
 
202
 
203
 
204
          --Normalization is necessary
205
          when s_normalize_right_1=>
206
            tmp_result(57 downto 1) <= '0'&tmp_result(57 downto 2);
207
            tmp_result(0)           <= tmp_result(1) or tmp_result(0);
208
            exponent_out            <= std_logic_vector(add_result(11 downto 0));
209
 
210
            state <= s_load_for_round;
211
 
212
          -- preload adder with mantissa and 1, maybe we need this for rounding next step
213
          when s_load_for_round =>
214
            add_op_a    <= unsigned(tmp_result(57 downto 3));
215
            add_op_b    <= (others => '0');
216
            add_op_b(0) <= '1';
217
            state       <= s_normalize_left;
218
 
219
          -- shift leading one to correct position
220
          when s_normalize_left=>
221
            state <= s_round;
222
            if tmp_result(55) = '0' and unsigned(exponent_out(11 downto 0)) /= ZEROS(11 downto 0)
223
            then
224
              tmp_result(55 downto 0) <= tmp_result(54 downto 0) & tmp_result(0);
225
              exponent_out            <= std_logic_vector(unsigned(exponent_out) - "1");
226
              state                   <= s_normalize_left;
227
            end if;
228
 
229
          --round if necessary
230
          when s_round=>
231
            case tmp_result(3 downto 0) is
232
              when "0101" => tmp_result(3) <= '1';
233
              when "0110" => tmp_result(3) <= '1';
234
              when "0111" => tmp_result(3) <= '1';
235
 
236
              when "1100" => tmp_result(57 downto 3) <= std_logic_vector(add_result);
237
              when "1101" => tmp_result(57 downto 3) <= std_logic_vector(add_result);
238
              when "1110" => tmp_result(57 downto 3) <= std_logic_vector(add_result);
239
              when "1111" => tmp_result(57 downto 3) <= std_logic_vector(add_result);
240
 
241
              when others => null;      -- others remain unchanged
242
            end case;
243
 
244
 
245
            state <= s_load_normalizer_right_2;
246
 
247
 
248
          -- Check again if Normalization needed, preload adder
249
          when s_load_normalizer_right_2=>
250
            add_op_a              <= (others => '0');
251
            add_op_b              <= (others => '0');
252
            add_op_a(11 downto 0) <= unsigned(exponent_out(11 downto 0));
253
            add_op_b(0)           <= '1';
254
 
255
            state <= s_finished;
256
            if tmp_result(56) = '1' then
257
              state <= s_normalize_right_2;
258
            end if;
259
 
260
 
261
          -- .Normalize
262
          when s_normalize_right_2=>
263
            tmp_result(57 downto 1) <= '0'&tmp_result(57 downto 2);
264
            tmp_result(0)           <= tmp_result(1) or tmp_result(0);
265
            exponent_out            <= std_logic_vector(add_result(11 downto 0));
266
            state                   <= s_finished;
267
 
268
 
269
          -- finished  
270
          when s_finished =>
271
            state <= s_finished;
272
            valid <= '1';
273
 
274
          when others => null;
275
        end case;
276
      end if;
277
    end if;
278
  end process state_trans;
279
end rtl;
280
 
281
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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