Files
vhdl/lib/misc/utils_pkg.vhd
T
jens 70e48af3ab - commit local changes after CVS2SVN
git-svn-id: http://moon:8086/svn/vhdl/trunk@1036 cc03376c-175c-47c8-b038-4cd826a8556b
2014-07-20 13:30:14 +00:00

197 lines
4.7 KiB
VHDL

-----------------------------------------------------------------------
-- $Header: D:\usr\cvsroot/VHDL/lib/misc/utils_pkg.vhd,v 1.6 2010/03/22 07:25:40 Jens Exp $
-----------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
package utils_pkg is
-- Constants
-- Functions
function MIN (X, Y: INTEGER) return INTEGER;
function MAX (X, Y: INTEGER) return INTEGER;
function NextPowerOfTwo(x : real) return real;
function NextExpBaseTwo(x : real) return real;
function NextPowerOfTwo(x : natural) return natural;
function NextExpBaseTwo(x : natural) return natural;
function GCD(a, b : natural) return natural;
function LCM(a, b : natural) return natural;
function UTILS_PERIOD_NS(f_in_MHz : real) return real;
function UTILS_FREQ_M(f_in_MHz, f_out_MHz : real) return natural;
function UTILS_FREQ_D(f_in_MHz, f_out_MHz : real) return natural;
function f_correct(f : real) return natural;
end utils_pkg;
package body utils_pkg is
-------------------------------------------------------------
function MIN (X, Y: INTEGER) return INTEGER is
variable res : integer := X;
begin
if Y < X then
res := Y;
end if;
return res;
end MIN;
-------------------------------------------------------------
function MAX (X, Y: INTEGER) return INTEGER is
variable res : integer := X;
begin
if Y > X then
res := Y;
end if;
return res;
end MAX;
-------------------------------------------------------------
function NextExpBaseTwo(x : real) return real is
begin
return ceil(log2(x));
end NextExpBaseTwo;
-------------------------------------------------------------
function NextPowerOfTwo(x : real) return real is
begin
return 2.0**NextExpBaseTwo(x);
end NextPowerOfTwo;
-------------------------------------------------------------
function NextExpBaseTwo(x : natural) return natural is
begin
return natural(NextExpBaseTwo(real(x)));
end NextExpBaseTwo;
-------------------------------------------------------------
function NextPowerOfTwo(x : natural) return natural is
begin
return 2**NextExpBaseTwo(x);
end NextPowerOfTwo;
-------------------------------------------------------------
function GCD(a, b : natural) return natural is
variable aa : natural;
variable bb : natural;
begin
aa := a;
bb := b;
while bb /= 0 loop
if aa > bb then
aa := aa - bb;
else
bb := bb - aa;
end if;
end loop;
return aa;
end GCD;
-------------------------------------------------------------
function LCM(a, b : natural) return natural is
begin
return (a * b)/GCD(a, b);
end LCM;
-------------------------------------------------------------
function UTILS_PERIOD_NS(f_in_MHz : real) return real is
begin
return 1.0E3/f_in_MHz;
end UTILS_PERIOD_NS;
-------------------------------------------------------------
function UTILS_FREQ_M(f_in_MHz, f_out_MHz : real) return natural is
variable f_in : natural;
variable f_out : natural;
variable C : natural;
variable M : natural;
variable D : natural;
begin
C := f_correct(f_out_MHz);
if C < 2 then
C := f_correct(f_in_MHz);
end if;
f_out := natural(ceil(real(C)*f_out_MHz));
f_in := natural(ceil(real(C)*f_in_MHz));
M := LCM(f_in, f_out)/f_in;
D := f_in/GCD(f_in, f_out);
assert (M*D) /= (f_in*f_out) report "Finding M and D failed!" severity failure;
if M = 1 then
M := 2;
end if;
return M;
end UTILS_FREQ_M;
-------------------------------------------------------------
function UTILS_FREQ_D(f_in_MHz, f_out_MHz : real) return natural is
variable f_in : natural;
variable f_out : natural;
variable C : natural;
variable M : natural;
variable D : natural;
begin
C := f_correct(f_out_MHz);
if C < 2 then
C := f_correct(f_in_MHz);
end if;
f_out := natural(ceil(real(C)*f_out_MHz));
f_in := natural(ceil(real(C)*f_in_MHz));
M := LCM(f_in, f_out)/f_in;
D := f_in/GCD(f_in, f_out);
assert (M*D) /= (f_in*f_out) report "Finding M and D failed!" severity failure;
if M = 1 then
D := 2*D;
end if;
return D;
end UTILS_FREQ_D;
-------------------------------------------------------------
function f_correct(f : real) return natural is
constant MAX_ITER : positive := 100;
constant MAX_ERR : real := 0.01;
variable fpart : real;
variable err : real;
begin
for i in 1 to MAX_ITER loop
fpart := real(i)*f - ceil(real(i)*f);
err := abs(fpart);
if err < max_err then
return i;
end if;
end loop;
end f_correct;
-------------------------------------------------------------
end utils_pkg;