verilog函数和任务

目录

一、函数

函数在模块中任意位置定义,并在模块内任意位置引用,作用范围也局限于此模块,一般用于组合逻辑的计算。

函数的声明和使用

函数的声明:

复制代码
function [N-1] function_name;
	input d1;
	integer i;
	parameter M=1;
	....
	begin
		...
	end
endfunction

function [N-1] function_name(input d1,....);
	integer i;
	...
	begin
		...
	end
endfunction

函数在声明时会隐式声明宽为N、名字为function_name的寄存器变量,函数返回值通过该变量传递。

函数的调用:

复制代码
...
b=function_name(a);

常数函数

常数函数:仿真开始前在编译期间就计算出结果的函数。

复制代码
function integer logb2;
	input integer depth;
	...
endfunction

automatic函数

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

用 automatic 修饰的函数在调用时是可以自动分配新的内存空间的。

复制代码
function automatic fac;
	....
endfunction

函数的特点

1)不含有任何延迟、时序或时序控制逻辑
2)至少有一个输入变量
3)只有一个返回值,且没有输出
4)不含有非阻塞赋值语句
5)函数可以调用其他函数,但是不能调用任务

二、任务

任务在模块中任意位置定义,并在模块内任意位置引用,作用范围也局限于此模块,用于描述一个过程,可以包含时序逻辑

复制代码
task task_name;
	input [N-1] a;
	output [N-1] b;
	...
endtask

task task_name(input [N-1] a,...);
	...
endtask

任务调用

任务可以单独作为一条语句放在initial或always块中。

复制代码
task_name(a,b,...);

任务调用时端口必须按顺序对应 ,输入端连接的模块内信号可以是 wire 型,也可以是 reg 型。输出端连接的模块内信号要求一定是 reg 型

任务操作全局变量

任务的 output 端信号返回时间是在任务中所有语句执行完毕之后,任务内部变量也只有在任务中可见,如果想具体观察任务中对变量的操作过程,需要将观察的变量声明在模块之内、任务之外。

复制代码
//way1 to decirbe clk generating, not work
task clk_rvs_iner ;
        output    clk_no_rvs ;
        # 5 ;     clk_no_rvs = 0 ;
        # 5 ;     clk_no_rvs = 1 ;
endtask 
reg          clk_test1 ;
always clk_rvs_iner(clk_test1);

//way2: use task to operate global varialbes to generating clk
reg          clk_test2 ;
task clk_rvs_global ;
        # 5 ;     clk_test2 = 0 ;
        # 5 ;     clk_test2 = 1 ;
endtask // clk_rvs_iner
always clk_rvs_global;

第一种描述方式,虽然任务内部变量会有赋值 0 和赋值 1 的过程操作,但中间变化过程并不可见,最后输出的结果只能是任务内所有语句执行完毕后输出端信号的最终值。所以信号 clk_test1 值恒为 1,此种方式产生不了时钟。

第二种描述方式,虽然没有端口信号,但是直接对"全局变量"进行过程操作,因为该全局变量对模块是可见的,所以任务内信号翻转的过程会在信号 clk_test2 中体现出来。

automatic任务

用关键字 automatic 来对任务进行声明,那么任务调用时各存储空间就可以动态分配,每个调用的任务都各自独立的对自己独有的地址空间进行操作,而不影响多个相同任务调用时的并发执行

任务的特点

1)子程序中包含时序控制逻辑,例如延迟,事件控制等
2)没有输入变量
3)没有输出或输出端的数量大于 1

三、任务和函数的区别

比较点 函数 任务
输入 至少有一个输入,端口声明不能包含inout型 可以没有输入,端口声明可以为inout型
输出 没有输出 可用没有或者有多个输出
返回值 至少一个 没有
仿真时刻 总在零时刻就开始执行 可用在非零时刻执行
时序逻辑 不能包含任何时序逻辑 不能出现always语句,但可用包含其它时序控制
调用 函数只能调用函数,不能调用任务 任务可用调用函数和任务
书写 函数不能单独作为一条语句出现,只能放在赋值语句右端 可用单独作为一条语句出现
相关推荐
不脱发的程序猿38 分钟前
如何让Skill同时跑在Cursor、Codex和Claude Code里?
单片机·嵌入式硬件·嵌入式
longxiangam1 小时前
esp-idf dsi 屏幕的驱动实现原理—— 关于零拷贝和 DMA 永续刷新
c语言·单片机·嵌入式硬件
星夜夏空991 小时前
FreeRTOS学习(6)——任务创建
单片机·嵌入式硬件·学习
Lance_mu2 小时前
UFS协议学习大纲
嵌入式硬件·七牛云存储
二进制10112 小时前
基于stm32的按键驱动框架的编写
stm32·单片机·嵌入式硬件
VALENIAN瓦伦尼安教学设备2 小时前
激光对中仪应用行业及全球市场份额解析
大数据·人工智能·嵌入式硬件
coward913 小时前
Linux内核驱动初始化流程认识(关于late_initcall和modul_init驱动初始化宏差异)
linux·嵌入式硬件
ACP广源盛139246256733 小时前
GSV2221@ACP# 高带宽低功耗显示转换芯片,赋能 TRAE SOLO 设备高清扩展升级
人工智能·嵌入式硬件·电脑·音视频
s09071364 小时前
【FPGA实战】基于Verilog的MCP2515 CAN控制器SPI驱动详解 | 附完整代码
fpga开发·硬件设计·can通信·mcp2515
周周记笔记4 小时前
【元器件专题】比较NPN管与PNP管用作开关设计的区别
嵌入式硬件