systemverilog中的函數function和任務task


在verilog中,任務task和函數function之間有明顯的區別,例如任務可以消耗時間而函數不能,函數里面不能帶有諸如#100的時延語句或諸如@(posedge clock)、wait(ready)的阻塞語句,也不能調用任務,還有verilog中的函數必須有返回值,並且返回值必須被使用,例如用到賦值語句中。
關於verilog中任務task和函數function的具體用法和區別參考我寫過的一篇文章;
verilog中的任務task和函數function用法及區別

systemveilog中函數和任務的使用方法如下:
1、一般情況下,不帶參數的子程序在定義或調用時不需要帶空括號();
2、begin...end為可選的,因為task...endtask和function...endfunction關鍵詞足以定義這些程序的邊界, 但是在verilog-1995中,除了單行以外的子程序是必須的;
3、可以采用簡明的c語言風格,缺省的類型和方向是logic input;但是在verilog中,對參數要進行兩次聲明,一次是方向聲明,一次是類型聲明;

//systemverilog風格
task test(a, b, output bit [15:0] c, d);
//其中a,b為input logic a,b; c,d為output bit [15:0];
//verilog風格
task test2;
	output [31:0] x;
	reg 	[31:0] x;
	input y;
endtask

4、可以在參數列表中指定輸入參數(input),輸出參數(output)、輸入輸出參數(inout)或引用參數(ref);只有數組變量可以在形式參數列表中聲明為ref類型,而線網類型不能聲明為ref類型;在使用ref時,有時候為了保護數據對象不被寫入,可以同通過const方式來限定ref聲明的參數
systemverilog中ref的具體用法可以參考我寫的一篇文章:systemverilog中ref的用法
但是在verilog中,對參數的處理方式很簡單,在子程序的開頭把input或inout的值復制給本地變量,在子程序退出時,則復制output或inout的值。除了標量以外,沒有任何把存儲器傳遞給verilog子程序的方法;
5、數組可以作為形式參數傳遞;
6、可以為參數指定一個缺省值,如果在調用時不指明參數,則使用缺省值。

function void print_checksum(ref bit [31:0] a[], input bit [31:0] low, input int high = -1);
	bit [31:0] checksum = 0;
	if(high = -1 || high >= a.size())
		high = a.size() - 1;
	for(int i = low, i < high; i++)
		checksum += a[i];
	$display("The array checksum is %0d", checksum);
endfunction
print_checksum(a);			//a[0:size()-1]中所有元素的校驗和---缺省情況
print_checksum(a, 2, 4);	//a[2:4]中所有元素的校驗和
print_checksum(a, 1);		//a[1;$]中所有元素的校驗和
print_checksum(a,,2)		//a[0:2]中所有元素的校驗和

7、采用名字進行參數傳遞;

task many(input int a = 1, b = 2; c = 3, d = 4);
	$display("%0d %0d %0d %0d", a, b, c, d);
endtask
initial begin
	many(6, 7, 8, 9);	//a b c d的值分別為 6 7 8 9
	many();				//a b c d全部使用默認值
	many(.c(8));		//c的值為8,其他全部用默認值
	many(,6, , d(8));	// 1 6 3 8混合指定方式
end

8、需要注意的其他問題:

task sticky(ref int array[10], int a, b);

上述a和b參數類型會采用與前一個參數一致的ref類型,對簡單的int變量使用ref並無必要,但編譯器不會對此做出任何反應,可能連警告都沒有,這是使用了一個錯誤的方向類型。
如果你在子程序中使用了非缺省輸入類型的參數,應該明確指明所有參數的方向,如下所示:

task sticky(ref int array[10], input int a, b);

function的獨特使用規則如下:
1、可以返回數值或不返回數值,如果返回需要使用關鍵詞return,如果不返回,則應該聲明函數為void function;
2、在systemveilog中,允許函數調用任務,但是只能在由fork...join_none語句生成的線程中調用。

void函數如下;

function void print_state();
	$display("@%0t: time = %s", $time);
endfunction

3、function中可以使用return得到函數的返回值,不使用return時,與函數名字相同的變量的值就是返回值。

function bit tranmit();		
	//其他語句
	return ~ifc.cb.error;
endfunction

4、從函數返回一個數組有兩種方法:
第一中方法是定義一個數組類型,然后在函數的聲明中使用該類型。

typedef int fixed_array5[5];
fixed_array5 f5;
function fixed_array5 init(int start);
	foreach(init[i])
		init[i] = i + start;
endfunction
initial begin
	f5 = init(5);
	foreach(f5[i[)
		$display("fd[%0d] = %0d", i, f5[i]);
end

上述代碼存在的問題是,函數init創建了一個數組,給數組的值被復制到數組f5中。如果數組很大,那么可能會引起一個性能上的問題。
第二種方法是通過引用來進行數組參數的傳遞。

function void init(ref int f[5], input int start);
	foreach(f[i])
		f[i] = i + start;
endfunction
int fa[5];
initial begin
	init(fa, 5);
	foreach(fa[i]
		$display("fa[%0d] = %0d", i, fa[i]);
end

從函數中返回數組的最后一種方式是將數組包裝到一個類中,然后返回對象的句柄。

task的獨特使用規則如下:
1、task無法通過return返回結果,因此只能通過output, inout或者ref參數來返回;
2、任務中可以使用return,提前返回;

task load_array(int len, ref int array[]);
	if(len < 0) begin
		$display("bad len");
		return;
	//其他代碼
endtask

3、task可以內置耗時語句,而function不能。常見的耗時語句包括@event, wait event, #delay等。

task和function的選擇建議:
1、在不耗時定義為function,在內置耗時語句時使用task;function一般用於純粹的數字或邏輯運算,task可能被運用於需要耗時的信號采樣或者驅動場景;
2、function可以被function和task調用,內置有耗時語句的task只能由task來調用;

關於task和function使用的例題:

typedef struct {
	bit [1:0] cmd;
	bit [7:0] addr;
	bit [31:0] data;
} trans;

function automatic void cp_copy(trans s, trans t);
	t = s;
endfunction

initial beign
	trans s, t;
	s.cmd = 'h1;
	s.addr = 'h10;
	s.data = 'h100;
	op_copy(t, s);
	t.cmd = 'h2;
end
//result
t.cmd = 'h2;
t.addr = 'h0;
t.data = 'h0;

task的調用方法:

logic red;
parameter red_tics = 100;
always begin //控制燈光
    red = on; //打開紅燈
    light(red,red_tics) ; //等待end
//等待‘tics’時鍾上升沿的任務
//在關掉‘color’燈之前
task light (output color,input [31:0] tics) ;
    repeat (tics)@ (posedge clock);
    color = off;//關燈
endtask: light


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM