0

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

3 回答 3

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;
于 2013-03-21T15:18:33.710 回答
1

您的过程对clk.

但是,您还需要(对于合成器)说出您想要处理的时钟边缘。

模拟器将在每个时钟沿(上升沿和下降沿)运行您的代码。合成器会一直运行代码,它真的很想看到时钟边沿。

如果您将流程文本包装在

if rising_edge(clk) then

end if;

短语,它会有所帮助。

于 2013-03-22T12:28:54.820 回答
0

请注意,您正在定义硬件!由于循环在综合中展开,边界必须是静态的。

但是,即使您使用带有静态边界的 for 循环,您也很可能会定义大量资源(例如,当 n=8 时,您将导致 256 个乘数!)在实际系统中可能不可用。尝试调整您的代码以使用一些流水线并优化资源和速度!

对于可综合代码,您不仅应该将时钟放在灵敏度列表中,还应该定义活动时钟沿

Process (clk)      
    ...   
begin
    if rising_edge(clk) then
        ...
于 2013-03-22T06:50:33.513 回答