当前位置: 首页 > article >正文

SystemVerilog学习笔记(九):Schedule

为什么要了解SV Schedule

  • verilog是一个硬件描述语言,而硬件在现实中都是并行执行的,所以verilog描述的组合电路和时序电路都是并行执行的。
  • 而仿真器作为运行在CPU上的软件,只是按照SV LRM的仿真调度算法,开始仿真后,将仿真时间串行的一步步的向前推进。
  • 因此,实际DUT中同时发生的动作由模拟器建模为一组有序动作,依次执行。如果不能很好地撰写RTL代码和TestBench,那么仿真可能得到不匹配的结果:即DUT为正确,但是仿真却报告错误;或者DUT为错误,但是仿真却报告正确。
  • 依照已经非常成熟的Coding规则,可以避免90%~100%由Verilog RTL设计引起的问问题。此外,还需要了解Verilog / SystemVerilog Schedule才能更好地理解规则。

systemverilog专门为这种并行到串行的转换定义了调度机制。但IEEE在制定规范时,并未规定一部分并行的事件执行的先后顺序,这点会引入不确定性(Nondeterminism),这种不确定性往往会体现在不同厂家的仿真器上(因为不同的厂家采用的调度算法是不一样的),最严重的后果就是在不同仿真器上看到的最终结果是不一样的。所以作为一名合格的工程师,应该对sv仿真器的调度机制、确定性与不确定性有基础的了解。

event与time slot的介绍

systemverilog是为离散事件执行模型(discrete event execution)所定义的一种语言。怎么理解呢?离散指的是仿真时间(simulation time)上的离散性,仿真基于时间片(time slot)进行,只对有效的时刻点进行仿真。事件执行模型指的是仿真基于事件进行建模和整体的调度。

下面先介绍几个概念:

  • 进程(Processes)是sv中并发调度的单元,比如:原语(Primitives)、initial过程块、always过程块、连续赋值(continuous assign)、异步任务(asynchronous tasks)、过程赋值(procedural assignment)等。进程是可以被执行的,有相应的状态标志(state,比如挂起)。进程会响应输入的变化并产生对应的输出。sv的描述的对象也正是这些进程。
  • 更新事件(update event):仿真中,net或者variable上每次的变化被认为是一次更新事件。
  • 求值事件(evaluation event):进程对更新事件敏感!当一个更新事件被执行时,所有对该更新事件敏感的进程都会被求值,但是顺序是任意的。进程的求值本身也被认为是一种事件,即求值事件(evaluation event)。更新事件和求值事件的相互交替执行,推动了仿真时间的前移。
  • 时间片(time slot):仿真是基于离散的时刻点来进行的就可以了。只有在每个时间片上的仿真活动全部完成,仿真器才会进行下一个时间片,也就是说仿真时间是不可逆的。在早期的IEEE描述里面,time slot也叫做timestep,只不过现在不这么叫了。每个时间片都会被划分成很多个区域,下面会详细介绍。划分的目的是为了保证仿真执行的正确性和清晰性。

Verilog的调度

IEEE Std 1364-2001将 Verilog 事件区域划分为四个有序区域: Active、Inactive、NBA、Postponed。
Verilog只有module,没有program,故所有的调度都是基于Module模块的


Active region

  • 阻塞赋值。
  • 计算非阻塞赋值的右侧表达式(RHS即Right-Hand-Side)。并且把相应的更新事件调度至NBA Region(NBA即nonblocking assignment,非阻塞赋值)。
  • 连续赋值。
  • 调用$display系统函数。
  • primitive计算。

Inactive region

  • 执行带#0延时的阻塞赋值

NBA region(Nonblocking Assignments)

  • 更新非阻塞赋值的左式(现在才被更新)

Postponed

  • 调用$monitor和$strobe系统函数。

下图为Verilog的调度图,将Inactive画叉代表RTL Coding时不要使用#0延时

  • 非阻塞赋值其实是分成了两个步骤,先计算RHS,再更新LHS,中间会去完成其它事件的调度和计算。而阻塞赋值两步同时执行,不存在中间插入其它事件的情况。
  • 有一些工程师喜欢用#0延迟去消除对同一变量赋值所引起的竞争,但是其实按照编码规范来,你就不应该在多个always对同一个变量进行阻塞赋值,所以理论上就不应该用到#0的阻塞赋值,所以也就用不到Inavtive Region了。

使用Verilog进行设计和验证时的race


下面为一个用verilog写的RTL和Testbench

DUT中,a和b应该时延后一拍的关系,但是仿真出来,a和b波形居然一致。
问题在于DUT和Testbench之间的race,在第一个clk上升沿,a在Test中被赋值为1,DUT中计算NBA的RHS(Right-Hand-Side),a为1。随后在NBA region,DUT中Update LHS,此时b被更新为1。故波形就如上图所示。
为了避免该问题,可以在Test中加入#0延时

此仿真图得到DUT中a和b有一拍延时关系,符合设计预期。
因为在第一个clk上升沿的时候,执行DUT中的RHS时,a还是初始值0,然后到了Inactive region,执行了Test中的 #0,此时Test中的a被赋值为1,然后在NBA region,更新DUT中b的值,b被更新为0,故复位上图波形。

为什么需要SystemVerilog

上面已经了解到单纯用Verilog很容易引起DUT和Test之间的race,故引入了SV。SystemVerilog中引入了Program,从而将module和Program的调度分开,达到减少race的目的。

IEEE Std 1800-2005的更新将 SystemVerilog 的timeslot分为17个有序区域、9个有序区域用于执行 SystemVerilog 语句和8个有序区域用于执行 PLI (Programming Language Interface,用来调用其它语言的函数的接口,比如C/C++)代码。

 SystemVerilog的调度

暂时不考虑PLI,删除PLI后的SystemVerilog的时间区域划分如下:大致可以分为4个region:Preponed,Active(Active、Inactive、NBA),Observed,Reactive(Reactive、Re-Inactive、Re-NBA)

Active Region、Inactive Region、NBA Region统称为Active Region set,这是专门为RTL代码执行所设立的区域集合(set),实际上就是上面介绍的verilog代码的区域,只不过在sv中需要限定一下事件是在module中定义的,而不是program中定义的(verilog不存在program)。

在sv中,相对于为RTL代码设立的区域,还有专门为验证平台所设计的区域集合,Reactive Region set。包含了Reactive Region、Re-Inactive Region、Re-NBA Region。Observed Region则是专门为断言所设计的区域。

Preponed Region

  • 采样数据,为断言做准备。

Active region 

  • 兼容Verilog调度(for module)

Observed Region

  • 使用Preponed Region采样到的值来计算断言。
  • 断言可能还会引起块的计算,会调回到active(module中的断言)或reactive(program中的断言)中去,这也就是图中Observed下个可以往其他区域流转的原因。

Reactive Region

  • 所有定义在program内的阻塞赋值。
  • 执行断言pass/fail代码
  • 所有定义在program内的非阻塞赋值RHS的计算,并将相应的更新事件调度至Re-NBA Region。
  • 所有program内的连续赋值。
  • 执行系统函数$exit及隐式的$exit命令。

其实仔细看下,和Active Region内执行事件是很类似的,只不过加了program的限定。

Re-Inactive Region

  • program内#0延迟的进程。

虽然Inactive Region不推荐使用,但是Re-Inactive Region还是有一些独特的价值的,比如开一些后台fork时,你希望新开的子进程优先于父进程执行。

 Re-NBA Region

  • 执行Reactive Region调度过来的LHS更新事件。

Postponed Region

  • 调用$monitor和$strobe系统函数。
  • 收集利用strobe采样的功能覆盖率。

比较一下,systemverilog的Postponed Region比verilog的Postponed Region多了功能覆盖率的收集功能。

Preponed和Postponed的说明

Preponed采样的值是该timeslot的最初的值,Postponed采样的值是该timeslot的最后更新了的值。
上一个timeslot的Postponed采样到的值和下一个timeslot的Preponed采样到的值相同,只是timeslot不同而已。

采样Program后的仿真

拥有了SV后,那么可以将设计代码写成Module模块,将test代码写成Program模块
Program中不能再层次化调用任何其他模块(program、module、interface)
上面的例子中,当test使用program … endprogram后,不再需要加#0。

编码guideline

  • 时序逻辑使用nonblocking assignments(<=)
  • Latch 使用 nonblocking assignments (<=)
  • always块描述组合逻辑时使用 blocking assignments (=)
  • 在同一个always块中混用组合逻辑和时许逻辑时使用nonblocking assignments(<=)
  • 在同一个always块中不要混用 (<=) 和 (=)
  • 不能在不同的always块中对同一变量进行赋值
  • 使用$strob函数来打印使用nonblocking assignments的变量
  • 不要使用 #0 延时

参考资料

SystemVerilog学习笔记5 ---《SV Schedule》_systemverilog timeslot region-CSDN博客

SystemVerilog调度机制与一些现象的思考_systemverilog中0延时的作用-CSDN博客


http://www.kler.cn/a/393106.html

相关文章:

  • Next.js 14 性能优化:从首屏加载到运行时优化的最佳实践
  • 振动分析-46-设备振动监测和故障诊断能力提升需要理解和掌握的知识体系
  • langchain使用FewShotPromptTemplate出现KeyError的解决方案
  • Vue.js前端框架教程11:Vue监听器watch和watchEffect
  • 鸿蒙开发:了解帧动画
  • information_schema是什么?
  • Vue 生命周期函数
  • 可认证数据资产合约标准协议(CMIDA-1)意见征集
  • 06.VSCODE:备战大项目,CMake专项配置
  • PcVue + SQL Grid : 释放数据的无限潜力
  • 堆排序与链式二叉树:数据结构与排序算法的双重探索
  • 【STM32F1】——无线收发模块RF200与串口通信
  • 使用Java绘制图片边框,解决微信小程序map组件中marker与label层级关系问题,label增加外边框后显示不能置与marker上面
  • go reflect 反射
  • 若依笔记(八):芋道的Docker容器化部署
  • 什么是 ISP:了解互联网服务提供商的作用
  • Vue 3 在现代前端开发中的应用
  • 【大数据学习 | HBASE高级】hbase的参数优化
  • 【Linux】linux编辑器-vim的命令及配置
  • Qt_day5_常用类
  • 图像处理实验四(Adaptive Filter)
  • 华为eNSP:MSTP
  • TensorFlow 2.0 环境配置
  • 常见git命令记录
  • 要查看你的系统是 x64(64位)还是 x86(32位),可以按照以下步骤操作
  • python高级之面向对象编程