如何确定在 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;

理由是:

  1. 如果输入字符串s的位数少于n,则不能设置n位
  2. 如果s是n位长,则必须全部设置
  3. 如果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;

我没有干掉 运行 代码(我猜有些类型转换丢失了),但它应该可以很好地扩展。