ERROR 10818 - 无法推断寄存器,因为它不会在时钟边沿之外保持其值

时间:2018-01-23 18:35:22

标签: compiler-errors vhdl fpga intel-fpga quartus

我正在处理修改过的Gauss-Jordan消除器的代码,并且我得到了错误:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.all;
USE IEEE.STD_LOGIC_ARITH.ALL;

PACKAGE matriz IS
    TYPE matrix IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(1 TO 7);
    TYPE vector IS ARRAY (NATURAL RANGE <>) OF INTEGER;
END matriz;

USE work.matriz.all;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.all;
USE IEEE.STD_LOGIC_ARITH.ALL;

ENTITY bloco2 IS
    GENERIC (m: integer:= 4;
                n: integer:= 7;
                k: integer:= 3);
    PORT (clk,rst: IN STD_LOGIC;
            s: IN vector(1 TO n);
            G: IN matrix(1 TO m);
            Gr0, Gr: OUT matrix(1 TO m));
END bloco2;

ARCHITECTURE bloco2 OF bloco2 IS

SIGNAL Grt: matrix(1 TO m):= (OTHERS=>(OTHERS=>'0'));
SIGNAL Gr0t: matrix(1 TO m):= (OTHERS =>(OTHERS=>'0'));
SIGNAL st: vector(1 TO n):= (OTHERS=>0);

SIGNAL temp1: STD_LOGIC_VECTOR(1 TO n):= (OTHERS=>'0');
SIGNAL temp2: STD_LOGIC_VECTOR(1 TO n):= (OTHERS=>'0');
SIGNAL verify: STD_LOGIC:= '0';

BEGIN

    PROCESS(clk, rst, G, Grt, Gr0t, st, s, verify, temp1, temp2)
    VARIABLE L: INTEGER:= 1;
    VARIABLE c: INTEGER:= 1;
    VARIABLE count: INTEGER:= 0;
    BEGIN

        Grt<=G;
        st<=s;

        IF rst='0' THEN
            IF (rising_edge(clk))THEN
                IF count <= 3 THEN
                    IF Grt(L)(st(c))='1' THEN
                                Gr0t(L)(st(c))<='1';
                                FOR i IN 1 TO m LOOP
                                    verify <= Grt(i)(st(c));
                                    FOR j IN 1 TO n LOOP
                                        IF ((i/=L) and (verify/='0')) THEN
                                            Grt(i)(j)<= Grt(L)(j) xor Grt(i)(j);
                                        END IF;
                                    END LOOP;
                                END LOOP;
                                count:=count+1;
                                L:=L+1;
                                c:=c+1;
                    END IF;

                    IF Grt(L)(st(c))='0' THEN
                        FOR i IN 1 TO m LOOP
                                IF i > L THEN
                                    IF Grt(i)(st(c)) ='1' THEN
                                     temp1<= Grt(L)(1 TO n);
                                     temp2<= Grt(i)(1 TO n);
                                     Grt(i)(1 TO n)<= temp1;
                                     Grt(L)(1 TO n)<= temp2;
                                     exit;
                                    END IF;
                                END IF;
                        END LOOP;   

                        IF Grt(L)(st(c)) /='1' THEN
                            c:=c+1;
                        END IF;
                    END IF;

                END IF;
            END IF;

        END IF;

        IF rst='1' THEN
            Gr0t <= (OTHERS=>(OTHERS=>'0'));
            Grt <= (OTHERS => (OTHERS =>'0'));

        END IF;
    Gr<=Grt;
    Gr0<=Gr0t;
END PROCESS;
END bloco2;
  

错误(10818):无法推断&#34; Grt [4] [7]&#34;在bloco2.vhd(50)因为它没有在时钟边缘之外保持其值。

P.S。:对于矩阵Grt的每个位置都会发生。

有人可以帮我理解这里发生了什么吗? PS :在我的代码中,我只使用IF结构,没有任何ELSEELSIF,因为我已阅读这可能是问题的原因,但在我的情况下,这个提示没有用。

1 个答案:

答案 0 :(得分:3)

要了解的几个基本事项。

  • 仅在进程暂停时更新信号。这将位于进程敏感性列表(您的情况)或等待语句(通常在测试平台中)。
  • 合成工具只能理解非常有限的语言子集,特别是挑剔的WRT触发器。
  • 如果您的过程使用综合工具进行了适当的便携性结构,那么您只需要在敏感度列表中使用时钟和异步控制(以及异步加载的数据,但不要)。

让我们以1076.6-1999的方式重写您的代码。

由于您的进程没有wait语句,因此所有代码都在相同的delta周期内执行。在过程的时钟/重置部分之外完成的任何信号分配可以同时完成。因此,我们将在设计的体系结构代码区域(而不是在进程中)编写以下代码:

Grt<=G;
st<=s;
Gr<=Grt;
Gr0<=Gr0t;

您编码的重置是异步的。一个便携式模板是:

PROCESS(clk, rst)
BEGIN
    IF rst='1' THEN
      . . . 

    elsif (rising_edge(clk))THEN
      .  .  .

    END IF;
END PROCESS;

您的代码更接近下面的模板。一个我喜欢的,但它的便携性稍差。请注意,在此分支中,时钟分支不以复位为条件,并且复位分支中的任何分配都会覆盖时钟分支中的设置。我建议首先从上面开始,让它在模拟和合成中正常工作,然后如果你真的想切换回来。

PROCESS(clk, rst)
BEGIN
    if (rising_edge(clk))THEN
      .  .  .

    END IF;
    IF rst='1' THEN
      . . . 
    END IF;
END PROCESS;

以下是您的代码,其中包含并发信号。我没有对其他可能存在问题的问题进行任何更改。

PROCESS(clk, rst)
VARIABLE L: INTEGER:= 1;
VARIABLE c: INTEGER:= 1;
VARIABLE count: INTEGER:= 0;
BEGIN
    IF rst='1' THEN
        Gr0t <= (OTHERS=>(OTHERS=>'0'));
        Grt <= (OTHERS => (OTHERS =>'0'));

    elsif (rising_edge(clk))THEN
            IF count <= 3 THEN
                IF Grt(L)(st(c))='1' THEN
                            Gr0t(L)(st(c))<='1';
                            FOR i IN 1 TO m LOOP
                                verify <= Grt(i)(st(c));
                                FOR j IN 1 TO n LOOP
                                    IF ((i/=L) and (verify/='0')) THEN
                                        Grt(i)(j)<= Grt(L)(j) xor Grt(i)(j);
                                    END IF;
                                END LOOP;
                            END LOOP;
                            count:=count+1;
                            L:=L+1;
                            c:=c+1;
                END IF;

                IF Grt(L)(st(c))='0' THEN
                    FOR i IN 1 TO m LOOP
                            IF i > L THEN
                                IF Grt(i)(st(c)) ='1' THEN
                                 temp1<= Grt(L)(1 TO n);
                                 temp2<= Grt(i)(1 TO n);
                                 Grt(i)(1 TO n)<= temp1;
                                 Grt(L)(1 TO n)<= temp2;
                                 exit;
                                END IF;
                            END IF;
                    END LOOP;   

                    IF Grt(L)(st(c)) /='1' THEN
                        c:=c+1;
                    END IF;
                END IF;
            END IF;
    END IF;
END PROCESS;

要考虑的一些事情:

  • Grt0仅在一个地方被分配。复位后会累积1。
  • 你对Temp1和Temp2的意图是什么?信号不会立即更新,因此它们不会交换值。如果您需要此行为,请使用变量或删除Temp1和Temp2并直接执行分配。
  • 您的验证意图是什么?根据其用法,它可能也需要变量。