本人的学习的一些小总结,写给自己,方便复习。一些总结性的摘要性的,可能自己才能看懂写的是什么鬼东西哈哈哈
1. 数据类型。
类型:变量variables/线网net。和Verilog不同的,对变量类型,可以使用连续赋值,或者过程赋值。
数据类型:四值逻辑logic/二值逻辑bit。
有符号/无符号。logic/bit构成的向量vector是无符号。integer,int,byte,short,int,longint有符号。
多驱动或者双向inout只能用 线网wire。logic不能被多驱动。
2. 自定义类型
typedef。Typedef就是用来创建新的类型的。常常和enum/struct一起用,定义枚举类型/定义结构体类型。
枚举类型enum。默认的枚举类型是int。枚举类型可转换成整型。整型不能隐式的转换成枚举类型。
结构体struct。
3. 字符串类型
4. 设计特性
= = / = = = 的区别。
inside。
unique case。每次case选项只能满足一条,不能重叠。可以并行运行,case选项必须完备。
priority case。必须至少有一个case满足。
case(z)/case(x)。
5. 接口interface
modport约束不同模块连接的信号方向。(常用在设计中)。
clocking block(常用在testbench)。
6. 采样和数据驱动
设计中,避免RTL仿真中的信号竞争。采用非阻塞赋值或者特定的信号延迟来解决同步的问题。
clocking block(常用在testbench)。做信号的同步和采样。clocking block基于时钟周期对信号进行驱动或者采样的方式,使得testbench无需考虑准确及时的对信号驱动或者采样,消除信号竞争。
7. 任务和函数
function和task的区别:
- 任务可以消耗仿真时间,函数不可以。任务可以调用函数和任务,函数一般不能调用任务(只能在由fork...join_none语句中生成的线程中调用)。
- function只能返回一个单一数值,若不返回数值,应声明void。而task不会返回数值,只能通过output,inout或者ref的参数来返回。
- 函数至少有一个输入变量。任务可以没有或者多个输入(input)、输出(output)和双向(inout)变量
8. 数组
定宽数组:非组合型数组/组合型数组。
动态数组:
队列:
数组方法
9. 类class
封装/继承/多态(虚方法)。
类的成员默认是public。local(只有此类可以访问)/protect(此类和子类都可以)。
只要父类new函数没有参数,子类就会默认调用父类new函数(super.new写不写都调用)。若父类new函数有参数,则子类必须写super.new来调用父类new函数。必须继承new函数并调用,否则编译报错。
10. 包package
11. 随机约束
randomize()。randomize() with,内嵌约束。
系统函数:$urandom(),生成32位无符号随机数。$random(),生成32位有符号随机数。$urandom_range(max,min=0)。
类的成员变量:整型变量(bit/byte/int)/数组(定长数组/动态数组/关联数组/队列)(数组一定要先约束长度size)声明为随机属性。rand/randc。
12. 约束块
rand integer x,y,z;
constraint C {x inside {y,z};};
权重设置:
constraint C_dist {x dist {0:=40, 1:=60};};
constraint C_dist {x dist {0:/40, 1:/60};};
:=
:/
unique
条件约束
软约束soft 约束覆盖。
13. 随机控制
rand_mode(0)/ rand_mode(1)/
14. 约束控制
constraint_mode()
15. randomize()
随机化个别变量。使用随机化函数时randomize(),如果有参数,例如randomize(x)。那么只随机化x(不管有没有声明rand),其他不管(不管有没有声明rand)。
16. 数组约束
foreach约束数组每一个成员。约束数组的size。
17. 线程控制
fork join/fork join_any/fork join_none
wait fork:等待所有fork进程全部执行完。
disable fork:停止fork…join_any中所有没有来得及执行的并发子线程。
18. event
event是2个线程之间的通信
触发:-> (非阻塞)(类比于接电话)
等待:@ or wait(阻塞)
若用->和@搭配,一定要先@再->;若用->和wait搭配,则谁先谁后都可以。@是边沿触发,wait是电平触发。event e1;@e1/wait(e1.triggred); ->e1;
Wait_order: 阻塞等待多个事件的触发,并且要求这多个事件按照用户决定顺序触发。wait_order可以和else一同使用,当多个事件 按顺序触发时,执行wait_order后的语句,否则执行else后的语句。
19. semaphore旗语
≥2个线程之间的通信。共享资源管理,多个线程访问某一个公共资源时可以使用这个要素;
20. mailbox信箱
类似FIFO,数据传输的媒介,在线程之间做数据通信或内部数据缓存时可以考虑此元素。
21. 虚方法/多态
类的三个小知识:1.小白不要给变量添加local/protect,给自己挖坑。2.类继承的时候,为了操作简单,为了能访问到更多的变量,子类和父类不要出现同名的变量。但是子类和父类出现同名的方法是常见的,因为经常要override重载方法或者继承方法。3.用不同类型的句柄(子类句柄赋值给父类句柄,复制后都指向子类对象)调用相同对象的方法时,为了让输出结果一致,要在父类或者根类声明virtual。
22. 类型转换
静态类型转换:
动态类型转换:$cast()。父类句柄赋值给子类句柄。确保该父类句柄所指向的对象是子类句柄类型的对象。(应用场景:实际项目中简化操作)。
23. 断言assertion
断言是设计的属性的描述
即时断言:1.不是时序相关的,是立即被求值2.必须放在过程快中3.只能用在动态仿真中。用不用无所谓。
并发断言:1.基于时钟周期2.可以放到过程快,模块,接口,或者program中3.可以在形式验证或者动态仿真工具中使用。时序检查
sequence/property
断言$past的用法:例如让你写abcd四个信号在时钟沿处监测,当cd同时为1时,在时钟的前两个周期要ab同时为1的断言.
property P1;
@(posedge clk) (c&&d)|->($past(a&&b,2)==1);
endproperty
a1:assert property(P1);
24. 接口上使用output和ref的区别是:
1. output 端口用于将信号值从模块(或接口)的内部传输到外部。它只能在模块(或接口)内部驱动,外部只能读取值,不能驱动它。单向
2. ref 端口用于通过引用传递变量, ref 变量的改变会直接反映在引用者和被引用者之间。它允许双向的读写访问,并使得参数的改变可以在调用者和被调用者之间直接传递。ref 端口只能是 var(变量)。双向
3. 接口模块里的信号不能定义方向,需要定义方向时使用modport指定interface相应模块里的信号方向和分组,若没有使用modport定义方向,接口中的线网信号默认为inout、变量默认为ref。