天天看點

Verilog初級教程(18)Verilog中的函數與任務

文章目錄

    • 前言
    • 正文
      • 函數
        • 文法
        • 函數聲明
        • 從函數中傳回一個值
        • 函數調用
        • 函數規則
      • 任務
        • 任務調用
        • 全局任務
        • 函數與任務之間的差別
    • 往期回顧
    • 參考資料及推薦關注

函數與任務是仿真中常用的文法,但合理使用也可以在設計中使用,可以綜合。

很多時候我們會發現某些代碼是重複的,在RTL中被多次調用。它們大多不消耗仿真時間,可能涉及複雜的計算,需要用不同的資料值來完成。在這種情況下,我們可以聲明一個函數,将重複的代碼放在函數裡面,讓它傳回結果。這将大大減少RTL中的行數,因為現在你需要做的就是進行函數調用,并傳遞需要在其上進行計算的資料。事實上,這與C語言中的函數非常相似。

函數的目的是傳回一個要在表達式中使用的值。一個函數定義總是以關鍵字

function

開始,後面是

傳回類型

名稱

和用括弧括起來的

端口清單

。當Verilog找到

endfunction

關鍵字時,就知道一個函數定義結束了。注意,一個函數至少要聲明一個輸入,如果函數沒有傳回任何東西,則傳回類型為

void

function [automatic] [return_type] name ([port_list]);
	[statements]
endfunction
           

關鍵字automatic将使函數重入,在任務中聲明的項目被動态配置設定,而不是在任務的不同調用之間共享。這對于遞歸函數,以及當同一個函數在分叉時被N個程序并發執行時,将非常有用。

有兩種方式來聲明函數的輸入。

function [7:0] sum;
	input [7:0] a, b;
	begin
		sum = a + b;
	end
endfunction

function [7:0] sum (input [7:0] a, b);
	begin
		sum = a + b;
	end
endfunction
           

函數定義将隐含地建立一個與函數同名的内部變量。是以,在函數的作用域内聲明另一個同名的變量是非法的。傳回值是通過将函數結果指派給内部變量來初始化的。

sum = a + b;
           

函數調用是一個帶有表達式的操作數,其文法如下圖所示。

reg [7:0] result;
reg [7:0] a, b;

initial begin
	a = 4;
	b = 5;
	#10 result = sum (a, b);
end
           

  • 函數不能包含任何時間控制的語句,如#, @, wait, posedge, negedge
  • 函數不能調用任務,因為它可能會消耗仿真時間,但可以調用其他函數。
  • 函數應該至少有一個輸入
  • 函數不能有非阻塞性的指派或force…release或assign…deassign。
  • 函數不能有任何觸發器
  • 函數不能有output或者inout

函數的作用是對輸入進行一些處理,并傳回一個單一的值,而任務則更為通用,它可以計算出多個結果值,并使用output和inout類型的參數傳回。任務可以包含@、posedge等仿真耗時元素。任務有兩種寫法,我們接下來會看到。

// Style 1
	task [name];
		input  [port_list];
		inout  [port_list];
		output [port_list];
		begin
			[statements]
		end
	endtask

	// Style 2
	task [name] (input [port_list], inout [port_list], output [port_list]);
		begin
			[statements]
		end
	endtask

           

關鍵字automatic将使任務重入,否則它将預設為靜态的。如果一個任務是靜态的,那麼它的所有成員變量将在同一任務的不同調用中被共享,該任務已被啟動為并發運作。注意,auomatic任務項不能通過層次引用來通路。

如果任務不需要任何參數,那麼可以避免使用參數清單。如果任務需要參數,則可以在調用任務時在同一條語句中提供參數。

task sum (input [7:0] a, b, output [7:0] c);
		begin
			c = a + b;
		end
	endtask
// or 	
	task sum;
		input  [7:0] a, b;
		output [7:0] c;
		begin
			c = a + b;
		end
	endtask
	
	
	initial begin
		reg [7:0] x, y , z;
		sum (x, y, z);          
	end

           

任務使能參數(x,y,z)對應于任務定義的參數(a,b,c)。由于a和b是輸入,x和y的值将分别放在a和b中。由于c被聲明為輸出,并且在調用過程中與z連接配接,是以總和将自動從c傳遞到變量z中。

在所有子產品之外聲明的任務稱為全局任務,因為它們具有全局範圍,可以在任何子產品中調用。

// This task is outside all modules
task display();
  $display("Hello World !");
endtask

module des;
  initial begin
    display();
  end
endmodule
           

仿真結果:

Hello World !
           

不能有時間控制語句/延遲,是以在同一仿真時間機關内執行。 可包含時間控制聲明/延遲,且隻能在其他時間完成。
無法啟用任務 可以實作其他任務和功能
至少要有一個輸入,函數不能有output或者inout。 可以有零個或多個任何類型的參數。
隻能傳回一個值 不能傳回一個值,但可以使用輸出參數達到同樣的效果。

Verilog初級教程(17)Verilog中的case語句

Verilog初級教程(16)Verilog中的控制塊

Verilog初級教程(15)Verilog中的阻塞與非阻塞語句

Verilog初級教程(14)Verilog中的指派語句

Verilog初級教程(13)Verilog中的塊語句

Verilog初級教程(12)Verilog中的generate塊

Verilog初級教程(11)Verilog中的initial塊

Verilog初級教程(10)Verilog的always塊

Verilog初級教程(9)Verilog的運算符

Verilog初級教程(8)Verilog中的assign語句

Verilog初級教程(7)Verilog子產品例化以及懸空端口的處理

Verilog初級教程(6)Verilog子產品與端口

Verilog初級教程(5)Verilog中的多元數組和存儲器

Verilog初級教程(4)Verilog中的标量與向量

Verilog初級教程(3)Verilog 資料類型

Verilog初級教程(2)Verilog HDL的初級文法

Verilog初級教程(1)認識 Verilog HDL

晶片設計抽象層及其設計風格

Verilog以及VHDL所倡導的的代碼準則

FPGA/ASIC初學者應該學習Verilog還是VHDL?

Verilog Functions

Verilog Task

繼續閱讀