Verilog HDL數(shù)字設計教程(賀敬凱)第3章_第1頁
Verilog HDL數(shù)字設計教程(賀敬凱)第3章_第2頁
Verilog HDL數(shù)字設計教程(賀敬凱)第3章_第3頁
Verilog HDL數(shù)字設計教程(賀敬凱)第3章_第4頁
Verilog HDL數(shù)字設計教程(賀敬凱)第3章_第5頁
已閱讀5頁,還剩199頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

3.1建模方法引例

3.2結構化形式建模

3.3數(shù)據(jù)流級建模

3.4行為級建模

3.5小結

習題33.1建模方法引例

下面通過一個典型數(shù)字電路實例來引入建模方法。

【例3-1】設計實現(xiàn)一個3人判決電路,若3個人中有2人或者超過2人同意,則表決結果為通過;否則表決結果為不通過。這是一道經(jīng)典的數(shù)字電路例題,下面我們來看一下數(shù)字電路中對該問題的求解過程。第一步:理解題意。設a、b、c分別代表3個人,同意用1表示,不同意用0表示,y代表表決結果,1表示通過,0表示不通過。根據(jù)題意有,當a、b、c三個中有2個為1,或者3個均為1時,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的電路實現(xiàn)至此解題完畢。以上五步,我們均可以采用VerilogHDL語言進行數(shù)字電路建模,建模過程見例3-2至例3-6。

【例3-2】對應于步驟一的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Ⅱ軟件綜合的結果如圖3-3所示。圖3-3例3-2的綜合結果【例3-3】對應于步驟二的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Ⅱ軟件綜合的結果如圖3-4所示。圖3-4例3-3的綜合結果

【例3-4】對應于步驟三的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Ⅱ軟件綜合的結果如圖3-5所示。圖3-5例3-4的綜合結果

【例3-5】對應于步驟四的Verilog建模。

moduledecision_4(a,b,c,y);

inputa,b,c;

outputy;

assigny=(a&b)|(b&c)|(c&a);

endmodule使用QuartusⅡ軟件綜合的結果如圖3-2所示。

【例3-6】對應于步驟五的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Ⅱ軟件綜合的結果如圖3-2所示。以上五步對應著不同的建模方法,但其功能仿真波形都是相同的,如圖3-6所示。圖3-6功能仿真波形從仿真波形可以看出,以上五種不同的建模方法均實現(xiàn)了判決功能,都是問題的解決方法。對例3-2至例3-6的說明:

(1)各種建模方法得出的電路圖不盡相同,但最終的仿真結果完全相同,也就是說,最終的電路實現(xiàn)不同,但功能卻相同。

(2)例3-2和例3-3采用了行為建模方式建模,用到了always語句;例3-4和例3-5采用了數(shù)據(jù)流建模方式建模,用到了assign語句;例3-6采用了門級建模方式建模,調(diào)用了門級原語。這三種建模方式是VerilogHDL最主要的建模方式。在一個模塊中,可以采用以上三種建模方式的一種建模,也可以采用多種方式混合建模。本章后續(xù)內(nèi)容還要對上述三種建模方式展開討論。

(3)例3-2用到了條件語句if,例3-3用到多路分支語句case,這些語句只能用在always語句中,也就是只能用在行為建模中;assign語句是數(shù)據(jù)流建模的標志;模塊調(diào)用類似于門級原語調(diào)用,均歸屬結構化建模。

(4)從以上例子也可以看出,從門級建模到數(shù)據(jù)流建模再到行為建模,建模抽象程度越來越高,距離電路的具體實現(xiàn)越來越遠,但是也越來越接近人類解決問題的思維。3.2結構化形式建模

在VerilogHDL中可使用如下方式描述結構:

(1)開關級原語(在晶體管級)——開關級建模。

(2)內(nèi)置門原語(在門級)——門級建模。

(3)用戶定義的原語。

(4)模塊實例(創(chuàng)建層次結構)。上述幾種結構化描述方式之中,比較常用的是門級建模、用戶自定義原語和模塊實例。而模塊實例化已在第2章中進行了介紹,下面僅就門級建模和用戶自定義原語作詳細介紹。3.2.1門級建模簡單的邏輯電路可以使用邏輯門來設計實現(xiàn)?;镜倪壿嬮T分為兩類:與/或門類、緩沖/非門類。

1.與/或門類與/或門類包括與門(and)、或門(or)、與非門(nand)、或非門(nor)、異或門(xor)、同或門(xnor)。與/或門類都具有一個標量輸出端和多個標量輸入端,門的端口列表中的第一個端口必定是輸出端口,其他均為輸入端口。當任意一個輸入端口的值發(fā)生變化時,輸出端的值立即重新計算。與/或門類的實例引用:

wireOUT,IN1,IN2,IN3;

andand2(OUT,IN1,IN2);

//基本門的實例引用

nandnand3(OUT,IN1,IN2,IN3);

//輸入端超過兩個,三輸入與非門

and(OUT,IN1,IN2,IN3);

//合法的門實例引用,不給實例命名

2.緩沖/非門類緩沖/非門類包括緩沖器(buf)、非門(not)、帶控制端的緩沖器/非門(bufif1、bufif0、notif1、notif0)。緩沖/非門類具有一個標量輸入端和多個標量輸出端,門的端口列表中的最后一個端口必定是輸入端口,其他均為輸出端口。緩沖/非門類的實例引用:wireOUT1,OUT2,OUT3,IN,ctrl;bufb1(OUT1,IN);

//基本門的實例引用notn1(OUT1,IN);

//基本門的實例引用bufb2(OUT1,OUT2,OUT3,IN);

//輸出端超過兩個,三輸出緩沖not(OUT1,OUT2,IN);

//合法的門實例引用,不給實例命名bufif1(OUT1,IN,ctrl);//ctrl為1時,OUT1=INnotif0(OUT1,IN,ctrl);//ctrl為0時,OUT1=~IN

【例3-7】利用雙輸入端的nand門,編寫自己的雙輸入端的與門(my_and)、或門(my_or)、非門(my_not)、異或門(my_xor)。

modulemy_and(a,b,y);//用兩個nand門實現(xiàn)與門

inputa,b;

outputy;

wirenandab;

nand(nandab,a,b),

(y,nandab,nandab);

endmodulemodulemy_or(a,b,y);//用三個nand門實現(xiàn)或門inputa,b;outputy;wirenandaa,nandbb;nand(nandaa,a,a),(nandbb,b,b),(y,nandaa,nandbb);endmodulemodulemy_not(a,y);//用一個nand門實現(xiàn)非門inputa;outputy;nand(y,a,a);endmodulemodulemy_xor(a,b,y);//用四個nand門實現(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)用門級原語時均沒有給出實例名。注意,在門級原語實例引用的時候,我們可以不指定具體的實例名,這一點對需要實例引用幾百個甚至更多門的模塊提供了方便。但對于初學者,建議在調(diào)用門級原語時給出實例名。

(2)在實際應用中,與非門和或非門的應用更為普遍,這是因為由這兩種門生成其他邏輯門較容易實現(xiàn)。

(3)例子中有4個模塊,分別實現(xiàn)與門、或門、非門、異或門,可在多模塊編譯環(huán)境QuartusⅡ中逐個模塊編譯并進行仿真驗證,這部分工作留給讀者完成。邏輯門是最基本的電路單元,任何復雜的數(shù)字邏輯電路均可由邏輯門實現(xiàn)。但復雜電路的設計如果從邏輯門開始來搭建,顯然是不現(xiàn)實的,必須采用其他建模方式。3.2.2用戶自定義原語

VerilogHDL提供了一整套標準的原語,例如and、or、nor和not等,它們是該語言的一部分,即通常所說的內(nèi)置原語。然而,在設計過程中,設計者有時希望使用自己編寫的原語。VerilogHDL具有這種自定義原語的能力,這種原語就是用戶自定義原語(UserDefinedPrimitive,UDP)。UDP是自成體系的,在UDP中不能調(diào)用其他模塊或者其他原語。UDP的調(diào)用方式和門級原語的調(diào)用方式完全相同。

UDP有兩類:

(1)表示組合邏輯的UDP:輸出僅取決于輸入信號的組合邏輯。

(2)表示時序邏輯的UDP:下一個輸出值不但取決于當前的輸入值,還取決于當前的內(nèi)部狀態(tài)。

UDP的語法定義如下:primitive<UDP名稱>(<輸出端口名>,<輸入端口名>);//端口說明語句output<輸出端口名>;input<輸入端口名>;reg<輸出端口名>;(可選,只有表示時序邏輯的UDP才需要)//UDP初始化(只有時序邏輯才需要)Initial<輸出端口名>=<值>//UDP狀態(tài)表table<狀態(tài)表>endtableendprimitive下面舉例對這兩類UDP進行說明。

【例3-8】表示組合邏輯的UDP舉例:一位全加器。全加器進位實現(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全加器求和實現(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)用上述兩個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設計全加器,僅需要兩個UDP來描述全加器的邏輯功能;而使用VerilogHDL原語元件,則需要多個VerilogHDL提供的基本門級原語元件。當設計需要使用大量全加器時,采用UDP來表示全加器,將大大減少內(nèi)存的需要,事件的數(shù)目將大大降低。

(2)兩個UDP的端口列表中,第一個端口CO和S均為輸出端口,其余端口均為輸入端口。

(3)程序中的“?”表示邏輯值可以為0、1或x。

(4)使用QuartusⅡ軟件綜合的結果如圖3-7所示。圖3-7一位全加器的綜合結果其仿真波形如圖3-8所示。圖3-8一位全加器的仿真波形從仿真波形可以看出,該設計實現(xiàn)了一位全加器的功能。

【例3-9】表示時序邏輯的UDP舉例:D觸發(fā)器。

primitived_edge_ff(q,clk,data);

outputq;

inputclk,data;

regq;

table//clk

datstatenext

(01)0:?:0;

(01)1:?:1;//時鐘下降沿

(?0)?:?:-;

//時鐘穩(wěn)定時忽略data的變化

?(??):?:-;

endtable

endprimitive程序說明:

(1)使用QuartusⅡ軟件綜合的結果如圖3-9所示。圖3-9D觸發(fā)器的綜合結果從綜合結果可以看出,該設計實現(xiàn)了一個D觸發(fā)器。

(2)程序中的“?”表示邏輯值可以為0、1或x。

(3)端口列表中的第一個端口q為輸出端口,其余為輸入端口。對用戶自定義原語的進一步說明:

(1)?UDP只能有一個輸出,輸出端口必須列為端口列表的第一個。如果在功能上要求有多個輸出,則需要在UDP輸出端連接其他的基本單元,或者同時使用幾個UDP。

(2)?UDP可以有1~10個輸入。若輸入端口超過5,則存儲需求會大幅增加。表3-2列出輸入端口數(shù)與存儲需求的關系。

(3)所有端口必須為標量且不允許是雙向端口。

(4)不支持邏輯值z。3.3數(shù)據(jù)流級建模

在電路規(guī)模較小的情況下,由于包含的門數(shù)比較少,因此使用門級建模進行設計不僅直觀,而且方便。但是,如果電路的功能比較復雜,則通常該電路包含的邏輯門的個數(shù)會很多,這時使用門級建模不僅繁瑣而且很容易出錯。在這種情況下,如果從更高抽象層次入手,將設計重點放在功能實現(xiàn)上,則不僅能避免繁瑣的細節(jié),還可以大大提高設計的效率。本節(jié)介紹更高抽象層次的建模方法:數(shù)據(jù)流建模。3.3.1連續(xù)賦值語句以關鍵詞assign開始的語句為連續(xù)賦值語句,連續(xù)賦值語句是Verilog數(shù)據(jù)流建模的基本語句,用于對線網(wǎng)進行賦值。

【例3-10】使用數(shù)據(jù)流建模,實現(xiàn)一位半加器。解題指引:半加器實現(xiàn)的是不帶進位的兩個數(shù)的相加,若半加器的輸入為ain和bin,輸出為sum和co,其中sum為和,co為進位,則半加器的真值表如表3-3所示。VerilogHDL實現(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拼接成一個兩位的數(shù)。

(2)連續(xù)賦值語句的左邊必須是一個標量或向量線網(wǎng),或者是標量或向量線網(wǎng)的拼接,而不能是任何形式的寄存器。例如下面的形式是非法的:

regsum;

assign{co,sum}=ain+bin;//非法,sum不能為寄存器類型對連續(xù)賦值語句的進一步說明:

(1)連續(xù)賦值語句的基本元素是表達式、運算符和操作數(shù)。其功能是計算右側表達式的值,然后賦給左邊變量。表達式由運算符和操作數(shù)構成,根據(jù)運算符界定的功能對操作數(shù)進行運算后得出結果。數(shù)據(jù)流的強大建模能力體現(xiàn)在多種運算符類型上。下一節(jié)我們將詳細介紹運算符類型。

(2)連續(xù)賦值語句總是處于激活狀態(tài)。只要任意一個操作數(shù)發(fā)生變化,表達式就會被立即重新計算,并且將結果賦給等號左邊的線網(wǎng)。

(3)操作數(shù)可以是標量或向量線網(wǎng),也可以是標量或向量寄存器。3.3.2運算符類型

VerilogHDL提供了許多類型的運算符,分別是算術、關系、邏輯、按位、縮減、條件、移位和位拼接運算符。表3-4按運算符類型列出了常用的運算符。從表3-4可知,在VerilogHDL語言中運算符所帶的操作數(shù)是不同的。只帶一個操作數(shù)的運算符稱為單目運算符,此時操作數(shù)需放在運算符的右邊;帶二個操作數(shù)的運算符稱為雙目運算符,操作數(shù)需放在運算符的兩邊;帶三個操作數(shù)的運算符稱為三目運算符,這三個操作數(shù)用三目運算符分隔開,如條件運算符就是三目運算符。表達式中的操作數(shù)可以是以下類型中的一種:常數(shù)、參數(shù)、線網(wǎng)、寄存器、位選擇、部分選擇、存儲器單元和函數(shù)調(diào)用。下面對表3-4中的運算符分別加以介紹。

1.算術運算符算術運算符包括加(+)、減(-)、乘(*)、除(/)、取模(%)、乘方(**)。

【例3-11】算術運算符示例。

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)加(+)、減(-)、乘(*)、除(/)、取模(%)、乘方(**)均為雙目運算符,要求運算符兩側均有操作數(shù)。

(2)該例仿真時可以設置在0~255內(nèi)的任意輸入值a和b,觀察add、sub、mul、div、mod、pow值的變化。

(3)乘方運算符要求冪是一個常量,不能為變量。對于算術運算符的進一步說明:

(1)在進行整數(shù)除法運算時,結果值要略去小數(shù)部分,只取整數(shù)部分。

(2)取模運算符又稱為求余運算符,要求%兩側均為整型數(shù)據(jù)。

(3)取模運算時,結果值的符號位采用模運算式里第一個操作數(shù)的符號位。表3-5中列舉了一些例子。

2.關系運算符關系運算符包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)、不等于(!=)。在進行關系運算時,如果聲明的關系是假的(flase),則返回值是0,如果聲明的關系是真的(true),則返回值是1。關系運算符中大于、小于、大于等于、小于等于有著相同的優(yōu)先級別,等于、不等于有著相同的優(yōu)先級別,前者的優(yōu)先級別大于后者的優(yōu)先級別。關系運算符的優(yōu)先級別低于算術運算符的優(yōu)先級別。例如:

a==size-1//這種表達方式等同于:a==(size-1)

size-(1==a)//這種表達方式不等同于:size-1==a

a<size-1//這種表達方式等同于:a<(size-1)

size-(1<a)//這種表達方式不等同于:size-1<a從上面的例子可以看出這兩種不同運算符的優(yōu)先級別。當表達式size-(1<a)進行運算時,關系表達式先運算,然后返回結果值0或1被size減去。而當表達式size-1<a進行運算時,size先減去1,然后再同a相比。

3.邏輯運算符邏輯運算符包括邏輯與(&&)、邏輯或(||)、邏輯非(!)?!?&”和“||”是雙目運算符,要求有兩個操作數(shù),如(a>b)&&(b>c)、(a<b)||(b<c)?!?!”是單目運算符,只要求一個操作數(shù),如!(a>b)。表3-6為邏輯運算的真值表。它表示當a和b的值為不同的組合時,各種邏輯運算所得到的值。邏輯運算符中“&&”和“||”的優(yōu)先級別低于關系運算符,“!”高于算術運算符。例如:

(a>b)&&(x>y)

//可寫成:a>b&&x>y

(a==b)||(x==y)

//可寫成:a==b||x==y

(!a)||(a>b) //可寫成:!a||a>b

4.按位運算符

按位運算符包括取反(~)、按位與(&)、按位或(|)、按位異或(^)、按位同或(~^,^~)。

位運算符中除了~?是單目運算符以外,其余均為雙目運算符。位運算符中的雙目運算符要求對兩個操作數(shù)的相應位進行運算操作。

表3-7給出了按位操作的邏輯規(guī)則。對按位運算符的幾點說明:

(1)兩個長度不同的數(shù)據(jù)進行位運算時,系統(tǒng)會自動將兩者按右端對齊。位數(shù)少的操作數(shù)會在相應的高位用0填滿,以使兩個操作數(shù)按位進行操作。

(2)按位運算符與邏輯運算符雖然符號相近,但兩者完全不同。邏輯運算符執(zhí)行邏輯操作,運算的結果是一個邏輯值0或1;按位運算符產(chǎn)生一個跟較長位寬操作數(shù)等寬的數(shù)值,該數(shù)值的每一位都是兩個操作數(shù)按位運算的結果。

5.縮減運算符

縮減運算符包括縮減與(&)、縮減與非(~&)、縮減或(|)、縮減或非(~|)、縮減異或(^)、縮減同或(~^,^~)。

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

例如:

reg[3:0]B;

regC;

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

由于邏輯運算符、按位運算符、縮減運算符都使用相同的符號表示,因此有時容易混淆。區(qū)分這些運算符的重點在于分清操作數(shù)的數(shù)目和運算的規(guī)則。

6.條件運算符

條件運算符(?:)帶有三個操作數(shù),其格式為:

條件表達式?真表達式:假表達式;

執(zhí)行過程為:首先計算條件表達式,如果為真,則計算真表達式的值;如果為假,則計算假表達式的值。條件運算符可以嵌套使用,每個真表達式或假表達式也可以是一個條件運算符表達式。條件表達式的作用相當于控制開關?!纠?-12】試用條件運算符來實現(xiàn)一個四選一多路選擇器。

Verilog實現(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);在真表達式和假表達式中均嵌套了一個條件運算符表達式。程序的運算過程如下:首先判斷condition1是否為真,若為真則計算(condition2?in1:in2),否則計算(condition2?in3:in4),然后按照同樣的規(guī)則計算這兩個條件運算符表達式。

(2)本代碼實現(xiàn)了一個四選一多路選擇器,輸出由條件condition1和condition2決定。根據(jù)代碼可以得出,當{condition2,condition1}為2'b11時選擇in1,為2'b10時選擇in3,為2'b01時選擇in2,為2'b00時選擇in4。

7.移位運算符移位運算符包括左移位運算符(<<)和右移位運算符(>>)。其使用方法如下:

a>>n或a<<n其中,a代表要進行移位的操作數(shù),n代表要移幾位。這兩種移位運算都用0來填補移出的空位。

【例3-13】采用移位運算符實現(xiàn)2個3位數(shù)的乘法。解題指引:設a為3位乘數(shù),用a2a1a0表示,設b為3位被乘數(shù),用b2b1b0表示,乘法運算過程如圖3-10所示。圖3-10乘法的運算過程乘法的最后是把5列分別求和得到5位的積。根據(jù)以上運算過程可以看出,乘法的最后也可以這樣進行,將最后3行代表的3個數(shù)相加,當然第2行相對第1行要左移1位,第3行相對第1行要左移2位。

VerilogHDL實現(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個中間變量,mul1用于存放第1行的值,mul2用于存放第1行和第2行的和,mul3用于存放所有3行的和。

(2)本例為2個3位數(shù)相乘,我們可以采用數(shù)據(jù)流建模方式來完成。如果位數(shù)較多,比如位數(shù)為64位,采用數(shù)據(jù)流建模則顯得繁瑣,此時可采用循環(huán)語句來完成此算法,即采用更高抽象級的行為建模。

(3)從本例可看出,由于移位運算符可以用來實現(xiàn)移位操作、乘法算法的移位相加以及其他許多有用的操作,因此在具體設計中是很有用處的。另外,進行移位運算時應注意移位前后變量的位數(shù),例如:4'b1001<<1=5'b10010,4'b1001<<2=6'b100100,1<<6=32'b1000000。

8.位拼接運算符位拼接運算符包括拼接運算符({})、重復運算符({{}})。拼接運算符{}可以把兩個或多個信號的某些位拼接起來進行運算操作。其使用方法如下:

{信號1的某幾位,信號2的某幾位,…,信號n的某幾位}即把某些信號的某些位詳細地列出來,中間用逗號分開,最后用大括號括起來表示一個整體信號。例如:

{a,b[3:0],w,3‘b101}//等價于

{a,b[3],b[2],b[1],b[0],w,1'b1,1'b0,1'b1}在位拼接表達式中的每個信號均需指明位數(shù),這是因為在計算拼接信號位寬的大小時必須知道其中每個信號的位寬。對于未指明位數(shù)的數(shù)字則按照默認值32位進行處理。例如:

{1,1}//64位,從右邊數(shù)第0位為1,第32位為1,其余位均為0如果需要重復多次拼接同一個操作數(shù),則可以使用重復運算符。重復拼接的次數(shù)用常數(shù)來表示,該常數(shù)指定了其后大括號內(nèi)變量的重復次數(shù)。例如:

{4{w}}//等價于{w,w,w,w}位拼接還可以用嵌套的方式來表達。例如:

{b,{3{a,b}}}//等價于{b,a,b,a,b,a,b}用于表示重復的表達式,如上例中的4和3,必須是常數(shù)表達式。位拼接運算符在一些場合非常有用,比如要在使用的函數(shù)中返回幾個值的時候,使用位拼接符可將幾個待返回的值拼接為一個值,作為函數(shù)值進行返回。

9.優(yōu)先級別如果不使用小括號將表達式的各個部分分開,則VerilogHDL將根據(jù)運算符之間的優(yōu)先級對表達式進行計算。圖3-11列出了常用的幾種運算符的優(yōu)先級別。圖3-11運算符的優(yōu)先級下面再通過一個例子說明運算符優(yōu)先級別的應用?!纠?-14】若a、b、x、y均定義為wire[3:0]類型,且a=1,b=7,試計算x和y的值。(1)

x=(a==2)?~a|b:b>>2;(2)

y=3+2>>2;計算結果為:

x=1,y=1程序說明:

(1)?x=(a==2)?~a|b:b>>2;用到了相等運算符(==)、按位運算符(~、|)、移位運算符(>>)和條件運算符(?:)。小括號優(yōu)先級最高,在計算時首先計算小括號內(nèi)的表達式的值,然后再按優(yōu)先級求其他表達式的值。按照其優(yōu)先級先求~a,因a=1且為4位wire類型,所以~a=4'b1110,然后可求出條件運算符的一個操作數(shù)~a|b的值為4'b1111;而條件運算符的另一個操作數(shù)b>>2的結果為4'b0001。根據(jù)題意,條件運算符的條件為假,所以x的值為4'b0001。

(2)?y=3+2>>2;用到了算術運算符(+)和移位運算符(>>)。根據(jù)優(yōu)先級,y=3+2>>2;等價于y=(3+2)>>2;,所以y的值為4'b0001。

(3)事實上,由于運算符的優(yōu)先級被忽視或混淆而造成錯誤的情況經(jīng)常發(fā)生。為了避免源于運算符優(yōu)先級的運算錯誤,在不確定運算符優(yōu)先級的情況下,建議讀者使用小括號將各個表達式分開。另外,使用括號也可以提高程序的可讀性,明確表達各運算符間的優(yōu)先關系。3.4行?為?級?建?模

VerilogHDL支持從算法的角度,即從電路外部行為的角度對其進行描述,因此行為級建模是從一個很高的抽象層次來表示電路的。?在這個層次上進行數(shù)字系統(tǒng)設計類似于使用C語言編程,而且VerilogHDL行為建模的語法結構和C語言相當類似。VerilogHDL提供了許多行為級建模語法結構,為設計者提供了很大的靈活性。3.4.1結構化過程語句always

always語句是行為建模的基本語句,每個always語句代表一個獨立的執(zhí)行過程,也稱為進程。與C語言不同,VerilogHDL的各個always進程是并發(fā)執(zhí)行的,而不是順序執(zhí)行的。

always語句包括的所有行為語句構成了一個always語句塊。每個always語句塊在滿足一定的條件后即執(zhí)行其中的第一條語句,然后順序執(zhí)行隨后的語句,直到最后一條語句執(zhí)行完后,再次等待always語句塊的執(zhí)行條件,等條件滿足后又從第一條語句開始執(zhí)行,循環(huán)往復。因此,always語句通常用于對數(shù)字電路中一組反復執(zhí)行的活動進行建模。【例3-15】使用always語句描述D觸發(fā)器。

modulemydff(q,clk,d);

inputclk,d;

outputq;regq;

always@(posedge

clk)

q<=d;

endmodule程序說明:

(1)本程序的功能是在時鐘上升沿時刻,將數(shù)據(jù)d賦予觸發(fā)器輸出q,其功能同D觸發(fā)器一樣。

(2)?always語句由于其不斷重復執(zhí)行的特性,只有和一定的時序控制結合在一起才有用。always@(posedge

clk)語句表示只有在clk上升沿時才開始執(zhí)行always語句塊,否則不執(zhí)行。這種時序控制是always語句最常用的。

(3)?always的時序控制除沿觸發(fā)時序控制外,還可以是電平觸發(fā)的,也可以是單個信號或多個信號,中間需要用關鍵字or或“,”連接,如:

always@(posedgeclockorposedgereset)//由兩個沿觸發(fā)的always塊

begin

end

always@(aorborc)//由多個電平觸發(fā)的always塊

begin

end沿觸發(fā)的always塊常用來描述時序邏輯,如果符合可綜合風格要求,則可用綜合工具將其自動轉換為表示時序邏輯的寄存器組和門級邏輯;而電平觸發(fā)的always塊常用來描述一般組合邏輯和帶鎖存器的組合邏輯,如果符合可綜合風格要求,則可轉換為表示組合邏輯的門級邏輯或帶鎖存器的組合邏輯。一個模塊中可以有多個always塊,它們都是并行運行的。(4)本例的綜合結果如圖3-12所示。圖3-12例3-15的綜合結果從綜合結果來看,本例實現(xiàn)了一個上升沿觸發(fā)的D觸發(fā)器。3.4.2過程賦值語句過程賦值語句的更新對象是寄存器、整數(shù)等。這些類型的變量在被賦值后,其值將保持不變,直到被其他過程賦值語句賦予新值。過程賦值語句與數(shù)據(jù)流建模中的連續(xù)賦值語句是不同的。首先,連續(xù)賦值語句總是處于活動狀態(tài),任意一個操作數(shù)的變化都會導致表達式的重新計算以及重新賦值,但過程賦值語句只有在執(zhí)行到的時候才會起作用。其次,更新對象不同,連續(xù)賦值語句的更新對象是線網(wǎng),而過程賦值語句的更新對象是寄存器、整數(shù)等。最后,從形式上看,過程賦值語句不使用assign。但過程賦值語句與連續(xù)賦值語句又有相同之處,即兩者可以使用的運算符是完全相同的。連續(xù)賦值語句中使用的運算符在過程賦值語句中同樣適用,而且含義完全相同。

VerilogHDL包括兩種類型的過程賦值語句:阻塞賦值語句和非阻塞賦值語句。下面通過5個例題來說明兩種賦值方式的不同。這5個例題的設計目標都是實現(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綜合結果如圖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綜合結果如圖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綜合結果如圖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的綜合結果是一樣的,如圖3-16所示。圖3-16例3-19和例3-20綜合出來的電路圖例3-16~例3-20的程序說明:

(1)?5個例題的設計目標均是實現(xiàn)3位移位寄存器,但從綜合結果可以看出例3-17和例3-18沒有實現(xiàn)設計目標。

(2)Q2=Q1;這種賦值方式稱為阻塞賦值,Q2的值在賦值語句執(zhí)行完成后立刻就改變,而且隨后的語句必須在賦值語句執(zhí)行完成后才能繼續(xù)執(zhí)行。所以當例3-18中的三條語句Q0=D;Q1=Q0;Q2=Q1;執(zhí)行完后,Q0、Q1、Q2的值都變化為D的值,也就是說,D的值同時賦給了Q0、Q1、Q2,參照其綜合結果能更清晰地看到這一點。例3-16和例3-17可通過同樣的分析得出與綜合結果一致的結論。

(3)Q2<=Q1;這種賦值方式稱為非阻塞賦值,Q2的值在賦值語句執(zhí)行完后并不會立刻就改變,而是等到整個always語句塊結束后才完成賦值操作。所以當例3-20中的三條語句Q0<=D;Q2<=Q1;Q1<=Q0;執(zhí)行完后,Q0、Q1、Q2的值并沒有立刻更新,而是保持了原來的值,直到always語句塊結束后才同時進行賦值,因此Q0的值變?yōu)榱薉的值,Q2的值變?yōu)榱嗽瓉鞶1的值,Q1的值變?yōu)榱嗽瓉鞶0的值(而不是剛剛更新的Q0的值D),參照其綜合結果能更清晰地看到這一點。例3-19可通過同樣的分析得出與綜合結果一致的結論。

(4)例3-16~例3-18采用的是阻塞賦值方式,可以看出阻塞賦值語句在always塊語句中的位置對其結果有影響;例3-19和例3-20采用的是非阻塞賦值方式,可以看出非阻塞賦值語句在always塊語句中的位置對其結果沒有影響。因此,在使用賦值語句時要注意兩者的區(qū)別與聯(lián)系。3.4.3塊語句塊語句通常用來將兩條或多條語句組合在一起,使它們更像一條語句,類似于C語言中的復合語句。VerilogHDL中可綜合的塊語句為順序塊,關鍵字begin和end用于將多條語句組成順序塊,前面有許多例子用到了順序塊。順序塊具有以下特點:

(1)順序塊中的語句是一條接一條按順序執(zhí)行的;只有前面的語句執(zhí)行完之后才能執(zhí)行后面的語句(非阻塞賦值語句除外)。

(2)嵌套塊:塊可以嵌套使用。

(3)命名塊:塊可以具有自己的名字,我們稱之為命名塊。在命名塊中可以聲明局部變量;命名塊是設計層次的一部分,命名塊中聲明的變量可以通過層次名引用進行訪問。下面是一個使用命名塊的例子。

【例3-21】完成以下兩個功能:(1)使用異或運算符對D完成縮位異或運算;(2)檢測D中1的個數(shù)。

VerilogHDL實現(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)語句來對D的各位進行運算。for語句的用法參見“循環(huán)語句”一節(jié)。

(2)本例定義了3個命名塊,其中塊block1和塊xor_block、塊Count_block是嵌套關系。xor_block的功能是完成縮位異或,塊Count_block的功能是完成檢測D中1的個數(shù)。

(3)在命名塊xor_block中聲明的局部變量I和在命名塊Count_block中聲明的局部變量J,都用于循環(huán)計數(shù)。需要說明的是,如果在塊中使用局部變量,則必須對該塊進行命名。3.4.4條件語句

if-else語句用來判定所給定的條件是否滿足,根據(jù)判定的結果(真或假)決定執(zhí)行給出的兩種操作中的哪一種。VerilogHDL語言提供了三種形式的if語句:

(1)形式一:

if(表達式)語句;例如:

if(a>b)out1<=int1;(2)形式二:if(表達式)語句1;else 語句2;例如:

if(a>b)out1<=int1;elseout1<=int2;(3)形式三:if(表達式1)語句1;elseif(表達式2)語句2;elseif(表達式3)語句3;...elseif(表達式m)語句m;else語句n;例如:

if(a>b)out1<=int1;

elseif(a==b)out1<=int2;

elseout1<=int3;下面是一個使用if語句的例子?!纠?-22】使用always語句描述具有同步復位和同步置位功能的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綜合結果如圖3-17所示。圖3-17例3-22的綜合結果程序說明:

(1)本程序使用了第3種if語句形式:if…elseif…else的條件語句,在時鐘上升沿時刻,首先判斷置位信號set是否有效,若有效則將D觸發(fā)器輸出置1,否則判斷復位信號clr是否有效,若有效則將D觸發(fā)器輸出置0,否則將數(shù)據(jù)d賦予D觸發(fā)器輸出。

(2)?if(set)等同于if(set==1),elseif(!clr)等同于if(clr!=1),VerilogHDL允許采用這樣的表達式簡寫方式。

(3)?always@(posedge

clk)語句表示只有在clk上升沿時才開始執(zhí)行always語句塊,否則不執(zhí)行。所以,D觸發(fā)器置位和復位為同步置位和同步復位。關于條件語句的進一步說明:

(1)三種形式的if語句中在if后面都有“表達式”,這種表達式一般為邏輯表達式或關系表達式。系統(tǒng)對表達式的值進行判斷,若為1按“真”處理,否則按“假”處理,執(zhí)行指定的語句。

(2)三種形式的if語句在語句后都有分號。這是由于分號是VerilogHDL語句中不可缺少的部分,這個分號是if語句中的內(nèi)嵌套語句所要求的。但應注意,不要誤認為if和else是兩個語句,其實它們都屬于同一個if語句。else子句不能作為語句單獨使用,它必須是if語句的一部分,且與離它最近的if配對使用。

(3)在if和else后面可以包含一個語句,也可以有多個操作語句,此時可用begin和end這兩個關鍵詞將幾個語句包含起來,使其成為一個復合塊語句。例如:

if(a>b)

begin

out1<=int1;

out2<=int2;

end

else

begin

out1<=int2;

out2<=int1;

end注意在end后不需要再加分號。因為begin…end內(nèi)是一個完整的復合語句,不需再附加分號。

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

if(expression1)

if(expression2)語句1

else語句2elseif(expression3)語句3else語句4應當注意if與else的配對關系,else總是與它上面最近的if配對。如果if與else的數(shù)目不一樣,為了實現(xiàn)程序設計者的企圖,可以用begin…end塊語句來確定配對關系。例如:

if( )

begin

if( )語句1

end

else語句2這時begin_end塊語句限定了內(nèi)嵌if語句的范圍,因此else與第一個if配對。注意begin_end塊語句在if_else語句中的使用。3.4.5多路分支語句基本的if語句只有兩個分支可供選擇,而實際問題中常常需要用到多分支選擇,

VerilogHDL提供的case語句可直接處理多分支選擇。case語句的一般形式如下:

case(表達式) <case分支項> endcase

case分支項的一般格式如下:分支表達式: 語句;缺省項(default項): 語句;

case括弧內(nèi)的表達式稱為控制表達式,case分支項中的表達式稱為分支表達式??刂票磉_式通常表示為控制信號的某些位,分支表達式則用這些控制信號的具體狀態(tài)值來表示,因此分支表達式又可以稱為常量表達式。當控制表達式的值與分支表達式的值相等時,就執(zhí)行分支表達式后面的語句。如果所有的分支表達式的值都沒有與控制表達式的值相匹配的,就執(zhí)行default后面的語句。

default項可有可無,一個case語句里只允許有一個default項。下面是一個簡單的使用case語句的例子。

【例3-23】使用case語句實現(xiàn)四功能的算術邏輯單元(ALU),其輸入信號a、b均為4位,功能選擇信號sel為2位,輸出信號out為5位,具體關系見表3-8。VerilogHDL的實現(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該例的功能仿真結果如圖3-18所示。圖3-18功能仿真結果程序說明:

(1)執(zhí)行完case分項后的語句,將跳出該case語句結構,終止case語句的執(zhí)行。

(2)在用case語句表達式進行比較的過程中,只有當信號對應位的值能明確進行比較時,比較才能成功,因此要注意詳細說明case分項的分支表達式的值。case語句的所有表達式的值的位寬必須相等,只有這樣,控制表達式和分支表達式才能進行對應位的比較。

(3)每一個case分項的分支表達式的值必須互不相同,否則就會出現(xiàn)矛盾現(xiàn)象(對表達式的同一個值有多種執(zhí)行方案,對應到實際的電路,則會感覺到電路不穩(wěn)定)。

(4)?case語句與if…else…if語句可以很容易地轉換,但與case語句中的控制表達式和多分支表達式這種比較結構相比,if…else…if結構中的條件表達式更為直觀一些。

(5)程序中使用了default語句,這樣可避免生成鎖存器。由于條件語句或多路分支語句使用不當,可能會在設計中生成原本沒有的鎖存器。對于條件語句的不當使用,見下例:

always@(aord)

begin

if(a)q<=d;

end上例always語句塊中,if語句說明了當a=1時,q取d的值。當a=0時,q取什么值沒有定義。在always塊內(nèi),如果在給定的條件下變量沒有賦值,這個變量將保持原值,也就是說會生成一個鎖存器。如果希望當a=0時q的值為0,else項就必不可少了,如下例所示。整個VerilogHDL程序模塊綜合出來后,always塊對應的部分不會生成鎖存器。

always@(aord)

begin

if(a)q<=d;

elseq<=0;

end對于多路選擇語句的不當使用,見下例:

always@(seloraorb)

case(sel)

2'b00:q<=a;

2'b11:q<=b;

endcase

上例中,case語句的功能是:在信號sel取不同的值時,給另一個信號q賦不同的值。always塊中說明了如果sel=0,q取a值,而sel=2'b11,q取b的值。如果sel取2'b00和2'b11以外的值時,q將被賦予什么值?答案是:在always塊內(nèi),默認為q保持原值,這樣便自動生成了鎖存器。如果希望當sel取2'b00和2'b11以外的值時q賦為0,則default就必不可少了,如下例所示:

always@(seloraorb)

case(sel)

2'b00:q<=a;

2'b11:q<=b;

default:q<=‘b0;

endcase

程序中的case語句有default項,指明了如果sel不取2'b00或2'b11時,編譯器或仿真器應賦給q的值。整個VerilogHDL程序模塊綜合出來后,always塊對應的部分不會生成鎖存器。

如果用到if語句,最好寫上else項。如果用case語句,最好寫上default項。遵循上面兩條原則,就可以避免發(fā)生偶然生成鎖存器這種錯誤,使設計者更加明確設計目標,同時也增強了VerilogHDL程序的可讀性。

3.4.6循環(huán)語句在VerilogHDL中常用的可綜合的循環(huán)語句有repeat和for,用來控制執(zhí)行語句的執(zhí)行次數(shù)。

repeat用于連續(xù)執(zhí)行一條語句n次。

for通過以下三個步驟來決定語句的循環(huán)執(zhí)行:

(1)先給控制循環(huán)次數(shù)的變量賦初值。

(2)判定控制循環(huán)表達式的值,如為假,則跳出循環(huán)語句,如為真,則執(zhí)行指定的循環(huán)語句后,轉到第三步。

(3)執(zhí)行一條賦值語句來修正控制循環(huán)變量次數(shù)的變量的值,然后返回第二步。下面對各種循環(huán)語句進行詳細介紹。

1.?repeat語句

repeat語句的格式如下:

repeat(表達式)語句;或?repeat(表達式)begin多條語句end

【例3-24】使用repeat循環(huán)語句及加法和移位操作來實現(xiàn)一個參數(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)本例所采用的通過加法和移位操作實現(xiàn)乘法的算法在前面的例子中已經(jīng)作過介紹,在此不再贅述。

(2)在repeat語句中,其表達式通常為常量表達式。如例3-24的repeat(size)中表達式size的值為常值4。

2.?for語句

for語句的一般形式為:

for(表達式1;表達式2;表達式3)語句;它的執(zhí)行過程如下:

(1)求解表達式1。

(2)求解表達式2,若其值為真(非0),則執(zhí)行for語句中指定的內(nèi)嵌語句,然后執(zhí)行下面的第(3)步。若為假(0),則結束循環(huán),轉到第(5)步。(3)若表達式為真,在執(zhí)行指定的語句后,求解表達式3。(4)轉回上面的第(2)步繼續(xù)執(zhí)行。(5)執(zhí)行for語句下面的語句。

【例3-25】使用for循環(huán)語句實現(xiàn)一個參數(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來實現(xiàn)乘法功能,二者的原理相同,實現(xiàn)形式上有所區(qū)別。

(2)本例中for(i=0;i<size;i=i+1)是for語句最簡單的應用形式,其中的i僅用作循環(huán)計數(shù),不再作其他用途。

(3)若在順序塊中定義變量,則需要給順序塊命名,如本例中的順序塊命名為mult。

【例3-26】使用for循環(huán)語句實現(xiàn)一個參數(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等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論