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

Subversion Repositories openfpu64

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 bro
-------------------------------------------------------------------------------
2
-- Project    : openFPU64 - a double precision FPU (Toplevel Modul for Avalon)
3
-------------------------------------------------------------------------------
4
-- File       : openfpu64.vhd
5
-- Author     : Peter Huewe  <peterhuewe@gmx.de>
6
-- Created    : 2010-02-09
7
-- Last update: 2010-04-19
8
-- Platform   : CycloneII, CycloneIII.
9
-- Standard   : VHDL'87
10
-------------------------------------------------------------------------------
11
-- Description: This module contains the bus logic for the Avalon Interface of 
12
--              the openFPU64.
13
--              the openFPU64 currently features: 
14
--                    - double precision
15
--                    - Addition/Subtraction
16
--                    - Multiplication
17
--                    - rounding (to nearest even)
18
--                    - subnormals/denormals
19
--                    - verified against IEEE754
20
--              New algorithms can be added easily, just modify the code marked 
21
--                    with ADD_ALGORITHMS_HERE
22
--              Everything marked with FUTURE is not yet implemented, 
23
--                    but already added for easier transition.
24
-------------------------------------------------------------------------------
25
-- Copyright (c) 2010 
26
-------------------------------------------------------------------------------
27
-- Licence: gpl v3 - see licence.txt
28
-------------------------------------------------------------------------------
29
 
30
library ieee;
31
use ieee.std_logic_1164.all;
32
use ieee.numeric_std.all;
33
use work.fpu_package.all;               -- contains import defines.
34
 
35
-------------------------------------------------------------------------------
36
 
37
entity openFPU64 is
38
  port(
39
    reset_n : in std_logic := '0';      -- reset, active low
40
    read    : in std_logic := '0';      -- indicates a read transfer (from fpu)
41
    write   : in std_logic := '1';      -- indicates a write tranfer (to fpu)
42
 
43
    -- address register, specifies where data comes from or is written to, #
44
    -- and also contains the desired operation while writing first operands high word
45
    -- see constants in fpu_package for more details
46
    address : in std_logic_vector (4 downto 0) := (others => '0');
47
 
48
    --readdata result (FUTURE: and exceptions), transfers hi and low words in 2 cycles
49
    readdata  : out std_logic_vector(31 downto 0) := (others => '0');
50
    writedata : in  std_logic_vector(31 downto 0) := (others => '0');  --operands and operator,2 cycles
51
 
52
    -- this signal indicates whether slave is stilly busy. When signal is asserted, bus signals have to remain stable
53
    -- CAUTION: Master may initiate a transfer though!
54
    waitrequest   : out std_logic := '0';
55
    begintransfer : in  std_logic := '0';  -- Master initiates a new transfer
56
    clk           : in  std_logic := '0'   -- clock
57
    );
58
end openFPU64;
59
 
60
-------------------------------------------------------------------------------
61
 
62
architecture rtl of openFPU64 is
63
  -----------------------------------------------------------------------------
64
  -- Internal signal declarations
65
  -----------------------------------------------------------------------------
66
  -- Internal Floating Point format S eEEE EEEE EEEE bOhM....MRGt
67
  -- S Sign bit 
68
  -- e xtra Exponent bit        (12)
69
  -- E biased exponent          (11 downto 0)
70
  -- b borrow for Subtraction   (57)
71
  -- O Overflow                 (56)
72
  -- h Hiddenbit                (55)
73
  -- M Mantissa bits            (54 downto 3)
74
  -- R Round bit                (2)
75
  -- G Guard bit                (1)
76
  -- t Sticky bit               (0)
77
 
78
 
79
  signal sign_a, sign_b                       : std_logic;  -- signs of first/second operand
80
  signal exponent_a, exponent_b               : std_logic_vector (11 downto 0);  -- exponents of first/second operand
81
  signal mantissa_a, mantissa_b               : std_logic_vector (57 downto 0);  -- mantissas of first/second operand
82
  signal iwaitrequest                         : std_logic;  -- internal signal waitrequest, is connected to waitrequest.
83
  signal started                              : std_logic;  -- calculation can begin
84
  signal rounding_needed_1, rounding_needed_2 : std_logic;  -- FUTURE signal which indicates if rounding is necessary.
85
 
86
  signal opmode     : std_logic_vector (2 downto 0);  -- keeps value of operation.
87
  -- The operation is encoded in the address, for better readability we define two aliases to split the
88
  -- register address from the desired operation
89
  alias operation   : std_logic_vector (2 downto 0) is address(4 downto 2);  -- desired operation -> fpu_package.vhd
90
  alias op_register : std_logic_vector (1 downto 0) is address (1 downto 0);  -- register address of operand
91
 
92
 
93
  -- the next few signals are used for connecting components,
94
  -- if you like to add your own algorithm, please specify the necessary signals here,
95
  -- and document their usage.
96
  -- Notes: Add/Sub are one component, so some signals are shared.
97
  --         By using this technique a tristate bus for the components is avoided
98
-- ADD_ALGORITHMS_HERE --
99
  signal mode_1                         : std_logic;  -- ADD/SUB, switches between Addition ('0') and Subtraction ('1')
100
  signal cs_1, cs_2                     : std_logic;  -- chip select for each operation
101
  signal valid_1, valid_2               : std_logic;  -- operation asserts this if it has finished its calculation
102
  signal sign_res_1, sign_res_2         : std_logic;  -- sign of result for each operation.
103
  signal exponent_res_1, exponent_res_2 : std_logic_vector (11 downto 0);  -- exponent of result for each operation
104
  signal mantissa_res_1, mantissa_res_2 : std_logic_vector(57 downto 0);  -- mantissa of result, for each operation
105
-- ADD_ALGORITHMS_HERE_END--
106
 
107
 
108
  -----------------------------------------------------------------------------
109
  -- Component declarations
110
  -----------------------------------------------------------------------------
111
 
112
  -- Add/Sub component, reset active low
113
  component fpu_add
114
    port (
115
      -- input operands
116
      sign_a, sign_b         : in  std_logic;
117
      exponent_a, exponent_b : in  std_logic_vector (11 downto 0);
118
      mantissa_a, mantissa_b : in  std_logic_vector (57 downto 0);
119
      -- output result
120
      sign_res               : out std_logic;
121
      exponent_res           : out std_logic_vector(11 downto 0);
122
      mantissa_res           : out std_logic_vector (57 downto 0);
123
      -- misc signals
124
      rounding_needed        : out std_logic;   -- FUTURE
125
      mode                   : in  std_logic;   -- Switch mode Add=0 Sub=1
126
      cs                     : in  std_logic;   -- Chip Select
127
      valid                  : out std_logic;   -- calculation is finished
128
      clk                    : in  std_logic;   -- Clock
129
      reset_n                : in  std_logic);  -- reset active low
130
  end component;
131
 
132
  -- Multiplication unit
133
  -- FUTURE: can be replaced by other implementations of Multiplication,
134
  --     e.g. one that uses only one embedded Multiplier, see fpu_mul_single.vhd
135
  --     Interface should remain stable for all implementations
136
  component fpu_mul
137
    port (
138
      -- input operands
139
      sign_a, sign_b         : in  std_logic;
140
      exponent_a, exponent_b : in  std_logic_vector (11 downto 0);
141
      mantissa_a, mantissa_b : in  std_logic_vector (57 downto 0);
142
      -- output results
143
      sign_res               : out std_logic;
144
      exponent_res           : out std_logic_vector(11 downto 0);
145
      mantissa_res           : out std_logic_vector (57 downto 0);
146
-- misc signals
147
      rounding_needed        : out std_logic;   -- FUTURE
148
      valid                  : out std_logic;   -- calculation is finished
149
      cs                     : in  std_logic;   -- Chip Select
150
      clk                    : in  std_logic;   -- Clock
151
      reset_n                : in  std_logic);  -- Reset active low
152
  end component;
153
 
154
 
155
-----------------------------------------------------------------------------
156
-- Component instantiations
157
-- connect everything
158
-----------------------------------------------------------------------------
159
begin
160
  fpu_addsub_1 : fpu_add
161
    port map (
162
      sign_a          => sign_a,
163
      sign_b          => sign_b,
164
      exponent_a      => exponent_a,
165
      exponent_b      => exponent_b,
166
      mantissa_a      => mantissa_a,
167
      mantissa_b      => mantissa_b,
168
      sign_res        => sign_res_1,
169
      exponent_res    => exponent_res_1,
170
      mantissa_res    => mantissa_res_1,
171
      rounding_needed => rounding_needed_1,
172
      mode            => mode_1,
173
      cs              => cs_1,
174
      valid           => valid_1,
175
      clk             => clk,
176
      reset_n         => reset_n);
177
 
178
  fpu_mul_1 : fpu_mul
179
    port map (
180
      clk             => clk,
181
      reset_n         => reset_n,
182
      cs              => cs_2,
183
      sign_a          => sign_a,
184
      sign_b          => sign_b,
185
      exponent_a      => exponent_a,
186
      exponent_b      => exponent_b,
187
      mantissa_a      => mantissa_a,
188
      mantissa_b      => mantissa_b,
189
      sign_res        => sign_res_2,
190
      exponent_res    => exponent_res_2,
191
      mantissa_res    => mantissa_res_2,
192
      rounding_needed => rounding_needed_2,
193
      valid           => valid_2);
194
 
195
-- purpose: Implements the Avalon logic and transfers data from/to submodules
196
-- inputs : clk, reset_n,read, write, address, writedata, begintransfer
197
-- outputs: readdata, waitrequest
198
-- Note: Process is not coded using states on purpose in order to prevent 
199
--         lockups in case of bus resets or undefined accesses
200
  avalon_bus_logic : process (clk, reset_n)
201
  begin
202
    if reset_n = '0' then  -- active low, switch of subcomponents, reset everything
203
      cs_1         <= '0';
204
      cs_2         <= '0';
205
      iwaitrequest <= '0';
206
      started      <= '0';
207
      opmode       <= (others => '0');
208
      mantissa_a   <= (others => '0');
209
      mantissa_b   <= (others => '0');
210
      exponent_a   <= (others => '0');
211
      exponent_b   <= (others => '0');
212
      sign_a       <= '0';
213
      sign_b       <= '0';
214
      readdata     <= x"AAAAC0C0";
215
    elsif rising_edge(clk) then
216
      waitrequest <= iwaitrequest;
217
      cs_1        <= cs_1;
218
      cs_2        <= cs_2;
219
      opmode      <= opmode;
220
      mantissa_a  <= mantissa_a;
221
      mantissa_b  <= mantissa_b;
222
      exponent_a  <= exponent_a;
223
      exponent_b  <= exponent_b;
224
      sign_a      <= sign_a;
225
      sign_b      <= sign_b;
226
 
227
      -- Dummy value which indicates wrong reads, deadbeef was already taken
228
      readdata <= x"AAAAC0C0";
229
      started  <= started;
230
 
231
      if started = '0'  -- calculation is in progress, keep signals
232
      then
233
        iwaitrequest <= '0';
234
      else
235
        iwaitrequest <= '1';
236
      end if;
237
 
238
      if begintransfer = '1' and write = '1' then  -- new write transfert
239
        case op_register is
240
          -- hi word is written, populate first operand and set opmode to desired operation
241
          when addr_a_hi =>
242
            sign_a     <= writedata(31);
243
            exponent_a <= '0' & writedata(30 downto 20);
244
            -- check for denormals, if not, set _h_idden bit in internal format.
245
            if unsigned(writedata(30 downto 20)) = ZEROS(30 downto 20) then
246
              mantissa_a(57 downto 35) <= "000" & writedata(19 downto 0);
247
            else
248
              mantissa_a(57 downto 35) <= "001" & writedata(19 downto 0);
249
            end if;
250
            opmode <= operation;
251
 
252
          -- lo word is written, populate rest of mantissa with clear RGS
253
          when addr_a_lo =>
254
            mantissa_a(34 downto 0) <= writedata(31 downto 0) & "000";
255
 
256
          -- hi word of second operand, populate fields  
257
          when addr_b_hi =>
258
            sign_b     <= writedata(31);
259
            exponent_b <= '0' & writedata(30 downto 20);
260
            -- check for denormals, if not, set _h_idden bit in internal format.
261
            if unsigned(writedata(30 downto 20)) = ZEROS(30 downto 20) then
262
              mantissa_b(57 downto 35) <= "000" & writedata(19 downto 0);
263
            else
264
              mantissa_b(57 downto 35) <= "001" & writedata(19 downto 0);
265
            end if;
266
 
267
 
268
          -- lo word is written, populate rest of mantissa with clear RGS
269
          -- after low word is written, calculation starts
270
          when addr_b_lo =>
271
            mantissa_b(34 downto 0) <= writedata(31 downto 0) & "000";
272
            -- perform calculation by enabling component
273
            case opmode is
274
              -- ADD_ALGORITHMS_HERE
275
              when mode_add =>
276
                cs_1   <= '1';
277
                mode_1 <= '0';
278
              when mode_sub =>
279
                cs_1   <= '1';
280
                mode_1 <= '1';
281
                opmode <= mode_add;  -- result will be read from same location
282
              when mode_mul =>
283
                cs_2 <= '1';
284
--                when mode_div =>  -- FUTURE not implemented yet 
285
--                 cs_3             <= '1'; -- FUTURE
286
              -- ADD_ALGORITHMS_HERE_END
287
              when others => null;
288
            end case;
289
            started <= '1';             -- calculation has started
290
          when others => null;
291
        end case;
292
      end if;
293
 
294
      -- results requested
295
      if read = '1' and started = '1' then
296
        if begintransfer = '1' then
297
          iwaitrequest <= '1';
298
          waitrequest  <= '1';
299
        end if;
300
        -- ADD_ALGORITHMS_HERE --
301
        -- if any of the operation returns with a valid result
302
        if valid_1 = '1' or valid_2 = '1' then
303
          -- ADD_ALGORITHMS_HERE_END--
304
          iwaitrequest <= '1';
305
          waitrequest  <= '0';
306
 
307
          -- read hi word of result
308
          if op_register = addr_result_hi then
309
            case opmode is
310
              -- ADD_ALGORITHMS_HERE --
311
              -- generate result, skip internal format bits.
312
              when mode_add => readdata <= sign_res_1 & exponent_res_1 (10 downto 0) & mantissa_res_1(54 downto 35);  -- ADD and SUB
313
              when mode_mul => readdata <= sign_res_2 & exponent_res_2 (10 downto 0) & mantissa_res_2(54 downto 35);
314
              --  when mode_div => readdata <= result_2(63 downto 32); -- not implemented yet
315
              -- ADD_ALGORITHMS_HERE_END--
316
              when others   => null;
317
            end case;
318
 
319
          -- read low word of result
320
          else                          -- op_register = add_result_lo
321
            case opmode is
322
              -- ADD_ALGORITHMS_HERE --
323
              when mode_add => readdata <= mantissa_res_1(34 downto 3);  -- ADD and SUB
324
              when mode_mul => readdata <= mantissa_res_2(34 downto 3);
325
              --  when mode_div => readdata <= result_2(31 downto 0); --Not implemented yet
326
              -- ADD_ALGORITHMS_HERE_END --
327
              when others   => null;
328
            end case;
329
 
330
            -- read is finished, return to "reset_state"
331
            -- ADD_ALGORITHMS_HERE --
332
            cs_1    <= '0';
333
            cs_2    <= '0';
334
            mode_1  <= '0';
335
            -- ADD_ALGORITHMS_HERE_END --
336
            started <= '0';
337
            opmode  <= (others => '0');
338
          end if;
339
        else
340
        end if;
341
      end if;
342
    end if;
343
  end process avalon_bus_logic;
344
end rtl;
345
 
346
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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