数字验证学习笔记——SystemVerilog芯片验证5 ——过程块和方法

一. Initial 和 always

在SV中同学们首先需要清楚哪些语句应该被放置于硬件世界,那些程序被放置于软件世界。

硬件

  1. module/endmodule
  2. interface/endinterface

软件

  1. program/endprogram
  2. class/endclass

1.1 always

always过程块是用来描述硬件时序电路和组合电路的,因此只可以在module或者interface中使用。

1.2 initial

initial与always在执行路径上有明显的区别,initial符合软件的执行方式,即执行一次。

initial不可综合,因此,不应该存在硬件设计代码中,initial是为测试而生的,由于测试需要按照时间顺序的习惯即软件方式完成,所以initial便可以实现这一要求。

initial过程块可以在module、interface、program过程中使用。

二.函数 function

可以在参数列表中指定输入参数(input)、输出参数(output)、输入输出参数(inout)或者引用参数(ref)。
可以返回数值或者不返回数值(void)。
function int double( input [31:0] a ); //默认的数据类型是logic
return 2*a; // 如果没有明确定义输入输出类型,默认是输入
endfunction
int
initial begin
$diaplay( " double of %0d is %d " , 10 , double(10) ) ; // \n 是换行
end

三.任务 task

任务相比于函数就更加灵活,且有以下不同点:

  1. task 无法通过return返回结果,只能通过output、inout或者ref的参数返回
  2. task内可以置入耗时语句,而function则不能。常见的耗时语句包括@event、wait event、#delay 等

task mytask1( output logic [31:0] x,input logic y);

endtask

function和task的使用建议:

1.初学者,全部用task来定义方法
2.有经验的使用者 ,非耗时方法,用function(纯粹的数字或者逻辑运算);内置耗时语句 task(耗时的信号采样或者驱动场景)
3.function和task均可以调用function。只有task能调用task,因为如果task内置耗时语句,function是无法调用的

问题
typedef struct{
bit [1:0] cmd ;
bit [7:0] addr;
bit [31:0] data;
} trans;
function automatic void op_copy( trans t,trans s);
t=s;
endfunction

initial begin
trans s;
trans t;
s. cmd=’h1;
s. addr='h10;
s.data='h100;
op_copy(t, s);
t.cmd='h2;
end //最后的结果是t.cmd='h2 t.addr='h0 t.data=0 因为function没有明确定义输入输出类型,默认是输入

四.变量生命周期

在SV中,我们将数据的生命周期分为动态(automatic)和静态(static)

4.1 动态生命周期

局部变量的生命周期同其所在域共存亡,例如function/task 中的临时变量,在其方法调用结束后,临时变量的生命也将终结,所以它们是动态生命周期。

4.2 静态生命周期

全局变量即伴随着程序执行开始到结束一直存在,例如module中的变量(默认情况下全部为全局变量),我们可以理解为module中的变量在模拟硬件信号,所以它们是静态生命周期。

如果数据变量被声明为automatic,那么在进入该进程/方法后,automatic变量会被创建,而在离开该进程/方法后,automatic变量会被销毁。
而static变量在仿真开始时即会被创建,而在进程/方法执行过程中,自身不会被销毁,且可以被多个进程和方法所共享。

module

function automatic int auto_cnt( input a); //这个函数里面所有的变量都是automatic
int cnt=0;
cnt = cnt +a ;
return cnt;
endfunction

function static int static_cnt( input a); //这个函数里面所有的变量都默认static
static int cnt =0; //第二次调用这个函数 静态变量cnt=1 因为静态变量只会初始化一次
cnt =cnt +a;
return cnt;
endfunction

function int def_cnt(input a); //在非动态的任务和函数中,缺省时为静态变量
int cnt=0; // 对于automatic或者static方法,也可以对内部定义的变量做单个声明
cnt =cnt +a;
return cnt;
endfunction

intial begin
$display(" @1 auto_cnt =%0d" , auto_cnt(1) ); // auto_cnt=1
$display(" @2 auto_cnt =%0d" , auto_cnt(1) ); // auto_cnt=1
$display(" @1 static_cnt =%0d" , static_cnt(1) ); // static_cnt=1
$display(" @2 static_cnt =%0d" , static_cnt(1) ); // static_cnt=2
$display(" @1 def_cnt =%0d" , def_cnt(1) ); // def_cnt=1
$display(" @2 def_cnt =%0d" , def_cnt(1) ); // def_cnt=2
end

endmodule

你可能感兴趣的:(验证学习,学习)