据我了解,运行预定义迭代次数的循环会在 HLS 期间展开。但是没有预定义边界的循环又如何呢?例如,
for (i = 0; i < j; i++) { ... }
如何在 FPGA 中实现此类循环?
最佳答案
我不确定这与 VHDL 或 Verilog 有何关系,因为您明确说明了 HLS 并给出了 C 风格的问题。但在 VHDL 中,未明确支持未绑定(bind)循环。在某些情况下,您可以使用无界循环,但它们必须在某个时刻终止。
正如用户1155120所指出的,不支持动态循环约束。但稍微扩展一下。
编辑:最初,当我应该说“动态范围”循环时,我使用了“无界”一词。我已经用该语言更新了答案。
因此,首先,支持某些类型的具有伪动态范围的循环。例如:
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;
在这种情况下,循环的范围是静态未知的。
但是有一种方法可以根据输入动态“绑定(bind)”循环,但它确实需要了解输入的边界。人们可以做这样的事情:
signal a : natural range 0 to 7;
...
for i in 0 to 7 loop
if ( i < a ) then
...
end if;
end loop;
现在,循环仅有效地运行到 a
的值。 (这里需要注意一些。在执行此操作时,对于那些循环提前终止。有一些方法可以避免它,但这超出了本答案的范围。)
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
>= a
时。
关于vhdl - 如何在 FPGA 中实现无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37042981/