【IC验证】systemverilog_数组

systemverilog_数组

一.概述

1.数组的分类

systemverilog中,除了有定长数组外,还扩展了动态数组、队列和关联数组;

2.数组的基本规则

(1)在声明变量时,变量名右侧的维度大于变量名左侧的维度,变量名同一侧的维度从左向右递减;

(2)变量的索引,索引位于变量名右侧,且维度从左导游递减;

(3)systemverilog中,数组的每个元素存储时使用的是32bite字边界,当单个元素超过32位时,就增加到多个32bite字边界;

(4)在sysytemverilog中,存储一bit4值逻辑需要消耗2bit存储空间(四个状态0,1,X,Z);

(5)byte,shortint,int,longint只能声明非组合型数组(存疑)???,bit、logic既可以声明组合型数组和非组合型数组;

二.定长数组

1.定义

在声明时必须明确指定大小(上下界或宽度)的数组。

2.非组合型数组

(1)定义

数组,各元素,独立分配存储空间;

(2)语法

在变量声明时,维度声明在变量名侧;
声明语法

c 复制代码
变量类型 变量名 维度;

初始化及赋值语法

多个元素或整体初始化或赋值时,每一维一个**'{}**

非组合型数组初始化或赋值时,赋的值和被赋值的元素结构必须一致;

c 复制代码
被赋值元素 = 赋的值;

(3)例子

A 例子1:非组合型数组结构及存储空间分配

代码:

c 复制代码
module test_array;
    bit [7:0] a [0:2] = '{1,2,3}; 
    initial begin
        $display("a = %b",a[0]);
    end
endmodule

说明:

声明了3个元素,每个元素(a[0]、a[1]、a[2]各)都会分配32位宽的存储空间,但是只使用了低8位;

B 例子2:非组合型数组的声明初始化及赋值

代码:

c 复制代码
module test_array;
    int b [3:0][2:0];
    int c [1:0][2:0];
    initial begin
        b = '{'{0,1,2},'{3,4,5},'{6,7,8},'{9,10,11}};
        c = '{'{12,13,14},'{15,16,17}};
	    $display("b[1][2] = %0d",b[1][2]);
        b[1][2] = 18;
        $display("b[1][2] = %0d",b[1][2]);
	    b[0] = c[0];
	    $display("b[0][2] = %0d",b[0][2]);
        b[0]= '{19,20,21};
        $display("b[0][2] = %0d",b[0][2]);
    end
endmodule

结果:

(4)特殊点

A非组合型数组,每一个维度指定,可以按照[msb:lsb]的方式,也可以按照[size]的方式;

B非组合型数组的初始化或赋值,可以用'{default:值}的方式,表示将每一个元素都赋值为指定的值;

3.组合型数组

(1)定义

数组,各元素,组合分配地连续的存储空间;

(2)语法

在变量声明时,维度声明在变量侧;
声明语法

c 复制代码
变量类型  维度 变量名;

初始化及赋值语法

很灵活,支持拼接赋值,位宽不一致(同verilog,短了高位补0,长了截断);

c 复制代码
被赋值元素 = 赋的值;

(3)例子

A非组合型数组的声明和初始化

代码

c 复制代码
module test_array;
    bit [3:0][7:0] d;
    initial begin
        d = 32'h8888_8888;
        $display("d = %h",d);
        d = {8'h12,8'h34,8'h56,8'h78};
        $display("d = %h",d);
    end
endmodule

结果:

说明:

声明了4个8位宽的组合型数组,存储空间分配的存储空间的梁旭的4*8=32位:

(4)特殊点

A组合型数组连续存放的优点有:节省存储空间,方便存读;

4.混合型数组

(1)定义

数组,既包含组合型数组的部分,又包含非组合型数组的部分;

(2)语法

声明语法

c 复制代码
变量类型  维度 变量名 维度;

初始化及赋值语法

组合型部分按照组合型部分赋值,非组合型部分按照非组合型赋值;

(3)特殊点

组合型数组组合部分不可以赋值给非组合型数组,非组合型数组不可以赋值给组合型数组的组合部分;

5.foreach循环

(1)简介

在**()**中给出变量名和索引,sysytemverilog会自动遍历数组中的元素;

(2)语法

c 复制代码
foreach(元素名[索引])begin
	具体操作;
end

(3)例子

代码:

c 复制代码
module test_array;
    int a [10];
    initial begin
        foreach(a[i])begin
            a[i] = i;
            $display("a[%0d] = %0d",i,a[i]);
        end
    end
endmodule

结果:

(4)注意点

索引是可以引用,但不可以更改;

6.数组相关的系统函数

(1)dimensions

A作用:返回数组的维度;

B语法:

c 复制代码
dimensions(数组名);

C例子

c 复制代码
module test_array;
    int a [0:3][0:1];
    bit [3:0] b [0:1];
    initial begin
        $display("The dimensions of a is %0d",$dimensions(a));
        $display("The dimensions of b is %0d",$dimensions(b));
    end
endmodule

结果:

(2)$size

A作用:返回指定维度的尺寸大小

B语法

c 复制代码
$size(数字名,维度);

C例子

代码:

c 复制代码
    int a[0:3][0:2];
    bit [3:0] b [0:2];
    initial begin
        $display("a's first dimension is %0d",$size(a,1));
        $display("a's thied dimension is %0d",$size(a,3));
        $display("b's second dimension is %0d",$size(b,2));
    end
endmodule

结果:

三.动态数组

1.定义

在声明时不需要明指定大小,且可以随时改变大小的数组;

2.语法

(1)声明语法:

c 复制代码
类型 数组名 [];

(2)初始化大小或改变数组大小的语法:

方法1:通过new函数

c 复制代码
变量名 = new[大小];

方法二:通过变量赋值

c 复制代码
变量名 = 赋值变量;

方法三:常量赋值:同非组合型数组

c 复制代码
变量名 ='{值1,值2,...};

(3)开辟新的存储空间并保留原值

c 复制代码
变量名 = new[大小](变量名);

(4)清空动态数组

方法一:

c 复制代码
数组名.delete();

方法二:

c 复制代码
数组名=new[0];

3.例子

代码:

c 复制代码
module test_array;
    int a[],b[],c[];
    initial begin
        $display("%0d,%0d",$size(b,2),$size(b,1));
        a = new[4];
        b = new[3];
        c = new[2];
        $display("a's size is %0d",$size(a,1));
        $display("b's size is %0d",$size(b,1));
        b = a;
        $display("b's size is %0d",$size(b,1));
        c = '{1,2};
        //
        foreach(b[i])begin
            b[i] = i;
            $display("b[%0d] = %0d",i,b[i]);
        end
        b = new[5](b);
        foreach(b[i])begin
            $display("b[%0d] = %0d",i,b[i]);
        end
        //
        b.delete();
        $display("b's dimension is %0d",$dimensions(b));
        $display("%0d,%0d",$size(b,2),$size(b,1));
    end
endmodule 

结果:

四.队列

1.定义

队列是数组和链表的结合,我们可以在任意位置添加或删除数据成员;

2.语法

(1)队列的声明

c 复制代码
类型 队列名 [$];

(2)队列的初始化和赋值

方法一:通过赋常量(注意{}旁没有')

c 复制代码
队列名 = {值1,值2,...}; //注意{}没有'

方法二:通过赋队列(队列2会将值和队列大小同时赋给队列1)

c 复制代码
队列1名 = 队列2名; //注意{}没有'

方法三:可以通过拼接赋值

c 复制代码
队列1名 = {队列2名,值,队列3名};

(3)常用的系统函数

A insert

说明:在指定位置插入值

语法:队列.insert(位置,值);

注意:队列不能插入队列

B delete

说明:删除指定位置的值,或删除所有元素

语法:队列名.delete(索引);//删除指定位置的值,仅适用于队列,不适用于动态数组

队列名.selete();

C push和pop

队列名.push_front(值):在队列前面插入一个值;

存储变量=队列名.pop_front:在队列前面取出一个值;

队列名.push_back(值):在队列后面插入一个值;

存储变量=队列名.pop_back:在队列后面取出一个值;

3.例子

代码:

c 复制代码
module test_array;
    int a [$];
    int b [$];
    int c [$];
    initial begin
        a = {1,2,3};
        b = {5,6};
	  c = {10,b[0:1]};
        $display("a is %p",a);
        $display("b is %p",b);
        $display("c is %p",c);
        b = a;
        $display("b is %p",b);
        b.insert(1,7);
	  b.delete(2);
        $display("b is %p",b);
        void'(a.pop_front);
	  a.push_front(8);
	  void'(b.pop_back);
        b.push_back(9);
        $display("a is %p",a);
        $display("b is %p",b);
    end
endmodule

结果:

4.注意点

(1)队列的索引$表示最后一个元素;

五.关联数组

1.定义

索引可以是任意类型(logic,bit,byte,short,int,long,字符串,枚举类型),存储可以不连续的一种数组;

2.语法

(1)声明语法

c 复制代码
数据类型 大小 名字 [索引类型及大小];

(2)初始化、赋值、改变大小

A 赋常量(键为索引,值为取值)

关联数组名 = '{键1:值1,键2:值,...}

B 赋关联数组

关联数组1名 = 关联数组2名;

(3)关联数组相关的函数

A delete

作用:删除关联数组中的键值对;

语法:关联数组名.delete(索引);

(4)例子

代码:

c 复制代码
    int a [string];
    int b [string]; 
    initial begin
        a = '{"name":1,"age":12,"weigh":45};
        $display("a is %p",a);
	  b = '{"hong":1,"lan":2};
	  $display("b is %p",b);
	  b = a;
	  $display("a is %p",b);
	  b.delete("age");
	  $display("a is %p",b);
    end
endmodule

结果:

六.数组常用方法

1.缩减方法

(1)sum

作用:元素求和

语法:和值存储变量 = 数组.sum();

(2)product

作用:元素求积

语法:积值存储变量 = 数组.product();

(3)and

作用:元素按位与

语法:结果存储变量 = 数组.and();

(4)or

作用:元素按位或

语法:结果存储变量 = 数组.or();

(5)xor

作用:元素按位异或

语法:结果存储变量 = 数组.xor();

(6)例子

代码:

c 复制代码
module test_array14;
	int a[0:3];	
	initial begin
		a = '{1,2,3,4};
		$display("sum is %0d",a.sum());
		$display("product is %0d",a.product());
             $display("and is %0b",a.and());  
 		$display("or is %0b",a.or());
		$display("xor is %0b",a.xor());
	end 
endmodule

结果:

2.定位方法

(0)注意
定位函数的返回值是一个队列,而不是一个元素,所以打印要用%p ;

(1)min

作用:元素最小值

语法:结果存储变量 = 数组.min();

(2) max

作用:元素最小值

语法:结果存储变量 = 数组.max();

(3)unique

作用:遍历不同的值

语法:结果存储变量 = 数组.unique();

(4)例子

代码:

c 复制代码
endmodule
module test_array15;
	int b[];
	initial begin
		b = '{1,2,3,3,5,5,7,9};
		$display("max is %p",b.max());
		$display("min is %p",b.min());
		$display("unique is %p",b.unique());
	end
endmodule 

结果:

3.排序方法

(1)reverse

作用:倒序

语法:结果存储数组 = 数组.reverse();

(2)sort

作用:增序排列

语法:结果存储数组 = 数组.sort();

(3)rsort

作用:降序排列

语法:结果存储数组 = 数组.rsort();

(4)例子

代码:

c 复制代码
module test_array16;
	int a [0:5] = '{1,3,5,7,8,9};
	int b []    = '{2,3,5,6,7,9};
	int c [$]   = {1,3,4,5,7,8};
	initial begin
		a.reverse();
		$display("reverse is %p",a);
           	b.sort();
		$display("sort is %p",b);
		c.rsort();
		$display("rsort is %p",c);
	end
endmodule 

结果:

4.size

四种数组中,哪个数组可以使用size内嵌方法?

动态数组、队列、关联数组都可以,定长数组不可以;
要注意函数$size和内嵌方法size的区别
所有数组$size函数,但是后续三个数组可以用用size内嵌方法

相关推荐
云山工作室4 小时前
基于fpga技术的脉冲信号源设计(论文+源码)
stm32·嵌入式硬件·fpga开发·毕业设计·毕设
Dr.勿忘12 小时前
C#面试常考随笔8:using关键字有哪些用法?
开发语言·unity·面试·c#·游戏引擎
Terasic友晶科技12 小时前
第26篇 基于ARM A9处理器用C语言实现中断<二>
c语言·fpga开发·中断·de1-soc开发板
今天也想MK代码17 小时前
写好简历的三个关键认知
面试·职场和发展
好记性+烂笔头18 小时前
4 Hadoop 面试真题
大数据·hadoop·面试
猫九森19 小时前
golang面试题
面试·golang
Zoolybo21 小时前
FPGA|安装USB Blaster驱动
fpga开发
鲨鱼 Fish1 天前
JVM运行时数据区域-附面试题
java·开发语言·jvm·面试
字节全栈_vBr1 天前
面试之Solr&Elasticsearch
elasticsearch·面试·solr