版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 高考英語(yǔ)短語(yǔ)高頻考點(diǎn)總結(jié)
- 政府舞獅活動(dòng)策劃方案(3篇)
- 紅酒鑒賞活動(dòng)策劃方案(3篇)
- 靜音爆破施工方案(3篇)
- 航司營(yíng)銷(xiāo)方案(3篇)
- 防爆安裝施工方案(3篇)
- 復(fù)式營(yíng)銷(xiāo)方案案例(3篇)
- 購(gòu)房惠民活動(dòng)方案策劃(3篇)
- 貴州中考語(yǔ)文試題與詳細(xì)解析
- 餐飲技能活動(dòng)策劃方案(3篇)
- 濕疹患者護(hù)理查房
- 2025至2030中國(guó)融媒體行業(yè)市場(chǎng)深度分析及前景趨勢(shì)與投資報(bào)告
- 2026年江蘇農(nóng)牧科技職業(yè)學(xué)院?jiǎn)握新殬I(yè)技能測(cè)試模擬測(cè)試卷附答案
- 2026年南京交通職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)傾向性測(cè)試題庫(kù)附答案
- 2025吐魯番市高昌區(qū)招聘第二批警務(wù)輔助人員(165人)筆試考試參考試題及答案解析
- 醫(yī)學(xué)檢驗(yàn)技術(shù)專(zhuān)業(yè)《血液學(xué)檢驗(yàn)》課程標(biāo)準(zhǔn)
- 預(yù)防控制冬蚊
- 經(jīng)典話劇劇本《雷雨》
- 半導(dǎo)體廠耗能指標(biāo)及節(jié)能方案之研究57張課件
- 奶牛產(chǎn)后癱瘓的綜合防治畢業(yè)設(shè)計(jì)論文
- 啟爾暢產(chǎn)品介紹專(zhuān)家講座
評(píng)論
0/150
提交評(píng)論