fpga: sim: Add PkgComplex, PkgMath, and PkgRandom
PkgComplex adds functions for doing complex arithmetic in SystemVerilog simulation. PkgMath provides mathematical operations and constants that aren't built into SystemVerilog, such as a constant for pi and the function round(). PkgRandom adds randomization functions beyond what standard Verilog supports but that don't require any special licenses or simulators. Original-commit: da4202e6f74796603072aa14544581604e81df02
This commit is contained in:
@@ -0,0 +1,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
|
||||
Reference in New Issue
Block a user