《數(shù)字電路設(shè)計(jì)及VerilogHDL實(shí)現(xiàn)》課件第3章_第1頁(yè)
《數(shù)字電路設(shè)計(jì)及VerilogHDL實(shí)現(xiàn)》課件第3章_第2頁(yè)
《數(shù)字電路設(shè)計(jì)及VerilogHDL實(shí)現(xiàn)》課件第3章_第3頁(yè)
《數(shù)字電路設(shè)計(jì)及VerilogHDL實(shí)現(xiàn)》課件第3章_第4頁(yè)
《數(shù)字電路設(shè)計(jì)及VerilogHDL實(shí)現(xiàn)》課件第3章_第5頁(yè)
已閱讀5頁(yè),還剩151頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

3.1VerilogHDL程序的基本結(jié)構(gòu)

3.2VerilogHDL基本語(yǔ)法

3.3VerilogHDL的運(yùn)算符

3.4VerilogHDL常用建模方式

3.5模塊化程序設(shè)計(jì)第3章VerilogHDL的基本語(yǔ)法3.1.1VerilogHDL設(shè)計(jì)風(fēng)格

1.VerilogHDL功能描述方式

VerilogHDL可綜合硬件邏輯電路的功能描述通常有三種方式:結(jié)構(gòu)描述方式、數(shù)據(jù)流描述方式和行為描述方式。

(1)結(jié)構(gòu)描述方式也稱(chēng)為門(mén)級(jí)描述方式,是通過(guò)調(diào)用VerilogHDL語(yǔ)言預(yù)定義的基礎(chǔ)元件(也稱(chēng)為原語(yǔ),即Primitive),

比如邏輯門(mén)元件,并定義各元件間的連接關(guān)系來(lái)構(gòu)建電路。

這種方式構(gòu)建的電路模型綜合和執(zhí)行效率高,但描述效率低,

難于設(shè)計(jì)復(fù)雜數(shù)字系統(tǒng)。3.1VerilogHDL程序的基本結(jié)構(gòu)(2)數(shù)據(jù)流描述方式描述組件間的數(shù)據(jù)流,主要使用連續(xù)賦值語(yǔ)句assign(參見(jiàn)3.4.2節(jié))將表達(dá)式所得結(jié)果賦值給(連續(xù)驅(qū)動(dòng))表達(dá)式左邊的線網(wǎng)(信號(hào)輸出),多用于組合邏輯電路的建模。

因?yàn)槟苡帽磉_(dá)式方便地表示比較復(fù)雜的邏輯運(yùn)算,因此描述效率高于門(mén)級(jí)描述方式。(3)行為描述方式類(lèi)似于計(jì)算機(jī)語(yǔ)言中的高級(jí)語(yǔ)言,使用過(guò)程塊語(yǔ)句always、initial(包含if…else…、case…等高級(jí)抽象描述語(yǔ)句)描述邏輯電路的邏輯功能(行為),無(wú)須設(shè)計(jì)者熟知硬件電路結(jié)構(gòu)即可進(jìn)行,是一種多見(jiàn)且常用的建模方式。行為描述方式既可用于組合邏輯也可用于時(shí)序邏輯電路的建模。

對(duì)一個(gè)硬件邏輯電路建模,可根據(jù)需要任意選用其中的一種方法,或者混合幾種方法。2.硬件邏輯電路功能描述示例

表3.1.1給出一個(gè)半加器電路的真值表,圖3.1.1給出了用與非門(mén)實(shí)現(xiàn)該半加器的邏輯電路圖。我們分別使用上述三種描述方式對(duì)這個(gè)半加器進(jìn)行建模,從Verilog示例代碼認(rèn)識(shí)VerilogHDL的設(shè)計(jì)風(fēng)格。圖3.1.1半加器電路圖【例3.1.1】試描述表3.1.1所示半加器的數(shù)據(jù)流模型。本例中使用連續(xù)賦值語(yǔ)句“assignS=A^B”實(shí)現(xiàn)將A、B的異或運(yùn)算結(jié)果賦值給S,只要A、B變化就會(huì)驅(qū)動(dòng)S變化,這也是連續(xù)賦值的含義,可看做實(shí)現(xiàn)了一個(gè)兩輸入的異或門(mén)。“assignC=A&B”語(yǔ)句功能與“assignS=A^B”類(lèi)似,實(shí)現(xiàn)將A、B的與運(yùn)算結(jié)果賦值給C。這個(gè)例子是表3.1.1所對(duì)應(yīng)的邏輯表達(dá)式的直接描述,模塊功能描述部分說(shuō)明電路要用什么樣的部件,以及部件之間數(shù)據(jù)的流動(dòng)關(guān)系。

程序中,“//”符號(hào)是VerilogHDL規(guī)定的單行注釋的開(kāi)始,表示后續(xù)內(nèi)容是注釋?zhuān)⑨尣糠值交剀?chē)符結(jié)束。注釋只為方便設(shè)計(jì)人員閱讀,綜合程序不會(huì)處理注釋部分。本例中“always@(AorB)”語(yǔ)句表示只要A或B信號(hào)發(fā)生變化就執(zhí)行always語(yǔ)句塊,即begin…end塊中的case語(yǔ)句,所以case語(yǔ)句可多次執(zhí)行。Verilog拼接運(yùn)算符“{}”將A、B兩個(gè)一位二進(jìn)制數(shù)拼接為一個(gè)兩位二進(jìn)制數(shù)。當(dāng)AB取值為二進(jìn)制00時(shí),執(zhí)行“S=0,C=0”,將S、C都賦值為0;當(dāng)AB取值為01時(shí),S賦值為1,C賦值為0;當(dāng)AB取值為10時(shí),S賦值為1,C賦值為1;當(dāng)AB取值為11時(shí),S賦值為0,C賦值為1。所以case語(yǔ)句實(shí)際上是半加器真值表的描述,即按半加器行為進(jìn)行建模,并不描述電路的具體結(jié)構(gòu)。

3.VerilogHDL設(shè)計(jì)風(fēng)格

綜合例3.1.1、例3.1.2、例3.1.3的代碼可以看,VerilogHDL程序與一般計(jì)算機(jī)程序類(lèi)似,其源文件由關(guān)鍵字、標(biāo)識(shí)符、表達(dá)式等組成的語(yǔ)句構(gòu)成。其主要設(shè)計(jì)風(fēng)格表現(xiàn)為以下幾個(gè)方面。

(1)程序由模塊構(gòu)成。在源代碼中,模塊以關(guān)鍵字module標(biāo)識(shí),以關(guān)鍵字endmodule結(jié)束。VerilogHDL程序位于module和endmodule之間。

(2)模塊邏輯功能描述,可以使用實(shí)例化已有元件的方法,或者使用連續(xù)賦值語(yǔ)句assign,或者使用過(guò)程塊語(yǔ)句always(包含if…else…、case…等高級(jí)抽象描述語(yǔ)句)來(lái)描述電路行為,或者混合使用這幾種方法。always過(guò)程塊語(yǔ)句是行為建模最主要和常見(jiàn)的結(jié)構(gòu)。(3)Verilog代碼以空格分隔關(guān)鍵字、標(biāo)識(shí)符等。除endmodule語(yǔ)句外,其余語(yǔ)句都要以“;”結(jié)束。一行可以寫(xiě)多條語(yǔ)句,每條語(yǔ)句用“;”結(jié)束。一條語(yǔ)句也可以寫(xiě)在多行,直到遇到“;”結(jié)束。

(4)可以使用“//…”和“/*…*/”對(duì)程序進(jìn)行注釋?!?/…”用于單行注釋,從“//”開(kāi)始,到回車(chē)結(jié)束,都被看做注釋部分?!?*…*/”用于多行注釋。多行注釋不能嵌套。3.1.2VerilogHDL模塊結(jié)構(gòu)

如例3.1.1~例3.1.3所示,Verilog模塊由4個(gè)主要部分組成:端口定義、端口說(shuō)明、內(nèi)部信號(hào)說(shuō)明和功能定義,模塊結(jié)構(gòu)如圖3.1.2所示。圖3.1.2VerilogHDL模塊的一般結(jié)構(gòu)1.端口定義

端口是外部電路調(diào)用/引用模塊時(shí)需要的輸入/輸出連接,是模塊與外界溝通的橋梁。

端口定義包括定義模塊的名稱(chēng),給出端口(輸入/輸出連接)的名稱(chēng)列表。其格式如下:

module模塊名(端口名1,端口名2,端口名3,…);模塊名是用戶(hù)定義的標(biāo)識(shí)符,要符合VerilogHDL對(duì)標(biāo)識(shí)符的命名要求(參見(jiàn)3.2.1節(jié))。端口列表用逗號(hào)分隔,列出模塊所有的輸入輸出信號(hào)。

例如:modulehalf_adder(A,B,S,C)//例3.1.1~例3.1.3中的端口定義語(yǔ)句以上語(yǔ)句說(shuō)明模塊名稱(chēng)為half_adder,模塊有A、B、S和C四個(gè)端口。2.端口說(shuō)明

端口說(shuō)明用于說(shuō)明端口列表中每個(gè)端口的位寬和輸入/輸出方向。輸入/輸出方向可用input、output或inout進(jìn)行說(shuō)明。

input輸入端口說(shuō)明格式為input[msb1:lsb1]端口名11,端口名12,…;、input[msb2:lsb2]端口名21,端口名22,…;

output輸出端口說(shuō)明格式為

output[msb1:lsb1]端口名11,端口名12,…;

output[msb2:lsb2]端口名21,端口名22,…;

inout雙向端口說(shuō)明格式為

inout[msb1:lsb1]端口名11,端口名12,…;

inout[msb2:lsb2]端口名21,端口名22,…;相同位寬的端口可在一條語(yǔ)句中說(shuō)明,不同位寬的端口要在不同的語(yǔ)句中說(shuō)明。

[msb:lsb]指定端口位寬,多位寬端口可看做總線。其中,msb說(shuō)明總線高位;lsb說(shuō)明總線低位。[msb:lsb]也可以省略,省略時(shí)默認(rèn)端口位寬為1位。

例如:

inputa;//1位寬的輸入端口

input[3:0]b;//4位總線b

outputc,d;//2個(gè)1位寬的輸出端口用output說(shuō)明的輸出端口默認(rèn)為wire型。當(dāng)輸出端口在過(guò)程塊語(yǔ)句中賦值時(shí)(比如always塊),需要將其定義為reg型(關(guān)于wire型和reg型變量的說(shuō)明參見(jiàn)3.2.3節(jié)),格式為

outputreg[msb:lsb]端口名1,端口名2,…;

或output端口名1,端口名2,…;

reg[msb:lsb]端口名1,端口名2,…;端口說(shuō)明舉例如下:

outputS,C;//說(shuō)明S、C為1位寬輸出端口

regS,C;//說(shuō)明S、C為reg型

inputa,b;//說(shuō)明兩個(gè)1位寬的輸入端口a、b

input[7:0]abus;//說(shuō)明8位寬的輸入總線abus,最高位為abus[7],最低位為abus[0]

outputs;//說(shuō)明1位寬的輸出端口s

output[16:1]oBus;//說(shuō)明16位寬的輸出總線oBus,最高位為oBus[16],最低位為oBus[1]

inoutdcx;//說(shuō)明1位寬的雙向端口dcx

端口說(shuō)明也可以寫(xiě)在端口聲明語(yǔ)句中,格式如下:

module模塊名(input[msb:lsb]輸入端口名1,output[msb:lsb]輸出端口名1,…);

3.內(nèi)部信號(hào)說(shuō)明在模塊功能描述時(shí)若需要使用命名的信號(hào)線或者存儲(chǔ)單元,就需要定義。內(nèi)部信號(hào)最常見(jiàn)的是wire型和reg型,wire型用于聲明線網(wǎng)信號(hào),reg單元。

wire型信號(hào)和reg型信號(hào)說(shuō)明語(yǔ)句格式如下:

wire[msb:lsb]變量1,變量2,…;reg[msb:lsb]變量1,變量2,…;

[msb:lsb]說(shuō)明信號(hào)位寬,可省略,省略時(shí)默認(rèn)為1位寬。例如:wireX1,X2,X3;

//例3.1.2的內(nèi)部信號(hào)說(shuō)明語(yǔ)句,1位寬reg[8:1]bBus;

//8位寬的reg型變量,可在always語(yǔ)句塊中賦值第3章VerilogHDL語(yǔ)法基礎(chǔ)

4.模塊功能描述

如前所述,模塊功能描述可用以下的一種或幾種方法。

1)門(mén)級(jí)描述

VerilogHDL內(nèi)置了與、或、異或、非、與非、緩沖器、反相器等12個(gè)基本門(mén)級(jí)元件模型,可通過(guò)實(shí)例引用構(gòu)建電路結(jié)構(gòu)。

2)數(shù)據(jù)流描述

數(shù)據(jù)流描述是使用連續(xù)賦值語(yǔ)句assign構(gòu)建表達(dá)式,描述電路使用的部件及部件間的數(shù)據(jù)流動(dòng)。

3)行為描述

行為描述是使用if…else…、case…等高級(jí)抽象描述語(yǔ)句描述電路的行為。高級(jí)抽象描述語(yǔ)句必須寫(xiě)在過(guò)程塊語(yǔ)句中,不可獨(dú)立存在于模塊中。最常用的過(guò)程塊語(yǔ)句是always,

另一種是initial。

綜合起來(lái),Verilog模塊功能定義部分的格式可用圖3.1.2說(shuō)明。需要注意的是,除了連續(xù)賦值語(yǔ)句assign和實(shí)例引用語(yǔ)句外,其他語(yǔ)句都不可以獨(dú)立于過(guò)程塊而存在。

5.并行執(zhí)行

作為電路建模語(yǔ)言,在學(xué)習(xí)VerilogHDL時(shí)必須注意的是,模塊中的實(shí)例化語(yǔ)句、連續(xù)賦值語(yǔ)句與過(guò)程塊之間是并行執(zhí)行的。這是VerilogHDL與一般高級(jí)語(yǔ)言最為不同的地方。

若Verilog模塊用到了多個(gè)實(shí)例引用語(yǔ)句,或者多個(gè)assign語(yǔ)句,或者多個(gè)always塊,或者將這些語(yǔ)句混合使用,那么它們的書(shū)寫(xiě)順序是任意的,因?yàn)樗鼈儗?duì)仿真程序和綜合程序的執(zhí)行來(lái)說(shuō)是并行的。也就是說(shuō),當(dāng)它們被綜合器綜合成實(shí)際電路時(shí),會(huì)形成不同的電路塊,當(dāng)輸入信號(hào)變化時(shí),這些電路塊在滿(mǎn)足延時(shí)的條件下同時(shí)動(dòng)作,是并行執(zhí)行的。

但是,需要明確的是,always塊內(nèi)部的高級(jí)抽象描述語(yǔ)句是按順序執(zhí)行的。因?yàn)椤癷f…else…”這樣的語(yǔ)句若不按順序執(zhí)行,其功能就沒(méi)有任何意義。

6.模塊的實(shí)例化

一個(gè)Verilog模塊通常只實(shí)現(xiàn)一個(gè)功能相對(duì)獨(dú)立的電路,一個(gè)大的電路往往由很多個(gè)模塊構(gòu)成。對(duì)成熟Verilog模塊的引用可像引用Verilog語(yǔ)言預(yù)定義的元件一樣進(jìn)行,也稱(chēng)為實(shí)例化。

實(shí)例化模塊的格式有兩種。一種是按模塊端口的順序列出對(duì)應(yīng)連接的外部信號(hào),格式如下:

模塊名實(shí)例名(連接端口1的信號(hào)名,連接端口2的信號(hào)名,…);

另一種格式可以不按端口順序給出外部信號(hào),但必須說(shuō)明每個(gè)外部信號(hào)對(duì)應(yīng)連接的端口信號(hào),格式如下:

模塊名實(shí)例名(.端口名i(連接端口i的信號(hào)名),.端口名k(連接端口k的信號(hào)名),…);

【例3.1.4】調(diào)用例3.1.1~例3.1.3描述的半加器模塊“half_adder”,實(shí)現(xiàn)兩個(gè)1位二進(jìn)制數(shù)myA與myB的相加,產(chǎn)生和myS和進(jìn)位myC。

解例3.1.1~例3.1.3描述的半加器模塊“half_adder”的端口如圖3.1.3所示。定義模塊myAdder完成對(duì)半加器模塊的調(diào)用,形成如圖3.1.4所示的輸入/輸出。半加器模塊

“half_adder”的調(diào)用程序如下:圖3.1.3half_adder端口圖圖3.1.4

half_adder引用圖 3.2VerilogHDL基本語(yǔ)法

3.2.1分隔符、標(biāo)識(shí)符和關(guān)鍵字

1.分隔符

VerilogHDL的分隔符包括空格、tab鍵、換行符和換頁(yè)符。除了分隔字符的空格及字符串中的分隔符外,其他分隔符都被綜合器所忽略。所以Verilog語(yǔ)句可以寫(xiě)在一行,也可以跨行跨頁(yè)書(shū)寫(xiě)。正確合理使用分隔符能夠使程序代碼排列整齊有序,便于閱讀和修改。

2.標(biāo)識(shí)符

標(biāo)識(shí)符是用戶(hù)定義的表示對(duì)象名稱(chēng)的字符串。VerilogHDL標(biāo)識(shí)符可由英文字母、數(shù)字、下劃線“_”和美元符號(hào)“$”組成,但要求第一個(gè)字母必須是英文字母或下劃線,如“half_adder”、“A”、“X1”等?!?bus”、“-adder”是不合法的標(biāo)識(shí)符。Verilog標(biāo)識(shí)符區(qū)分大小寫(xiě),如“A”和“a”是兩個(gè)不同的標(biāo)識(shí)符。

VerilogHDL允許使用轉(zhuǎn)義標(biāo)識(shí)符,目的是允許不同綜合、仿真工具間語(yǔ)法的轉(zhuǎn)換,其作用是標(biāo)識(shí)符中可以包含任意可打印字符。轉(zhuǎn)義標(biāo)識(shí)符以“\”開(kāi)始,到空格結(jié)束,但不包含“\”本身。

例如,下面都是合法的轉(zhuǎn)義標(biāo)識(shí)符:

\a+3*b

\{A,B}&3.2.2常量

在程序運(yùn)行過(guò)程中,其值不能改變的量稱(chēng)為常量。在VerilogHDL中有三類(lèi)常量:

1.邏輯值常量

除了邏輯值0和1,VerilogHDL增加了x(或X)和z(或Z)值。x代表不定態(tài),即未知值;z代表高阻態(tài)。VerilogHDL常量主要由這4種邏輯值構(gòu)成,其含義如表3.2.1所示。

2.數(shù)值型常量

1)整數(shù)

(1)整數(shù)表示。

VerilogHDL整數(shù)可使用十進(jìn)制(d或D)、二進(jìn)制(b或B)、十六進(jìn)制(h或H)或八進(jìn)制(o或O)表示,默認(rèn)為十進(jìn)制。在不指定位寬的情況下,一個(gè)十進(jìn)制數(shù)至少映射為一個(gè)32位(決定于機(jī)器字長(zhǎng))的二進(jìn)制值。

指定整數(shù)型常量位寬、進(jìn)制和數(shù)值的格式為

<位寬><‘進(jìn)制><數(shù)值>

位寬用來(lái)說(shuō)明數(shù)值對(duì)應(yīng)的二進(jìn)制數(shù)的位數(shù)。若指定位寬多于實(shí)際數(shù)值的位數(shù),則高位部分用0補(bǔ)齊;若指定位寬少于實(shí)際數(shù)值的位數(shù),則數(shù)值多出的高位部分被舍棄。進(jìn)制類(lèi)型用'd、'b、'h或'o表示,大小寫(xiě)均可;數(shù)值按指定進(jìn)制格式給出。若省略<位寬>說(shuō)明部分,則默認(rèn)位寬至少為32位。若省略<位寬><'進(jìn)制>兩個(gè)說(shuō)明部分,則默認(rèn)為十進(jìn)制,且位寬至少為32位。例如:

'hf1//十六進(jìn)制數(shù)f1,至少對(duì)應(yīng)為一個(gè)32位的二進(jìn)制數(shù)

5648//十進(jìn)制數(shù)5648,至少對(duì)應(yīng)為一個(gè)32位的二進(jìn)制數(shù)數(shù)值位數(shù)較多時(shí),為增加程序的可讀性,可在數(shù)位間增加下劃線“_”,但要注意,下劃線不能放置于數(shù)字開(kāi)始處。例如:

16‘b1001_0001_0010_1110

//16位二進(jìn)制數(shù)1001000100101110

8’b_1001_1101

//非法表示

VerilogHDL語(yǔ)法要求<位寬>與<‘進(jìn)制>間不可以有空格,<位寬>也不可以用表達(dá)式表示。

例如:

4’b1001//非法表示,<位寬>與<‘進(jìn)制>間不可以有空格

(2*4)'b1001_1101//非法表示,<位寬>不可以用表達(dá)式表示

(2)帶x和z值的數(shù)值表示。

在<位寬><‘進(jìn)制><數(shù)值>的定義格式中,通常情況下,數(shù)值部分出現(xiàn)的每個(gè)x或z的含義如下:

二進(jìn)制表示中,每個(gè)x或z代表1位邏輯x或z;

八進(jìn)制表示中,每個(gè)x或z代表3位邏輯x或z;

十六進(jìn)制表示中,每個(gè)x或z代表4位邏輯x或z。

例如:

4’b10zx//位寬為4的二進(jìn)制數(shù),最低位為未知狀態(tài)x,次低位為高阻態(tài)z

4‘o1z//位寬為4,低3位為高阻態(tài),最高位為1

8’hdx//位寬為8,低4位為任意值

但若x或z位于數(shù)值的最左邊,則綜合工具會(huì)將x或z補(bǔ)滿(mǎn)該數(shù)值左邊的所有位。例如:

8'bx//位寬為8,x擴(kuò)展為8位,等價(jià)于8'bxxxxxxxx(3)負(fù)數(shù)的數(shù)值表示。VerilogHDL負(fù)數(shù)定義格式為

<-><位寬><'進(jìn)制><數(shù)值>首先把數(shù)值轉(zhuǎn)換為負(fù)數(shù)補(bǔ)碼形式進(jìn)行存儲(chǔ),之后就將其看做無(wú)符號(hào)數(shù)。減號(hào)“-”必須置于位寬左邊,否則非法。例如:-8'd2//合法格式,以補(bǔ)碼存儲(chǔ),對(duì)應(yīng)的二進(jìn)制值為8'b111111108'd-2//非法格式若省略<位寬><'進(jìn)制>,則默認(rèn)為帶符號(hào)十進(jìn)制數(shù),對(duì)應(yīng)至少32位二進(jìn)制數(shù),以補(bǔ)碼形式存儲(chǔ),但之后作為帶符號(hào)數(shù)使用。例如:

-2//合法格式,以補(bǔ)碼存儲(chǔ),對(duì)應(yīng)為至少32位的二進(jìn)制數(shù)

//與上面-8'd2不同,-8'd2以8'b11111110存儲(chǔ),看做無(wú)符號(hào)數(shù)

2)字符串字符串是用雙引號(hào)括起來(lái)的字符序列,通常用在initial塊中給寄存器賦初值或用在仿真測(cè)試文件中。綜合工具或仿真工具將字符轉(zhuǎn)換為8位ASCII碼存儲(chǔ)。例如:

″AB″//合法格式,以ASCII碼存儲(chǔ),對(duì)應(yīng)的二進(jìn)制值為16'b01000001_01000010因?yàn)槊總€(gè)字符都以8位ASCII碼存儲(chǔ),所以對(duì)于字符串存儲(chǔ)需要定義足夠大的存儲(chǔ)器件。要在字符串中表示特殊字符,如非打印字符等,可以使用轉(zhuǎn)義字符表示。Verilog

HDL字符串中的轉(zhuǎn)義字符及其含義如表3.2.2所示。

3.參數(shù)常量

parameter用于定義參數(shù)常量,以提高程序的可讀性和可維護(hù)性。參數(shù)常量定義格式如下:

parameter常量名1=表達(dá)式,常量名2=表達(dá)式,…;例如:

parameterSIZE=8,LONG=16;

parmeterr=5;

parameterf=2*r;下面通過(guò)代碼3.2.1說(shuō)明參數(shù)常量的典型用法。代碼3.2.1簡(jiǎn)易運(yùn)算器模塊。modulehalf_adder(op,a,b,c);代碼3.2.1可實(shí)現(xiàn)簡(jiǎn)易運(yùn)算器,根據(jù)輸入的op,完成兩個(gè)8位二進(jìn)制數(shù)a、b的加、減、與運(yùn)算及b的取非運(yùn)算。代碼首先定義了參數(shù)常量SIZE,用SIZE定義a、b和c的位寬。語(yǔ)句“input[SIZE-1:0]a,b”聲明a、b是兩個(gè)8位寬的輸入信號(hào)。語(yǔ)句“outputreg[SIZE-1:0]c”的功能類(lèi)似,但將c聲明為reg型輸出。代碼又定義操作碼參數(shù)常量addop、subop、andop、notop作為運(yùn)算操作選項(xiàng),由case選擇實(shí)現(xiàn)不同的運(yùn)算。使用參數(shù)常量的優(yōu)點(diǎn)是,若要修改位寬或操作碼取值,只需重新設(shè)置parameter常數(shù),而不用修改代碼本身,便于程序維護(hù)。例如,代碼3.2.2引用代碼3.2.1所示簡(jiǎn)易運(yùn)算器模塊,在引用模塊時(shí),通過(guò)參數(shù)設(shè)置模塊定義的parameter值,可方便地重定義輸入/輸出信號(hào)位寬,實(shí)現(xiàn)16位運(yùn)算。代碼3.2.2引用代碼3.2.1所示模塊,實(shí)現(xiàn)16位運(yùn)算。modulemy_alu(op,a,b,c);

input[15:0]a,b;

input[1:0]op;

output[15:0]c;

simple_alu#16u1(op,a,b,c);endmodule語(yǔ)句“simple_alu#16u1(op,a,b,c)”引用模塊simple_alu,用參數(shù)#16將SIZE修改為16,即將運(yùn)算器位寬設(shè)置為16位,然后將my_alu模塊的變量op、a、b、c依次與simple_alu模塊的變量op、a、b、c連接。通過(guò)只修改參數(shù),將8位運(yùn)算器變?yōu)?6位運(yùn)算器。若將代碼3.2.2中的實(shí)例引用語(yǔ)句改為如下的語(yǔ)句:

simple_alu#(16,2'b11,2'b10,2'b01,2'b00)u1(op,a,b,c);則除了將實(shí)例的SIZE修改為16外,還依次使實(shí)例的addop=2'b11,subop=2'b10,andop=2'b01,notop=2'b00。這使得16位的簡(jiǎn)易運(yùn)算器在op=2'b11時(shí)做加法運(yùn)算,op=2'b10時(shí)做減法運(yùn)算,op=2'b01時(shí)做與運(yùn)算,op=2'b00時(shí)對(duì)b取非,改變了操作代碼。3.2.3變量

1.wire型

wire型屬于線網(wǎng)(Net)類(lèi)型,主要用來(lái)表示結(jié)構(gòu)實(shí)體(邏輯門(mén)和實(shí)例化的模塊等)之間的物理連接。wire型變量不能存儲(chǔ)值,所以必須受驅(qū)動(dòng)器驅(qū)動(dòng)。若沒(méi)有驅(qū)動(dòng)器連接到wire型的變量上,變量值即為高阻z。驅(qū)動(dòng)wire型變量的方法通常有兩種:一種是將它連接到實(shí)例化元件或模塊的輸出;另一種是用assign語(yǔ)句對(duì)其賦值。如圖3.2.1所示電路結(jié)構(gòu)采用原理圖建模,輸出L隱含定義為wire型,由a、b驅(qū)動(dòng)。圖3.2.1所示電路結(jié)構(gòu)也可以用實(shí)例化元件方式或assign語(yǔ)句建模,程序如下:

wireL;

rega,b;

oru1(L,a,b);或wireL;

rega,b;

assignL=a|b;

wire型變量的說(shuō)明格式如下:

wire[msb:lsb]變量名1,變量名2,…;其中,msb表示位寬的最高位;lsb表示位寬的最低位。相同位寬的變量可在一條語(yǔ)句中聲明,使用逗號(hào)“,”分隔。wire型變量被說(shuō)明時(shí),若未指定位寬則省略“[msb:lsb]”,默認(rèn)為1位寬。模塊輸入/輸出端口若未說(shuō)明為reg型,則隱含為wire型。例如:

wirea,b;//定義了位寬為1的wire型變量a、b

wire[7:0]abus;//定義了位寬為8的wire型變量abus,通常用作總線

wire[31:2]b1,b2;

2.reg型

reg型變量是數(shù)據(jù)存儲(chǔ)單元的抽象,但并不與觸發(fā)器對(duì)應(yīng)。reg型變量只能在initial語(yǔ)句塊或always語(yǔ)句塊中被賦值,且賦值可被保存下來(lái),直到下次改變。reg型變量沒(méi)有被賦值前,其值為x。

reg型變量說(shuō)明的格式與wire型變量說(shuō)明類(lèi)似,為

reg[msb:lsb]變量名1,變量名2,…;其中,msb表示位寬的高位;lsb表示位寬的低位。相同位寬的變量可在一條語(yǔ)句中聲明,使用逗號(hào)“,”分隔。例如:

rega,b;

reg[7:0]ra;//定義了位寬為8的reg型變量ra

reg[31:2]b1,b2;//定義了位寬為30的reg型變量,最高位為第31位,最低位為第2位

reg型變量與wire型類(lèi)似,也是向量型變量,因此可以按下標(biāo)訪問(wèn)其中的元素,例如:

ra[7]^ra[6]。

3.memory型在VerilogHDL中,可以通過(guò)定義reg型的數(shù)組來(lái)說(shuō)明memory型變量,構(gòu)建存儲(chǔ)器,用于對(duì)ROM、RAM等的建模。memory型數(shù)據(jù)定義格式如下:

reg[msb:lsb]memory型變量名[m-1:0];或

reg[msb:lsb]memory型變量名[m:1];這里每個(gè)memory型變量都是一個(gè)reg型數(shù)組,每個(gè)數(shù)組元素稱(chēng)為一個(gè)存儲(chǔ)單元。[msb:lsb]說(shuō)明每個(gè)存儲(chǔ)單元的位寬,“memory型變量名[m-1:0]”或“memory型變量名[m:1]”說(shuō)明數(shù)組名稱(chēng)以及數(shù)組元素的下標(biāo)范圍,也說(shuō)明該存儲(chǔ)器中有多少個(gè)這樣的寄存器。如果要對(duì)memB賦值,必須指定存儲(chǔ)單元的下標(biāo),也就是這個(gè)單元在存儲(chǔ)器中的地址。例如:

memB[0]=1'b1;需要說(shuō)明的是,上述賦值語(yǔ)句不能單獨(dú)出現(xiàn)在模塊中,需要寫(xiě)在過(guò)程塊語(yǔ)句中。memory單元的賦值通常在initial塊中完成。例如:initialbegin memB[0]=1'b1; memB[1]=1'b1; memB[2]=1'b0;

mmemB[3]=1'b1;end使用reg數(shù)組定義的memory型變量并不是完全意義上的存儲(chǔ)器,且比較耗費(fèi)PLD器件資源,因此,在復(fù)雜電路系統(tǒng)設(shè)計(jì)時(shí),建議使用PLD器件內(nèi)部嵌入的存儲(chǔ)器資源。

4.數(shù)字型在VerilogHDL中,整數(shù)(integer)、實(shí)數(shù)(real)和時(shí)間(time)型變量都是數(shù)字型寄存器變量。但real和time型變量不可綜合,主要用于仿真測(cè)試環(huán)境,因此,下面介紹integer型變量。

integer型變量說(shuō)明格式如下:

integer變量名1,變量名2,…;

integer型變量與reg型變量都是寄存器型變量,不同之處在于:①integer型變量不允許說(shuō)明位寬,因此綜合時(shí)至少綜合為32位二進(jìn)制數(shù),具體位數(shù)取決于機(jī)器字長(zhǎng);②integer型變量將存儲(chǔ)的數(shù)據(jù)看做帶符號(hào)數(shù),用補(bǔ)碼表示,而reg型變量將存儲(chǔ)的數(shù)據(jù)看做無(wú)符號(hào)數(shù)。例如:

reg[7:0]a,b;

reg[3:0]c;

integeri;

initial

begin

c=-1;//c賦值為4'b1111,即-1的補(bǔ)碼表示

i=-1;//i賦值為32'hffff,即-1的補(bǔ)碼表示

b=c;//b賦值為8'h0f,c作為無(wú)符號(hào)數(shù)

a=i;//a賦值為8'hff

end這個(gè)例子只為說(shuō)明integer型與reg型變量的不同,但給c賦值為-1(32位),將i賦值給a、c賦值給b在位寬方面都是不匹配的,在實(shí)際應(yīng)用時(shí)應(yīng)盡量避免。由于reg型和integer型都是寄存器變量,要在過(guò)程塊語(yǔ)句中賦值,所以使用了initial塊。雖然integer型變量也屬于寄存器變量,可以進(jìn)行與reg型類(lèi)似的操作,但通常用reg型來(lái)描述寄存器邏輯,而將integer型用于循環(huán)變量和計(jì)數(shù)。1.算術(shù)運(yùn)算符

算術(shù)運(yùn)算符包括:

+(加法運(yùn)算符或正值運(yùn)算符,如x+y,+8)

-(減法運(yùn)算符或負(fù)值運(yùn)算符,如x-y,-90)

*(乘法運(yùn)算符,如x*y)

/(除法運(yùn)算符,如x/y)

%(取模運(yùn)算符,如x%y)3.3VerilogHDL的運(yùn)算符

2.邏輯運(yùn)算符

邏輯運(yùn)算符把它的操作數(shù)當(dāng)做布爾量,非零的操作數(shù)看做真(1‘b1),零操作數(shù)看做假(1’b0),進(jìn)行邏輯運(yùn)算,運(yùn)算返回邏輯假(1‘b0)或真(1’b1)。

邏輯運(yùn)算符包括:

&&(邏輯與)

||(邏輯或)

!(邏輯非)設(shè)a=4‘b1001,b=4’b0000,c=2‘b1x,在邏輯運(yùn)算中,a被看做真,值為1’b1;b被看做假,值為1‘b0;c因?yàn)椴荒芘袛嗾婕?所以值為不確定的1’bx。當(dāng)一個(gè)操作數(shù)為x時(shí),邏輯運(yùn)算的結(jié)果也是x,所以

a&&b=1‘b0

a||b=1’b1

!b=1‘b1

!a=1’b0

a&&c=1‘bx

!c=1'bx

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

關(guān)系運(yùn)算符對(duì)兩個(gè)操作數(shù)進(jìn)行大小比較,運(yùn)算結(jié)果為布爾值真(1‘b1)或假(1’b0)。

關(guān)系運(yùn)算符包括:

>

(大于)

>=

(大于或等于)

<

(小于)

<=

(小于或等于)

若比較判斷的結(jié)果為真,則返回1'b1;否則返回1'b0。設(shè)a=4'b1111,b=4'b0101,則a>=b返回1'b1,a<b返回1'b0。若兩個(gè)操作數(shù)中有未知值x,則返回結(jié)果也為x。關(guān)系運(yùn)算符通常和邏輯運(yùn)算符一起構(gòu)成多條件判斷的表達(dá)式。例如:

parameterLength=4‘b0101;

(a>b)||(a<c)

//a>b或a<c時(shí)返回1’b1

(a>=4‘b0)&&(a<=Length-1)//0≤a≤4時(shí)返回1’b1

關(guān)系運(yùn)算優(yōu)先級(jí)別小于邏輯運(yùn)算,也小于算術(shù)運(yùn)算,必要時(shí)需要使用括號(hào)。

4.位運(yùn)算符

位運(yùn)算是將操作數(shù)按對(duì)應(yīng)位逐位操作的運(yùn)算符,包括:

&(按位與運(yùn)算)

|(按位或運(yùn)算)

~(按位取反運(yùn)算,單目運(yùn)算符)

^(按位異或運(yùn)算)

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

例如:

ra=4'b1101;

rb=8'b10110011;

ra=~ra;//ra的值按位取反,賦值為4'b0010

rb=ra^rb;//rb=0000_0010^1011_0011,結(jié)果為1011_0001

5.等值運(yùn)算符

等值運(yùn)算符對(duì)兩個(gè)操作數(shù)是否相等進(jìn)行判斷,返回邏輯值真或假。

等值運(yùn)算符包括:

==(相等判斷)

!=(不等判斷)

===(全等判斷)

!==(不全等判斷)

“==”和“===”,“!=”和“!===”的區(qū)別在于,前者只對(duì)兩個(gè)數(shù)是否相等或不等進(jìn)行判斷,若待判斷的數(shù)含有x或z,判斷結(jié)果不能確定時(shí),則返回x;后者按兩個(gè)操作數(shù)的對(duì)應(yīng)位進(jìn)行逐位判斷,對(duì)對(duì)應(yīng)位是否同為x或同為z也進(jìn)行判斷。“==”和“===”的運(yùn)算規(guī)則如表3.3.1所示。設(shè)a=3,b=5,都為十進(jìn),c=4'b110,d=4'b11x,e=4'bx110,f=4'bxx11;則a==b返回1'b0,c!=d返回1'bx,c!=f返回1'b1,d===f返回1'b0,c!==d返回1'b1?!?=”和“!=”運(yùn)算符可綜合,能被綜合為比較器;“===”和“!==”運(yùn)算符不可綜合。

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

移位運(yùn)算符有“?”和“?”兩種,分別對(duì)操作數(shù)進(jìn)行左移或右移操作,使用格式如下:

a?n

//將操作數(shù)a左移n位

a?n

//將操作數(shù)a右移n位

兩種移位方式都是將移空的位用0補(bǔ)齊,移出范圍的位舍棄。例如:

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

initial

begin

a=8‘b11011;

b=(a?2);//a左移兩位后等于8’b01101100,賦值給b

c=(a?2);//a右移兩位后等于8‘b00000110,賦值給c

end

7.縮減運(yùn)算符

縮減運(yùn)算符是VerilogHDL特有的運(yùn)算符,它能將多位二進(jìn)制操作數(shù)按一定規(guī)則縮減為1位二進(jìn)制數(shù),即能將向量縮減為標(biāo)量??s減運(yùn)算是單目運(yùn)算,其運(yùn)算過(guò)程是將向量最低位(第0位)與次低位(第1位)進(jìn)行運(yùn)算,得到的結(jié)果再與第2位進(jìn)行運(yùn)算,運(yùn)算結(jié)果再與第3位進(jìn)行運(yùn)算,直到得到1位二進(jìn)制結(jié)果。例如,假設(shè):

reg[3:0]a;

regb;

則b=&a就是對(duì)a的各位按與運(yùn)算進(jìn)行縮減,運(yùn)算過(guò)程等價(jià)于:

b=((a[0]&a[1])&a[2])&a[3];

縮減運(yùn)算符包括:

&

(按與運(yùn)算縮減)

|

(按或運(yùn)算縮減)

^

(按異或運(yùn)算縮減)

~&

(按與非運(yùn)算縮減)

~|

(按或非運(yùn)算縮減)

~^

(按異或非(同或)運(yùn)算縮減)例如:

//判斷a值是否為全1,若是,給b賦值為1;否則給b賦值為0

reg[15:0]a;

regb;

always@(a)

if(&a==1'b1)//若“&a==1'b1”為真,則a值為16位全1

b=1'b1;

else

b=1'b0;

8.條件運(yùn)算符

拼接運(yùn)算符能夠?qū)⒉煌盘?hào)的指定位或一個(gè)信號(hào)的指定位拼接為一個(gè)二進(jìn)制數(shù)。拼接運(yùn)算符格式如下:

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

若信號(hào)i指定的某些位位置連續(xù),可用[msb:lsb]說(shuō)明msb~lsb間連續(xù)的若干位。

例如,假設(shè):

a=4‘b0010,b=8’b11110110,c=1‘b1;

那么:

{a[1:0],b[2],c,b[3:0]}=8'b10110110;位拼接表達(dá)式中不允許存在沒(méi)有指明位數(shù)的信號(hào),因?yàn)檫\(yùn)算過(guò)程不能判定需要拼接幾位。若某些位需要連續(xù)拼接幾次,可以使用下面的格式說(shuō)明重復(fù)次數(shù):

{[重復(fù)次數(shù)]{信號(hào)1的某些位,信號(hào)2的某些位,…}}

{信號(hào)1的某些位,信號(hào)2的某些位,…}內(nèi)的信號(hào)將被重復(fù)“[重復(fù)次數(shù)]”次。

例如:

{{3{a[1:0]}},{2{1'b0}},{2{b[1],b[3]}}}=12'b101010001010;

上面格式中,“[重復(fù)次數(shù)]”必須是常數(shù)表達(dá)式。

9.條件運(yùn)算符

條件運(yùn)算符“?:”是一個(gè)三目運(yùn)算符,格式如下:

<條件表達(dá)式>?<表達(dá)式1>:<表達(dá)式2>

若條件表達(dá)式為真,則結(jié)果為表達(dá)式1的值;否則結(jié)果為表達(dá)式2的值。

例如:

assigny=sel?a:b;//若sel值為0,則y=a;否則y=b

//下例中條件表達(dá)式(2‘b10<2’b11)為假,所以k被賦值為3‘b000

assignk=(2'b10<2'b11)?3'b111:3'b000;

10.運(yùn)算符的優(yōu)先級(jí)

當(dāng)上述運(yùn)算符出現(xiàn)在同一個(gè)表達(dá)式中時(shí),按照表3.3.2所示的優(yōu)先級(jí)進(jìn)行運(yùn)算。若要改變運(yùn)算順序,則需要用括號(hào)。3.4VerilogHDL常用建模方式3.4.1VerilogHDL門(mén)級(jí)建模門(mén)級(jí)建模是指通過(guò)引用VerilogHDL預(yù)定義的基本門(mén)級(jí)元件(原語(yǔ)),并定義元件之間的連接關(guān)系來(lái)構(gòu)建電路的方式,可使用的基本門(mén)級(jí)元件如表3.4.1所示。門(mén)級(jí)元件的輸入/輸出連接必須是線網(wǎng)類(lèi)型的變量,當(dāng)輸入為x或z時(shí),依據(jù)其邏輯運(yùn)算產(chǎn)生相應(yīng)的0、1、x或z。

1.多輸入門(mén)

and、or、xor、nand、nor和xnor門(mén)都是多輸入/輸出的門(mén)電路,引用時(shí)需要將輸出端連接至第一個(gè)端口,其他連接至輸入端口。引用時(shí)可以給出實(shí)例名稱(chēng),也可以省略。例如:norGnor1(out,in1,in2,in3);//生成一個(gè)三輸入的或非門(mén),實(shí)例名稱(chēng)為Gnor1xor(out,in1,in2);

//生成一個(gè)二輸入的異或門(mén),沒(méi)有定義實(shí)例名稱(chēng)and、or和xor門(mén)的功能如表3.4.2所示;nand、nor和xnor的功能如表3.4.3所示。2.多輸出門(mén)buf和not圖3.4.1buf和not門(mén)邏輯符號(hào)(a)緩沖器buf;(b)反相器not例如:

notG1(out,in);

//單輸出非門(mén)

notG2(out1,out2,out3,in);//三輸出非門(mén)

bufG3(out1,out2,in);

//二輸出緩沖器

3.三態(tài)門(mén)三態(tài)門(mén)由控制端決定輸出是高阻還是正常邏輯狀態(tài)。三態(tài)門(mén)的邏輯符號(hào)如圖3.4.2所示。其中,bufif1和notif1在控制端為高電平時(shí)按正常邏輯態(tài)工作,稱(chēng)為高電平有效的三態(tài)緩沖器和三態(tài)反相緩沖器;bufif0和notif0在控制端為低電平時(shí)按正常邏輯態(tài)工作,稱(chēng)為低電平有效的三態(tài)緩沖器和三態(tài)反相緩沖器。三態(tài)緩沖器功能如表3.4.5所示;三態(tài)反相緩沖器功能如表3.4.6所示。圖3.4.2三態(tài)門(mén)邏輯符號(hào)(a)bufif1;(b)bufif0;(c)notif1;(d)notif0功能表中,0/z表明三態(tài)門(mén)的輸出可能是0,也可能是高阻態(tài),由輸入的數(shù)據(jù)信號(hào)和控制信號(hào)強(qiáng)度決定。有興趣的讀者可參考有關(guān)文獻(xiàn)。三態(tài)門(mén)實(shí)例化時(shí),第一個(gè)端口連接至輸出,第二個(gè)端口連接至輸入,第三個(gè)端口連接至控制信號(hào)。例如:

bufif1G1(out1,in1,ctrl1);//實(shí)例化高電平有效的三態(tài)緩沖器G1,輸出端為out1,//輸入端為in1,控制端為ctrl1

notfif0(out2,in2,ctrl2);//實(shí)例化低電平有效的三態(tài)反相緩沖器,輸出端為out2,//輸入端為in2,控制端為ctrl24.門(mén)級(jí)建模示例【例3.4.1】試對(duì)表3.4.7描述的邏輯電路進(jìn)行門(mén)級(jí)建模。解依據(jù)真值表,寫(xiě)出函數(shù)邏輯表達(dá)式:圖3.4.3例3.4.1的邏輯電路圖3.4.2VerilogHDL數(shù)據(jù)流建模

1.連續(xù)賦值語(yǔ)句assign連續(xù)賦值語(yǔ)句指定驅(qū)動(dòng)的線網(wǎng)變量以及驅(qū)動(dòng)該線網(wǎng)變量的表達(dá)式。連續(xù)賦值語(yǔ)句有兩種描述格式。格式1:

assign變量名1=表達(dá)式1,變量名2=表達(dá)式2,…;格式2:

wire[msg:lsb]變量名1=表達(dá)式1,變量名2=表達(dá)式2,…;說(shuō)明:

(1)assign語(yǔ)句完整的說(shuō)明格式包括指定變量的驅(qū)動(dòng)強(qiáng)度和延遲時(shí)間等,但綜合工具不能處理,所以此處不予列出。

(2)變量必須是wire類(lèi)型。變量可以用wire語(yǔ)句顯式聲明,也可以是通過(guò)output語(yǔ)句聲明的輸出變量,此時(shí)默認(rèn)為wire型。例如:moduleassignTest(a,b,c); input[3:0]a,b; output[3:0]c; wire[3:0]m; assignm=~a; assignc=m&~b;endmodule

(3)格式2將變量聲明與賦值過(guò)程在一條語(yǔ)句中完成,可以不使用關(guān)鍵字assign。兩種格式效果相同。例如:

wire[3:0]m;

assignm=~a;可替換成下面語(yǔ)句:

wire[3:0]m=~a;

(4)連續(xù)賦值語(yǔ)句可以位于模塊內(nèi)任意位置處,但不可以位于initial和always過(guò)程塊內(nèi)部。

(5)連續(xù)賦值語(yǔ)句可以綜合成組合邏輯電路。2.數(shù)據(jù)流建模舉例【例3.4.2】試對(duì)表3.4.8描述的邏輯電路進(jìn)行數(shù)據(jù)流建模。3.4.3VerilogHDL行為建模

1.過(guò)程塊語(yǔ)句過(guò)程塊語(yǔ)句可包含一條或多條過(guò)程語(yǔ)句構(gòu)成過(guò)程塊,當(dāng)包含多條語(yǔ)句時(shí),需要使用begin…end關(guān)鍵字。過(guò)程塊內(nèi)部各語(yǔ)句按順序執(zhí)行,過(guò)程塊之間以及與連續(xù)賦值語(yǔ)句之間并行執(zhí)行。always語(yǔ)句是最常用的過(guò)程塊語(yǔ)句之一。1)always語(yǔ)句always語(yǔ)句格式如下:

always<@(敏感事件列表)>

<begin:塊名>

<塊內(nèi)局部變量定義;>過(guò)程賦值語(yǔ)句;

<end>說(shuō)明:

(1)敏感事件列表允許有多個(gè)變量,使用關(guān)鍵字“or”或逗號(hào)“,”分隔,意思是等待確定的事件發(fā)生或某一特定條件變?yōu)椤罢妗?就執(zhí)行后邊的過(guò)程塊。所以過(guò)程塊的執(zhí)行是多次重復(fù)的過(guò)程,若不列出敏感事件,always塊就會(huì)無(wú)限循環(huán)執(zhí)行。

(2)敏感事件可以是信號(hào)的電平發(fā)生變化,這時(shí)可用信號(hào)名作為敏感事件列表,例如“@(AorB)”;也可以是信號(hào)的上升沿或下降沿到來(lái),上升沿使用posedge信號(hào)名,下降沿使用negedge信號(hào)名,例如“@(posedgeclkornegedgereset)”。

(3)過(guò)程塊內(nèi)有多條語(yǔ)句時(shí),必須寫(xiě)在begin…end塊中。begin…end塊可以命名,取了名字的塊稱(chēng)為有名塊。

(4)begin…end塊內(nèi)的語(yǔ)句順序執(zhí)行,稱(chēng)為順序塊。

(5)過(guò)程塊內(nèi)的賦值語(yǔ)句稱(chēng)為過(guò)程賦值語(yǔ)句,使用符號(hào)“=”或“<=”實(shí)現(xiàn)。過(guò)程賦值語(yǔ)句左邊的變量必須為reg型。

(6)一個(gè)模塊中可以有多個(gè)always塊,它們都并行執(zhí)行。對(duì)同一變量的賦值修改應(yīng)放在一個(gè)always塊中完成。雖然always語(yǔ)句可綜合,但并不針對(duì)所有的書(shū)寫(xiě)方式。為確保其綜合性,建議按下面的always電路塊建模方式書(shū)寫(xiě)。

(1)方式1。

always@(in1orin2or…)//所有的輸入信號(hào)必須都列出

begin

?

end輸入信號(hào)只要有變化就會(huì)引起輸出變化。這種結(jié)構(gòu)通常用于組合邏輯電路建模。

(2)方式2。

always@(enableorin1orin2or…)//所有的輸入信號(hào)都必須列出

if(enable)

//使能信號(hào)決定電路是否動(dòng)作

begin

?

end

(3)方式3。

always@(posedgeclock)

//僅列出時(shí)鐘信號(hào)

begin

?

end該方式通常用于時(shí)序邏輯電路建模,always塊中所有的動(dòng)作都在clock時(shí)鐘上升沿發(fā)生,所建模型是同步時(shí)序邏輯電路。(4)方式4。always@(posedgeclockornegedg/e/r列es出et時(shí))鐘信號(hào)和異步信號(hào)

if(!reset)

?//異步動(dòng)作

else

begin

?//同步動(dòng)作end敏感事件包括異步信號(hào)reset和時(shí)鐘信號(hào)clock,reset下降沿引發(fā)的電路動(dòng)作并不受clock約束,所以是異步動(dòng)作。在非reset狀態(tài)下,所有的電路動(dòng)作都在clock時(shí)鐘上升沿發(fā)生,是同步動(dòng)作。always語(yǔ)句使用舉例如下:modulehalf_adder(a,b,en,c);inputa,b,en;outputreg[1:0]c;always@(aorboren)//列出所有輸入信號(hào)if(en)//使能信號(hào)有效時(shí),執(zhí)行順序塊beginc[1]=a^b;c[0]=a^~b;endendmodule2)initial語(yǔ)句initial語(yǔ)句也是過(guò)程塊語(yǔ)句,它所包含的過(guò)程塊不能綜合為實(shí)際的電路塊,但是可用于給電路中的reg型變量或memory單元賦初值,只執(zhí)行一遍。initial塊常用于測(cè)試文件的編寫(xiě),用來(lái)產(chǎn)生仿真測(cè)試信號(hào)的仿真環(huán)境。對(duì)仿真程序來(lái)說(shuō),initial塊只在仿真一開(kāi)始執(zhí)行一次。initial語(yǔ)句格式如下:initial<begin>一條或多條過(guò)程賦值語(yǔ)句;<end>說(shuō)明:(1)initial塊中有多條語(yǔ)句時(shí),必須寫(xiě)在begin…end塊中。(2)initial塊中使用過(guò)程賦值語(yǔ)句,賦值語(yǔ)句左邊的變量必須是reg型。(3)一個(gè)模塊中可以有多個(gè)initial塊,它們都并行運(yùn)行。

2.過(guò)程賦值語(yǔ)句過(guò)程賦值語(yǔ)句是只能在過(guò)程塊中賦值的語(yǔ)句,可分為阻塞賦值語(yǔ)句(賦值符為“=”)和非阻塞賦值語(yǔ)句(賦值符為“<=”)。過(guò)程賦值語(yǔ)句使用格式如下:變量名=表達(dá)式;

//例如a=b;變量名<=表達(dá)式;

//例如a<=b;說(shuō)明:

(1)過(guò)程賦值語(yǔ)句必須書(shū)寫(xiě)在always或initial過(guò)程塊中,賦值的變量必須是reg型。

(2)當(dāng)過(guò)程塊包含多個(gè)阻塞賦值語(yǔ)句時(shí),這些語(yǔ)句按順序執(zhí)行,且前邊的語(yǔ)句會(huì)阻塞后邊語(yǔ)句的執(zhí)行。也就是說(shuō),只有前邊語(yǔ)句執(zhí)行結(jié)束,后邊的語(yǔ)句才開(kāi)始執(zhí)行。例如:

begin

a=b;

c=a;

end若執(zhí)行前a值為5,b值為8,則執(zhí)行“a=b”會(huì)使得a值為8,之后執(zhí)行“c=a”會(huì)使得c值也變?yōu)?。

(3)當(dāng)過(guò)程塊包含多個(gè)非阻塞賦值語(yǔ)句時(shí),這些語(yǔ)句在過(guò)程塊結(jié)束時(shí)同時(shí)執(zhí)行,不會(huì)相互阻塞。例如:

begin

a<=b;

c<=a;

end若執(zhí)行前a值為5,b值為8,則過(guò)程塊結(jié)束時(shí),“a<=b”和“c<=a”同時(shí)執(zhí)行,會(huì)使得a值為8,同時(shí)使得c值為5。

(4)說(shuō)明(2)中描述的例子,只會(huì)綜合出一個(gè)存儲(chǔ)部件,存儲(chǔ)值為8,但是會(huì)有兩個(gè)輸出的名字,分別是a和c。說(shuō)明(3)中描述的例子,會(huì)綜合出兩個(gè)存儲(chǔ)部件,分別存儲(chǔ)a和c,值分別是8和5。

(5)在可綜合電路的設(shè)計(jì)中,一個(gè)語(yǔ)句塊內(nèi)部不允許同時(shí)出現(xiàn)阻塞賦值和非阻塞賦值語(yǔ)句。

(6)組合邏輯電路設(shè)計(jì)中一般采用阻塞賦值,時(shí)序邏輯電路設(shè)計(jì)中一般采用非阻塞賦值。

3.條件語(yǔ)句條件語(yǔ)句包括if語(yǔ)句和多路選擇case語(yǔ)句,用于在過(guò)程塊內(nèi)描述電路行為。

1)

if語(yǔ)句

if語(yǔ)句用來(lái)判斷給定的條件是否滿(mǎn)足,根據(jù)判定的結(jié)果為真或假?zèng)Q定執(zhí)行的操作。VerilogHDL提供了三種形式的if語(yǔ)句。if語(yǔ)句描述格式1:

if(條件表達(dá)式)語(yǔ)句;

if語(yǔ)句描述格式2:

if(條件表達(dá)式)語(yǔ)句;

else語(yǔ)句;

if語(yǔ)句描述格式3:

if(條件表達(dá)式1)語(yǔ)句;

elseif(條件表達(dá)式2)語(yǔ)句;elseif(條件表達(dá)式3)語(yǔ)句;?else語(yǔ)句;例如:

if(a&&b)

d=2'b11;

elseif(a)

d=2'b10;

elseif(b)

d=2'b01;

else

d=2'b00;說(shuō)明:

(1)if語(yǔ)句必須寫(xiě)在過(guò)程塊內(nèi)。若每個(gè)部分語(yǔ)句有多條,則必須寫(xiě)在begin…end塊中。

(2)在格式3中,else和最近的if語(yǔ)句配對(duì)

2)多路選擇case語(yǔ)句嵌套的if語(yǔ)句有時(shí)會(huì)被綜合成多層邏輯,case語(yǔ)句則可避免這類(lèi)問(wèn)題發(fā)生。

case語(yǔ)句格式如下:

case(case表達(dá)式)分支項(xiàng)表達(dá)式1:語(yǔ)句1;分支項(xiàng)表達(dá)式2:語(yǔ)句2;

?

default:default語(yǔ)句;

endcase例如:

case(addrin)

2'b00:dataout<=din1;

2'b01,2'b10:dataout<=din2;

default:dataout<=din0;

endcase說(shuō)明:

(1)case語(yǔ)句要寫(xiě)在過(guò)程塊內(nèi)。每個(gè)分支項(xiàng)中語(yǔ)句多于一條時(shí),必須寫(xiě)在begin…end塊中。

(2)一條case語(yǔ)句只允許有一個(gè)default分支,覆蓋所有沒(méi)有列出的分支項(xiàng)。若case表達(dá)式?jīng)]有任何匹配的分支項(xiàng),case語(yǔ)句又沒(méi)有default選項(xiàng),則該case語(yǔ)句沒(méi)有作用。

(3)分支項(xiàng)表達(dá)式不進(jìn)行重復(fù)檢查,執(zhí)行時(shí)會(huì)找到第一個(gè)匹配的分支項(xiàng)執(zhí)行。所以若兩個(gè)分支項(xiàng)被錯(cuò)誤地寫(xiě)成了相同的,綜合程序不會(huì)報(bào)錯(cuò)。

(4)若幾個(gè)分支項(xiàng)執(zhí)行相同的語(yǔ)句,則可以將它們用逗號(hào)分隔,共用執(zhí)行語(yǔ)句,如上例中的第二個(gè)case選項(xiàng)。

4.循環(huán)語(yǔ)句

VerilogHDL有四種循環(huán)語(yǔ)句,分別是forever循環(huán)語(yǔ)句,for循環(huán)語(yǔ)句,repeat循環(huán)語(yǔ)句和while循環(huán)語(yǔ)句。

forever循環(huán)語(yǔ)句會(huì)以無(wú)條件方式執(zhí)行語(yǔ)句區(qū)塊,不能綜合,只能寫(xiě)在initial過(guò)程塊中,通常用來(lái)描述仿真時(shí)序波形。下面主要介紹for循環(huán)語(yǔ)句、repeat循環(huán)語(yǔ)句和while循環(huán)語(yǔ)句。

1)for循環(huán)語(yǔ)句

for循環(huán)語(yǔ)句的語(yǔ)法格式如下:

for(表達(dá)式1;條件表達(dá)式2;表達(dá)式3)語(yǔ)句;執(zhí)行時(shí),首先使用表達(dá)式1給循環(huán)變量賦初值;然后判斷條件表達(dá)式2是否成立,若條件表達(dá)式2的值為真,則執(zhí)行后邊的語(yǔ)句塊,否則退出循環(huán);語(yǔ)句塊執(zhí)行結(jié)束后,執(zhí)行表達(dá)式3修改循環(huán)變量。若語(yǔ)句塊多于一條語(yǔ)句,則必須寫(xiě)在begin…end塊中。例如,使用for循環(huán)給存儲(chǔ)器單元賦初值:integeri;reg[7:0]memA[63:0];initialfor(i=0;i<64;i=i+1)

memA[i]=8'b0;

【例3.4.3】使用for循環(huán)語(yǔ)句通過(guò)移位相加的方法對(duì)8位二進(jìn)制乘法器建模。

解以?xún)蓚€(gè)4位二進(jìn)制數(shù)opA=4,b0110、opB=4'b1101的乘法運(yùn)算為例,乘法過(guò)程如圖3.4.4(a)所示。二進(jìn)制乘法規(guī)則簡(jiǎn)單:0×0=0,0×1=0,1×1=1,所以乘法的關(guān)鍵在于累積相加的部分。豎式中累積相加的部分就是將被乘數(shù)或0(取決于乘數(shù)的當(dāng)前位為1還是0)錯(cuò)位相加,最終結(jié)果會(huì)是一個(gè)8位二進(jìn)制數(shù)。這個(gè)過(guò)程可用圖3.4.4(b)中的加法表示或代替。圖3.4.4(b)中的加法首先設(shè)置一個(gè)全0的部分積result=8'b00000000,然后加上被乘數(shù)左移0次得到的00000110,左移2次得到的00011000以及左移3次得到的00110000,累加結(jié)果即為乘積。因?yàn)槌藬?shù)第1位為0,所以部分積不加被乘數(shù)左移1次的結(jié)果。按照這一思路,8位二進(jìn)制數(shù)乘法電路的Verilog描述代碼如下:modulemultiplier(result,opA,opB);

parametersize=8,longsize=16;

input[size-1:0]opA,opB;

outputreg[longsize-1:0]result;

always@(opAoropB)

begin

integerindex;

result=0;

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

if(opB[index]==1)圖3.4.4例3.4.3的乘法過(guò)程描述(a)手工乘法過(guò)程;(b)移位相加實(shí)現(xiàn)乘法

result=result+(opA?index);

endendmodule2)while循環(huán)語(yǔ)句while語(yǔ)句的語(yǔ)法格式如下:

while(條件表達(dá)式)語(yǔ)句;條件表達(dá)式值為真時(shí),執(zhí)行語(yǔ)句;否則不執(zhí)行。條件表達(dá)式值為x或z時(shí),也看做假。若語(yǔ)句多于一條,則需要寫(xiě)在begin…end塊中。例如,例3.4.3中二進(jìn)制乘法器改用while循環(huán)語(yǔ)句,其always塊可寫(xiě)為:always@(opAoropB)begin

integerindex;

index=0;

result=0;

while(index<size)

begin

if(opB[index]==1)

result=result+(opA?index);

index=index+1;//index作為循環(huán)變量,需要自增

endend

3)repeat循環(huán)語(yǔ)句

repeat循環(huán)語(yǔ)句預(yù)先指定循環(huán)次數(shù),語(yǔ)法格式如下:

repeat(循環(huán)次數(shù)表達(dá)式)語(yǔ)句;當(dāng)循環(huán)次數(shù)表達(dá)式值為0、x或z時(shí),都不執(zhí)行語(yǔ)句;否則按指定次數(shù)循環(huán)執(zhí)行語(yǔ)句。若語(yǔ)句塊不止一條語(yǔ)句,需要寫(xiě)在begin…end塊中。例如,例3.4.3中二進(jìn)制乘法器改用repeat循環(huán)語(yǔ)句,其always塊可寫(xiě)為:

always@(opAoropB)

begin

integerindex;

index=0;

result=0;

repeat(8)

begin

if(opB[index]==1)

result=result+(opA?index);

index=index+1;//index作為循環(huán)變量,需要自增

endend3.5模塊化的電路設(shè)計(jì)3.5.1分層次電路設(shè)計(jì)采用層次化設(shè)計(jì)方法,能將復(fù)雜的電路系統(tǒng)分層簡(jiǎn)化實(shí)現(xiàn),具有便于多人協(xié)作、故障調(diào)試、模塊重用的優(yōu)點(diǎn),是目前復(fù)雜電路系統(tǒng)設(shè)計(jì)廣泛采用的方法。層次化的電路設(shè)計(jì)分為自頂向下和自底向上兩種方法。自頂向下的方法是先設(shè)計(jì)頂層模塊,然后依據(jù)頂層模塊劃分功能,定義頂層模塊用到的各個(gè)子模塊。自底向上的方法是先設(shè)計(jì)各個(gè)子模塊,然后由子模塊組合起來(lái)構(gòu)成頂層模塊。Verilog層次化建模結(jié)構(gòu)如圖3.5.1所示。圖3.5.1VerilogHDL層次化建模示意圖

【例3.5.1】引用半加器模塊構(gòu)成1位全加器。

解半加器不考慮低位來(lái)的進(jìn)位,是兩個(gè)1位二進(jìn)制數(shù)相加。全加器考慮低位來(lái)的進(jìn)位,是三個(gè)1位二進(jìn)制數(shù)相加。引用半加器構(gòu)成全加器,需要引用半加器兩次,即將A、B半加的結(jié)果與Cin再進(jìn)行半加,電路結(jié)構(gòu)如圖3.5.2所示。Verilog代碼如代碼3.5.1所示。圖3.5.2本例中,full_adder是頂層模塊。full_adder實(shí)例化half_adder形成u1,完成外界輸入A與B的半加生成半加和S1和半加進(jìn)位C1,再實(shí)例化half_adder為u2,將u1輸出的S1和外界輸入的Cin半加,生成全加和S2和u2的半加進(jìn)位C2。assign語(yǔ)句用于將C1和C2進(jìn)行或運(yùn)算驅(qū)動(dòng)進(jìn)位輸出Co?!纠?.5.2】引用1位十進(jìn)制計(jì)數(shù)器構(gòu)成2位十進(jìn)制計(jì)數(shù)器。解引用1位十進(jìn)制計(jì)數(shù)器構(gòu)成2位十進(jìn)制計(jì)數(shù)器的代碼如下:modulebcd2Counter(en,clk,rst,one_q,ten_q,zout);

inputen,clk,rst;

outputzout;

output[3:0]one_q,ten_q;

wireone_out;

bcd_counterone(.en(1'b1),.clk(clk),.rst(rst),.zout(one_out),.qout(one_q));

bcd_counterten(.en(one_out),.clk(clk),.rst(rst),.zout(),.qout(ten_q));

assignzout=(one_q==4'h9&&ten_q==4'h9);endmodulemodulebcd_counter(en,clk,rst,zout,qout);

inputen,clk,rst;

outputzout;

outputreg[3:0]qout;

always@(posedgeclkornegedgerst)

if(~rst)

qout<=4'b0;

else

if(en)

if(qout==4'h9)

qout<=4'b0;

else

qout<=qout+1'b1;

assignzout=(qout==4'h9);endmodule3.5.2任務(wù)和函數(shù)的使用

1.函數(shù)(function)聲明語(yǔ)句函數(shù)function的使用包括函數(shù)定義和函數(shù)調(diào)用兩部分。函數(shù)定義使用function聲明語(yǔ)句,從關(guān)鍵字function開(kāi)始,至endfunction結(jié)束。函數(shù)聲明必須出現(xiàn)在模塊內(nèi)部,可以在模塊的任意位置。function聲明語(yǔ)句語(yǔ)法格式如下:

function<類(lèi)型或位寬><函數(shù)名>;

<參數(shù)聲明>;

?語(yǔ)句區(qū);

?

endfunction函數(shù)可接受多個(gè)輸入?yún)?shù),由函數(shù)名返回結(jié)果,可看做表達(dá)式計(jì)算。類(lèi)型或位寬用于說(shuō)明返回值的類(lèi)型,可聲明為integer、real、time或reg型,real和time型不可綜合。若為reg型,則可通過(guò)[msb:lsb]指定位寬,缺省時(shí)默認(rèn)為1位。參數(shù)聲明部分用于說(shuō)明傳遞給函數(shù)的輸入變量,或函數(shù)內(nèi)部使用的變量。每個(gè)函數(shù)至少要有一個(gè)輸入變量。輸入變量用input說(shuō)明,不可以是output或inout型。語(yǔ)句區(qū)使用行為描述語(yǔ)句實(shí)現(xiàn)函數(shù)功能,可以是if…else…、case、過(guò)程塊賦值語(yǔ)句等。函數(shù)語(yǔ)句區(qū)中必須要有一條語(yǔ)句用來(lái)給函數(shù)名賦值。若語(yǔ)句區(qū)有多于一條的語(yǔ)句,則需使用begin…end塊。函數(shù)的調(diào)用是將函數(shù)作為表達(dá)式中的操作數(shù)實(shí)現(xiàn)的。函數(shù)調(diào)用的語(yǔ)法格式如下:函數(shù)名(表達(dá)式1,表達(dá)式2,…)表達(dá)式作為傳入函數(shù)的參數(shù),按順序依次連接到函數(shù)的輸入變量。

【例3.5.3】用8位二進(jìn)制高

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論