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
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
Verilog一般只能返回一个 简单值,如bit, integer等, 若想计算并返回一个数组, verilog就无能为力了。而SV中的函数可以采用多种 方式返回一个数组:
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
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
如果不声明,则task/function默认是静态static的
静态子程序其内部变量可以共享,相当于全局变量
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,这是因此在静态子程序中,其内部变量可共享,因此当再调用该子程序时,会将上一次的变量修改:
动态子程序内部变量不可共享,相当于每次调用子程序的时候,都单独为变量开辟了一块儿内存,动态子程序只要在声明的时候加上automatic即可,上述的例子将task改成动态子程序:
task automatic add2x2(input [1:0] opt,output [1:0]result,output co); ······ endtask
仿真结果:
可见符合预期结果。
其常用于指定%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