system verilog 笔记(摘抄于网络)

lw:硬件放到lib;软件放到package;vif连接软硬件世界;

接口的作用
对各个模块做清晰有序的连接,同时将DUT和testch隔离开来,提高环境的复用性。需要注意的是:接口中的信号应该定义为四值逻辑,这样是为了防止接口与DUT相连时,X与Z的信号丢失(还要用“!==”“===”检查)。
接口还可以使用modport进一步确立不同对象对信号的连接方向。

program的使用
一般将设计部分放在module中,而将测试采样的部分放在program中。因此,program可以认为是软件的区域。所以always,module,interface等不应该出现在program中。
2.program驱动外部的硬件信号时应该使用非阻塞赋值

随机约束:
1.典型的随机分为俩大类:场景随机和接口随机。
2.应该在类中使用rand来声明随机变量,并且可以继承和复用。
3.可以使用randc来完成不重复的随机化
4.要完成随机化,例化的对象要显示调用randomize();
5.随机化生成二值逻辑。logic也只能生产二值。
6.没有在类中rand声明的变量也可以被外部随机化。

约束块
使用inside产生一个值的集合。
使用dist产生权重分布
使用unique来产生不重复的随机数。
使用foreach来完成迭代约束
内部约束均为硬约束,我们可以使用soft来定义软约束,当后来的约束与软约束冲突时,以硬约束为准。


随机化的控制
可以使用rand_mode来控制整个对象或某个成员的随机属性。
也可以使用constraint_mode来控制和关闭约束块。
我们可以使用randomize() with 来增加额外的约束。
我们使用randomize()可以传递变量的一个子集,只随机化类里的几个变量。例如:r.randomize(med)只随机华med。这种应用针对的是类里所有被指定或者没有被指定rand的变量都可以作为randomize()的参数而被随机化。
SV可以使用foreach对数组的每一个元素进行约束。
对句柄数组随机化时,要保证句柄的每一个元素都是非悬空的,需要在随机化之前为每一个元素句柄构建对象

在SV中,类可以定义在program, module, package中,但是一般一个类或几个相关的类会单独写在一个文件中。最终在program中调用。而且在SV中,所有成员默认都是public类型的,除非显示的用local/protected来声明。实际上,SV class中的变量应该尽可能的用public并且rand,来增加可控性。
基类的指针可以直接指向扩展类的对象,但是只能调用扩展类中基类的那一部分。基类的指针也可以直接转换为扩展类的指针,通过$cast函数,此时的基类指针指向的已经是扩展类对象,通过$cast,转变为扩展类指针,可以调用扩展类中自有的元素。
类中的静态变量可以通过类名::变量名的方式来引用。类中的其他变量都默认是automatic的修饰符,而且可以通过this.变量名,来直接调用类一级别的变量。在类的外部定义方法时,可以用关键字extern来在类中声明,后在类外通过类名::方法名的方式来定义。
类的继承(Inheritance),扩展类拥有基类的一切变量与方法,在扩展类中调用基类的变量与函数,可以通过super.+变量/方法来调用。在扩展类的构造函数中,应该先对基类先进行new函数。在扩展类的对象中调用对象时,SV比较句柄的类型来决定调用的是基类function还是扩展类function。但是当function是virtual类型时,SV会根据对象的类型来决定调用基类function还是扩展类function。推荐在需要扩展的基类中使用virtual function的形式,这样符合OOP的多态概念,也有利于向下转换。

类的三要素
4.1类的封装
类与结构体的异同:

都可以定义数据成员
类需要构造函数来构建对象实体。struct在变量声明就开辟了内存。
类可以声明方法,struct不能
struct只是一种数据结构,而类包含了数据成员以及操作方法。
类与module的异同:
二者都可以作为封闭的容器来定义和存储。
module必须在仿真一开始就确定是否被例化,而类可以在任何时间创建对象。
封装性来看,module内部的方法是开放的,而类内部的方法可以是protected或local。
继承性来看,module没有任何继承性,而类可以。
4.2类的继承
子类作用域如果与父类有相同的变量或方法名,以子类作用域为准。
父类的句柄指向子类的对象,只能访问子类中属于父类的部分。
4.3类的多态
-利用虚方法 实现类的动态方法查找
在定义虚方法时,要尽量定义在底层父类中。
虚方法通过virtual声明,且只用声明一次。
虚方法的继承遵循相同的参数和返回类型。
通过动态转换$cast可以判断父类句柄是否成功转换为子类句柄。

interface clocking
作用:用来进行事件的同步,输入的采样,输出的驱动。

线程的控制
fork join等所有线程都执行完毕,才跳出循环。
fork join_any只要有一个线程执行完,就跳出循环
fork join_none只是启动所有线程,并不等他们执行完毕。
如果希望所有fork块都执行完毕再退出,我们可以使用wait_fork语句。
我们可以使用disable来停止线程。

组件的通信
event ,单一的通知功能,用来做事件的触发。@是边沿敏感,阻塞等待事件的变化,wait(e1.triggered()是电平敏感。
semaphore,共享资源的安全卫士。使用前要用new对其进行初始化
mailbox,精小的SV原生fifo。也需要使用new对其进行初始化。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值