2.1内建数据类型
Sv中的reg可以进行连续赋值;
logic只能有一个驱动;若是信号本身有多个驱动,则需要被定义为wire线网类型;
二值逻辑和四值逻辑:
Logic是四值逻辑:1,0,X,Z;bit为二值逻辑;1,0
Sv引入四值逻辑是期望硬件世界和软件世界分离开。四值逻辑属于硬件设计,二值逻辑属于验证环境;
四值逻辑:integer,logic,reg,wire
二值逻辑:byte,shortint,int,longint,bit
无符号的四值逻辑中的一个位x,转换为无符号的二值逻辑会等于0
接口内的信号需要DUT连接,因此要用四值逻辑来确保有x和z状态,而非二值逻辑。接口中最好以使用 logic 做为信号的类型。因为logic可以直接赋值,而 wire 必须要被连续赋值语句可来驱动。
有符号类型:beyt,shortint,int,longint,integer
无符号类型:bit,logic,reg,wire
有符号数:负数以补码的形式储存;正数以原码形式储存;最高位为符号位,0为正数,1为负数;
不同类型的数据进行操作时,应该注意变量的:1.逻辑数值类型2.符号类型3.矢量位宽
2.2定宽数组
2.2.1定宽数组的声明和初始化
如果试图从一个越界的地址中读取数据,那么sv将返回数组元素类型的缺省值;对于一个元素为四状态类型的数组,返回的是X;而对于双状态数组,则返回0;
存放四值类型数据会比存放两值类型数据多占用一倍的空间
用一个单引号和大括号来初始化数组`{};
2.2.2常量数组
int descend[5];
descend = `{4,3,2,1,0}//`{9,8,3{1}}//`{6,5,default:0}
2.2.3for和foreach
$size函数返回数组的深度
for 和 foreach会按照数组中元素的索引值开始遍历。也就是说:
对于 f[0:4] 数组,遍历索引值从 0 ~ 4,采样foreach(f[i]),等同于for( int i = 0; i <= 4; i ++)
对于 f[6:2] 数组,遍历索引值从 6 ~ 2,foreach(f[i]),等同于for( int i = 6; i <= 2; i --)
int array2 [2] [3] = '{'{2,3,4},'{4,5,6}};
//遍历方式一://推荐!!!
foreach( array2[i,j] ) $display("数组中第[%0d] [%0d]= %0d;",i,j,array1[i][j]);
//遍历方式二:
foreach(array[i]) begin
foreach(array[,j]) $display("数组中第[%0d] [%0d]= %0d;",i,j,array1[i][j]);
end
2.2.4复制和比较
对于组合型,数组会被视为一个向量,即便两边的操作数的维度不相同时,也可以做赋值
长的赋值给短的,会截断高位,保留跟短的相同长度的低位
短的赋值给长的,短的会占据低位,高位会被填充为0
对于非组合型,要求左右两侧操作数的维度和大小必须一致;
非组合型无法直接赋值给组合型;同样组合型也无法直接赋值给非组合型
2.2.5合并数组
它可以作为一个整体来访问,也可以把他分解成更小的单元;它的存放方式是连续的集合,中间没有任何闲置的空间。
声明合并数组的时候,合并的位和数组大小作为数据类型的一部分必须在变量名前面指定。合并数组大小定义的格式必须是[msb,lsb],而不是[size]
2.3动态数组
动态数组在声明时使用空的下标[],数组在最开始时是空的,所以你必须调用new[]操作符来分配空间,同时在方括号中传递数组宽度;
int dyn[],d2[];
dyn = new[5];
d2=dyn;//复制一个动态数组
dyn=new[20](dyn);//分配20个整数值并进行复制
dyn=new[100];
dyn.delete();//删除所有元素
当定宽数组复制给一个动态数组时,sv会调用构造函数new[]来分配空间并复制数值;
只要基本数据类型相同,定宽数组和动态数组之间就可以相互赋值;
动态数组赋值:
在new[ ]中设置动态数组大小时,并不完全需要匹配所赋数组的大小。当初始化动态数组的大小较大时,赋值的常量数组会被截断以匹配;当它较小时,初始化的数组将使用默认值填充以获得指定的大小。如下:
int src[3] = '{2, 3, 4};
int dest1[];
int dest2[];
dest1 = new[2] (src); // dest1中的元素为: {2, 3} ,数组被截断
dest2 = new[4] (src); // dest2中的元素为: {2, 3, 4, 0} ,用默认值0 补齐
2.4队列
队列可以在任何一个地方增加或删除元素,且这类操作的性能上的损失比动态数组小的多;
对队列赋值只有大括号,没有单引号;队列是连续储存的
//对于内存连续储存的数组,赋值不需要使用单引号
//对于内存不连续的数组,赋值需要使用单引号
可以把定宽或动态数组的值复制给队列
|
2.5关联数组
用来保存稀疏矩阵的元素;仿真器可以采用树或哈希表的形式来存放关联数组,会有一定的开销;关联数组采用在方括号中放置数据类型的形式来进行声明;
还可以使用exists()来检查元素是否存在
2.6链表
书中没有展开介绍,作者建议尽量避免使用
2.7数组方法
min(),max()函数能够找出数组中的最小值和最大值;返回值是一个队列不是标量;
unique()返回的是在数组中具有唯一值的队列,即删除掉重复的数值;
Shuffle()是乱序函数
2.8使用typedef创建新的类型
规范用户自定义类型都带后缀_t;
2.9自定义结构体
Struct是一个数据集合;如果想生成带约束的随机数据,那就应该使用类了;
默认的结构体是非组合型的,赋值是要把数值放到带单引号的大括号中;
规范用户自定义结构体都带后缀_s;
合并结构体:typedef struct packed {bit [7:0] r,g,b} pixel_p_s;
2.10创建可容纳不同类型的联合
2.11类型转换
静态转换:此操作不对转换值进行检查;转换时指定目标类型,并需要再转换的表达式前加上单引号
动态转换:$cast( , )
流操作符<<和>>用在赋值表达式的右边,后面带表达式、结构或者数组。流操作符用于把其后的数据打包成一个比特流。操作符>>把数据从左至右变成流,而<<则把数据从右至左变成流。
*数组声明中的下标[256]等同于[0:255]而非[255:0]
2.12枚举类型
enum提供方法来描述抽象变量的合法值范围
枚举数据默认(缺省类型)的存储类型为int型(32位有符号二值逻辑),且数值从0开始递增
枚举类型也可以直接赋初值
enum logic [2:0] {WAITE = 3'b001,LOAD = 3'b010,READY = 3'b100} state_n;
枚举类型是四值逻辑时(logic),直接对枚举值赋值X 、Z也是合法的
如果右侧是枚举类型,可以直接赋值给整型,即int = enum 型式成立
如果右侧是整型,不可以直接赋值给枚举 ,即enum = int 不成立;必须要做类型转换 enum = T’(int);
如果枚举类型没有伴随typedef,那么该枚举类型是一个匿名枚举类型
同do..while实现遍历枚举
枚举类型子程序
2.13常量
Const修饰符 允许在变量声明时对其进行初始化,但不能在过程代码中改变其值;
//const byte colon = “:”;
2.14字符串
string类型可以用来保存长度可变的字符串。单个字符是byte类型。长度为N的字符串中,元素编号从0到N-1;
getc(N)返回位置N上的字节;toupper返回一个所有字符大写的字符串;tolower返回一个小写的字符串;大括号{}用于串接字符串;putc(M,C)字节c写到字符串的M位上;函数substr(start,end)提取出从位置start到end之间的所有字符;
2.15表达式位宽
避免方式A那样由于溢出造成精度受损的情况