我理解在HLS期间展开运行预定义迭代次数的循环。但是没有预定义边界的循环呢?如,
for (i = 0; i < j; i++) { ... }
如何在FPGA中实现这样的循环?
答案 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
时。