vhdl中进程语句中的顺序执行

时间:2018-05-03 15:01:10

标签: vhdl

对于vhdl中的进程语句,可以说进程语句中的执行顺序是顺序的。我的问题是,请首先查看下面的代码,是否在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,因为我们在分配给c之前将b分配给a。但是,硬件似乎无法做到这一点。

2 个答案:

答案 0 :(得分:2)

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

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将值从一个移位到另一个作为循环移位寄存器:

sequent_exec.png

为什么会出现VHDL模拟周期的运作方式。

参见IEEE Std 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 Std 1076-1993,为简单起见,不要混淆VHPI动作:

12.6.4模拟周期

  

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

     

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

     

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

     
    

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

         

- S&#39; Stable(T)或S&#39; Quiet(T)形式的每个隐含信号的值设置为True。 S&#39; Delayed(T)形式的每个隐含信号的值被设置为其前缀S的初始值。

         

- 每个隐含GUARD信号的值被设置为评估相应保护表达式的结果。

         

- 模型中的每个非推送过程都会执行,直到它暂停。

         

- 模型中的每个推迟过程都会执行,直到它暂停。

         

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

  
     

模拟周期包括以下步骤:

     
    

一个。当前时间Tc设置为等于Tn。当Tn = TIME&#39; HIGH并且在Tn处没有活动的驱动器或过程恢复时,模拟完成     湾模型中的每个活动显式信号都会更新。 (结果可能会在信号上发生事件。)
    C。模型中的每个隐含信号都会更新。 (结果可能会在信号上发生事件。)
    d。对于每个过程P,如果P当前对信号S敏感,并且如果在该模拟循环中S上发生了事件,则P重新开始。
    即在当前模拟周期中已恢复的每个非应延过程都将执行,直到它暂停为止     F。下一个模拟周期的时间Tn通过将其设置为最早的

来确定          
      
          
  1. TIME&#39; HIGH,
  2.       
  3. 下次驱动程序变为活动状态或
  4.       
  5. 下一次进程恢复的时间。
  6.       
  7. 如果Tn = Tc,那么下一个模​​拟周期(如果有的话)将是一个增量周期。
  8.            
         

克。如果下一个模拟周期是增量循环,则跳过此步骤的其余部分。否则,每个推迟的进程已经恢复但自上次恢复以来尚未执行,直到它暂停为止。然后根据步骤f的规则重新计算Tn。如果执行任何推迟的过程导致在当前模拟循环之后立即发生增量循环,则会出错。

  

信号值在执行过程中不会发生变化。他们的更新排队并在执行模拟周期的不同步骤中应用。

回到-2008:

  1. 顺序陈述,10.1一般
  2.   

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

    我们看到顺序信号分配执行的顺序与订单信号的更新没有关系。

答案 1 :(得分:0)

信号分配是排队的事件,请参阅注释中的链接。所以在评估之后a(new)= b(old),b(new)= c(old),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(新)= a(新)= b(旧)和b(新)= c(旧)