日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Verilog HDL的基本語(yǔ)法(一)

 春華_秋實(shí) 2012-05-24
 
 

Verilog HDL的基本語(yǔ)法(一)  

2010-03-12 23:27:37|  分類: Verilog |  標(biāo)簽: |字號(hào) 訂閱

 Verilog HDL的基本語(yǔ)法

 

前言

 

Verilog HDL是一種用于數(shù)字邏輯電路設(shè)計(jì)的語(yǔ)言。用Verilog HDL描述的電路設(shè)計(jì)就是該電路的Verilog HDL模型。Verilog HDL既是一種行為描述的語(yǔ)言也是一種結(jié)構(gòu)描述的語(yǔ)言。這也就是說(shuō),既可以用電路的功能描述也可以用元器件和它們之間的連接來(lái)建立所設(shè)計(jì)電路的Verilog HDL模型。Verilog模型可以是實(shí)際電路的不同級(jí)別的抽象。這些抽象的級(jí)別和它們對(duì)應(yīng)的模型類型共有以下五種:

 

  • 系統(tǒng)級(jí)(system):用高級(jí)語(yǔ)言結(jié)構(gòu)實(shí)現(xiàn)設(shè)計(jì)模塊的外部性能的模型。
  • 算法級(jí)(algorithm):用高級(jí)語(yǔ)言結(jié)構(gòu)實(shí)現(xiàn)設(shè)計(jì)算法的模型。
  • RTL級(jí)(Register Transfer Level):描述數(shù)據(jù)在寄存器之間流動(dòng)和如何處理這些數(shù)據(jù)的模型。
  • 門(mén)級(jí)(gate-level):描述邏輯門(mén)以及邏輯門(mén)之間的連接的模型。
  • 開(kāi)關(guān)級(jí)(switch-level):描述器件中三極管和儲(chǔ)存節(jié)點(diǎn)以及它們之間連接的模型。

   

一個(gè)復(fù)雜電路系統(tǒng)的完整Verilog HDL模型是由若干個(gè)Verilog HDL模塊構(gòu)成的,每一個(gè)模塊又可以由若干個(gè)子模塊構(gòu)成。其中有些模塊需要綜合成具體電路,而有些模塊只是與用戶所設(shè)計(jì)的模塊交互的現(xiàn)存電路或激勵(lì)信號(hào)源。利用Verilog HDL語(yǔ)言結(jié)構(gòu)所提供的這種功能就可以構(gòu)造一個(gè)模塊間的清晰層次結(jié)構(gòu)來(lái)描述極其復(fù)雜的大型設(shè)計(jì),并對(duì)所作設(shè)計(jì)的邏輯電路進(jìn)行嚴(yán)格的驗(yàn)證。

 

Verilog HDL行為描述語(yǔ)言作為一種結(jié)構(gòu)化和過(guò)程性的語(yǔ)言,其語(yǔ)法結(jié)構(gòu)非常適合于算法級(jí)和RTL級(jí)的模型設(shè)計(jì)。這種行為描述語(yǔ)言具有以下功能:

 

·         可描述順序執(zhí)行或并行執(zhí)行的程序結(jié)構(gòu)。

·         用延遲表達(dá)式或事件表達(dá)式來(lái)明確地控制過(guò)程的啟動(dòng)時(shí)間。

·         通過(guò)命名的事件來(lái)觸發(fā)其它過(guò)程里的激活行為或停止行為。

·         提供了條件、if-else、case、循環(huán)程序結(jié)構(gòu)。

·         提供了可帶參數(shù)且非零延續(xù)時(shí)間的任務(wù)(task)程序結(jié)構(gòu)。

·         提供了可定義新的操作符的函數(shù)結(jié)構(gòu)(function)。

·         提供了用于建立表達(dá)式的算術(shù)運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算符。

·         Verilog HDL語(yǔ)言作為一種結(jié)構(gòu)化的語(yǔ)言也非常適合于門(mén)級(jí)和開(kāi)關(guān)級(jí)的模型設(shè)計(jì)。因其結(jié)構(gòu)化的特點(diǎn)又使它具有以下功能:

                           -                         提供了完整的一套組合型原語(yǔ)(primitive);

                           -                         提供了雙向通路和電阻器件的原語(yǔ);

                           -                         可建立MOS器件的電荷分享和電荷衰減動(dòng)態(tài)模型。

                                 Verilog HDL的構(gòu)造性語(yǔ)句可以精確地建立信號(hào)的模型。這是因?yàn)樵赩erilog HDL中,提供了延遲和輸出強(qiáng)度的原語(yǔ)來(lái)建立精確程度很高的信號(hào)模型。信號(hào)值可以有不同的的強(qiáng)度,可以通過(guò)設(shè)定寬范圍的模糊值來(lái)降低不確定條件的影響。

                                  

Verilog HDL作為一種高級(jí)的硬件描述編程語(yǔ)言,有著類似C語(yǔ)言的風(fēng)格。其中有許多語(yǔ)句如:if語(yǔ)句、case語(yǔ)句等和C語(yǔ)言中的對(duì)應(yīng)語(yǔ)句十分相似。如果讀者已經(jīng)掌握C語(yǔ)言編程的基礎(chǔ),那么學(xué)習(xí)Verilog HDL并不困難,我們只要對(duì)Verilog HDL某些語(yǔ)句的特殊方面著重理解,并加強(qiáng)上機(jī)練習(xí)就能很好地掌握它,利用它的強(qiáng)大功能來(lái)設(shè)計(jì)復(fù)雜的數(shù)字邏輯電路。下面我們將對(duì)Verilog HDL中的基本語(yǔ)法逐一加以介紹。

 

 

3.1.簡(jiǎn)單的Verilog HDL模塊

 

3.1.1.簡(jiǎn)單的Verilog HDL程序介紹

下面先介紹幾個(gè)簡(jiǎn)單的Verilog HDL程序,然后從中分析Verilog HDL程序的特性。

 

例[3.1.1]:module  adder ( count,sum,a,b,cin );

input [2:0] a,b;

input   cin;

output  count;

output [2:0] sum;

assign {count,sum} = a + b + cin;

endmodule

 

這個(gè)例子通過(guò)連續(xù)賦值語(yǔ)句描述了一個(gè)名為adder的三位加法器可以根據(jù)兩個(gè)三比特?cái)?shù)a、b和進(jìn)位(cin)計(jì)算出和(sum)和進(jìn)位(count)。 從例子中可以看出整個(gè)Verilog HDL程序是嵌套在module和 endmodule 聲明語(yǔ)句里的。

 

例[3.1.2]:module compare ( equal,a,b );

output  equal;    //聲明輸出信號(hào)equal

input [1:0] a,b;  //聲明輸入信號(hào)a,b

  assign  equal=(a==b)?1:0;

/*如果a、b 兩個(gè)輸入信號(hào)相等,輸出為1。否則為0*/

endmodule

 

這個(gè)程序通過(guò)連續(xù)賦值語(yǔ)句描述了一個(gè)名為compare的比較器。對(duì)兩比特?cái)?shù) a、b 進(jìn)行比較,如a與b相等,則輸出equal為高電平,否則為低電平。在這個(gè)程序中,/*........*/和//.........表示注釋部分,注釋只是為了方便程序員理解程序,對(duì)編譯是不起作用的。

 

例[3.1.3]:module  trist2(out,in,enable);

output  out;

input   in, enable;

  bufif1  mybuf(out,in,enable);

endmodule

 

這個(gè)程序描述了一個(gè)名為trist2的三態(tài)驅(qū)動(dòng)器。程序通過(guò)調(diào)用一個(gè)在Verilog語(yǔ)言庫(kù)中現(xiàn)存的三態(tài)驅(qū)動(dòng)器實(shí)例元件bufif1來(lái)實(shí)現(xiàn)其功能。

 

例[3.1.4]: module trist1(out,in,enable);

output  out;

input  in, enable;

   mytri  tri_inst(out,in,enable);

    //調(diào)用由mytri模塊定義的實(shí)例元件tri_inst

endmodule

 

module  mytri(out,in,enable);

output  out;

input  in, enable;

   assign  out = enable? in : 'bz;

endmodule

 

這個(gè)程序例子通過(guò)另一種方法描述了一個(gè)三態(tài)門(mén)。在這個(gè)例子中存在著兩個(gè)模塊。模塊trist1調(diào)用由模塊mytri定義的實(shí)例元件tri_inst。模塊trist1是頂層模塊。模塊mytri則被稱為子模塊。

 

    通過(guò)上面的例子可以看到:

·                        Verilog HDL程序是由模塊構(gòu)成的。每個(gè)模塊的內(nèi)容都是嵌在module和endmodule兩個(gè)語(yǔ)句之間。每個(gè)模塊實(shí)現(xiàn)特定的功能。模塊是可以進(jìn)行層次嵌套的。正因?yàn)槿绱?才可以將大型的數(shù)字電路設(shè)計(jì)分割成不同的小模塊來(lái)實(shí)現(xiàn)特定的功能,最后通過(guò)頂層模塊調(diào)用子模塊來(lái)實(shí)現(xiàn)整體功能。

·                        每個(gè)模塊要進(jìn)行端口定義,并說(shuō)明輸入輸出口,然后對(duì)模塊的功能進(jìn)行行為邏輯描述。

·                        Verilog HDL程序的書(shū)寫(xiě)格式自由,一行可以寫(xiě)幾個(gè)語(yǔ)句,一個(gè)語(yǔ)句也可以分寫(xiě)多行。

·                        除了endmodule語(yǔ)句外,每個(gè)語(yǔ)句和數(shù)據(jù)定義的最后必須有分號(hào)。

·                        可以用/*.....*/和//.......對(duì)Verilog HDL程序的任何部分作注釋。一個(gè)好的,有使用價(jià)值的源程序都應(yīng)當(dāng)加上必要的注釋,以增強(qiáng)程序的可讀性和可維護(hù)性。

 

 

3.1.2.模塊的結(jié)構(gòu)

 

Verilog的基本設(shè)計(jì)單元是“模塊”(block)。一個(gè)模塊是由兩部分組成的,一部分描述接口,另一部分描述邏輯功能,即定義輸入是如何影響輸出的。下面舉例說(shuō)明:

 

 

請(qǐng)看上面的例子,程序模塊旁邊有一個(gè)電路圖的符號(hào)。在許多方面,程序模塊和電路圖符號(hào)是一致的,這是因?yàn)殡娐穲D符號(hào)的引腳也就是程序模塊的接口。而程序模塊描述了電路圖符號(hào)所實(shí)現(xiàn)的邏輯功能。上面的Verilog設(shè)計(jì)中,模塊中的第二、第三行說(shuō)明接口的信號(hào)流向,第四、第五行說(shuō)明了模塊的邏輯功能。以上就是設(shè)計(jì)一個(gè)簡(jiǎn)單的Verilog程序模塊所需的全部?jī)?nèi)容。

 

從上面的例子可以看出,Verilog結(jié)構(gòu)完全嵌在module和endmodule聲明語(yǔ)句之間,每個(gè)Verilog程序包括四個(gè)主要部分:端口定義、I/O說(shuō)明、內(nèi)部信號(hào)聲明、功能定義。

 

3.1.3.模塊的端口定義

 

模塊的端口聲明了模塊的輸入輸出口。其格式如下:

 

module    模塊名(口1,口2,口3,口4, ………);

 

3.1.4.模塊內(nèi)容

 

模塊的內(nèi)容包括I/O說(shuō)明、內(nèi)部信號(hào)聲明、功能定義。

 

  I/O說(shuō)明的格式如下:

輸入口:    input  端口名1,端口名2,………,端口名i;   //(共有i個(gè)輸入口)

輸出口:    output 端口名1,端口名2,………,端口名j;   //(共有j個(gè)輸出口)

I/O說(shuō)明也可以寫(xiě)在端口聲明語(yǔ)句里。其格式如下:

module  module_name(input port1,input port2,

output port1,output port2 );

  內(nèi)部信號(hào)說(shuō)明:在模塊內(nèi)用到的和與端口有關(guān)的wire 和 reg  變量的聲明。

如: reg [width-1 : 0] R變量1,R變量2 。。。。;

    wire [width-1 : 0] W變量1,W變量2 。。。。;

    ………..

  功能定義: 模塊中最重要的部分是邏輯功能定義部分。有三種方法可在模塊中產(chǎn)生邏輯。

1).用“assign”聲明語(yǔ)句

如: assign  a = b & c;

這種方法的句法很簡(jiǎn)單,只需寫(xiě)一個(gè)“assign”,后面再加一個(gè)方程式即可。例子中的方程式描述了一個(gè)有兩個(gè)輸入的與門(mén)。

2).用實(shí)例元件

如: and  and_inst( q, a, b );

采用實(shí)例元件的方法象在電路圖輸入方式下,調(diào)入庫(kù)元件一樣。鍵入元件的名字和相連的引腳即可,表示在設(shè)計(jì)中用到一個(gè)跟與門(mén)(and)一樣的名為and_inst的與門(mén),其輸入端為a, b,輸出為q。要求每個(gè)實(shí)例元件的名字必須是唯一的,以避免與其他調(diào)用與門(mén)(and)的實(shí)例混淆。

3).用“always”塊

如:always @(posedge clk or posedge clr)

begin

if(clr)  q <= 0;

else  if(en) q <= d;

end

 

采用“assign”語(yǔ)句是描述組合邏輯最常用的方法之一。而“always”塊既可用于描述組合邏輯也可描述時(shí)序邏輯。上面的例子用“always”塊生成了一個(gè)帶有異步清除端的D觸發(fā)器。“always”塊可用很多種描述手段來(lái)表達(dá)邏輯,例如上例中就用了if...else語(yǔ)句來(lái)表達(dá)邏輯關(guān)系。如按一定的風(fēng)格來(lái)編寫(xiě)“always”塊,可以通過(guò)綜合工具把源代碼自動(dòng)綜合成用門(mén)級(jí)結(jié)構(gòu)表示的組合或時(shí)序邏輯電路。

 

注意:

如果用Verilog模塊實(shí)現(xiàn)一定的功能,首先應(yīng)該清楚哪些是同時(shí)發(fā)生的,哪些是順序發(fā)生的。上面三個(gè)例子分別采用了“assign”語(yǔ)句、實(shí)例元件和“always”塊。這三個(gè)例子描述的邏輯功能是同時(shí)執(zhí)行的。也就是說(shuō),如果把這三項(xiàng)寫(xiě)到一個(gè) VeriIog 模塊文件中去,它們的次序不會(huì)影響邏輯實(shí)現(xiàn)的功能。這三項(xiàng)是同時(shí)執(zhí)行的,也就是并發(fā)的。

 

然而,在“always”模塊內(nèi),邏輯是按照指定的順序執(zhí)行的?!癮lways”塊中的語(yǔ)句稱為“順序語(yǔ)句”,因?yàn)樗鼈兪琼樞驁?zhí)行的。請(qǐng)注意,兩個(gè)或更多的“always”模塊也是同時(shí)執(zhí)行的,但是模塊內(nèi)部的語(yǔ)句是順序執(zhí)行的??匆幌隆癮lways”內(nèi)的語(yǔ)句,你就會(huì)明白它是如何實(shí)現(xiàn)功能的。  if..else… if必須順序執(zhí)行,否則其功能就沒(méi)有任何意義。如果else語(yǔ)句在if語(yǔ)句之前執(zhí)行,功能就會(huì)不符合要求!為了能實(shí)現(xiàn)上述描述的功能,“always”模塊內(nèi)部的語(yǔ)句將按照書(shū)寫(xiě)的順序執(zhí)行。

 

 

3.2.數(shù)據(jù)類型及其常量、變量

 

Verilog HDL中總共有十九種數(shù)據(jù)類型,數(shù)據(jù)類型是用來(lái)表示數(shù)字電路硬件中的數(shù)據(jù)儲(chǔ)存和傳送元素的。在本教材中我們先只介紹四個(gè)最基本的數(shù)據(jù)類型,它們是:

reg型、wire型、integer型、parameter型

其它數(shù)據(jù)類型在后面的章節(jié)里逐步介紹,同學(xué)們也可以查閱附錄中Verilog HDL語(yǔ)法參考書(shū)的有關(guān)章節(jié)逐步掌握。其它的類型如下:

large型、medium型、scalared型、time型、small型、tri型、trio型、tri1型、triand型、trior型、trireg型、vectored型、wand型、wor型。這些數(shù)據(jù)類型除time型外都與基本邏輯單元建庫(kù)有關(guān),與系統(tǒng)設(shè)計(jì)沒(méi)有很大的關(guān)系。在一般電路設(shè)計(jì)自動(dòng)化的環(huán)境下,仿真用的基本部件庫(kù)是由半導(dǎo)體廠家和EDA工具廠家共同提供的。系統(tǒng)設(shè)計(jì)工程師不必過(guò)多地關(guān)心門(mén)級(jí)和開(kāi)關(guān)級(jí)的Verilog HDL語(yǔ)法現(xiàn)象。

 

Verilog HDL語(yǔ)言中也有常量和變量之分。它們分別屬于以上這些類型。下面就最常用的幾種進(jìn)行介紹。

 

 

3.2.1.常量

 

在程序運(yùn)行過(guò)程中,其值不能被改變的量稱為常量。下面首先對(duì)在Verilog HDL語(yǔ)言中使用的數(shù)字及其表示方式進(jìn)行介紹。

 

一.?dāng)?shù)字

 

  整數(shù):

在Verilog HDL中,整型常量即整常數(shù)有以下四種進(jìn)制表示形式:

1)   二進(jìn)制整數(shù)(b或B)

2)   十進(jìn)制整數(shù)(d或D)

3)   十六進(jìn)制整數(shù)(h或H)

4)   八進(jìn)制整數(shù)(o或O)

數(shù)字表達(dá)方式有以下三種:

1)   <位寬><進(jìn)制><數(shù)字>這是一種全面的描述方式。

2)   <進(jìn)制><數(shù)字>在這種描述方式中,數(shù)字的位寬采用缺省位寬(這由具體的機(jī)器系統(tǒng)決定,但至少32位)。

3)   <數(shù)字>在這種描述方式中,采用缺省進(jìn)制十進(jìn)制。

 

在表達(dá)式中,位寬指明了數(shù)字的精確位數(shù)。例如:一個(gè)4位二進(jìn)制數(shù)的數(shù)字的位寬為4,一個(gè)4位十六進(jìn)制數(shù)的數(shù)字的位寬為16(因?yàn)槊繂蝹€(gè)十六進(jìn)制數(shù)就要用4位二進(jìn)制數(shù)來(lái)表示)。見(jiàn)下例:

8'b10101100  //位寬為8的數(shù)的二進(jìn)制表示, 'b表示二進(jìn)制

8'ha2        //位寬為8的數(shù)的十六進(jìn)制,'h表示十六進(jìn)制。

 

  x和z值:

在數(shù)字電路中,x代表不定值,z代表高阻值。一個(gè)x可以用來(lái)定義十六進(jìn)制數(shù)的四位二進(jìn)制數(shù)的狀態(tài),八進(jìn)制數(shù)的三位,二進(jìn)制數(shù)的一位。z的表示方式同x類似。z還有一種表達(dá)方式是可以寫(xiě)作?。在使用case表達(dá)式時(shí)建議使用這種寫(xiě)法,以提高程序的可讀性。見(jiàn)下例:

4'b10x0  //位寬為4的二進(jìn)制數(shù)從低位數(shù)起第二位為不定值

4'b101z  //位寬為4的二進(jìn)制數(shù)從低位數(shù)起第一位為高阻值

12'dz    //位寬為12的十進(jìn)制數(shù)其值為高阻值(第一種表達(dá)方式)

12'd?    //位寬為12的十進(jìn)制數(shù)其值為高阻值(第二種表達(dá)方式)

8'h4x    //位寬為8的十六進(jìn)制數(shù)其低四位值為不定值

 

  負(fù)數(shù):

一個(gè)數(shù)字可以被定義為負(fù)數(shù),只需在位寬表達(dá)式前加一個(gè)減號(hào),減號(hào)必須寫(xiě)在數(shù)字定義表達(dá)式的最前面。注意減號(hào)不可以放在位寬和進(jìn)制之間也不可以放在進(jìn)制和具體的數(shù)之間。見(jiàn)下例:

-8'd5   //這個(gè)表達(dá)式代表5的補(bǔ)數(shù)(用八位二進(jìn)制數(shù)表示)

8'd-5   //非法格式

 

  下劃線(underscore_):

下劃線可以用來(lái)分隔開(kāi)數(shù)的表達(dá)以提高程序可讀性。但不可以用在位寬和進(jìn)制處,只能用在具體的數(shù)字之間。見(jiàn)下例:

16'b1010_1011_1111_1010         //合法格式

8'b_0011_1010            //非法格式

當(dāng)常量不說(shuō)明位數(shù)時(shí),默認(rèn)值是32位,每個(gè)字母用8位的ASCII值表示。

例:

10=32’d10=32’b1010

1=32’d1=32’b1

-1=-32’d1=32’hFFFFFFFF

‘BX=32’BX=32’BXXXXXXX…X

“AB”=16’B01000001_01000010

 

二.參數(shù)(Parameter)型

在Verilog HDL中用parameter來(lái)定義常量,即用parameter來(lái)定義一個(gè)標(biāo)識(shí)符代表一個(gè)常量,稱為符號(hào)常量,即標(biāo)識(shí)符形式的常量,采用標(biāo)識(shí)符代表一個(gè)常量可提高程序的可讀性和可維護(hù)性。parameter型數(shù)據(jù)是一種常數(shù)型的數(shù)據(jù),其說(shuō)明格式如下:

 

parameter 參數(shù)名1=表達(dá)式,參數(shù)名2=表達(dá)式, , 參數(shù)名n=表達(dá)式;

 

parameter是參數(shù)型數(shù)據(jù)的確認(rèn)符,確認(rèn)符后跟著一個(gè)用逗號(hào)分隔開(kāi)的賦值語(yǔ)句表。在每一個(gè)賦值語(yǔ)句的右邊必須是一個(gè)常數(shù)表達(dá)式。也就是說(shuō),該表達(dá)式只能包含數(shù)字或先前已定義過(guò)的參數(shù)。見(jiàn)下列:

parameter  msb=7;       //定義參數(shù)msb為常量7

parameter  e=25, f=29;  //定義二個(gè)常數(shù)參數(shù)

parameter  r=5.7;       //聲明r為一個(gè)實(shí)型參數(shù)

parameter  byte_size=8, byte_msb=byte_size-1; //用常數(shù)表達(dá)式賦值

parameter  average_delay = (r+f)/2;           //用常數(shù)表達(dá)式賦值

 

參數(shù)型常數(shù)經(jīng)常用于定義延遲時(shí)間和變量寬度。在模塊或?qū)嵗脮r(shí)可通過(guò)參數(shù)傳遞改變?cè)诒灰媚K或?qū)嵗幸讯x的參數(shù)。下面將通過(guò)兩個(gè)例子進(jìn)一步說(shuō)明在層次調(diào)用的電路中改變參數(shù)常用的一些用法。

 

[例1]:在引用Decode實(shí)例時(shí),D1,D2的Width將采用不同的值4和5,且D1的Polarity將為0??捎美又兴玫姆椒▉?lái)改變參數(shù),即用 #(4,0)向D1中傳遞 Width=4,Polarity=0; 用#(5)向D2中傳遞Width=5,Polarity仍為1。

 

module Decode(A,F);

parameter  Width=1, Polarity=1;

……………

endmodule

module  Top;

wire[3:0] A4;

wire[4:0] A5;

wire[15:0] F16;

wire[31:0] F32;

Decode  #(4,0)  D1(A4,F16);

Decode  #(5)    D2(A5,F32);

Endmodule

 

[例2]:下面是一個(gè)多層次模塊構(gòu)成的電路,在一個(gè)模塊中改變另一個(gè)模塊的參數(shù)時(shí),需要使用defparam命令

 

 

 

 

3.2.2 變量

 

變量即在程序運(yùn)行過(guò)程中其值可以改變的量,在Verilog HDL中變量的數(shù)據(jù)類型有很多種,這里只對(duì)常用的幾種進(jìn)行介紹。

 

網(wǎng)絡(luò)數(shù)據(jù)類型表示結(jié)構(gòu)實(shí)體(例如門(mén))之間的物理連接。網(wǎng)絡(luò)類型的變量不能儲(chǔ)存值,而且它必需受到驅(qū)動(dòng)器(例如門(mén)或連續(xù)賦值語(yǔ)句,assign)的驅(qū)動(dòng)。如果沒(méi)有驅(qū)動(dòng)器連接到網(wǎng)絡(luò)類型的變量上,則該變量就是高阻的,即其值為z。常用的網(wǎng)絡(luò)數(shù)據(jù)類型包括wire型和tri型。這兩種變量都是用于連接器件單元,它們具有相同的語(yǔ)法格式和功能。之所以提供這兩種名字來(lái)表達(dá)相同的概念是為了與模型中所使用的變量的實(shí)際情況相一致。wire型變量通常是用來(lái)表示單個(gè)門(mén)驅(qū)動(dòng)或連續(xù)賦值語(yǔ)句驅(qū)動(dòng)的網(wǎng)絡(luò)型數(shù)據(jù),tri型變量則用來(lái)表示多驅(qū)動(dòng)器驅(qū)動(dòng)的網(wǎng)絡(luò)型數(shù)據(jù)。如果wire型或tri型變量沒(méi)有定義邏輯強(qiáng)度(logic strength),在多驅(qū)動(dòng)源的情況下,邏輯值會(huì)發(fā)生沖突從而產(chǎn)生不確定值。下表為wire型和tri型變量的真值表(注意:這里假設(shè)兩個(gè)驅(qū)動(dòng)源的強(qiáng)度是一致的,關(guān)于邏輯強(qiáng)度建模請(qǐng)參閱附錄:Verilog語(yǔ)言參考書(shū))。

 

wire/tri

0

1

x

z

0

0

x

x

0

1

x

1

x

1

x

x

x

x

x

z

0

1

x

z

 

一. wire型

wire型數(shù)據(jù)常用來(lái)表示用于以assign關(guān)鍵字指定的組合邏輯信號(hào)。Verilog程序模塊中輸入輸出信號(hào)類型缺省時(shí)自動(dòng)定義為wire型。wire型信號(hào)可以用作任何方程式的輸入,也可以用作“assign”語(yǔ)句或?qū)嵗妮敵觥?/P>

 

wire型信號(hào)的格式同reg型信號(hào)的很類似。其格式如下:

 

wire [n-1:0] 數(shù)據(jù)名1,數(shù)據(jù)名2,數(shù)據(jù)名i; //共有i條總線,每條總線內(nèi)有n條線路 

wire [n:1] 數(shù)據(jù)名1,數(shù)據(jù)名2,數(shù)據(jù)名i;  

 

wire是wire型數(shù)據(jù)的確認(rèn)符,[n-1:0]和[n:1]代表該數(shù)據(jù)的位寬,即該數(shù)據(jù)有幾位。最后跟著的是數(shù)據(jù)的名字。如果一次定義多個(gè)數(shù)據(jù),數(shù)據(jù)名之間用逗號(hào)隔開(kāi)。聲明語(yǔ)句的最后要用分號(hào)表示語(yǔ)句結(jié)束。看下面的幾個(gè)例子。

 

wire  a;          //定義了一個(gè)一位的wire型數(shù)據(jù)

wire [7:0] b;     //定義了一個(gè)八位的wire型數(shù)據(jù)

wire [4:1] c, d;  //定義了二個(gè)四位的wire型數(shù)據(jù)

 

二. reg型

寄存器是數(shù)據(jù)儲(chǔ)存單元的抽象。寄存器數(shù)據(jù)類型的關(guān)鍵字是reg.通過(guò)賦值語(yǔ)句可以改變寄存器儲(chǔ)存的值,其作用與改變觸發(fā)器儲(chǔ)存的值相當(dāng)。Verilog HDL語(yǔ)言提供了功能強(qiáng)大的結(jié)構(gòu)語(yǔ)句使設(shè)計(jì)者能有效地控制是否執(zhí)行這些賦值語(yǔ)句。這些控制結(jié)構(gòu)用來(lái)描述硬件觸發(fā)條件,例如時(shí)鐘的上升沿和多路器的選通信號(hào)。在行為模塊介紹這一節(jié)中我們還要詳細(xì)地介紹這些控制結(jié)構(gòu)。reg類型數(shù)據(jù)的缺省初始值為不定值,x。

 

reg型數(shù)據(jù)常用來(lái)表示用于“always”模塊內(nèi)的指定信號(hào),常代表觸發(fā)器。通常,在設(shè)計(jì)中要由“always”塊通過(guò)使用行為描述語(yǔ)句來(lái)表達(dá)邏輯關(guān)系。always塊內(nèi)被賦值的每一個(gè)信號(hào)都必須定義成reg型。

 

reg型數(shù)據(jù)的格式如下:

 

reg [n-1:0] 數(shù)據(jù)名1,數(shù)據(jù)名2, 數(shù)據(jù)名i;

reg [n:1]   數(shù)據(jù)名1,數(shù)據(jù)名2, 數(shù)據(jù)名i;

 

reg是reg型數(shù)據(jù)的確認(rèn)標(biāo)識(shí)符,[n-1:0]和[n:1]代表該數(shù)據(jù)的位寬,即該數(shù)據(jù)有幾位(bit)。最后跟著的是數(shù)據(jù)的名字。如果一次定義多個(gè)數(shù)據(jù),數(shù)據(jù)名之間用逗號(hào)隔開(kāi)。聲明語(yǔ)句的最后要用分號(hào)表示語(yǔ)句結(jié)束。看下面的幾個(gè)例子:

 

reg  rega;           //定義了一個(gè)一位的名為rega的reg型數(shù)據(jù)

reg [3:0]  regb;     //定義了一個(gè)四位的名為regb的reg型數(shù)據(jù)

reg [4:1]  regc, regd; //定義了兩個(gè)四位的名為regc和regd的reg型數(shù)據(jù)

 

對(duì)于reg型數(shù)據(jù),其賦值語(yǔ)句的作用就象改變一組觸發(fā)器的存儲(chǔ)單元的值。在Verilog中有許多構(gòu)造(construct)用來(lái)控制何時(shí)或是否執(zhí)行這些賦值語(yǔ)句。這些控制構(gòu)造可用來(lái)描述硬件觸發(fā)器的各種具體情況,如觸發(fā)條件用時(shí)鐘的上升沿等,或用來(lái)描述具體判斷邏輯的細(xì)節(jié),如各種多路選擇器。reg型數(shù)據(jù)的缺省初始值是不定值。reg型數(shù)據(jù)可以賦正值,也可以賦負(fù)值。但當(dāng)一個(gè)reg型數(shù)據(jù)是一個(gè)表達(dá)式中的操作數(shù)時(shí),它的值被當(dāng)作是無(wú)符號(hào)值,即正值。例如:當(dāng)一個(gè)四位的寄存器用作表達(dá)式中的操作數(shù)時(shí),如果開(kāi)始寄存器被賦以值-1,則在表達(dá)式中進(jìn)行運(yùn)算時(shí),其值被認(rèn)為是+15。

 

注意:

reg型只表示被定義的信號(hào)將用在always塊內(nèi),理解這一點(diǎn)很重要。并不是說(shuō)reg型信號(hào)一定是寄存器或觸發(fā)器的輸出。雖然reg型信號(hào)常常是寄存器或觸發(fā)器的輸出,但并不一定總是這樣。在本書(shū)中我們還會(huì)對(duì)這一點(diǎn)作更詳細(xì)的解釋。

 

三. memory型

 

Verilog HDL通過(guò)對(duì)reg型變量建立數(shù)組來(lái)對(duì)存儲(chǔ)器建模,可以描述RAM型存儲(chǔ)器,ROM存儲(chǔ)器和reg文件。數(shù)組中的每一個(gè)單元通過(guò)一個(gè)數(shù)組索引進(jìn)行尋址。在Verilog語(yǔ)言中沒(méi)有多維數(shù)組存在。 memory型數(shù)據(jù)是通過(guò)擴(kuò)展reg型數(shù)據(jù)的地址范圍來(lái)生成的。其格式如下:

 

reg [n-1:0] 存儲(chǔ)器名[m-1:0];

或  reg [n-1:0] 存儲(chǔ)器名[m:1];

 

在這里,reg[n-1:0]定義了存儲(chǔ)器中每一個(gè)存儲(chǔ)單元的大小,即該存儲(chǔ)單元是一個(gè)n位的寄存器。存儲(chǔ)器名后的[m-1:0]或[m:1]則定義了該存儲(chǔ)器中有多少個(gè)這樣的寄存器。最后用分號(hào)結(jié)束定義語(yǔ)句。下面舉例說(shuō)明:

 

reg [7:0]  mema[255:0];

 

這個(gè)例子定義了一個(gè)名為mema的存儲(chǔ)器,該存儲(chǔ)器有256個(gè)8位的存儲(chǔ)器。該存儲(chǔ)器的地址范圍是0到255。注意:對(duì)存儲(chǔ)器進(jìn)行地址索引的表達(dá)式必須是常數(shù)表達(dá)式。

 

另外,在同一個(gè)數(shù)據(jù)類型聲明語(yǔ)句里,可以同時(shí)定義存儲(chǔ)器型數(shù)據(jù)和reg型數(shù)據(jù)。見(jiàn)下例:

 

parameter  wordsize=16,     //定義二個(gè)參數(shù)。

memsize=256;

reg [wordsize-1:0] mem[memsize-1:0],writereg, readreg;

 

盡管memory型數(shù)據(jù)和reg型數(shù)據(jù)的定義格式很相似,但要注意其不同之處。如一個(gè)由n個(gè)1位寄存器構(gòu)成的存儲(chǔ)器組是不同于一個(gè)n位的寄存器的。見(jiàn)下例:

 

reg [n-1:0] rega;     //一個(gè)n位的寄存器

reg mema [n-1:0];     //一個(gè)由n個(gè)1位寄存器構(gòu)成的存儲(chǔ)器組

 

一個(gè)n位的寄存器可以在一條賦值語(yǔ)句里進(jìn)行賦值,而一個(gè)完整的存儲(chǔ)器則不行。見(jiàn)下例:

 

rega =0;    //合法賦值語(yǔ)句

mema =0;    //非法賦值語(yǔ)句

 

如果想對(duì)memory中的存儲(chǔ)單元進(jìn)行讀寫(xiě)操作,必須指定該單元在存儲(chǔ)器中的地址。下面的寫(xiě)法是正確的。

mema[3]=0;  //給memory中的第3個(gè)存儲(chǔ)單元賦值為0。

 

進(jìn)行尋址的地址索引可以是表達(dá)式,這樣就可以對(duì)存儲(chǔ)器中的不同單元進(jìn)行操作。表達(dá)式的值可以取決于電路中其它的寄存器的值。例如可以用一個(gè)加法計(jì)數(shù)器來(lái)做RAM的地址索引。本小節(jié)里只對(duì)以上幾種常用的數(shù)據(jù)類型和常數(shù)進(jìn)行了介紹,其余的在以后的章節(jié)的示例中用到之處再逐一介紹。有興趣的同學(xué)可以參閱附錄:Verilog語(yǔ)言參考書(shū)

 

 

3.3. 運(yùn)算符及表達(dá)式

Verilog HDL語(yǔ)言的運(yùn)算符范圍很廣,其運(yùn)算符按其功能可分為以下幾類:

 

1)   算術(shù)運(yùn)算符(+,-,×,/,%)

2)   賦值運(yùn)算符(=,<=)

3)   關(guān)系運(yùn)算符(>,<,>=,<=)

4)   邏輯運(yùn)算符(&&,||,!)

5)   條件運(yùn)算符(?:)

6)   位運(yùn)算符(~,|,^,&,^~)

7)   移位運(yùn)算符(<<,>>)

8)   拼接運(yùn)算符({ })

9)   其它

 

在Verilog HDL語(yǔ)言中運(yùn)算符所帶的操作數(shù)是不同的,按其所帶操作數(shù)的個(gè)數(shù)運(yùn)算符可分為三種:

 

1)   單目運(yùn)算符(unary operator):可以帶一個(gè)操作數(shù),操作數(shù)放在運(yùn)算符的右邊。

2)   二目運(yùn)算符(binary operator):可以帶二個(gè)操作數(shù),操作數(shù)放在運(yùn)算符的兩邊。

3)   三目運(yùn)算符(ternary operator):可以帶三個(gè)操作,這三個(gè)操作數(shù)用三目運(yùn)算符分隔開(kāi)。

見(jiàn)下例:

clock = ~clock;      // ~是一個(gè)單目取反運(yùn)算符, clock是操作數(shù)。

c = a | b;           // 是一個(gè)二目按位或運(yùn)算符, a 和 b是操作數(shù)。

r = s ? t : u;       // ?: 是一個(gè)三目條件運(yùn)算符, s,t,u是操作數(shù)。

 

下面對(duì)常用的幾種運(yùn)算符進(jìn)行介紹。

 

3.3.1.基本的算術(shù)運(yùn)算符

在Verilog HDL語(yǔ)言中,算術(shù)運(yùn)算符又稱為二進(jìn)制運(yùn)算符,共有下面幾種:

1)   + (加法運(yùn)算符,或正值運(yùn)算符,如 rega+regb,+3)

2)   - (減法運(yùn)算符,或負(fù)值運(yùn)算符,如 rega-3,-3)

3)   × (乘法運(yùn)算符,如rega*3)

4)   / (除法運(yùn)算符,如5/3)

5)   % (模運(yùn)算符,或稱為求余運(yùn)算符,要求%兩側(cè)均為整型數(shù)據(jù)。如7%3的值為1)

 

在進(jìn)行整數(shù)除法運(yùn)算時(shí),結(jié)果值要略去小數(shù)部分,只取整數(shù)部分。而進(jìn)行取模運(yùn)算時(shí),結(jié)果值的符號(hào)位采用模運(yùn)算式里第一個(gè)操作數(shù)的符號(hào)位。見(jiàn)下例。

模運(yùn)算表達(dá)式  結(jié)果        說(shuō)明

10%3      1      余數(shù)為1

11%3      2      余數(shù)為2

12%3      0      余數(shù)為0即無(wú)余數(shù)

-10%3     -1      結(jié)果取第一個(gè)操作數(shù)的符號(hào)位,所以余數(shù)為-1

11%3      2      結(jié)果取第一個(gè)操作數(shù)的符號(hào)位,所以余數(shù)為2.

 

注意: 在進(jìn)行算術(shù)運(yùn)算操作時(shí),如果某一個(gè)操作數(shù)有不確定的值x,則整個(gè)結(jié)果也為不定值x。

 

3.3.2.位運(yùn)算符

 

Verilog HDL作為一種硬件描述語(yǔ)言,是針對(duì)硬件電路而言的。在硬件電路中信號(hào)有四種狀態(tài)值1,0,x,z.在電路中信號(hào)進(jìn)行與或非時(shí),反映在Verilog HDL中則是相應(yīng)的操作數(shù)的位運(yùn)算。Verilog HDL提供了以下五種位運(yùn)算符:

 

1)   ~           //取反

2)   &           //按位與

3)   |           //按位或

4)   ^           //按位異或

5)   ^~          //按位同或(異或非)

 

說(shuō)明:

·         位運(yùn)算符中除了~是單目運(yùn)算符以外,均為二目運(yùn)算符,即要求運(yùn)算符兩側(cè)各有一個(gè)操作數(shù).

·         位運(yùn)算符中的二目運(yùn)算符要求對(duì)兩個(gè)操作數(shù)的相應(yīng)位進(jìn)行運(yùn)算操作。

 

下面對(duì)各運(yùn)算符分別進(jìn)行介紹:

 

1)  "取反"運(yùn)算符~

~是一個(gè)單目運(yùn)算符,用來(lái)對(duì)一個(gè)操作數(shù)進(jìn)行按位取反運(yùn)算。

其運(yùn)算規(guī)則見(jiàn)下表:

 

~

 

1

0

0

1

x

x

 

舉例說(shuō)明:

rega='b1010;//rega的初值為'b1010

rega=~rega;//rega的值進(jìn)行取反運(yùn)算后變?yōu)?b0101

 

2)  "按位與"運(yùn)算符&

按位與運(yùn)算就是將兩個(gè)操作數(shù)的相應(yīng)位進(jìn)行與運(yùn)算,

其運(yùn)算規(guī)則見(jiàn)下表:

 

&

0

1

x

0

0

0

0

1

0

1

x

x

0

x

x

 

3)  "按位或"運(yùn)算符|

按位或運(yùn)算就是將兩個(gè)操作數(shù)的相應(yīng)位進(jìn)行或運(yùn)算。

其運(yùn)算規(guī)則見(jiàn)下表:

|

0

1

x

0

0

1

x

1

1

1

1

x

x

1

x

 

4)  "按位異或"運(yùn)算符^(也稱之為XOR運(yùn)算符)

按位異或運(yùn)算就是將兩個(gè)操作數(shù)的相應(yīng)位進(jìn)行異或運(yùn)算。

其運(yùn)算規(guī)則見(jiàn)下表:

^

0

1

x

0

0

1

x

1

1

0

x

x

x

x

x

 

5)  "按位同或"運(yùn)算符^~

按位同或運(yùn)算就是將兩個(gè)操作數(shù)的相應(yīng)位先進(jìn)行異或運(yùn)算再進(jìn)行非運(yùn)算.

其運(yùn)算規(guī)則見(jiàn)下表:

^~

0

1

x

0

1

0

x

1

0

1

x

x

x

x

x

 

6)  不同長(zhǎng)度的數(shù)據(jù)進(jìn)行位運(yùn)算

兩個(gè)長(zhǎng)度不同的數(shù)據(jù)進(jìn)行位運(yùn)算時(shí),系統(tǒng)會(huì)自動(dòng)的將兩者按右端對(duì)齊.位數(shù)少的操作數(shù)會(huì)在相應(yīng)的高位用0填滿,以使兩個(gè)操作數(shù)按位進(jìn)行操作.

 

 

3.3.3 邏輯運(yùn)算符

 

在Verilog HDL語(yǔ)言中存在三種邏輯運(yùn)算符:

1)   && 邏輯與

2)   || 邏輯或

3)   !  邏輯非

 

"&&"和"||"是二目運(yùn)算符,它要求有兩個(gè)操作數(shù),如(a>b)&&(b>c),(a<b)||(b<c)。"!"是單目運(yùn)算符,只要求一個(gè)操作數(shù),如!(a>b)。下表為邏輯運(yùn)算的真值表。它表示當(dāng)a和b的值為不同的組合時(shí),各種邏輯運(yùn)算所得到的值。

 

a

b

!a

!b

a&&b

a||b

 

邏輯運(yùn)算符中"&&"和"||"的優(yōu)先級(jí)別低于關(guān)系運(yùn)算符,"!" 高于算術(shù)運(yùn)算符。見(jiàn)下例:

(a>b)&&(x>y)    可寫(xiě)成: a>b && x>y

(a==b)||(x==y)  可寫(xiě)成:a==b || x==y

(!a)||(a>b) 可寫(xiě)成: !a || a>b

為了提高程序的可讀性,明確表達(dá)各運(yùn)算符間的優(yōu)先關(guān)系,建議使用括號(hào).

 

 

3.3.4.關(guān)系運(yùn)算符

 

關(guān)系運(yùn)算符共有以下四種:

 

a < b        a小于b

a > b        a大于b

a <= b       a小于或等于b

a >= b       a大于或等于b

 

在進(jìn)行關(guān)系運(yùn)算時(shí),如果聲明的關(guān)系是假的(flase),則返回值是0,如果聲明的關(guān)系是真的(true),則返回值是1,如果某個(gè)操作數(shù)的值不定,則關(guān)系是模糊的,返回值是不定值。

 

所有的關(guān)系運(yùn)算符有著相同的優(yōu)先級(jí)別。關(guān)系運(yùn)算符的優(yōu)先級(jí)別低于算術(shù)運(yùn)算符的優(yōu)先級(jí)別。見(jiàn)下例:

a < size-1         //這種表達(dá)方式等同于下面

a < (size-1)       //這種表達(dá)方式。

size - ( 1 < a )   //這種表達(dá)方式不等同于下面

size - 1 < a       //這種表達(dá)方式。

 

從上面的例子可以看出這兩種不同運(yùn)算符的優(yōu)先級(jí)別。當(dāng)表達(dá)式size-(1<a)進(jìn)行運(yùn)算時(shí),關(guān)系表達(dá)式先被運(yùn)算,然后返回結(jié)果值0或1被size減去。而當(dāng)表達(dá)式 size-1<a 進(jìn)行運(yùn)算時(shí),size先被減去1,然后再同a相比。

 

 

3.3.5.等式運(yùn)算符

在Verilog HDL語(yǔ)言中存在四種等式運(yùn)算符:

 

1)   ==  (等于)

2)   !=  (不等于)

3)   === (等于)

4)   !== (不等于)

 

這四個(gè)運(yùn)算符都是二目運(yùn)算符,它要求有兩個(gè)操作數(shù)。"=="和"!="又稱為邏輯等式運(yùn)算符。其結(jié)果由兩個(gè)操作數(shù)的值決定。由于操作數(shù)中某些位可能是不定值x和高阻值z(mì),結(jié)果可能為不定值x。而"==="和"!=="運(yùn)算符則不同,它在對(duì)操作數(shù)進(jìn)行比較時(shí)對(duì)某些位的不定值x和高阻值z(mì)也進(jìn)行比較,兩個(gè)操作數(shù)必需完全一致,其結(jié)果才是1,否則為0。"==="和"!=="運(yùn)算符常用于case表達(dá)式的判別,所以又稱為"case等式運(yùn)算符"。這四個(gè)等式運(yùn)算符的優(yōu)先級(jí)別是相同的。下面畫(huà)出==與===的真值表,幫助理解兩者間的區(qū)別。

 

下面舉一個(gè)例子說(shuō)明“==”和“===”的區(qū)別。

例:

if(A==1’bx)  $display(“AisX”); (當(dāng)A等于X時(shí),這個(gè)語(yǔ)句不執(zhí)行)

if(A===1’bx) $display(“AisX”); (當(dāng)A等于X時(shí),這個(gè)語(yǔ)句執(zhí)行)

 

 

3.3.6.移位運(yùn)算符

在Verilog HDL中有兩種移位運(yùn)算符:

<< (左移位運(yùn)算符) 和  >>(右移位運(yùn)算符)。

其使用方法如下:

 a >> n  或  a << n

a代表要進(jìn)行移位的操作數(shù),n代表要移幾位。這兩種移位運(yùn)算都用0來(lái)填補(bǔ)移出的空位。下面舉例說(shuō)明:

 

module  shift;

reg [3:0]  start, result;

initial

begin

start  = 1;   //start在初始時(shí)刻設(shè)為值0001

result = (start<<2);

//移位后,start的值0100,然后賦給result。

end

endmodule

 

從上面的例子可以看出,start在移過(guò)兩位以后,用0來(lái)填補(bǔ)空出的位。

 

進(jìn)行移位運(yùn)算時(shí)應(yīng)注意移位前后變量的位數(shù),下面將給出一例。

 

例:4’b1001<<1 = 5’b10010;  4’b1001<<2 = 6’b100100;

 1<<6 = 32’b1000000;     4’b1001>>1 = 4’b0100;  4’b1001>>4 = 4’b0000;

 

 

3.3.7.位拼接運(yùn)算符(Concatation)

在Verilog HDL語(yǔ)言有一個(gè)特殊的運(yùn)算符:位拼接運(yùn)算符{}。用這個(gè)運(yùn)算符可以把兩個(gè)或多個(gè)信號(hào)的某些位拼接起來(lái)進(jìn)行運(yùn)算操作。其使用方法如下:

 

{信號(hào)1的某幾位,信號(hào)2的某幾位,..,..,信號(hào)n的某幾位}

 

即把某些信號(hào)的某些位詳細(xì)地列出來(lái),中間用逗號(hào)分開(kāi),最后用大括號(hào)括起來(lái)表示一個(gè)整體信號(hào)。見(jiàn)下例:

{a,b[3:0],w,3’b101}

也可以寫(xiě)成為

{a,b[3],b[2],b[1],b[0],w,1’b1,1’b0,1’b1}

在位拼接表達(dá)式中不允許存在沒(méi)有指明位數(shù)的信號(hào)。這是因?yàn)樵谟?jì)算拼接信號(hào)的位寬的大小時(shí)必需知道其中每個(gè)信號(hào)的位寬。

 

位拼接還可以用重復(fù)法來(lái)簡(jiǎn)化表達(dá)式。見(jiàn)下例:

{4{w}}            //這等同于{w,w,w,w}

位拼接還可以用嵌套的方式來(lái)表達(dá)。見(jiàn)下例:

{b,{3{a,b}}}     //這等同于{b,a,b,a,b,a,b}

用于表示重復(fù)的表達(dá)式如上例中的4和3,必須是常數(shù)表達(dá)式。

 

3.3.8.縮減運(yùn)算符(reduction operator)

縮減運(yùn)算符是單目運(yùn)算符,也有與或非運(yùn)算。其與或非運(yùn)算規(guī)則類似于位運(yùn)算符的與或非運(yùn)算規(guī)則,但其運(yùn)算過(guò)程不同。位運(yùn)算是對(duì)操作數(shù)的相應(yīng)位進(jìn)行與或非運(yùn)算,操作數(shù)是幾位數(shù)則運(yùn)算結(jié)果也是幾位數(shù)。而縮減運(yùn)算則不同,縮減運(yùn)算是對(duì)單個(gè)操作數(shù)進(jìn)行或與非遞推運(yùn)算,最后的運(yùn)算結(jié)果是一位的二進(jìn)制數(shù)??s減運(yùn)算的具體運(yùn)算過(guò)程是這樣的:第一步先將操作數(shù)的第一位與第二位進(jìn)行或與非運(yùn)算,第二步將運(yùn)算結(jié)果與第三位進(jìn)行或與非運(yùn)算,依次類推,直至最后一位。

例如:reg [3:0] B;

reg C;

C = &B;

相當(dāng)于:

C =( (B[0]&B[1]) & B[2] ) & B[3];

 

由于縮減運(yùn)算的與、或、非運(yùn)算規(guī)則類似于位運(yùn)算符與、或、非運(yùn)算規(guī)則,這里不再詳細(xì)講述,請(qǐng)參照位運(yùn)算符的運(yùn)算規(guī)則介紹。

 

3.3.9.優(yōu)先級(jí)別

下面對(duì)各種運(yùn)算符的優(yōu)先級(jí)別關(guān)系作一總結(jié)。見(jiàn)下表:


 

 

3.3.10.關(guān)鍵詞

在Verilog HDL中,所有的關(guān)鍵詞是事先定義好的確認(rèn)符,用來(lái)組織語(yǔ)言結(jié)構(gòu)。關(guān)鍵詞是用小寫(xiě)字母定義的,因此在編寫(xiě)原程序時(shí)要注意關(guān)鍵詞的書(shū)寫(xiě),以避免出錯(cuò)。下面是Verilog HDL中使用的關(guān)鍵詞(請(qǐng)參閱附錄:Verilog語(yǔ)言參考手冊(cè)):

 

always, and, assign,begin,buf,bufif0,bufif1,case,casex,casez,cmos,deassign,default,defparam,disable,edge,else,end,endcase,endmodule,endfunction,endprimitive, endspecify, endtable, endtask, event, for, force, forever, fork, function,highz0, highz1, if,initial, inout, input,integer,join,large,macromodule,medium,module,nand,negedge,nmos,nor,not,notif0,notifl, or, output, parameter, pmos, posedge, primitive, pull0, pull1, pullup, pulldown, rcmos, reg, releses, repeat, mmos, rpmos, rtran, rtranif0,rtranif1,scalared,small,specify,specparam,strength,strong0, strong1, supply0, supply1, table, task, time, tran, tranif0, tranif1, tri, tri0, tri1, triand, trior, trireg,vectored,wait,wand,weak0,weak1,while, wire,wor, xnor, xor

 

注意在編寫(xiě)Verilog HDL程序時(shí),變量的定義不要與這些關(guān)鍵詞沖突.

 

 

3.4 賦值語(yǔ)句和塊語(yǔ)句

 

3.4.1 賦值語(yǔ)句

 

在Verilog HDL語(yǔ)言中,信號(hào)有兩種賦值方式:

 

(1).非阻塞(Non_Blocking)賦值方式( 如 b <= a; )

1)   塊結(jié)束后才完成賦值操作。

2)   b的值并不是立刻就改變的。

3)   這是一種比較常用的賦值方法。(特別在編寫(xiě)可綜合模塊時(shí))

 

(2).阻塞(Blocking)賦值方式( 如 b = a; )

1)   賦值語(yǔ)句執(zhí)行完后,塊才結(jié)束。

2)   b的值在賦值語(yǔ)句執(zhí)行完后立刻就改變的。

3)   可能會(huì)產(chǎn)生意想不到的結(jié)果。

 

非阻塞賦值方式和阻塞賦值方式的區(qū)別常給設(shè)計(jì)人員帶來(lái)問(wèn)題。問(wèn)題主要是給"always"塊內(nèi)的reg型信號(hào)的賦值方式不易把握。到目前為止,前面所舉的例子中的"always"模塊內(nèi)的reg型信號(hào)都是采用下面的這種賦值方式:

 

b <= a;

 

這種方式的賦值并不是馬上執(zhí)行的,也就是說(shuō)"always"塊內(nèi)的下一條語(yǔ)句執(zhí)行后,b并不等于a,而是保持原來(lái)的值。"always"塊結(jié)束后,才進(jìn)行賦值。而另一種賦值方式阻塞賦值方式,如下所示:

 

b = a;

 

這種賦值方式是馬上執(zhí)行的。也就是說(shuō)執(zhí)行下一條語(yǔ)句時(shí),b已等于a。盡管這種方式看起來(lái)很直觀,但是可能引起麻煩。下面舉例說(shuō)明:

 

[例1]:always @( posedge clk )

begin

b<=a;

c<=b;

end

 

[例1] 中的"always"塊中用了非阻塞賦值方式,定義了兩個(gè)reg型信號(hào)b和c,clk信號(hào)的上升沿到來(lái)時(shí),b就等于a,c就等于b,這里應(yīng)該用到了兩個(gè)觸發(fā)器。請(qǐng)注意:賦值是在"always"塊結(jié)束后執(zhí)行的,c應(yīng)為原來(lái)b的值。這個(gè)"always"塊實(shí)際描述的電路功能如下圖所示:


 

 

 

[例2]: always @(posedge  clk)

begin

b=a;

c=b;

end

 

[例2]中的 "always"塊用了阻塞賦值方式。clk信號(hào)的上升沿到來(lái)時(shí),將發(fā)生如下的變化:b馬上取a的值,c馬上取b的值(即等于a),生成的電路圖如下所示只用了一個(gè)觸發(fā)器來(lái)寄存器a的值,又輸出給b和c。這大概不是設(shè)計(jì)者的初衷,如果采用[例1]所示的非阻塞賦值方式就可以避免這種錯(cuò)誤。

 

 

D

CLK

 

Q

a

b

c

clk

 



 

關(guān)于賦值語(yǔ)句更詳細(xì)的說(shuō)明請(qǐng)參閱第七章中深入理解阻塞和非阻塞賦值小節(jié)。

 

3.4.2 塊語(yǔ)句

 

塊語(yǔ)句通常用來(lái)將兩條或多條語(yǔ)句組合在一起,使其在格式上看更象一條語(yǔ)句。塊語(yǔ)句有兩種,一種是begin_end語(yǔ)句,通常用來(lái)標(biāo)識(shí)順序執(zhí)行的語(yǔ)句,用它來(lái)標(biāo)識(shí)的塊稱為順序塊。一種是fork_join語(yǔ)句,通常用來(lái)標(biāo)識(shí)并行執(zhí)行的語(yǔ)句,用它來(lái)標(biāo)識(shí)的塊稱為并行塊。下面進(jìn)行詳細(xì)的介紹。

 

一.順序塊

順序塊有以下特點(diǎn):

1)   塊內(nèi)的語(yǔ)句是按順序執(zhí)行的,即只有上面一條語(yǔ)句執(zhí)行完后下面的語(yǔ)句才能執(zhí)行。

2)   每條語(yǔ)句的延遲時(shí)間是相對(duì)于前一條語(yǔ)句的仿真時(shí)間而言的。

3)   直到最后一條語(yǔ)句執(zhí)行完,程序流程控制才跳出該語(yǔ)句塊。

順序塊的格式如下:

begin

語(yǔ)句1;

語(yǔ)句2;

......

語(yǔ)句n;

end

 

begin:塊名

塊內(nèi)聲明語(yǔ)句 

語(yǔ)句1;

語(yǔ)句2;

......

語(yǔ)句n;

end

 

其中:

  塊名即該塊的名字,一個(gè)標(biāo)識(shí)名。其作用后面再詳細(xì)介紹。

  塊內(nèi)聲明語(yǔ)句可以是參數(shù)聲明語(yǔ)句、reg型變量聲明語(yǔ)句、integer型變量聲明語(yǔ)句、real型變量聲明語(yǔ)句。

下面舉例說(shuō)明:

[例1]:begin

areg = breg;

creg = areg;   //creg的值為breg的值。

end

 

從該例可以看出,第一條賦值語(yǔ)句先執(zhí)行,areg的值更新為breg的值,然后程序流程控制轉(zhuǎn)到第二條賦值語(yǔ)句,creg的值更新為areg的值。因?yàn)檫@兩條賦值語(yǔ)句之間沒(méi)有任何延遲時(shí)間,creg的值實(shí)為breg的值。當(dāng)然可以在順序塊里延遲控制時(shí)間來(lái)分開(kāi)兩個(gè)賦值語(yǔ)句的執(zhí)行時(shí)間,見(jiàn)[例2]:

 

[例2]: begin

areg = breg;

#10 creg = areg;

//在兩條賦值語(yǔ)句間延遲10個(gè)時(shí)間單位。

end

 

[例3]:parameter  d=50;  //聲明d是一個(gè)參數(shù)

reg [7:0]  r;     //聲明r是一個(gè)8位的寄存器變量

begin             //由一系列延遲產(chǎn)生的波形

#d  r = 'h35;

#d  r = 'hE2;

#d  r = 'h00;

#d  r = 'hF7;

#d  -> end_wave;  //觸發(fā)事件end_wave

end

 

這個(gè)例子中用順序塊和延遲控制組合來(lái)產(chǎn)生一個(gè)時(shí)序波形。

 

二. 并行塊

并行塊有以下四個(gè)特點(diǎn):

1)   塊內(nèi)語(yǔ)句是同時(shí)執(zhí)行的,即程序流程控制一進(jìn)入到該并行塊,塊內(nèi)語(yǔ)句則開(kāi)始同時(shí)并行地執(zhí)行。

2)   塊內(nèi)每條語(yǔ)句的延遲時(shí)間是相對(duì)于程序流程控制進(jìn)入到塊內(nèi)時(shí)的仿真時(shí)間的。

3)   延遲時(shí)間是用來(lái)給賦值語(yǔ)句提供執(zhí)行時(shí)序的。

4)   當(dāng)按時(shí)間時(shí)序排序在最后的語(yǔ)句執(zhí)行完后或一個(gè)disable語(yǔ)句執(zhí)行時(shí),程序流程控制跳出該程序塊。

 

并行塊的格式如下:

fork

語(yǔ)句1;

語(yǔ)句2;

.......

語(yǔ)句n;

join

 

fork:塊名

塊內(nèi)聲明語(yǔ)句   

語(yǔ)句1;

語(yǔ)句2;

......

語(yǔ)句n;

join

 

其中:

·         塊名即標(biāo)識(shí)該塊的一個(gè)名字,相當(dāng)于一個(gè)標(biāo)識(shí)符。

·         塊內(nèi)說(shuō)明語(yǔ)句可以是參數(shù)說(shuō)明語(yǔ)句、reg型變量聲明語(yǔ)句、integer型變量聲明語(yǔ)句、real型變量聲明語(yǔ)句、time型變量聲明語(yǔ)句、事件(event)說(shuō)明語(yǔ)句。

 

下面舉例說(shuō)明:

 

[例4]:fork

#50   r = 'h35;

#100  r = 'hE2;

#150  r = 'h00;

#200  r = 'hF7;

#250    ->  end_wave;    //觸發(fā)事件end_wave.

join

 

在這個(gè)例子中用并行塊來(lái)替代了前面例子中的順序塊來(lái)產(chǎn)生波形,用這兩種方法生成的波形是一樣的。

 

三. 塊名

在VerilgHDL語(yǔ)言中,可以給每個(gè)塊取一個(gè)名字,只需將名字加在關(guān)鍵詞begin或fork后面即可。這樣做的原因有以下幾點(diǎn)。

1)   這樣可以在塊內(nèi)定義局部變量,即只在塊內(nèi)使用的變量。

2)   這樣可以允許塊被其它語(yǔ)句調(diào)用,如被disable語(yǔ)句。

3)   在Verilog語(yǔ)言里,所有的變量都是靜態(tài)的,即所有的變量都只有一個(gè)唯一的存儲(chǔ)地址,因此進(jìn)入或跳出塊并不影響存儲(chǔ)在變量?jī)?nèi)的值。

基于以上原因,塊名就提供了一個(gè)在任何仿真時(shí)刻確認(rèn)變量值的方法。

 

四. 起始時(shí)間和結(jié)束時(shí)間

在并行塊和順序塊中都有一個(gè)起始時(shí)間和結(jié)束時(shí)間的概念。對(duì)于順序塊,起始時(shí)間就是第一條語(yǔ)句開(kāi)始被執(zhí)行的時(shí)間,結(jié)束時(shí)間就是最后一條語(yǔ)句執(zhí)行完的時(shí)間。而對(duì)于并行塊來(lái)說(shuō),起始時(shí)間對(duì)于塊內(nèi)所有的語(yǔ)句是相同的,即程序流程控制進(jìn)入該塊的時(shí)間,其結(jié)束時(shí)間是按時(shí)間排序在最后的語(yǔ)句執(zhí)行完的時(shí)間。

 

當(dāng)一個(gè)塊嵌入另一個(gè)塊時(shí),塊的起始時(shí)間和結(jié)束時(shí)間是很重要的。至于跟在塊后面的語(yǔ)句只有在該塊的結(jié)束時(shí)間到了才能開(kāi)始執(zhí)行,也就是說(shuō),只有該塊完全執(zhí)行完后,后面的語(yǔ)句才可以執(zhí)行。

 

在fork_join塊內(nèi),各條語(yǔ)句不必按順序給出,因此在并行塊里,各條語(yǔ)句在前還是在后是無(wú)關(guān)緊要的。見(jiàn)下例:

 

[例5]:fork

#250  -> end_wave;

#200  r = 'hF7;

#150  r = 'h00;

#100  r = 'hE2;

#50   r = 'h35;

join

 

在這個(gè)例子中,各條語(yǔ)句并不是按被執(zhí)行的先后順序給出的,但同樣可以生成前面例子中的波形。

 

 

3.5.條件語(yǔ)句

 

3.5.1. if_else語(yǔ)句

if語(yǔ)句是用來(lái)判定所給定的條件是否滿足,根據(jù)判定的結(jié)果(真或假)決定執(zhí)行給出的兩種操作之一。Verilog HDL語(yǔ)言提供了三種形式的if語(yǔ)句。

(1).if(表達(dá)式)語(yǔ)句

例如:    if ( a > b )    out1 <= int1;

(2).if(表達(dá)式)      語(yǔ)句1

else        語(yǔ)句2

例如:         if(a>b)      out1<=int1;

else        out1<=int2;

(3).if(表達(dá)式1)  語(yǔ)句1;

else  if(表達(dá)式2)  語(yǔ)句2;

else  if(表達(dá)式3)  語(yǔ)句3;

........

else  if(表達(dá)式m)  語(yǔ)句m;

else               語(yǔ)句n;

 

例如:

if(a>b)  out1<=int1;

else  if(a==b)  out1<=int2;

else            out1<=int3;

 

 

六點(diǎn)說(shuō)明:

 

(1).三種形式的if語(yǔ)句中在if后面都有“表達(dá)式”,一般為邏輯表達(dá)式或關(guān)系表達(dá)式。系統(tǒng)對(duì)表達(dá)式的值進(jìn)行判斷,若為0,x,z,按“假”處理,若為1,按“真”處理,執(zhí)行指定的語(yǔ)句。

 

(2)  .第二、第三種形式的if語(yǔ)句中,在每個(gè)else前面有一分號(hào),整個(gè)語(yǔ)句結(jié)束處有一分號(hào)。

例如:

 

 

這是由于分號(hào)是Verilog HDL語(yǔ)句中不可缺少的部分,這個(gè)分號(hào)是if語(yǔ)句中的內(nèi)嵌套語(yǔ)句所要求的。如果無(wú)此分號(hào),則出現(xiàn)語(yǔ)法錯(cuò)誤。但應(yīng)注意,不要誤認(rèn)為上面是兩個(gè)語(yǔ)句(if語(yǔ)句和else語(yǔ)句)。它們都屬于同一個(gè)if語(yǔ)句。else子句不能作為語(yǔ)句單獨(dú)使用,它必須是if語(yǔ)句的一部分,與if配對(duì)使用。

 

(3).在if和else后面可以包含一個(gè)內(nèi)嵌的操作語(yǔ)句(如上例),也可以有多個(gè)操作語(yǔ)句,此時(shí)用begin和end這兩個(gè)關(guān)鍵詞將幾個(gè)語(yǔ)句包含起來(lái)成為一個(gè)復(fù)合塊語(yǔ)句。如:

if(a>b)

begin

  out1<=int1;

  out2<=int2;

end

else

begin

  out1<=int2;

  out2<=int1;

end

注意在end后不需要再加分號(hào)。因?yàn)閎egin_end內(nèi)是一個(gè)完整的復(fù)合語(yǔ)句,不需再附加分號(hào)。

 

(4).允許一定形式的表達(dá)式簡(jiǎn)寫(xiě)方式。如下面的例子:

if(expression)  等同與  if( expression == 1 )

if(!expression) 等同與  if( expression != 1 )

 

(5).if語(yǔ)句的嵌套

在if語(yǔ)句中又包含一個(gè)或多個(gè)if語(yǔ)句稱為if語(yǔ)句的嵌套。一般形式如下:

if(expression1)

if(expression2) 語(yǔ)句1 (內(nèi)嵌if)

else   語(yǔ)句2

else

if(expression3)  語(yǔ)句3 (內(nèi)嵌if)

else   語(yǔ)句4

應(yīng)當(dāng)注意if與else的配對(duì)關(guān)系,else總是與它上面的最近的if配對(duì)。如果if與else的數(shù)目不一樣,為了實(shí)現(xiàn)程序設(shè)計(jì)者的企圖,可以用begin_end塊語(yǔ)句來(lái)確定配對(duì)關(guān)系。例如:

if( )

begin

if(   )  語(yǔ)句1    (內(nèi)嵌if)

end

else

語(yǔ)句2

這時(shí)begin_end塊語(yǔ)句限定了內(nèi)嵌if語(yǔ)句的范圍,因此else與第一個(gè)if配對(duì)。注意begin_end塊語(yǔ)句在if_else語(yǔ)句中的使用。因?yàn)橛袝r(shí)begin_end塊語(yǔ)句的不慎使用會(huì)改變邏輯行為。見(jiàn)下例:

if(index>0)

for(scani=0;scani<index;scani=scani+1)

if(memory[scani]>0)

begin

$display("...");

memory[scani]=0;

end

else    /*WRONG*/

$display("error-indexiszero");

 

    盡管程序設(shè)計(jì)者把else寫(xiě)在與第一個(gè)if(外層if)同一列上,希望與第一個(gè)if對(duì)應(yīng),但實(shí)際上else是與第二個(gè)if對(duì)應(yīng),因?yàn)樗鼈兿嗑嘧罱U_的寫(xiě)法應(yīng)當(dāng)是這樣的:

if(index>0)

begin

for(scani=0;scani<index;scani=scani+1)

if(memory[scani]>0)

begin

$display("...");

memory[scani]=0;

end

end

 

else   /*WRONG*/

    $display("error-indexiszero");

 

(6).if_else例子。

下面的例子是取自某程序中的一部分。這部分程序用if_else語(yǔ)句來(lái)檢測(cè)變量index以決定三個(gè)寄存器modify_segn中哪一個(gè)的值應(yīng)當(dāng)與index相加作為memory的尋址地址。并且將相加值存入寄存器index以備下次檢測(cè)使用。程序的前十行定義寄存器和參數(shù)。

 

//定義寄存器和參數(shù)。

reg [31:0]  instruction, segment_area[255:0];

reg [7:0]   index;

reg [5:0]   modify_seg1, modify_seg2, modify_seg3;

parameter

segment1=0,  inc_seg1=1,

segment2=20, inc_seg2=2,

segment3=64, inc_seg3=4,

data=128;

//檢測(cè)寄存器index的值

if(index<segment2)

begin

instruction = segment_area[index + modify_seg1];

index = index + inc_seg1;

end

else  if(index<segment3)

begin

instruction = segment_area[index + modify_seg2];

index = index + inc_seg2;

end

else  if (index<data)

begin

instruction = segment_area[index + modify_seg3];

index = index + inc_seg3;

end

else

instruction

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多