在 std_logic_vector 中生成规则模式

Generate regular pattern in std_logic_vector

我正在寻找一种资源有效的方法来设置 std_logic_vector 中特定位置的位。

假设我有一个 std_logic_vector 例如 signal a := std_logic_vector(LEN-1 downto 0) := (others => '0'), 其中 LEN 是泛型。 我想定期将它设置为 1,例如,在第五、第十……位置,其中间隔可能来自一组(小的)预定义数字, 例如,(5,10,20,25,30,40,50)。 实现此目的最节省资源的方法是什么?

显然这可以使用 for 循环和 mod 函数来实现。 但是,我想使用这种方法进行合成,因此 mod 函数可能会很昂贵。另一种可能性是展开循环。但是,由于 LEN 是通用的,我不知道步骤数。此外,我想排除不可能的组合,例如,如果 LEN = 20,应该排除 invervalls > 20

鉴于您的数字是预定义的,您只是在常数位位置和一个(少数)常数之间进行取模。这可以通过一组两个循环来完成,每个循环生成一个简单的 and/or 树。合成器很可能也可以消除一些通用逻辑。我可能会将步距编码为一个热,或者可能是一种树形,这样 5 也意味着 n*5。我想代码可能类似于:

component columns is
  generic (
    LEN     : integer;                  -- bits of output
    choices : integer;                  -- number of column combinations
      -- distances at which bits may be 1
    values  : array (0 to choices-1) of integer);
  port (
      -- one hot encoded distance choice
    distance : in  std_logic_vector(choices-1 downto 0);
      -- data which is 1 at selected distance
    bits     : out std_logic_vector(LEN-1 downto 0));
end component columns;

architecture behavioural of columns is

begin  -- architecture behavioural

  bitgen: for i in 0 to choices-1 generate
  begin
    -- purpose: calculate one individual bit
    -- type   : combinational
    -- inputs : distance
    -- outputs: bits(i)
    bitcalc: process (distance) is
      variable j : integer;
    begin  -- process bitcalc
      bits(i) <= '0';
      for j in 0 to chocies-1 loop
        if i mod values(j) = 0 and distance(j) then
          bits(i) <= '1';
        end if;
      end loop;  -- j
    end process bitcalc;
  end generate;

end architecture behavioural;

这只会产生少量或不同宽度的门。

Yann 的回答有几个问题,我想在这里解决,以便为那些不太精通 VHDL 语法的人提供答案。这不是对 Yann 选择的实现的批评,而是为了澄清语法问题。

首先,上面的例子并不完整。它描述了一个 component 语句,但没有相应的 entitycomponent 的使用仅在声明区域中,不能在 packagearchitecture 之外独立存在。正如所写,它不会编译。相反,它应该更改为:

entity columns is
...
end entity columns;

其次,不能在没有相应类型声明的情况下声明数组。即Yann中的例子post:

values  : array (0 to choices-1) of integer

无法完成。类型必须在使用前声明。为了使 component/entity 可见该类型,它必须在 componententity 之前定义。在entity的情况下,它需要在包中定义。例如:

package columns_pkg is
  type values_array is array(natural range <>) of integer;
end package columns_pkg;

那么columns_pkg就可以在entity中引用了。如:

library ieee;
use ieee.std_logic_1164.all;
use work.columns_pkg.all;

entity columns is
  generic (
    LEN     : integer;                  -- bits of output
    choices : integer;                  -- number of column combinations
      -- distances at which bits may be 1
    values  : values_array(0 to choices-1)
  );
  ...

现在,这仍然不太正确。只有在 VHDL-2008 中泛型才能相互依赖。也就是说,values的范围只能依赖于VHDL-2008中的choices。较早的语言版本要求它们不相关,这意味着上面 values 的声明在 VHDL-2002 及更早版本中将失败。

但事实证明 choices 甚至没有必要。相反,可以这样做(将它们放在一起并清理一些错别字):

library ieee;
use ieee.std_logic_1164.all;

package columns_pkg is
  type values_array is array(natural range <>) of integer;
end package columns_pkg;

library ieee;
use ieee.std_logic_1164.all;
use work.columns_pkg.all;

entity columns is
  generic
  (
    LEN     : integer;                  -- bits of output
    values  : values_array
  );
  port
  (
    -- one hot encoded distance choice
    distance : in  std_logic_vector(values'length-1 downto 0);
    -- data which is 1 at selected distance
    bits     : out std_logic_vector(LEN-1 downto 0)
  );
end entity columns;

architecture behavioural of columns is    
begin  -- architecture behavioural

  bitgen: for i in bits'range generate
  begin
    -- purpose: calculate one individual bit
    -- type   : combinational
    -- inputs : distance
    -- outputs: bits(i)
    bitcalc: process (distance) is
      variable j : integer;
    begin  -- process bitcalc
      bits(i) <= '0';
      for j in values'range loop
        if i mod values(j) = 0 and distance(j) = '1' then
          bits(i) <= '1';
        end if;
      end loop;  -- j
    end process bitcalc;
  end generate;

end architecture behavioural;

请注意 values 不受约束。长度将在制定时确定。并且可以利用属性来确定长度和范围。

另外,如果LENvalues的范围有关系,那么LEN泛型大概也可以去掉了。

最后,要利用 columns,可以这样做:

entity top is
end entity top;

use work.columns_pkg.all;

architecture behavioural of top is
  constant columns_values : values_array(0 to 5) := (0, 5, 10, 15);

  -- one hot encoded distance choice
  signal distance : std_logic_vector(columns_values'length-1 downto 0);

  -- data which is 1 at selected distance
  signal bits     : out std_logic_vector(31 downto 0);
begin
  columns_inst : entity work.columns
  generic map
  (
    LEN => bits'length,
    values => columns_values
  )
  port map
  (
    distance => distance,
    bits => bits
  );

end architecture behavioural;