【问题标题】:Use alias-like variable in for loops在 for 循环中使用类似别名的变量
【发布时间】:2020-09-08 01:14:53
【问题描述】:

是否可以创建别名变量/信号来提高 VHDL 进程中for 循环的可读性?

例如,考虑以下模块,它包含一个带有内部 for 循环的进程(代码是为了举例,我没有测试它):

library ieee;
use ieee.std_logic_1164.all;

entity MyModule is
  port (
    clk                 : in  std_logic;
    inData              : in  std_logic_vector(7 downto 0);
    outData             : out std_logic_vector(7 downto 0));
end MyModule;

architecture functional of MyModule is
  type sample_vector  is array (natural range <>) of std_logic_vector(9 downto 0);
  type data_t is record
    samples     : sample_vector(3 downto 0);
    -- other elements...
  end record data_t;
  type data_vector  is array (natural range <>) of data_t;
  signal data  : data_vector(1 downto 0);

begin  -- functional
  process (clk)
  begin  -- process
    if clk'event and clk = '1' then
      -- Set outData(N) to '1' if at least 1 of the last 10 values of inData(N) was '1'
      for d in data'RANGE loop
        for s in data(0).samples'RANGE loop
          data(d).samples(s)(9 downto 1) <= data(d).samples(s)(8 downto 0);
          data(d).samples(s)(0) <= inData(d * 4 + s);
          outData(d * 4 + s) <= '0';
          for b in data(d).samples(s)'RANGE loop
            if data(d).samples(s)(b) = '1' then
              outData(d * 4 + s) <= '1';
            end if;
          end loop;
        end loop;
      end loop;
    end if;
  end process;

end functional;

每次我需要引用该信号时都必须使用data(d).samples(s) 很麻烦,所以我宁愿使用类似别名的变量,而不是类似的东西(灵感来自generate 语法,idx 部分只是奖金):

      -- Set outData(N) to '1' if at least 1 of the last 10 values of inData(N) was '1'
      for d in data'RANGE loop
        for s in data(0).samples'RANGE loop
          alias sample  : std_logic_vector(9 downto 0) is data(d).samples(s);
          constant idx  : integer := d * 4 + s;
        begin
          sample(9 downto 1) <= sample(8 downto 0);
          sample(0) <= inData(idx);
          outData(idx) <= '0';
          for b in sample'RANGE loop
            if sample(b) = '1' then
              outData(idx) <= '1';
            end if;
          end loop;
        end loop;
      end loop;

当然,这是行不通的。那么,有没有办法在 VHDL 中实现类似的功能,还是我们每次都必须指定完整的信号“路径”?

我可以用一个过程替换循环体,但是必须在文件的(很远的)不同位置声明过程代码会进一步降低可读性。我也可以使用 for ... generate 构造,但这会为每次迭代创建 1 个进程,并阻止我在迭代中使用公共进程变量。

【问题讨论】:

  • 表达式id * 4 + s可以产生一个超出inData索引范围的值提供一个无错误的minimal reproducible example作为压缩的基础,从而可以演示解决方案。 For 循环语句不允许循环参数以外的声明。注意idxsample 可以是包含for 循环的声明区域中的变量,并在for 循环中使用参数s 分配。
  • @user1155120 我已经修复了示例以匹配您的评论,谢谢。如果我使用流程变量来实现该别名概念,我担心综合工具可能不会将迭代实现为并行路径,因为每次迭代都将取决于变量值并且每次迭代都会更改该值。我知道该值只会在每次迭代开始时发生变化,因此迭代之间没有依赖关系,但我不确定合成工具是否足够聪明以找出...
  • 通过展开循环,可以清楚地看出综合工具如何找出迭代之间未重用的过程变量值。 Vivado 至少生产相同的网络。 @user1155120 感谢您的建议。如果您想使用该解决方案发布答案​​,我会接受。

标签: for-loop vhdl alias


【解决方案1】:

如问题 cmets 所示,这可以使用流程变量来实现:

  process (clk)
    variable sample : std_logic_vector(9 downto 0);
    variable idx    : integer;
  begin  -- process
    if clk'event and clk = '1' then
      -- Set outData(N) to '1' if at least 1 of the last 10 values of inData(N) was '1'
      for d in data'RANGE loop
        for s in data(0).samples'RANGE loop
          -- Helpers
          sample := data(d).samples(s);
          idx := d * 4 + s;

          outData(idx) <= '0';
          for b in sample'RANGE loop
            if sample(b) = '1' then
              outData(idx) <= '1';
            end if;
          end loop;
          sample(9 downto 1) <= sample(8 downto 0);
          sample(0) <= inData(idx);

          -- Do not forget to apply changes
          data(d).samples(s) <= sample;
        end loop;
      end loop;
    end if;
  end process;

当然,使用流程变量意味着更改操作顺序以获得相同的行为。

由于过程变量是在循环中读取和写入的,我担心合成工具会认为迭代N 的结果依赖于迭代N-1 的结果,并且make 会按顺序执行迭代(而不是在平行下)。然而,在展开循环后(这是综合工具所做的),很明显综合工具将看到 sampleidx 值不会在迭代之间重复使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-19
    • 2018-07-04
    • 2019-09-30
    • 2019-12-19
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    相关资源
    最近更新 更多