1.子程序参数
SV对子程序的改进使参数的声明变得更方便,同时也扩展了参数传递的方式
Verilog-1995的子程序参数设置:
task mytask2;//无( )
output[31:0] x;
reg [31:0] x;
input y;
...
endtask
SV中,可以用简明的C语言风格:
task mytask2 (output logic [31:0] x,input logic y);//可同时声明方向和类型
...
endtask
2.参数传递
task many(input int a=1,b=2,c=3,d=4);//这里为形参指定默认值,当调用该task而未指定参数值时,使用默认值
$display(“%0d %0d %0d %0d”,a,b,c,d);
endtask
initial begin
many(6,7,8,9); //6 7 8 9 指定所有值,这种比较常用
many(); //1 2 3 4 使用缺省值
many(.c(5)); //1 2 5 4 只指定c
many(,6,,.d(8)); //1 6 3 8 混合指定
end
3.子程序返回
3.1返回数组
Verilog一般只能返回一个 简单值,如bit, integer等, 若想计算并返回一个数组, verilog就无能为力了。而SV中的函数可以采用多种 方式返回一个数组:
3.1.1用typedef从函数中返回一个数组
typedef int fixed_array[5];
fixed_array f5;//定义一个数组
function fixed_array init(int start);//再定义一个数组类型的函数
foreach(init[i]) init[i]=i+start;
endfunction
initial begin
f5=init(5);//调用函数,将函数生成的数组给f5数组,因为函数调用结束后,内存被释放掉了
foreach(f5[i]) $display("f5[%0d]=%0d",i,f5[i]);
end
3.1.2把数组作为ref参数传递给函数
program example;
int fa[5];//定义一个数组
initial begin
init(fa,5);//该函数直接修改上面的数组内存
foreach(fa[i]) $display(“fa[%0d]=%0d”,i,fa[i]);
end
function void init(ref int f[5], input int start);//ref指向输入的数组
foreach(f[i]) f[i]=i+start;
endfunction
endprogram
4.静态/动态子程序
如果不声明,则task/function默认是静态static的
4.1静态子程序
静态子程序其内部变量可以共享,相当于全局变量
module top_tb;
reg [1:0] result_1,result_2;
reg co_1,co_2;
initial begin
fork
begin // p1
#1;
add2x2 (2'b01,result_1,co_1);
end
begin // p2
#2;
add2x2 (2'b10,result_2,co_2);
#8;
end
join
end
//defaut static task
task add2x2(input [1:0] opt,output [1:0]result,output co);
reg [1:0] temp;
begin
temp = opt;
#4;
$display("static task : %t : temp is%0d",$time,temp);
{co,result} = temp + 2'b10;
end
endtask
endmodule
仿真结果:
可见,本来应该在5ns时temp应该打印1,却打印了2,这是因此在静态子程序中,其内部变量可共享,因此当再调用该子程序时,会将上一次的变量修改:
4.2动态子程序
动态子程序内部变量不可共享,相当于每次调用子程序的时候,都单独为变量开辟了一块儿内存,动态子程序只要在声明的时候加上automatic即可,上述的例子将task改成动态子程序:
task automatic add2x2(input [1:0] opt,output [1:0]result,output co);
······
endtask
仿真结果:
可见符合预期结果。
4.3静态/动态子程序区别
5.$timeformat系统函数
其常用于指定%t显示的时间格式,例如$display,$monitor等,其用法如下:
$timeformat (units_number, precision_number,suffix_string,minimum_field_width);
//units_number : -9 表示ns; -12表示ps; -15表示fs;
//precision_number: 数据精度,小数点后的多少位;
//suffix_string: 时间值之后的字符串;
//minimum_field_width:时间字符串字段的最小宽度;
module timing;
timeunit 1ns; // 时间单位
timeprecision 1ps; // 时间精度
initial begin
$timeformat(-9,3,"ns",8);
#1 $display(“%t”,$realtime); // 1.000ns
#2ns $display(“%t”,$realtime); // 3.000ns
#0.1 $display(“%t”,$realtime); // 3.100ns
#41ps $display(“%t”,$realtime); // 3.141ns
end
endmodule