SV学习笔记—子程序

2022/2/8 20:13:52

本文主要是介绍SV学习笔记—子程序,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

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



这篇关于SV学习笔记—子程序的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程