前言:个人学习SV的在线笔记。学习SV的过程中借鉴一些大佬的笔记和路科验证学习资料,只做个人学习交流使用,感谢!
logic和reg、wire的区分和联系:
SV为何有了四值逻辑还要引入二值逻辑?
SV在开始设计时就希望将硬件世界和软件世界分开,而软件的世界即验证环境,更多的是二值逻辑。
四值逻辑:integer、logic、reg、net-type(如wire、tri)
二值逻辑:shortint、int、longint、byte、bit
有符号:shortint、int、longint、byte、integer
无符号:bit、logic、reg、net-type(如wire、tri)
助记:二值逻辑:三种int+bit/byte;有符号:三种int+integer/byte。
四值转二值:Z、X变为0;每位四值逻辑须用连续2位存储。四值逻辑类型有四种值,所以需要2bit来表示。
组合型数组和非组合型数组:变量名右边声明数组维度为非组合型(拷贝时操作数维度和大小须一致),左边为组合型数组(可直接赋值);
数组维度从高到低是先看数组名右侧(从左到右)再看左侧(从左到右)
bit[3][7:0] b_pack;
每一个元素都是8bit,一共有3个元素,3*8=24bit,因为是组合型,所以占用一个WORD空间。bit[7:0] b_unpack[3];
因为是非组合型,每一个元素占用一个WORD空间,但是有效空间只有8bit。logic[3][7:0] l_pack;
因为是组合型,每个元素有8bit,一共有3个元素,每种值得用2bit来表示,所以8×3×2=48位,用2个WORD空间足以。logic[7:0] l_unpack[3];
因为是非组合型,每个元素占用8bit,而四值逻辑得用2bit表示,所以一个元素8*2=16位,用一个WORD足以放下一个元素,所以需要3 * WORD=3WORD的空间。定宽数组的宽度在编译时就确定,动态数组最大特点是可以在仿真运行时灵活调节数组的大小即存储量,在一开始声明时用‘[ ]’来声明,此时是空数组;其后用‘new[]’分配空间,在[ ]中传递数组的宽度;可在调用new[ ]时将数组名一并传递,将已有数组的值复制到新数组中。
关联数组可用来保存稀疏矩阵的元素,对一个非常大的地址空间寻址时,该数组只为实际写入的元素分配空间,这种实现方法所需空间比定宽或动态数组所占用的空间要小得多。
对于赋值,可用赋值符号“=”直接进行数组的复制;
对于比较,在不适用循环的情况下,可利用“==”或“!=”比较数组的内容,结果仅限于内容相同或不相同。
//声明的同时,对4个元素初始化
int ascend[4] = '{0,1,2,3};
//声明和赋值分开操作
int descend[5];
descend = '{4,3,2,1,0};
//4个值全部赋值为8
ascend = '{4{8}};
//部分元素使用默认赋值
descend = '{9,8,default:-1}; //{9,8,-1,-1,-1}
队列结合链表和数组的优点,可在其任何地方添加或删除元素,通过索引实现对任一元素的访问,声明:[$]
,队列元素的标号从0到$;不需要new[ ]创建空间,初识空间为0;通过其方法push_back()和pop_front()的结合实现FIFO的用法。
注意:队列赋值不像数组或结构体赋值需要使用单引号。
结构体struct:数据的集合,其通常的使用方式是将若干相关的变量组合到一个struct结构定义中;伴随typedef可用来创建新类型(实现类型共享),并利用新类型声明更多变量。
枚举类型enum:常和typedef搭配使用,便于用户自定义枚举类型的共享使用,保证了一些非期望值的出现,降低设计风险。
举例: INT=enum √ 枚举类型可直接赋值;
enum=T’(INT) —— 反过来须做类型转换为enum类型。
在enum/struct类型声明时添加typedef与否的差别:
enum{NO,YES} bool
,那么bool为枚举类型"变量",而enum{NO,YES}
按匿名类型 (implicit type)来理解;typedef enum{NO,YES} bool_t
,那么bool_t为枚举类型,即通过typedef将匿名类型“显式" (explicitly)定义为bool_t,并且接下来可重复利用bool_t声明多个变量。避坑指南:对于重复使用的enum/struct定义,默认添加typedef先定义类型,再利用该类型声明变量。
字符串string(VHDL和Verilog所没有的):保存和处理所有与字符串相关的处理;
字符串的格式化函数$sformatf()
,即如何形成一个想要的字符串句子;使用$display
打印输出。
域:定义的软件变量或例化的硬件所在的空间。
always:描述硬件行为,描述硬件时序电路和组合电路的正确打开方式,使用时需注意是描述时序电路还是组合电路,其@(event..)
敏感列表是为了模拟硬件信号的触发行为,只可在module或interface中使用。
注意,always由时钟或其他非时钟信号驱动,不同的always语句块之间是并行执行的,不可在always中初始化变量(这是软件概念,一般在initial或定义变量时进行初始化),但可以做复位。
initial:非常符合软件的执行方式,即只执行一次;和always一样无法被延迟执行,仿真一开始都会同步执行,不同的initial和always之间的执行顺序是没有顺序的;initial不应存在于硬件设计代码中,其本身不可综合,对于描述电路没有任何帮助;它为测试而生,可实现测试按照时间顺序,即软件方式来完成。
函数function:同C语言的函数非常类似。可以在参数列表中指定input、output、inout、ref类型的参数,也可返回数值或是void不返回数值。
模块:module为硬件域,在定义时需标注方向、位宽和端口名。
模块例化:在上层例化底层模块,或TB例化DUT时均需要完成模块例化;例化时需注意模块名、参数例化传递、例化名和端口名例化对应。
模块连接:
测试平台:整个验证系统的总称,包括验证结构的各组件、组件之间连接关系、测试平台的配置和控制,更系统的讲还包括编译仿真的流程、结果分析报告和覆盖率检查等。狭义上主要关注验证平台的结构和组件部分,可产生设计所需要的各种输入,在此基础上进行设计功能的检查。