【IEEE_SV-9.2】initial、always和final过程语句的用法

9.2 Structured procedures

结构化语句
SystemVerilog中的所有结构化过程都是在以下结构之一中指定的:
—initial过程,用关键词initial表示(参考9.2.1)
—always过程,用以下关键词表示:
always(参考9.2.2.1)
always_comb(参考9.2.2.2)
always_latch(参考9.2.2.3)
always_ff(参考9.2.2.4)
—final过程,用关键词final表示(参考9.2.3)
—task
—function
这些结构化过程的语法如语法9-1所示。

initial和always过程语句在仿真开始的时候启用。initial语句只执行一次,当语句完成时,它的活动就停止了。相比之下,always语句重复执行,当仿真停止时,它的活动应该停止。
在initial和always过程语句之间没有隐含的执行顺序。initial过程不需要在always过程之前调度和执行。在一个模块中,定义的initial和always过程没有数量限制。变量初始化相对于过程执行的顺序见6.8。
final过程在仿真结束时启用,并且只执行一次。
任务和函数是从其他过程中的一个或多个位置启用的过程。task和function在第13条中描述。
除了这些结构化的过程外,SystemVerilog包含其他过程上下文,例如覆盖率点表达式(19.5)、断言序列匹配项(16.10、16.11)和操作块(16.14)。
SystemVerilog在过程中有以下几种类型的控制流:
—选择、循环和跳转(参见第12条)
—子程序调用(见第13条)
—顺序和并行块(见9.3)
—定时控制(见9.4)
—过程控制(见9.5至9.7)

9.2.1 Initial procedures

initial过程语句
一个initial过程语句只执行一次,当语句执行完后,它的活动就停止了。
以下示例演示了在仿真开始时变量初始化的initial过程语句的使用。

initial begin
a = 0;              // initialize a 
for (int index = 0; index < size; index++)
 memory[index] = 0; // initialize memory word
end

另外一个initial过程语句的典型应用是波形描述规范的使用,波形描述只执行一次,为仿真电路的主要部分提供激励。

initial begin
inputs = 'b000000;     // initialize at time zero
#10 inputs = 'b011001; // first pattern
#10 inputs = 'b011011; // second pattern
#10 inputs = 'b011000; // third pattern
#10 inputs = 'b001000; // last pattern
end

9.2.2 Always procedures

always过程语句
always过程有四种形式:always, always_comb, always_latch, 和 always_ff。always过程的所有形式在仿真期间重复连续执行。

9.2.2.1 General purpose always procedure

通用的always过程语句
关键字always表示一个通用的always过程,可以被用来使用代表重复行为,例如时钟振荡器。该构造还可以与适当的定时控制一起使用,以表示组合的、锁存的和顺序的硬件行为。
通用的always过程,因为它的循环特性,只有当和一些形式的时序控制一起使用才有用。如果一个always语句对仿真时间向前没有控制,它将会创建一个仿真死锁的状况。
例如,下面的代码创建了一个零延迟无限循环:
always areg = ~areg;
为前面的代码提供一个定时控制会创建一个潜在有用的描述,如下所示:
always #half_period areg = ~areg;

9.2.2.2 Combinational logic always_comb procedure

组合逻辑always_comb过程语句
SystemVerilog提供了一个特殊的always_comb过程来建模组合逻辑行为。例如:

always_comb
  a = b & c;
always_comb
  d <= #1ns b & c;

always_comb过程提供的功能不同于通用的always过程,如下所示:
—有一个推断敏感度列表,其中包含9.2.2.2.1中定义的表达式。
—写在赋值表达式左边的变量不应该被其它任何进程写入。但是,只要它们最长的静态前缀不重叠,对一个变量的独立元素进行多重赋值是允许的(参看11.5.3)。例如,一个非合并结构或数组的一bit可以被always_comb过程赋值,其它位可以被连续赋值或其它的always_comb过程赋值。详情请参见6.5。
—在所有initial过程和always过程启动之后,这个过程在零时刻自动触发一次,以便此过程的输出与输入一致。
如果always_comb过程中的行为不代表组合逻辑,软件工具应该执行额外的检查来发出警告,比如是否可以推断出锁存的行为。

9.2.2.2.1 Implicit always_comb sensitivities

隐式always_comb敏感性
always_comb的隐式敏感度列表包括每个变量,或者在块内读取的选择表达式,或在块内调用的任何函数的最长静态前缀的扩展但有以下例外:
a)在块中或在块中调用的函数声明的变量的任何展开
b)在块中或在块中调用的任何函数编写的任何表达式
最长静态前缀的定义请参见11.5.3。
层次函数调用和包中的函数调用被分析为普通函数,对类范围解析操作符引用的静态方法函数的调用也是如此。类对象的引用和类对象的方法调用不会向always_comb的灵敏度列表添加任何东西,除了传递给这些方法调用的参数表达式的任何贡献。
在always_comb中允许任务调用,但是任务的内容不会向灵敏度列表添加任何内容。
注意:一个不消耗时间的任务可以被一个void函数代替,以便对内容进行灵敏度分析。
在过程中的即时断言(见16.3)中使用的表达式,或在过程中调用的任何函数中使用的表达式,都有助于生成always_comb的隐式灵敏度列表,就好像这个表达式被用作if语句的条件一样。在断言操作块中使用的表达式不会参与到always_comb的隐式灵敏度列表。在下面的例子中,每当b、c或e发生变化时,always_comb就会触发。

always_comb
  begin
    a = b & c;
    A1:assert (a != e) else if (!disable_error) $error("failed");
  end
9.2.2.2.2 always_comb compared to always @*

always_comb和always@*比较
SystemVerilog always_comb过程与always @*(参见9.4.2.2)的区别如下:
—Always_comb在时间0时自动执行一次,而always @*会等待,直到推断敏感度列表中的一个信号发生变化。
—Always_comb对函数内容中的变化敏感,而always @*只对函数参数的变化敏感。
—在always_comb过程中,赋值左边的变量,包括被调用函数内容中的变量,不能被任何其他进程写入,而@*总是允许多个进程写入同一个变量。
—Always_comb中的语句不应该包括那些阻塞的、有阻塞计时或事件控制的语句,或者fork-join语句。
—Always_comb对过程中立即断言中的表达式和过程中调用的函数的内容敏感,而总是@*只对过程中立即断言中的表达式敏感。

9.2.2.3 Latched logic always_latch procedure

锁存逻辑always_latch过程语句
SystemVerilog还提供了一个特殊的always_latch过程,用于对锁存逻辑行为进行建模。例如:

always_latch
  if(ck) q <= d;

always_latch结构与always_comb结构是相同的,除了如果always_latch结构中的行为不代表锁存逻辑,软件工具应该执行额外的检查并警告;而在always_comb结构中,如果行为不代表组合逻辑,工具应该检查并警告。9.2.2.2中的所有语句都应适用于always_latch。

9.2.2.4 Sequential logic always_ff procedure

顺序逻辑always_ff过程语句
always_ff过程可以用来建模可综合的顺序逻辑行为。例如:

always_ff @(posedge clock iff reset == 0 or posedge reset) begin
  r1 <= reset ? 0 : r2 + 1;
end

always_ff过程施加了一个限制,即它包含且仅包含一个事件控制,并且没有阻塞计时控制。在always_ff过程中,赋值左边的变量,包括来自被调用函数内容的变量,不应被任何其他进程写入。
如果always_ff过程中的行为不代表顺序逻辑,软件工具应该执行额外的检查来发出警告。

9.2.3 Final procedures

final过程语句
final过程类似于initial过程,它定义了一个语句过程块,不同的是它发生在仿真时间的末尾,并且执行时没有延迟。finial通常用于显示有关仿真的统计信息。
final过程中允许的语句只有函数声明中允许的语句,以便它们在一个单独仿真循环执行。与initial过程不同,final过程并不作为单独的进程执行;相反,它在零时间内执行,作为来自单个进程的一系列函数调用。所有final程序应以任意顺序执行。在所有final程序执行完毕后,将不再执行剩余的计划事件。
当仿真结束时,由于对$finish的显式或隐式调用,执行final过程。

final
begin
  $display("Number of cycles executed %d",$time/period);
  $display("Final PC = %h",PC);
end

在final过程中执行$finish、tf_dofinish()或vpi_control(vpiFinish,…)将导致仿真立即结束。final程序在仿真中只能触发一次。
final过程应该在表示仿真结束的PLI回调之前执行。
SystemVerilog的final过程以任意但确定的顺序执行。这是可能的,因为final过程被限制为函数允许的合法语句集。
注意:SystemVerilog不指定执行final过程的顺序,但是实现应该定义保持运行之间的规则。这有助于保持输出日志文件的稳定,因为final过程主要用于显示统计信息。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值