SystemVerilog学习笔记3——接口、采样、测试、调试


接口

  • 接口可用作设计,也可用作验证
  • 在验证环境中,接口可以使连接变简洁而不易出错
  • interface和module使用性质很像,它可以定义端口和双向信号,它可使用initial和always,也可定义function和task
  • interface可在硬件环境和软件环境中传递,例如作为module中的端口列表和软件方法中的形参;
  • 可以把interface看作一个“插排”,而DUT与TB之间的数据驱动关系都可以使用interface这个“插排”来完成。

接口的优势:

  • 将有关信号封装在同个接口中,对于设计和验证环境都便于维护和使用。添加新信号只需在接口中定义该信号,在使用该接口的模块或验证环境中做相应修改;
  • interface是SV中唯一的硬件和软件环境的媒介交互
  • 接口由于可以例化,使得对于多组相同的总线,在例化和使用时变得更加灵活。

接口的定义和使用:

  • interface的端口列表中只需要定义时钟、复位等公共信号,或不定义任何端口信号,转而在变量列表中定义各个需要跟DUT和TB连接的logic变量
  • interface也可依靠函数参数化方式提供复用性
  • interface在例化时,同module例化方式一样;
  • 模块里面可以例化模块和interface,interface里面可例化interface但不能例化module

采样和数据驱动

竞争问题

  • 为避免在RTL仿真行为发生的信号竞争问题,建议通过非阻塞赋值或特定的信号延迟解决同步的问题。为尽量避免时序电路中时钟和驱动信号的时序竞争问题,需给出尽量明确的驱动时序和采样时序
  • 默认情况下,时钟对于组合电路的驱动会添加一个无限最小时间(delta-cycle)的延迟,而该延迟无法用绝对时间单位衡量,它要比最小时间单位精度还小;
  • 在一个时间片(time-slot)中可以发生很多事情,例如在仿真器中敲命令“run 0”,即让仿真器运行一个无限最小时间,一个时间片包含无限多个delta-cycle。 s > ms > ns > ps > fs > delta-cycle。

如何避免采样的竞争问题?

  • 在驱动时添加相应的人为延迟,模拟真实的延迟行为,同时加大clk与变量之间的延迟,以此提高DUT使用信号时的准确性和TB采样信号时的可靠性;
  • 对于一些采样时依然存在的delta-cycle延迟的信号,还可以依靠在采样事件前的某段时刻进行采样,来模拟建立时间的采样要求,确保采样的可靠性。

接口中的clocking

  • interface可通过modport进一步限定信号传输的方向,避免端口的连接错误
  • 可在接口中声明clocking(时序块)和采样的时钟信号,实现信号的同步和采样
  • clocking块基于时钟周期对信号进行驱动或采样的方式,使testbench不再苦恼于如何准确及时地对信号驱动或者采样,消除信号竞争的问题
  • clocking块也可定义在module和program中,其列举的信号不是自己定义的,而是应该由interface或其它声明clocking的模块定义的;
  • 声明完名字后应伴随着定义默认的采样事件,即“default input/output event”。没有定义则默认在clocking采样事件前的1step对输入进行采样,在采样事件后的#0对输出进行驱动
  • interface中可定义多个clocking,同个变量在不同clocking中可声明不同方向
    在这里插入图片描述
    注:“input clocking_skew”中clocking_skew(时钟偏移量)采取的是负值,而输出驱动采用的是正值
  • 采样偏移量抽象为物理中的建立时间,则其要求时钟上升沿之前的某段时间内数据不能有变化,否则数据采样会有不一样的结果;
  • 利用clocking块通过一种类似“物理保持时间”的驱动方式,可实现时钟沿叠加偏移量的延迟驱动效果;
  • 为避免可能的采样竞争问题,应在验证环境的驱动环节就添加固定延迟,使得在仿真波形中更容易体现时钟与被驱动信号之间的时序前后关系,同时便于DUT的准确处理和TB的准确采样;
  • 如果TB在采样从DUT送出的数据,时钟与被驱动信号之间存在delta-cycle时,应考虑时钟采样沿的更早时间段去模拟建立时间要求采样,这种方法也可以避免由于delta-cycle问题带来的采样竞争问题;
  • 当把clocking运用到interface中,用来声明各接口与时钟的采样和驱动关系后,可大大提高数据驱动和采样的准确性,从根本上消除采样竞争的可能性

测试的开始和结束

  • 各设计自身可作为一个大线程,内部又包含多个并行的线程,而模块之间即线程的通信主要依靠信号的变化
  • 对于一个设计,如果在仿真开始没有任何激励(如时钟和复位信号),那么仿真并未开始,也可认为已结束,因为对于设计内部并没有产生任何新事件,也不会由这些事件进一步触发组合逻辑和时序逻辑;
  • 如果在仿真开始后提供时钟和复位信号,对验证而言是必要步骤,但它本身不会对设计的功能产生实质的功能影响。从设计的角度来看复位信号只是让设计进入确定的状态,而时钟信号如同血管的供血功能一般保证设计可以正常地“跳动”;
  • 在Verilog的测试方式中,即便只给设计提供复位和时钟信号,整个仿真也会一直持续下去,并不会主动结束。即使DUT的输入激励已执行完毕,仿真也会一直进行下去,这就需要通过Verilog系统函数$finish()主动结束仿真(结束方式一),也可考虑使用$stop()暂停仿真;两者区别在于$finish会使仿真退出,将控制权交回给操作系统,仿真无法再次继续;$stop会使得仿真暂停,用户还有机会让仿真继续运行。

若仿真开始时在命令窗口敲入命令“run 0”,assign赋值语句和initial语句会开始执行,always时序/组合语句块不会执行:因为assign和intial在0时刻会执行一次,always必须等到信号变化才执行

结束方式二——program隐式结束:SV推出program将验证与设计进行有效隔离后,SV也会将每个program块作为一个独立的测试,如果testbench中只有一个program,则会在执行完该program最后一个initial后自动结束仿真。如果testbench中有多个program,那么需要等待所有program中最后一个initial才能结束仿真;要求仿真自动结束的前提是所有program的initial块都应在一定时间内完成

结束方式三——program显示结束:在目标program内置入系统函数$exit()要求该program强行结束,仿真器仍会等待其它program执行完毕再结束仿真

  • 建议将设计部分放置在module中,而将测试采样部分放置在program中;
  • program视为软件域不可出现和硬件行为相关的过程语句和实例,如always、module、interface(软硬媒介),也不应出现其它program例化语句
  • 为使program进行类软件方式的顺序执行方式,可在program内部定义变量,以及发起多个initial块
  • program内部定义的变量赋值方式应采用阻塞赋值(软件方式);
  • program内部在驱动外部硬件信号时应使用非阻塞赋值(硬件方式)。

为验证环境建立独立的测试盒子

  • 考虑采用program帮助消除采样竞争问题以及自动结束测试用例;
  • 也可采用module硬盒子的方式,使用interface clocking消除采样竞争问题,使用$stop()$finish()系统方法显示结束测试用例。

调试方法

库窗口

库(library)是编译的产物,在没有介绍软件之前,硬件(module,interface,program)都会编译到库中,如果不指定编译库则会被编译进入默认库中。从容纳的类型来看,库既可容纳硬件类型,也可容纳软件类型,例如类和方法,也包括包(package);

  • 对于编译的module,interface和package这些硬/软件,会进入哪个library呢?若无额外指定,它们都会被编译到默认库(work)中。在默认库中各个module是互相识别的,module也识别同个library中的package,如果要使用其他library中的module或package,那么config文件是一项好的选择;
  • 放入库中是仿真的必要步骤,但不代表后续的链接(elaboration)就不会出错。编译(compilation)会检查语法,而链接会进一步检查硬件和软件之间的兼容性、内存安全、结构可靠性等问题.

仿真窗口

仿真窗口(sim window)代表目前正在进行的仿真结构。一般在验证环境中,应该包含硬件测试的结构组件和待测设计(DUT)

  • 可以观察到TB的展开结构和DUT的结构,这种层次化的结构演示是所有仿真器的共性。而通过这种将硬件层次可视化展示的方式方便verifier查找任一层的信号。同时,被引入的package和其组件(utilities)、方法(methods)也会被显式出来;
  • 仿真窗口只能提供静态的层次结构,即由module,program,interface和package的内容,但对于class的例化实例这种在验证环境中的软件动态内容,则需要在类窗口(class window)和对象窗口(object window)中查看。

过程窗口

过程窗口(process window)代表整个仿真在某一时间点上所有过程语句块(initial, always, assign)的状态

  • 如果状态为active,代表该进程块正在执行ready状态代表该进程块是非活跃状态(但不一定代表它已执行完毕或不会再执行);
  • 过程窗口对调试仿真挂起(hang-on),时间无法继续前进的仿真难题特别有效。

查看信号和波形

打印消息

  • 打印消息是调试循环语句、顺序执行语句等查看执行路径和当前变量值的简便方式;
  • 打印消息的基本要点:在$display()系统方法中通过传递$time显示消息发生的时间点。在$display()中通过不同数据格式显式想要的数据格式,例如%x(十六进制)、%d(十进制)、%b(二进制)、%s(字符串)、%t(时间)等;
  • 掌握$display()(消息级别)、$warning()(警告级别)、$error()(错误级别)和$fatal()(严重级别)的使用场景;
  • 在打印数据消息时尽量采取格式美观、可读性高、便于维护的字符串显示格式;
  • 要实现对字符串string赋值,可采用$sformatf()方式对字符串变量格式化。

设置断点和查看变量

设置断点是软件的方法,在软件执行中,通过设置断点(breakpoint)可查看在程序在执行到断点处(程序暂时停止)时的变量数值,而设置断点就要求verifier对程序的执行顺序足够了解;

  • 设置断点便于查看软件程序(function,task,object)中局部变量的数值。要注意的是软件部分的变量(即动态变量,与硬件变量即静态变量相对)无法添加到波形窗口,原因之一是软件变量会在0时刻中完成多次运算,而波形窗口无法反映出在0时刻中的若干变化,且这么做对于波形存储的压力也很大。因此软件变量只可以通过设置断点来查看当前程序中的变量数值;
  • 设置断点的另一个作用在于可以用来调试程序执行的顺序,例如在顺序执行语句执行的多个位置设置断点,通过让仿真执行,查看是否程序在断点处停下,如果没有某个断点没有停留,那么程序的挂起(hang-on)原因就应该在上一个停留的断点和下一个未停留的断点之间。通过这种方式可以缩小调试可疑程序的范围
  • 如果要查看程序执行处的局部变量,需要使用的是局部变量窗口(locals window),可以从菜单栏View-> Locals选中,继而通过断点查看变量,不应使用信号窗口(objects window)查看变量,因为信号窗口是针对静态变量,而局部变量窗口是针对动态变量的。
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SystemVerilog的听课学习笔记,包括讲义截取、知识点记录、注意事项等细节的标注。 目录如下: 第一章 SV环境构建常识 1 1.1 数据类型 1 四、二值逻辑 4 定宽数组 9 foreach 13 动态数组 16 队列 19 关联数组 21 枚举类型 23 字符串 25 1.2 过程块和方法 27 initial和always 30 function逻辑电路 33 task时序电路 35 动态 静态变量 39 1.3 设计例化和连接 45 第二章 验证的方法 393 动态仿真 395 静态检查 397 虚拟模型 403 硬件加速 405 效能验证 408 性能验证 410 第三章 SV组件实现 99 3.1 接口 100 什么是interface 101 接口的优势 108 3.2 采样和数据驱动 112 竞争问题 113 接口中的时序块clocking 123 利于clocking的驱动 133 3.3 测试的开始和结束 136 仿真开始 139 program隐式结束 143 program显式结束 145 软件域program 147 3.4 调试方法 150 第四章 验证的计划 166 4.1 计划概述 166 4.2 计划的内容 173 4.3 计划的实现 185 4.4 计划的进程评估 194 第五章 验证的管理 277 6.1 验证的周期检查 277 6.2 管理三要素 291 6.3 验证的收敛 303 6.4 问题追踪 314 6.5 团队建设 321 6.6 验证的专业化 330 第六章 验证平台的结构 48 2.1 测试平台 49 2.2 硬件设计描述 55 MCDF接口描述 58 MCDF接口时序 62 MCDF寄存器描述 65 2.3 激励发生器 67 channel initiator 72 register initiator 73 2.4 监测器 74 2.5 比较器 81 2.6 验证结构 95 第七章 激励发生封装:类 209 5.1 概述 209 5.2 类的成员 233 5.3 类的继承 245 三种类型权限 protected/local/public 247 this super 253 成员覆盖 257 5.4 句柄的使用 263 5.5 包的使用 269 第八章 激励发生的随机化 340 7.1 随机约束和分布 340 权重分布 353 条件约束 355 7.2 约束块控制 358 7.3 随机函数 366 7.4 数组约束 373 7.5 随机控制 388 第九章 线程与通信 432 9.1 线程的使用 432 9.2 线程的控制 441 三个fork...join 443 等待衍生线程 451 停止线程disable 451 9.3 线程的通信 458 第十章 进程评估:覆盖率 495 10.1 覆盖率类型 495 10.2 功能覆盖策略 510 10.3 覆盖组 516 10.4 数据采样 524 10.5 覆盖选项 544 10.6 数据分析 550 第十一章 SV语言核心进阶 552 11.1 类型转换 552 11.2 虚方法 564 11.3 对象拷贝 575 11.4 回调函数 584 11.5 参数化的类 590 第十二章 UVM简介 392 8.2 UVM简介 414 8.3 UVM组件 420 8.4 UVM环境 425
SystemVerilog是一种硬件描述语言(HDL),用于设计和验证数字电路。SystemVerilog具有丰富的特性,适用于各种设计和验证任务。以下是SystemVerilog入门笔记的一些重点内容。 首先,了解SystemVerilog的基本语法是很重要的。SystemVerilog继承了Verilog的语法,同时加入了一些额外的特性,如数据类型、类和接口等。熟悉这些语法规则对于编写有效的代码至关重要。 其次,了解模块和端口的概念。SystemVerilog中的模块是最基本的构建单元,而端口则是模块与外部环境之间的接口。了解如何定义和使用模块和端口是编写可重用代码的关键。 另外,掌握数据类型和运算符是必不可少的。SystemVerilog支持多种数据类型,如整数、浮点数、逻辑值等,同时也提供了丰富的运算符,如加法、减法、逻辑运算符等。这些知识对于设计和验证数字电路非常重要。 此外,了解时序控制和并发控制是必要的。SystemVerilog提供了多种时序控制和并发控制的语法和特性,如always块、initial块和fork/join语句等。掌握这些知识对于设计复杂的数字电路至关重要。 最后,了解Verilog验证中的一些基本概念也是很重要的。例如,了解如何使用assert语句进行断言检查、如何使用coverage语句进行覆盖率分析等。 总之,SystemVerilog入门需要掌握其基本语法、模块和端口、数据类型和运算符、时序控制和并发控制,以及一些基本的验证概念。这些知识是成为一名合格的SystemVerilog工程师所必备的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值