aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/issue2103/pkg_math_signed.vhdl
blob: 8dedeb43c2fe086af9195c0c2b5b05e22b1573c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
------------------------------------------------------------------------------
--          ____  _____________  __                                         --
--         / __ \/ ____/ ___/\ \/ /                 _   _   _               --
--        / / / / __/  \__ \  \  /                 / \ / \ / \              --
--       / /_/ / /___ ___/ /  / /               = ( M | S | K )=            --
--      /_____/_____//____/  /_/                   \_/ \_/ \_/              --
--                                                                          --
------------------------------------------------------------------------------
--! @copyright Copyright 2020-2022 DESY
--! SPDX-License-Identifier: CERN-OHL-W-2.0
------------------------------------------------------------------------------
--! @date 2020-10-02/2022-04-01
--! @author Lukasz Butkowski <lukasz.butkowski@desy.de>
--! @author Michael Buechler <michael.buechler@desy.de>
------------------------------------------------------------------------------
--! @brief
--! Provides math function/procedures with signed signals
------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.math_utils.all;
use work.logic_misc.all;

package math_signed is

  --! Saturate *arg* to the maximum or minimum representable value depending on
  --! sat
  function f_saturate (arg : signed; sat : t_saturation) return signed;

  --! Resize with saturation protection
  function f_resize_sat (arg : signed; length : positive) return signed;

  --! Resize with saturation protection and saturation flag
  --! Like the <<f_resize_sat>> function but also sets an overflow bit.
  --! To be able to combine this with another preceding operation like shift_right
  --! in a process, the argument 'arg' must be a variable instead of a signal.
  procedure prd_resize_sat (
    signal arg      : in signed;
    constant length : in positive;
    signal result   : out signed;
    signal sat      : out t_saturation
  );

end package math_signed;

--******************************************************************************

package body math_signed is

  function f_saturate (arg : signed; sat : t_saturation) return signed is
  begin

    if (sat = ST_SAT_OVERFLOWN) then
      return f_max_val_of(arg);
    elsif (sat = ST_SAT_UNDERFLOWN) then
      return f_min_val_of(arg);
    else
      return arg;
    end if;

  end function f_saturate;

  function f_resize_sat (arg : signed; length : natural) return signed is

    variable var_result : signed(length - 1 downto 0);

  begin

    prd_resize_sat(arg => arg, length => length, result => var_result);
    return var_result;

  end function;

  procedure prd_resize_sat (
    signal arg      : in signed;
    constant length : in positive;
    signal result   : out signed;
    signal sat      : out t_saturation
  ) is

    variable var_sat : t_saturation;

  begin

    if (length >= arg'length) then
      var_sat := ST_SAT_OK;
    else
      -- check overflow saturation
      if (arg(arg'high) = '0' and
          f_all_zeroes(arg(arg'high-1 downto length - 1)) = '0') then
        var_sat := ST_SAT_OVERFLOWN;
      -- check underflow saturation
      elsif (arg(arg'high) = '1' and
             f_all_ones(arg(arg'high-1 downto length - 1)) = '0') then
        var_sat := ST_SAT_UNDERFLOWN;
      else
        var_sat := ST_SAT_OK;
      end if;
      result <= f_saturate(resize(arg, length), var_sat);
      sat    <= var_sat;
    end if;

  end procedure prd_resize_sat;

end package body math_signed;