首页 > 解决方案 > 如何在不使用 for 循环的情况下获取 one-hot 编码向量的索引?

问题描述

我有一个信号“event_id”,其中任何时候只有一个位为高。我需要将此单热编码信号转换为索引的整数值。

信号:

signal event_id: std_logic_vector(3 downto 0);
signal event_index: natural;

我知道我可以用 for 循环做到这一点。这就是我目前正在做的事情:

for i in 3 downto 0 loop
    if(event_id(i) = '1') then
      event_index = i;
    end if;
end loop;

有没有更好的方法来做到这一点,不需要for循环或单独遍历每一位?我知道我可以使用 for-loop 方法创建一个函数,但我觉得应该有一个我缺少的简单解决方案。

标签: vhdlhdl

解决方案


没有用于在 VHDL 中生成 one-hot 向量索引的“简单”解决方案。

对于 4 位的 one-hot 向量,因此结果索引为 2 位,您所做的循环是一个好的解决方案,它是可读的并且在实现中不会占用太多资源。虽然它不是最小的解决方案,因为它不允许实现大小从 one-hot 属性中受益,因为它返回设置位的最低索引。对于简短的 one-hot 向量,如果实现是在 FPGA 中,这并不重要,因为它使用量化的 LUT 资源。

对于较长的 one-hot 向量,如果使用 one-hot 属性,则实现将更小。这可以通过一种算法来完成,其中索引位是从 one-hot 向量和掩码生成的。下面显示了一个函数。

-- One hot to index calculate; assuming LEN_HOT = 2 ** LEN_IDX
function hot2idx_cal(hot : std_logic_vector) return std_logic_vector is
  variable mask_v : std_logic_vector(LEN_HOT - 1 downto 0);
  variable res_v  : std_logic_vector(LEN_IDX - 1 downto 0);
begin
  for i in 0 to LEN_IDX - 1 loop
    -- Generate mask
    for j in 0 to LEN_HOT - 1 loop
      if ((j / (2 ** i)) mod 2) = 0 then
        mask_v(j) := '0';
      else
        mask_v(j) := '1';
      end if;
    end loop;
    -- Apply mask and generate bit in index
    if unsigned(hot and mask_v) = 0 then
      res_v(i) := '0';
    else
      res_v(i) := '1';
    end if;
  end loop;
  return res_v;
end function;

推荐阅读