0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Verilog任務(wù)與函數(shù)的區(qū)別

冬至子 ? 來源:數(shù)字IC與好好生活的兩居室 ? 作者:除夕之夜啊 ? 2023-06-01 16:38 ? 次閱讀

任務(wù)與函數(shù)的區(qū)別

和函數(shù)一樣,任務(wù)(task)可以用來描述共同的代碼段,并在模塊內(nèi)任意位置被調(diào)用,讓代碼更加的直觀易讀。函數(shù)一般用于組合邏輯的各種轉(zhuǎn)換和計(jì)算,而任務(wù)更像一個(gè)過程,不僅能完成函數(shù)的功能,還可以包含時(shí)序控制邏輯。下面對(duì)任務(wù)與函數(shù)的區(qū)別進(jìn)行概括:

1.jpg

任務(wù)

◆任務(wù)聲明

任務(wù)在模塊中任意位置定義,并在模塊內(nèi)任意位置引用,作用范圍也局限于此模塊。

模塊內(nèi)子程序出現(xiàn)下面任意一個(gè)條件時(shí),則必須使用任務(wù)而不能使用函數(shù)。

1)子程序中包含時(shí)序控制邏輯,例如延遲,事件控制等

2)沒有輸入變量

3)沒有輸出或輸出端的數(shù)量大于 1

Verilog 任務(wù)聲明格式如下:

task       task_id ;
       port_declaration ;
       procedural_statement ;
endtask

任務(wù)中使用關(guān)鍵字 input、output 和 inout 對(duì)端口進(jìn)行聲明。input 、inout 型端口將變量從任務(wù)外部傳遞到內(nèi)部,output、inout 型端口將任務(wù)執(zhí)行完畢時(shí)的結(jié)果傳回到外部。

進(jìn)行任務(wù)的邏輯設(shè)計(jì)時(shí),可以把 input 聲明的端口變量看做 wire 型,把 output 聲明的端口變量看做 reg 型。但是不需要用 reg 對(duì) output 端口再次說明。

對(duì) output 信號(hào)賦值時(shí)也不要用關(guān)鍵字 assign。為避免時(shí)序錯(cuò)亂,建議 output 信號(hào)采用阻塞賦值。

例如,一個(gè)帶延時(shí)的異或功能 task 描述如下:

task xor_oper_iner;
    input [N-1:0]   numa;
    input [N-1:0]   numb;
    output [N-1:0]  numco ;
    //output reg [N-1:0]  numco ; //無需再注明 reg 類型,雖然注明也可能沒錯(cuò)
    #3  numco = numa ^ numb ;
    //assign #3 numco = numa ^ numb ; //不用assign,因?yàn)檩敵瞿J(rèn)是reg
endtask

任務(wù)在聲明時(shí),也可以在任務(wù)名后面加一個(gè)括號(hào),將端口聲明包起來。

上述設(shè)計(jì)可以更改為:

task xor_oper_iner(
    input [N-1:0]   numa,
    input [N-1:0]   numb,
    output [N-1:0]  numco  ) ; 
    #3  numco       = numa ^ numb ;
endtask

◆任務(wù)調(diào)用

任務(wù)可單獨(dú)作為一條語句出現(xiàn)在 initial 或 always 塊中,調(diào)用格式如下:

task_id(input1, input2, …,outpu1, output2, …);

任務(wù)調(diào)用時(shí),端口必須按順序?qū)?yīng)。

輸入端連接的模塊內(nèi)信號(hào)可以是 wire 型,也可以是 reg 型。輸出端連接的模塊內(nèi)信號(hào)要求一定是 reg 型,這點(diǎn)需要注意。

對(duì)上述異或功能的 task 進(jìn)行一個(gè)調(diào)用,完成對(duì)異或結(jié)果的緩存。

module xor_oper
    #(parameter         N = 4)
     (
      input             clk ,
      input             rstn ,
      input [N-1:0]     a ,
      input [N-1:0]     b ,
      output [N-1:0]    co  );

    reg [N-1:0]          co_t ;
    always @(*) begin          //任務(wù)調(diào)用
        xor_oper_iner(a, b, co_t);
    end

    reg [N-1:0]          co_r ;
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            co_r   <= 'b0 ;
        end
        else begin
            co_r   <= co_t ;         //數(shù)據(jù)緩存
        end
    end
    assign       co = co_r ;

   /*------------ task -------*/
    task xor_oper_iner;
        input [N-1:0]   numa;
        input [N-1:0]   numb;
        output [N-1:0]  numco ;
        #3  numco       = numa ^ numb ;   //阻塞賦值,易于控制時(shí)序
    endtask

endmodule

◆對(duì)上述設(shè)計(jì)進(jìn)行簡單仿真,testbench 描述如下。

激勵(lì)部分我們使用簡單的 task 進(jìn)行描述,看起來會(huì)更加的清晰簡潔。

其實(shí),task 最多的應(yīng)用場景還是在 testbench 中使用。task 在一些編譯器中也不支持綜合。

`timescale 1ns/1ns

module test ;
    reg          clk, rstn ;

    initial begin
        rstn      = 0 ;
        #8 rstn   = 1 ;
        forever begin
            clk = 0 ; # 5;
            clk = 1 ; # 5;
        end
    end

    reg  [3:0]   a, b;
    wire [3:0]   co ;
    initial begin
        a         = 0 ;
        b         = 0 ;
        sig_input(4'b1111, 4'b1001, a, b);
        sig_input(4'b0110, 4'b1001, a, b);
        sig_input(4'b1000, 4'b1001, a, b);
    end

    task sig_input ;
        input [3:0]       a ;
        input [3:0]       b ;
        output [3:0]      ao ;
        output [3:0]      bo ;
        @(posedge clk) ;
        ao = a ;
        bo = b ;
    endtask ; // sig_input

    xor_oper         u_xor_oper
    (
      .clk              (clk  ),
      .rstn             (rstn ),
      .a                (a    ),
      .b                (b    ),
      .co               (co   ));

    initial begin
        forever begin
            #100;
            if ($time >= 1000)  $finish ;
        end
    end

endmodule

◆仿真結(jié)果如下。

由圖可知,異或輸出邏輯結(jié)果正確,相對(duì)于輸入有 3ns 的延遲。

且連接信號(hào) a,b,co_t 與任務(wù)內(nèi)部定義的信號(hào) numa,numb,numco 狀態(tài)也保持一致。

圖片

任務(wù)操作全局變量

因?yàn)槿蝿?wù)可以看做是過程性賦值,所以任務(wù)的 output 端信號(hào)返回時(shí)間是在任務(wù)中所有語句執(zhí)行完畢之后。

任務(wù)內(nèi)部變量也只有在任務(wù)中可見,如果想具體觀察任務(wù)中對(duì)變量的操作過程,需要將觀察的變量聲明在模塊之內(nèi)、任務(wù)之外,可謂之“全局變量”。

◆例如有以下 2 種嘗試?yán)?task 產(chǎn)生時(shí)鐘的描述方式。

//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;

◆ 仿真結(jié)果如下。

第一種描述方式,雖然任務(wù)內(nèi)部變量會(huì)有賦值 0 和賦值 1 的過程操作,但中間變化過程并不可見,最后輸出的結(jié)果只能是任務(wù)內(nèi)所有語句執(zhí)行完畢后輸出端信號(hào)的最終值。所以信號(hào) clk_test1 值恒為 1,此種方式產(chǎn)生不了時(shí)鐘。

第二種描述方式,雖然沒有端口信號(hào),但是直接對(duì)“全局變量”進(jìn)行過程操作,因?yàn)樵撊肿兞繉?duì)模塊是可見的,所以任務(wù)內(nèi)信號(hào)翻轉(zhuǎn)的過程會(huì)在信號(hào) clk_test2 中體現(xiàn)出來。

圖片

automatic 任務(wù)

和函數(shù)一樣,Verilog 中任務(wù)調(diào)用時(shí)的局部變量都是靜態(tài)的??梢杂藐P(guān)鍵字 automatic 來對(duì)任務(wù)進(jìn)行聲明,那么任務(wù)調(diào)用時(shí)各存儲(chǔ)空間就可以動(dòng)態(tài)分配,每個(gè)調(diào)用的任務(wù)都各自獨(dú)立的對(duì)自己獨(dú)有的地址空間進(jìn)行操作,而不影響多個(gè)相同任務(wù)調(diào)用時(shí)的并發(fā)執(zhí)行。

如果一任務(wù)代碼段被 2 處及以上調(diào)用,一定要用關(guān)鍵字 automatic 聲明。

◆當(dāng)沒有使用 automatic 聲明任務(wù)時(shí),任務(wù)被 2 次調(diào)用,可能出現(xiàn)信號(hào)間干擾,例如下面代碼描述:

task test_flag ;
        input [3:0]       cnti ;
        input             en ;
        output [3:0]      cnto ;
        if (en) cnto = cnti ;
    endtask

    reg          en_cnt ;
    reg [3:0]    cnt_temp ;
    initial begin
        en_cnt    = 1 ;
        cnt_temp  = 0 ;
        #25 ;     en_cnt = 0 ;
    end
    always #10 cnt_temp = cnt_temp + 1 ;

    reg [3:0]             cnt1, cnt2 ;
    always @(posedge clk) test_flag(2, en_cnt, cnt1);       //task(1)
    always @(posedge clk) test_flag(cnt_temp, !en_cnt, cnt2);//task(2)

◆ 仿真結(jié)果如下。

en_cnt 為高時(shí),任務(wù) (1) 中信號(hào) en 有效, cnt1 能輸出正確的邏輯值;

此時(shí)任務(wù) (2) 中信號(hào) en 是不使能的,所以 cnt2 的值被任務(wù) (1) 驅(qū)動(dòng)的共用變量 cnt_temp 覆蓋。

en_cnt 為低時(shí),任務(wù) (2) 中信號(hào) en 有效,所以任務(wù) (2) 中的信號(hào) cnt2 能輸出正確的邏輯值;而此時(shí)信號(hào) cnt1 的值在時(shí)鐘的驅(qū)動(dòng)下,一次次被任務(wù) (2) 驅(qū)動(dòng)的共用變量 cnt_temp 覆蓋。

可見,任務(wù)在兩次并發(fā)調(diào)用中,共用存儲(chǔ)空間,導(dǎo)致信號(hào)間產(chǎn)生了影響。

圖片

◆其他描述不變,只在上述 task 聲明時(shí)加入關(guān)鍵字 automatic,如下所示。

task automatic test_flag ;

◆此時(shí)仿真結(jié)果如下。

en_cnt 為高時(shí),任務(wù) (1) 中信號(hào) cnt1 能輸出正確的邏輯值,任務(wù) (2) 中信號(hào) cnt2 的值為 X;

en_cnt 為低時(shí),任務(wù) (2) 中信號(hào) cnt2 能輸出正確的邏輯值,任務(wù) (1) 中信號(hào) cnt1 的值為 X;

可見,任務(wù)在兩次并發(fā)調(diào)用中,因?yàn)榇鎯?chǔ)空間相互獨(dú)立,信號(hào)間并沒有產(chǎn)生影響。

圖片

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Verilog
    +關(guān)注

    關(guān)注

    28

    文章

    1335

    瀏覽量

    109844
  • 時(shí)序控制器
    +關(guān)注

    關(guān)注

    0

    文章

    17

    瀏覽量

    11202
  • CLK
    CLK
    +關(guān)注

    關(guān)注

    0

    文章

    126

    瀏覽量

    17089
  • 時(shí)鐘驅(qū)動(dòng)器

    關(guān)注

    0

    文章

    32

    瀏覽量

    13804
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Verilog系統(tǒng)任務(wù)的相關(guān)資料推薦

    Verilog數(shù)字系統(tǒng)設(shè)計(jì)十任務(wù)函數(shù)實(shí)驗(yàn)2文章目錄Verilog數(shù)字系統(tǒng)設(shè)計(jì)十前言一、Verilog系統(tǒng)
    發(fā)表于 02-09 06:05

    任務(wù)函數(shù)區(qū)別?

    Verilog數(shù)字系統(tǒng)設(shè)計(jì)九任務(wù)函數(shù)實(shí)驗(yàn)1文章目錄Verilog數(shù)字系統(tǒng)設(shè)計(jì)九前言一、任務(wù)函數(shù)
    發(fā)表于 02-09 07:47

    FreeRTOS任務(wù)應(yīng)用函數(shù)介紹

    任務(wù)應(yīng)用函數(shù)是一組輔助類函數(shù),一般用于調(diào)試信息輸出、獲取任務(wù)句柄、獲取任務(wù)狀態(tài)、操作任務(wù)標(biāo)簽值等
    的頭像 發(fā)表于 03-19 10:22 ?2495次閱讀

    Verilog HDL語言中任務(wù)函數(shù)的比較

    其中,返回值的類型和位寬是可選項(xiàng),如果缺省會(huì)返回一位寄存器類型數(shù)據(jù)。Verilog HDL認(rèn)為函數(shù)的定義隱式地聲明了與函數(shù)同名的寄存器。函數(shù)的定義把
    的頭像 發(fā)表于 07-02 10:24 ?2229次閱讀

    Verilog數(shù)字系統(tǒng)設(shè)計(jì)——任務(wù)函數(shù)二(系統(tǒng)任務(wù)readmemb或readmemh)

    Verilog數(shù)字系統(tǒng)設(shè)計(jì)十任務(wù)函數(shù)實(shí)驗(yàn)2文章目錄Verilog數(shù)字系統(tǒng)設(shè)計(jì)十前言一、Verilog系統(tǒng)
    發(fā)表于 12-05 19:06 ?7次下載
    <b class='flag-5'>Verilog</b>數(shù)字系統(tǒng)設(shè)計(jì)——<b class='flag-5'>任務(wù)</b>和<b class='flag-5'>函數(shù)</b>二(系統(tǒng)<b class='flag-5'>任務(wù)</b>readmemb或readmemh)

    Verilog數(shù)字系統(tǒng)設(shè)計(jì)——任務(wù)函數(shù)一(斐波那契數(shù)列)

    Verilog數(shù)字系統(tǒng)設(shè)計(jì)九任務(wù)函數(shù)實(shí)驗(yàn)1文章目錄Verilog數(shù)字系統(tǒng)設(shè)計(jì)九前言一、任務(wù)函數(shù)
    發(fā)表于 12-05 19:06 ?9次下載
    <b class='flag-5'>Verilog</b>數(shù)字系統(tǒng)設(shè)計(jì)——<b class='flag-5'>任務(wù)</b>和<b class='flag-5'>函數(shù)</b>一(斐波那契數(shù)列)

    Verilog設(shè)計(jì)中函數(shù)任務(wù)的作用分析

    任務(wù)函數(shù)Verilog中用于描述常用的功能行為。與其在不同的地方復(fù)制相同的代碼,不如根據(jù)需求使用函數(shù)任務(wù),這是一種良好且常見的做法。為
    的頭像 發(fā)表于 03-15 11:01 ?1669次閱讀

    Verilog系統(tǒng)函數(shù)和邊沿檢測

    “ 本文主要分享了在Verilog設(shè)計(jì)過程中一些經(jīng)驗(yàn)與知識(shí)點(diǎn),主要包括Verilog仿真時(shí)常用的系統(tǒng)任務(wù)、雙向端口的使用(inout)、邊沿檢測”
    的頭像 發(fā)表于 03-15 13:34 ?2202次閱讀

    Verilog中關(guān)于文件操作的系統(tǒng)任務(wù)

    Verilog提供了很多對(duì)文件操作的系統(tǒng)任務(wù)函數(shù),例如打開關(guān)閉文件、向文件寫入值、從文件讀出值等等。
    的頭像 發(fā)表于 12-05 13:57 ?1444次閱讀

    FreeRTOS任務(wù)通知通用發(fā)送函數(shù)

    發(fā)送任務(wù)通知 任務(wù)通知通用發(fā)送函數(shù) 任務(wù)級(jí)任務(wù)通知發(fā)送函數(shù):xTaskNotify()、xTas
    的頭像 發(fā)表于 07-30 11:43 ?680次閱讀
    FreeRTOS<b class='flag-5'>任務(wù)</b>通知通用發(fā)送<b class='flag-5'>函數(shù)</b>

    verilog函數(shù)任務(wù)對(duì)比

    verilog中,函數(shù)任務(wù)均用來描述共同的代碼段,并且在模式內(nèi)任意位置被調(diào)用,提高代碼效率,讓代碼更加的直觀,提高代碼可讀性。但是在實(shí)際使用的過程中,函數(shù)
    的頭像 發(fā)表于 02-12 18:43 ?796次閱讀

    verilog同步和異步的區(qū)別 verilog阻塞賦值和非阻塞賦值的區(qū)別

    Verilog中同步和異步的區(qū)別,以及阻塞賦值和非阻塞賦值的區(qū)別。 一、Verilog中同步和異步的區(qū)別 同步傳輸和異步傳輸是指數(shù)據(jù)在電路中
    的頭像 發(fā)表于 02-22 15:33 ?1312次閱讀

    verilog中function和task的區(qū)別

    非常相似,但它們在功能和使用方式上有一些重要的區(qū)別。 定義和聲明方式不同: Function:使用關(guān)鍵字"function"來定義和聲明。函數(shù)可以有一個(gè)或多個(gè)輸入?yún)?shù),可以有一個(gè)返回值。函數(shù)必須在聲明之后直接定義,不能在其他
    的頭像 發(fā)表于 02-22 15:40 ?1553次閱讀

    verilog function函數(shù)的用法

    Verilog 是一種硬件描述語言 (HDL),主要用于描述數(shù)字電子電路的行為和結(jié)構(gòu)。在 Verilog 中,函數(shù) (Function) 是一種用于執(zhí)行特定任務(wù)并返回一個(gè)值的可重用代碼
    的頭像 發(fā)表于 02-22 15:49 ?4447次閱讀

    verilog task和function區(qū)別

    verilog中的task和function都是用于實(shí)現(xiàn)模塊中的可重復(fù)的功能,并且可以接收參數(shù)和返回結(jié)果。但是它們在編寫和使用上有一些區(qū)別。下面將詳細(xì)介紹task和function的區(qū)別。 語法結(jié)構(gòu)
    的頭像 發(fā)表于 02-22 15:53 ?885次閱讀