一、systemverilog 数据类型

数据类型

内建数据模型

SV对Verilog是兼容的,Verilog的数据类型SV都包括。例如net的wire,variable中的reg,integer,real等
相对于Verilog将寄存器类型reg和线网(net)类型,如wire,SV中引入了logic数据类型。
Verilog便硬件描述,所以注重的是声明的变量是寄存器类型还是线网类型。
SV偏验证,不关心logic对应逻辑应该被综合成为寄存器类型还是线网类型,只会作为单纯的变量进行赋值。
logic类型为四值逻辑,分别是0、1、x、z。x代表不确定,可能为0也可能为1;z代表高阻态,表示没有被驱动。四值逻辑可以看作是硬件的世界。
bit类型为二值逻辑,分别是0、1。二值逻辑可以看作是软件的世界。

  • 四值逻辑
	integer
	logic
	reg
	net-type(wire、tri)
  • 二值逻辑
	byte
	short int
	int		
	long int
	bit
  • 有无符号划分
	有符号:byte、short intintlong int、integer
	无符号:bit、logic、reg、net-type(wire、tri)
  • 赋值与比较

赋值:阻塞赋值“=”,非阻塞赋值“<=”
比较:等于“==”, 不等于“!=”

  • 显式转换

静态转换:在转换的表达式前面加上单引号,该方式不会对转换值做检查
动态转换:$cast(src,dst), 转换失败会在仿真的时候报错

  • 隐式转换
	logic[3:0] a = 4'b111x;
	bit[2:0] b;
	b = a;		//b的值应该为110,四值赋值给二值逻辑类型时,x变成0,z也会变成0

在不同类型进行操作时要注意:
1、逻辑数值类型:是四值还是二值
2、符号的类型
3、矢量的位宽

定宽数组

  • 数组声明
	一维数组:
	int array[0:15];	//16个int类型元素
	int array1[16];	//C语言风格
	二维数组:
	int array2[0:7][0:3];	//完整声明
	int array3[8][4];		//紧凑声明
  • 初始化和赋值
	//声明的同时,对4个元素初始化
	int array[4] = '{0,1,2,3};		
	//声明和赋值分开操作
	int array[4];
	array = '{1,2,3,4};
	//4个值全部赋值为1
	array = '{4{1}};
	//部分元素使用默认赋值
	array = '{1,2,default:0};		//{1,2,0,0}
  • pack/unpack 合并型数组/非合并型数组
//合并型数组
bit[3][7:0] b_pack;			
logic[3][7:0] l_pack;		

合并型数组可以实现连续的存储,赋值时不需要用 '{ }
p_pack:表示3行x8列的数组,[3]是高维度,[7:0]的低维度(第一维)
数组中,数据排列为{b_pack[2],b_pack[1],b_pack[0]},其中每个b_pack为8个bit;
bit是二值逻辑,每位bit只占据1位。故24位(8bit * 3)只占据一个word(一般一个word为32bit)的存储空间;
l_pack:因为是非合并型,每一个元素占用一个WORD空间,但是有效空间只有8bit。

只有用到

	//非合并型数组
	bit[7:0] b_unpack[3];	//形式2 int array[7:0][1023:0] 也是非组合型数组,[7:0]是高维度
	logic[7:0] l_unpack[3];		

存储的数据都是相互独立(不连续)的,赋值时需要用 '{ }。
b_unpack: [3]是高维度,bit 是二值逻辑,表示占据了三个word的空间,每个占据低8位空间
l_unpack:logic是4值逻辑,每一位logic需要2bit表示,所以24bit logic就需要48位来表示。即需要两个word来存储。

  • 数组基本操作:for/foreach/
	initial begin
		bit[31:0] b;
		int array[3] = {1,1,1};
		for(int i = 0; i < $size(b); i++)		//for循环进行赋值
			b[i] = i;
	 	foreach(array[j])						//foreach循环遍历
	 	$display(j,array[j]);
	end

动态数组

定宽数组:宽度编译时确定
动态数组:运行时再确定宽度
动态数组声明时用[],之后使用new[]来分配空间

	int array[];
	initial begin
		...
		array = new[5];//分配5个元素
		...
	end

关联数组

关联数组:用于保存稀疏矩阵的元素。当你对一个非常大的地址空间寻址时,该数组只为实际写入的元素分配空间,这种实现方法所需的空间比定宽或动态数组所占用的空间要小得多。

当使用超大容量的数组时,使用关联数组会更好一些。动态数组面临超大容量的情景,可能存在着浪费的情况,因为很有可能该大容量数组中有相当多的数据不会被存储和访问。而关联数组可以用来保存稀疏矩阵的元素,该数组只为实际写入的元素分配空间。

在这里插入图片描述

其他语言也有类似的数据存储结构,如哈希(hash)和python中的词典(dictionary),可以灵活赋予键值(key)和数值(value)。

	bit [63:0] assoc[int],idx = 1;
	repeat (64) begin       //对稀疏分布的元素进行初始化
	    assoc[idx] = idx; //assoc[1] = 1
	    idx = idx << 1; //assoc[2] = 2,assoc[3] =4,...
	end
	 
	forrach (assoc[i]) //使用foreach遍历数组
	    $display("assoc[%h] = %h",i,assoc[i]);
	 
	//找到并删除第一个元素
	assoc.first(idx);
	assoc.delete(idx);

遍历使用:first/last/next/prev

队列

队列的声明使用[$],队列元素的标号从0到 $ 。
队列不需要new[]来创建空间。

	//队列声明
	int array [$];
	initial begin
	    for(int i = 0 ; i < 10 ; i++ ) begin
	    	array.insert(i,i);
	    end
	end

队列除了可以像数组一样通过index直接访问到内部元素,一般还会通过内建的一系列方法来对其进行操作。常用的几个内建方法列举如下:

函数功能描述
size()返回队列中元素个数
insert(index, item)将数据item插入到队列的index处。如果index为负数或存在x/z态或大于队列的size,则无法插入成功,会报warning。
delete([index])删除队列中index处数据。当参数没有指定,则会将整个队列的数据都清空。
pop_front()将队列的第一个元素弹出。若是由一个空队列调用,则会返回元素默认值,且可能会报warning。
pop_back()将队列的最后一个元素弹出。若是由一个空队列调用,则会返回元素默认值,且可能会报warning。
push_front(item)将数据item添加到队列开头
push_back(item)将数据item添加到队列最后

结构体

Verilog没有数据结构,而在SV中可以使用struct语句创建结构体。struct只是一个数据的集合,伴随typedef可以用来创建新的类型。

	typedef struct {            //用户自定义类型的结构体
	    logic   [7:0]   a, b;
	    logic   [31:0]  address;
	} Instruction_word_t;
	
	Instruction_word_t  IW; //用IW代替结构体名
	
	//调用结构体内部变量
	IW.a
	IW.adress

将一个结构体声明为用户自定义类型不分配存储空间,在调用 (或实例化) 这个结构体时才会分配存储空间,示例中在Instruction_word_t IW;会给结构体分配存储空间
如果结构体不用typedef声明,它会被当作匿名结构体引用

	module struct_tb;
	    typedef struct{
	        logic   [7:0]   a, b;
	        logic   [3:0]   all_one;
	        bit             flag;
	    }Instruction_t;
	
	    Instruction_t   IW = '{100, 8'hF0, '1, 0}; //实例化方式1
	    Instruction_t 	IW = '{a:10, b:8'h0F, all_one:2, flag:0}; //实例化方式2
	
	    initial begin   //打印结构体中的内容
	        $display ("\n\t the a is %b", IW.a);
	        $display ("\n\t the b is %b", IW.b);
	        $display ("\n\t the all_one is %b", IW.all_one);
	        $display ("\n\t the flag is %b", IW.flag);
	    end
	endmodule

枚举

enum经常和typedef搭配使用

	module enumeration_basic;
		//enum {red, green, yellow} traffic_lights;
		typedef enum {red, green, yellow} traffic_lights;
		traffic_lights light;
		initial begin	
			$display("default light_name=%s, light=%0d",light.name,light);
			light = red ;
			#1;
			light = yellow;
			#1;
			light = green;
			#1;
		end
	 	initial begin
	    	$monitor ("time %0t ns, ligh_name=%s, light=%0d",$time,light.name,light);
	  	end
	endmodule

如果枚举没有初始化,默认是int 型,则从第一个标识符开始,顺次赋给标识符0、1、2 …

例如要遍历一个枚举类型的数据,使用简单的for循环或者foreach循环是不行的,可以使用如下例中所示的 first() 以及 next() 方法.

SV中枚举类型提供了以下方法供用户使用:
	first() //returns the first member of theenumeration.
	last()  //returns the last member of theenumeration.
	next()  //returns the next element of theenumeration.
	next(N) //returns the Nth next element.
	prev()  //returns the previous element ofthe enumeration.
	prev(N) //returns the Nth previous element.
	typedef enum {RED, BLUE, GREEN} color_e;
	color_e color;
	color = color.first();
	do
	  begin
	    $display("Color = %0d/%s",color, color.name);
	    color = color.next();
	  end
	while (color != color.first);

字符串

Verilog语言对于字符串的处理手段非常有限。SV引入了string类型用来容纳可变长度的字符串。

SV中字符串的特点:
字符串类型变量的存储单元为byte类型( 8位二值逻辑)。
字符串类型变量长度为N时,其字符成员索引值为从0到N-1
不同于C语言,字符串结尾没有空字符“\0”
字符串的内存是动态分配的,用户无需担心内存空间管理。

	typedef logic [15:0] r_t;
	r_t r;
	integer i = 1;
	string b = "" ;//声明赋予初值。定义的字符串默认值是空字符串
	string a = {"Hi",b} ;//利用连接符号{}
	r = r_t' (a) ; //字节类型转换,字符串变成向量类型
	b = string'(r); //向量转换成字符串
	b = "Hi"; 
	b = { 5{ "Hi"}}; //b ={"Hi","Hi","Hi","Hi","Hi"}常量复制
	a = { i{ "Hi"}}; //(非常量复制)a里面的i个Hi
	a = {i{b}};
	a = {a,b} ; 
	a = { "Hi",b}; 
	b = {"H"""} ;//"H"。""是空字符串
	a[0]=-"h";//等同于a[0]= "cough”
	str.len()//返回字符串的长度。
	str.putc(i, c)//将第i个字符替换为字符c,等同于str[i]=c。
	str.getc(i)//返回第i个字符。
	str.substr(i,j)//将从第i个字符到第j个字符的字符串返回。
	str. {atoi(), atohex(), atooct, atobin}//将字符串转变为十进制、十六进制、八进制或者二进制数据。
	string s ;
	initial begin
	    s ="IEEE";
	    $display (s.getc(0)); //显示'I' 显示第几个字符
	    $display (s.tolower()); //显示ieee。把字符串小写
	    s.putc(s.len () -1, "-"); //将空格变为'-'。将最后一个字符变成'-'
	    s = {s, "P1800"}; //"IEEE-P1800"
	    $display(s.substr (2,.5));//显示EE-P
	end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值