在 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 之前。
状态 = A 进入最后一个周期 = 0在,CLK_1 所有其他进程应该看到状态 = A |波形正确 输出
状态 = B 进入最后一个周期 = 0在,CLK_2 所有进程开始看到状态 = B。另一个并行 进程检查 state = B 然后它驱动 ENTERED_STATEB_LASTCYCLE 到 是1个波形正确输出
状态 = B 进入最后一个周期 = 1然后在 CLK_3,波形正确输出
我有什么误解吗?
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实现16*16点阵的显示 在用quartus ii 进行管脚分配的时候,该如何分配?(所选芯片为EP2C35F672C8)