164 lines
5.0 KiB
Systemverilog
164 lines
5.0 KiB
Systemverilog
//
|
|
// 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
|
|
|
|
// Coerce from real to 16-bit signed integer
|
|
function automatic shortint coerce_to_int16(real num);
|
|
if (num > SHORT_MAX) return SHORT_MAX;
|
|
if (num < SHORT_MIN) return SHORT_MIN;
|
|
return shortint'(num);
|
|
endfunction : coerce_to_int16
|
|
|
|
//---------------------------------------------------------------------------
|
|
// 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
|