Verilog中function函数的使用说明

平台:vivado2017.4

仿真:modelsin10.6d

最近在看XILINX的IP仿真时,发现他们做的仿真模型里面使用了很多task和function。这部分类容是在学习verilog期间忽略掉了。

首先来看看官方的解释。

  • Function说明语句

函数的目的是返回一个用于表达式的值。

定义函数的语法:

function <返回值的类型或范围>(函数名);

                <端口说明语句>

                <变量类型说明语句>

                beign

                <语句>

                ...

                End

endfunction

请注意<返回值的类型或范围>这一项是可选项,如缺省则返回为一位寄存器类型数据。

  • 函数返回的值

函数的定义蕴含声明了与函数同名的,函数内部的寄存器。如在函数的声明语句中<返回值的类型或范围>为缺省,则这个寄存器是一位的,否则是与函数定义中<返回值的类型或范围>一致的寄存器。函数的定义把函数返回值所赋值寄存器的名称初始化为与函数同名的内部变量。

  • 调用

函数的调用是通过将函数作为表达式中操作数来实现的。

<函数名>(<表达式><,<表达式>>*)

  • 使用规则

与任务相比较函数的使用有较多的约束,下面给出的是函数的使用规则:

  1. 函数的定义不能包含有任何的时间控制语句,即任何用#、@、或wait来标识的语句。
  2. 函数不能启动任务。
  3. 定义函数时至少要有一个输入参量。
  4. 在函数的定义中必须由一条赋值语句给函数中的一个变量赋以函数的结果值,该内部变量具有和函数名相同的名字。

这里来看一看用法。原verilog模块为一个分频模块。模块的功能是对输入时钟100mhz信号进行分频。输出分频后时钟信号的上升沿。

这里我们使用n来对分频次数计数。

配置函数FREQUENCY_CNT ,此函数的作用是通过输入的值,来选择输出的值。返回值的是一个32位的FREQUENCY_CNT。

在任务中调用该函数。根据任务的输入值,来让函数FREQUENCY_CNT输出值。

下面看一看代码。

`timescale 1ns / 1ps


// Company: 
// Engineer:
//
// Create Date:   14:36:04 07/28/2022
// Design Name:   ad_frequency
// Module Name:   E:/code1/xiyao/PXI_9801_FPGA_H0/9801_seq_writes/PXI_9801_seq/sources/sim/vtf_ad_frequency.v
// Project Name:  PXI_9801
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: ad_frequency
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module vtf_ad_frequency;

	// Inputs
	reg [31:0] reg_clk_div_param;
	reg clk_100mhz;
	reg rst_n;
	// Outputs
	wire clk_cnv;
	// Instantiate the Unit Under Test (UUT)
	ad_frequency uut (
		.reg_clk_div_param          (reg_clk_div_param          ), 
		.clk_cnv                    (clk_cnv                    ), 
		.clk_100mhz                 (clk_100mhz                 ), 
		.rst_n                      (rst_n                      )
	);

    //------------------------------------------------------
    //复位参数
    //------------------------------------------------------
    integer            i;
    //设置复位参数
    initial
    begin
            $display("[%t] : reset begin...", $realtime);
            rst_n = 0;
            for( i=0 ; i<100 ; i=i+1)
            begin
                    @(posedge clk_100mhz );
            end
            $display("[%t] : reset stop...", $realtime);
            rst_n = 1;
    end
    //------------------------------------------------------
    //时钟参数
    //------------------------------------------------------
    initial
    begin
            clk_100mhz = 0;
    end

    //------------------------------------------------------
    //分频数值
    //------------------------------------------------------
    parameter       delay_cnt   = 100000;
    reg     [31:0]  result;
    reg     [4:0]   n;
    reg             delay_over;

    initial
    begin
            #100;
            $display("[%t] : div start...", $realtime);
            for(n = 0 ; n <= 4 ;n = n + 1 )
            begin
                    tsk_frequency(result,n);
                    reg_clk_div_param   = result;
                    delay(delay_over,delay_cnt);//调用等待任务
            end
            $display("[%t] : div end...", $realtime);
            $finish(1);
    end
    //------------------------------------------------------
    //函数,
    //------------------------------------------------------
    function    [31:0]  FREQUENCY_CNT;
            input   [4:0]   operand;
            reg     [31:0]  index;
            begin
                    case(operand)
                            5'd0 :  index = 32'd100;
                            5'd1 :  index = 32'd1000;
                            5'd2 :  index = 32'd5000;
                            5'd3 :  index = 32'd10000;
                            5'd4 :  index = 32'd2000;
                            5'd5 :  index = 32'd11000;
                            5'd6 :  index = 32'd4000;
                            5'd7 :  index = 32'd12000;
                            5'd8 :  index = 32'd6000;
                            5'd9 :  index = 32'd300;
                            5'd10:  index = 32'd9900;
                            5'd11:  index = 32'd20000;
                            5'd12:  index = 32'd500;
                            5'd13:  index = 32'd2000;
                            5'd14:  index = 32'd4000;
                            5'd15:  index = 32'd6000;
                            default:
                                    index   = 32'd0;
                    endcase
                    FREQUENCY_CNT   = index;
            end
    endfunction
    //------------------------------------------------------
    //任务,在任务中调用函数
    //------------------------------------------------------
    task    tsk_frequency;
            output  [31:0]  tsk_frequency_cnt;
            input   [4:0]   tsk;
            begin
                    $display("[%t] : tsk start...", $realtime);
                    tsk_frequency_cnt   = FREQUENCY_CNT(tsk);
                    $display("[%t] : tsk end...", $realtime);
            end
    endtask

    //------------------------------------------------------
    //任务,输入的分频数值加100后输出
    //------------------------------------------------------
    task    clk_div;
            output  [31:0]  div_out;
            input   [31:0]  div_in;
            begin
                    repeat(10)@(posedge clk_100mhz);
                    div_out = div_in + 100;
            end
    endtask

    //------------------------------------------------------
    //任务,延时模块
    //------------------------------------------------------
    task    delay;
            output          delay_over;
            input   [31:0]  delay_in;
            begin
                    repeat(delay_in)@(posedge clk_100mhz);
                    delay_over = 1;
            end
    endtask








            


    
    always #5 clk_100mhz = ~clk_100mhz;

endmodule

仿真效果图。

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog function 函数可以用来实现一些简单的逻辑运算或计算,其语法为: ``` function [data_type] function_name ( input [input_type] input_name, ... ); [data_type] variable_name; // 函数操作 return variable_name; endfunction ``` 其,`[data_type]` 表示函数返回值的数据类型,`function_name` 是函数的名称,`[input_type]` 表示输入参数的数据类型,`input_name` 是输入参数的名称,`variable_name` 是函数内部定义的变量名称。 下面是一个简单的例子,实现两个 4 位二进制数的加法: ``` function [3:0] adder (input [3:0] a, b); reg [3:0] sum; integer i; sum = 4'b0; for (i = 0; i < 4; i = i + 1) begin sum[i] = a[i] + b[i] + sum[i]; if (sum[i] > 1) begin sum[i+1] = 1; sum[i] = sum[i] - 2; end end return sum; endfunction ``` 在上面的代码,`adder` 函数的返回值为一个 4 位二进制数,输入参数为两个 4 位二进制数 `a` 和 `b`。函数内部定义了一个 4 位寄存器 `sum`,并通过 for 循环实现了二进制数的加法运算。最后,函数返回计算结果 `sum`。 在 Verilog function 函数可以在模块内部和模块外部使用。在模块内部使用时,可以直接调用函数名称,如: ``` module top; reg [3:0] a, b; wire [3:0] sum; function [3:0] adder (input [3:0] a, b); // 函数操作 endfunction assign sum = adder(a, b); endmodule ``` 在模块外部使用时,需要使用 `extern` 关键字声明函数,并在调用时指定函数名称和参数类型,如: ``` extern function [3:0] adder (input [3:0] a, b); module top; reg [3:0] a, b; wire [3:0] sum; assign sum = adder(a, b); endmodule ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值