SV语言部分二
2020-11-10 13:45:02 0 举报
AI智能生成
大家点个赞
作者其他创作
大纲/内容
interface
可做硬件设计可做软件部分可单独做交互媒介
让dut和tb独立开来,使得连接变得简洁不容易出错,是硬件软件唯一的交互媒介
可在hardware中使用做例化,也可以在software中使用,用指针找到接口实例找其信号
在lab中主要用作数据的驱动
采样和数据驱动
竞争问题
always块内的阻塞赋值可能会引起竞争问题
非阻塞赋值也可能存在竞争问题
clk1产生clk2且clk1时刻触发数据时,某时刻的采样问题
在clk1,clk2,触发数据的时刻采样时,clk1上升沿采样的值是clk1触发前的值,clk2上升沿采样的值是clk1触发时的值(因为电路会有延迟,对应到仿真中就是一个delta-cycle,也就是说由于clk1产生的信号clk2和data会延迟一个delta-cycle)
如何避免采样中的竞争问题
1 在驱动时人为添加延迟,模拟真实信号行为,同时加大clk与变量之间的延迟
2 对于一些采样时仍然存在delta-cycle延迟的信号,可以在采样事件前的某段时刻中进行采样,来模拟建立时间的采样要求
接口中的clocking
可以在接口中声明clocking(时序块)和采样的clk,用来做信号的同步和采样。
clocking块基于clk周期对信号进行驱动或者采样的方式,使得tb不用纠结如何准确及时的对信号驱动或采样,消除了信号竞争的问题。
可以定义在interface中,module中,program中,且内部信号也是由interface或者其他声明clocking的模块定义的
声明完名字后,应该伴随着定义默认的采样事件,若没有定义,则默认在采样事件前1step对输入采样,事件后#0(一个时间片,即无穷多个delta-cycle)对输出做驱动。
可以利用clocking人为添加固定延迟来避免可能的采样竞争问题,使得仿真波形更容易体现出clk与被驱动信号的时序前后关系
clocking运用到interface中来声明接口与clk采样和驱动关系,提高了数据驱动和采样的准确性,根本上消除了采样竞争的可能性
测试的开始和结束
$finish()
$stop()
continue run
隐式结束:SV的program将验证部分和设计部分进行有效的隔离以后,SV将每一个program作为一个独立的测试,tb中所有program中最后一个initial完成后才能自动结束仿真。
显示结束:如果program中出现forever语句,可以用 $exit(); 结束
program是软件类型,不应出现always、module、interface、以及其他program例化语句
program内部定义的变量赋值应采用阻塞赋值(软件方式)
program内部在驱动外部的硬件信号时应使用非阻塞赋值(硬件方式)
可以有initial过程块
调试方法
库窗口
library是编译的产物,module、interface、program都会编译到库中
库既可以容纳硬件类型,也可以容纳软件类型例如类和方法,也包括包package
编译的module、interface、package这些硬件和软件默认会进入work里,默认库中的module是互相识别的
如果要使用其他library中的module或者package,一个config文件是一项好的选择
放入库中是仿真的必要步骤,但不代表后续的链接(elaboration)就不会出错。编译(compilation)会检查语法,链接会进一步检查硬件和软件之间的兼容性、内存安全、结构可靠性问题等。
仿真窗口
代表正在进行的仿真结构。一般在验证环境中,应该包含硬件测试的结构组件和DUT。
在整个tb结构中,可以看到tb的展开结构和dut的结构。层次化的结构演示是所有仿真器的共性,可以方便verifier查找任何一层信号
过程窗口
代表某一时间点所有过程块(initial、always/assign)的状态。
active代表该进程块正在执行,如果是ready状态,代表该进程块是非活跃状态
process window对于调试一些hang-on,时间无法继续前进的仿真难题特别有效(例如:initial forever (delta-cycle无限制循环))
查看信号和波形
在sim window中点击某一个层次,继而在 object window中选中需要的信号添加到波形窗口处
懂得信号的输入、输出和内部信号的属性以及当前数值的默认进制(十六进制),懂得修改信号数值的进制显示格式,懂得如何强制修改force信号的数值。
熟练应用如何开始仿真、重启仿真、结束仿真等操作。
在命令窗口 transcript window使用命令“log -r /*"在开始仿真前调用,确保tb层次下所有信号都可以保存到数据库以供查看任何信号的波形。
打印消息
$display() $time显示时间 %x十六进制 %d十进制 %b二进制 %s字符串 %t时间
$display() $warning() $error() $fatal()严重级别
如果要实现对字符串string赋值,可以采用$sformatf()来对字符串变量格式化,例如 string s = $sformatf("Hello, %s!", name_s),这里name_s是名字的字符串变量。
设置断点和查看变量*
设置断点breakpoint可以查看在程序在执行断点处(程序暂时停止)时的变量数值,而设置断点就要求verifier对程序的执行顺序有足够的了解。
设置断点便于查看软件程序(function、task、object)中局部变量的数值。要注意的是,软件部分变量(动态变量dynamic variable,与硬件变量即静态变量相对)是无法添加到波形窗口的,因为软件变量会在0时刻完成多次运算,而波形窗口无法反映出0时刻中若干变化,对于波形存储压力也很大。
设置断点可以用来调试程序执行的顺序(例如在顺序执行语句执行的多个位置设置断点,通过让仿真执行,查看是否程序在断点处停下,如果没有在某个断点停下,那么程序的挂起原因就应该在上一个停留的断点和下一个未停留断点之间,缩小可以程序范围)
查看程序执行处的局部变量,需要使用局部变量窗口locals window,可以从view - locals选中,继而通过断点查看变量,不能使用object window查看,object window对应的是静态变量,locals对应的是动态。
0 条评论
下一页