在std_logic_vector中生成常规模式

时间:2016-06-13 07:19:22

标签: vhdl fpga synthesis

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

我们假设我有一个std_logic_vector,例如signal a := std_logic_vector(LEN-1 downto 0) := (others => '0'), 其中LEN是通用的。 我想在常规的intervalls中将它设置为1,例如,在第五,第十,......位置,其中intervall可能来自(一小组)预定义数字, 例如,(5,10,20,25,30,40,50)。 实现这一目标的最省钱方法是什么?

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

2 个答案:

答案 0 :(得分:1)

Yann的回答有一些我想在这里提出的问题,为那些不太熟悉VHDL语法的人提供答案。这不是对Yann选择的实现的批评,而是澄清语法问题。

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

entity columns is
...
end entity columns;

其次,如果没有相应的类型声明,就无法声明数组。也就是Yann的帖子中的例子:

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

无法完成。必须先声明类型才能使用它。并且为了使该类型对组件/实体可见,必须在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;

答案 1 :(得分:0)

鉴于您的数字是预定义的,您只是在恒定位位置和一个(少数)常数之间进行模数运算。这可以通过一组两个循环来完成,每个循环产生一个简单和/或树。合成器很可能也可以消除一些常见的逻辑。我可能会将步距编码为一个热点,或者可能是树形式,这样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;

这应该只产生一些不同宽度的门或门。