SystemVerilog绿皮书疑难点解析

本文详细探讨了SystemVerilog中的关键概念,包括联合(union)、从函数中返回数组、激励时序、接口驱动与采样、断言、任务中修改句柄、对象复制、随机化检查、约束、线程使用和回调机制。通过实例解析,解释了在设计和验证中如何有效地利用这些特性,特别强调了对象复制的复杂性和蓝图模式在生成器中的应用。
摘要由CSDN通过智能技术生成

2.10.3 联合(union)

(待续)

3.5.2 从函数中返回一个数组

(待续)

4.3 激励时序

(待续)

4.4 接口的驱动和采样

(待续)

4.8 SystemVerilog断言

(待续)

5.14.2 在任务中修改句柄

1、当你想修改参数的值的时候,需要在方法的参数前面加上ref关键词,尤其是句柄。(ref参数有一个好处是在任务里可以对其进行修改而且修改结果对调用它的函数随时可见)

修改句柄——对句柄使用new()
修改对象——将对象的变量重新赋值

若你想在方法中修改句柄,那么必须加ref,若只是修改对象,可以不用加ref。

不加ref,方法对句柄的修改在主程序中不可见,也就不知道句柄被new()了,调用该句柄的对象时会失败,因为在主程序中该句柄仍然是null。
不加ref修改对象是可以的,如下例,主程序中new()创建了一个对象,而句柄是指向对象的指针,传递的是句柄,transmit中也指向了对象,所以transmit中可以对该对象进行修改。

Task transmit(Transcation t);
Cbbus.rx_data <= t.data;
t.stats.startT  =  $time;     //在任务中,改变了对象
endtask

trancation t;
initilal beign
t = new();
t.addr = 42;
transmit(t);
end

2、当你想创建多个对象时,应该在循环中,new()多个对象,而不是先new()对象再循环发送事物。

5.15 对象的复制

1.使用new操作符复制一个对象——简易复制(shallow copy)
你定义的任何new()函数都不会被调用。

Transaction src,dst;
src = new() //
dst = new src //复制

局限:如果类中包含一个指向另外一个类的句柄,那么只有最高一级的对象被new复制(包括该句柄),下层的对象都不会被复制。这样会出现意想不到的错误。当前类中变量和句柄被复制,这样两个句柄都指向另外一个类的对象statistic,但是statistic没有被复制。如果其中一个transaction对象,修改了statistic对象值,会影响到另一个transaction看到statistic的值。

6.3.2 检查随机化(randomize)的结果

除了使用断言来检查随机化的结果,还可以宏定义一个语句来进行检查,输出有用的错误信息,并结束仿真。
在这里插入图片描述
绿皮书的英文版中很多地方用的这个来检查。

6.4 约束

约束块可以像类外的方法定义一样,定义在类的外面

class C;
	rand int x;
	constraint c1;         //隐式形式
	extern constraint c2;  //显式形式
endclass

constraint C::c1{
   x inside {
   0,1};}
constraint C::c2{
   x >= 0;}

如果使用约束原型的隐式形式,则对应的外部约束块可以有,也可以没有,没有则为空约束。
如果使用约束原型的显式形式,则必须有对应的外部约束块,没有的话会报错。

6.4.7 条件约束和相等约束

a -> b      //(!a || b)

当a为true时,b必为true;
当a为false时,b可能为true,也可能为false。
可以正推也可以反推。
a和b可以是表达式,判断其为true或false即可。
例:

rand bit a,b;
constraint c{
   `(a==1)`->(b==1);}

如果在上例中再加入一个约束{b==0},那么可知约束c中(b==1)是false的,可以推出(a==1)也是false的,则a应该为0。

如果加入的约束是{b==1},那么可知约束c中(b==1)是true的,可以推出(a==1)可能是true的,也可能是false的,则a可能为0或1。

也可见书中例6.25和例6.26。

a <-> b   //相等约束

当a为true时,b也为true;
当a为false时,b也为false,

6.5 解的概率

(待续)

6.13.5 产生具有唯一元素值的随机数组

为什么例6.59中的数组没有使用rand,而例6.61的数组使用了rand?
其原因可能是上例中使用的是固定数组,只能随机化其内容,而其内容又是通过randc辅助类来产生的,故不用rand来修饰数组;下例中使用的是动态数组,可以对其长度或内容进行随机化,所以使用rand来修饰。

为什么例6.59使用的是pre_randomize,而例6.61使用的是post_randomize?
上例中LittleUniqueArray类中没有rand变量,randomize()不会成功,若使用post_randomize()来将随机值赋给数组元素是不会执行的,因此在pre_randomize()中进行赋值;而下例中有rand变量,randomize()会成功,若在pre_randomize()中进行赋值,randomize()后会将其覆

  • 3
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值