为什么信号不会在过程语句中立即更新?超高密度语言

Why won't a signal be updated instantly in process statement? VHDL

在VHDL 中,您需要在流程语句中使用变量以使其即时更新。信号的使用可以完成,但不会立即更新。重复我上面的问题:为什么信号不会在过程语句中立即更新?

因为 signal 的设计类似于硬件中物理实现的值,它只会根据确定的刺激和时间的推移进行更新。

在VHDL中,这体现在信号赋值语句本身并不更新a的值signal。相反,它安排在该信号上发生事务,当指定时间到来时,将触发信号上的事件以更改其值(如果赋值是更改值)。

事务的默认调度是在模拟中的增量延迟之后,即模拟时刻刚好在所有并发执行的进程在那个时间完成之后。因此,如果我在一个时钟进程中运行,并且我更新了一个由 rising_edge(clk) 触发的进程中的信号值,新值将无法在进程的当前 运行 中访问,但会更新 刚好在时钟的上升沿之后,当过程完成时。

存在这种差异是因为VHDL是一种硬件描述语言,而不是一种编程语言。因此,设计必须考虑硬件操作的现实情况——时间的进展、对因果刺激的需求等。因此,在良好的 VHDL 设计中,任何旨在随时间持续存在的值都将被定义为 signal,以便设计考虑到它应该表现得像硬件的一部分。在一个过程中,variable 可以提供用于组合计算的中间值 - 合成器将确定完成该工作所需的任何逻辑,但是 variable 作为语言元素是用于计算,而不是定义持久值的方法。当然,variable 滥用是可能的并且确实存在......:^)

简短的回答是 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,那么在模拟器中我们会看到1个触发器A被Reg2接收. OTOH,如果按 proc2 然后 proc1 的顺序处理 运行,那么在模拟器中我们会看到 Reg2 接收 A 的 2 个触发器。

这也是为什么 VHDL 中普通类型的共享变量只是在 1993 年才临时引入并在 2000 年能够引入更合适的特性(受保护类型的共享变量)时被删除的原因。