verilog 作为一种 HDL (Hardware Description Language) 用来描述电子硬件的结构,SystemVerilog 是在 verilog 基础上扩展而来的,它不仅可以用来描述电子硬件,新增的扩展主要用于 verification,称为 HVL(Hardware Verification Language)。 我们知道硬件和普通程序的最大的区别:硬件是完全并行的,而程序本质上是串行的,所以 Verilog 和 SystemVerilog 仿真本质上是用串行的程序来描述硬件的并行行为。
为了解决串行模拟并行的问题,SystemVerilog 引入了 event 调度以及根据时间片划分成多个 region 的方式调度,下面主要就是看这两个概念怎么解决并行问题的。
SV 的事件是离散的模型。在设计中所有语言都有左值和右值两个元素,每次右值的变化都会引起左值的变化,每次左值和右值的变化都被视为更新事件,所有对这些事件敏感的表达式都会被考虑进行评估,称为评估事件。
表达式的通常包括:initial, always, always_comb, always_latch, and always_ff procedural blocks
, continuous assignments(assign)
, procedural assignment statements
.
verilog 中主要就是有两种赋值方法,Continuous assignment(连续赋值)适用于 net 类型,Procedural assignment(过程赋值)使用于variable 类型;其中过程赋值中有两种,阻塞赋值和非阻塞赋值。另外主要的就是 task 和 function,里面也是用这两种赋值。
systemverilog 中新增了 program, assertion,clocking 会影响调度器,其他的 package,class,interface,constraint 等并不会影响调度器,暂且不提。
// procedural block
initial, always, always_comb, always_latch, always_ff, final, task, function
// block 里面可以使用 block 和 non-blocking 赋值
[ delay ] register_name = [ delay ] expression; // blocking
[ delay ] register_name <= [ delay ] expression; // non-blocking
//还可以使用if、case跳转, forever、 repeat、for等循环
// continuous assignments
wire out;
wire in1, in2;
assign out = in1 & in2;
对于事件的定义在原来延时和始终变化上新增了event
#1 a = b
@(posedge clk)
@(b); wait(b.triggered) #10 -> a;
Note:
- 术语“仿真时间”用于指仿真器维护的时间值,用于对被仿真的系统描述所需的实际时间进行建模。
- 时间片包括每个仿真时间在事件区域中处理的所有仿真活动 SystemVerilog 事件区域 开发新的 SystemVerilog 事件区域是为了支持新的 SystemVerilog 构造,并防止在 RTL 设计和新验证构造之间创建竞争条件 。
SystemVerilog 时间片划分为 17 个有序区域:
a) Preponed
b) Pre-Active
c) Active
d) Inactive
e) Pre-NBA
f) NBA
g) Post-NBA
h) Pre-Observed
i) Observed
j) Post-Observed
k) Reactive
l) Re-Inactive
m) Pre-Re-NBA
n) Re-NBA
o) Post-Re-NBA
p) Pre-Postponed
q) Postponed
兼容 SystemVerilog 的模拟器应维护某种形式的数据结构,允许事件随着模拟器时间的推移动态地调度、执行和删除。 数据结构通常作为一组按时间排序的链表来实现,这些链表以明确定义的方式进行划分和细分。第一个划分是按时间划分。 每个事件都有且仅有一个模拟执行时间,在任意时刻执行时间可以是当前时间或未来的某个时间。 所有需要被调度的事件都会创建一个time slot,开始执行这17个region的event。 通过执行和删除当前模拟中的所有事件,当所有时间都被调度完之后移动到下一个 time slot 中。 程序通过类似的方式保证了模拟器永远不会出现模拟时间倒退的现象。
这些 region 可以从不同的角度进行划分:
根据 active 它把 region 分成了两组 region :active group, reactive group。其中 active region 包括 Active, Inactive, Pre-NBA, NBA, and Post-NBA 。reactive region 包括 Reactive, Re-Inactive, Pre- Re-NBA, Re-NBA, and Post-Re-NBA。
根据是否在 simulation 中执行划分成 simulation region: Preponed, Active, Inactive, NBA, Observed, Reactive, ReInactive, Re-NBA and Postponed
和 PLI region:Preponed, Pre-Active, Pre-NBA, Post-NBA, Pre-Observed, Post-Observed, Pre-Re-NBA, Post-Re-NBA, Pre-Postponed
.
下面我们先只看 simulation region 的各个 region 需要完成的工作。
主要用于验证环境下,在 assertion 中如果 clocking skew 中指定了输入 #1step
在该 region中进行采样。采样的结果和在上一个 time slot 中 postponed region 中采样的结果应该是相同的。 该 region 的 event 在每个 time slot 中仅执行一次,采样之后正式遍历 time slot 的各个region 调度 event。
包含了当前 active group 中所有需要评估的事件,事件被处理的顺序不提供任何保证,可以按任何顺序进行调度。
事件包括:
1. 所有的阻塞赋值
2. 非阻塞赋值表达式中右值的评估,它会在NBA中更新左值.
3. 所有的连续赋值.
4. 评估 verilog 的自定义源语UDP的输入和输出(一般用的很少).
5. Execute the $display and $finish commands.
保存所有active region 事件处理完毕后要评估的事件。
如果在 active region 中 执行 #0 a = 1
,其中显示的使用 #0
延时的 blocking 赋值操作,在 active region 处理时会将该表达式的处理暂时挂起,然后在 inactive 中调度,之后再次从 inactive 到 active 跳转时再次调度处理该表达式。
这种方式在 RTL 中不推荐使用。
NBA 中处理所有非阻塞赋值的更新事件,其中 Active region 中处理右值的更新,NBA 更新左值。
concurrent assertion 的语句事件评估在该 region 中处理,另外 clocking 中 input skew #0
的输入也在这个 region 中进行采样。
它保存了在 reactive group 所有需要被评估的事件,和 active region 中一样并不对事件被处理的顺序做任何保证,可以按任何顺序进行调度。
1. concurrent assertion 的 action 块
2. 在 program block 中的 blocking 赋值
3. 评估所有 program 中 non-blocking赋值的右值,之后会在 Re-NBA region 更新左值
4. program block 中所有的连续赋值
5. 执行了 $exit 或者隐式的 $exit 命令
这个 region 类似于 inactive region, 如果在 reactive region 中有使用 #0
赋值,这个表达式在 reactive region 中会被挂起并且在当前time slot 的 re-inactive region 中调度处理,所以这个表达式会在下一次进入 reactive region 中被处理。
和 NBA region 类似,处理 program block 中 non-blocking 赋值的更新。另外 clock 中 output skew #0
的也会在该 region 中更新。
该区域的主要功能是执行 $strobe 和 $monitor 命令,这些命令将显示当前 time slot 的最终更新值。 该区域还用于收集使用选通采样的项目的功能覆盖范围。
预活动区域专门用于 PLI 回调控制点,允许用户代码在评估活动区域中的事件之前读取和写入值并创建事件
Pre-NBA 区域专门用于 PLI 回调控制点,允许用户代码在评估 NBA 区域中的事件之前读取和写入值并创建事件
Post-NBA 区域专门用于 PLI 回调控制点,允许用户代码在评估 NBA 区域中的事件后读取和写入值并创建事件
Post-observed 区域专门用于 PLI 回调控制点,允许用户代码在评估属性后读取值(在 Observed 或更早的区域中)。
SystemVerilog 2012 specification Manual, Chapter 4 Schduling semantics