【发布时间】:2021-07-23 11:23:00
【问题描述】:
在 VHDL 中,您需要在流程语句中使用一个变量才能立即更新它。可以使用信号,但不会立即更新。从上面重复我的问题:为什么不会在进程语句中立即更新信号?
【问题讨论】:
在 VHDL 中,您需要在流程语句中使用一个变量才能立即更新它。可以使用信号,但不会立即更新。从上面重复我的问题:为什么不会在进程语句中立即更新信号?
【问题讨论】:
简短的回答是 VHDL 执行模型。 VHDL 执行模型分两个独立的步骤执行仿真循环:更新和执行。模拟循环的一个有限视角(我已经抽象出许多细节)是:
您的问题是为什么要这样做?它保证每个兼容的 VHDL 仿真器以完全相同的仿真周期数执行相同的代码,并产生完全相同的结果。
要了解为什么信号瞬时更新会出现问题,请考虑以下代码:
proc1 : process(Clk)
begin
if rising_edge(Clk) then
Reg1 <= A ;
end if ;
end process ;
proc2 : process(Clk)
begin
if rising_edge(Clk) then
Reg2 <= Reg1 ;
end if ;
end process ;
在上面的代码中,如果信号像变量一样瞬时更新,并且进程按照 proc1 然后 proc2 的顺序运行,那么在模拟器中我们会看到 Reg2 接收到 A 的 1 个触发器。 OTOH,如果进程按照 proc2 然后 proc1 的顺序运行,那么在模拟器中我们会看到 Reg2 接收到 A 的 2 个触发器。
这也是为什么 VHDL 中普通类型的共享变量在 1993 年才被临时引入,并在 2000 年能够引入更合适的特性(受保护类型的共享变量)时被删除。
【讨论】:
因为signal 的设计行为类似于硬件中物理实现的值,所以它只会根据确定的刺激和时间的进展进行更新。
在 VHDL 中,这反映在信号分配语句本身不会更新 signal 的值。相反,它安排在该信号上发生事务,当指定时间到来时,将触发信号上的事件以更改其值(如果分配是更改的值)。
事务的默认调度是在模拟中的增量延迟之后,即模拟时间瞬间就在当时所有并发执行的进程完成之后。因此,如果我在时钟进程中操作并且更新由rising_edge(clk) 触发的进程中的信号值,则新值将无法在该进程的当前运行中访问,但会在之后更新 em> 时钟的上升沿,当进程完成时。
之所以存在这种差异,是因为 VHDL 是一种硬件描述语言,而不是一种编程语言。因此,设计必须考虑硬件操作的实际情况——时间的进展、对因果刺激的需求等。因此,在一个良好的 VHDL 设计中,任何旨在随时间持续存在的值都将被定义为signal,以便设计考虑到它应该像硬件的一部分一样运行。在一个过程中,variable 可以提供用于组合计算的中间值 - 合成器将确定完成该工作所需的任何逻辑,但作为语言元素的 variable 是计算工具,而不是定义持久值的方法。当然,variable 滥用是可能的并且确实存在...... :^)
【讨论】: