前言
某种事情是不可能重新复原的,只能向前推进……不管什么地方,两人能去哪里就去哪里好了——《国境以南太阳以西》
\;\\\;\\\;
目录
- 前言
- 内建数据类型
- reg和wire和logic
- logic和bit
- 四值和二值类型
- 位宽
- 类型转换
- 隐式转换
- 常见数据类型
- 定宽数组
- 动态数组
- packed数组与unpacked数组
- for与foreach
- 容器
- 队列
- 关联数组
- 结构体
- 枚举
- 不可综合(synthesis)的数据类型
内建数据类型
reg和wire和logic
reg 寄存器,由always块驱动
wire 线网,只能用assign语句赋值
logic sv较verilog新引入的类型,方便验证人员驱动与
连接硬件模块,不用讨论用reg还是wire
四值逻辑
\;\\\;\\\;
logic和bit
logic贴近硬件,bit贴近软件。
logic 0 1 X(不确定,其他正数) Z(高阻,没被驱动)
bit 0 1
\;\\\;\\\;
四值和二值类型
四值逻辑类型(默认为x):
integer (32bit,默认有符号)
logic
reg
wire
time (64bit)
二值逻辑类型(默认为0):
byte (默认有符号)
shortint (默认有符号)
int (默认有符号)
longint (默认有符号)
bit
有符号 的意思是有负数,即二进制格式中第一位为1,那么就是负数。
有无符合可以通过signed、unsigned关键字设置。
\;\\\;\\\;
位宽
- reg、logic、bit只有1位
- byte是8位
- shortint是16位
- int、integer是32位
- longint是64位
\;\\\;\\\;
类型转换
如果左右运算的类型不一致,需要先转换再计算(安全性)。
module yishijun;
//sv语法练习
byte activate=8'b1000_0000;//#8位,有符号
bit [8:0] result;//#9位,无符号
initial begin
//#有符号8位扩展成9位,高位补一:1_1000_0000
result=activate;
$display("@1 result='h%x?",result);//#@1 result='h180?
//#无符号8位扩展成9位,高位补零:0_1000_0000
result=unsigned'(activate);
$display("@2 result='h%x?",result);//#@2 result='h080?
end
endmodule
- unsigned '() 是静态转换,在编译时就能完成检查。
- $cast(dst,src) 是动态转换
\;\\\;\\\;
隐式转换
module yishijun;
logic [3:0] x='b111x;
bit [2:0] y;
initial begin
$display("x='b%b",x); //#x='b111x
y=x;
$display("y='b%b",y); //#y='b110
end
endmodule
- 转换过程是右对齐的,多余位被删除。
- X转化bit时只会为0
\;\\\;\\\;
常见数据类型
定宽数组
默认顺序是从0到N-1
数组赋值的时候禁止在{ }内添加default
//0->4
int a[5]='{4,3,2,1,0};
int b[0:4];
b='{3,4,5,6,7};
b='{5{0}}; //#0 0 0 0 0
//5X3
int a[5][3];
int a[0:4][0:2];
int [0:2] a[0:4];
module yishijun;
int b[5];
initial begin
b='{5{0}};
$display("%p",b);
b[0:2]='{1,0,3};
$display("%p",b);
//#b='{1,0,3,default:-1}; //无论如何都运行不了
//#$display("%p",b);
end
endmodule
\;\\\;\\\;
动态数组
-
动态数组刚声明的时候是空的!
-
=可以做复制
module yishijun;
int a[],b[]; //#声明动态数组
initial begin
//#申请空间
a=new[3];
//#初始化
foreach(a[i])
a[i]=i;
//#复制
b=a;
//#
b[0:2]='{3,2,1};
$display(a[0],a[1],a[2]);//# 0 1 2
$display(b[0],b[1],b[2]);//# 3 2 1
//#申请并复制
a=new[2](a);
$display(a[0],a[1]);//# 0 1
//#删除
a.delete();
end
endmodule
module yishijun;
initial begin
int a[]='{1,2,3,4,5};
int b[]=a;
a=new[3];//#原本的空间'{1,2,3,4,5}消失了,b复制的数据放在b申请的空间内
foreach(a[i])
a[i]=i;
$display(a[0],a[1],a[2]); //# 0 1 2
$display(b[0],b[1],b[2],b[3],b[4]); //# 1 2 3 4 5
end
endmodule
\;\\\;\\\;
packed数组与unpacked数组
如果总线为16位,那么16bit=1word
如果总线为24位,那么24bit=1word
如果总线为32位,那么32bit=1word
如果总线为64位,那么64bit=1word
logic a_pack[3][8]; //行3,列8,连续24X2=48位=2word
logic [2:0][7:0] a1_pack; //行3,列8,连续24X2=48位=2word
logic [7:0] b_unpack[3]; //行3,列8,但是每行之间不连续,单行8X2=16位 -> 1word,3行3个word
\;\\\;\\\;
for与foreach
module yishijun;
initial begin
bit [31:0] a[5],b[5];
for(int i=0;i<$size(a);i++)
a[i]=i;
//#不要end
$display(a[0],a[1],a[2],a[3],a[4]);
//# 0 1 2 3 4
foreach(b[j])
b[j]=a[j] * 2;
//#不要end
$display(b[0],b[1],b[2],b[3],b[4]);
//# 0 2 4 6 8
end
endmodule
\;\\\;\\\;
容器
队列
- 用[$]声明队列
module yishijun;
int j=1;
//#队列不用'{}
int a[$]={3,4};
int b[$]={0,2,5};
int c[$];
initial begin
b.insert(1,j); //0 1 2 5
//b.insert(3,a); //不能把队列插入队列
b.delete(0); //1 2 5
$display(b); //1 2 5
$display(b.size);//3
b.push_front(99);
b.push_back(-99);
$display(b); //99 1 2 5 -99
b.pop_front();
b.pop_back();
$display(b); //1 2 5
//队列复制,不能在用的时候定义,要在开头定义
c=b;
b={a[0:1],b[1:$]}; //正确的队列插入
$display(c); //1 2 5
foreach(b[i])
$display(b[i]);
//3
//4
//2
//5
$display("last element is %p",b[$]); //last element is 5
$display("sum of b is %p",b.sum); //sum of b is 14
$display("product of b's elements is %p",b.product); //product of b's elements is 120
$display("max of b is %p",b.max); //max of b is '{5}
$display("min of b is %p",b.min); //min of b is '{2}
$display("unique elements of b was %p",b.unique); //unique elements of b was '{2,3,4,5}
b.reverse(); //颠倒
$display(b);
//5 2 4 3
b.sort(); //排序小到大
$display(b);
//2 3 4 5
b.rsort(); //排序大到小
$display(b);
//5 4 3 2
b.shuffle(); //重新打乱
$display(b);
//4 5 2 3
c.delete();
b.delete();
a.delete();
end
endmodule
\;\\\;\\\;
关联数组
用来保存稀疏矩阵的元素,即只为实际写入的元素分配空间;这种方法所需的内存比定宽或动态数组所占用的小
类似哈希表
module chertanis;
initial begin
bit [63:0] arr[int] , key=1;
//初始化稀疏分布的元素
repeat (64) begin
arr[key]=key;
key=key<<1; //X2
end
//打印看看
foreach (arr[i])
$display("arr[%h]=%h",i,arr[i]);
if(arr.first(key)) begin //first
do
$display("arr[%h]=%h",key,arr[key]);
while(arr.next(key)); //next
end
//删除第一个元素
arr.first(key);//first
arr.delete(key);//delete
end
endmodule
# arr[80000000]=0000000080000000
# arr[00000000]=8000000000000000
# arr[00000001]=0000000000000001
# arr[00000002]=0000000000000002
# arr[00000004]=0000000000000004
# arr[00000008]=0000000000000008
# arr[00000010]=0000000000000010
# arr[00000020]=0000000000000020
# arr[00000040]=0000000000000040
# arr[00000080]=0000000000000080
# arr[00000100]=0000000000000100
# arr[00000200]=0000000000000200
# arr[00000400]=0000000000000400
# arr[00000800]=0000000000000800
# arr[00001000]=0000000000001000
# arr[00002000]=0000000000002000
# arr[00004000]=0000000000004000
# arr[00008000]=0000000000008000
# arr[00010000]=0000000000010000
# arr[00020000]=0000000000020000
# arr[00040000]=0000000000040000
# arr[00080000]=0000000000080000
# arr[00100000]=0000000000100000
# arr[00200000]=0000000000200000
# arr[00400000]=0000000000400000
# arr[00800000]=0000000000800000
# arr[01000000]=0000000001000000
# arr[02000000]=0000000002000000
# arr[04000000]=0000000004000000
# arr[08000000]=0000000008000000
# arr[10000000]=0000000010000000
# arr[20000000]=0000000020000000
# arr[40000000]=0000000040000000
# arr[0000000080000000]=0000000080000000
# arr[0000000000000000]=8000000000000000
# arr[0000000000000001]=0000000000000001
# arr[0000000000000002]=0000000000000002
# arr[0000000000000004]=0000000000000004
# arr[0000000000000008]=0000000000000008
# arr[0000000000000010]=0000000000000010
# arr[0000000000000020]=0000000000000020
# arr[0000000000000040]=0000000000000040
# arr[0000000000000080]=0000000000000080
# arr[0000000000000100]=0000000000000100
# arr[0000000000000200]=0000000000000200
# arr[0000000000000400]=0000000000000400
# arr[0000000000000800]=0000000000000800
# arr[0000000000001000]=0000000000001000
# arr[0000000000002000]=0000000000002000
# arr[0000000000004000]=0000000000004000
# arr[0000000000008000]=0000000000008000
# arr[0000000000010000]=0000000000010000
# arr[0000000000020000]=0000000000020000
# arr[0000000000040000]=0000000000040000
# arr[0000000000080000]=0000000000080000
# arr[0000000000100000]=0000000000100000
# arr[0000000000200000]=0000000000200000
# arr[0000000000400000]=0000000000400000
# arr[0000000000800000]=0000000000800000
# arr[0000000001000000]=0000000001000000
# arr[0000000002000000]=0000000002000000
# arr[0000000004000000]=0000000004000000
# arr[0000000008000000]=0000000008000000
# arr[0000000010000000]=0000000010000000
# arr[0000000020000000]=0000000020000000
# arr[0000000040000000]=0000000040000000
\;\\\;\\\;
结构体
struct只是一个数据的集合
module chertanis;
initial begin
//#struct { bit [7:0] r, g,b;}pixel;
//#简化结构体的变量声明
typedef struct { bit [7:0] r,g,b;}pixel2;
pixel2 a = '{'h10,'h10,'h10};
$display(a.r,a.g,a.b); // 16 16 16
end
endmodule
\;\\\;\\\;
枚举
module chertanis;
initial begin
typedef enum {INIT,DECODE,IDLE} state_t;
state_t a,b;
case (a)
INIT: b = INIT;
IDLE: b=DECODE;
default: b=IDLE;
endcase
//#打印状态名
$display("state is %s",b.name()); //# state is INIT
end
endmodule
\;\\\;\\\;
不可综合(synthesis)的数据类型
- real :双精度浮点double
- shortreal:单精度浮点float
- time:具有timeunit和timeprecision属性的64位无符号4态变量
- realtime:和real一样
- string:可存储8位ASCII字符字符串的字节类型的动态大小数组(字符串char数组)
\;
- event:存储仿真同步对象句柄的指针变量
- class handle:存储类对象句柄的指针变量(声明类型是类的名称,而不是关键字类)
- chandle:一个指针变量,用于存储从SystemVerilog直接编程接口(DPI,Direct Programming Interface)传递到仿真中的指针
- virtual interface: 存储接口端口句柄的指针变量(interface关键字是可选的)
\;\\\;\\\;