systemverilog学习日记(一)


IC前端设计需要设计人员编写testbench来进行对模块的初步前仿,一般是用verilog来写,但是verilog语言结构简单,编写一个稍微复杂的仿真环境很是费力,所以systemverilog便被开发设计出来。systemVerilog是一门高级语言,官方描述为:
SystemVerilog简称为SV语言,是一种相当新的语言,它建立在Verilog语言的基础上,是 IEEE 1364 Verilog-2001 标准的扩展增强,兼容Verilog 2001,将硬件描述语言(HDL)与现代的高层级验证语言(HVL)结合了起来,并新近成为下一代硬件设计和验证的语言。
既可以用作设计又可以用作验证,功能十分强大,所以多学一门systemverilog会让你如虎添翼。笔者本着学无止境的态度,开始接触学习systemverilog.开始吧,一步一个脚印。

数据类型

内建数据类型

什么语言一开始都要从基本数据类型学起,sv也不例外。sv的数据类型像是继承了c语言的很多特色,除了byte 、int、shortint、longint这些c语言里经常看到的,SV还加了logic
、bit等。接下我解释一下这些类型怎么个用法。

logic: 只能双状态,0或者1,reg型和wire型综合,只能被单一驱动
bit: 四状态,0,1,高阻z,未知x,这个比较常用,可以自由定义位宽,例如

bit b;    //单比特
bit [15:0] data;//16比特数据,无符号
rand bit [15:0] r_data;// 写testbench时经常会加上rand,用于生成随机化数据。

byte: 8比特有符号数据
int: 32比特有符号数据
shortint: 16比特有符号整数
longint: 64比特有符号整数

这些都可以用bit来代替,而且Bit是无符号的,bit [7:0] 等于 byte unsigned

数组

数组可分成定宽数组和动态数组,定宽数组又可以分成压缩数组和非压缩数组,

bit [7:0] data [0:3] //生成位宽8,深度为4的数组,这是非压缩数组
//也可以这样表达
bit [0:3] [7:0]  data;//压缩数组,作用类似上面表达
bit [0:3] [7:0] barray[3]//这个用法我也没见过,书上是这么定义的,其存放示意图如下

压缩数组的结构是这样的
图1
图2

动态数据是位宽暂时无法确定的数组,其在声明时使用空的[],在使用时需要调用new[],同时方括号里要填上数组的宽度,例如:

int data[];//声明动态数组
initial begin
data=new[4];//数组宽度为4
end

自定义数据类型

sv提供typedef 和 struct来为用户自定义数据类型

struct和typedef用法和c语言的差不多,直接代码解释:

typedef struct {int a,b,c;} usr_data;//创建usr_data结构,包括三个int数据
typedf int unsigned uint;//uint 和 int unsigned等效,下面语句可以直接使用uint

接口

interface

端口与端口之间的连接一般通过input和output来传输信号线,当这些信号线数目大的时候,信号线连接就会出现很多的问题和麻烦,于是接口interface就被提出,interface的作用就是把一群信号线捆绑成一个接口,里面可以有时钟有复位信号,也有多位宽数据。接口可以被方便引用,例如:

interface arb_if (input bit clk); 
	logic [1:0] grant,request; 
	logic rst; 
endinterface

发没发现接口里的数据类型都是logic,而不是wire,想想什么原因?
以上是我们定义了一个接口,接下来展示我们怎么使用它。如果需要用到接口里的某个信号,我们只要写接口名.信号名,例如:

module test (arb_if arbif);//接口名 自定义名
always @ (posedge arbif. clk or posedge arbif. rst) 
begin 
	if (arbif. rst) 
	arbif.grant<=2'bOO; 
	else 
	••• 
end
endmodule

PS:接口里的信号必须使用非阻塞赋值

modport

modport的功能是把interface里的信号分组,选取一些信号作为输入,一些信号作为输出,modport 名(input/output 信号名,…..)例如:

interface arb_if (input bit clk); 
	logic [ 1: O] grant, reques 七;
	logic rst; 
	modport TEST (output request, rst, 
	input grant, clk); 
	modport DUT (input request,rst,clk, 
	output grant);
	modport MONITOR (input request,grant,rst,clk); 
endinterface

那我们怎么去用它呢?很简单,就是 接口名.modport名 自定义接口名 ,例如:

module arb (arb_if.DUT arbif); 
••• 
endmodule

clocking

每个接口可以有多个时钟块,clocking cb @(posedge clk)的作用是表明我这个区域里的信号只在我这时钟上升沿有效,具体怎么表达例如:

clocking cb @ (posedge clk) ;//声明 cb
output request; 
input grant;
endclocking

既然学了clocking,那么modport的写法我们又能这么写了:

modport TEST (clocking cb, //使用 cb
output rst);

怎么用这个接口呢?那就是像套娃一样,怎么套进去的怎么拿出来,

program automatic test (arb_if.TEST arbif); //program习惯加上automatic,
initial begin 
	arbif. cb. request<= 2'bOl;   //接口里的clocking模块里的信号
	$display( "@%t: Drove req= 01", $time); 
	repeat (2) @arbif.cb;   //重复两个clocking模块里的时钟
	if (arbif.cb.grant! =2'b01) 
	$display ("@%t: al: grant! = 2'bOl", $time); 
end 
endprogram : test

文章作者: zhr
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 zhr !
  目录