转载请标明出处

数组、结构体和联合体

1. 结构体(struct)

1.1. 结构体声明

结构体默认是变量,也可以声明为线网

var struct { // 通过var进行结构体变量声明

logic [31:0] a, b;

logic [ 7:0] opcode;} Instruction_Word_var;

wire struct { //结构体线网声明,定义为线网类型时,结构体的所有成员必须都是四态类型的 logic [31:0] a, b;

logic [ 7:0] opcode;} Instruction_Word_net;

Point:结构体内不能使用线网类型。多个线网可以用SV接口打包成一个组。

Eg:自定义结构体

typedef struct { //结构体定义,不分配存储器

logic [31:0] a, b;

logic [ 7:0] opcode;

logic [23:0] address;

} instruction_word_t;

instruction_word_t IW; // 结构体实例化时分配存储区

自定义结构体可以在模块,接口或者包中定义。

1.2. 结构体赋值

u 使用值列表 初始化

结构体在实例化的时候可以对其成员初始化using ’{<value>}

instruction_word_t IW = ’{100, 3, 8’hFF, 0};   //赋值a=100 b=3 opcode=FF address=0

u 结构体成员赋值

IW.a = 100;   //引用结构体成员的名称对成员进行赋值

u 将结构体表达式赋给结构体

if (!resetN) IW = ’{100, 5, 8’hFF, 0};    //同初始化的时候类似,但这是在过程块中进行的

u 结构体表达式的默认值

IW = ’{ real:1.0, default:0, r1:3.1415 };//r1=3.1415 其他real成员=1.0 其他成员=0 (precedence:显性成员名赋值>指定数据类型赋值>default)

1.3. 压缩(packed)和非压缩(unpacked)结构体(均可综合)

默认情况下,结构体是非压缩的。结构体成员是独立的变量或常量。

使用packed显示的声明一个压缩结构体。压缩结构体按照指定的顺序以相邻的位来存储结构体成员。压缩结构体被当做一个向量存储,结构体的第一个成员在向量的最左边。向量的最低位是结构体最后一个成员最低位,其位编号为bit 0。如图所示(类似小端模式):

struct packed {

logic valid; logic [ 7:0] tag; logic [31:0] data;

} data_word;

packed structure的成员可以通过成员名引用(<struct_name>.<mem_name>)也可以使用结构体向量的相应位来引用(<struct_name>[M:N])。

压缩结构体只能包含整数。

(题外话:real和shortreal分别对应C语言的双精度和单精度,不可被综合,但是在抽象硬件模型和tb中有用,因此不算做整数范畴)

压缩结构体可被看作是向量来操作。(除了’{}赋值操作是当做unpacked以外)

1.4. 通过端口传递结构体

要想使用结构体类型的端口,要先使用typedef定义为用户自定义数据类型的结构体。

Unpacked struct通过模块port传递时,端口两边连接必须是同一种类型的结构体。

在两个不同模块声明的匿名结构体即便成员类型相同也不能看作同一类型结构体。

1.5. 将结构体作为自变量传递至task和function

要想传递结构体类型的自变量,要先使用typedef定义为用户自定义数据类型的结构体。

同4.1.4,要相同类型结构体才能作为自变量传递给task和function

2. 联合体(union)

联合体只存储一个元素,但该元素可以有多种表示方法,每种表示方法可以是不同数据类型

Union声明及成员引用方法同struct,关键词为union

Union内的成员公用同一存储空间。所以对其中一个成员赋值,其他成员也会相应变化,只是数据类型不同而已

2.1. 非压缩联合体(unpacked unions)  (不可综合)

非压缩联合体可以包含任意变量类型,包括real,非压缩结构体和非压缩数组。

2.2. 标签联合体(tagged unions)(没懂啥应用价值P130)

相当于在使用时要注意读值和上次存储都是针对同一个union member(有啥用)

2.3. 压缩联合体(packed unions)(可综合)

压缩联合体中每个成员位数相同,只存储整数值。

(一般用于存signed,unsigned两种类型,比如,当需要存signed类型时,给ele0赋值,需要存unsigned类型时,给ele1赋值)

typedef struct packed {

logic [15:0] source_address;

logic [15:0] destination_address;

logic [23:0] data;

logic [ 7:0] opcode;

} data_packet_t;

union packed {

data_packet_t packet; //压缩结构体

logic [7:0][7:0] bytes; // 压缩数组

} dreg;

该例中,值可以使用byte格式的数组写入,然后以data_packet格式读出相同的值(共享空间)

3. 数组(Arrays)(可综合)

3.1. 非压缩数组(unpacked arrays)

l Verilog数组

变量及线网均可以用于数组。

声明:<data_type> <vector_size> <array_name> <array_dimensions>

verilog一次只能访问数组的一个元素。

数组中各个元素存储位置相互独立

需指定起始地址及结束地址 eg.int array [64:83]; //地址从64-83的Verilog数组

l SV数组

增加event数据类型及所有SV数据类型

SV可以引用整个非压缩数组以及一段元素(复制非压缩数组时”=”左右需同样结构及类型)

无需指定起始位置及结束位置,只需指定维度大小

eg.logic [31:0] data [1024];          //is equivalent to logic [31:0] data [0:1023];

3.2. 压缩数组(packed arrays)

l Verilog向量是一维压缩数组

l SV允许多维压缩数组,压缩数组作为邻近元素存储

Eg: logic [3:0][7:0] data; // 2-D packed array包含4个8位的子数组

l 引用压缩数组

logic [3:0][7:0] data; // 2-D packed array 4个8位数组

wire [31:0] out = data; // whole array

wire sign = data[3][7]; // 一位

wire [3:0] nib = data [0][3:0]; // 一部分

byte high_byte;

assign high_byte = data[3]; // 8-bit 宽的一段

logic [15:0] word;

assign word = data[1:0]; // 2段

3.3. 使用压缩或非压缩数组

l 非压缩数组用于模拟存储器以及抽象数据类型如RAM,ROM,通常每次只访问一个元素

l 压缩数组创建有子域的变量,可以访问子段

3.4. 声明时对数组进行初始化

l 压缩数组初始化

logic [3:0][7:0] a = 32’h0; //向量赋值

logic [3:0][7:0] b = {16’hz,16’h0}; //常数的拼接

logic [3:0][7:0] c = {16{2’b01}}; //常数的复制(16个01)

l 非压缩数组初始化

n Verilog:int d [0:1][0:3] = { {7,3,0,5}, {2,0,1,6} };  //d[0][0]=7  d[1][3]=6  不用’

n SV:int e [0:1][0:3] = ’{ 2{7,3,0,5} }; //’{’{},’{}} or ’{n{}}

l 非压缩数组可以被初始化有一个默认值(default)

int a1 [0:7][0:1023] = ’{default:8’h55};

3.5. 数组赋值

给非压缩数组赋值的时候要以元素为单位赋值,给压缩数组赋值的时候当它是个向量就行

Eg:a[3] = '{'hF, 'hA, 'hC, 'hE};//非压缩数组  a[0] = 16’hFACE;  //压缩数组

3.6. 数组复制

压缩数组可以直接赋值给压缩数组,同理非压缩数组可以直接赋值给非压缩数组。

压缩数组和非压缩数组的互相赋值要使用位流转换的方式

3.7. 使用位流转换复制数组和结构体(静态转换操作符  )

位流转换使用SV静态转换操作符,转换需要至少目标数组是用typedef表示的自定义类型

typedef int data_t [3:0][7:0]; // unpacked type

data_t a; // unpacked array

int b [1:0][3:0][3:0]; // unpacked array

a = data_t(b); // 将非压缩数组赋给不同结构的非压缩数组

转换操作通过将源数组或结构体转换成临时向量表达式(位流),然后将位组赋给目标数组的各个元素来实现。

3.8. 由数组构成的数组

Eg: wire [3:0][7:0] data [0:1023];

//由32位元素组成的非压缩数组,每个元素是由4个字节组成的压缩数组

非压缩数组的索引先于压缩数组的索引,顺序如图(unpacked→packed,left→right)

3.9. 数组中使用用户自定义类型,结构体和联合体

数组可以包含用户自定义类型,结构体和联合体(联合体必须是压缩的)

3.10. 数组可以通过端口及任务和函数传送

4. foreach数组循环结构体

foreach循环用来对一维或多维数组中的元素进行迭代,而不必指定数组每个维度的宽度

int sum [1:8] [1:3];

foreach ( sum[i,j] ) //自变量是数组名,[ ]中用,隔开循环变量列表。

sum[i][j] = i + j; //对数组初始化

外循环对应低基数索引。上例中,最外层循环对i进行索引,最内层循环对j进行迭代

循环变量可缺省,循环变量为空时,循环不会对数组的该维度进行迭代

5. 用于数组查询的系统函数(array定宽时可综合)

$dimensions(array_name) //返回数组的维数

$left(array_name, dimension) //返回指定维度的最高有效位(MSB)

从最左端的非压缩维度开始,从左到右递增;然后递增到压缩维度,从左到右递增

Eg. logic [1:2][7:0] word [0:3][4:1];

$left(word,1) will return 0

$left(word,2) will return 4

$left(word,3) will return 1

$left(word,4) will return 7

$right(array_name, dimension) //返回指定维度的最低有效位(LSB)

$low(array_name, dimension) //返回指定维度的最低位数(上例中dimension1-4分别 对应0,1,1,0)

$high(array_name, dimension) //返回指定维度的最高位数

$size(array_name, dimension) //返回指定维度元素的总个数(high-low+1)

$increment(array_name, dimension) //对于指定的维度,如果$left>=$right,返回1,否则-1

$bit(expression) //返回表达式的位数

Eg. bit [63:0] a; logic [63:0] b;

$bits(a) returns 64;$bits(b) returns 64;道理我都懂,but why $bits(a+b) returns 128?

Systemverilog for design 笔记(四)的更多相关文章

  1. Systemverilog for design 笔记(一)

    转载请标明出处 一.     System Verilog 声明的位置 1.       包(packages) Verilog要求局部声明: variables, nets, tasks and f ...

  2. Systemverilog for design 笔记(七)

    转载请标明出处 第一章 接口(interface) 1.1.    接口的概念 接口允许许多信号合成一组由一个端口表示. 1.2.    接口声明 //接口定义 Interface main_bus ...

  3. Systemverilog for design 笔记(六)

    转载请标明出处 第一章 有限状态机建模(FSM,finite state machine) 1.1.    使用枚举类型建立状态机模型 l  三过程块建模风格:三个过程块分别实现: a.状态转换(al ...

  4. Systemverilog for design 笔记(五)

    转载请标明出处 第一章 System Verilog过程块.任务和函数 1.1.    verilog通用目的always过程块(procedural block)(可综合) always过程块的综合 ...

  5. Systemverilog for design 笔记(三)

    转载请标明出处 用户自定义和枚举数据类型 1. 用户自定义类型(typedef) 局部typedef定义:只用于设计的特定部分时,typedef的定义可在module或interface中 共享typ ...

  6. SystemVerilog for design 笔记(二)

    转载请标明出处 1. System Verilog文本值和数据类型 1.1. 增强的文本值赋值 相对于verilog,SV在文本值赋值时可以1.无需指定进制    2.赋值可以是逻辑1 用法: reg ...

  7. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  8. 《MFC游戏开发》笔记四 键盘响应和鼠标响应:让人物动起来

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9327377 作者:七十一雾央 新浪微博:http:// ...

  9. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

随机推荐

  1. springboot集成实现秒杀

    springboot集成开发实现商场秒杀 加入主要依赖 <dependency> <groupId>org.springframework.boot</groupId&g ...

  2. jenkins和hudson

    自动化构建:Jenkins起源于Hudson.Hudson在商业软件的路上继续前行,而Jenkins则作为开源软件,从hudson分支出来. 因此现在的jenkins和hudson非常类似,但是随着二 ...

  3. 激活windows系统

    1.下载KMS 2.如图所示,双击KMSpico看是否正常运行 3.双击KMSpico正常后出现以下界面 4.点击红色按钮 5.等自动退出就是激活成功,大概半年需要激活一次

  4. eosio 编译与部署

    1. 名词解释 创世节点(BIOS) 用于创建初始区块,加载基础合约,供其它节点同步连接. 矿工节点(BP) 主要用于生产同步区块,计算合约产生的费用归矿工账号所有. 查询节点 不产生区块,同步区块信 ...

  5. NTP网络授时服务器部署及网络时钟同步设置说明

    NTP网络授时服务器部署及网络时钟同步设置说明 NTP网络授时服务器部署及网络时钟同步设置说明  本文由安徽京准科技提供@请勿转载. 一.前言 1.NTP简介 NTP是网络时间协议(Network T ...

  6. 普及C组第一题(8.1)

    1999. [2015.8.6普及组模拟赛]Wexley接苹果(apple) 题目: Wexley最近发现了一个古老的屏幕游戏.游戏的屏幕被划分成n列.在屏幕的底端,有一个宽为m列的篮子(m<n ...

  7. Ubuntu 国内安装 kubernetes

    由于墙的原因,国内要安装 kubernetes 非常的麻烦,因此只要解决这个问题,就可以顺利安装 kubernetes 的 三个官法工具 kubelet.kubeadm.kubectl. 安装环境: ...

  8. 1011 World Cup Betting

    Title:1011 World Cup Betting 1. 注意点 比较简单,没有注意点 2. python3代码 def func(output): max = 0 index = -1 lin ...

  9. makefile的书写

    工作中会遇到makefile的书写,有必要做一些笔记.尽管网上有”万能模板“可以使用,但我觉得还是有必要从最基础的写起. 平常在windows下开发,不知道自己用过makefile,其实大部分IDE里 ...

  10. Spring的核心api和两种实例化方式

    一.spring的核心api Spring有如下的核心api BeanFactory :这是一个工厂,用于生成任意bean.采取延迟加载,第一次getBean时才会初始化Bean Applicatio ...