【问题标题】:sequential execution in process statement in vhdlvhdl 中的 process 语句中的顺序执行
【发布时间】:2018-05-03 15:01:10
【问题描述】:

对于vhdl中的进程语句,据说进程语句内部的执行顺序是顺序的。我的问题是,请先看下面的代码,在process语句的if语句中,a、b、c信号是同时还是顺序分配给它们的新值?

   process(clk) is
   begin
   if rising_edge(clk) then
   a <= b ;
   b <= c ;
   c <= a;
   end if;
   end process;

所以如果这是顺序的,我必须说在进程结束之后,a 等于 b,b 等于 c,c 等于 b,因为我们在将 a 分配给 c 之前将 b 分配给了 a。但是,这对于硬件来说似乎是不可能的。

【问题讨论】:

  • 你会找到解释的开头here

标签: vhdl


【解决方案1】:

构建包含您的流程的最小、完整且可验证的示例:

library ieee;
use ieee.std_logic_1164.all;

entity sequent_exec is
end entity;

architecture foo of sequent_exec is
    signal a:       std_ulogic := '1';
    signal b, c:    std_ulogic := '0';
    signal clk:     std_ulogic := '0';
begin
    CLOCK:
    process
    begin
        wait for 10 ns;
        clk <= not clk;
        if now > 200 ns then
            wait;
        end if;
    end process;
DUT:
    process(clk) is
    begin
    if rising_edge(clk) then
    a <= b ;
    b <= c ;
    c <= a;
    end if;
    end process;
end architecture;

我们将 a、b 和 c 值从一个移到另一个作为循环移位寄存器:

为什么会发生这种情况与 VHDL 的仿真周期如何运作有关。

参见 IEEE 标准 1076-2008

10.5 简单信号分配(10.5.1 常规):

信号分配语句修改包含在一个或多个信号的驱动器中的投影输出波形(见 14.7.2),为一个或多个信号安排力,或安排一个或多个信号的释放(见 14.7.3 )。

信号分配将新值排队以进行信号更新。 10.5.2.2 执行简单赋值语句描述了投影输出波形队列如何操作:

一个波形元素的评估产生一个单一的交易。事务的时间分量由当前时间加上波形元素中时间表达式的值来确定。对于第一种形式的波形元素,交易的价值成分由波形元素中的价值表达决定。

没有时间表达式的赋值是当前模拟时间。 (将出现一个增量周期 - 一个不提前模拟时间的模拟周期)。中描述的事务序列 10.5.2.2 告诉我们旧交易到同一模拟时间被删除。

这意味着对于任何模拟时间只有一个队列条目,并解释了为什么对特定信号的最后分配是导致事务(并为进程敏感的信号产生事件)的原因。

14.7 模型的执行包含有关模拟周期如何运行的信息(14.7.5 模型执行)。

14.7.5.1 常规:

模型的执行包括一个初始化阶段,然后是重复执行该模型描述中的流程语句。每个这样的重复被称为一个模拟循环。在每个循环中,计算描述中所有信号的值。如果此计算的结果是在给定信号上发生事件,则对该信号敏感的过程语句将恢复并作为模拟周期的一部分执行。

14.7.5.3 模拟周期描述了模拟周期,此处使用 IEEE 标准 1076-1993 是为了简单起见,不会与 VHPI 操作混淆:

12.6.4 模拟循环

模型的执行包括一个初始化阶段,然后是重复执行该模型描述中的流程语句。每个这样的重复被称为一个模拟循环。在每个循环中,计算描述中所有信号的值。如果此计算的结果是在给定信号上发生事件,则对该信号敏感的过程语句将恢复并作为模拟周期的一部分执行。

在初始化开始时,当前时间 Tc 假定为 0 ns。

初始化阶段包括以下步骤:

--计算每个显式声明的信号的驱动值和有效值,并将信号的当前值设置为有效值。该值被假定为在模拟开始之前无限长的时间内的信号值。

-- S'Stable(T) 或 S'Quiet(T) 形式的每个隐式信号的值设置为 True。每个 S'Delayed(T) 形式的隐式信号的值都设置为其前缀 S 的初始值。

-- 将每个隐含的 GUARD 信号的值设置为对应保护表达式的求值结果。

-- 模型中的每个非延迟进程都会执行,直到它挂起。

-- 模型中每个被推迟的进程都会被执行,直到它挂起。

-- 下一个模拟周期(在这种情况下是第一个模拟周期)的时间,Tn,根据模拟周期步骤 f 的规则计算,如下所示。

一个模拟循环由以下步骤组成:

一个。当前时间,Tc 设置为等于 Tn。当 Tn= TIME'HIGH 并且在 Tn 处没有活动的驱动程序或进程恢复时,模拟完成。
湾。模型中的每个活动显式信号都会更新。 (结果可能会在信号上发生事件。)
C。模型中的每个隐式信号都会更新。 (结果可能会在信号上发生事件。)
d。对于每个进程 P,如果 P 当前对信号 S 敏感,并且在此模拟周期中 S 上发生了事件,则 P 恢复。
e.在当前模拟周期中恢复的每个非延迟进程都会被执行,直到它挂起。
F。下一个模拟周期的时间,Tn,通过将其设置为最早的来确定

  1. TIME'HIGH,
  2. 驱动程序下一次激活的时间,或
  3. 下一次进程恢复的时间。
  4. 如果 Tn = Tc,则下一个仿真周期(如果有)将是一个增量周期。

g.如果下一个模拟周期将是一个增量周期,则跳过此步骤的其余部分。否则,每个已恢复但自上次恢复后尚未执行的延迟进程将被执行,直到它挂起。然后根据步骤 f 的规则重新计算 Tn。如果任何延迟过程的执行导致在当前模拟周期之后立即发生增量周期,则这是一个错误。

信号值在流程执行期间不会改变。它们的更新在模拟周期执行的不同步骤中排队和应用。

回到-2008:

  1. 顺序语句,10.1 通用

本节描述了各种形式的顺序语句。顺序语句用于定义执行子程序或进程的算法;它们按照它们出现的顺序执行。

我们看到顺序信号分配执行的顺序与更新信号的顺序无关。

【讨论】:

    【解决方案2】:

    信号分配是排队的事件,请参阅 cmets 中的链接。所以经过评估a(new)=b(old), b(new)=c(old), and c(new)=a(old).

    如果你真的想要顺序赋值,你可以使用变量(但最好不要,因为你很容易出错)

    process(clk) is
        variable i_a, i_b, i_c : [some type];
    begin
        if rising_edge(clk) then
            -- initialize with signal value
            i_a := a;
            i_b := b;
            i_c := c;
            --- modify
            i_a := i_b;
            i_b := i_c;
            i_c := i_a;
            -- write back to signal
            a <= i_a;
            b <= i_b;
            c <= i_c;
        end if;
    end process;
    

    现在 c(new)=a(new)=b(old) 和 b(new)=c(old)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-18
      • 2013-11-23
      • 1970-01-01
      • 2014-08-23
      • 1970-01-01
      • 2011-09-27
      • 2013-05-18
      相关资源
      最近更新 更多