芯片人必会的task与function区别详解【Verilog高级教程】

一、写在前面

本专栏为作者在 【数字IC手撕代码】 【数字IC笔试面经分享】 【数字IC工具解析】 以外开设的第四个独立专栏,旨在学习并提供有关Verilog硬件描述语言中非基础性的高阶语法特性知识,因本身专栏的独特定位,因此作者并不会涉及基础Verilog语言如阻塞式非阻塞赋值,过程块,数据类型等内容;同时受限于作者知识有限,本专栏也不会涉及System Verilog的相关内容,若按照IEEE的相关标准来看,本专栏将会聚焦Verilog-2005,即“IEEE Std 1364™-2005”以及之前的有关内容,提供相关的IC设计领域语法特性。以下为Verilog的进阶框图,有更多学习需求的读者可以检索相关英文标准进行学习。
在这里插入图片描述

二、解读task与function

2.1 task与function的区别

简单来说,function有着比task更为严苛的使用条件,严苛在以下几点上
(1) function需要在一个单位仿真时间内完成,而task中可以包含时间控制的命令

因此 “#,@,wait等” 语句都不能出现在function中

(2) function不能调用task但是task可以调用function

(3) function至少需要一个input端口,同时不能出现output和inout端口,task没有这个要求

(4) function需要有返回值,task可以没有返回值

(5) function中不能使用非阻塞赋值

2.2 task的使用细则

2.2.1 task使用格式

task有两种使用格式,但无论是哪一种,task只能存在于module和endmodlue之间。

(1) 以关键字task开始,然后是可选的关键字automatic,然后是使用任务名称和分号,并以关键字endtask结尾.

task [automatic] task_name;
{
    
    task_item_declaration}
  begin
	statement
  end  
endtask

(2) 以关键字task开始,然后是可选的关键字automatic,然后是使用任务名称和端口名称,再紧跟分号,接着类比module端口声明,说明端口input/output等属性,并以关键字endtask结尾.

task [automatic] task_name (task_port_list);
{
    
    block_item_declaration}
  begin
    statement
  end
endtask

2.2.2 task使用实例

task常用于仿真中相似行为的建模,也频繁的出现于作者之前的文章中,相较于数字IC设计时,虽说与面向对象的编程相比(SV与UVM)问题和效率颇低,但是与一个端口一个端口的赋值相比,使用task大大增加了代码的复用率简化了仿真的流程。以下代码摘自作者以往的文章

比如说我们可以按照时序要求写出一个复位的task出来,在仿真需要复位的时候直接进行调用即可

task reset;
begin
	sck = 0;
	rst_n = 1;
	nss = 1;
	@(negedge sck);
	rst_n = 0;
	@(negedge sck);
	rst_n = 1;
	@(negedge sck);
	@(negedge sck);
end
endtask

我们也同样可以写出一个读取数据的task,按照时序要求进行数据的发送任务,调用时只需要r_data(8’h1a)即可依次发送十六进制1a数据

task r_data;
input [7:0] r_data;
begin
	@(negedge sck);
	nss = 0;
  #0.5
	mosi = r_data[7];

	@(negedge sck);
	mosi = r_data[6];

	@(negedge sck);
	mosi = r_data[5];

	@(negedge sck);
	mosi = r_data[4];

	@(negedge sck);
	mosi = r_data[3];

	@(negedge sck);
	mosi = r_data[2];

	@(negedge sck);
	mosi = r_data[1];

	@(negedge sck);
	mosi = r_data[0];
end
endtask

2.3 disable task

disable语句提供了终止task的能力,它可以在task执行前之前终止它,这种特性对于处理硬件中断和全局重置等异常情况非常有用。

以下的例子说明了这种情况,根据输入的条件,我们可以disable掉continue task块或者break task块

begin : break
 for (i = 0; i < n; i = i+1) begin : continue
  @clk
  if (a == 0) // "continue" loop
  disable continue;
  statements
  statements
 @clk
  if (a == b) // "break" from loop
  disable break;
  statements
  statements
 end
end

2.4 function使用细则

function的使用与task相似,以function关键词开始,以endfunction为关键词结尾。我们在计算位宽的系统函数中也提到了fucntion的使用,粘贴如下,有兴趣的读者可以参考以下文章关于Verilog自动计算位宽的系统函数$clog2,这些是你不得不知道的进行学习交流。

function integer clog2(
    input           integer depth
    );
begin
    if(depth == 0)
        clog2 = 1;
    else if(depth != 0)
        for(clog2 = 0; depth > 0;clog2 = clog2 + 1)
            depth = depth >> 1;
end
endfunction

三、其他《Verilog高级教程》文章

猜你喜欢

转载自blog.csdn.net/weixin_43698385/article/details/125119536