SystemVerilog学习笔记1 ---《数据类型》

1. 数据类型

1.1 logic

  • 变量没有声明类型时,默认为logci
  • verilog中有两种基本的数据类型:变量和线网(net)。都为4状态(0、1、X、Z)
  • SystemVerilog中将Verilog中的reg进行了一定改进,使其除了作为一个变量外,还可以被连续赋值、门单元和模块所驱动。任何可以使用了reg和wire的地方都可以使用logic,除了存在多个结构性驱动场景时,例如,对双向总线建模时,应该申明线网类型(例如:wire),不能使用logic。
  • logic为4状态类型。

类型整理表

类型名位宽有无符号状态默认值
wire14Z
reg14X
logic14X
bit120
int3220
byte820
shortint1620
longint6420
integer32432{1‘bX}
time64464{1’bX}
  • 还有 real 型为双状态,双精度浮点数。
  • 相比2状态变量,仿真器通常需要多一倍的空间去存放4状态变量。
  • 有符号的变量,可以通过 unsigned 关键字来声明无符号情况,例如 int unsigned ui;

变量的默认值图
变量的默认值

1.2 4状态和2状态之间转化导致的错误

4状态有X和Z,转化为2状态时,不论转化为了0/1,都不再是原来的X和Z。
下例中DUT为一个异步复位的DFF。
在这里插入图片描述

4状态波形(logic):
在这里插入图片描述
2状态波形(bit):
在这里插入图片描述

2. 定宽数组

2.1 数组的声明

  • verilog声明数组时要求给出数组的上下界
  • SystemVerilog声明定宽数组的时候,可以给出数组的上下界,也可以只给出数组宽度。
//一维数组
int a[0:15];   //16个整数 【0】...【15】
int b[16];     //16个整数 【0】...【15】    只给出数组宽度就是大端模式
int c[15:0];   //16个整数, a和b是一样的,c与其相反

//多维数组
int a[0:7][0:3];
int a[8][4];
a[7][3] = 1;

2.2 数组的初始化

  • 可以直接声明的时候就初始化,或者先声明后初始化
  • 可以只给部分元素初始化赋值
  • 可以指定未赋值元素的初始值
int a[4] = '{0,1,2,3};         //对4个元素分别赋值0-3。 a[0]=0; a[1]=1; a[2]=2; a[3]=3;
int a[4:0] = '{0,1,2,3};       //a[3]=0; a[2]=1; a[1]=2; a[0]=3;
int b[4];
b = '{0,1,2,3};                //先声明,后赋值
b[0:2] = '{0,1,2};             //部分赋值
int c[5] = '{5{8}};            //5个值全赋值为8
int d[5] = '{6,7,default:1};   //{6,7,1,1,1}

3. 合并数组与非合并数组

  • 单比特的变量称为标量,多比特的变量称为向量。

  • 在Verilog和Sverilog中声明数组时,可以在数组变量名前、后声明"维度"。

  • 对于Verilog,声明在变量名前的"维度"叫做"vector width" dimension, 声明在变量名后的"维度"叫做"array" dimensions。

  • 对于Sverilog,声明在变量名前的"维度"叫做 packed array,声明在变量名后的"维度"叫做unpacked array

  • packed array 会将内容存放在一起,而 unpacked array 会随机存储。

    1. 一般SV仿真器在存放数组元素时使用32bit的字边界,所以byte、shortint和int是放在一个字中,而longint则存放在两个字中。
    2. 这里的三个b_unpack的存储地址是随机的,不一定在一起。
    在这里插入图片描述

    1. 这里的5个barray的存储地址是随机的,不一定在一起。
    在这里插入图片描述

3.1 多维数组

bit [3:0] [7:0] array1 [2] [3];
array1 [1][2][3][7] = 0;

在这里插入图片描述

4. 动态数组

  • 定宽数组的大小在编译时就确认了
  • 动态数组的大小在使用时才会确认,可以认为动态数组是一个在运行过程中才会被确认大小的定宽数组

4.1声明与初始化

  • 动态数组声明和赋值分开时,需要先使用new[ ]操作符来分配空间。
int dyn[];            //声明动态数组
dyn = new[5];         //分配5个元素,此时动态数组的宽度为5
dyn = new[20](dyn);   //重新分配20个元素,并将原dyn的值赋给新的dyn
dyn = new[100];       //分配100个元素,原先的值已丢弃(释放)
  • 动态数组声明和赋值一起的时候,就可以不需要new[ ]操作符
int dyn[] = '{0,1,2,3};          //声明动态数组,宽度为4,并赋值如下:dyn[0]=0;dyn[1]=1;dyn[2]=2;dyn[3]=3;

5.队列

5.1 声明与初始化

  • 队列的初始化不需要 '{ },而是 { }
int q[$];
int qq[$] = {1,2,3,3,2,1};   

5.2 队列的特殊函数

  • push_front、push_back、pop_front、pop_back这四个函数只实用于队列,不能用于其他数组
int q2[$] = {1,2};
int q1[$] = {7,8,9};
q1.insert(1, q2);          //q1为{7,1,2,8,9}。在q1的第1位上插入q2  

6. 关联数组

6.1 声明与初始化

  • 关联数组比较类似perl中的hash,python中的 dictionary
  • 关联数组名后为index的类型,关联数组名前为value的类型
  • 关联数组只会给已经赋值的元素分配存储空间,比较适合存储大容量的数组
 bit [63:0] mem[bit [15:0]];    //变量名:mem; index类型: bit[15:0]; 值的类型: bit[63:0]
 bit [3:0] assoc [string];

7. 创建用户自定义类型

  • 关键字为typedef
  • 注意将一个定宽数组定义为一种类型的写法
typedef bit [31:0] uint;    //uint就代表  bit[31:0] 这种类型
uint  aa;                   //等价于 bit[31:0] aa;  aa这个变量的类型就时bit [31:0]

typedef int fixed_array5[5];  //fixed_array5为类型名,代表数组值为int、宽度为5的定宽数组类型
fixed_array5  aa;             //等价于int aa[5];

8. 创建struct

  • 关键字为typedefstructpacked
  • 使用typedef才是在声明一种类型,不然只使用struct那么就只临时申明一个变量
  • 结构中有多个成员,如果加入packed关键字,这些成员会被挨着存储在一起
  • struct packed 被当做一个向量存储,结构体的第一个成员在向量的最左边。向量的最低位是结构体最后一个成员最低位,其位编号为bit 0。(类似小端模式)
  • 默认情况是unpacked的
  • 经常会对结构这个整体进行操作时,建议使用packed
  • 经常操作的是结构中的个体,建议不使用packed
  • 注 意 下 面 代 码 中 包 含 t y p e d e f 和 不 含 t y p e d e f 的 区 别 \color{red}{注意下面代码中包含typedef和不含typedef的区别} typedeftypedef
struct {bit[7:0] r,g,b;} pixel;    //pixel为变量名,是一个结构体变量。
struct packed {bit[7:0] r,g,b;} pixel;

typedef struct {bit[7:0] r,g,b;} pixel_s;         //pixel_s为类型名
pixel_s  pixel ;                                  //pxiel为变量名
pixel = '{8'haa, 8'hbb, 8'hcc}                    //初始化
$display("%x %x %x",pixel.r, pixel.g, pixel.b);   //结构体成员的引用

9.创建Union

  • 关键字为 t y p d e f 、 p a c k e d 、 u n i o n \color{red}{typdef、packed、union} typdefpackedunion
  • 使用方式类似struct
  • 联合体只存储一个元素,但该元素可以有多种表示方法,每种表示方法可以是不同数据类型
  • Union内的成员公用同一存储空间。所以对其中一个成员赋值,其他成员也会相应变化,只是数据类型不同而已
  • 默认情况为unpacked的
  • VCS不支持编译unpacked的 union
  • Packed union members must have same size
    在这里插入图片描述
  • 下图中my_u默认应该是my_u.a
    在这里插入图片描述
  • 注 意 下 面 代 码 中 包 含 t y p e d e f 和 不 含 t y p e d e f 的 区 别 \color{red}{注意下面代码中包含typedef和不含typedef的区别} typedeftypedef
union packed {byte      a;
              bit [7:0] b;} my_u;    //my_u为变量名,是一个union变量。

typedef union packed {byte      a;
                       bit [7:0] b;} tmp_u;    //tmp_u为类型名
tmp_u  my_u ;                                  //my_u为变量名
my_u.b = 8'hff;                    //初始化, my_u.a也变为8’hff,打印出来就是 -1
$display("%0d",my_u.b);            

枚举类型

  • 关键字为 t y p d e f 、 e n u m \color{red}{typdef、enum} typdefenum
  • 使用方式类似struct
  • 枚举类型会自动为列表{…}中的每个名称分配不同的数值,默认从0开始递增,有指定缺省值则为缺省值
  • 有点类似参数的作用,但是意义不大
  • 枚举类型变量无特殊声明默认为int存储,缺省值为0,所对应的 .name()也就是列表中分配数值为0的名称(下例中curr_state 默认为0,curr_state.name()就是IDLE)
//用parameter描述一个状态机的几种状态
parameter IDLE    = 2'd0;
parameter DETECT  = 2'd1;
parameter POLLING = 2'd2;
parameter L0      = 2'd3; 

//用枚举类型来表示
//当curr_state为 0~3 时,curr_state.name() 就分别为 IDLE ...
enum {IDLE, DETECT, POLLING, L0} curr_state;
  • 注 意 下 面 代 码 中 包 含 t y p e d e f 和 不 含 t y p e d e f 的 区 别 \color{red}{注意下面代码中包含typedef和不含typedef的区别} typedeftypedef
enum {IDLE, DETECT, POLLING, L0} curr_state_e;   //curr_state_e 为变量名,是一个enum变量

typedef enum {IDLE, DETECT, POLLING, L0} CURR_STATE_E;  //CURR_STATE_E为类型名
CURR_STATE_E curr_state_e;                              //curr_state_e为变量名       
curr_state_e = 2;
$display("%s", curr_state_e.name());         //打印 POLLING
  • 定义枚举值
enum {INIT, DECODE=2, IDLE} fsmtype_e;    //0:INIT    2:DECODE    3:IDLE
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值