(原創)task和function語法的使用討論(Verilog,CPLD/FPGA)


1. Abstract

  function和task語句的功能有很多的相似之處,在需要有多個相同的電路生成時,可以考慮使用它們來實現。因為個人使用它們比較少,所以對它們沒有進行更深的了解,現在時間比較充裕,我想通過寫幾個簡單的電路將它們二者的功能進行驗證一下,看看究竟是怎么生成電路的。

2. Contents

    主要為測試function和task各自生成的電路,所以電路設計功能比較簡單——4位BCD碼轉換成4位余3碼。

    文件開頭的注釋說明。

/* --------------------------------------- 
    Module Name:         temp 
    Module Function:    將4位BCD碼轉換成為余3碼,無效狀態為4'b0000 
    Module Input:         4-bit data_in 
    Module Output:      4-bit data_out 
    Module Reference:    None 
    Note:                  碼表如下 
######################################## 
          data_in        data_out    
    0      4'b0000        4'b0011 
    1      4'b0001        4'b0100    
    2      4'b0010        4'b0101    
    3      4'b0011        4'b0110 
    4      4'b0100        4'b0111 
    5      4'b0101        4'b1000 
    6      4'b0110        4'b1001 
    7      4'b0111        4'b1010 
    8      4'b1000        4'b1011 
    9      4'b1001        4'b1100 
    10      4'b1010        4'b0000        無效 
    11      4'b1011        4'b0000        無效 
    12      4'b1100        4'b0000        無效 
    13      4'b1101        4'b0000        無效 
    14      4'b1110        4'b0000        無效 
    15      4'b1111        4'b0000        無效 
   ---------------------------------------*/

    2.1 直接使用組合邏輯電路生成BCD碼轉余3碼。

module temp(data_in,data_out); 

output reg [3:0] data_out; 
input [3:0] data_in; 

always @(data_in) 
begin 
    if(data_in >=  4'd10) data_out = 4'b0000; 
    else  data_out = data_in + 4'd3; 
end 

endmodule

    用RTL視圖查看一下生成出來的網表

imageFIG2.1 直接用組合邏輯生成的邏輯圖

    生成出來的電路由加法器、比較器和選擇器構成,輸入數據data_in + 3作為選擇器的選擇控制,下面做一下驗證測試。

image FIG2.2 測試仿真驗證

    2.2 用task語句編寫組合電路

module temp(data_in,data_out); 

output reg [3:0] data_out; 
input [3:0] data_in; 

always @(data_in) 
begin 
    if(data_in >=  4'd10) data_out = 4'b0000; 
    else  BCD2Access3(data_out,data_in); 
end 

task BCD2Access3; 
output [3:0] data_out; 
input [3:0] data_in; 

    data_out = data_in + 4'd3; 
endtask 
endmodule

     用RTL視圖查看一下最后生成的網表。

imageFIG2.3 使用task語句生成出的邏輯圖

    仔細對比,FIG2.3和FIG2.1是一模一樣的,也就是說采用task語句可以生成預期的邏輯圖,非常成功!既然生成出的邏輯圖都是一樣的,測試部分在此就省略了吧,和FIG2.2應該是一樣的。

2.3 用function語句編寫組合邏輯

module temp(data_in,data_out); 

output reg [3:0] data_out; 
input [3:0] data_in; 

always @(data_in) 
begin 
    if(data_in >=  4'd10) data_out = 4'b0000; 
    else  data_out = BCD2Access3(data_in); 
end 

function [3:0] BCD2Access3; 
input [3:0] data_in; 

BCD2Access3 = data_in + 4'd3; 
endfunction 
endmodule

    用RTL視圖查看一下最后生成出來的網表。

image FIG2.4 使用function語句生成出的邏輯圖

    相信已經很熟悉這個邏輯圖了,與前面的FIG2.1一模一樣,也就是說使用function語句也是可以生成預期的電路的,而且也是非常成功的!既然邏輯圖都是與前面一致的,故測試部分……也省去了吧。

   小結一下,用function和task語句都可以生成預期的邏輯電路,不過,查查語法書,可以知道task語句的適用性更廣泛一點,更符合邏輯思維的習慣;function最大的好處就是可以有一個返回值,運算以后結果可以直接返回供調用的塊使用。

  在組合邏輯設計的過程中,寫成可綜合的電路可以達到預期的生成電路邏輯,那么在時序邏輯設計中,function和task語句又會生成出怎樣的電路呢?還是以這一個電路功能為模板,值得注意的是,得額外加一個時鍾信號。

2.4 直接使用時序邏輯編寫的BCD碼轉余3碼。

module temp(data_in,data_out,clk); 

output reg [3:0] data_out; 
input [3:0] data_in; 
input clk; 

always @(posedge clk) 
begin 
    if(data_in >=  4'd10) data_out = 4'b0000; 
    else  data_out <= data_in + 3'd3; 
end 

endmodule

    用RTL視圖來看下生成出來的邏輯網表。

imageFIG2.5 直接用時序邏輯編寫生成的邏輯網表

    和上面生成的邏輯網表相比,多了一個鎖存器,這也是典型的時序邏輯的特征,數據的變化只在clk的上升沿才有效。下面來做一下電路邏輯的驗證。

image FIG2.6 時序邏輯網表的驗證

    圖確實有點小,可能看起來有點不方便,但邏輯的功能是正確的,每到clk的上升沿,數據更新一次,譯碼是正確的,為了方便看,再截取一部分出來吧,作為一個局部放大圖。

image FIG2.7 時序邏輯驗證的局部放大圖

    直接用時序邏輯設計成功了,再嘗試着用task語句和function語句實現,看看最后的效果會怎么樣。

2.5 時序邏輯下使用task語句實現電路

module temp(data_in,data_out,clk); 

output reg [3:0] data_out; 
input [3:0] data_in; 
input clk; 

always @(posedge clk) 
begin 
    if(data_in >=  4'd10) data_out = 4'b0000; 
    else  BCD2Access3(data_out,data_in); 
end 

task BCD2Access3; 
output [3:0] data_out; 
input [3:0] data_in; 

    data_out = data_in + 4'd3; 
endtask 

endmodule

    用RTL視圖來看一下生成的邏輯網表。

imageFIG2.8 使用task語句生成的邏輯網表

     同樣,仔細對照一下,發現FIG2.8和FIG2.6是一樣的,也就是說在時序邏輯中使用task語句也是可以實現預期的電路的,非常的成功!和上述討論的一樣,既然邏輯圖相同的話,驗證的部分就略去了吧。

2.6 時序邏輯下用function語句實現電路

module temp(data_in,data_out,clk); 

output reg [3:0] data_out; 
input [3:0] data_in; 
input clk; 

always @(posedge clk) 
begin 
    if(data_in >=  4'd10) data_out = 4'b0000; 
    else  data_out <= BCD2Access3(data_in); 
end 

function [3:0] BCD2Access3; 
input [3:0] data_in; 

BCD2Access3 = data_in + 4'd3; 
endfunction 

endmodule

    跟上面一樣,用RTL視圖來看看最后生成出來的電路。

image FIG2.9 時序邏輯下使用function語句生成的邏輯網表

    仔細對比,會發現跟如上的邏輯網表一樣,也就是說在時序邏輯下使用function語句也是可以實現預期的電路的,非常的成功!邏輯網表一致的話,在此邏輯的驗證容我略去吧。

    小結一下,在時序邏輯的電路設計中,也可以使用task語句和function語句來實現電路。

    在學習過程中,也不斷的在看語法書,畢竟這一塊是我不太熟悉的地方,現在將它們使用的一些要點整理出來,對如何使用和最后生成怎樣的很有參考幫助。

task語句要點 

(1)若用於任務中的命名變量或參數沒有在任務塊中聲明,則指的是在模塊中聲明的命名變量或參數。

(2)任務中的input,output和inout的個數不受限制(也可以為0個)。(任務可以沒有參數)

(3)任務中的變量(包括輸入(input)和雙向端口(inout))可以聲明為寄存器型。如果沒有明確地聲明,則默認為寄存器類型,且其位寬與相應的變量匹配。

(4)當啟動任務時,相應於任務的輸入和雙向端口(inout)的變量表達式的值被存入相應的變量寄存器中。當任務結束時,輸入和雙向端口(inout)的變量寄存器中的值又被代入啟動任務的語句中相應的表達式。

電路綜合參考:包含時序控制語句的任務是不可綜合的。啟動的任務往往被綜合成組合邏輯。 

function語句要點

(1)函數必須至少有一個輸入變量,不能有任何輸出或輸入/輸出雙向變量(output 和inout類型)。

(2)函數不能包含時間控制語句(如延遲#、事件控制@或者等待wait)。

(3)函數是通過對函數名賦值的途徑返回其值的,就好比是一個寄存器。

(4)函數不能啟動任務。

(5)函數不能被禁用。(特指應用於編寫測試文件)

    電路綜合參考:函數的每一次調用都被綜合為一個獨立的組合邏輯電路塊。

 

3.Conclusion

    總體來說,task的功能更加符合硬件邏輯設計的習慣,而且語法中對它的限制比較少。而且它們最終生成的電路都是組合邏輯,所以在需要產生多個相同的模塊時,可以采用由它們構成。

4.Platform

  Quartus II 9.1 Build 222 Full Version

5.Reference

[1] Verilog 數字系統設計教程(第2版) 夏宇聞

[2] Advanced Digital Design with the Verilog HDL (Second Edition) Michael D.Ciletti


免責聲明!

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



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