aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/sim/packages/PkgMath.sv
blob: db5c15840d79dd4e0a5db442e7302741dfbe4007 (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//
// Copyright 2021 Ettus Research, A National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Package: PkgMath
//
// Description:
//
//   SystemVerilog supports many Math functions. This adds a few that it
//   doesn't have built in, as well as useful mathematical constants.
//
//   SystemVerilog has built-in support for the following:
//
//     $clog2   $asin
//     $ln      $acos
//     $log10   $atan
//     $exp     $atan2
//     $sqrt    $hypot
//     $pow     $sinh
//     $floor   $cosh
//     $ceil    $tanh
//     $sin     $asinh
//     $cos     $acosh
//     $tan     $atanh
//

package PkgMath;

  //---------------------------------------------------------------------------
  // Constants
  //---------------------------------------------------------------------------

  localparam real PI  = 2*$acos(0.0);
  localparam real TAU = 4*$acos(0.0);

  localparam real PHI = (1 + $sqrt(5.0)) / 2.0;
  localparam real E   = $exp(1);

  localparam byte     BYTE_MAX  =  8'sh7F;
  localparam byte     BYTE_MIN  =  8'sh80;
  localparam shortint SHORT_MAX = 16'sh7FFF;
  localparam shortint SHORT_MIN = 16'sh8000;
  localparam int      INT_MAX   = 32'sh7FFFFFFF;
  localparam int      INT_MIN   = 32'sh80000000;
  localparam longint  LONG_MAX  = 64'sh7FFFFFFFFFFFFFFF;
  localparam longint  LONG_MIN  = 64'sh8000000000000000;

  localparam byte     unsigned UBYTE_MAX  =  8'hFF;
  localparam byte     unsigned UBYTE_MIN  =  8'h00;
  localparam shortint unsigned USHORT_MAX = 16'hFFFF;
  localparam shortint unsigned USHORT_MIN = 16'h0000;
  localparam int      unsigned UINT_MAX   = 32'hFFFFFFFF;
  localparam int      unsigned UINT_MIN   = 32'h00000000;
  localparam longint  unsigned ULONG_MAX  = 64'hFFFFFFFFFFFFFFFF;
  localparam longint  unsigned ULONG_MIN  = 64'h0000000000000000;


  //---------------------------------------------------------------------------
  // Functions (For real data types)
  //---------------------------------------------------------------------------

  // Return the absolute value
  function automatic real abs(real num);
    if (num < 0) return -1.0*num;
    return num;
  endfunction : abs

  // Round a float to the nearest whole number, rounding away from zero for 0.5
  // (same as C++ and default SystemVerilog behavior).
  function automatic real round(real num);
    if (num >= 0) begin
      // Round toward +inf
      if (num - $floor(num) < 0.5) return $floor(num);
      return $ceil(num);
    end else begin
      // Round toward -inf
      if (num - $floor(num) <= 0.5) return $floor(num);
      return $ceil(num);
    end

  endfunction : round

  // Round a float to the nearest value having bits to the right of the binary
  // point. For example:
  //
  //   1.2265625 (0b1.0011101) --> 3 bits --> 1.25000 (0b1.0100000)
  //   1.2265625 (0b1.0011101) --> 5 bits --> 1.21875 (0b1.0011100)
  //
  function automatic real round_bits(real num, int unsigned bits);
    return round(num * 2.0**bits) / (2.0**bits);
  endfunction : round_bits

  // Return the sign of num as +1.0 or -1.0;
  function automatic real sign(real num);
    if (num < 0.0) return -1.0;
    return 1.0;
  endfunction : sign;

  // Return the modulus (remainder) of a / b, with the sign of the numerator.
  // This should match the C++ standard library std::fmod() behavior, as well
  // as SystemVerilog % operator with integer values.
  function automatic real fmod(real a, real b);
    a = abs(a);
    b = abs(b);
    return sign(b) * (a - ($floor(a / b) * b));
  endfunction : fmod

  // Return the (remainder) of a / b, where the quotient is rounded to the
  // nearest integer. This should approximate the C++ standard library
  // std::remainder() behavior.
  function automatic real remainder(real a, real b);
    return a - round(a/b)*b;
  endfunction : remainder

  // Return the maximum of a and b.
  function automatic real fmax(real a, real b);
    if (a > b) return a;
    return b;
  endfunction : fmax

  // Return the minimum of a and b.
  function automatic real fmin(real a, real b);
    if (a < b) return a;
    return b;
  endfunction : fmin


  //---------------------------------------------------------------------------
  // Template Functions (For any data type)
  //---------------------------------------------------------------------------

  class Math #(type T);

    static function T abs(T num);
      if (num < 0) return -num;
      return num;
    endfunction : abs

    static function T sign(T num);
      if (num < 0) return -1;
      return 1;
    endfunction : sign

    static function T max(T a, T b);
      if (a > b) return a;
      else return b;
    endfunction : max

    static function T min(T a, T b);
      if (a < b) return a;
      else return b;
    endfunction : min

  endclass : Math

endpackage : PkgMath