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

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [sparc/] [fpu_lth.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 tarookumic
-------------------------------------------------------------------------------
2
--  Copyright (C) 2002 Martin Kasprzyk <m_kasprzyk@altavista.com>
3
--
4
--  This library is free software; you can redistribute it and/or
5
--  modify it under the terms of the GNU Lesser General Public
6
--  License as published by the Free Software Foundation; either
7
--  version 2 of the License, or (at your option) any later version.
8
--
9
-------------------------------------------------------------------------------
10
-- File       : fpu.vhd
11
-- Author     : Martin Kasprzyk <e00mk@efd.lth.se>
12
-------------------------------------------------------------------------------
13
-- Description: A IEEE754 floating point unit for the LEON SPARC processor
14
-------------------------------------------------------------------------------
15
-- Modfied by Jiri Gaisler to:
16
-- * be VHDL-87 compatible 
17
-- * remove ambiguity for std_logic +,-, and > operands.
18
-- * supress 'X' warnings from std_logic_arith packages
19
-- * added bug fixes from Albert Wang (5 Dec 2002)
20
-- * added bug fixes from Albert Wang (16 Dec 2002)
21
-------------------------------------------------------------------------------
22
library IEEE;
23
use ieee.std_logic_1164.all;
24
use ieee.std_logic_arith.all;
25
use ieee.std_logic_unsigned."-";
26
use ieee.std_logic_unsigned."+";
27
use ieee.std_logic_unsigned.">";
28
use work.leon_iface.all;
29
use work.sparcv8.all;
30
 
31
entity fpu_lth is
32
  port(
33
    ss_clock        : in  std_logic;
34
    FpInst          : in  std_logic_vector(9 downto 0);
35
    FpOp            : in  std_logic;
36
    FpLd            : in  std_logic;
37
    Reset           : in  std_logic;
38
    fprf_dout1      : in  std_logic_vector(63 downto 0);
39
    fprf_dout2      : in  std_logic_vector(63 downto 0);
40
    RoundingMode    : in  std_logic_vector(1 downto 0);
41
    FpBusy          : out std_logic;
42
    FracResult      : out std_logic_vector(54 downto 3);
43
    ExpResult       : out std_logic_vector(10 downto 0);
44
    SignResult      : out std_logic;
45
    SNnotDB         : out std_logic;                            -- Not used
46
    Excep           : out std_logic_vector(5 downto 0);
47
    ConditionCodes  : out std_logic_vector(1 downto 0);
48
    ss_scan_mode    : in  std_logic;                            -- Not used
49
    fp_ctl_scan_in  : in  std_logic;                            -- Not used
50
    fp_ctl_scan_out : out std_logic                             -- Not used
51
  );
52
end;
53
 
54
architecture rtl of fpu_lth is
55
 
56
  constant zero : std_logic_vector(63 downto 0) := (others => '0');
57
 
58
-------------------------------------------------------------------------------
59
-- Leading zero counter.
60
-------------------------------------------------------------------------------
61
  procedure lz_counter (
62
    in_vect       : in  std_logic_vector(55 downto 0);
63
    leading_zeros : out std_logic_vector(5 downto 0)) is
64
    variable pos_mask : std_logic_vector(55 downto 0);
65
    variable neg_mask : std_logic_vector(55 downto 0);
66
    variable leading_one : std_logic_vector(55 downto 0);
67
    variable nr_zeros : std_logic_vector(5 downto 0);
68
  begin
69
    -- Find leading one e.g. if in_vect = 00101101 then pos_mask = 00111111
70
    -- and neg_mask = "11100000, performing and gives leading_one = 00100000
71
    pos_mask(55) := in_vect(55);
72
    for i in 54 downto 0 loop
73
      pos_mask(i) := pos_mask(i+1) or in_vect(i);
74
    end loop;
75
    neg_mask := "1" & (not pos_mask(55 downto 1));
76
    leading_one := pos_mask and neg_mask;
77
 
78
    -- Get number of leading zeros from the leading_one vector
79
    nr_zeros := "000000";
80
 
81
    for i in 1 to 55 loop
82
      if (i / 32) /= 0 then
83
        nr_zeros(5) := nr_zeros(5) or leading_one(55-i);
84
      end if;
85
 
86
      if ((i mod 32) / 16) /= 0  then
87
        nr_zeros(4) := nr_zeros(4) or leading_one(55-i);
88
      end if;
89
 
90
      if (((i mod 32) mod 16) / 8) /= 0 then
91
        nr_zeros(3) := nr_zeros(3) or leading_one(55-i);
92
      end if;
93
 
94
      if ((((i mod 32) mod 16) mod 8) / 4) /= 0 then
95
        nr_zeros(2) := nr_zeros(2) or leading_one(55-i);
96
      end if;
97
 
98
      if (((((i mod 32) mod 16) mod 8) mod 4) / 2) /= 0 then
99
        nr_zeros(1) := nr_zeros(1) or leading_one(55-i);
100
      end if;
101
 
102
      if (i mod 2) /= 0 then
103
        nr_zeros(0) := nr_zeros(0) or leading_one(55-i);
104
      end if;
105
    end loop;
106
 
107
    -- Return result
108
    leading_zeros := nr_zeros;
109
  end lz_counter;
110
 
111
-------------------------------------------------------------------------------
112
-- Variable amount right shifter with sticky bit calculation.
113
-------------------------------------------------------------------------------
114
  procedure right_shifter_sticky (
115
    in_vect    : in  std_logic_vector(54 downto 0);
116
    amount     : in  std_logic_vector(5 downto 0);
117
    out_vect   : out std_logic_vector(54 downto 0);
118
    sticky_bit : out std_logic) is
119
    variable after32  : std_logic_vector(54 downto 0);
120
    variable after16  : std_logic_vector(54 downto 0);
121
    variable after8   : std_logic_vector(54 downto 0);
122
    variable after4   : std_logic_vector(54 downto 0);
123
    variable after2   : std_logic_vector(54 downto 0);
124
    variable after1   : std_logic_vector(54 downto 0);
125
    variable sticky32 : std_logic;
126
    variable sticky16 : std_logic;
127
    variable sticky8  : std_logic;
128
    variable sticky4  : std_logic;
129
    variable sticky2  : std_logic;
130
    variable sticky1  : std_logic;
131
  begin
132
    -- If amount(5) = '1' then shift vector 32 positions right
133
    if amount(5) = '1' then
134
      after32 := zero(31 downto 0) & in_vect(54 downto 32);
135
      if in_vect(31 downto 0) /= zero(31 downto 0) then
136
        sticky32 := '1';
137
      else
138
        sticky32 := '0';
139
      end if;
140
    else
141
      after32 := in_vect;
142
      sticky32 := '0';
143
    end if;
144
 
145
    -- If amount(4) = '1' then shift vector 16 positions right
146
    if amount(4) = '1' then
147
      after16 := zero(15 downto 0) & after32(54 downto 16);
148
      if after32(15 downto 0) /= zero(15 downto 0) then
149
        sticky16 := '1';
150
      else
151
        sticky16 := '0';
152
      end if;
153
    else
154
      after16 := after32;
155
      sticky16 := '0';
156
    end if;
157
 
158
    -- If amount(3) = '1' then shift vector 8 positions right
159
    if amount(3) = '1' then
160
      after8 := zero(7 downto 0) & after16(54 downto 8);
161
      if after16(7 downto 0) /= zero(7 downto 0) then
162
        sticky8 := '1';
163
      else
164
        sticky8 := '0';
165
      end if;
166
    else
167
      after8 := after16;
168
      sticky8 := '0';
169
    end if;
170
 
171
    -- If amount(2) = '1' then shift vector 4 positions right
172
    if amount(2) = '1' then
173
      after4 := zero(3 downto 0) & after8(54 downto 4);
174
      if after8(3 downto 0) /= zero(3 downto 0) then
175
        sticky4 := '1';
176
      else
177
        sticky4 := '0';
178
      end if;
179
    else
180
      after4 := after8;
181
      sticky4 := '0';
182
    end if;
183
 
184
    -- If amount(1) = '1' then shift vector 2 positions right
185
    if amount(1) = '1' then
186
      after2 := "00" & after4(54 downto 2);
187
      if after4(1 downto 0) /= "00" then
188
        sticky2 := '1';
189
      else
190
        sticky2 := '0';
191
      end if;
192
    else
193
      after2 := after4;
194
      sticky2 := '0';
195
    end if;
196
 
197
    -- If amount(0) = '1' then shift vector 1 positions right
198
    if amount(0) = '1' then
199
      after1 := "0" & after2(54 downto 1);
200
      sticky1 := after2(0);
201
    else
202
      after1 := after2;
203
      sticky1 := '0';
204
    end if;
205
 
206
    -- Return values
207
    out_vect := after1;
208
    sticky_bit := sticky32 or sticky16 or sticky8 or sticky4 or sticky2 or
209
                 sticky1;
210
  end right_shifter_sticky;
211
 
212
-------------------------------------------------------------------------------
213
-- Variable amount left shifter
214
-------------------------------------------------------------------------------
215
  procedure left_shifter (
216
    in_vect  : in  std_logic_vector(56 downto 0);
217
    amount   : in  std_logic_vector(5 downto 0);
218
    out_vect : out std_logic_vector(56 downto 0)) is
219
    variable after32 : std_logic_vector(56 downto 0);
220
    variable after16 : std_logic_vector(56 downto 0);
221
    variable after8  : std_logic_vector(56 downto 0);
222
    variable after4  : std_logic_vector(56 downto 0);
223
    variable after2  : std_logic_vector(56 downto 0);
224
    variable after1  : std_logic_vector(56 downto 0);
225
  begin
226
    -- If amount(5) = '1' then shift vector 32 positions left
227
    if amount(5) = '1' then
228
      after32 := in_vect(24 downto 0) & zero(31 downto 0);
229
    else
230
      after32 := in_vect;
231
    end if;
232
 
233
    -- If amount(4) = '1' then shift vector 16 positions left
234
    if amount(4) = '1' then
235
      after16 :=  after32(40 downto 0) & zero(15 downto 0);
236
    else
237
      after16 := after32;
238
    end if;
239
 
240
    -- If amount(3) = '1' then shift vector 8 positions left
241
    if amount(3) = '1' then
242
      after8 := after16(48 downto 0) & zero(7 downto 0);
243
    else
244
      after8 := after16;
245
    end if;
246
 
247
    -- If amount(2) = '1' then shift vector 4 positions left
248
    if amount(2) = '1' then
249
      after4 := after8(52 downto 0) & zero(3 downto 0);
250
    else
251
      after4 := after8;
252
    end if;
253
 
254
    -- If amount(1) = '1' then shift vector 2 positions left
255
    if amount(1) = '1' then
256
      after2 := after4(54 downto 0) & "00";
257
    else
258
      after2 := after4;
259
    end if;
260
 
261
    -- If amount(0) = '1' then shift vector 1 positions left
262
    if amount(0) = '1' then
263
      after1 := after2(55 downto 0) & "0";
264
    else
265
      after1 := after2;
266
    end if;
267
 
268
    -- Return value
269
    out_vect := after1;
270
  end left_shifter;
271
 
272
-------------------------------------------------------------------------------
273
-- Declaration of record types used to pass signals between pipeline stages.
274
-------------------------------------------------------------------------------
275
type op_decode_stage_type is record     -- input <-> op_decode
276
  opcode : std_logic_vector(9 downto 0);
277
end record;
278
 
279
type prenorm_stage_type is record       -- op_decode <-> prenorm
280
  sign1      : std_logic;
281
  exp1       : std_logic_vector(10 downto 0);
282
  frac1     : std_logic_vector(51 downto 0);
283
  sign2      : std_logic;
284
  exp2       : std_logic_vector(10 downto 0);
285
  frac2     : std_logic_vector(51 downto 0);
286
  single     : std_logic;               -- Single precision
287
  comp       : std_logic;               -- Compare and set cc
288
  gen_ex     : std_logic;               -- Generate exception if unordered 
289
  op1_denorm : std_logic;
290
  op2_denorm : std_logic;
291
  op1_inf    : std_logic;
292
  op2_inf    : std_logic;
293
  op1_NaN    : std_logic;
294
  op2_NaN    : std_logic;
295
  op1_SNaN   : std_logic;
296
  op2_SNaN   : std_logic;
297
end record;
298
 
299
type addsub_stage_type is record        -- prenorm <-> addsub
300
  sign_a   : std_logic;
301
  a        : std_logic_vector(56 downto 0);
302
  sign_b   : std_logic;
303
  b        : std_logic_vector(56 downto 0);
304
  exp      : std_logic_vector(10 downto 0);
305
  single   : std_logic;                 -- Single precision
306
  comp     : std_logic;                 -- Compare and set cc
307
  gen_ex   : std_logic;                 -- Generate exception if unordered 
308
  swaped   : std_logic;                 -- Operands swaped during pre_norm
309
  op1_inf  : std_logic;
310
  op2_inf  : std_logic;
311
  op1_NaN  : std_logic;
312
  op2_NaN  : std_logic;
313
  op1_SNaN : std_logic;
314
  op2_SNaN : std_logic;
315
end record;
316
 
317
type postnorm_stage_type is record      -- addsub <-> postnorm
318
  frac     : std_logic_vector(56 downto 0);
319
  exp      : std_logic_vector(10 downto 0);
320
  sign     : std_logic;
321
  single   : std_logic;                         -- Single precision
322
  comp     : std_logic;                         -- Compare and set cc  
323
  cc       : std_logic_vector(1 downto 0);      -- Condition codes
324
  exc      : std_logic_vector(4 downto 0);      -- Exceptions
325
  res_inf  : std_logic;
326
  res_NaN  : std_logic;
327
  res_SNaN : std_logic;
328
  res_zero : std_logic;
329
end record;
330
 
331
type roundnorm_stage_type is record     -- postnorm <-> roundnorm
332
  frac     : std_logic_vector(56 downto 0);
333
  exp      : std_logic_vector(10 downto 0);
334
  sign     : std_logic;
335
  single   : std_logic;                         -- Single precision
336
  comp     : std_logic;                         -- Compare and set cc  
337
  cc       : std_logic_vector(1 downto 0);      -- Condition codes
338
  exc      : std_logic_vector(4 downto 0);      -- Exceptions
339
  res_inf  : std_logic;
340
  res_NaN  : std_logic;
341
  res_SNaN : std_logic;
342
end record;
343
 
344
type fpu_result_type is record          -- roundnorm <-> out
345
  frac : std_logic_vector(51 downto 0);
346
  exp  : std_logic_vector(10 downto 0);
347
  sign : std_logic;
348
  cc   : std_logic_vector(1 downto 0);
349
  exc  : std_logic_vector(5 downto 0);
350
end record;
351
 
352
-------------------------------------------------------------------------------
353
-- Declaration of input and output signal from the different pipeline
354
-- registers.
355
-------------------------------------------------------------------------------
356
signal de, de_in : op_decode_stage_type;
357
signal pren, pren_in : prenorm_stage_type;
358
signal as, as_in : addsub_stage_type;
359
signal posn, posn_in : postnorm_stage_type;
360
signal rnd, rnd_in : roundnorm_stage_type;
361
signal rnd_out : fpu_result_type;
362
 
363
-------------------------------------------------------------------------------
364
-- Type and signals used by generate busy process. In the fututure this process
365
-- might be integrated into the pipeline but for now a seperat process is used.
366
-------------------------------------------------------------------------------
367
type fpu_state is (start, get_operand, pre_norm, add_sub, post_norm,
368
                   rnd_norm, hold_val);
369
signal state, next_state : fpu_state;
370
signal result_ready : std_logic;
371
 
372
begin  -- rtl
373
 
374
  de_in.opcode <= FpInst;
375
 
376
-------------------------------------------------------------------------------
377
-- Opcode decode and unpacking stage
378
-------------------------------------------------------------------------------
379
  decode_stage: process (de, fprf_dout1, fprf_dout2)
380
    variable single : std_logic;
381
    variable exp1 : std_logic_vector(10 downto 0);
382
    variable exp2 : std_logic_vector(10 downto 0);
383
    variable frac1 : std_logic_vector(51 downto 0);
384
    variable frac2 : std_logic_vector(51 downto 0);
385
    variable frac1_zero : std_logic;
386
    variable frac2_zero : std_logic;
387
    variable exp1_max : std_logic;
388
    variable exp2_max : std_logic;
389
    variable exp1_min : std_logic;
390
    variable exp2_min : std_logic;
391
  begin
392
    -- Get sign bit for op1
393
    pren_in.sign1 <= fprf_dout1(63);
394
 
395
    -- Unpack exponent and fraction depending on the precision mode. Note that
396
    -- if single precision is used som bit filling must be done for the
397
    -- exponent and fraction since double precision is used internally.
398
    if de.opcode(1 downto 0) = "01" then -- If single precision
399
      single := '1';
400
      exp1 := "000" & fprf_dout1(62 downto 55);
401
      frac1 := "0" & zero(27 downto 0) & fprf_dout1(54 downto 32);
402
      exp2 := "000" & fprf_dout2(62 downto 55);
403
      frac2 := "0" & zero(27 downto 0) & fprf_dout2(54 downto 32);
404
    else
405
      -- If double precision
406
      single := '0';
407
      exp1 := fprf_dout1(62 downto 52);
408
      frac1 := fprf_dout1(51 downto 0);
409
      exp2 := fprf_dout2(62 downto 52);
410
      frac2 := fprf_dout2(51 downto 0);
411
    end if;
412
 
413
    -- Check if fracions zero
414
    if frac1 = zero(51 downto 0) then
415
      frac1_zero := '1';
416
    else
417
      frac1_zero := '0';
418
    end if;
419
 
420
    if frac2 = zero(51 downto 0) then
421
      frac2_zero := '1';
422
    else
423
      frac2_zero := '0';
424
    end if;
425
 
426
    -- Check if exp is max or min
427
    if (exp1(7 downto 0) = "11111111") and
428
       ((single = '1') or (exp1(10 downto 8) = "111")) then
429
      exp1_max := '1';
430
      exp1_min := '0';
431
    elsif exp1 = "00000000000" then
432
      exp1_max := '0';
433
      exp1_min := '1';
434
    else
435
      exp1_max := '0';
436
      exp1_min := '0';
437
    end if;
438
 
439
    if (exp2(7 downto 0) = "11111111") and
440
       ((single = '1') or (exp2(10 downto 8) = "111")) then
441
      exp2_max := '1';
442
      exp2_min := '0';
443
    elsif exp2 = "00000000000" then
444
      exp2_max := '0';
445
      exp2_min := '1';
446
    else
447
      exp2_max := '0';
448
      exp2_min := '0';
449
    end if;
450
 
451
    -- Detect special numbers
452
    pren_in.op1_denorm <= exp1_min;
453
    pren_in.op2_denorm <= exp2_min;
454
    pren_in.op1_inf <= exp1_max and frac1_zero;
455
    pren_in.op2_inf <= exp2_max and frac2_zero;
456
    pren_in.op1_SNaN <= exp1_max and (not frac1_zero) and
457
                        not (frac1(51) or (frac1(22) and single));
458
    pren_in.op2_SNaN <= exp2_max and (not frac2_zero) and
459
                        not (frac2(51) or (frac2(22) and single));
460
    pren_in.op1_NaN <= exp1_max and (not frac1_zero) and
461
                       (frac1(51) or (frac1(22) and single));
462
    pren_in.op2_NaN <= exp2_max and (not frac2_zero) and
463
                       (frac2(51) or (frac2(22) and single));
464
 
465
    -- Decode instruction. If operation is sub or cmp then negate op2 sign.
466
    -- Unimplemented opcodes will result in addition.
467
    case de.opcode(8 downto 0) is
468
      when FSUBS | FSUBD =>     pren_in.sign2 <= not fprf_dout2(63);
469
                                pren_in.comp <= '0';
470
                                pren_in.gen_ex <= '0';
471
      when FCMPS | FCMPD =>     pren_in.sign2 <= not fprf_dout2(63);
472
                                pren_in.comp <= '1';
473
                                pren_in.gen_ex <= '0';
474
      when FCMPES | FCMPED =>   pren_in.sign2 <= not fprf_dout2(63);
475
                                pren_in.comp <= '1';
476
                                pren_in.gen_ex <= '1';
477
      when others =>            pren_in.sign2 <= fprf_dout2(63);
478
                                pren_in.comp <= '0';
479
                                pren_in.gen_ex <= '0';
480
    end case;
481
 
482
    pren_in.single <= single;
483
    pren_in.frac1 <= frac1;
484
    pren_in.exp1 <= exp1;
485
    pren_in.frac2 <= frac2;
486
    pren_in.exp2 <= exp2;
487
  end process decode_stage;
488
 
489
-------------------------------------------------------------------------------
490
-- Prenorm stage
491
-------------------------------------------------------------------------------
492
  prenorm_stage: process (pren)
493
    variable switch_ops : std_logic;
494
    variable sign_diff : std_logic_vector(11 downto 0);
495
    variable abs_diff : std_logic_vector(11 downto 0);
496
    variable all_zero : std_logic_vector(11 downto 0);
497
    variable shift_amount : std_logic_vector(5 downto 0);
498
    variable adj_op : std_logic_vector(54 downto 0);
499
    variable shifted_op : std_logic_vector(54 downto 0);
500
    variable sticky_bit : std_logic;
501
  begin
502
    all_zero := (others => '0');
503
 
504
    -- Calculate differens
505
-- pragma translate_off
506
    if not is_x(pren.exp1 & pren.exp2) then
507
-- pragma translate_on
508
      sign_diff := ("0" & pren.exp1) - ("0" & pren.exp2);
509
-- pragma translate_off
510
    end if;
511
-- pragma translate_on
512
    switch_ops := sign_diff(11);        -- Switch needed
513
 
514
    -- If negative get absolute value
515
    if sign_diff(11) = '1' then
516
-- pragma translate_off
517
      if not is_x(all_zero & sign_diff) then
518
-- pragma translate_on
519
        abs_diff := all_zero - sign_diff;
520
-- pragma translate_off
521
      end if;
522
-- pragma translate_on
523
    else
524
      abs_diff := sign_diff(11 downto 0);
525
    end if;
526
 
527
    -- Not needed to shift more then the length of the fraction
528
-- pragma translate_off
529
    if not is_x(abs_diff) then
530
-- pragma translate_on
531
      if abs_diff > 52 then
532
        shift_amount := "110100";
533
      else
534
        shift_amount := abs_diff(5 downto 0);
535
      end if;
536
-- pragma translate_off
537
    end if;
538
-- pragma translate_on
539
 
540
    -- Do switch of operands if needed. Then retrieve the hidden bit for the
541
    -- larger operand and append overflow, guard, round and sticky bit. For the
542
    -- smaller operand retrive hidden bit and append guard and round bit. 
543
    if switch_ops = '1' then
544
      if (pren.single='1') then   -- single precision
545
        as_in.a <=zero(29 downto 0) & (not pren.op2_denorm) & pren.frac2(22 downto 0) & "000";
546
        adj_op := zero(28 downto 0) & (not pren.op1_denorm) & pren.frac1(22 downto 0) & "00";
547
      else
548
        as_in.a <= "0" & (not pren.op2_denorm) & pren.frac2 & "000";
549
        adj_op := (not pren.op1_denorm) & pren.frac1 & "00";
550
      end if;
551
      as_in.exp <= pren.exp2;
552
      as_in.sign_a <= pren.sign2;
553
      as_in.sign_b <= pren.sign1;
554
    else
555
      if (pren.single='1') then   -- single precision
556
        as_in.a <=zero(29 downto 0) & (not pren.op1_denorm) & pren.frac1(22 downto 0) & "000";
557
        adj_op := zero(28 downto 0) & (not pren.op2_denorm) & pren.frac2(22 downto 0) & "00";
558
      else
559
        as_in.a <= "0" & (not pren.op1_denorm) & pren.frac1 & "000";
560
        adj_op := (not pren.op2_denorm) & pren.frac2 & "00";
561
      end if;
562
      as_in.exp <= pren.exp1;
563
      as_in.sign_a <= pren.sign1;
564
      as_in.sign_b <= pren.sign2;
565
    end if;
566
 
567
    -- Shift smaller operand right and get sticky bit.
568
    right_shifter_sticky(adj_op,shift_amount,shifted_op,sticky_bit);
569
 
570
    -- Add overflow and sticky bit for shifted smaller operand.
571
    as_in.b <= "0" & shifted_op & sticky_bit;
572
 
573
    as_in.swaped <= switch_ops;
574
    as_in.op1_inf <= pren.op1_inf;
575
    as_in.op2_inf <= pren.op2_inf;
576
    as_in.op1_NaN <= pren.op1_NaN;
577
    as_in.op2_NaN <= pren.op2_Nan;
578
    as_in.op1_SNaN <= pren.op1_SNaN;
579
    as_in.op2_SNaN <= pren.op2_SNaN;
580
    as_in.single <= pren.single;
581
    as_in.comp <= pren_in.comp;
582
    as_in.gen_ex <= pren_in.gen_ex;
583
  end process prenorm_stage;
584
 
585
-------------------------------------------------------------------------------
586
-- Add/Sub stage
587
-------------------------------------------------------------------------------
588
  addsub_stage: process (as)
589
    variable signs : std_logic_vector(1 downto 0);
590
    variable result : std_logic_vector(56 downto 0);
591
    variable temp : std_logic_vector(56 downto 0);
592
    variable neg_value : std_logic;
593
    variable all_zero : std_logic_vector(56 downto 0);
594
    variable unordered : std_logic;
595
    variable zero_fraction : std_logic;
596
    variable cc_bit0 : std_logic;
597
    variable cc_bit1 : std_logic;
598
    variable SNaN : std_logic;
599
    variable NaN : std_logic;
600
    variable inf : std_logic;
601
  begin
602
    all_zero := (others => '0');
603
 
604
    signs := as.sign_a & as.sign_b;
605
 
606
    -- Perform operation based on the sign of the operands
607
    case signs is
608
      when "00" =>
609
-- pragma translate_off
610
                if not is_x(as.a & as.b) then
611
-- pragma translate_on
612
                   result := as.a + as.b;
613
-- pragma translate_off
614
                end if;
615
-- pragma translate_on
616
                   posn_in.sign <= '0';
617
                   neg_value := '0';
618
      when "01" =>
619
-- pragma translate_off
620
                if not is_x(as.a & as.b) then
621
-- pragma translate_on
622
                   result := as.a - as.b;
623
-- pragma translate_off
624
                end if;
625
-- pragma translate_on
626
                   posn_in.sign <= result(56);
627
                   neg_value := result(56);
628
      when "10" =>
629
-- pragma translate_off
630
                if not is_x(as.a & as.b) then
631
-- pragma translate_on
632
                   result := as.a - as.b;
633
-- pragma translate_off
634
                end if;
635
-- pragma translate_on
636
                   posn_in.sign <= not result(56);
637
                   neg_value := result(56);
638
      when "11" =>
639
-- pragma translate_off
640
                if not is_x(as.a & as.b) then
641
-- pragma translate_on
642
                   result := as.a + as.b;
643
-- pragma translate_off
644
                end if;
645
-- pragma translate_on
646
                   posn_in.sign <= '1';
647
                   neg_value := '0';
648
      when others => null;
649
    end case;
650
 
651
    -- If result is negative set fraction = -result else set fraction = result
652
-- pragma translate_off
653
    if not is_x(all_zero & result) then
654
-- pragma translate_on
655
      temp := all_zero - result;
656
-- pragma translate_off
657
    end if;
658
-- pragma translate_on
659
    if neg_value = '1' then
660
      posn_in.frac <= temp(56 downto 0);
661
    else
662
      posn_in.frac <= result(56 downto 0);
663
    end if;
664
 
665
    -- Check if result is zero
666
    if result = all_zero then
667
      zero_fraction := '1';
668
      posn_in.exp <= "00000000000";
669
    else
670
      zero_fraction := '0';
671
      posn_in.exp <= as.exp;
672
    end if;
673
 
674
    -- Check if unordered operands i.e. any operand is some sort of NaN
675
    unordered := as.op1_NaN or as.op2_NaN or as.op1_SNaN or as.op2_SNaN;
676
 
677
    -- Check if result should be a SNaN.
678
    SNaN := as.op1_SNaN or as.op2_SNaN or (unordered and as.gen_ex);
679
 
680
    -- Check if result should be a NaN i.e. unordered opearands that don't
681
    -- result in a SNaN or two inf values with different signs.
682
    NaN := (unordered and (not SNaN)) or
683
           (as.op1_inf and as.op2_inf and (signs(1) xor signs(0)));
684
 
685
    -- Check if result should be inf.
686
    inf := (as.op1_inf or as.op2_inf) and (not NaN) and (not SNaN);
687
 
688
    -- Calculate condition codes.
689
    cc_bit1 := ((not zero_fraction) and (not neg_value) and (not as.swaped)) or
690
               unordered;
691
    cc_bit0 := ((not zero_fraction) and
692
                (as.swaped or (neg_value and (not as.swaped)))) or unordered;
693
 
694
    -- Set condition codes if comp signal is 1.
695
    if as.comp = '1' then
696
      posn_in.cc <= cc_bit1 & cc_bit0;
697
    else
698
      posn_in.cc <= (others => '0');
699
    end if;
700
 
701
    -- Set exceptions
702
    posn_in.exc <= SNaN & inf & "000";
703
 
704
    -- Check if operation results in specal value
705
    posn_in.res_SNaN <= SNaN;
706
    posn_in.res_NaN <= NaN;
707
    posn_in.res_inf <= inf;
708
    posn_in.single <= as.single;
709
    posn_in.res_zero <= zero_fraction;
710
    posn_in.comp <= as.comp;
711
  end process addsub_stage;
712
 
713
-------------------------------------------------------------------------------
714
-- Postnorm stage
715
-------------------------------------------------------------------------------
716
  posnorm_stage: process (posn)
717
    variable mask : std_logic_vector(55 downto 0);
718
    variable leading_one : std_logic_vector(55 downto 0);
719
    variable leading_zeros : std_logic_vector(55 downto 0);
720
    variable shifts_needed : std_logic_vector(5 downto 0);
721
    variable shift_amount : std_logic_vector(5 downto 0);
722
    variable exp : std_logic_vector(10 downto 0);
723
    variable frac : std_logic_vector(56 downto 0);
724
    variable overflow : std_logic;
725
    variable underflow : std_logic;
726
  begin
727
    -- If supernormal (overflow bit set) shift left by one step and inc exp
728
    if ((posn.single = '1') and (posn.frac(27) = '1')) or
729
       (posn.frac(56) = '1') then
730
      frac := "0" & posn.frac(56 downto 1);
731
-- pragma translate_off
732
      if not is_x(posn.exp) then
733
-- pragma translate_on
734
        exp := posn.exp + 1;
735
-- pragma translate_off
736
      end if;
737
-- pragma translate_on
738
      underflow := '0';
739
    else
740
      -- Get number of leading zeros, if single precision is used don't count
741
      -- leading 29 zeroes. (Overflow bit is not counted)
742
      if posn.single = '1' then
743
        lz_counter((posn.frac(26 downto 0) & "0" & zero(27 downto 0)),shifts_needed);
744
      else
745
        lz_counter(posn.frac(55 downto 0),shifts_needed);
746
      end if;
747
 
748
      -- If the shift amount needed is larger then the exponent then underflow
749
      -- has occured, check that fraction is not zero.
750
-- pragma translate_off
751
      if not is_x(shifts_needed & posn.exp) then
752
-- pragma translate_on
753
        if (unsigned(shifts_needed) > unsigned(posn.exp)) and (posn.res_zero = '0') then
754
            shift_amount := posn.exp(5 downto 0);
755
          exp := (others => '0');
756
          underflow := '1';
757
        else
758
          shift_amount := shifts_needed;
759
-- pragma translate_off
760
          if not is_x( posn.exp & shift_amount) then
761
-- pragma translate_on
762
            exp := posn.exp - shift_amount;
763
-- pragma translate_off
764
          end if;
765
-- pragma translate_on
766
          underflow := '0';
767
        end if;
768
-- pragma translate_off
769
      end if;
770
-- pragma translate_on
771
 
772
      -- Perform left shift
773
      left_shifter(posn.frac,shift_amount,frac);
774
    end if;
775
 
776
    -- Check if overflow has occured, also check that result is not any NaN
777
    if (exp(7 downto 0) = "11111111") and
778
       ((posn.single = '1') or (exp(10 downto 8) = "111")) and
779
       (posn.res_SNaN = '0') and (posn.res_NaN = '0') then
780
      overflow := '1';
781
    else
782
      overflow := '0';
783
    end if;
784
 
785
    -- If operation is not some sort of compare set overflow/underflow
786
    -- exceptions caused in this pipeline stage
787
    if (posn.comp = '0') then
788
      rnd_in.exc <= posn.exc(4) & overflow & underflow & posn.exc(1 downto 0);
789
    else
790
      rnd_in.exc <= posn.exc(4) & "00" & posn.exc(1 downto 0);
791
    end if;
792
 
793
    rnd_in.frac <= frac;
794
    rnd_in.exp <= exp;
795
    rnd_in.cc <= posn.cc;
796
    rnd_in.res_NaN <= posn.res_NaN;
797
    rnd_in.res_SNaN <= posn.res_SNaN;
798
    rnd_in.res_inf <= posn.res_inf or overflow;
799
    rnd_in.single <= posn.single;
800
    rnd_in.comp <= posn.comp;
801
    rnd_in.sign <= posn.sign;
802
  end process posnorm_stage;
803
 
804
 
805
-------------------------------------------------------------------------------
806
-- Round and normalize stage
807
-------------------------------------------------------------------------------
808
  roundnorm_stage: process (rnd, RoundingMode)
809
    variable rounded_value : std_logic_vector(53 downto 0);
810
    variable rounded_norm_value : std_logic_vector(52 downto 0);
811
    variable exp_norm : std_logic_vector(10 downto 0);
812
    variable exp : std_logic_vector(10 downto 0);
813
    variable fraction : std_logic_vector(51 downto 0);
814
    variable all_zero : std_logic_vector(51 downto 0);
815
    variable overflow : std_logic;
816
    variable inexact : std_logic;
817
    variable NaNs : std_logic;
818
  begin
819
    all_zero := (others => '0');
820
 
821
    -- Perform rounding according to selected rounding mode
822
    case RoundingMode is
823
      when "00" => if rnd.frac(2) = '1' and
824
                      rnd.frac(3 downto 0) /=  "0000" then
825
-- pragma translate_off
826
                     if not is_x(rnd.frac(56 downto 3)) then
827
-- pragma translate_on
828
                       rounded_value := rnd.frac(56 downto 3) + 1;
829
-- pragma translate_off
830
                     end if;
831
-- pragma translate_on
832
                   else
833
                     rounded_value := rnd.frac(56 downto 3);
834
                   end if;
835
      when "01" => rounded_value := rnd.frac(56 downto 3);
836
      when "10" => if rnd.sign = '0' and rnd.frac(2) = '1' then
837
-- pragma translate_off
838
                     if not is_x(rnd.frac(56 downto 3)) then
839
-- pragma translate_on
840
                       rounded_value := rnd.frac(56 downto 3) + 1;
841
-- pragma translate_off
842
                     end if;
843
-- pragma translate_on
844
                   else
845
                     rounded_value := rnd.frac(56 downto 3);
846
                   end if;
847
      when "11" => if rnd.sign = '1' and rnd.frac(2) = '1' then
848
-- pragma translate_off
849
                     if not is_x(rnd.frac(56 downto 3)) then
850
-- pragma translate_on
851
                       rounded_value := rnd.frac(56 downto 3) + 1;
852
-- pragma translate_off
853
                     end if;
854
-- pragma translate_on
855
                   else
856
                     rounded_value := rnd.frac(56 downto 3);
857
                   end if;
858
      when others => null;
859
    end case;
860
 
861
    -- Normalize if needed i.e. if overflow bit set shift fraction one step
862
    -- left and inc exp.
863
    if (rnd.single = '1' and rounded_value(24) = '1') or
864
       rounded_value(36) = '1' then
865
      rounded_norm_value := rounded_value(53 downto 1);
866
-- pragma translate_off
867
      if not is_x(rnd.exp) then
868
-- pragma translate_on
869
        exp_norm := rnd.exp + 1;
870
-- pragma translate_off
871
      end if;
872
-- pragma translate_on
873
    else
874
      rounded_norm_value := rounded_value(52 downto 0);
875
      exp_norm := rnd.exp;
876
    end if;
877
 
878
    -- Check if overflow has occured
879
    if (exp_norm(7 downto 0) = "11111111") and
880
       ((rnd.single = '1') or (exp_norm(10 downto 8) = "111")) and
881
       (rnd.res_SNaN = '0') and (rnd.res_NaN = '0') then
882
      overflow := '1';
883
    else
884
      overflow := '0';
885
    end if;
886
 
887
    -- Check if result is inexact
888
    inexact := (rnd.frac(2) or rnd.frac(1) or rnd.frac(0)) and (not rnd.comp);
889
 
890
    -- Check if result is some sort of NaN
891
    NaNs := rnd.res_NaN or rnd.res_SNaN;
892
 
893
    -- Set fraction and exponent.
894
    if NaNs = '1' then
895
      fraction := rnd.res_NaN & "1" & all_zero(49 downto 0);
896
      exp := (others => '1');
897
    elsif overflow = '1' or rnd.res_inf = '1' then
898
      fraction := (others => '0');
899
      exp := (others => '1');
900
    else
901
      fraction := rounded_norm_value(51 downto 0);
902
      exp := exp_norm;
903
    end if;
904
 
905
    -- Set exception bits. If operaration is some sort of compare then
906
    -- overflow, underflow and inexact interrupt can not occure. 
907
    if rnd.comp = '1' then
908
      rnd_out.exc <= "0" & rnd.exc(4) & "0000";
909
    else
910
      rnd_out.exc <= "0" & rnd.exc(4) & (overflow or rnd.exc(3)) &
911
                     rnd.exc(2 downto 1) & inexact;
912
    end if;
913
 
914
    -- Put out result
915
    if rnd.single = '1' then
916
      rnd_out.frac <= fraction(22 downto 0) & "0" & zero(27 downto 0);
917
    else
918
      rnd_out.frac <= fraction;
919
    end if;
920
 
921
    rnd_out.exp <= exp;
922
    rnd_out.sign <= rnd.sign;
923
    rnd_out.cc <= rnd.cc;
924
  end process roundnorm_stage;
925
 
926
-------------------------------------------------------------------------------
927
-- FPU busy signal generation process
928
-------------------------------------------------------------------------------
929
  gen_busy: process (state, FpOp, FpLd)
930
  begin
931
    -- Default assignments
932
    FpBusy <= '0';
933
    next_state <= state;
934
    result_ready <= '0';
935
 
936
    -- Calculate nextstate and output
937
    case state is
938
      when start       => if FpOp = '1' then
939
                            next_state <= get_operand;
940
                          end if;
941
      when get_operand => FpBusy <= '1';
942
                          if FpLd = '1' then
943
                            next_state <= pre_norm;
944
                          end if;
945
      when pre_norm    => FpBusy <= '1';
946
                          next_state <= add_sub;
947
      when add_sub     => FpBusy <= '1';
948
                          next_state <= post_norm;
949
      when post_norm   => FpBusy <= '1';
950
                          next_state <= rnd_norm;
951
      when rnd_norm    => result_ready <= '1';
952
                          if FpOp = '1' then
953
                            next_state <= get_operand;
954
                          else
955
                            next_state <= hold_val;
956
                          end if;
957
      when hold_val    => if FpOp = '1' then
958
                            next_state <= get_operand;
959
                          end if;
960
      when others      => null;
961
    end case;
962
  end process gen_busy;
963
 
964
  process (ss_clock, Reset)
965
  begin
966
    if Reset = '1' then
967
      state <= start;
968
    elsif ss_clock = '1' and ss_clock'event then
969
      state <= next_state;
970
    end if;
971
  end process;
972
 
973
-------------------------------------------------------------------------------
974
-- Pipeline registers
975
-------------------------------------------------------------------------------
976
 
977
  -- Gated ff holding opcode
978
  de_gated : process (ss_clock, FpOp)
979
  begin
980
    if ss_clock = '1' and ss_clock'event then
981
      if FpOp = '1' then
982
        de <= de_in;
983
      end if;
984
    end if;
985
  end process de_gated;
986
 
987
  -- Gated ff holding unpacked operands and control signals
988
  pren_gated : process (ss_clock, FpLd)
989
  begin
990
    if ss_clock = '1' and ss_clock'event then
991
      if FpLd = '1' then
992
        pren <= pren_in;
993
      end if;
994
    end if;
995
  end process pren_gated;
996
 
997
  -- Normal ff for the other pipeline stages
998
  pipe_regs: process (ss_clock)
999
  begin  -- process pipe_regs
1000
    if ss_clock = '1' and ss_clock'event then
1001
      as <= as_in;
1002
      posn <= posn_in;
1003
      rnd <= rnd_in;
1004
    end if;
1005
  end process pipe_regs;
1006
 
1007
  -- Gated ff with asynchronous reset holding the FPU output values
1008
  out_gated_reset: process (ss_clock, Reset, result_ready)
1009
  begin  -- process out_gated_reset
1010
    if Reset = '1' then
1011
      FracResult <= (others => '0');
1012
      ExpResult <= (others => '0');
1013
      SignResult <= '0';
1014
      Excep <= (others => '0');
1015
      ConditionCodes <= (others => '0');
1016
    elsif ss_clock = '1' and ss_clock'event then
1017
      if result_ready = '1' then
1018
        FracResult <= rnd_out.frac;
1019
        ExpResult <= rnd_out.exp;
1020
        SignResult <= rnd_out.sign;
1021
        Excep <= rnd_out.exc;
1022
        ConditionCodes <= rnd_out.cc;
1023
      end if;
1024
    end if;
1025
  end process out_gated_reset;
1026
 
1027
end rtl;

powered by: WebSVN 2.1.0

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