SV学习小结
1、验证的目的或指标?
①DUT的行为表现是否与特性列表中的要求一致;
②DUT是否实现了所有特性;
③DUT对于异常状况的反应是否与特性列表和spec中一致,比如中断是否置起;
④DUT是否能够从异常状态中恢复到正常工作模式。
2、什么是分层验证平台?
3、SV中program的作用?
1)分离testbench与DUT;
2)有助于确保testbench和DUT没有竞争冒险;
3)提供了执行testbench的入口点;
4)通过(program…endprogram)指定了 reactive region的调度。
4、program和module的区别?
两者的代码运行的时间域是不同的,可以避免一些竞争与冒险。
1)module里可以定义program,而program里不能定义module。
2)是module里不能调用program里定义的task,、function,而program可以调用module里定义的task和function。
3)program里不能例化module、interface、其它program,也不能包含always块·。
4)最主要的区别是program是在inactive时域执行的,而module在active时域执行的,所以program在module后执行,可以解决竞争冒险现象。
5、解释数据类型logic、reg和wire之间的区别?
wire:用于连接不同的元件,不存储值,被连续复制(assign)或端口(port)驱动
reg:并不意味着实际的寄存器,代表verilog/sv 中的数据存储元素。保存值,直到将下一个赋值(不是通过assign语句赋值)。可以被综合成触发器,锁存器或组合电路。
logic:不能被多驱动,改进了reg数据类型,可以被连续赋值。
6、什么数据结构用于在scoreboard中存储数据,为什么?
mailbox或queue。对于每个周期,我们分别从输入和响应中收集并删除这些数据,因此,queue或mailbox比array更方便。
7、什么是队列?
可以在队列中的任何位置添加或删除元素;可以直接访问带有索引的任何元素。
8、与队列相比,链表的优点是什么?
队列具有固定的顺序,很难将数据插入队列中。但是链表可以轻松地将数据插入任何位置。
9、关联数组和动态数组之间的区别?
关联数组具有字符串索引功能,在编译时分配内存;动态数组在运行时分配内存,构造函数用于初始化动态数组的大小。
10、什么时候使用关联数组?
当集合的大小未知或者数据空间稀疏时,关联数组是更好的选择,在使用前不会分配任何存储,并且索引不限于整数表达式。
11、什么是流操作符,其作用是什么?
流操作符<<和>>,将数据块打包为比特流。>>运算符从左向右打包数据,而<<运算符从右向左打包数据。
12、什么是clocking skew?
1)input在时钟之前的skew time采样;
2)output在时钟之后skew驱动;
3)默认input skew为1 step time;output skew为0;
13、时钟块什么时候采样?
答:时钟块默认输入偏斜为1step,也就是在上一个时钟片的结束部分。换句话说,就是在紧接着时钟上升沿之前采样信号,或者说是本时钟片的preponed区域。如果显示使用#0输入,则会在相应的时钟事件同步进行采样,但是是在observed区域采样,这样可以避免竞争情况。同样的,在re-NBA区域进行输出。忘了的,不懂的看这个SystemVerilog中scheduler(调度)。
14、clocking block的用处?modports 的用途是什么?
interface指定testbench和DUT通信的信号,但是interface没有明确指定任何时序规则和同步要求。system verilog添加了clocking block 指定任何时序规则和同步要求,以确保testbench在正确的时间与DUT交互,实现同步特性,还可以避免竞争冒险问题。
modports是interface的一部分。modports用于指定与不同模块接口所连接的信号方向。
15、interface为什么clk要写在括号里?
我的理解是,clk 是在顶层testbench中驱动的,其他component只会使用clk作为input,这样可以减少不必要的接口层次。而且,虽然clk和interface中的其他端口定义的位置不一样,但是在仿真环境中还是可以使用<接口实例名>.clk。这个仍然代表着interface中的clk信号。但是除了对DUT模块使用上述clk信号,对于在testbench,不建议使用这个clk,要用时钟块的名称替换,这样做的好处是避免在仿真时发生竞争冒险,使得各个信号是时钟同步信号。但是需要注意的是,使用时钟块时,不再需要添加上升沿或者下降沿关键字,给时钟块中的变量赋值时应当使用<=而不是=。
16、为什么resetn需要定义两次?一次在时钟块中,一次在modport中?
答:为了做到异步复位,同步释放。因此resetn有效时应当直接使用<接口实例名>resetn,释放时为<接口实例名>.resetn。
17、使用system verilog避免testbench与DUT之间竞争冒险的方法有哪些?
module中的initial语句块调度在active region,而program中的initial语句块调度在reactive region。
在program中使用非阻塞赋值来驱动设计信号,在re-NBA区域对其进行更新。
通过带有#0 input skew 的clocking block。
18、Interface的优点是什么?
接口是设计可重用的理想选择。
1)当信号数量很大时,它减少了信号错误连接的可能性。
2)易于在设计中添加新信号。
19、virtual interface的需求是什么?
无法在system verilog中的non-module 实体内部实例化interface,但是需要验证环境中的class中驱动interface。
virtual interface 是一种数据类型(可以在一个class中实例化),它保存着对实际接口的句柄(这意味着class可以使用virtual interface来驱动该interface )。
virtual interface 提供了一种可以将验证平台抽象模型与构成设计的实际信号分开的机制。另一个优点是,类可以在运行(run time)动态连接到不同的物理接口(physical interfaces)。
20、SV中的alias有什么用?
verilog的assign赋值是单向赋值,通过RHS变化影响LHS,但是LHS的变化不会影响RHS,SV中alias可以进行双向赋值。
21、什么是“范围解析运算符(::)”(scope resolution operator)?
extern关键字允许在类外定义方法。范围解析运算符(::)将方法构造链接到类声明。
22、如何确保传递的ref函数参数不被改变?
const ref
23、解释pass by ref和pass by value?
pass by value(按值传递)是将参数传递给function和tasks的默认方法,每个子程序保留该参数的本地副本。如果在子程序中更改了参数,不会影响原本数据。
pass by reference(按引用传递)中functions和tasks可以直接访问改变传递的参数,就像传递变量的指针一样。
24、什么是变量的scope 和lifetime?
1)static:在时间0分配内存并初始化;存在于整个仿真周期。
2)automatic:在调用时分配内存并初始化;存在于某个进程中。
3)global variable:在模块外定义,所有模块可以读取。
4)local varialbe :在模块外定义,用于模块内,也可以层次化调用。
25、介绍一下SV中的三种fork-join?
1)fork-join:父进程将阻塞,直到该语句块中所有进程都完成为止。
2)fork-join_any:父进程将阻塞,直到该语句块中的任何一个进程完成为止。
3)fork-join_none:父进程与该语句块中所有进程同时执行。
26、initial语句块和final语句块有什么区别?
initial语句块在仿真开始时执行,final语句块在仿真结束时执行。
final语句块不能有delay、wait和non-blocking具有时序的语句。
27、packages 的用途是什么?
在verilog中,模块内变量/任务/函数的声明特定于模块(module)。system verilog的package结构允许声明全局变量/任务/函数,从而在module/classes之间使用。
package可以包含module/class/function/task/constraints/covergroup等声明,在使用时需要使用范围解析运算符(::)或import来访问packages中的内容。
28、system verilog package的作用以及include和import的区别?
答:include是编译预处理语句,是将文件中的内容插入到当前文件中。
import是package里面的全部identifiers 或者指定identifiers 对当前作用域可见。
29、如何随机化动态数组对象?
class ABC;
rand bit [7:0] data[];
constraint cc {
data.size inside{[1:10]}; //constrainting size
data[0] > 5; //constrainting individual entry
foreach (data[i]) //all elements
if (i > 0)
data[i] > data[i-1];
}
endclass
30、什么是$root?
top-level scope,可用于引用任意层次中例化的模块。
31、 $ rose和posege有什么区别?
always @(posedge clk)
reg1 <= a & $rose(b);
在此示例中,(posedge clk)应用于$ rose,当b的采样值变为1时,$ rose为true。
1)采样值变为1,则$ rose返回true,否则返回false
2)采样值变为0,则$ fell返回true,否则返回false
3)采样值不变,则$ stable 返回true,否则返回false
posege返回一个事件(event),而$ rose等返回一个布尔值,两者不可互换。
32、什么是双向约束(bi-directional constraints)?
默认情况下,System verilog 中的约束是双向的。这意味着约束求解器(constraint solver)不遵循约束指定的顺序,同时约束所有变量。
33、在constraint之前的solve是什么意思?
如果用户要指定约束求解器求解约束的顺序,则用户可以在约束之前通过solve指定顺序。
34、什么是依赖循环(circular dependency),如何避免这个问题?
过度指定约束求解顺序可能会导致循环依赖,对此没有解决方案,并且约束求解器可能会给出错误/警告,约束求解失败。
35、如何根据随机索引从queue中选择元素?
int q[$] = {1,2,3,4};
int index[4],out;
foreach(index[i])
index[i] = i;
index.shuffle(); //orindex[i] = $urandom_range(1,4);
foreach(q[i])
out = q[index[i]];
36、不使用randomize方法或rand,生成随机循环数组。
int uniqval[10];
foreach(uniqval[i])
uniqval[i] = i;
uniqval.shuffle(); //打乱排序
37、如何检查随机化是否成功?
if (!obj.randomize()) begin
$display("Error in randomization");
$finish;
end
或者
assert (!obj.randomize())
38、什么是覆盖率驱动的验证(coverage driven verification)?
覆盖率驱动验证是一种以结果为导向的功能验证方法。
根据测试的防窥来开发随机测试激励,初始测试可以使用许多不同的种子,从而创建许多唯一的输入序列。后来,即使使用了新的种子,测试激励也不太可能产生到达所有的设计空间。
当功能覆盖率逐渐接近其极限时,需要更改测试以找到新方法来覆盖设计的未覆盖空间。这就是所谓的“覆盖率驱动验证”。
39、代码覆盖率和功能覆盖率有什么区别?
功能覆盖率:决定了设计已实现了多少功能。
代码覆盖率:描述设计中代码执行的客观信息。
40、什么是交叉覆盖率(cross coverage)?
在多个cover point上同时统计接收到的信息。
cross coverage通过下面方式指定:
covergroup cg;
cover_point_x:coverpoint x;
cover_point_y:coverpoint y;
cross_xy:cross cover_point_x, cover_point_y;
endgroup
41、什么是bin(仓)?
bin使用名称(name)和计数(count)记录一组值(value)或者序列(value transitions)的次数。如果bin指定一组值,则每次覆盖点与该组中的一个值匹配时,相应的次数就会增加。如果bin指定序列,则每次覆盖点序列匹配时,相应的计数就会增加。
program main;
bit [0:2] y;
bit [0:2] values[$] = `{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
option.auto_bin_max = 4;
}
endgroup
cg cg_inst = new();
initail
foreach(values[i]) begin
y = values[i];
cg_inst.sample(); //gather coverage
end
endprogram
42、什么是covergroup?
捕获来自随机激励刺激,封装覆盖率要求。
43、为什么要使用断言(assertions)?
断言主要用于检查设计的行为是否正常。可以用来提供功能覆盖信息,断言可以分为立即断言和并发断言。
44、什么是立即断言(Immediate assertions)和并发断言(concurrent assertion)?
立即断言:当使用if或assert()执行语句时,立即断言检查表达式是否为真。
并发断言:并发断言通过使用property持续检查仿真过程中的信号值。
45、如果设计工程师和验证工程师在testbench和DUT中犯同样的错误怎么办?如何能够发现错误?
1)代码审查(code reviews)和协议检查器(protocol checkers);
2)在多个层次,由不同的人员进行验证(模块级和系统级);
3)客户发现(worst case)
46、如何客户发现了芯片的bug,该如何调试?如何防止它再次发生?
1)尝试在自己的环境中重现该问题。
2)确定问题之后,在下一个的验证中增加断言或者相应的test case。
47、函数重载和函数覆盖之间有什么区别?
重载是一种允许使用相同名称定义多个成员函数的方法,编译器将选择正确的函数。
覆盖是一种允许派生类重新定义从基类继承的成员函数的方法。