我知道在HLS期间展开运行预定义迭代次数的循环.但是没有预定义边界的循环呢?例如,
for (i = 0; i < j; i++) { ... }
Run Code Online (Sandbox Code Playgroud)
如何在FPGA中实现这样的循环?
我不确定这是如何与VHDL或Verilog相关的,因为你明确声明了HLS并给出了一个C风格的问题.但当然在VHDL中,未明确支持未绑定的循环.在某些情况下,您可以使用无界循环,但它们必须在某个时刻终止.
正如user1155120指出的那样,不支持动态循环约束.但要扩大一点.
编辑:当我应该说"动态范围"循环时,我最初使用术语"无界".我用这种语言更新了答案.
因此,首先,支持一些具有伪动态范围的循环.例如:
for i in 0 to 7 loop
for j in 0 to i loop
...
end loop;
end loop;
Run Code Online (Sandbox Code Playgroud)
这真的不是动态的,因为它们很容易展开.合成器可以确定此循环的边界.显然j只能从0到7.但是不支持其他类型的动态循环:
signal a : natural;
...
for i in 0 to a loop
...
end loop;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,循环的范围不是静态已知的.
但是有一种方法可以根据输入动态"绑定"循环,但它确实需要知道输入的边界.人们可以这样做:
signal a : natural range 0 to 7;
...
for i in 0 to 7 loop
if ( i < a ) then
...
end if;
end loop;
Run Code Online (Sandbox Code Playgroud)
现在循环有效地仅运行到的值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;
Run Code Online (Sandbox Code Playgroud)
这也可以用另一种方式表达:
process
begin
wait until rising_edge(clk);
ctr <= ctr + 1;
end process;
Run Code Online (Sandbox Code Playgroud)
并且可以使用无界循环,例如:
process
begin
while true loop
wait until rising_edge(clk);
ctr <= ctr + 1;
end loop;
end process;
Run Code Online (Sandbox Code Playgroud)
所有这些都是可综合的.
警告以下讨论是疯狂的事情,不应该用作代码的示例.这些示例仅供讨论之用.
动态范围循环是可综合的,尽管它们的功能尚不清楚.例如:
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;
Run Code Online (Sandbox Code Playgroud)
甚至是无限循环:
process
variable i : natural := 0;
begin
while i < a loop
wait until rising_edge(clk);
ctr <= ctr + 1;
end loop;
end process;
Run Code Online (Sandbox Code Playgroud)
这两者都合成.但后者尤其成问题,因为它不能很好地模拟,特别是当i> =时a.