如何在FPGA中实现无界循环?

时间:2016-05-05 05:22:02

标签: vhdl verilog fpga

我理解在HLS期间展开运行预定义迭代次数的循环。但是没有预定义边界的循环呢?如,

for (i = 0; i < j; i++) { ... }

如何在FPGA中实现这样的循环?

1 个答案:

答案 0 :(得分:5)

我不确定这是如何与VHDL或Verilog相关的,因为您明确声明了HLS并提出了C样式问题。但当然在VHDL中,未明确支持未绑定的循环。在某些情况下,您可以使用无界循环,但它们必须在某个时刻终止。

正如user1155120所指出的,不支持动态循环约束。但要稍微扩展一下。

编辑:最初我使用了术语&#34;无界&#34;什么时候我应该说&#34;动态范围&#34;循环。我用这种语言更新了答案。

因此,首先,支持一些具有伪动态范围的循环。例如:

for i in 0 to 7 loop
  for j in 0 to i loop
    ...
  end loop;
end loop;

这真的不动态,因为它们很容易展开。合成器可以确定此循环的边界。显然j只能从0到7.但是不支持其他类型的动态循环:

signal a : natural;
...
for i in 0 to a loop
...
end loop;

在这种情况下,循环的范围不是静态已知的。

但是有一种方法可以动态地绑定&#34;基于输入的循环,但它确实需要知道输入的边界。人们可以这样做:

signal a : natural range 0 to 7;
...
for i in 0 to 7 loop
  if ( i < a ) then
    ...
  end if;
end loop;

现在循环实际上只能运行a的值。 (这里有一些注意事项。当这样做时,内存 - 触发器或锁存器取决于上下文 - 可以在if / end if内推断出那些环路提前终止的情况。避免它,但这超出了这个答案的范围。)

RTL无法合成动态结构。因此,您的设计必须根据最大可能情况进行调整,然后动态选择最多支持的迭代次数。

最后一点说明。支持无界循环(while循环),但它确实需要终止循环。让我们来看一下典型的自由运行计数器示例:

signal ctr : unsigned(31 downto 0) := (others => '0');
...
process(clk)
begin
  if ( rising_edge(clk) ) then
    ctr <= ctr + 1;
  end if;
end process;

这也可以用另一种方式表达:

process
begin
  wait until rising_edge(clk);
  ctr <= ctr + 1;
end process;

可以使用无界循环,例如:

process
begin
  while true loop
    wait until rising_edge(clk);
    ctr <= ctr + 1;
  end loop;
end process;

所有这些都是可综合的。

警告 以下讨论是疯狂的内容,不应将其用作代码示例。这些示例仅供讨论之用。

动态范围循环是可综合的,但它们的功能并不清晰。例如:

signal a   : natural := 33;
signal ctr : natural := 0;
...
process
begin
  for i in 0 to a-1 loop
    wait until rising_edge(clk);
    ctr <= ctr + 1;
  end loop;
end process;

甚至是一个无限循环:

process
  variable i : natural := 0;
begin
  while i < a loop
    wait until rising_edge(clk);
    ctr <= ctr + 1;
  end loop;
end process;

这两者都合成。但后者尤其成问题,因为它不能很好地模拟,特别是当i&gt; = a时。