这是我正在运行的代码
architecture arch of func
signal sig_s1: std_logic;
begin
process(d1,d2,d3)
begin
sig_s1 <= d1 and d2;
res2 <= sig_s1 xor d3;
end process;
end arch;
您可能希望 res2 始终使用之前的 sig_s1 值,但在模拟中它会使用更新后的值,就像这是一个顺序代码。是什么给了什么?
这里是波形https://i.imgur.com/SezncCS.jpg(如果我使用变量代替sig_s1的信号,则res1是结果)。我不知道基准测试的工作原理。
答案 0 :(得分:2)
在所有进程暂停之前,信号不会得到更新。
假设d1
,d2
或d3
中的一个或多个发生了更改(事件)。它们位于流程的敏感列表中,因此流程开始执行。
1)首先执行此行:sig_s1 <= d1 and d2;
。这是一个包含信号分配的行(<=
)。如果要更改该信号的值,则执行具有信号分配的任何行的效果是在将来的某个时间安排该变化。如果没有指定延迟(这里是这种情况),则该未来时间是模拟的下一次迭代,一旦所有进程完成执行(已暂停),将发生。
2)然后这一行被执行res2 <= sig_s1 xor d3;
。由于执行上一行的效果是在sig_s1
计划未来的更改,执行此行时信号sig_s1
的值尚未更改。这真的非常重要。因此粗体。因此,信号sig_s1
的先前值将用于评估表达式sig_s1 xor d3
。如果这导致信号res2
发生变化,那么该变化也将安排用于下一次模拟迭代。
您的问题有各种解决方案。最简单的方法是将信号sig_s1
添加到灵敏度列表中:
architecture arch of func
signal sig_s1: std_logic;
begin
process(d1,d2,d3,sig_s1)
begin
sig_s1 <= d1 and d2;
res2 <= sig_s1 xor d3;
end process;
end arch;
然后,一旦对信号sig_s1
进行任何更改,该过程将再次执行(因为信号sig_s1
现在位于敏感度列表中。此行将首先执行sig_s1 <= d1 and d2
并且,假设信号d1
和d2
尚未再次更改,信号sig_s1
将不会发生变化。然后线res2 <= sig_s1 xor d3
将立即执行。 sig_s1
现在将具有其新值,因此信号res2
的值将更新(在下一次模拟迭代中,如前所述)。
但是,我建议你不要这样做。你不需要像这样的简单表达式来完成一个过程。最好不要使用该过程并只使用并发信号分配,如下所示:
architecture arch of func
signal sig_s1: std_logic;
begin
sig_s1 <= d1 and d2;
res2 <= sig_s1 xor d3;
end arch;
每个并发信号分配(顾名思义)同时运行,因此本身就是一个过程。 (所以,现在有两个并发进程)。通过并发信号分配,您可以免费获得灵敏度列表。因此,不可能从灵敏度列表中丢失信号。不仅如此,它占用页面上的空间更少,这意味着读者可以一次看到更多代码,从而更好地理解*。
始终将这样的简单组合逻辑实现为并发信号分配,而不是作为一个过程。
*我是一位多产的评论者,而不是取消这种优势。哼哼。