错误(10818):无法推断...的寄存器...因为它不在时钟边沿之外保持其值

时间:2014-07-24 20:45:40

标签: vhdl quartus

我正在尝试验证四个按钮。当其中一个被按下时,我需要检查相应的LED是否点亮。所以,我做了代码,其中一个进程检查按下了哪个按钮,并将值与led的值进行比较(是否点亮)。当我想增加控制播放器的点击次数(成功)的变量时,会出现问题。

记住“acertos”是std_logic_vector类型的信号(3 downto 0)

process(pb0,pb1,pb2,pb3)
    variable erro_int   : STD_LOGIC;
begin
    if (clk_game = '0') then
        erro_int:='0';
        if rising_edge(pb0) then
            if pb0 /= led(0) then 
                erro_int:='1';
            end if;
        elsif rising_edge(pb1) then
            if pb1 /= led(1) then 
                erro_int:='1';
            end if;
        elsif rising_edge(pb2) then
            if pb2 /= led(2) then 
                erro_int:='1'; 
            end if;
        elsif rising_edge(pb3) then
            if pb3 /= led(3) then 
                erro_int:='1'; 
            end if;
        else    
            acertos <= acertos+1;
        end if;
    end if;
end process;

1 个答案:

答案 0 :(得分:0)

请参阅Error (10818): Can't infer register for “E” at clk200Hz.vhd(29) because it does not hold its value outside the clock edge,其中演示了完全相同的错误案例。通常,您也会被鼓励使用供应商作为其错误消息的资源。

这里的错误情况表明,acertos赋值不是在条件赋值语句中发生的,而是取决于用作时钟的信号事件。

然而,这并不是您从某些设计规范中向我们展示过程中可能遇到的潜在问题的终结。

问题是信号pb0pb1pb2pb3是否被反弹过滤。参见Wentworth Institute of Technology Department of Electronics and Mechanical ELEC 236 Logic Circuits Switch Debounce Design,其中第一个示波器轨迹显示正常拉高的瞬时开关,连接到接地开关输入。问题是联系人反弹。该网页谈到了一些解决方案。

去抖动允许您将按钮输入用作时钟,但您的过程中还有其他问题。

例如,某些供应商不会在同一个流程声明中接受多个时钟,您的设计规范可能无法移植。

没有公认的顺序事件推断存储元素构造允许同一存储元素(erro_int)的多个时钟。因为没有相互依赖性的连续if语句所表示的模拟时间没有通过,所以可能只有最后一个表达式被表示为硬件。

您可以将所有按钮组合成一个信号:

button_press <= not (not pb0 and not pb1 and not pb2 and not bp3);

当按下任何按钮时,按下任何按钮都会导致边缘事件。

如果您反弹,请说使用计数器并测试连续的事件,您可以将其用作唯一的时钟。

让我们假设以下它被反弹了。在erro_out的流程语句中设置默认值会为您提供类似于以下内容的流程:

process(button_press)
    variable erro_int: std_logic;
begin
    if (clk_game = '0') then
        erro_int:='0';
        if rising_edge(button_press) then
            if pb0 /= led(0)  or pb1 /= led(1) or pb1 /= led(2) or pb3 /=pb3 then 
                erro_int:= '1';
            end if;
        acertos <= acertos + 1;
    end if;
end process;

(我查了一下acertos的翻译 - 点击,不一定是有效点击,我认为这是游戏。)

这仍然无法解决erro_int是局部变量的问题。如果它在其他地方使用,它希望被声明为信号。如果您将流程更改为:

...
signal erro_int:   std_logic;  -- defined say as an architecture declarative item
...

process(button_press)
begin
    if (clk_game = '0') then
        erro_int <='0';
        if rising_edge(button_press) then
            if pb0 /= led(0)  or pb1 /= led(1) or pb1 /= led(2) or pb3 /=pb3 then 
                erro_int <= '1';
            end if;
        acertos <= acertos + 1;
    end if;
end process;

您可以在外部使用它。这样做的原因是一个进程只有一个信号驱动器,而当前模拟时的最后一个赋值是生效的(当前模拟时间只有一个赋值)。

当然,如果你使用时钟去抖动,你可以使用button_press作为启用,如果它被选通只持续一个时钟。