下面是非恢复平方根算法。它工作正常,但在综合过程中显示错误:“第46行:超出非静态循环限制”。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
ENTITY code IS
GENERIC(n: NATURAL:= 8);
PORT(
Xin: IN STD_LOGIC_VECTOR(2*n-1 DOWNTO 0);
clk :IN STD_LOGIC ;
root: OUT STD_LOGIC_VECTOR(n-1 DOWNTO 0) ;
root2: OUT STD_LOGIC_VECTOR(2*n-1 DOWNTO 0) ;
intval: IN STD_LOGIC_VECTOR(n-1 DOWNTO 0)
);
END code;
architecture Behavioral of code is
Signal Outp : STD_LOGIC_VECTOR(n-1 DOWNTO 0);
Signal Const1 : STD_LOGIC_VECTOR(n-1 DOWNTO 0) ;
Signal Const2 : STD_LOGIC_VECTOR(n-1 DOWNTO 0) ;
--Signal Var : STD_LOGIC_VECTOR(n-1 DOWNTO 0);
begin
Const1 <= "00000010";
Const2 <= "00000000";
--D <= intval;
--Var <= intval;
Process (clk)
Variable Acc1 : STD_LOGIC_VECTOR(2*n-1 DOWNTO 0);
Variable Acc2 : STD_LOGIC_VECTOR(n-1 DOWNTO 0);
Variable D : STD_LOGIC_VECTOR(n-1 DOWNTO 0);
Variable Var : STD_LOGIC_VECTOR(n-1 DOWNTO 0);
Variable Q : STD_LOGIC_VECTOR(2*n-1 DOWNTO 0);
begin
Var := "00000000";
D := intval;
Var := intval;
while (Var > "00000000") loop
Q := signed(D)*signed(D);
Acc1 := signed(Xin) - signed(Q);
if (Acc1 = "0000000000000000") then
var:= Const2;
elsif (Acc1 < "1000000000000000") then
--root2<=Acc1;
Acc2 := '0' & var(n-1 downto 1);
Var := Acc2;
D := signed(D) + signed(Var);
elsif (Acc1 > "0111111111111111") then
--root2<=Acc1;
Acc2 := '0' & var(n-1 downto 1);
Var := Acc2;
--root <= Var;
D := signed(D) - signed(Var);
end if;
end loop;
Outp <= D;
end process;
root <= Outp;
end Behavioral;
答案 0 :(得分:5)
除非您正确地重新格式化,否则我不打算阅读该代码。所以我只是给你一个问题的近似描述。 [编辑:有些人确实重新格式化了]
合成在处理具有非静态边界的循环方面不是很好。当您考虑它时,这应该是显而易见的:对于合成,循环(除非它们包括显式WAIT语句)被展开,直到每个迭代可以并行执行。这意味着循环边界定义了生成的硬件的大小。
所以非静态界限意味着在硬件实际运行之前你不知道需要多少硬件!到那时生成更多的门有点太晚了......
答案是将算法转换为具有静态循环边界的等效算法。在实践中,这通常并不困难:简单地转换
while (Var > "00000000") loop
do something;
end loop;
到
constant max_iterations : natural := <some number>;
for i in 1 to max_iterations loop
-- assuming Var is numeric_std.unsigned, you can simply compare it to 0
if Var > 0 then
do something
end if;
end loop;
答案 1 :(得分:1)
您的流程对clk
敏感。
但是,您还需要(对于合成器)说出您想要处理的时钟边缘。
模拟器将在每个时钟边沿(上升和下降)运行代码。合成器将一直运行代码,它真的想看时钟边缘。
如果您将流程文本包装在
中if rising_edge(clk) then
end if;
短语,它会有所帮助。
答案 2 :(得分:0)
请注意您正在定义硬件!当循环在合成中展开时,边界必须是静态的。
然而,即使你使用带有静态边界的for循环,你很可能会定义很多资源(例如n = 8,你会得到256个乘数!),这些资源可能在真实系统中不可用。尝试调整代码以使用一些流水线并优化资源和速度!
对于可合成代码,您不仅应将时钟放在灵敏度列表中,还应定义有效时钟边沿
Process (clk)
...
begin
if rising_edge(clk) then
...