[verilog读书笔记]8.任务和函数

来源:互联网 发布:经典的迷宫生成算法 编辑:程序博客网 时间:2024/06/06 00:55

    设计者常需要在程序的多个不同地方实现同样的功能,这就有必要将这些公共的部分提取出来,将其组成子程序,然后在有需要的地方调用这些子程序。

一、任何和函数的区别

                       函数                                                              任务                                      函数能调用另一个函数,但不能调用另一个任务         任务能调用另一个任务,也能调用另一个函数                 函数总是在仿真时刻0就开始执行                  任务可以在非零仿真时刻进行函数一定不能包含任何延迟、事件或者时序控制声明语句任务可以包含延迟、事件或者时序控制声明语句函数至少有一个输入变量,函数可以有多个输入变量 任务可以没有或者有多个输入、输出和双向变量          函数只能返回一个值,函数不能有输出或者双向变量任务不返回任何值,任务可以通过输出或双向变量传递多个值

二、任务

    任务使用关键字task和endtask进行声明,如果子程序满足以下任意一个条件,则必须使用任务而不能使用函数:
  • 子程序中包含有延迟、时序或者事件控制结构
  • 没有输出或者输出变量数目大于1
  • 没有输入变量

    1.任务的声明和调用

    
module operation;......parameter delay = 10;reg [15:0] A, B;reg [15:0] AB_AND, AB_OR, AB_XOR;always @(A or B)begin    //启动bitwise_oper任务,该任务提供两个输入变量A和B    //有三个输出变量AB_AND, AB_OR, AB_XOR    bitwise_oper(AB_AND, AB_OR, AB_XOR, A, B);end......//定义bitwise_oper任务task bitwise_oper;output [15:0] ab_and, ab_or, ab_xor;input [15:0] a, b;begin    #delay ab_and = a & b;    ab_or = a| b;    ab_xor = a ^ b;endendtask...endmodule
    2.自动(可重入)任务
        任务在本质上是静态的,任务重的所有声明项的地址空间是静态分配的,同时并发执行的多个任务共享这些存储区。因此,如果这个任务在模块中的两个地方被同时调用,则这两个任务调用将对同一块地址空间进行操作,那么结果很有可能是错的。
        这时候我们可以在task前面添加关键字automatic就能避免。这样的任务也被称为自动任务。
        每次调用的时候,在动态任务重声明的所有模块项的存储空间都是动态分配的。
module topreg [15:0] cd_xor, ef_xor;reg [15:0] c, d, e, f;task automatic bitwise_xor;output [15:0] ab_xor;input [15:0]a, b;begin    #delay ab_and = a & b;    ab_or = a | b;    ab_xor = a ^ b;endend task//下面两个always块将会在clk上升沿的时候同时调用bitwise_xor任务。//因为该任务是可以重入的,所以并发的同时调用能正常地运行always @(posedge clk)    bitwise_xor(ef_xor, e, f);always @(posedge clk)    bitwise_xor(cd_xor, c, d);endmodule

三、函数

    verilog使用关键字function和endfunction来进行函数声明。对于一个子程序来说,如果下面的所有条件全部成立,则可以用函数来完成:
  • 在子程序内不含有延迟、时序或者控制结构
  • 子程序只有一个返回值
  • 至少有一个输入变量
  • 没有输出或者双向变量
  • 不含有非阻塞赋值语句

    1.函数的声明和调用

//定义一个模块,其中包含能计算偶校验位的函数calc_paritymodule parity;...reg [31:0] addr;reg parity;//每当地址值发生变化,计算新的偶校验位always @(addr)begin    parity = calc_parity(addr);    $display("Parity calculated = %b", calc_parity(addr));end......//定义偶校验位计算函数function calc_parity;input [31:0]address;begin    calc_parity = ^address;endendfunction......endmodule

    2.自动(递归)函数

        verilog中的函数时不能进行递归调用的,原因同上,因为是对同一块地址空间进行操作,那么计算结果将是不确定的。因此我们需要加上automatic,那么该函数将成为自动的或可递归的,即仿真器每一次函数调用都动态分配新的地址空间,每个函数调用对各自的地址空间进行操作。
module Top;function automatic integer factorial;input [31:0] oper;integer i;beginif(operand >= 2)    factorial = factorial(oper - 1) * oper;else    factorial = 1;endendfunctioninteger result;initialbegin    result = factorial(4);    $display("Factorial of 4 is %0d", result);endendmodule

    3.常量函数

        常量函数实际上就是一个带有某些限制的常规verilog函数。


0 0
原创粉丝点击