Systemverilog笔记 数据类型

第二章 数据类型

1.内建数据类型

1.1 logic类型

​ 原本的verilog代码中,需要分辨reg以及wire两种类型。在sv中,新加入了logic类型(逻辑类型)。

logic类型既可以代替reg,也可以代替wire。但是logic不能有多个结构性的驱动,所以在对双向总线建模时,不能使用logic,而是应该使用wire类型

在代码中一律使用logic,这样当一个信号被多次驱动就会编译报错。如果你知道该信号确实需要被多次驱动,可以直接使用wire

1.2 双状态数据类型

双状态(0,1)bit(单比特),byte(8位有符号整数),int(32位有符号整数),shortint(16位有符号整数),longint(64位有符号整数),real(双精度浮点数)
四状态(0,1,x,z)integer(32位有符号整数),time(64位无符号整数),logic,wire,reg

使用双状态数据,如果出现x或者z,它会被默认转换为0或者装换为1,可以使用指令$isunknown(iport)在任意位出现x或者z时候直接返回为1

2.定宽数组

2.1定宽数组的声明以及初始化

一维数组

int array[0:15]int array[16]等价,都是索引从0到15的一维数组。

多维数组

int array[0:7][0:3]和int array[8][4] 等价,都是8行4列的数组。

越界地址访问的默认缺省值
四状态(logic)X(未知态)
双状态(int ,bit)0
wire没有被驱动Z(高阻态)

2.2合并数组和非合并数组

合并数组合并数组同时存在同一块内存中,有利于数组和标量进行转换,也有利于直接将合并数组做为@操作符中的敏感信号。
非合并数组非合并数组不是放在同一块内存空间中,有利于分散存放,会造成空间的浪费
//合并数组的定义方法,数组大小必须为[msb:lsb]而不是[size],行列都必须在数组名之前定义
int [3:0][7:0] a; 
a=32'h1111_1111; //可以直接对合并数组赋值

//非合并数组的定义方法,一般将行定义在等号右边,列定义在数组名之前
int [7:0] a[3:0];

//直接将合并数组转换
int [31:0] b=a; 

//注意分辨什么情况下是合并数组
int [3:0][7:0] a[3]; //此时a是一个包括3个合并数组的非合并数组

在这里插入图片描述

2.3常量数组

//初始化数组的几种方法

//(1)定义时直接赋值
int a[5]='{1,2,3,4,5};

//(2)为部分元素赋值
a[0:2]='{5,6,7};

//(3)拼接赋值,类似verilog中的字符拼接
int a[5]='{5{8}};

//(4)缺省赋值,使用default默认赋值剩余元素,类似python的语法
int a[5]='{1,2,default:-1};

2.4数组循环

一维遍历
//for循环
initial begin
int a[5]='{5{8}};
    for(int i=0;i<$size(a);i++)        //其中的$size()输出为数组的长度,类似于C++中的.size().
    a[i]=a[i]+1;

//foreach循环,类似于在C++中直接使用   for(auto i:a)遍历
foreach(a[j])
    a[j]=a[j]+1;
end
二维遍历
initial begin
int a[2][2]='{'{0,1},'{2,3}};
//foreach一次循环,这里必须写成a[i,j]而不是a[i][j]
foreach(a[i,j])
    a[i][j]=a[i][j]+1;
    
//foreach两次循环,分别对行列进行遍历的过程
foreach(a[i]) begin   //行
    foreach(a[,j]) begin  //列
         a[i][j]=a[i][j]+1;
    end
end
    
end

foreach相当于与for对应:

int a[5] 类比于int a[0:4] foreach(a[i]) 等同于 for(int i=0;i<=4;i++)

int a[6:2] foreach(a[i]) 等同于 for(int i=6;i>=2;i–)

3.动态数组

类似java生成动态数组的方式,sv也可以通过new操作来定义数组的大小。

//初始化数组的几种方法
//定义动态数组
int a[],b[];

//通过new来定义数组的大小
a=new[5];

//赋值动态数组
b=a;
 
a=new[100](a);  //分配100个新的数值,原来的前面5个值也被复制过来,但是原有的5个值所占的空间被释放
a=new[100];     //分配100个新的数值,原来的前面5个值也被覆盖掉,但是原有的5个值所占的空间被释放

//删除a的所有元素
a.delete();

当元素数目相同时,动态数组的值可以被赋给定宽数组;

当把定宽数组赋给动态数组,动态数组会默认通过new操作来获得所需要的操作空间。

4.队列

队列的特点是先入先出。
队列使用 $ 符号,并且队列的编号从0开始到 $ 结束。

//队列的创建
a[$]={1,2,3};  //队列不用',这可能是因为队列定义的空间是在一个块内的
b[$]={1,2};

//队列的插入insert和删除delete
a.insert(1,4);  //{1,4,2,3}在第1个位置上插入2 
a.insert(0,b);	 //{1,2,1,4,2,3}在第0个位置上插入b 
a.delete(0);     //{2,1,4,2,3}删除第0个位置的元素

//队列在对头和结尾增加和删除
a.push_front(6); //{6,2,1,4,2,3}
a.push_back(7); //{6,2,1,4,2,3,7}
i = a.pop_front(); //{2,1,4,2,3,7} i=6
i = a.pop_back(); //{2,1,4,2,3} i=7

a[$]={0,1,2};

[$:2] 在左边表示最小值0

[0:$]在右边表示最大值2

[$]默认取为[2]

5.关联数组

关联数组其实就是哈希表的一种实现方式。

//关联数组的定义
bit [63:0] assoc[bit[63:0]],idx=1;

//初始化
repeat(32) begin
	assoc[idx]=idx;
	idx=idx<<1;
end

//foreach遍历
foreach(assoc[idx])
	$display("assoc[%h]=%h",i,assoc[i]);
	
//函数first和next遍历
if(assoc.fisrt(idx))
begin
	do
		$display("assoc[%h]=%h",i,assoc[i]);
    while(assoc.next(idx));
end

//删除第一个元素
assoc.first(idx);
assoc.delete(idx);

string也能进行关联数组,可以用exist()来判断元素是否存在,对于双状态不存在会返回0,四状态不存在会返回X。(例2.2)

6.数组的方法

sum

//在用bit时候,求和也会变成1位的结果
bit a[10];
int total;

initial begin
foreach(a[i])
	a[i]=i;

//打印单比特和
$display("a.sum=%0d",on.sum);  //on.sum=1

//打印32比特和
$display("a.sum=%0d",on.sum+32’d0);  //on.sum=5

//打印32比特和
total = on.sum
$display("a.sum=%0d",total);  //total=5

$urandom_range( $ size(array)-1)

$urandom_range(array.size()-1)

随机选取1个元素对应的索引

$urandom 随机数

min最小的元素

max最大的元素

unique返回具有唯一值的队列

find

int a = '{1,2,3,4,5},b[$];

b=a.find with(item>3); //返回大于3的元素的队列 {4,5}

b=a.find_index with(item>3); //返回大于3的元素的索引队列 {3,4}
b=a.find_first with(item>3); //返回大于3的第一个元素的队列 {4}
b=a.find_first_index with(item==3); //返回等于3的元素的索引队列 {2}
b=a.find_last with(item>3); //返回大于3的最后元素的队列 {5}
b=a.find_last_index with(item>3); //返回大于3的最后元素的索引队列 {4}

//以下四条语句都是等价的
b=a.find_fisrt with(item==3);
b=a.find_fisrt() with(item==3);
b=a.find_fisrt(item) with(item==3);
b=a.find_fisrt(x) with(x==3);

sort排序

int a[] = '{1,3,2,4};
a.reverse();  //{4,2,3,1}
a.sort();     //{1,2,3,4}
a.rsort();    //{4,3,2,1}
a.shuffle();  //混排序列中的元素

7.typedef创建新的类型

typedef bit [31:0] uint;

typedef int unsigned uint;

定义32位双状态无符号数

8.struct

//创建新类型结构体
struct {
	bit [7:0] r,g,b;
}pixel;

//创建一个结构体类型
typedef struct{
	bit[7:0] r,g,b;
}pixel_s;

//用自己定义的结构体类型来创建一个对象,并对结构进行初始化
pixel_s my_pixel=  ‘{8’b0,8'b1,8'b0};

//为了节约空间,可以将定义的结构合并,这样只需要用3个字节就能解决问题
typedef struct packed{
	bit[7:0] r,g,b;
}pixel_s;

union联合体,可以把不同的元素放置在同一个位置上

typedef union{
	int i;
	real f;
} num_u;

num_u un;
un.f=0.0; // 将数值设置为浮点类型

9.类型转换

//静态转换
int a;
real b;
a=int'(10.0);
b=real'(42);

//动态转换
int a;
real b;
$cast(a,b);  //把b转化为a,将右边强制转化为左边

流操作能够将字数组转换为字节数组,还能将结构体转换为字节数组的作用。

//流操作符号  >>  <<
bit[7:0] j[4]='{8'ha,8'hb,8'hc,8'hd};

int h;
h={>>{j}};      //0a0b0c0d  将数组打包为整形
h={<<{j}};      //b030d050  位倒序
h={<<byte{j}};  //0d0c0b0a  字节倒序

bit[7:0] g[4];
g={<<byte{j}};  //0d,0c,0b,0a  拆分为数组

bit[7:0] b;
b={<<{8'b0011_0101}};   //1010_1100 位倒序
b={<<4{8'b0011_0101}};  //0101_0011 4位倒序

10.枚举类型

//定义枚举结构体
typedef enum{INT,DECODE,IDLE} fs;
fs a,b;

initial begin
	case(a)                               //case语句来赋值b的状态
		INT: b=INT;
		IDLE: b=IDLE;
		default: b=DECODE;
	endcase
	$display("Next state is %s",b.name());  //打印b的state
end

//默认缺省从0开始,就是确保第一个的默认值为0
typedef enum{INT=0,DECODE,IDLE} fs;  //True
typedef enum{INT,DECODE=2,IDLE} fs;  //True
typedef enum{INT=1,DECODE,IDLE} fs;  //False


//遍历枚举,先设为first,再遍历一圈到first时候来结束,用do…while
typedef enum{INT,DECODE,IDLE} fs;
fs a;
a=a.first;
do
	begin
	$display("state = %0d /  %s",a,a.name); //a默认值为数字,a.name才是对应的state
	a=a.next;
	end
while(a!=a.first)

//强制类型转换
typedef enum{INT,DECODE,IDLE} fs;
fs a;
int b;
b=a;
b++;

if(!$cast(a,b))                  //如果$cast成功会返回1,失败则返回0
    $display("Cast change is failed when b=%0d",b);

11.字符串

string s;

initial begin
s="IEEE";
$display(s.getc(0));   //get char 得到I,打印出来为73
$display(s.tolower());   //“ieee”

s.putc(s.len()-1,"-");  //"IEE-"
s={s,"11"};             //"IEE-11"
$display(s.substr(2,5)); //"E-11"
end

用字符串来打印日志有关的信息

task my_log(string message)
	$display("@%0t : %s ",$time,message);
	
initial begin	
mylog($psprintf("%s %5d",s,42));  
//$psprintf是临时字符串,返回一个格式化字符串,可以直接传递给其他子程序
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jun_luo_yu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值