ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Simens EDA:在Modelsim/QuestaSim中观察一个时间片(Time Slot)中Simulation/Delta Cycle发生的事件

Simens EDA:在Modelsim/QuestaSim中观察一个时间片(Time Slot)中Simulation/Delta Cycle发生的事件

相关阅读

Simens EDAhttps://blog.csdn.net/weixin_45791458/category_13125676.html


本文的目的是教会读者如何使用Modelsim/QuestaSim观察一个时间片(Time Slot)中Simulation/Delta Cycle发生的事件,有关Verilog/SystemVerilog中的时序调度的更详细信息,可以阅读Verilog/SystemVerilog Standard中的Scheduling semantics一章,其中详细给出了层次事件队列的定义。

对于Modelsim/QuestaSim,Simulation/Delta Cycle是一个抽象概念,指的是一个持续时间比仿真时间精度还小的循环,每个循环执行所有被触发的进程(进程指的是always语句、initial语句、assign语句等),在所有被触发的进程结束/挂起后,进入下一个Simulation/Delta Cycle,并执行那些在上一个循环执行的进程中被触发的进程,直到当前仿真时间不存在活跃事件。

下面用一个愚蠢的例子进行说明,注意:一定不要在设计中使用这种风格的代码。

// 例1 // a, b, c的值最终是多少? module demo; reg a = 0; reg b = 0; reg c = 0; initial begin #4 a = 1; b = 1; end initial @(b) begin a = 0; c = 1; end initial @(negedge a) begin b = 0; end initial @(posedge c) begin c = 0; end endmodule

在仿真时间0,变量a、b、c的赋值在一个Simulation/Delta Cycle中先后执行,它们被给予了初值0;在仿真时间4,变量a、b在第一个Simulation/Delta Cycle中先后被赋值为1,其中变量b赋值后触发了initial @(b),该进程中的语句将在第二个Simulation/Delta Cycle中执行;在仿真时间4,变量a在第二个Simulation/Delta Cycle中被赋值为0,触发了initial @(negedge a),随后变量c在第二个Simulation/Delta Cycle中被赋值为1,触发了initial @(posedge c),这两个进程中的语句将在第三个Simulation/Delta Cycle中执行;在仿真时间4,变量b在第三个Simulation/Delta Cycle中被赋值为0,变量c在第三个Simulation/Delta Cycle中被赋值为0,需要注意的是,这两个赋值的先后顺序是不确定的(即未定义行为),即使initial @(negedge a)先被触发,更详细信息可以参考下面的博客。

Verilog基础:时序调度中的竞争(一)(不要在两个及以上的always或initial结构中对同一个变量赋值)https://blog.csdn.net/weixin_45791458/article/details/134606846?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522ea312df4d330b6ccc7f1d81970a4e309%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=ea312df4d330b6ccc7f1d81970a4e309&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-4-134606846-null-null.nonecase&utm_term=%E7%AB%9E%E4%BA%89&spm=1018.2226.3001.4450下面我们将使用Modelsim展示如何在波形窗口观察到这些信息,首先按照正常的流程进行编译和仿真,结果如图1所示。

图1 仿真结果

从图1中可以看出,变量a、b、c的值似乎一直是0,但在仿真时间4时出现了一个类似毛刺的变化。

为了观察这个毛刺的具体情况,我们需要使用图2所示的Wave Expand Time Toolbar。

图2 Wave Expand Time Toolbar

其中各按钮的功能如表1所示。

表1

按钮名字功能

Expanded Time Off默认模式

Expanded Time Deltas Mode进入Delta时间模式

Expanded Time Events Mode进入Event时间模式

Expand All Time展开所有时间(只有在非默认模式下可用)

Expand Time at Active Cursor展开标尺处的时间(只有在非默认模式下可用)

Collapse All Time折叠所有时间(只有在非默认模式下可用)

Collapse Time at Active Cursor折叠标尺处的时间(只有在非默认模式下可用)

点击按钮进入Delta时间模式,此时的波形如图3所示。

图3 仿真结果

从图2中可以看出,变量a、b、c的值似乎一直是0,但在仿真时间4时出现了一个红点,这代表信号在该仿真时间的Simulation/Delta Cycle中变化了多次。

点击按钮展开所有时间,此时的波形如图4所示。

图4 仿真结果

从图3中可以看出,被展开区域的背景变成了蓝色,此时底部的仿真时间4后出现了+1,+2等标志,这代表了Delta时间或者说Simulation/Delta Cycle,可以看出其中有三个Simulation/Delta Cycle,信号的变化和之前的分析一致。

虽然Delta时间可以反映信号在同一仿真时间的多次变化,但每个Simulation/Delta Cycle依然有多个信号变化,例如第一个Simulation/Delta Cycle,信号a、b变化;第二个Simulation/Delta Cycle,信号a、c变化;第三个Simulation/Delta Cycle,信号b、c变化。

如果想获得更详细的信号变化情况,可以使用按钮,此时的波形如图5所示。

图5 仿真结果

从图4中可以看出,被展开区域的背景变成了绿色,此时底部的仿真时间4后出现了+1,+2等标志,这代表了Event时间,可以看出其中有六个时间,每个时间只有一个信号变化,可以看到在最后的第三个Simulation/Delta Cycle中,Modelsim选择先对变量b赋值,后对变量c赋值,再次强调,赋值顺序是不确定的(即未定义行为)。

除了波形窗口,在信号列表中也可以观察到Delta时间和Event时间的具体情况,如图6和图7所示(可以通过configure list -delta命令切换两种模式)。

图6 信号列表

图7 信号列表

使用单步运行功能也可以观察到语句执行的具体情况,在此不进行详细说明。

某些情况下,可能用户在观察Delta时间和Event时间时会有意想不到的结果,下面用一个例子进行说明。

// 例2 module demo; reg a = 0; initial begin #4 a = 1; a = 0; end endmodule

默认情况下的仿真结果如图8所示。

图8 仿真结果

从图7中并没有看到仿真时间4时期望的毛刺,查看Delta时间和Event时间也看不到信号a变化的过程,这是因为Modelsim在优化过程中直接将重复赋值优化掉了,使用单步运行功能可以强制降低优化等级,此时就可以在仿真结果中看到变量a先被赋值为1,后被赋值为0的过程。

最后需要注意的是,本文中有关Simulation/Delta Cycle的具体定义仅限于Modelsim/QuestaSim,不同的仿真器可能对此有不同的实现方式,下面用一个例子进行说明。

// 例3 always @(q) p = q; always @(q) p2 = not q; always @(p or p2) clk = p and p2; always @(posedge clk)

假设存在以上四条always语句,并且变量q、p、clk的初值为0,变量p2的初值为1,当变量q被赋值为1时,按照Modelsim/QuestaSim中的规则,事件的顺序如图9所示。其中数字代表各语句(从上到下编号)或者说一个评估事件(Evaluation event),而<name>(old->new)则代表一个变量的更新事件(Update event)。

图9 Modelsim/QuestaSim中的情况

图9的左列展示了所有执行的语句及其顺序,右列则展示了在这个过程中,由于评估事件而产生的更新事件,以及由更新事件触发的评估事件,可以再次看出,这个过程符合之前的分析,即在当前Simulation/Delta Cycle先处理所有的更新事件,在下一个Simulation/Delta Cycle处理那些被触发的评估事件。

默认情况下的仿真结果如图10所示,Delta时间的仿真结果如图11所示,Event时间的仿真结果如图12所示。

图10 仿真结果

图11 仿真结果

图12 仿真结果

对于其他仿真器,则可能使用其他实现方式,图13展示了其中一种情况。

图13 另一种可能的情况

在图13展示的情况中,仿真器在always @(q) p = q;被触发后就立刻处理了,即使此时always @(q) p2 = not q;已经在事件队列中了,就像是插队一样,这是允许的,Verilog/SystemVerilog Standard并没有强制要求顺序。

笔者尝试使用VCS+Verdi查看例1的波形(这需要使用其中的Expand Delta和Event Sequence功能),但无法观察到细节,只能在交互式仿真调试模式并单步运行才能观察到图14所示的变化。

图14 Verdi中的Event Sequence

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进