错误:超出了非静态循环限制

时间:2013-03-21 14:50:30

标签: vhdl

下面是非恢复平方根算法。它工作正常,但在综合过程中显示错误:“第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;

3 个答案:

答案 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
        ...