版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
3.1建模方法引例
3.2結(jié)構(gòu)化形式建模
3.3數(shù)據(jù)流級(jí)建模
3.4行為級(jí)建模
3.5小結(jié)
習(xí)題33.1建模方法引例
下面通過一個(gè)典型數(shù)字電路實(shí)例來引入建模方法。
【例3-1】設(shè)計(jì)實(shí)現(xiàn)一個(gè)3人判決電路,若3個(gè)人中有2人或者超過2人同意,則表決結(jié)果為通過;否則表決結(jié)果為不通過。這是一道經(jīng)典的數(shù)字電路例題,下面我們來看一下數(shù)字電路中對(duì)該問題的求解過程。第一步:理解題意。設(shè)a、b、c分別代表3個(gè)人,同意用1表示,不同意用0表示,y代表表決結(jié)果,1表示通過,0表示不通過。根據(jù)題意有,當(dāng)a、b、c三個(gè)中有2個(gè)為1,或者3個(gè)均為1時(shí),y為1,否則y為0。第二步:根據(jù)題意,列真值表,如表3-1所示。第三步:根據(jù)真值表,列輸出方程:
y=a'bc+ab'c+abc'+abc第四步:化簡方程,可以采用代數(shù)化簡法或者卡諾圖化簡法(見圖3-1)。圖3-1卡諾圖化簡化簡后的方程為:y=ab+bc?+?ca。第五步:根據(jù)化簡后的方程畫出電路圖,如圖3-2所示。圖3-2例3-1的電路實(shí)現(xiàn)至此解題完畢。以上五步,我們均可以采用VerilogHDL語言進(jìn)行數(shù)字電路建模,建模過程見例3-2至例3-6。
【例3-2】對(duì)應(yīng)于步驟一的Verilog建模。moduledecision_1(a,b,c,y);inputa,b,c;outputregy;always@(a,b,c)if((a&b==1)|(b&c==1)|(c&a==1)|(a&b&c==1))y=1;elsey=0;endmodule使用QuartusⅡ軟件綜合的結(jié)果如圖3-3所示。圖3-3例3-2的綜合結(jié)果【例3-3】對(duì)應(yīng)于步驟二的Verilog建模。moduledecision_2(a,b,c,y);inputa,b,c;outputregy;always@(a,b,c)
case({a,b,c}) 3'b000:y=0; 3'b001:y=0; 3'b010:y=0;
3'b011:y=1; 3'b100:y=0; 3'b101:y=1; 3'b110:y=1; 3'b111:y=1; endcaseendmodule使用QuartusⅡ軟件綜合的結(jié)果如圖3-4所示。圖3-4例3-3的綜合結(jié)果
【例3-4】對(duì)應(yīng)于步驟三的Verilog建模。
moduledecision_3(a,b,c,y);
inputa,b,c;
outputy;
assigny=(~a&b&c)|(a&~b&c)|(a&b&~c)|(a&b&c);
endmodule使用QuartusⅡ軟件綜合的結(jié)果如圖3-5所示。圖3-5例3-4的綜合結(jié)果
【例3-5】對(duì)應(yīng)于步驟四的Verilog建模。
moduledecision_4(a,b,c,y);
inputa,b,c;
outputy;
assigny=(a&b)|(b&c)|(c&a);
endmodule使用QuartusⅡ軟件綜合的結(jié)果如圖3-2所示。
【例3-6】對(duì)應(yīng)于步驟五的Verilog建模。
moduledecision_5(a,b,c,y);
inputa,b,c;
outputy;
//assigny=(a&b)+(b&c)+(c&a);
//assigny=a&b+b&c;
and(ab,a,b),
(bc,b,c),
(ca,c,a);
or(y,ab,bc,ca);
endmodule使用QuartusⅡ軟件綜合的結(jié)果如圖3-2所示。以上五步對(duì)應(yīng)著不同的建模方法,但其功能仿真波形都是相同的,如圖3-6所示。圖3-6功能仿真波形從仿真波形可以看出,以上五種不同的建模方法均實(shí)現(xiàn)了判決功能,都是問題的解決方法。對(duì)例3-2至例3-6的說明:
(1)各種建模方法得出的電路圖不盡相同,但最終的仿真結(jié)果完全相同,也就是說,最終的電路實(shí)現(xiàn)不同,但功能卻相同。
(2)例3-2和例3-3采用了行為建模方式建模,用到了always語句;例3-4和例3-5采用了數(shù)據(jù)流建模方式建模,用到了assign語句;例3-6采用了門級(jí)建模方式建模,調(diào)用了門級(jí)原語。這三種建模方式是VerilogHDL最主要的建模方式。在一個(gè)模塊中,可以采用以上三種建模方式的一種建模,也可以采用多種方式混合建模。本章后續(xù)內(nèi)容還要對(duì)上述三種建模方式展開討論。
(3)例3-2用到了條件語句if,例3-3用到多路分支語句case,這些語句只能用在always語句中,也就是只能用在行為建模中;assign語句是數(shù)據(jù)流建模的標(biāo)志;模塊調(diào)用類似于門級(jí)原語調(diào)用,均歸屬結(jié)構(gòu)化建模。
(4)從以上例子也可以看出,從門級(jí)建模到數(shù)據(jù)流建模再到行為建模,建模抽象程度越來越高,距離電路的具體實(shí)現(xiàn)越來越遠(yuǎn),但是也越來越接近人類解決問題的思維。3.2結(jié)構(gòu)化形式建模
在VerilogHDL中可使用如下方式描述結(jié)構(gòu):
(1)開關(guān)級(jí)原語(在晶體管級(jí))——開關(guān)級(jí)建模。
(2)內(nèi)置門原語(在門級(jí))——門級(jí)建模。
(3)用戶定義的原語。
(4)模塊實(shí)例(創(chuàng)建層次結(jié)構(gòu))。上述幾種結(jié)構(gòu)化描述方式之中,比較常用的是門級(jí)建模、用戶自定義原語和模塊實(shí)例。而模塊實(shí)例化已在第2章中進(jìn)行了介紹,下面僅就門級(jí)建模和用戶自定義原語作詳細(xì)介紹。3.2.1門級(jí)建模簡單的邏輯電路可以使用邏輯門來設(shè)計(jì)實(shí)現(xiàn)。基本的邏輯門分為兩類:與/或門類、緩沖/非門類。
1.與/或門類與/或門類包括與門(and)、或門(or)、與非門(nand)、或非門(nor)、異或門(xor)、同或門(xnor)。與/或門類都具有一個(gè)標(biāo)量輸出端和多個(gè)標(biāo)量輸入端,門的端口列表中的第一個(gè)端口必定是輸出端口,其他均為輸入端口。當(dāng)任意一個(gè)輸入端口的值發(fā)生變化時(shí),輸出端的值立即重新計(jì)算。與/或門類的實(shí)例引用:
wireOUT,IN1,IN2,IN3;
andand2(OUT,IN1,IN2);
//基本門的實(shí)例引用
nandnand3(OUT,IN1,IN2,IN3);
//輸入端超過兩個(gè),三輸入與非門
and(OUT,IN1,IN2,IN3);
//合法的門實(shí)例引用,不給實(shí)例命名
2.緩沖/非門類緩沖/非門類包括緩沖器(buf)、非門(not)、帶控制端的緩沖器/非門(bufif1、bufif0、notif1、notif0)。緩沖/非門類具有一個(gè)標(biāo)量輸入端和多個(gè)標(biāo)量輸出端,門的端口列表中的最后一個(gè)端口必定是輸入端口,其他均為輸出端口。緩沖/非門類的實(shí)例引用:wireOUT1,OUT2,OUT3,IN,ctrl;bufb1(OUT1,IN);
//基本門的實(shí)例引用notn1(OUT1,IN);
//基本門的實(shí)例引用bufb2(OUT1,OUT2,OUT3,IN);
//輸出端超過兩個(gè),三輸出緩沖not(OUT1,OUT2,IN);
//合法的門實(shí)例引用,不給實(shí)例命名bufif1(OUT1,IN,ctrl);//ctrl為1時(shí),OUT1=INnotif0(OUT1,IN,ctrl);//ctrl為0時(shí),OUT1=~IN
【例3-7】利用雙輸入端的nand門,編寫自己的雙輸入端的與門(my_and)、或門(my_or)、非門(my_not)、異或門(my_xor)。
modulemy_and(a,b,y);//用兩個(gè)nand門實(shí)現(xiàn)與門
inputa,b;
outputy;
wirenandab;
nand(nandab,a,b),
(y,nandab,nandab);
endmodulemodulemy_or(a,b,y);//用三個(gè)nand門實(shí)現(xiàn)或門inputa,b;outputy;wirenandaa,nandbb;nand(nandaa,a,a),(nandbb,b,b),(y,nandaa,nandbb);endmodulemodulemy_not(a,y);//用一個(gè)nand門實(shí)現(xiàn)非門inputa;outputy;nand(y,a,a);endmodulemodulemy_xor(a,b,y);//用四個(gè)nand門實(shí)現(xiàn)異或門inputa,b;outputy;wireandab,c,d;nand(andab,a,b), (c,andab,a),
(d,andab,b), (y,c,d);endmodule
程序說明:
(1)在以上示例中,調(diào)用門級(jí)原語時(shí)均沒有給出實(shí)例名。注意,在門級(jí)原語實(shí)例引用的時(shí)候,我們可以不指定具體的實(shí)例名,這一點(diǎn)對(duì)需要實(shí)例引用幾百個(gè)甚至更多門的模塊提供了方便。但對(duì)于初學(xué)者,建議在調(diào)用門級(jí)原語時(shí)給出實(shí)例名。
(2)在實(shí)際應(yīng)用中,與非門和或非門的應(yīng)用更為普遍,這是因?yàn)橛蛇@兩種門生成其他邏輯門較容易實(shí)現(xiàn)。
(3)例子中有4個(gè)模塊,分別實(shí)現(xiàn)與門、或門、非門、異或門,可在多模塊編譯環(huán)境QuartusⅡ中逐個(gè)模塊編譯并進(jìn)行仿真驗(yàn)證,這部分工作留給讀者完成。邏輯門是最基本的電路單元,任何復(fù)雜的數(shù)字邏輯電路均可由邏輯門實(shí)現(xiàn)。但復(fù)雜電路的設(shè)計(jì)如果從邏輯門開始來搭建,顯然是不現(xiàn)實(shí)的,必須采用其他建模方式。3.2.2用戶自定義原語
VerilogHDL提供了一整套標(biāo)準(zhǔn)的原語,例如and、or、nor和not等,它們是該語言的一部分,即通常所說的內(nèi)置原語。然而,在設(shè)計(jì)過程中,設(shè)計(jì)者有時(shí)希望使用自己編寫的原語。VerilogHDL具有這種自定義原語的能力,這種原語就是用戶自定義原語(UserDefinedPrimitive,UDP)。UDP是自成體系的,在UDP中不能調(diào)用其他模塊或者其他原語。UDP的調(diào)用方式和門級(jí)原語的調(diào)用方式完全相同。
UDP有兩類:
(1)表示組合邏輯的UDP:輸出僅取決于輸入信號(hào)的組合邏輯。
(2)表示時(shí)序邏輯的UDP:下一個(gè)輸出值不但取決于當(dāng)前的輸入值,還取決于當(dāng)前的內(nèi)部狀態(tài)。
UDP的語法定義如下:primitive<UDP名稱>(<輸出端口名>,<輸入端口名>);//端口說明語句output<輸出端口名>;input<輸入端口名>;reg<輸出端口名>;(可選,只有表示時(shí)序邏輯的UDP才需要)//UDP初始化(只有時(shí)序邏輯才需要)Initial<輸出端口名>=<值>//UDP狀態(tài)表table<狀態(tài)表>endtableendprimitive下面舉例對(duì)這兩類UDP進(jìn)行說明。
【例3-8】表示組合邏輯的UDP舉例:一位全加器。全加器進(jìn)位實(shí)現(xiàn)部分:
primitiveU_ADD_C(CO,A,B,CI);
outputCO;
inputA,B,CI;
table//ABCI:CO
11?:1;
1?1:1;
?11:1;
00?:0;
0?0:0;
?00:0;
endtableendprimitive全加器求和實(shí)現(xiàn)部分:
primitiveU_ADD_S(S,A,B,CI);
outputS;
inputA,B,CI;
table//ABCI:S
000:0;
001:1;
010:1;
011:0;
100:1;
101:0;
110:0;
111:1;
endtableendprimitive調(diào)用上述兩個(gè)UDP的全加器模塊:moduleU_ADD(SUM,CO,a,b,ci);inputa,b,ci;outputSUM,CO;U_ADD_SU1(SUM,a,b,ci);U_ADD_CU2(CO,a,b,ci);endmodule程序說明:
(1)若使用UDP設(shè)計(jì)全加器,僅需要兩個(gè)UDP來描述全加器的邏輯功能;而使用VerilogHDL原語元件,則需要多個(gè)VerilogHDL提供的基本門級(jí)原語元件。當(dāng)設(shè)計(jì)需要使用大量全加器時(shí),采用UDP來表示全加器,將大大減少內(nèi)存的需要,事件的數(shù)目將大大降低。
(2)兩個(gè)UDP的端口列表中,第一個(gè)端口CO和S均為輸出端口,其余端口均為輸入端口。
(3)程序中的“?”表示邏輯值可以為0、1或x。
(4)使用QuartusⅡ軟件綜合的結(jié)果如圖3-7所示。圖3-7一位全加器的綜合結(jié)果其仿真波形如圖3-8所示。圖3-8一位全加器的仿真波形從仿真波形可以看出,該設(shè)計(jì)實(shí)現(xiàn)了一位全加器的功能。
【例3-9】表示時(shí)序邏輯的UDP舉例:D觸發(fā)器。
primitived_edge_ff(q,clk,data);
outputq;
inputclk,data;
regq;
table//clk
datstatenext
(01)0:?:0;
(01)1:?:1;//時(shí)鐘下降沿
(?0)?:?:-;
//時(shí)鐘穩(wěn)定時(shí)忽略data的變化
?(??):?:-;
endtable
endprimitive程序說明:
(1)使用QuartusⅡ軟件綜合的結(jié)果如圖3-9所示。圖3-9D觸發(fā)器的綜合結(jié)果從綜合結(jié)果可以看出,該設(shè)計(jì)實(shí)現(xiàn)了一個(gè)D觸發(fā)器。
(2)程序中的“?”表示邏輯值可以為0、1或x。
(3)端口列表中的第一個(gè)端口q為輸出端口,其余為輸入端口。對(duì)用戶自定義原語的進(jìn)一步說明:
(1)?UDP只能有一個(gè)輸出,輸出端口必須列為端口列表的第一個(gè)。如果在功能上要求有多個(gè)輸出,則需要在UDP輸出端連接其他的基本單元,或者同時(shí)使用幾個(gè)UDP。
(2)?UDP可以有1~10個(gè)輸入。若輸入端口超過5,則存儲(chǔ)需求會(huì)大幅增加。表3-2列出輸入端口數(shù)與存儲(chǔ)需求的關(guān)系。
(3)所有端口必須為標(biāo)量且不允許是雙向端口。
(4)不支持邏輯值z。3.3數(shù)據(jù)流級(jí)建模
在電路規(guī)模較小的情況下,由于包含的門數(shù)比較少,因此使用門級(jí)建模進(jìn)行設(shè)計(jì)不僅直觀,而且方便。但是,如果電路的功能比較復(fù)雜,則通常該電路包含的邏輯門的個(gè)數(shù)會(huì)很多,這時(shí)使用門級(jí)建模不僅繁瑣而且很容易出錯(cuò)。在這種情況下,如果從更高抽象層次入手,將設(shè)計(jì)重點(diǎn)放在功能實(shí)現(xiàn)上,則不僅能避免繁瑣的細(xì)節(jié),還可以大大提高設(shè)計(jì)的效率。本節(jié)介紹更高抽象層次的建模方法:數(shù)據(jù)流建模。3.3.1連續(xù)賦值語句以關(guān)鍵詞assign開始的語句為連續(xù)賦值語句,連續(xù)賦值語句是Verilog數(shù)據(jù)流建模的基本語句,用于對(duì)線網(wǎng)進(jìn)行賦值。
【例3-10】使用數(shù)據(jù)流建模,實(shí)現(xiàn)一位半加器。解題指引:半加器實(shí)現(xiàn)的是不帶進(jìn)位的兩個(gè)數(shù)的相加,若半加器的輸入為ain和bin,輸出為sum和co,其中sum為和,co為進(jìn)位,則半加器的真值表如表3-3所示。VerilogHDL實(shí)現(xiàn)代碼如下:moduleadder_half(ain,bin,sum,co);inputain,bin;outputsum,co;assign{co,sum}=ain+bin;endmodule程序說明:
(1)?assign{co,sum}=ain+bin;是一條連續(xù)賦值語句,它將ain和bin的和存放在{co,sum}中。該語句中,“{}”為位拼接符,其功能是將co和sum拼接成一個(gè)兩位的數(shù)。
(2)連續(xù)賦值語句的左邊必須是一個(gè)標(biāo)量或向量線網(wǎng),或者是標(biāo)量或向量線網(wǎng)的拼接,而不能是任何形式的寄存器。例如下面的形式是非法的:
regsum;
assign{co,sum}=ain+bin;//非法,sum不能為寄存器類型對(duì)連續(xù)賦值語句的進(jìn)一步說明:
(1)連續(xù)賦值語句的基本元素是表達(dá)式、運(yùn)算符和操作數(shù)。其功能是計(jì)算右側(cè)表達(dá)式的值,然后賦給左邊變量。表達(dá)式由運(yùn)算符和操作數(shù)構(gòu)成,根據(jù)運(yùn)算符界定的功能對(duì)操作數(shù)進(jìn)行運(yùn)算后得出結(jié)果。數(shù)據(jù)流的強(qiáng)大建模能力體現(xiàn)在多種運(yùn)算符類型上。下一節(jié)我們將詳細(xì)介紹運(yùn)算符類型。
(2)連續(xù)賦值語句總是處于激活狀態(tài)。只要任意一個(gè)操作數(shù)發(fā)生變化,表達(dá)式就會(huì)被立即重新計(jì)算,并且將結(jié)果賦給等號(hào)左邊的線網(wǎng)。
(3)操作數(shù)可以是標(biāo)量或向量線網(wǎng),也可以是標(biāo)量或向量寄存器。3.3.2運(yùn)算符類型
VerilogHDL提供了許多類型的運(yùn)算符,分別是算術(shù)、關(guān)系、邏輯、按位、縮減、條件、移位和位拼接運(yùn)算符。表3-4按運(yùn)算符類型列出了常用的運(yùn)算符。從表3-4可知,在VerilogHDL語言中運(yùn)算符所帶的操作數(shù)是不同的。只帶一個(gè)操作數(shù)的運(yùn)算符稱為單目運(yùn)算符,此時(shí)操作數(shù)需放在運(yùn)算符的右邊;帶二個(gè)操作數(shù)的運(yùn)算符稱為雙目運(yùn)算符,操作數(shù)需放在運(yùn)算符的兩邊;帶三個(gè)操作數(shù)的運(yùn)算符稱為三目運(yùn)算符,這三個(gè)操作數(shù)用三目運(yùn)算符分隔開,如條件運(yùn)算符就是三目運(yùn)算符。表達(dá)式中的操作數(shù)可以是以下類型中的一種:常數(shù)、參數(shù)、線網(wǎng)、寄存器、位選擇、部分選擇、存儲(chǔ)器單元和函數(shù)調(diào)用。下面對(duì)表3-4中的運(yùn)算符分別加以介紹。
1.算術(shù)運(yùn)算符算術(shù)運(yùn)算符包括加(+)、減(-)、乘(*)、除(/)、取模(%)、乘方(**)。
【例3-11】算術(shù)運(yùn)算符示例。
modulearith(a,b,add,sub,mul,div,mod,pow);
input[7:0]a,b;
output[7:0]add,sub,mul,div,mod,pow;
assign add=a+b,
sub=a-b,
mul=a*b, div=a/b,
mod=a%b,
pow=a**4;
endmodule程序說明:
(1)加(+)、減(-)、乘(*)、除(/)、取模(%)、乘方(**)均為雙目運(yùn)算符,要求運(yùn)算符兩側(cè)均有操作數(shù)。
(2)該例仿真時(shí)可以設(shè)置在0~255內(nèi)的任意輸入值a和b,觀察add、sub、mul、div、mod、pow值的變化。
(3)乘方運(yùn)算符要求冪是一個(gè)常量,不能為變量。對(duì)于算術(shù)運(yùn)算符的進(jìn)一步說明:
(1)在進(jìn)行整數(shù)除法運(yùn)算時(shí),結(jié)果值要略去小數(shù)部分,只取整數(shù)部分。
(2)取模運(yùn)算符又稱為求余運(yùn)算符,要求%兩側(cè)均為整型數(shù)據(jù)。
(3)取模運(yùn)算時(shí),結(jié)果值的符號(hào)位采用模運(yùn)算式里第一個(gè)操作數(shù)的符號(hào)位。表3-5中列舉了一些例子。
2.關(guān)系運(yùn)算符關(guān)系運(yùn)算符包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)、不等于(!=)。在進(jìn)行關(guān)系運(yùn)算時(shí),如果聲明的關(guān)系是假的(flase),則返回值是0,如果聲明的關(guān)系是真的(true),則返回值是1。關(guān)系運(yùn)算符中大于、小于、大于等于、小于等于有著相同的優(yōu)先級(jí)別,等于、不等于有著相同的優(yōu)先級(jí)別,前者的優(yōu)先級(jí)別大于后者的優(yōu)先級(jí)別。關(guān)系運(yùn)算符的優(yōu)先級(jí)別低于算術(shù)運(yùn)算符的優(yōu)先級(jí)別。例如:
a==size-1//這種表達(dá)方式等同于:a==(size-1)
size-(1==a)//這種表達(dá)方式不等同于:size-1==a
a<size-1//這種表達(dá)方式等同于:a<(size-1)
size-(1<a)//這種表達(dá)方式不等同于:size-1<a從上面的例子可以看出這兩種不同運(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.邏輯運(yùn)算符邏輯運(yùn)算符包括邏輯與(&&)、邏輯或(||)、邏輯非(!)?!?&”和“||”是雙目運(yùn)算符,要求有兩個(gè)操作數(shù),如(a>b)&&(b>c)、(a<b)||(b<c)?!埃 笔菃文窟\(yùn)算符,只要求一個(gè)操作數(shù),如!(a>b)。表3-6為邏輯運(yùn)算的真值表。它表示當(dāng)a和b的值為不同的組合時(shí),各種邏輯運(yùn)算所得到的值。邏輯運(yùn)算符中“&&”和“||”的優(yōu)先級(jí)別低于關(guān)系運(yùn)算符,“!”高于算術(shù)運(yùn)算符。例如:
(a>b)&&(x>y)
//可寫成:a>b&&x>y
(a==b)||(x==y)
//可寫成:a==b||x==y
(!a)||(a>b) //可寫成:!a||a>b
4.按位運(yùn)算符
按位運(yùn)算符包括取反(~)、按位與(&)、按位或(|)、按位異或(^)、按位同或(~^,^~)。
位運(yùn)算符中除了~?是單目運(yùn)算符以外,其余均為雙目運(yùn)算符。位運(yùn)算符中的雙目運(yùn)算符要求對(duì)兩個(gè)操作數(shù)的相應(yīng)位進(jìn)行運(yùn)算操作。
表3-7給出了按位操作的邏輯規(guī)則。對(duì)按位運(yùn)算符的幾點(diǎn)說明:
(1)兩個(gè)長度不同的數(shù)據(jù)進(jìn)行位運(yùn)算時(shí),系統(tǒng)會(huì)自動(dòng)將兩者按右端對(duì)齊。位數(shù)少的操作數(shù)會(huì)在相應(yīng)的高位用0填滿,以使兩個(gè)操作數(shù)按位進(jìn)行操作。
(2)按位運(yùn)算符與邏輯運(yùn)算符雖然符號(hào)相近,但兩者完全不同。邏輯運(yùn)算符執(zhí)行邏輯操作,運(yùn)算的結(jié)果是一個(gè)邏輯值0或1;按位運(yùn)算符產(chǎn)生一個(gè)跟較長位寬操作數(shù)等寬的數(shù)值,該數(shù)值的每一位都是兩個(gè)操作數(shù)按位運(yùn)算的結(jié)果。
5.縮減運(yùn)算符
縮減運(yùn)算符包括縮減與(&)、縮減與非(~&)、縮減或(|)、縮減或非(~|)、縮減異或(^)、縮減同或(~^,^~)。
縮減運(yùn)算符是單目運(yùn)算符,也有與、或、非運(yùn)算。其與、或、非運(yùn)算規(guī)則類似于位運(yùn)算符的與、或、非運(yùn)算規(guī)則,但其運(yùn)算過程不同。位運(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)算過程是這樣的:第一步先將操作數(shù)的第一位與第二位進(jìn)行與、或、非運(yùn)算,第二步將運(yùn)算結(jié)果與第三位進(jìn)行與、或、非運(yùn)算,依次類推,直至最后一位。
例如:
reg[3:0]B;
regC;
C=&B;//C=((B[0]&B[1])&B[2])&B[3];
由于邏輯運(yùn)算符、按位運(yùn)算符、縮減運(yùn)算符都使用相同的符號(hào)表示,因此有時(shí)容易混淆。區(qū)分這些運(yùn)算符的重點(diǎn)在于分清操作數(shù)的數(shù)目和運(yùn)算的規(guī)則。
6.條件運(yùn)算符
條件運(yùn)算符(?:)帶有三個(gè)操作數(shù),其格式為:
條件表達(dá)式?真表達(dá)式:假表達(dá)式;
執(zhí)行過程為:首先計(jì)算條件表達(dá)式,如果為真,則計(jì)算真表達(dá)式的值;如果為假,則計(jì)算假表達(dá)式的值。條件運(yùn)算符可以嵌套使用,每個(gè)真表達(dá)式或假表達(dá)式也可以是一個(gè)條件運(yùn)算符表達(dá)式。條件表達(dá)式的作用相當(dāng)于控制開關(guān)。【例3-12】試用條件運(yùn)算符來實(shí)現(xiàn)一個(gè)四選一多路選擇器。
Verilog實(shí)現(xiàn)代碼如下:
modulemux4to1(out,condition1,condition2,in1,in2,in3,in4);
outputout;
inputin1,in2,in3,in4;
inputcondition1,condition2;
assignout=(condition1)?(condition2?in1:in2):(condition2?in3:in4);
endmodule程序說明:
(1)?assignout=(condition1)?(condition2?in1:in2):(condition2?in3:in4);在真表達(dá)式和假表達(dá)式中均嵌套了一個(gè)條件運(yùn)算符表達(dá)式。程序的運(yùn)算過程如下:首先判斷condition1是否為真,若為真則計(jì)算(condition2?in1:in2),否則計(jì)算(condition2?in3:in4),然后按照同樣的規(guī)則計(jì)算這兩個(gè)條件運(yùn)算符表達(dá)式。
(2)本代碼實(shí)現(xiàn)了一個(gè)四選一多路選擇器,輸出由條件condition1和condition2決定。根據(jù)代碼可以得出,當(dāng){condition2,condition1}為2'b11時(shí)選擇in1,為2'b10時(shí)選擇in3,為2'b01時(shí)選擇in2,為2'b00時(shí)選擇in4。
7.移位運(yùn)算符移位運(yùn)算符包括左移位運(yùn)算符(<<)和右移位運(yùn)算符(>>)。其使用方法如下:
a>>n或a<<n其中,a代表要進(jìn)行移位的操作數(shù),n代表要移幾位。這兩種移位運(yùn)算都用0來填補(bǔ)移出的空位。
【例3-13】采用移位運(yùn)算符實(shí)現(xiàn)2個(gè)3位數(shù)的乘法。解題指引:設(shè)a為3位乘數(shù),用a2a1a0表示,設(shè)b為3位被乘數(shù),用b2b1b0表示,乘法運(yùn)算過程如圖3-10所示。圖3-10乘法的運(yùn)算過程乘法的最后是把5列分別求和得到5位的積。根據(jù)以上運(yùn)算過程可以看出,乘法的最后也可以這樣進(jìn)行,將最后3行代表的3個(gè)數(shù)相加,當(dāng)然第2行相對(duì)第1行要左移1位,第3行相對(duì)第1行要左移2位。
VerilogHDL實(shí)現(xiàn)代碼如下:modulemul_3bit(a,b,mul);input[2:0]a,b;output[5:0]mul;wire[5:0]mul1,mul2,mul3;assignmul=mul3;assignmul1=b[0]?a:0;assignmul2=b[1]?(mul1+(a<<1)):mul1;assignmul3=b[2]?(mul2+(a<<2)):mul2;endmodule程序說明:
(1)?wire[5:0]mul1,mul2,mul3;定義了3個(gè)中間變量,mul1用于存放第1行的值,mul2用于存放第1行和第2行的和,mul3用于存放所有3行的和。
(2)本例為2個(gè)3位數(shù)相乘,我們可以采用數(shù)據(jù)流建模方式來完成。如果位數(shù)較多,比如位數(shù)為64位,采用數(shù)據(jù)流建模則顯得繁瑣,此時(shí)可采用循環(huán)語句來完成此算法,即采用更高抽象級(jí)的行為建模。
(3)從本例可看出,由于移位運(yùn)算符可以用來實(shí)現(xiàn)移位操作、乘法算法的移位相加以及其他許多有用的操作,因此在具體設(shè)計(jì)中是很有用處的。另外,進(jìn)行移位運(yùn)算時(shí)應(yīng)注意移位前后變量的位數(shù),例如:4'b1001<<1=5'b10010,4'b1001<<2=6'b100100,1<<6=32'b1000000。
8.位拼接運(yùn)算符位拼接運(yùn)算符包括拼接運(yùn)算符({})、重復(fù)運(yùn)算符({{}})。拼接運(yùn)算符{}可以把兩個(gè)或多個(gè)信號(hào)的某些位拼接起來進(jìn)行運(yùn)算操作。其使用方法如下:
{信號(hào)1的某幾位,信號(hào)2的某幾位,…,信號(hào)n的某幾位}即把某些信號(hào)的某些位詳細(xì)地列出來,中間用逗號(hào)分開,最后用大括號(hào)括起來表示一個(gè)整體信號(hào)。例如:
{a,b[3:0],w,3‘b101}//等價(jià)于
{a,b[3],b[2],b[1],b[0],w,1'b1,1'b0,1'b1}在位拼接表達(dá)式中的每個(gè)信號(hào)均需指明位數(shù),這是因?yàn)樵谟?jì)算拼接信號(hào)位寬的大小時(shí)必須知道其中每個(gè)信號(hào)的位寬。對(duì)于未指明位數(shù)的數(shù)字則按照默認(rèn)值32位進(jìn)行處理。例如:
{1,1}//64位,從右邊數(shù)第0位為1,第32位為1,其余位均為0如果需要重復(fù)多次拼接同一個(gè)操作數(shù),則可以使用重復(fù)運(yùn)算符。重復(fù)拼接的次數(shù)用常數(shù)來表示,該常數(shù)指定了其后大括號(hào)內(nèi)變量的重復(fù)次數(shù)。例如:
{4{w}}//等價(jià)于{w,w,w,w}位拼接還可以用嵌套的方式來表達(dá)。例如:
{b,{3{a,b}}}//等價(jià)于{b,a,b,a,b,a,b}用于表示重復(fù)的表達(dá)式,如上例中的4和3,必須是常數(shù)表達(dá)式。位拼接運(yùn)算符在一些場合非常有用,比如要在使用的函數(shù)中返回幾個(gè)值的時(shí)候,使用位拼接符可將幾個(gè)待返回的值拼接為一個(gè)值,作為函數(shù)值進(jìn)行返回。
9.優(yōu)先級(jí)別如果不使用小括號(hào)將表達(dá)式的各個(gè)部分分開,則VerilogHDL將根據(jù)運(yùn)算符之間的優(yōu)先級(jí)對(duì)表達(dá)式進(jìn)行計(jì)算。圖3-11列出了常用的幾種運(yùn)算符的優(yōu)先級(jí)別。圖3-11運(yùn)算符的優(yōu)先級(jí)下面再通過一個(gè)例子說明運(yùn)算符優(yōu)先級(jí)別的應(yīng)用?!纠?-14】若a、b、x、y均定義為wire[3:0]類型,且a=1,b=7,試計(jì)算x和y的值。(1)
x=(a==2)?~a|b:b>>2;(2)
y=3+2>>2;計(jì)算結(jié)果為:
x=1,y=1程序說明:
(1)?x=(a==2)?~a|b:b>>2;用到了相等運(yùn)算符(==)、按位運(yùn)算符(~、|)、移位運(yùn)算符(>>)和條件運(yùn)算符(?:)。小括號(hào)優(yōu)先級(jí)最高,在計(jì)算時(shí)首先計(jì)算小括號(hào)內(nèi)的表達(dá)式的值,然后再按優(yōu)先級(jí)求其他表達(dá)式的值。按照其優(yōu)先級(jí)先求~a,因a=1且為4位wire類型,所以~a=4'b1110,然后可求出條件運(yùn)算符的一個(gè)操作數(shù)~a|b的值為4'b1111;而條件運(yùn)算符的另一個(gè)操作數(shù)b>>2的結(jié)果為4'b0001。根據(jù)題意,條件運(yùn)算符的條件為假,所以x的值為4'b0001。
(2)?y=3+2>>2;用到了算術(shù)運(yùn)算符(+)和移位運(yùn)算符(>>)。根據(jù)優(yōu)先級(jí),y=3+2>>2;等價(jià)于y=(3+2)>>2;,所以y的值為4'b0001。
(3)事實(shí)上,由于運(yùn)算符的優(yōu)先級(jí)被忽視或混淆而造成錯(cuò)誤的情況經(jīng)常發(fā)生。為了避免源于運(yùn)算符優(yōu)先級(jí)的運(yùn)算錯(cuò)誤,在不確定運(yùn)算符優(yōu)先級(jí)的情況下,建議讀者使用小括號(hào)將各個(gè)表達(dá)式分開。另外,使用括號(hào)也可以提高程序的可讀性,明確表達(dá)各運(yùn)算符間的優(yōu)先關(guān)系。3.4行?為?級(jí)?建?模
VerilogHDL支持從算法的角度,即從電路外部行為的角度對(duì)其進(jìn)行描述,因此行為級(jí)建模是從一個(gè)很高的抽象層次來表示電路的。?在這個(gè)層次上進(jìn)行數(shù)字系統(tǒng)設(shè)計(jì)類似于使用C語言編程,而且VerilogHDL行為建模的語法結(jié)構(gòu)和C語言相當(dāng)類似。VerilogHDL提供了許多行為級(jí)建模語法結(jié)構(gòu),為設(shè)計(jì)者提供了很大的靈活性。3.4.1結(jié)構(gòu)化過程語句always
always語句是行為建模的基本語句,每個(gè)always語句代表一個(gè)獨(dú)立的執(zhí)行過程,也稱為進(jìn)程。與C語言不同,VerilogHDL的各個(gè)always進(jìn)程是并發(fā)執(zhí)行的,而不是順序執(zhí)行的。
always語句包括的所有行為語句構(gòu)成了一個(gè)always語句塊。每個(gè)always語句塊在滿足一定的條件后即執(zhí)行其中的第一條語句,然后順序執(zhí)行隨后的語句,直到最后一條語句執(zhí)行完后,再次等待always語句塊的執(zhí)行條件,等條件滿足后又從第一條語句開始執(zhí)行,循環(huán)往復(fù)。因此,always語句通常用于對(duì)數(shù)字電路中一組反復(fù)執(zhí)行的活動(dòng)進(jìn)行建模?!纠?-15】使用always語句描述D觸發(fā)器。
modulemydff(q,clk,d);
inputclk,d;
outputq;regq;
always@(posedge
clk)
q<=d;
endmodule程序說明:
(1)本程序的功能是在時(shí)鐘上升沿時(shí)刻,將數(shù)據(jù)d賦予觸發(fā)器輸出q,其功能同D觸發(fā)器一樣。
(2)?always語句由于其不斷重復(fù)執(zhí)行的特性,只有和一定的時(shí)序控制結(jié)合在一起才有用。always@(posedge
clk)語句表示只有在clk上升沿時(shí)才開始執(zhí)行always語句塊,否則不執(zhí)行。這種時(shí)序控制是always語句最常用的。
(3)?always的時(shí)序控制除沿觸發(fā)時(shí)序控制外,還可以是電平觸發(fā)的,也可以是單個(gè)信號(hào)或多個(gè)信號(hào),中間需要用關(guān)鍵字or或“,”連接,如:
always@(posedgeclockorposedgereset)//由兩個(gè)沿觸發(fā)的always塊
begin
…
end
always@(aorborc)//由多個(gè)電平觸發(fā)的always塊
begin
…
end沿觸發(fā)的always塊常用來描述時(shí)序邏輯,如果符合可綜合風(fēng)格要求,則可用綜合工具將其自動(dòng)轉(zhuǎn)換為表示時(shí)序邏輯的寄存器組和門級(jí)邏輯;而電平觸發(fā)的always塊常用來描述一般組合邏輯和帶鎖存器的組合邏輯,如果符合可綜合風(fēng)格要求,則可轉(zhuǎn)換為表示組合邏輯的門級(jí)邏輯或帶鎖存器的組合邏輯。一個(gè)模塊中可以有多個(gè)always塊,它們都是并行運(yùn)行的。(4)本例的綜合結(jié)果如圖3-12所示。圖3-12例3-15的綜合結(jié)果從綜合結(jié)果來看,本例實(shí)現(xiàn)了一個(gè)上升沿觸發(fā)的D觸發(fā)器。3.4.2過程賦值語句過程賦值語句的更新對(duì)象是寄存器、整數(shù)等。這些類型的變量在被賦值后,其值將保持不變,直到被其他過程賦值語句賦予新值。過程賦值語句與數(shù)據(jù)流建模中的連續(xù)賦值語句是不同的。首先,連續(xù)賦值語句總是處于活動(dòng)狀態(tài),任意一個(gè)操作數(shù)的變化都會(huì)導(dǎo)致表達(dá)式的重新計(jì)算以及重新賦值,但過程賦值語句只有在執(zhí)行到的時(shí)候才會(huì)起作用。其次,更新對(duì)象不同,連續(xù)賦值語句的更新對(duì)象是線網(wǎng),而過程賦值語句的更新對(duì)象是寄存器、整數(shù)等。最后,從形式上看,過程賦值語句不使用assign。但過程賦值語句與連續(xù)賦值語句又有相同之處,即兩者可以使用的運(yùn)算符是完全相同的。連續(xù)賦值語句中使用的運(yùn)算符在過程賦值語句中同樣適用,而且含義完全相同。
VerilogHDL包括兩種類型的過程賦值語句:阻塞賦值語句和非阻塞賦值語句。下面通過5個(gè)例題來說明兩種賦值方式的不同。這5個(gè)例題的設(shè)計(jì)目標(biāo)都是實(shí)現(xiàn)3位移位寄存器,它們分別采用了阻塞賦值方式和非阻塞賦值方式?!纠?-16】阻塞賦值方式描述的移位寄存器1。
moduleblock1(Q0,Q1,Q2,D,clk);
outputQ0,Q1,Q2;
inputclk,D;
regQ0,Q1,Q2;
always@(posedge
clk)
beginQ2=Q1;//注意賦值語句的順序Q1=Q0;Q0=D;
endendmodule綜合結(jié)果如圖3-13所示。圖3-13例3-16綜合出來的電路圖【例3-17】阻塞賦值方式描述的移位寄存器2。moduleblock2(Q0,Q1,Q2,D,clk);outputQ0,Q1,Q2;inputclk,D;regQ0,Q1,Q2;always@(posedge
clk)begin
Q1=Q0;//該句與下句的順序與例3-16顛倒
Q2=Q1; Q0=D;endendmodule綜合結(jié)果如圖3-14所示。
圖3-14例3-17綜合出來的電路圖【例3-18】阻塞賦值方式描述的移位寄存器3。moduleblock3(Q0,Q1,Q2,D,clk);outputQ0,Q1,Q2;inputclk,D;regQ0,Q1,Q2;always@(posedge
clk)begin
Q0=D;//3條賦值語句的順序與例3-16完全顛倒
Q1=Q0; Q2=Q1;endendmodule綜合結(jié)果如圖3-15所示。圖3-15例3-18綜合出來的電路圖【例3-19】非阻塞賦值方式描述的移位寄存器1。modulenon_block1(Q0,Q1,Q2,D,clk);outputQ0,Q1,Q2;inputclk,D;regQ0,Q1,Q2;always@(posedge
clk)
begin Q1<=Q0; Q2<=Q1; Q0<=D;endendmodule【例3-20】非阻塞賦值方式描述的移位寄存器2。modulenon_block2(Q0,Q1,Q2,D,clk);outputQ0,Q1,Q2;inputclk,D;regQ0,Q1,Q2;always@(posedgeclk)beginQ0<=D;//3條賦值語句的順序與例3-19完全顛倒
Q2<=Q1; Q1<=Q0;endendmodule例3-19和例3-20的綜合結(jié)果是一樣的,如圖3-16所示。圖3-16例3-19和例3-20綜合出來的電路圖例3-16~例3-20的程序說明:
(1)?5個(gè)例題的設(shè)計(jì)目標(biāo)均是實(shí)現(xiàn)3位移位寄存器,但從綜合結(jié)果可以看出例3-17和例3-18沒有實(shí)現(xiàn)設(shè)計(jì)目標(biāo)。
(2)Q2=Q1;這種賦值方式稱為阻塞賦值,Q2的值在賦值語句執(zhí)行完成后立刻就改變,而且隨后的語句必須在賦值語句執(zhí)行完成后才能繼續(xù)執(zhí)行。所以當(dāng)例3-18中的三條語句Q0=D;Q1=Q0;Q2=Q1;執(zhí)行完后,Q0、Q1、Q2的值都變化為D的值,也就是說,D的值同時(shí)賦給了Q0、Q1、Q2,參照其綜合結(jié)果能更清晰地看到這一點(diǎn)。例3-16和例3-17可通過同樣的分析得出與綜合結(jié)果一致的結(jié)論。
(3)Q2<=Q1;這種賦值方式稱為非阻塞賦值,Q2的值在賦值語句執(zhí)行完后并不會(huì)立刻就改變,而是等到整個(gè)always語句塊結(jié)束后才完成賦值操作。所以當(dāng)例3-20中的三條語句Q0<=D;Q2<=Q1;Q1<=Q0;執(zhí)行完后,Q0、Q1、Q2的值并沒有立刻更新,而是保持了原來的值,直到always語句塊結(jié)束后才同時(shí)進(jìn)行賦值,因此Q0的值變?yōu)榱薉的值,Q2的值變?yōu)榱嗽瓉鞶1的值,Q1的值變?yōu)榱嗽瓉鞶0的值(而不是剛剛更新的Q0的值D),參照其綜合結(jié)果能更清晰地看到這一點(diǎn)。例3-19可通過同樣的分析得出與綜合結(jié)果一致的結(jié)論。
(4)例3-16~例3-18采用的是阻塞賦值方式,可以看出阻塞賦值語句在always塊語句中的位置對(duì)其結(jié)果有影響;例3-19和例3-20采用的是非阻塞賦值方式,可以看出非阻塞賦值語句在always塊語句中的位置對(duì)其結(jié)果沒有影響。因此,在使用賦值語句時(shí)要注意兩者的區(qū)別與聯(lián)系。3.4.3塊語句塊語句通常用來將兩條或多條語句組合在一起,使它們更像一條語句,類似于C語言中的復(fù)合語句。VerilogHDL中可綜合的塊語句為順序塊,關(guān)鍵字begin和end用于將多條語句組成順序塊,前面有許多例子用到了順序塊。順序塊具有以下特點(diǎn):
(1)順序塊中的語句是一條接一條按順序執(zhí)行的;只有前面的語句執(zhí)行完之后才能執(zhí)行后面的語句(非阻塞賦值語句除外)。
(2)嵌套塊:塊可以嵌套使用。
(3)命名塊:塊可以具有自己的名字,我們稱之為命名塊。在命名塊中可以聲明局部變量;命名塊是設(shè)計(jì)層次的一部分,命名塊中聲明的變量可以通過層次名引用進(jìn)行訪問。下面是一個(gè)使用命名塊的例子。
【例3-21】完成以下兩個(gè)功能:(1)使用異或運(yùn)算符對(duì)D完成縮位異或運(yùn)算;(2)檢測D中1的個(gè)數(shù)。
VerilogHDL實(shí)現(xiàn)代碼如下:module
named_block(D,xnor_D,CountOnes);
input[3:0]D;
outputreg
xnor_D;
outputreg[2:0]CountOnes;always@(D)begin:block1
xnor_D=0;
CountOnes=0; begin:xor_block integerI; for(I=0;I<4;I=I+1)
xnor_D=xnor_D^D[I]; end//循環(huán)
begin:Count_block integerJ; for(J=0;J<4;J=J+1) if(D[J])
CountOnes=CountOnes+1; endendendmodule
程序說明:
(1)本例使用了for循環(huán)語句來對(duì)D的各位進(jìn)行運(yùn)算。for語句的用法參見“循環(huán)語句”一節(jié)。
(2)本例定義了3個(gè)命名塊,其中塊block1和塊xor_block、塊Count_block是嵌套關(guān)系。xor_block的功能是完成縮位異或,塊Count_block的功能是完成檢測D中1的個(gè)數(shù)。
(3)在命名塊xor_block中聲明的局部變量I和在命名塊Count_block中聲明的局部變量J,都用于循環(huán)計(jì)數(shù)。需要說明的是,如果在塊中使用局部變量,則必須對(duì)該塊進(jìn)行命名。3.4.4條件語句
if-else語句用來判定所給定的條件是否滿足,根據(jù)判定的結(jié)果(真或假)決定執(zhí)行給出的兩種操作中的哪一種。VerilogHDL語言提供了三種形式的if語句:
(1)形式一:
if(表達(dá)式)語句;例如:
if(a>b)out1<=int1;(2)形式二:if(表達(dá)式)語句1;else 語句2;例如:
if(a>b)out1<=int1;elseout1<=int2;(3)形式三:if(表達(dá)式1)語句1;elseif(表達(dá)式2)語句2;elseif(表達(dá)式3)語句3;...elseif(表達(dá)式m)語句m;else語句n;例如:
if(a>b)out1<=int1;
elseif(a==b)out1<=int2;
elseout1<=int3;下面是一個(gè)使用if語句的例子?!纠?-22】使用always語句描述具有同步復(fù)位和同步置位功能的D觸發(fā)器。
modulemydff(q,clk,set,clr,d);
inputclk,d,set,clr;
outputq;regq;
always@(posedge
clk)
begin
if(set)q<=1;elseif(!clr)q<=0;elseq<=d;endendmodule綜合結(jié)果如圖3-17所示。圖3-17例3-22的綜合結(jié)果程序說明:
(1)本程序使用了第3種if語句形式:if…elseif…else的條件語句,在時(shí)鐘上升沿時(shí)刻,首先判斷置位信號(hào)set是否有效,若有效則將D觸發(fā)器輸出置1,否則判斷復(fù)位信號(hào)clr是否有效,若有效則將D觸發(fā)器輸出置0,否則將數(shù)據(jù)d賦予D觸發(fā)器輸出。
(2)?if(set)等同于if(set==1),elseif(!clr)等同于if(clr!=1),VerilogHDL允許采用這樣的表達(dá)式簡寫方式。
(3)?always@(posedge
clk)語句表示只有在clk上升沿時(shí)才開始執(zhí)行always語句塊,否則不執(zhí)行。所以,D觸發(fā)器置位和復(fù)位為同步置位和同步復(fù)位。關(guān)于條件語句的進(jìn)一步說明:
(1)三種形式的if語句中在if后面都有“表達(dá)式”,這種表達(dá)式一般為邏輯表達(dá)式或關(guān)系表達(dá)式。系統(tǒng)對(duì)表達(dá)式的值進(jìn)行判斷,若為1按“真”處理,否則按“假”處理,執(zhí)行指定的語句。
(2)三種形式的if語句在語句后都有分號(hào)。這是由于分號(hào)是VerilogHDL語句中不可缺少的部分,這個(gè)分號(hào)是if語句中的內(nèi)嵌套語句所要求的。但應(yīng)注意,不要誤認(rèn)為if和else是兩個(gè)語句,其實(shí)它們都屬于同一個(gè)if語句。else子句不能作為語句單獨(dú)使用,它必須是if語句的一部分,且與離它最近的if配對(duì)使用。
(3)在if和else后面可以包含一個(gè)語句,也可以有多個(gè)操作語句,此時(shí)可用begin和end這兩個(gè)關(guān)鍵詞將幾個(gè)語句包含起來,使其成為一個(gè)復(fù)合塊語句。例如:
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ù)合語句,不需再附加分號(hào)。
(4)?if語句的嵌套。在if語句中又包含一個(gè)或多個(gè)if語句稱為if語句的嵌套。一般形式如下:
if(expression1)
if(expression2)語句1
else語句2elseif(expression3)語句3else語句4應(yīng)當(dāng)注意if與else的配對(duì)關(guān)系,else總是與它上面最近的if配對(duì)。如果if與else的數(shù)目不一樣,為了實(shí)現(xiàn)程序設(shè)計(jì)者的企圖,可以用begin…end塊語句來確定配對(duì)關(guān)系。例如:
if( )
begin
if( )語句1
end
else語句2這時(shí)begin_end塊語句限定了內(nèi)嵌if語句的范圍,因此else與第一個(gè)if配對(duì)。注意begin_end塊語句在if_else語句中的使用。3.4.5多路分支語句基本的if語句只有兩個(gè)分支可供選擇,而實(shí)際問題中常常需要用到多分支選擇,
VerilogHDL提供的case語句可直接處理多分支選擇。case語句的一般形式如下:
case(表達(dá)式) <case分支項(xiàng)> endcase
case分支項(xiàng)的一般格式如下:分支表達(dá)式: 語句;缺省項(xiàng)(default項(xiàng)): 語句;
case括弧內(nèi)的表達(dá)式稱為控制表達(dá)式,case分支項(xiàng)中的表達(dá)式稱為分支表達(dá)式??刂票磉_(dá)式通常表示為控制信號(hào)的某些位,分支表達(dá)式則用這些控制信號(hào)的具體狀態(tài)值來表示,因此分支表達(dá)式又可以稱為常量表達(dá)式。當(dāng)控制表達(dá)式的值與分支表達(dá)式的值相等時(shí),就執(zhí)行分支表達(dá)式后面的語句。如果所有的分支表達(dá)式的值都沒有與控制表達(dá)式的值相匹配的,就執(zhí)行default后面的語句。
default項(xiàng)可有可無,一個(gè)case語句里只允許有一個(gè)default項(xiàng)。下面是一個(gè)簡單的使用case語句的例子。
【例3-23】使用case語句實(shí)現(xiàn)四功能的算術(shù)邏輯單元(ALU),其輸入信號(hào)a、b均為4位,功能選擇信號(hào)sel為2位,輸出信號(hào)out為5位,具體關(guān)系見表3-8。VerilogHDL的實(shí)現(xiàn)代碼如下:
modulealu_4fun(a,b,sel,out);
input[3:0]a,b;
input[1:0]sel;
outputreg[4:0]out;
always@(a,b,sel)
begin
case(sel)
2'b00:out=a+b; 2'b01:out=a-b; 2'b10:out=a<<b; default:out=a%b;
endcaseendendmodule該例的功能仿真結(jié)果如圖3-18所示。圖3-18功能仿真結(jié)果程序說明:
(1)執(zhí)行完case分項(xiàng)后的語句,將跳出該case語句結(jié)構(gòu),終止case語句的執(zhí)行。
(2)在用case語句表達(dá)式進(jìn)行比較的過程中,只有當(dāng)信號(hào)對(duì)應(yīng)位的值能明確進(jìn)行比較時(shí),比較才能成功,因此要注意詳細(xì)說明case分項(xiàng)的分支表達(dá)式的值。case語句的所有表達(dá)式的值的位寬必須相等,只有這樣,控制表達(dá)式和分支表達(dá)式才能進(jìn)行對(duì)應(yīng)位的比較。
(3)每一個(gè)case分項(xiàng)的分支表達(dá)式的值必須互不相同,否則就會(huì)出現(xiàn)矛盾現(xiàn)象(對(duì)表達(dá)式的同一個(gè)值有多種執(zhí)行方案,對(duì)應(yīng)到實(shí)際的電路,則會(huì)感覺到電路不穩(wěn)定)。
(4)?case語句與if…else…if語句可以很容易地轉(zhuǎn)換,但與case語句中的控制表達(dá)式和多分支表達(dá)式這種比較結(jié)構(gòu)相比,if…else…if結(jié)構(gòu)中的條件表達(dá)式更為直觀一些。
(5)程序中使用了default語句,這樣可避免生成鎖存器。由于條件語句或多路分支語句使用不當(dāng),可能會(huì)在設(shè)計(jì)中生成原本沒有的鎖存器。對(duì)于條件語句的不當(dāng)使用,見下例:
always@(aord)
begin
if(a)q<=d;
end上例always語句塊中,if語句說明了當(dāng)a=1時(shí),q取d的值。當(dāng)a=0時(shí),q取什么值沒有定義。在always塊內(nèi),如果在給定的條件下變量沒有賦值,這個(gè)變量將保持原值,也就是說會(huì)生成一個(gè)鎖存器。如果希望當(dāng)a=0時(shí)q的值為0,else項(xiàng)就必不可少了,如下例所示。整個(gè)VerilogHDL程序模塊綜合出來后,always塊對(duì)應(yīng)的部分不會(huì)生成鎖存器。
always@(aord)
begin
if(a)q<=d;
elseq<=0;
end對(duì)于多路選擇語句的不當(dāng)使用,見下例:
always@(seloraorb)
case(sel)
2'b00:q<=a;
2'b11:q<=b;
endcase
上例中,case語句的功能是:在信號(hào)sel取不同的值時(shí),給另一個(gè)信號(hào)q賦不同的值。always塊中說明了如果sel=0,q取a值,而sel=2'b11,q取b的值。如果sel取2'b00和2'b11以外的值時(shí),q將被賦予什么值?答案是:在always塊內(nèi),默認(rèn)為q保持原值,這樣便自動(dòng)生成了鎖存器。如果希望當(dāng)sel取2'b00和2'b11以外的值時(shí)q賦為0,則default就必不可少了,如下例所示:
always@(seloraorb)
case(sel)
2'b00:q<=a;
2'b11:q<=b;
default:q<=‘b0;
endcase
程序中的case語句有default項(xiàng),指明了如果sel不取2'b00或2'b11時(shí),編譯器或仿真器應(yīng)賦給q的值。整個(gè)VerilogHDL程序模塊綜合出來后,always塊對(duì)應(yīng)的部分不會(huì)生成鎖存器。
如果用到if語句,最好寫上else項(xiàng)。如果用case語句,最好寫上default項(xiàng)。遵循上面兩條原則,就可以避免發(fā)生偶然生成鎖存器這種錯(cuò)誤,使設(shè)計(jì)者更加明確設(shè)計(jì)目標(biāo),同時(shí)也增強(qiáng)了VerilogHDL程序的可讀性。
3.4.6循環(huán)語句在VerilogHDL中常用的可綜合的循環(huán)語句有repeat和for,用來控制執(zhí)行語句的執(zhí)行次數(shù)。
repeat用于連續(xù)執(zhí)行一條語句n次。
for通過以下三個(gè)步驟來決定語句的循環(huán)執(zhí)行:
(1)先給控制循環(huán)次數(shù)的變量賦初值。
(2)判定控制循環(huán)表達(dá)式的值,如為假,則跳出循環(huán)語句,如為真,則執(zhí)行指定的循環(huán)語句后,轉(zhuǎn)到第三步。
(3)執(zhí)行一條賦值語句來修正控制循環(huán)變量次數(shù)的變量的值,然后返回第二步。下面對(duì)各種循環(huán)語句進(jìn)行詳細(xì)介紹。
1.?repeat語句
repeat語句的格式如下:
repeat(表達(dá)式)語句;或?repeat(表達(dá)式)begin多條語句end
【例3-24】使用repeat循環(huán)語句及加法和移位操作來實(shí)現(xiàn)一個(gè)參數(shù)化的多位乘法器。
modulemult_repeat(result,op_a,op_b);
parametersize=4;
input[size:1]op_a,op_b;
output[2*size:1]result;
reg[2*size:1]shift_opa,result;
reg[size:1]shift_opb;
always@(op_aorop_b)
begin:mult
result=0;shift_opa=op_a;shift_opb=op_b;repeat(size)beginif(shift_opb[1])result=result+shift_opa;
shift_opa=shift_opa<<1;//Shiftleft
shift_opb=shift_opb>>1;//Shiftrightendendendmodule
程序說明:
(1)本例所采用的通過加法和移位操作實(shí)現(xiàn)乘法的算法在前面的例子中已經(jīng)作過介紹,在此不再贅述。
(2)在repeat語句中,其表達(dá)式通常為常量表達(dá)式。如例3-24的repeat(size)中表達(dá)式size的值為常值4。
2.?for語句
for語句的一般形式為:
for(表達(dá)式1;表達(dá)式2;表達(dá)式3)語句;它的執(zhí)行過程如下:
(1)求解表達(dá)式1。
(2)求解表達(dá)式2,若其值為真(非0),則執(zhí)行for語句中指定的內(nèi)嵌語句,然后執(zhí)行下面的第(3)步。若為假(0),則結(jié)束循環(huán),轉(zhuǎn)到第(5)步。(3)若表達(dá)式為真,在執(zhí)行指定的語句后,求解表達(dá)式3。(4)轉(zhuǎn)回上面的第(2)步繼續(xù)執(zhí)行。(5)執(zhí)行for語句下面的語句。
【例3-25】使用for循環(huán)語句實(shí)現(xiàn)一個(gè)參數(shù)化的多位乘法器。
modulemult_for(result,op_a,op_b);
parametersize=4;
input[size:1]op_a,op_b;
output[2*size:1]result;
reg[2*size:1]shift_opa,result;
reg[size:1]shift_opb;
always@(op_aorop_b)
begin:mult//由于塊中定義了局部變量i,因此此處必須給塊命名
integeri=0;
result=0;shift_opa=op_a;shift_opb=op_b;
for(i=0;i<size;i=i+1)
begin
if(shift_opb[1])result=result+shift_opa;
shift_opa=shift_opa<<1;//Shiftleft
shift_opb=shift_opb>>1;//Shiftrightendendendmodule
程序說明:
(1)本例使用for循環(huán)代替repeat來實(shí)現(xiàn)乘法功能,二者的原理相同,實(shí)現(xiàn)形式上有所區(qū)別。
(2)本例中for(i=0;i<size;i=i+1)是for語句最簡單的應(yīng)用形式,其中的i僅用作循環(huán)計(jì)數(shù),不再作其他用途。
(3)若在順序塊中定義變量,則需要給順序塊命名,如本例中的順序塊命名為mult。
【例3-26】使用for循環(huán)語句實(shí)現(xiàn)一個(gè)參數(shù)化的多位乘法器的另一種算法。
modulemult_for2(result,op_a,op_b);
parametersize=4;
input[size:1]op_a,op_b;
output[2*size:1]result;
reg[2*size:1]shift_opa,result;
reg[size:1]shift_opb;
always@(op_aorop_b)
begin:mult integerj; result=0; for(j=1;j<=size;j=j+1)
if(op_b[j]) r
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年智能硬件設(shè)備及配套軟件研發(fā)與銷售合同
- 2024年版道路運(yùn)輸司機(jī)合同2篇
- 2021-2022學(xué)年甘肅省白銀市部分學(xué)校高一上學(xué)期第二次聯(lián)考語文試題(解析版)
- 2025造價(jià)工程師經(jīng)驗(yàn)對(duì)建設(shè)工程合同的審查意義備考資料
- 2025年陽泉貨運(yùn)準(zhǔn)駕證模擬考試
- 2024年房地產(chǎn)項(xiàng)目施工監(jiān)理合同范本集錦3篇
- 2024年度高級(jí)實(shí)習(xí)生個(gè)人隱私及商業(yè)秘密保護(hù)協(xié)議3篇
- 洛陽科技職業(yè)學(xué)院《經(jīng)濟(jì)數(shù)學(xué)(一)》2023-2024學(xué)年第一學(xué)期期末試卷
- 高端制造企業(yè)總經(jīng)理聘任合同
- 2024年度船舶買賣居間代理合同實(shí)施細(xì)則下載3篇
- 中軟統(tǒng)一終端安全管理平臺(tái)v90使用手冊(cè)
- 護(hù)理質(zhì)量管理PPT通用課件
- 氨水崗位應(yīng)知應(yīng)會(huì)手冊(cè).docx
- AQ-C1-19 安全教育記錄表(三級(jí))
- 廣東飼料項(xiàng)目建議書(參考范文)
- 鋁單板、玻璃幕墻建筑施工完整方案
- 六年級(jí)數(shù)學(xué)簡便計(jì)算易錯(cuò)題
- 工程造價(jià)咨詢公司質(zhì)量控制制度
- 《常用醫(yī)學(xué)檢查》PPT課件.ppt
- 《發(fā)展經(jīng)濟(jì)學(xué)派》PPT課件.ppt
- 雙層罐技術(shù)要求內(nèi)容
評(píng)論
0/150
提交評(píng)論