如何确定在 VHDL 中是否设置了 STD_LOGIC_VECTOR 中的多于一位
How to determine if more than one bit in an STD_LOGIC_VECTOR is set in VHDL
我想知道如何确定四位 STD_LOGIC_VECTOR 中是否有超过一位设置为“1”。
例如,如果它是“1001”或“1100”或“1111”。
我正在编写一个程序,如果我的实体收到多个控制信号,我必须将错误信号设置为“1”。四个控制信号已合并为一个 4 位STD_LOGIC_VECTOR,我需要一种智能方法来确定是否设置了多个位。
我用
解决了
with selvec select
ERR <= '0' when "0001",
'0' when "0010",
'0' when "0100",
'0' when "1000",
'0' when "0000",
'1' when others;
不是最简洁的代码,但它可以解决问题。
你的向量足够小,暴力解决方案是一种相当简单的方法(你的合法值比非法值少,所以检查合法值会更容易)。您还可以使用一个函数(此处概括):
function bits_set(v : std_logic_vector) return natural is
n : natural := 0;
begin
for i in v'range loop
if v(i) = '1' then
n := n + 1;
end if;
end loop;
return n;
end function bits_set;
不确定如何综合,但应该足够了。正如下面评论中所指出的,对于 n=4,这实际上在 Quartus 中似乎综合得相当好,至少。我很想知道其他工具的性能如何。正如 Morten 所说,它本来可以更有效地编码,特别是对于更大的位数(所以作为一个通用的解决方案,它比实际有用的更具说明性,我想)。
与对 fru1tbat 答案的评论相关,用于检测多个位集的替代函数可以是:
function bits_set_two_or_more(v : std_logic_vector) return std_logic is
variable one_or_more : std_logic := '0';
variable two_or_more : std_logic := '0';
begin
for i in v'range loop
if one_or_more = '0' then
one_or_more := v(i);
else -- one_or_more = '1'
two_or_more := two_or_more or v(i);
end if;
end loop;
return two_or_more;
end function;
使用 Altera Quartus II (QII) 与 Cyclone V 器件进行大量综合
space,显示在下面的"Or"栏,其中"Add > 1"栏是
bits_set(v) > 1
和 "N out" 列是从 bits_set(v)
输出的
获取表达式时QII减少多少的参考
bits_set(v) > 1
.
bits_set(v) > 1
的优化对于 QII 来说显然有点颠簸,
如 16 左右的 "Add > 1" 列所示,但 QII 实际上使用 bits_set(v) > 1
表达式来
减少逻辑,而不仅仅是进行愚蠢的比较。
当 v
设置了 n
位时,以下函数 returns 为真。
function is_nhot(v: std_logic_vector; n: natural) return boolean is
variable ret : boolean;
constant s : std_logic_vector(v'length-1 downto 0) := v;
begin
if n = 0 then
ret := s = (s'length-1 downto 0 => '0');
else
if s'length < n then
ret := false;
elsif s'length = n then
ret := s = (s'length-1 downto 0 => '1');
else
ret := ((s(s'length-1) = '1') and is_nhot(s(s'length-2 downto 0),n-1))
or ((s(s'length-1) = '0') and is_nhot(s(s'length-2 downto 0),n));
end if;
end if;
return ret;
end function;
理由是:
- 如果输入字符串s的位数少于n,则不能设置n位
- 如果s是n位长,则必须全部设置
- 如果s多于n位,递归比较
要检查 std_logic_vector 是否设置了 2 个或更多位,请使用
if not (is_nhot(v,0) or is_nhot(v,1)) then ...
基本上你想检查向量是否是 2 的幂。看看 https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
-- Taking the formula from the link above
-- f = (v & (v - 1)) == 0;
if (v and (v - 1)) > 0 then
-- at least 2 bits are set, hence an error occured
end if;
我没有干掉 运行 代码(我猜有些类型转换丢失了),但它应该可以很好地扩展。
我想知道如何确定四位 STD_LOGIC_VECTOR 中是否有超过一位设置为“1”。
例如,如果它是“1001”或“1100”或“1111”。
我正在编写一个程序,如果我的实体收到多个控制信号,我必须将错误信号设置为“1”。四个控制信号已合并为一个 4 位STD_LOGIC_VECTOR,我需要一种智能方法来确定是否设置了多个位。
我用
解决了with selvec select
ERR <= '0' when "0001",
'0' when "0010",
'0' when "0100",
'0' when "1000",
'0' when "0000",
'1' when others;
不是最简洁的代码,但它可以解决问题。
你的向量足够小,暴力解决方案是一种相当简单的方法(你的合法值比非法值少,所以检查合法值会更容易)。您还可以使用一个函数(此处概括):
function bits_set(v : std_logic_vector) return natural is
n : natural := 0;
begin
for i in v'range loop
if v(i) = '1' then
n := n + 1;
end if;
end loop;
return n;
end function bits_set;
不确定如何综合,但应该足够了。正如下面评论中所指出的,对于 n=4,这实际上在 Quartus 中似乎综合得相当好,至少。我很想知道其他工具的性能如何。正如 Morten 所说,它本来可以更有效地编码,特别是对于更大的位数(所以作为一个通用的解决方案,它比实际有用的更具说明性,我想)。
与对 fru1tbat 答案的评论相关,用于检测多个位集的替代函数可以是:
function bits_set_two_or_more(v : std_logic_vector) return std_logic is
variable one_or_more : std_logic := '0';
variable two_or_more : std_logic := '0';
begin
for i in v'range loop
if one_or_more = '0' then
one_or_more := v(i);
else -- one_or_more = '1'
two_or_more := two_or_more or v(i);
end if;
end loop;
return two_or_more;
end function;
使用 Altera Quartus II (QII) 与 Cyclone V 器件进行大量综合
space,显示在下面的"Or"栏,其中"Add > 1"栏是
bits_set(v) > 1
和 "N out" 列是从 bits_set(v)
输出的
获取表达式时QII减少多少的参考
bits_set(v) > 1
.
bits_set(v) > 1
的优化对于 QII 来说显然有点颠簸,
如 16 左右的 "Add > 1" 列所示,但 QII 实际上使用 bits_set(v) > 1
表达式来
减少逻辑,而不仅仅是进行愚蠢的比较。
当 v
设置了 n
位时,以下函数 returns 为真。
function is_nhot(v: std_logic_vector; n: natural) return boolean is
variable ret : boolean;
constant s : std_logic_vector(v'length-1 downto 0) := v;
begin
if n = 0 then
ret := s = (s'length-1 downto 0 => '0');
else
if s'length < n then
ret := false;
elsif s'length = n then
ret := s = (s'length-1 downto 0 => '1');
else
ret := ((s(s'length-1) = '1') and is_nhot(s(s'length-2 downto 0),n-1))
or ((s(s'length-1) = '0') and is_nhot(s(s'length-2 downto 0),n));
end if;
end if;
return ret;
end function;
理由是:
- 如果输入字符串s的位数少于n,则不能设置n位
- 如果s是n位长,则必须全部设置
- 如果s多于n位,递归比较
要检查 std_logic_vector 是否设置了 2 个或更多位,请使用
if not (is_nhot(v,0) or is_nhot(v,1)) then ...
基本上你想检查向量是否是 2 的幂。看看 https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
-- Taking the formula from the link above
-- f = (v & (v - 1)) == 0;
if (v and (v - 1)) > 0 then
-- at least 2 bits are set, hence an error occured
end if;
我没有干掉 运行 代码(我猜有些类型转换丢失了),但它应该可以很好地扩展。