Verilog之function使用说明


1.function的定义

<span style="font-size:14px;">function [range] function_name; 
    input_declaration 
    other_declarations 
    procedural_statement 
endfunction</span>
(1)函数通过关键词 function 和 endfunction 定义;

(2)不允许输出端口声明(包括输出和双向端口) ;但可以有多个输入端口;

(3)[range]参数指定函数返回值的类型或位宽,是一个可选项,若没有指定,默认缺省值为宽度 1 比特的寄存器数据

(4)function_name为所定义函数的名称,对函数的调用也是通过函数名完成的,并在函数结构体内部代表一个内部变函数调用的返回值就是通过函数名变量传递给调用语句。函数定义在函数内部会隐式定义一个寄存器变量,该寄存器变量和函数同名并且位宽也一致。函数通过在函数定义中对该寄存器的显式赋值来返回函数计算结果

(5)input_declaration 为各个输入端口的位宽和类型进行说明,在函数定义中至少要有一个输入端口


注意事项:

(1)函数定义只能在模块中完成,不能出现在过程块中;

(2)函数至少要有一个输入端口;不能包含输出端口和双向端口;

(3) 在函数结构中, 不能使用任何形式的时间控制语句 (#、 wait 等) , 也不能使用 disable中止语句;

(4)函数定义结构体中不能出现过程块语句(always 语句);

(5)函数内部可以调用函数,但不能调用任务

2.函数的调用

    func_name(expr1, expr2, ........., exprN),

    expr1, expr2, ......exprN是传递给函数的输入参数列表,该输入参数列表的顺序必须与函数定义时声明其输入的顺序相同.


  在函数调用中,有下列几点需要注意: 
  (1)函数调用可以在过程块中完成,也可以在 assign 这样的连续赋值语句中出现。 
  (2)函数调用语句不能单独作为一条语句出现,只能作为赋值语句的右端操作数

     如果task或者function在不同地方并发调用,则它们使用同一组变量个内存地址,存在冲突产生错误。为避免错误,声明时在task和function后面加上automatic 关键字。如:task automatic task_id ........ endtask

调用例子:

在过程语句always模块内调用,

`timescale 1ns / 100ps


module lfsr (clk, ena, nReset, rst, q);

	//
	// parameters
	//
	parameter [3:0] TAPS   = 8;                // number of flip-flops in LFSR

	//
	// inputs & outputs
	//
	input clk;                                 // master clock
	input ena;                                 // clock enable
	input nReset;                              // asynchronous active low reset
	input rst;                                 // synchronous active high reset

	output [TAPS:1] q;                         // LFSR output
	reg [TAPS:1] q;

	//
	// Module body
	//
	function lsb;
	   input [TAPS-1:0] q;

	   case (TAPS)
	       2: lsb = ~q[0];
	       3: lsb = q[3] ^ q[2];
	       4: lsb = q[4] ^ q[3];
	       5: lsb = q[5] ^ q[3];
	       6: lsb = q[6] ^ q[5];
	       7: lsb = q[7] ^ q[6];
	       8: lsb = q[8] ^ q[6] ^ q[5] ^ q[4];
	       9: lsb = q[9] ^ q[5];
	      10: lsb = q[10] ^ q[7];
	      11: lsb = q[11] ^ q[9];
	      12: lsb = q[12] ^ q[6] ^ q[4] ^ q[1];
	      13: lsb = q[13] ^ q[4] ^ q[3] ^ q[1];
	      14: lsb = q[14] ^ q[5] ^ q[3] ^ q[1];
	      15: lsb = q[15] ^ q[14];
	      16: lsb = q[16] ^ q[15] ^ q[13] ^ q[4];
	   endcase
	endfunction

	always @(posedge clk or negedge nReset)
	  if (~nReset)	q <= #1 0;
	  else if (rst)	q <= #1 0;
	  else if (ena)	q <= #1 {q[TAPS-1:1], lsb(q)};
endmodule



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值