大家好,我有以下包,由我自己定义
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
package util_pkg is
function log2c(n : natural) return natural;
end package util_pkg;
package body util_pkg is
function log2c(n : natural) return natural is
variable temp : natural := n;
variable ret_val : natural := 0;
begin
while temp > 1 loop
ret_val := ret_val + 1;
temp = temp/2;
end loop;
return ret_val;
end function log2c;
end package body util_pkg;
而我的设计是
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
use work.util_pkg.all;
entity ldz is
generic(n : natural); --i can assume n > 1
port(x : in std_logic_vector(n - 1 downto 0);
y : out std_logic_vector(log2c(n) - 1 downto 0));
end entity ldz;
-- Example
architecture ldz_arch of ldz is
function ldz_count(x : unsigned) return natural is
n_ldz : natural := 0;
begin
for i in x'high to 0 loop
if(x(i) = '1') then
return x'length - i - 1;
end if;
end loop;
return x'length - 1;
end function ldz_count;
begin
y <= std_logic_vector(to_unsigned(ldz_count(to_unsigned(x)));
end architecture ldz_arch;
当我尝试使用ncvhdl验证语法时,这是我得到的错误
unit (UTIL_PKG) not found in library (WORKLIB)
但是这样的单元(包)在设计的同一个库中。
设计为util_pkg.vhd
ldz.vhd
有什么问题?
答案 0 :(得分:1)
该工具抱怨,因为在ldz
之前尚未分析(编译)包。首先编译它,然后编译ldz
。
正如评论中所提到的,您的代码遇到了一些问题。以下代码计算正数的log2,向0或无穷大舍入:
function log2_down(n: positive) is
variable res: natural := 0;
begin
if n /= 1 then
res := 1 + log2_down(n / 2);
end if;
return res;
end function log2_down;
function log2_up(n: positive) is
variable res: natural := 0;
begin
if n /= 1 then
res := 1 + log2_up((n + 1) / 2);
end if;
return res;
end function log2_up;
是的,VHDL也支持递归和大多数合成器,至少当迭代次数是静态可计算的时候。
可以避免res
变量但它有助于避免某些工具的警告,如果函数的return语句都在控制结构的控制之下,它会发出警告。他们这样做是因为他们不能证明函数总会返回,而函数总是会返回。我总是试图压制警告,以便任何剩余的警告都是有意义的,不可忽视。
将参数声明为positive
是处理log2(0)
错误的简单方法。我总是尝试使用该语言的内置功能来处理错误。
使用相同的两个原则(没有警告,让语言的内置功能处理错误),可以编写前导零计数器ldz_count
函数:
function ldz_count(x: unsigned) return natural is
constant n: positive := x'length;
constant v: unsigned(0 to n - 1) := x;
variable res: natural := n;
begin
for i in 0 to n - 1 loop
if v(i) = '1' then
res := i;
end if;
end if;
return res;
end function ldz_count;
使用选定的位索引复制x
参数将使您的函数可用于任何x
参数,无论其声明(7 to 35
或9 downto 4
)是什么,只要它是至少有一点长。这是我喜欢的第三个原则:如果你做了一些通用的东西,那就让它真的泛型。