在 VHDL 中阻止对 SIGNALS 的分配

Posted

技术标签:

【中文标题】在 VHDL 中阻止对 SIGNALS 的分配【英文标题】:Blocking Assignments on SIGNALS in VHDL 【发布时间】:2019-12-11 00:16:52 【问题描述】:

我正在使用 VHDL 制作 FSM。当 valid = 1 从 stateA 更改为 stateB 时,最简单的可能。

令人困惑的部分是蓝色矩形选择的上升沿。当有效 = '1'。在第一个上升沿,状态将被计算为 B,但直到下一个上升沿才会生效,但是发生了什么,它在第一个上升沿生效。

因为从 A 到 B 的状态变化应该会影响 NEXT 循环中设计中的其他部分(并行过程)。从波形来看,如果有效 = '1' 就在 CLK_1 之前。

在,CLK_1 所有其他进程应该看到状态 = A |波形正确 输出

状态 = A 进入最后一个周期 = 0

在,CLK_2 所有进程开始看到状态 = B。另一个并行 进程检查 state = B 然后它驱动 ENTERED_STATEB_LASTCYCLE 到 是1个波形正确输出

状态 = B 进入最后一个周期 = 0

然后在 CLK_3,波形正确输出

状态 = B 进入最后一个周期 = 1

我有什么误解吗?

Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.KDlib.all;

entity nearestPoint is
generic ( ARRAY_WIDTH : integer := 8);
    port (
        clk: in std_logic;
        reset: in std_logic;
        inpoint: in kdvector;
        valid: in std_logic;
        finished: buffer std_logic
        );

end nearestPoint;

architecture behave of nearestPoint is
signal state: two_state_type;
signal stateB_entered_lastCycle: std_logic;
begin

process ( clk )
begin
if ( reset = '1' ) then
elsif ( rising_edge(clk) ) then
    case state is
        when stateA =>
            if ( valid = '1' ) then
                state <= stateB;
            end if;
        when stateB =>
        when others =>
    end case;
end if;
end process;


process(clk)
begin
if ( reset = '1' ) then
elsif ( clk = '1' ) then
    case state is
        when stateA =>
        when stateB =>
            stateB_entered_lastCycle <= '1';
        when others =>
    end case;
end if;
end process;

end behave;

【问题讨论】:

您可能会发现这很有用。 ***.com/questions/13954193/… 我认为您缺少的是即使 clk = '1',第二个进程也看不到新的“状态”值,因为它直到下一个 clk 事件才被唤醒。有趣的是,如果您将“状态”添加到其敏感度列表中会发生什么?自己回答这个问题,然后尝试一下…… 【参考方案1】:

VHDL 没有阻塞/非阻塞分配的概念。有信号和变量,它们的分配方式不同。

在您的情况下,您需要记住模拟运行在一系列增量周期上。 1 个增量是无限小的时间空间,但它们是按顺序发生的。信号分配直到增量结束才生效,因此state = B 在时钟上升沿之后的增量周期内。第二个进程只对时钟敏感,因此在时钟再次上升之前它无法更新stateB_entered_lastcycle

【讨论】:

是的,完全使用 SIGNALS 应该始终是非阻塞赋值,因此在一个周期中从 A 到 B 的状态变化应该会影响 NEXT 周期中的其他进程。 这里发生了什么,它影响了与 BLOCKing 分配相同的事务周期中的其他进程 不,它没有。状态改变,然后另一个进程在下一个周期改变信号。如果您的代码,波形会显示确切的行为。【参考方案2】:

我将通过数字电路棱镜给你一个解释。这是开发VHDL时必须牢记的一种思维方式。

您的有效在时钟沿之前为 1。你在模拟中,所以你可以想象你所有的计算都是即时的。在您的触发器的输入端,您的状态的新值已经被计算出来。

我习惯于只使用一个顺序过程和一个或多个组合过程进行编码。也许你会更好地理解这段代码与你的功能相同(有点简化):

SEQ : process(clk, rst)
begin

  if rst = '1' then
    current_state <= '0';
  elsif rising_edge(clk) then
    current_state <= next_state;
  end if;

end process SEQ;

此代码对应的电路:

COMB : process(current_state, valid)
begin

  next_state <= current_state; -- Default value to ensure that next_state will always be affected

  if current_state = '0' and valid = '1' then
    next_state <= '1';
  end if;

end process COMB;

此代码对应的电路:

如果我们认为当 valid 更改时 next_state 会立即刷新,current_state(您的代码中的 state)在下一个时钟上升沿变高。

希望您能理解,如果您需要更精确,请不要犹豫,我可以编辑我的帖子或在 cmets 中回答。

重要提示:如果您在顺序流程中有异步重置,则它必须在敏感度列表中。

【讨论】:

只是为了增加混乱,原始帖子中的重置用作时钟启用(重置='1'时信号不能改变)。 确实如此,但我认为作者在发布代码之前删除了一些代码以简化代码,所以我想这if reset = '1' 中有些东西。他会告诉我们:) 是的,状态在第一个 clk 时应该等于 B,但这不应该影响同一周期中的其他并行进程如果查看波形,您可以看到 A 到 B 的事务发生在第一个 CYCLE 但它也影响了其他进程,这不应该发生(我不需要关心模拟中的设置/保持时间) 我认为故障是因为我在测试台中使用的异步有效信号。当我使用同步有效信号时,它按预期工作。此外,您的代码工作正常。非常感谢。你能推荐一本参考书/教科书来学习制作更复杂的设计吗? 对不起,我不知道关于这个主题的书 :(

以上是关于在 VHDL 中阻止对 SIGNALS 的分配的主要内容,如果未能解决你的问题,请参考以下文章

变量是不是也需要 VHDL 默认信号分配?

VHDL 信号分配没有明显的原因不起作用

用VHDL实现16*16点阵的显示 在用quartus ii 进行管脚分配的时候,该如何分配?(所选芯片为EP2C35F672C8)

VHDL基础2

如何在库存分配方案中阻止这种竞争条件? [关闭]

Mongoose 阻止将默认值分配给枚举