Verilog语法之函数function的讲解

function讲解:

在verilog语言中,函数与任务是可综合的。

可以用function与task,将重复性的行为级设计(就是rtl描述)进行提取,并在多个地方调用,来避免重复代码的多次编写,可使代码更加的简洁易懂。

函数特点说明:

  1. 函数只能在模块内部,任意位置,定义与使用。作用范围也仅限于此模块;
  2. 不能有任何延迟,时序或者时序逻辑控制;
  3. 至少有一个输入变量;
  4. 只有一个返回值,没有输出;
  5. 不能含有非阻塞赋值语句;
  6. 函数可以调用其他函数,不能调用任务。

函数定义格式:

 

  //  定义格式:

    function [range-1:0]    function_id         ;   // 没有输出但是有一个返回值,就是这个函数名称(function_id),range 定义位宽。

                                                    // 函数的返回值通过这个变量进行传递。当该寄存器变量没有指定位宽时,默认位宽为 1。

        input               input_declaration   ;   // 输入端口。可以有多个输入。

                            other_declaration   ;   // 其他描述

                            procedural_statement;   // 工序过程要素

    endfunction

函数调用格式:


    // 函数调用格式:

    function_id(input_data1, input_data2);

下面用函数实现一个数据大小端转换的功能:

// 大小端转换,就是把低位变高位,高位变低位。

module endian_rvs #(parameter N = 4) (

    input       wire                    en  ,   //enable control

    input       wire    [N-1:0]         a   ,

    output      wire    [N-1:0]         b

 );

    // reg signal descrioption

    reg     [N-1:0]             b_temp ;

    always @(*) begin

        if (en) begin

            b_temp = data_rvs(a);

        end

        else begin

            b_temp = 0 ;

        end

    end

    assign b = b_temp ;

       

 //function entity

    function            [N-1:0]     data_rvs        ;

        input    wire    [N-1:0]     data_in         ;

        parameter                    MASK = 32'h3    ;

        integer                      k               ;

        begin

            for(k=0; k

里面的参数也可以改写为:

defparam data_rvs.MASK = 32'd7 ;

函数声明还可以在函数名称后面加上括号,把输入端口包含进入:

function [N-1:0]     data_rvs(

input     [N-1:0] data_in

    ......

) ;

常数函数:

什么是常数函数:

在仿真开始之前,在编译期间就计算出结果为常数的函数。常数函数不允许访问全局变量或者调用系统函数,但可以调用另一个常数函数。

parameter    MEM_DEPTH = 256 ;

reg  [logb2(MEM_DEPTH)-1: 0] addr ; //可得addr的宽度为8bit

 

    function integer     logb2;

    input integer     depth ;

        //256为9bit,我们最终数据应该是8,所以需depth=2时提前停止循环

    for(logb2=0; depth>1; logb2=logb2+1) begin

        depth = depth >> 1 ;

    end

endfunction

automatic 函数:

用得很少。

在 Verilog 中,一般函数的局部变量是静态的,即函数的每次调用,函数的局部变量都会使用同一个存储空间。若某个函数在两个不同的地方同时并发的调用,那么两个函数调用行为同时对同一块地址进行操作,会导致不确定的函数结果。

Verilog 用关键字 automatic 来对函数进行说明,此类函数在调用时是可以自动分配新的内存空间的,也可以理解为是可递归的。因此,automatic 函数中声明的局部变量不能通过层次命名进行访问,但是 automatic 函数本身可以通过层次名进行调用。

你可能感兴趣的:(fpga开发)