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<N; k=k+1) begin

                data_rvs[N-k-1] = data_in[k] ;      

            end

        end

    endfunction

       

endmodule

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

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 函数本身可以通过层次名进行调用。

### Verilog 中 `function` 的使用方法 #### 定义与调用方式 在 Verilog 中,`function` 是一种用于封装特定功能的代码块,其定义需遵循严格的语法格式。函数可以在模块内声明,并且能够接受参数列表,在过程中或连续赋值语句中被调用[^5]。 #### 基本语法结构 以下是创建一个简单整数加法运算函数的例子: ```verilog // 整型加法器函数定义 function integer add_function; input [7:0] a, b; // 输入8位二进制数值a,b begin add_function = a + b; // 计算两输入之和并将结果赋予函数名称add_function end endfunction ``` 上述例子展示了如何定义带有两个8位宽输入参数 `a` 和 `b` 的整数相加函数 `add_function` 。该函数返回两者求和后的结果[^2]。 #### 自动化关键字的应用 为了使函数支持并发执行或多线程环境下的操作,可在定义时加入 `automatic` 关键字: ```verilog // 含有自动化的减法器函数定义 function automatic reg signed [7:0] subtract_function; input [7:0] minuend, subtrahend; // 被减数minuend, 减数subtrahend均为8位宽度 begin subtract_function = minuend - subtrahend; // 执行减法计算 end endfunction ``` 这里通过指定 `reg signed [7:0]` 来表明这是一个带符号寄存器类型的输出,适用于处理可能产生负数的情况[^3]。 #### 返回类型说明 除了默认的数据类型外,还可以显式指明更具体的返回数据形式,比如逻辑向量(logic vector): ```verilog // 创建具有明确返回类型的乘法器函数 function logic [15:0] multiply_function(input logic [7:0] multiplicand, multiplier); begin multiply_function = multiplicand * multiplier; // 实现两位八比特数字间的乘积 end endfunction ``` 这段代码片段展示了一个接收两个无符号8位输入并返回它们之间乘积(作为一个16位宽的结果)的功能实现[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值