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

Subversion Repositories plasma_fpu

[/] [plasma_fpu/] [trunk/] [src/] [fpu/] [plasma_fpu_alu.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 __alexs__
-- --------------------------------------------------------------------------
2
-- >>>>>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<<<<
3
-- --------------------------------------------------------------------------
4
-- TITLE:       Plasma FPU ALU
5
-- AUTHORS:     Maximilian Reuter (maximilian.reuter@fs-etit.de)
6
--              Alex Schoenberger (Alex.Schoenberger@ies.tu-darmstadt.de)
7
-- COMMENT:     This project is based on Plasma CPU core by Steve Rhoads
8
--
9
-- www.ies.tu-darmstadt.de
10
-- TU Darmstadt
11
-- Institute for Integrated Systems
12
-- Merckstr. 25
13
-- 
14
-- 64283 Darmstadt - GERMANY
15
-- --------------------------------------------------------------------------
16
-- PROJECT:       Plasma CPU core with FPU
17
-- FILENAME:      plasma_fpu_alu.vhd
18
-- --------------------------------------------------------------------------
19
-- COPYRIGHT: 
20
--  This project is distributed by GPLv2.0
21
--  Software placed into the public domain by the author.
22
--  Software 'as is' without warranty.  Author liable for nothing.
23
-- --------------------------------------------------------------------------
24
-- DESCRIPTION
25
--    implementation of FPU ALU operations using FLI interface of ModelSIM
26
--
27
--    NOT SYNTHESIZABLE
28
--
29
----------------------------------------------------------------------------
30
-- Revision History
31
-- --------------------------------------------------------------------------
32
-- Revision   Date    Author     CHANGES
33
-- 1.0       4/2015    MR         initial
34
-- 2.0       5/2015    AS         changed to plasma coding style 
35
-- --------------------------------------------------------------------------
36
library IEEE;
37
  use IEEE.std_logic_1164.ALL;
38
  use IEEE.numeric_std.ALL;
39
 
40
library FLOATFIXLIB;
41
  use FLOATFIXLIB.fixed_float_types.all;
42
  use FLOATFIXLIB.float_pkg.all;
43
 
44
library PLASMA;
45
  use PLASMA.mips_instruction_set.ALL;
46
  use PLASMA.plasma_pack.ALL;
47
 
48
entity plasma_fpu_alu is
49
  port (
50
    control                   : in  t_main_control;
51
    -- INPUT
52
    alu_a_in                  : in  t_plasma_dword;
53
    alu_b_in                  : in  t_plasma_dword;
54
 
55
    -- CONTROL
56
    fpu_ctrl                  : in  t_fpu_ctrl;
57
    round_mode                : in  t_fpu_rm;
58
 
59
    -- STATUS
60
    cause_e                   : out std_logic;
61
    cause                     : out t_fpu_flags;
62
 
63
    -- OUTPUT
64
    alu_out                   : out t_plasma_dword
65
  );
66
end entity plasma_fpu_alu;
67
 
68
 
69
-- ____ _    ____ ____ ___ ____ _ _  _ _    _ ___     ____ _  _ _    _   _ 
70
-- |___ |    |  | |__|  |  |___ |  \/  |    | |__]    |  | |\ | |     \_/  
71
-- |    |___ |__| |  |  |  |    | _/\_ |___ | |__]    |__| | \| |___   |   
72
--
73
-- use only floatfixlibrary
74
--
75
architecture fphdl_plasma_fpu_alu of plasma_fpu_alu is
76
  --
77
  -- intern calculation result
78
  --
79
  signal i_result         : t_plasma_dword  := (others => '0');
80
 
81
  --
82
  -- single precision parts
83
  --
84
  alias alu_a_in_S        : t_plasma_word is alu_a_in(PLASMA_DATA_WIDTH - 1 downto 0);
85
  alias alu_b_in_S        : t_plasma_word is alu_b_in(PLASMA_DATA_WIDTH - 1 downto 0);
86
 
87
  alias i_result_S        : t_plasma_word is i_result(PLASMA_DATA_WIDTH - 1 downto 0);
88
 
89
  --
90
  -- rouund type
91
  --
92
  signal rm               : round_type;
93
 
94
begin
95
  --
96
  -- define round mode
97
  --
98
  with round_mode select
99
    rm         <= round_zero      when "01",
100
                  round_inf       when "10",
101
                  round_neginf    when "11",
102
                  round_nearest   when others;
103
 
104
  -- ____ ____ _    ____ _  _ _    ____ ___ ____ 
105
  -- |    |__| |    |    |  | |    |__|  |  |___ 
106
  -- |___ |  | |___ |___ |__| |___ |  |  |  |___ 
107
  --
108
  -- decode operation and call extern function
109
  --
110
  cacl_proc:process( fpu_ctrl, alu_a_in, alu_b_in, rm )
111
  --cacl_proc:process( control.clk )
112
    --
113
    -- FLI INTERFACE
114
    --
115
    variable func               : integer;
116
    variable double             : integer;
117
 
118
    variable real_a_in          : real;
119
    variable real_b_in          : real;
120
    variable real_out           : real;
121
 
122
    --
123
    -- special values
124
    --
125
    variable    class_a         : valid_fpstate;
126
    variable    class_b         : valid_fpstate;
127
    variable    class_out       : valid_fpstate;
128
 
129
  begin
130
    -- if rising_edge( control.clk ) then
131
    --
132
    -- DEFAULT VALUES
133
    --
134
    -- result
135
    i_result(63 downto 32)      <= PLASMA_ZERO_WORD;
136
    i_result_S                  <= alu_a_in_S;
137
 
138
    --
139
    -- unimplemented instruction flag
140
    --
141
    cause_e                     <= '0';       -- not active
142
 
143
    --
144
    -- DECODE
145
    --
146
    case fpu_ctrl.operation is
147
 
148
      -- ############# PASS INPUT ############
149
      when MIPS_FUNC_FMT_MOV    =>
150
 
151
      -- ############# CONVERT TO SINGLE #####
152
      when MIPS_FUNC_FMT_CVTS   =>
153
 
154
        if fpu_ctrl.fix = '1' then                                                            -- integer -> single
155
          i_result_S  <= to_slv( to_Float( arg            => signed( alu_a_in_S ),
156
                                           exponent_width => 8,
157
                                           fraction_width => 23) );
158
        else                                                                                  -- double -> single
159
          i_result_S  <= to_slv( to_Float32( Float64(alu_a_in) ) );
160
        end if;
161
 
162
 
163
      -- ############# CONVERT TO DOUBLE #####
164
      when MIPS_FUNC_FMT_CVTD   =>
165
 
166
        if fpu_ctrl.fix = '1' then                                                            -- integer -> double
167
          i_result    <= to_slv( to_Float( arg            => signed( alu_a_in_S ),
168
                                           exponent_width => 11,
169
                                           fraction_width => 52) );
170
        else                                                                                  -- single -> double
171
          i_result    <= to_slv( to_Float64( Float32(alu_a_in_S) ) );
172
        end if;
173
 
174
      -- ############# CONVERT TO WORD #######
175
      when MIPS_FUNC_FMT_CVTW   =>
176
 
177
        if fpu_ctrl.double = '1' then                                                         -- double -> integer
178
          i_result_S  <= std_logic_vector( to_signed( to_integer(Float64(alu_a_in)),
179
                                                      PLASMA_DATA_WIDTH) );
180
        else                                                                                  -- single -> integer
181
          i_result_S  <= std_logic_vector( to_signed( to_integer(Float32(alu_a_in_S)),
182
                                                      PLASMA_DATA_WIDTH) );
183
        end if;
184
 
185
      -- ############# CACLUATION ############
186
      when MIPS_FUNC_FMT_ADD    =>
187
 
188
        if fpu_ctrl.double = '1' then
189
          i_result    <= to_slv( add(       l => Float64(alu_a_in),   r => Float64(alu_b_in),   round_style => rm ));
190
        else
191
          i_result_S  <= to_slv( add(       l => Float32(alu_a_in_S), r => Float32(alu_b_in_S), round_style => rm ));
192
        end if;
193
 
194
      when MIPS_FUNC_FMT_SUB    =>
195
 
196
        if fpu_ctrl.double = '1' then
197
          i_result    <= to_slv( subtract(  l => Float64(alu_a_in),   r => Float64(alu_b_in),   round_style => rm ));
198
        else
199
          i_result_S  <= to_slv( subtract(  l => Float32(alu_a_in_S), r => Float32(alu_b_in_S), round_style => rm ));
200
        end if;
201
 
202
      when MIPS_FUNC_FMT_MUL    =>
203
 
204
        if fpu_ctrl.double = '1' then
205
          i_result    <= to_slv( multiply(  l => Float64(alu_a_in),   r => Float64(alu_b_in),   round_style => rm ));
206
        else
207
          i_result_S  <= to_slv( multiply(  l => Float32(alu_a_in_S), r => Float32(alu_b_in_S), round_style => rm ));
208
        end if;
209
 
210
      when MIPS_FUNC_FMT_DIV    =>
211
 
212
        if fpu_ctrl.double = '1' then
213
          i_result    <= to_slv( divide(    l => Float64(alu_a_in),   r => Float64(alu_b_in),   round_style => rm ));
214
        else
215
          i_result_S  <= to_slv( divide(    l => Float32(alu_a_in_S), r => Float32(alu_b_in_S), round_style => rm ));
216
        end if;
217
 
218
      when MIPS_FUNC_FMT_SQRT   =>
219
 
220
        if fpu_ctrl.double = '1' then
221
          i_result    <= to_slv( sqrt(      arg => Float64(alu_a_in),                           round_style => rm ));
222
        else
223
          i_result_S  <= to_slv( sqrt(      arg => Float32(alu_a_in_S),                         round_style => rm ));
224
        end if;
225
 
226
      when MIPS_FUNC_FMT_ABS    =>
227
 
228
        if fpu_ctrl.double = '1' then
229
          i_result    <= to_slv( abs(              Float64(alu_a_in)   ));
230
        else
231
          i_result_S  <= to_slv( abs(              Float32(alu_a_in_S) ));
232
        end if;
233
 
234
      when MIPS_FUNC_FMT_NEG    =>
235
 
236
        if fpu_ctrl.double = '1' then
237
          i_result    <= to_slv( -(                Float64(alu_a_in)   ));
238
        else
239
          i_result_S  <= to_slv( -(                Float32(alu_a_in_S) ));
240
        end if;
241
 
242
      when others               =>
243
 
244
        if not std_match( fpu_ctrl.operation, MIPS_FUNC_FMT_COND ) then                       -- check for comparator instruction
245
          cause_e        <= '1';                                                              -- if not -> unimplemented instruction
246
        end if;
247
 
248
    end case;
249
 
250
    -- ALU Status Bits
251
    --e: Unimplemented -> set before
252
    --v: Invalid
253
    --z: Divide by zero
254
    --o: Overflow
255
    --u: Underflow
256
    --i: Inexact result (denormalized)
257
    --
258
    -- default values
259
    --
260
    cause         <= ('0', '0', '0', '0', '0');
261
 
262
    if fpu_ctrl.double = '1' then
263
      class_a   := classFP( Float64( alu_a_in ) );
264
      class_b   := classFP( Float64( alu_b_in ) );
265
      class_out := classFP( to_Float( arg   => real_out, exponent_width => 11, fraction_width => 52) );
266
    else
267
      class_a   := classFP( Float32( alu_a_in_S ) );
268
      class_b   := classFP( Float32( alu_b_in_S ) );
269
      class_out := classFP( to_Float( arg   => real_out, exponent_width => 8,  fraction_width => 23) );
270
    end if;
271
 
272
    --
273
    -- CLASS OF 1. INPUT
274
    --
275
    case class_a is
276
      when neg_zero | pos_zero   => if fpu_ctrl.operation = MIPS_FUNC_FMT_DIV then cause.z <= '1'; end if;
277
      when nan      | quiet_nan  => cause.v  <= '1';
278
                                    if fpu_ctrl.double = '1' then i_result    <= to_slv(nanfp(11,52));
279
                                                             else i_result_S  <= to_slv(nanfp( 8,23)); end if;
280
      when others =>
281
    end case;
282
 
283
    --
284
    -- CLASS OF 2. INPUT
285
    --
286
    case class_b is
287
      when neg_zero | pos_zero   => if fpu_ctrl.operation = MIPS_FUNC_FMT_DIV then cause.z <= '1'; end if;
288
      when nan      | quiet_nan  => cause.v  <= '1';
289
                                    if fpu_ctrl.double = '1' then i_result    <= to_slv(nanfp(11,52));
290
                                                             else i_result_S  <= to_slv(nanfp( 8,23)); end if;
291
      when others =>
292
    end case;
293
 
294
    --
295
    -- CLASS OF OUTPUT
296
    --
297
    case class_out is
298
      when pos_inf      | neg_inf       =>  cause.o <= '1'; cause.i <= '1';
299
      when pos_denormal | neg_denormal  =>  cause.u <= '1'; cause.i <= '1';
300
      when others   =>
301
    end case;
302
 
303
    -- end if;
304
  end process;
305
 
306
  --
307
  -- OUTPUT
308
  --
309
  alu_out       <= i_result;
310
 
311
end architecture fphdl_plasma_fpu_alu;

powered by: WebSVN 2.1.0

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