目录
一、逻辑数值
二、变量转换
显示转换
隐式转换(不需要进行转换操作)
三、定宽数组
数组声明
多维数组声明
初始化和赋值
非合并数组
合并数组
基本数组操作
for和foreach
赋值:=
比较:==,!=
四、动态数组
数组定位
方法定位
with(指示sv如何搜索)
重复参数声明,意思相同
数组排序
五、队列
利用队列函数
利用队列操作
六、关联数组
七、结构体 struct
八、枚举类型enum
九、字符串
字符串声明string s
一、逻辑数值
- 四值逻辑类型(硬件世界):logic、integer、reg、net-type(例如wire、tri)
- 二值逻辑类型(软件世界):byte、shortint、int、longint、bit
- 有符号类型:byte、shortint、int、longint、integer
- 无符号类型:bit、logic、integer、reg、net-type(例如wire、tri)
注意:1.verilog中有寄存器类型reg、线网类型wire;sv侧重验证,并不关切logic对应逻 辑应该被 综合为reg还是wire。
2.net-type(例如wire、tri)只能连续复制,logic可以连续赋值、过程块赋值。
3.在缺省的情况下参数类型是与前一个参数相同的,而第一个参数的缺省类型是单比特输入
4.有符号类型最高位带有符号位,例如:8位有符号数'b1000_0000,打印为-128
二、变量转换
-
显示转换
- 静态转换(编译阶段检查),需要在转换表达式前加上单引号,不会对转换值做检查,转换失败也无从得知。
例如:byte signed_vec = 8’b1000_0000;
A=unsigned'(signed_vec); //将signed_vec转换成无符号数
$display("result_vec = 'h%x",A) //’h080
- 动态转换(仿真阶段检查),$cast(tgt,src)告诉是否成功
-
隐式转换(不需要进行转换操作)
例如:logic[3:0] x_vec = 'b111x;
Bit [2:0] b_vec;
b_vec = x_vec; //隐式转换,结果为’b110
注意:四值逻辑中的x、z转换成二值逻辑中的0。
三、定宽数组
-
数组声明
int A [0:15]; //[0]…[15] verilog中必须给上下界。
int A [16]; //[0]…[15]。
-
多维数组声明
int array [0:7][0:3]; //完整说明
int array [8][4]; //紧凑说明
array[7][3] = 1; //设置最后一个元素值
注意:从越界地址读取数据,那么SV将返回数组元素类型缺省值,例如对于logic返回X,对于int或bit返回0。
-
初始化和赋值
int ascend[4]='{0,1,2,3};
int descend[5];
descend='{4,3,2,1,0}; //先定义再初始化
descend [0:2]='{5,6,7}; //为前三个元素赋值
ascend='{4{8}} //重复操作
descend='{9,8,default:-1}; //{9,8,-1,-1,-1},default定义剩下的元素
int md[2][3]='{'{0,1,2,3},'{3,4,5}}; //定义多维数组
-
非合并数组
bit [7:0]barray[3]; //非合并数组,三行,每一行有一个8bit数据
-
合并数组
声明合并数组时,合并的位和数组大小作为数据类型的一部分必须在变量名前面指定,数组大小定义的格式必须是[msb:lsb],而不是[size].
bit [3:0][7:0]barray; //合并数组,一行,3个字节组成的32bit
bit [3:0][7:0]barray[3]; //合并,3行,3*32bit
barray[0]=lw
barray[0][3]=8'h01;
barray[0][1][6]=1'b1;
nibbles=barray[0]; //复制合并数组的元素值32bit
-
基本数组操作
-
for和foreach
bit[31:0] src[5],dst[5];
for(int i=0;i<$size(src);i++) //$size(src)默认同于$size(src,1)为5,$size(src,2)为32。
src[i]=i;
foreach(dst[j]) //多维数组foreach(md[i,j])
dst[j]=src[j]*2;
-
赋值:=
-
比较:==,!=
注意:绿皮书知识点$display(“src%sdst”,(src==dst)?“==”:“!=”)
四、动态数组
相较于定宽数组类型的宽度编译时就已经确定,动态数组则是在仿真运行时灵活调节数组的大小,因此需要‘[]’声明,并在运行时使用new[]分配空间。
int dyn[],d2[]; //声明动态数组
initial begin
dyn=new[5]; //分配空间
foreach(dyn[i])
dyn[i]=i; //元素初始化
d2=dyn; //复制
d2[0]=5;
$display(dyn[0],d2[0]);
dyn=new[20](dyn); //分配20个空间,并进行复制
dyn=new[100]; //重新赋值100个,旧值消失
dyn.delete(); //也可以用new[0]
end
注意:声明常数数组又不想统计元素个数时,对比定宽数组int dyn[3]='{1,2,3},动态数组
int dyn[]='{1,2,3} SV自动统计元素个数,避免了宽度指定错误的问题。
-
数组定位
-
方法定位
tq=q.min();
tq=d.max();
tq=f.unique(); //唯一值的队列
-
with(指示sv如何搜索)
int d[]='{9,1,8,3,4,4}, tq[$];
tq=d.find with(item>3); //找出大于三的元素
tq=d.find_index with(item>3); //{0,2,4,5}找出大于三元素的位置
tq=d.find_index_first with(item>3); //{0}
int count,d[] = '{9,1,8,3,4,4}
count=d.sum with(item>7) //count值为2,有{9,8}大于7。
-
重复参数声明,意思相同
tq=d.find_first with(item==4);
tq=d.finf_first()with(item==4);
tq=d.finf_first(x)with(x==4);
tq=d.finf_first(item)with(item==4);
-
数组排序
int d[]='{9,1,8,3,4,4};
d.reverse(); //'翻转
d.sort(); //从小到大
d.rsort(); //从大到小
d.shuffle(); //随机放
五、队列
结合了链表和数组的优点,可以在任何地方添加和删除元素,并且通过索引对任一元素访问,不像链表去遍历目标元素之前的所有元素,当元素增加到超过原有空间容量时,SV会自动分配更多空间。队列元素编号0到$。
-
利用队列函数
int j=1,q2[$]={3,4},q{$}={0,2,5}; //声明
initial begin
q.insert(1,j); //在2之前插入1
q.insert(3,q2); //在q中插入一个队列
q.delete(1) //删除第1个元素
q.push_front(6); //在队列最前面插入6
q.push_back(8); //在队列最后面插入8
j=q.pop_back(); //取出队列最后面的数并赋值给j
j=q.pop_front(); //取出队列最前面的数并赋值给j
foreach(q[i]) //打印队列
$display(q[i]);
q.delete();
end
-
利用队列操作
int j=1,q2[$]={3,4},q[$]={0,2,5};
initial begin
q={q[0],j,q[1:$]}; //利用队列
q={q[0],q[2:$]);
q={6,q};
j = q[$]; //等同于取最后一个
q=q[0:$-1] //从队伍末尾取出所有数据赋值给q
q={q,8}; //在队伍末尾插入数据
q={}; //删除整个队列
end
注意:$放在范围表达式左边表示最小值,放在右边表示最大值。
六、关联数组
动态数组的限制在于其储存空间在一开始就被固定下来,关联数组可以用来保存稀疏矩阵的元素,该数组只为实际写入的元素分配空间。
initial begin
bit[63:0] assoc[bit[63:0]], idx=1; //索引类型
repeat(64)begin //对稀疏分布的元素初始化
assoc[idx]=idx;
idx=idx<<1;
end
foreach(assoc[i]) //使用foreach遍历数组,i不一定是1,2,4,8 顺序可能会变
七、结构体 struct
Struct功能较少,只是一个数据的集合,通常适用的方式是将若干相关的变量组合到一个struct结构定义中,伴随typedef可以用来创建新的类型,并利用新类型声明更多变量。
typedef struct {int a;byte b;shortint c;int d;}my_struct_s; //创建有四个成员变量的结构体
my_struct_s st; //声明变量
st='{32'haaa_aaaad, 8'hbb,16'hcccc, 32'hdddd_dddd}; //结构体赋值
my_struct_s st='{32'haaa_aaaad, 8'hbb,16'hcccc, 32'hdddd_dddd}; //声明变量并结构体赋值
注意:数据非连续存放用“单引号”
八、枚举类型enum
规范的操作码和指令例如ADD、WRITE等有利于代码的编写和维护,它比直接使用’h01可读性和维护性更好。枚举类型enum经常和typedef搭配使用,便于用户自定义枚举类型的共享使用。枚举类型可以自动为列表中的每个名称分配不同的数值。
Typedef enum {INIT,DECODE,IDLE} fsmstate_e; //创建代表0,1,2的数据类型
fsmstate_e pastate,nstate; //声明自定义类型变量
initial begin
case(pastate)
IDLE: nstate=INIT; //数据赋值
INIT: nstate =DECODE;
default:nstate= IDLE;
endcase
end
注意: INIT=enum 右侧是枚举类型,可以赋值给整型,enum=T’(INT) 右侧是整型,要先转化成枚举类型,因为例如上面的fsmstate_e,当整数为3,4,5等无法赋值给nstate,编译失败。
九、字符串
字符串声明string s
string s; //声明
initial begin
s="IEEE "; //初始化
$display(s.getc(0)); //I
s.putc(s.len()-1,"-"); //将最后一个元素“一个空格”变成“-” //字符串用len()表示长度
s={s,"P1800"}; //链接字符 IEEE-P1800
$display(s.substr(2,5)); //显示EE-P
end
task my_log(string message); //传入一个字符串变量
$display("@%0t:%s",$time,message);文章来源:https://www.toymoban.com/news/detail-411125.html
endtask文章来源地址https://www.toymoban.com/news/detail-411125.html
到了这里,关于SV 逻辑数值、数组、队列、结构体、字符串的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!