From a3a85d2c98dd026a6df872494f386a616868ebd4 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Tue, 9 Feb 2010 10:16:36 +0000 Subject: [PATCH] - improved UTILS_FREQ_M(), UTILS_FREQ_D(). Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@739 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/misc/utils_pkg.vhd | 83 +++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/lib/misc/utils_pkg.vhd b/lib/misc/utils_pkg.vhd index ee37695..b219281 100644 --- a/lib/misc/utils_pkg.vhd +++ b/lib/misc/utils_pkg.vhd @@ -1,5 +1,5 @@ ----------------------------------------------------------------------- --- $Header: /tmp/cvsroot/VHDL/lib/misc/utils_pkg.vhd,v 1.4 2010-02-09 07:46:19 Jens Exp $ +-- $Header: /tmp/cvsroot/VHDL/lib/misc/utils_pkg.vhd,v 1.5 2010-02-09 10:16:36 Jens Exp $ ----------------------------------------------------------------------- library IEEE; @@ -21,6 +21,7 @@ package utils_pkg is 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; @@ -82,37 +83,77 @@ package body utils_pkg is end UTILS_PERIOD_NS; function UTILS_FREQ_M(f_in_MHz, f_out_MHz : real) return natural is - variable f_in_hz : natural; - variable f_out_hz : natural; - variable m : natural; + variable f_in : natural; + variable f_out : natural; + variable C : natural; + variable M : natural; + variable D : natural; begin - f_in_hz := natural(f_in_MHz*1.0E6); - f_out_hz := natural(f_out_MHz*1.0E6); - m := f_out_hz/GCD(f_in_hz, f_out_hz); - - if m = 1 then - m := 2; + C := f_correct(f_out_MHz); + if C < 2 then + C := f_correct(f_in_MHz); end if; - - return m; + + 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_hz : natural; - variable f_out_hz : natural; - variable m : natural; - variable d : natural; + variable f_in : natural; + variable f_out : natural; + variable C : natural; + variable M : natural; + variable D : natural; begin - m := UTILS_FREQ_M(f_in_MHz, f_out_MHz); - f_in_hz := natural(f_in_MHz*1.0E6); - f_out_hz := natural(f_out_MHz*1.0E6); - d := m*f_in_hz/f_out_hz; + 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; + 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;