《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第4章_第1頁
《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第4章_第2頁
《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第4章_第3頁
《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第4章_第4頁
《Xilinx FPGA設(shè)計(jì)與實(shí)踐教程》課件-第4章_第5頁
已閱讀5頁,還剩104頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第四章組合邏輯設(shè)計(jì)4.1基本操作符4.2組合邏輯描述4.3條件控制語句4.4.條件控制語句的布線結(jié)構(gòu)4.5always語句的編程指導(dǎo)4.6工程實(shí)踐本章小結(jié) 4.1基?本?操?作?符

Verilog語言包括兩種操作符。一種是在第三章簡(jiǎn)單講述過的位操作,另外還有用于算術(shù)、移位、關(guān)系等的運(yùn)算操作,這些運(yùn)算符與描述Verilog基本數(shù)字模塊緊密相關(guān),比如加法器、比較器等。本節(jié)討論VerilogHDL語言的運(yùn)算符操作,同時(shí)覆蓋所有的RTL級(jí)描述。表4-1列舉了所有的操作符,同時(shí)表4-2列舉了這些操作的優(yōu)先級(jí)。4.1.1算術(shù)操作符

算術(shù)操作符包括六種:加法(?+?)、減法(?-?)、乘法(?*?)、除法(?/?)、取模(?%?)和求冪運(yùn)算(?**?)。其中,加法(?+?)和減法(?-?)操作符可以被用作一元操作符。例如,“-a”在綜合時(shí),“+”與“-”操作符可以代表加法與減法而被FPGA的邏輯單元所綜合。

乘法運(yùn)算符(?*?)相對(duì)來說比較復(fù)雜,其綜合時(shí)需要依賴于所用的軟件綜合工具以及所選配的目標(biāo)硬件。Xilinx公司的Spartan-3FPGA系列內(nèi)部含有預(yù)制的乘法器模塊,XilinxXST軟件可以提供將“*”號(hào)乘法操作適配綜合到FPGA的乘法器模塊當(dāng)中,在以上兩個(gè)條件滿足的情況下,可以在HDL設(shè)計(jì)中使用“?*?”符號(hào)。針對(duì)S3板來說,XC3S200這款FPGA含有20個(gè)18?×?18的乘法器資源,所以盡管硬件支持乘法器綜合,我們還需要考慮資源包含的數(shù)目。

除法(?/?)、取模(?%?)和求冪運(yùn)算(?**?)操作符通常不可以直接被綜合。

4.1.2移位操作符

移位操作符有四種:邏輯右移(?>>?),邏輯左移(?<<?),算術(shù)右移(?>>>?)和算術(shù)左移(?<<<?)。

在邏輯移位運(yùn)算中,無論是左移還是右移都是用“0”來填補(bǔ)移出的空位。而在算術(shù)移位運(yùn)算時(shí),右移“>>>”操作是用符號(hào)位來填補(bǔ)移出的空位;左移“<<<”操作是用“0”來填補(bǔ)移位的空位。對(duì)于邏輯左移(?<<?)和算術(shù)左移(?<<<?)是沒有區(qū)別的,具體可參考表4-3中的例子。4.1.3關(guān)系運(yùn)算符與相等運(yùn)算符

關(guān)系運(yùn)算符有四種:大于(?>?)、小于(?<?)、大于等于(?>=?)和小于等于(?<=?)。

關(guān)系運(yùn)算符通過比較操作,然后返回布爾值結(jié)果,如果值為正確,則返回“1”,否則返回“0”。

相等運(yùn)算符也有四種:等于(?==?)、不等于(?!=?)、條件相等(?===?)和條件不相等(?!==?)。

等于運(yùn)算符(?==?)和不等于運(yùn)算符(?!=?)與關(guān)系運(yùn)算符相似,也是返回false和ture的布爾值。需要注意的是,針對(duì)X和Z的嚴(yán)格按位比較,是不能被綜合的。例如:

if(a==1‘bx)

$display(aisx);//當(dāng)a等于x時(shí),這個(gè)語句不執(zhí)行

if(a===1’bx)

$display(aisx); //當(dāng)a等于x時(shí),這個(gè)語句執(zhí)行4.1.4位操作、復(fù)制和邏輯操作運(yùn)算符

位操作、復(fù)制和邏輯操作運(yùn)算在許多情況下頗為相似,都針對(duì)與、或、異或和非操作。下面分別討論這三種運(yùn)算符的用法。

1.位運(yùn)算操作

有四種基本的位操作運(yùn)算:與(&)、或(?|?)、異或(?^?)和非(?~?)。

前三種操作都需要兩個(gè)操作對(duì)象,另外,異或與非操作,可以組合在一起構(gòu)成“異或非”,如“~^”或“^~”。

這些操作都是針對(duì)位來操作的。所以稱為位操作符。下面舉例來說明位操作符的用法。例:a,b,c為我們定義的三個(gè)位寬為4的信號(hào):

wire[3:0]a,b,c;

執(zhí)行如下語句:

assignc=a|b;

相當(dāng)于:

assignc[3]=a[3]|b[3];

assignc[2]=a[2]|b[2];

assignc[1]=a[1]|b[1];

assignc[0]=a[0]|b[0];

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

縮減運(yùn)算符包括與、或、非運(yùn)算。

與位運(yùn)算操作符不同的是,縮減運(yùn)算符是單操作數(shù)運(yùn)算符,并且最后的結(jié)果是1位的二進(jìn)制數(shù)。單個(gè)操作數(shù)一般是同一個(gè)數(shù)據(jù)類型。縮減運(yùn)算的具體運(yùn)算過程是:第一步先將操作數(shù)的第1位與第2位進(jìn)行與、或、非運(yùn)算。第二步將運(yùn)算結(jié)果與第3位進(jìn)行與、或、非運(yùn)算,依次類推,直至最后1位。比如說輸入a為4bit信號(hào),那么對(duì)于輸出y卻是1bit信號(hào):

wire[3:0]a;

wirey;用語句描述為

assigny=|a;等同于:

assigny=a[3]|a[2]|a[1]|a[0];

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

邏輯運(yùn)算符包含三種:邏輯與(&&)、邏輯或(?||?)、邏輯非(?!?)。

邏輯運(yùn)算操作與位操作不一樣,如果假設(shè)x與z不用,當(dāng)所有位都為0時(shí),則操作為false。當(dāng)至少有一位為1時(shí),則操作為ture。運(yùn)算結(jié)果通常為1bit。邏輯運(yùn)算符一般用在布爾表達(dá)式中的邏輯關(guān)系,如下面的例子:

(state==start)||(state==operator)&&(cnt>100)如表4-4所示,將邏輯運(yùn)算符和位操作運(yùn)算符的例子放在一起對(duì)比,我們可以很好比較這兩種運(yùn)算符的不同之處。

由于Verilog用“0”和“1”分別代表false和ture,所以在很多情況下,位操作和邏輯操作可以互相替換。然而,當(dāng)針對(duì)布爾表達(dá)式時(shí)用邏輯操作,而當(dāng)針對(duì)信號(hào)操作時(shí)用位操作。4.1.5連接與復(fù)制運(yùn)算符

連接運(yùn)算符?{}?能夠?qū)⒃鼗蛘咝〉臄?shù)組連接成一個(gè)大的數(shù)組。下面的例子表達(dá)了連接的含義:

wirea1;

wire[3:0]a4

wire[7:0]b8,c8,d8;

assignb8={a4,a4};

assignc8={a1,a1,a4,2'b00};

assignd8={b8[3:0],c8[3:0]};

連接運(yùn)算符同時(shí)也可以對(duì)input和output類型進(jìn)行連接操作,只需要“配線”就可以了。連接操作另外一種使用是可以對(duì)一個(gè)信號(hào)經(jīng)過移位和旋轉(zhuǎn)后再操作,如下例:

wire[7:0]a;

wire[7:0]rot,shl,sha;

assignrot={a[2:0],a[8:3]};//信號(hào)a左移3bit

assignsh1={3'b00,a[8:3]}; //信號(hào)a右移3bit并給高位插入0

assignsha={a[8],a[8],a[8],a[8:3]}; //信號(hào)a右移3bit并給高位插入a[8]

連接運(yùn)算符N{},表示復(fù)制括號(hào)里面的部分。N表示要復(fù)制的次數(shù),如{4{2'b01}}和8'01010101是一樣的。4.1.6條件運(yùn)算符

條件運(yùn)算符“?:”需要三個(gè)操作數(shù),一般的形式為

[信號(hào)]=[布爾表達(dá)式]?[操作數(shù)1]:[操作數(shù)2];

布爾表達(dá)式返回值為真(1‘b1)或者假為(1’b0)。如果返回值為“1”,[信號(hào)]返回[操作數(shù)1],否則返回[操作數(shù)2]。

也可以簡(jiǎn)單理解為

if[布爾表達(dá)式]then

[信號(hào)]=[操作數(shù)1];

else

[信號(hào)]=[操作數(shù)2];雖然描述方式簡(jiǎn)單,條件表達(dá)式還可以用來級(jí)聯(lián)操作,非常方便,比如下面的表達(dá)式:

assigneq=(~i1&~i0)?1‘b1:

(~i1&i0)?1’b1:

(i1&~i0)?z‘b1:

1’b1;

通過i1和i0的輸入進(jìn)行選擇eq信號(hào)的輸出,描述為一個(gè)兩輸入的數(shù)據(jù)選擇器。

下面電路表達(dá)式求a,b,c三個(gè)數(shù)中最大值:

assignmax=(a>b)?((a>c)?a:c);

(b>c)?((b>c)?b:c);

在綜合時(shí),條件運(yùn)算符映射為一個(gè)2選1電路。4.1.7位寬調(diào)整操作

在實(shí)際的硬件環(huán)境中,在VerilogHDL描述中的網(wǎng)線(net)和變量(variables),通常包含數(shù)值的位寬。在位寬不同時(shí),一定要注意根據(jù)如下規(guī)則進(jìn)行位寬的調(diào)整和變化:

(1)最長(zhǎng)的比特位由操作數(shù)來確定,包括左邊的操作數(shù)和右邊操作數(shù)。

(2)擴(kuò)展右邊的操作數(shù)位數(shù)為比特位數(shù)最大值,然后再進(jìn)行操作。

(3)在信號(hào)比特位數(shù)少的情況下,高位將被截掉,然后再賦值給左邊信號(hào)。下面考慮一個(gè)簡(jiǎn)單的例子:

wire[7:0]a,b;

assigna=8‘b00000000;

assignb=0;

語句1中,賦值a為一個(gè)8bit的值“00000000”,語句2中定義整數(shù)0給b,在Verilog語句中“integer”類型位寬為32bit,所以b的值相當(dāng)于“00…0000”(32個(gè))。由于定義b為8bit寬,那么高位被裁減最后為“00000000”,所以雖然兩條語句都是表示全0操作,依然要考慮到底給它賦了何值。下面再考慮另外一個(gè)例子:

wire[7:0]a,b;

wire[7:0]sum8;

wire[8:0]sum9;

assignsum8=a+b;

assignsum9=a+b;在第一條賦值語句中所有操作數(shù)位寬都是8,進(jìn)行加法運(yùn)算操作之后,進(jìn)位就被忽略掉了。第二條賦值語句中,a,b擴(kuò)展至9bit和sum9的比特位數(shù)一致。進(jìn)行加法運(yùn)算后,sum9[9]得到了進(jìn)位值。也可以用如下的形式進(jìn)行表示:

assign{c_out,sum8}=a+b;

雖然基本轉(zhuǎn)換規(guī)律非常簡(jiǎn)單和直觀,但是小的錯(cuò)誤還是難免的。比如定義a,b,sum1,和sum2為8bit的信號(hào),下面兩條語句將產(chǎn)生不同的結(jié)果:

assignsuml=(a+b)>>1; //sum1的最高位填0移位

assignsum2=(0+a+b)>>1;//將a+b之和的進(jìn)位結(jié)果移位到sum2最高位在第一條語句中,所有操作數(shù)為8bit位寬,并且進(jìn)行了一次加法運(yùn)算,那么進(jìn)位被丟棄掉。當(dāng)移位操作執(zhí)行后,0被移至最高位。在第二條語句中,0是integer類型,為32bit的位寬,所以a與b被擴(kuò)展至32位寬。然后將加法運(yùn)算的結(jié)果進(jìn)行移位。最后結(jié)果被高位裁掉至8bit后,sum2[7]得到進(jìn)位值。所以可以得出結(jié)論,如果考慮到信號(hào)類型就比較復(fù)雜了。

一種安全又笨拙的轉(zhuǎn)換方法,就是用人工的方式進(jìn)行轉(zhuǎn)換,如下面的例子所示:

wire[8:0]sum_ext; //將sum擴(kuò)展至9bit

assignsum_ext={1'b0,a}+{1'b0,b};

assignsum=sum_ext[9:1];4.1.8關(guān)于Z和X的綜合

除了0和1之外,線網(wǎng)和變量類型可以包含Z和X,雖然它們不是操作數(shù),但在綜合方面有著廣泛應(yīng)用。圖4-1三態(tài)緩沖器的符號(hào)標(biāo)志和功能表

1.關(guān)于Z的綜合

Z值表示高阻或者開漏極電路,不同于普通的邏輯值,只可被綜合為三態(tài)緩沖器。如圖4-1所示反映了其原件符號(hào)和功能表,緩沖器的操作由使能端控制,如果oe端為1,則輸出為輸入,否則輸出為高阻狀態(tài)。用語言表示如下:

assigny=(oe)?a_in:1'bz;

三態(tài)緩沖器最常用在雙端口,可以提高I/O口的利用率。如圖4-2所示,dir信號(hào)控制信號(hào)傳輸方向,當(dāng)dir為0時(shí),三態(tài)緩沖器為高阻狀態(tài)。sig_out被阻塞掉,管腳用作輸入,輸入信號(hào)到達(dá)sig_in。當(dāng)dir為1時(shí),管腳用作輸出端口,sig_out輸出到外部電路。圖4-2單緩沖器構(gòu)成的雙向IO口用HDL語言描述如下:

modulebi_demo(

inoutwirebi;

assignsig_out=output_expression;

assignsome_signal=expression_with_sig_in;

assignbi=(dir)?sig_out:q'bz;

assignsig_in=bi;

注意,bi端口一定要聲明為inout模式,以方便雙向傳輸操作。

對(duì)于XilinxSpartan-3器件來說,I/O模塊中包含三態(tài)緩沖器,所以,三態(tài)緩沖器可以被應(yīng)用在FPGA管腳上。

2.關(guān)于X的綜合

在一些組合邏輯電路中,有一些輸入模塊永遠(yuǎn)不會(huì)發(fā)生,即與輸出沒有任何關(guān)系。我們經(jīng)常認(rèn)為此輸出“無須關(guān)注”,在綜合時(shí),無須關(guān)注值要么賦值為1要么賦值為0。根據(jù)優(yōu)化情況而定??紤]4-5表的真值表,該值不會(huì)為11,所示output為不關(guān)注,綜合時(shí)我們用X表示不關(guān)注的值。如下面代碼所示:

assigny=(i==2‘b00)?1’b0:

(i==2‘b01)?1’b1:

(i==2‘b10)?1’b1:

1'bx;//i==1'b11;雖然這種方法簡(jiǎn)化了電路,卻給仿真和綜合之間制造了矛盾。在仿真時(shí),x只能被認(rèn)為是0或者1,若輸入為11,輸出為x,不會(huì)被認(rèn)為是綜合的結(jié)果。而是有可能被認(rèn)為是0也有可能被認(rèn)為是1,然而,因?yàn)?1不會(huì)發(fā)生,所以x將在TestBench時(shí)被認(rèn)為是錯(cuò)誤的。 4.2組合邏輯描述

4.2.1使用always模塊描述組合邏輯

為了促使模塊化,Verilog通常將大量的順序執(zhí)行的過程語句封裝在always模塊和initial模塊當(dāng)中。initial語句用在仿真文件中,只是在開始時(shí)執(zhí)行一次,而always模塊可以被綜合,由于過程語句比較抽象,所以通常也稱為行為描述。

always模塊可以被認(rèn)為是黑盒子。其行為是由封裝在它里面的過程語句組成的。過程語句構(gòu)造形式多樣,所以不規(guī)范的語句描述往往會(huì)導(dǎo)致沒有對(duì)應(yīng)的硬件模型與之對(duì)應(yīng),或者可導(dǎo)致不必要的邏輯被執(zhí)行,從而無法被綜合工具所綜合。在always模塊中使用的行為描述語句一般包括如下三類:過程賦值語句、if語句和case語句。帶有敏感量列表的always模塊的基本結(jié)構(gòu)如下:

always(【敏感量列表】)

begin[塊內(nèi)變量聲明

[順序執(zhí)行語句];

[順序執(zhí)行語句];

end

敏感量列表中列舉了always語句在執(zhí)行過程中相對(duì)比較“敏感”的信號(hào)。這些“敏感信號(hào)”可以決定always語句的掛起和激活。always語句內(nèi)部順序執(zhí)行語句一旦開始執(zhí)行,就不受其他任何因素所控制,直到執(zhí)行完所有語句,當(dāng)有新的敏感量信號(hào)改變時(shí),always語句才重新被激活。所以always模塊是在敏態(tài)量列表控制下永遠(yuǎn)循環(huán)執(zhí)行的。

對(duì)于組合邏輯電路來說,所有的輸入信號(hào)都要放在敏感量列表中。主體部分由多條過程語句組成。如果只有一條過程語句,則begin和end可以被省略掉。4.2.2使用賦值語句描述組合邏輯

賦值語句只能被用在always模塊或initial模塊當(dāng)中。有兩種類型的賦值,一種是阻塞賦值,另外一種是非阻塞賦值。其語法格式為

[變量名]=[表達(dá)式]; //阻塞賦值語句

[變量名]<=[表達(dá)式]; //非阻塞賦值語句

根據(jù)阻塞賦值的概念,在執(zhí)行下條語句之前。表達(dá)式先被估計(jì),然后立即賦值給變量,其行為與C語言中變量的賦值是一樣的。在非阻塞賦值中,表達(dá)式的估計(jì)值在所有語句執(zhí)行完之后才進(jìn)行賦值操作(即本次賦值并未阻止其它語句的執(zhí)行)。對(duì)于初學(xué)者來說,阻塞賦值與非阻塞賦值兩者非常容易搞混。其一般原則是:

(1)在時(shí)序邏輯中用非阻塞賦值;

(2)在組合邏輯中用阻塞賦值。

兩者之間的區(qū)別在第七章將詳細(xì)講解。4.2.3舉例說明

【程序4-1】采用always塊語句描述第三章講過的1位比較器電路。

moduleeq1_always

(

inputwirei0,i1,

outputregeq //eq定義為reg型

);

regp0,p1; //p0和p1聲明為reg型

always@(i0,i1) //i0和i1必須要在敏感量列表當(dāng)中

begin

//下面語句的順序是非常關(guān)鍵的

p0=~i0&~i1;

p1=i0&i1;

eq=p0|p1;

end

endmodule

由于eq、p0和p1在always模塊里面賦值,所以聲明為reg數(shù)據(jù)類型。敏感量列表中有i0和i1,用逗號(hào)隔開,當(dāng)它們之間有一個(gè)改變后,always模塊被激活,三條阻塞語句順序執(zhí)行。這和C語言當(dāng)中是一樣的。此時(shí)語句的順序非常重要,p0和p1在使用之前必須要先賦值,否則就會(huì)出錯(cuò)。

在verilog-1995版本中,敏感量列表中用關(guān)鍵字or來替代逗號(hào)。比如說:

always@(a,b,c)

被寫為

always@(aorborc);組合邏輯電路要將所有的輸入信號(hào)都包含在敏感量列表當(dāng)中,缺少一個(gè)信號(hào)都會(huì)在綜合和仿真中造成差別,而在Verilog-2001中,可以使用下面的表達(dá)式來表示覆蓋所有的敏感量:

always@*

本書都采用這種表達(dá)方式。如此一來,既方便還可以避免敏感量列舉不全。

前面舉的例子都是持續(xù)賦值語句。然而持續(xù)賦值語句和過程語句是有區(qū)別的,如程序4-2,程序執(zhí)行的功能是完成輸入信號(hào)a、b、c相與。

【程序4-2】三輸入與門電路。

moduleand_block_assign

(

inputwirea,b,c,

outputregy

);

always@*

begin

y=a;

y=y&b;

y=y&c;

end

endmodule

程序4-2所對(duì)應(yīng)的電路如圖4-3(a)所示,用同樣的方式將always塊用賦值語句死板代替,就成了程序4-3。

【程序4-3】對(duì)程序4-2進(jìn)行always塊替換之后的程序。

moduleand_cont_assign

(

inputwirea,b,c,

outputwirey

);

assigny=a;

assigny=y&b;

assigny=y&c;

endmodule圖4-3不同編碼方式所綜合得到的電路圖 4.3條件控制語句

4.3.1if-else語句

1.語法格式

if-else語句的語法格式如下:

if[布爾表達(dá)式]

begin

[過程語句];

[過程語句];

end

else

begin

[過程語句];

[過程語句];

end

布爾表達(dá)式首先被執(zhí)行,當(dāng)它為真時(shí),執(zhí)行順序分支,否則執(zhí)行else分支。else分支是可選的,不需要時(shí)可以略去,如果有多個(gè)條件,則可以使用if語句級(jí)聯(lián),并能確定條件的優(yōu)先級(jí)。比如有下面的例子:

if[布爾表達(dá)式1]

elseif[布爾表達(dá)式2]

elseif[布爾表達(dá)式3]

else

在綜合時(shí),布爾表達(dá)式1優(yōu)先級(jí)最高,布爾表達(dá)式2次之,依次論推。

2.舉例

【程序4-4】?jī)?yōu)先級(jí)譯碼器。優(yōu)先級(jí)譯碼器有四個(gè)條件信號(hào),分別是r信號(hào)的四個(gè)比特位:r[4]、r[3]、r[2]和r[1],其中r[4]的優(yōu)先級(jí)最高,輸出為高優(yōu)先級(jí)條件下的二進(jìn)制碼,其真值表如表4-6所示。對(duì)應(yīng)的HDL代碼如下所示:

moduleprio_encoder_if

(

inputwire[4:1]r,

outputreg[2:0]y

);

always@*

if(r[4]==1'b1)//也可以是(r[4])

y=3'b100;

else

if(r[3]==1'b1)//也可以是(r[3])

y=3'b011;

elseif(r[2]==1'b1)//也可以是(r[2])

y=3'b010;

elseif(r[1]==1'b1)//也可以是(r[1])

y=3'b001;

else

y=3'b000;

endmodule

代碼首先檢查r[4]條件是否滿足。如果滿足,則y賦值為“3'b100”;如果r[4]條件不滿足,則繼續(xù)檢查r[3]信號(hào);如果r[3]信號(hào)滿足,則y賦值為“3'b011”,否則繼續(xù)檢查下一位信號(hào),依次類推,直到所有的條件都檢查一遍。注意的是,當(dāng)r[4]為1時(shí),布爾表達(dá)式(r[4]==1'b1)為真,所以可以直接將布爾表達(dá)式寫為(r[4])。

【程序4-5】二進(jìn)制解碼器。一個(gè)n-2n二進(jìn)制解碼器,根據(jù)輸入n值將對(duì)應(yīng)的2n輸出位置1,如果n為2,則其真值表如表4-7所示。電路同時(shí)需要一個(gè)使能信號(hào)en,代碼如下所示:

moduledecoder_2_4_if

(

inputwire[1:0]a,

inputwireen,

outputreg[3:0]y

);

always@*

if(en==1'b0) //也可以為(~en)

y=4'b0000;

elseif(a==2'b00)

y=4'b0001;

elseif(a==2'b01)

y=4'b0010;

elseif(a==2'b10)

y=4'b0100;

else

y=4'b1000;

endmodule4.3.2case語句

1.語法格式

case語句的語法格式如下:

case[控制表達(dá)式]

[分支表達(dá)式值1]:

begin

[過程語句];

end

[分支表達(dá)式值2]:

begin

[過程語句];

end

default:

begin

[過程語句];

end

endcase

case語句是多分支選擇語句。前面講的if語句只有兩個(gè)分支可供選擇,case語句根據(jù)控制表達(dá)式的值來選擇分支,如果控制表達(dá)式的值與某個(gè)分支表達(dá)式值相等,則選擇執(zhí)行該分支的語句;如果控制表達(dá)式的值和所有分支表達(dá)式值都不相等,則選擇default分支語句執(zhí)行。如果某個(gè)分支執(zhí)行語句僅由一條語句組成,則begin和end可以省略。default項(xiàng)可以省略,但是容易產(chǎn)生鎖存器,所以建議讀者盡量保持default語句的存在。

case語句的各個(gè)分支是獨(dú)立且互不相同的,不然就會(huì)失去多路選擇的意義。

2.舉例

我們同樣用case語句實(shí)現(xiàn)優(yōu)先級(jí)編碼和譯碼電路來舉例,2-4譯碼器真值表如表4-7所示,HDL代碼如程序4-6所示。

【程序4-6】使用case語句實(shí)現(xiàn)2-to-4譯碼器。

moduledecoder_2_4_case

(

inputwire[1:0]a,

inputwireen,

outputreg[3:0]y

);

always@*

case({en,a})

3'b000,3'b001,3'b010,3'b011:y=4'b0000;

3'b100:y=4'b0001;

3'b101:y=4'b0010;

3'b110:y=4'b0100;

3'b111:y=4'b1000; //也可以作為default項(xiàng)

endcase

endmodule

在case語句中,如果多個(gè)條件表達(dá)式對(duì)應(yīng)同一條執(zhí)行語句,我們可以將多個(gè)分支值列舉在一起,比如程序4-6。需要注意一點(diǎn),如果控制表達(dá)式為{en,a},即所有的狀態(tài)都列舉到了,那么default語句可以省略。

【程序4-7】使用case語句描述2-4譯碼器。

moduleprio_encoder_case

(

inputwire[4:1]r,

outputreg[2:0]y

);

always@*

case(r)

4'b1000,4'b1001,4'b1010,4'b1011,

4'b1100,4'b1101,4'b1110,4'b1111:y=3'b100;

4'b0100,4'b0101,4'b0110,4'b0111:y=3'b011;

4'b0010,4'b0011:y=3'b010;

4'b0001:y=3'b001;

4'b0000:y=3'b000; //也可以作為default項(xiàng)

endcase

endmodule4.3.3casez和casex語句

在casez語句中,分支表達(dá)式值中包含有z和?,都不用理睬(don'tcare);在casex語句中,分支表達(dá)式值中包含有z、x和?,也都不理睬(don'tcare)。

比如將優(yōu)先級(jí)編碼器電路用casez語句描述,如程序4-8所示。

【程序4-8】使用casez語句描述優(yōu)先級(jí)編碼器電路。

moduleprio_encoder_casez

(

inputwire[4:1]r,

outputreg[2:0]y

);

always@*

casez(r)

4'b1???:y=3'b100;

4'b01??:y=3'b011;

4'b001?:y=3'b010;

4'b0001:y=3'b001;

4'b0000:y=3'b000; //default同樣可以被省略

endcase

endmodule

4.3.4“fullcase”和“parallelcase”語句

在Verilog中,分支表達(dá)式不必覆蓋所有控制表達(dá)式的值,而且某些分支表達(dá)式值可以匹配多次,比如下面的例子:

reg[2:0]:s

casez(s)

3‘b111: y=l’bl;

3‘bl??: y=l’b0;

3'b000: y=l'bl;

endcase

在上例中,3'b111匹配了兩次,但是當(dāng)s為3'b111時(shí),由于第一條語句優(yōu)先級(jí)高,所以y的值為1'b1;當(dāng)s為3'b001、3'b010或者3'b011時(shí),y的值只能保持原來的值,這樣y就不會(huì)得到一個(gè)確定的值。如此一來,就容易綜合成鎖存器。在數(shù)字電路中對(duì)鎖存器一定要慎用。

當(dāng)控制表達(dá)式的所有可能值都被分支表達(dá)式所覆蓋時(shí),此表達(dá)式稱為“fullcase”表達(dá)式。在組合邏輯電路中,必須用“fullcase”語句,因?yàn)槊總€(gè)輸入都對(duì)應(yīng)一個(gè)輸出值。如果不能完全覆蓋所有列舉項(xiàng)的情況下,需要增加default項(xiàng)來確定沒有覆蓋值的狀態(tài),比如前面舉例可以修改為

casez(s)

3‘b111:y=l’bl;

3‘b1??:y=l’b0;

default:y=l‘bl; //當(dāng)s不為以上兩種情況時(shí)y賦值為1

endcase

或者

casez(s)

3’blll:y=l‘bl;

3’bl??:y=l‘b0;

3'b000:y=l'bl;

default:y=l'bx; //y值為不確定

endcase

當(dāng)所有分支項(xiàng)值是互相不相同時(shí),稱為“parallelcase”語句。比如前面舉例s的值3'b111出現(xiàn)兩次,就不屬于“parallelcase”語句,而程序4-6和程序4-7都屬于“parallelcase”語句。

在綜合時(shí),“parallelcase”語句綜合成多路布線網(wǎng)絡(luò),而“non-parallelcase”語句傾向于綜合成優(yōu)先級(jí)布線網(wǎng)絡(luò)。許多綜合軟件中都有是否選擇“fullcasedirective”和“parallelcasedirective”的選項(xiàng)。如果選擇有效,所有case語句則都按照fullcase和parallelcase的原則來綜合。大家在使用綜合工具進(jìn)行綜合時(shí),要注意選擇合適的綜合選項(xiàng),這樣可有效提高設(shè)計(jì)的質(zhì)量。 4.4.條件控制語句的布線結(jié)構(gòu)

4.4.1優(yōu)先級(jí)布線網(wǎng)絡(luò)

首先舉一個(gè)2選1選擇器的例子,其真值表和框圖如4-4(a)所示。采用if-else語句實(shí)現(xiàn)優(yōu)先級(jí)布線網(wǎng)絡(luò),代碼如下:

if(m==n)

r=a+b+c;

elseif(m>n)

r=a-b;

else

r=c+1:圖4-42選1選擇器圖4-4(b)描述了2選1選擇器的基本結(jié)構(gòu)。兩個(gè)2選1選擇器實(shí)現(xiàn)布線優(yōu)先級(jí)網(wǎng)絡(luò),其它模塊實(shí)現(xiàn)布爾變量和數(shù)學(xué)表達(dá)。如果第一個(gè)布爾表達(dá)式條件滿足(如m=n),則端口1的值(a+b+c)賦給r,否則端口0的值將賦給r;端口0的值由另外一個(gè)布爾表達(dá)式?jīng)Q定,當(dāng)m>n時(shí)為a-b,否則為c+1。

需要注意的是,所有布爾表達(dá)式和數(shù)學(xué)表達(dá)式都是并行執(zhí)行的。布爾表達(dá)式的輸出決定r的賦值。隨著if-else分支增多,優(yōu)先級(jí)級(jí)聯(lián)層數(shù)越多,同時(shí)也會(huì)產(chǎn)生越長(zhǎng)時(shí)間的延時(shí)。4.4.2多路選擇布線網(wǎng)絡(luò)

多路選擇網(wǎng)絡(luò)最終實(shí)現(xiàn)為一個(gè)n到1的多路選擇器,選擇信號(hào)選擇決定n個(gè)輸入端口中的1個(gè)到輸出端口,多路選擇器的結(jié)構(gòu)和功能表如圖4-5所示。在并行case語句中,可以使case語句的每一個(gè)條件表達(dá)式對(duì)應(yīng)多路選擇器中的一個(gè)條件,將輸入和輸出端口映射起來。比如上小節(jié)講述的例子,可以表示如下:

wire[1:0]sel;

case(sel)

2'b00:r=a+b+c;

2'b10:r=a-b;

default:r=r+1;

endcase

圖4-54選1選擇器結(jié)構(gòu)圖和功能表圖4-6case語句執(zhí)行詳細(xì)邏輯電路框圖同樣需要注意的是,所有的表達(dá)式都是并行執(zhí)行的。sel變量作為選擇信號(hào)來選擇合適的輸出值。sel的位寬增加意味著多路選擇器的輸入端口增多。

通常來說,當(dāng)描述在某種情況下對(duì)輸出有偏愛時(shí)采用優(yōu)先級(jí)布線網(wǎng)絡(luò),如優(yōu)先編碼器等;當(dāng)描述基于真值表或者函數(shù)表時(shí)采用多路選擇布線網(wǎng)絡(luò),如二進(jìn)制解碼器等。 4.5always語句的編程指導(dǎo)

編寫可綜合的Verilog代碼,必須考慮到代碼在硬件結(jié)構(gòu)上具體綜合成怎樣的電路而不能像編寫C語言代碼一樣僅僅考慮數(shù)學(xué)上的邏輯。在使用always語句時(shí),尤其要考慮這一點(diǎn),因?yàn)樵赼lways模塊中變量和過程語句可以同時(shí)存在。下面分析在組合邏輯電路設(shè)計(jì)中,幾條大家非常容易犯錯(cuò)誤的地方:

(1)在多個(gè)always模塊中對(duì)同一變量賦值;

(2)不完全列舉敏感量列表;

(3)分支列舉不完全和輸出賦值不完全。

1.在多個(gè)always模塊中對(duì)同一變量賦值

在Verilog中,變量可以在多個(gè)always模塊中賦值,也可以理解為可以同時(shí)出現(xiàn)在多個(gè)always模塊中的賦值語句左邊。如下面的例子,變量y同時(shí)被兩個(gè)always語句共享:

regy;

rega,b,clear;

always@*

if(clear)y=l'b0;

always@*

y=a&b;此電路雖然語法沒有問題,并且可以仿真,但是無法綜合的。因?yàn)槊總€(gè)always模塊是一個(gè)電路,如果y同時(shí)被兩個(gè)電路所賦值,那么y的值可以被兩塊電路同時(shí)修改,從物理角度上理解是沒有實(shí)際電路能夠?qū)崿F(xiàn)這一功能的。解決這個(gè)問題的辦法是將所有的情況放在一個(gè)always模塊中。比如上面舉例,可以修改為

always@*

if(clear)

y=l‘b0;

else

y=a&b;

2.不完全列舉敏感量列表

對(duì)于組合邏輯電路來說,輸出是輸入的函數(shù),對(duì)于輸入信號(hào)的任何改變都會(huì)引起輸出值的改變,所以我們要將所有本模塊用到的輸入都寫在敏感量列表當(dāng)中。比如兩輸入的與電路可以寫為

always@(a,b) //a和b都在敏感量列表中

y=a&b;

如果忘記了將b寫入敏感量列表當(dāng)中,代碼變成了:

always@(a) //敏感量列表中少寫了b變量

y=a&b;雖然后者可以順利通過語法檢查,但是執(zhí)行起來就費(fèi)勁了。當(dāng)a改變時(shí),always模塊被激活,y等于a&b的值;當(dāng)b改變時(shí),always模塊依然保持原來的值,因?yàn)樗鼘?duì)b并不敏感,顯然不符合我們的設(shè)計(jì)意圖。此時(shí)許多綜合軟件都會(huì)提出告警,但是不會(huì)報(bào)錯(cuò),所以大家需要切記這一點(diǎn)。

在Verilog-2001中,用到一個(gè)特殊的符號(hào)@*,表示所有的本always塊中的輸入都列舉在敏感量列表當(dāng)中,建議大家盡量使用@*?描述。

3.分支列舉不完全和輸出賦值不完全

組合邏輯電路的輸出僅僅是輸入的函數(shù),所以組合邏輯電路不包含任何內(nèi)部狀態(tài)(比如memory)。然而根據(jù)Verilog標(biāo)準(zhǔn)規(guī)定,變量在always語句中如果沒有賦值,則會(huì)保持原來的值不變,這時(shí)它就會(huì)綜合成一個(gè)內(nèi)部狀態(tài)(通過閉環(huán)反饋)或者一個(gè)寄存狀態(tài)(比如鎖存器),這在組合邏輯電路中是不允許的。

為了避免在always模塊中不確定寄存器的出現(xiàn),所有輸出信號(hào)在任何時(shí)候都要有確定的賦值。if或者case語句條件分支列舉不完全或者輸出賦值不完全是兩種常見的導(dǎo)致不確定寄存器出現(xiàn)的情況,所以在開發(fā)組合邏輯電路時(shí)應(yīng)把握以下兩點(diǎn):

(1)在if和case語句中列舉所有的分支;

(2)在每個(gè)分支條件下對(duì)每一個(gè)輸出信號(hào)都要賦值。

如下面的代碼:

always@*

if(a>b) //此分支中沒有給eq賦值

gt=l‘bl;

elseif(a==b) //此分支中沒有給gt賦值

eq=l’bl;

//else分支也被省略掉了這段電路的目的是描述一個(gè)這樣的功能:當(dāng)a大于b時(shí),gt輸出為1;當(dāng)a等于b時(shí),eq輸出為1。這種電路我們平時(shí)用的非常多,如果簡(jiǎn)單的翻譯過來就是上面這段代碼,但是用剛才的兩條原則來分析,發(fā)現(xiàn)兩條原則全部被破壞了。

首先是不完全分支電路,電路中沒有考慮當(dāng)a小于b時(shí),gt和eq到底輸出什么,那么根據(jù)Verilog語法規(guī)定,只能是保持原來的值,這樣顯然形成鎖存器。

其次我們考慮不完全輸出錯(cuò)誤,比如說,當(dāng)a大于b時(shí),eq沒有賦值,所以eq也會(huì)保持原來的值不變,同樣也會(huì)形成一個(gè)鎖存器。所以為了解決上面的錯(cuò)誤,代碼就需要改動(dòng)。首先加上沒考慮到的分支,并給輸出賦值,代碼修改為

always@*

if(a>b)

begin

gt=l‘bl;

eq=1’b0;

end

elseif(a==b)

begin

gt=l‘b0;

eq=l’bl;

end

else //a<b

begin

gt=l‘b0;

eq=l'b0;

end

另外一種修改錯(cuò)誤的方法是在always模塊的開始將所有信號(hào)賦默認(rèn)值,以防發(fā)生不完全賦值,代碼相對(duì)簡(jiǎn)潔,比如:

always@*

begin

gt=l‘b0; //為gt賦默認(rèn)值

eq=l’b0; //為eq賦默認(rèn)值

if(a>b)

gt=l‘bl;

elseif(a==b)

eq=l'bl;

end

case語句也很容易出現(xiàn)上述的錯(cuò)誤。在控制表達(dá)式的所有值沒有被完全覆蓋的情況下就會(huì)出現(xiàn)上述錯(cuò)誤,比如下面的例子:

reg[1:0]s

case(s)

2'b00:y=l'bl;

2'bl0:y=l'b0;

2'bll:y=l'bl;

endcase

2'b01值沒有在表達(dá)式值中覆蓋,那么在此條件下,y值保持原來的值就會(huì)形成意料不到的鎖存器。為了避免這個(gè)錯(cuò)誤,要確定y在所有情況下都有確定的值,采用的方法就是在case語句最后加default語句:

case(s)

2’b00:y=l‘bl;

2’bl0:y=l‘b0;

default:y=l'bl; //當(dāng)s為2'b0l時(shí),y為1

endcase或者增加條件表達(dá)式,并賦值為無關(guān)值:

case(s)

2‘b00:y=l’bl;

2‘bl0:y=l’b0;

2‘bll:y=l’bl;

default:y=l‘bx; //s為2’b01時(shí)y賦值為x

endcase

或者可以選擇在always塊開始給y賦一個(gè)默認(rèn)值:

y=1‘b0; //也可以賦值y=1’bx

case(s)

2‘b00:y=l’bl;

2‘bl0:y=l’b0;

2'bll:y=l'bl;

endcase 4.6工程實(shí)踐

4.6.1十六進(jìn)制數(shù)到七段數(shù)碼管譯碼器

七段數(shù)碼管結(jié)構(gòu)如圖4-7所示,它包含七個(gè)LED發(fā)光二極管。本書以共陰極七段數(shù)碼管為例,即如果LED的發(fā)光二極管控制端為低,則對(duì)應(yīng)發(fā)光二極管亮。圖4-7七段數(shù)碼管顯示及其十六進(jìn)制數(shù)值表示如果還有小數(shù)點(diǎn),那么對(duì)于七段數(shù)碼管實(shí)際成八段了。按照?qǐng)D4-7(a)所示,數(shù)碼管控制信號(hào)為a、b、c、d、e、f、g和dp,我們可以定義為一條總線,命名為sseg,輸入為4bit的十六進(jìn)制數(shù),比如輸入為“0001”,那么數(shù)碼管顯示值應(yīng)該為1;按照?qǐng)D4-7(b)所示,應(yīng)該點(diǎn)亮b和c段,因?yàn)槭枪碴帢O電路連接方式,所以給數(shù)碼管控制總線的譯碼值為:“10011111”。代碼如程序4-9所示。

【程序4-9】七段數(shù)碼管譯碼電路。

modulehex_to_sseg

(

inputwire[3:0]hex,

inputwiredp,

outputreg[7:0]sseg//輸出低有效

);

always@*

begin

case(hex)

4'h0:sseg[6:0]=7'b0000001;

4'h1:sseg[6:0]=7'b1001111;

4'h2:sseg[6:0]=7'b0010010;

4'h3:sseg[6:0]=7'b0000110;

4'h4:sseg[6:0]=7'b1001100;

4'h5:sseg[6:0]=7'b0100100;

4'h6:sseg[6:0]=7'b0100000;

4'h7:sseg[6:0]=7'b0001111;

4'h8:sseg[6:0]=7'b0000000;

4'h9:sseg[6:0]=7'b0000100;

4'ha:sseg[6:0]=7'b0001000;

4'hb:sseg[6:0]=7'b1100000;

4'hc:sseg[6:0]=7'b0110001;

4'hd:sseg[6:0]=7'b1000010;

4'he:sseg[6:0]=7'b0110000;

default:sseg[6:0]=7'b0111000;//4'hf

endcase

sseg[7]=dp;

end

endmodule

驗(yàn)證板上有4個(gè)七段數(shù)碼管,它們共用數(shù)據(jù)控制端。為了4個(gè)數(shù)碼管能夠正確顯示,需要一個(gè)時(shí)序分配模塊。時(shí)序分配模塊如圖4-8(a)所示。4個(gè)七段數(shù)碼管的控制端(sseg)對(duì)應(yīng)連接在時(shí)序分配模塊的輸入端:in0、in1、in2和in3,時(shí)序分配模塊按照一定的時(shí)間優(yōu)先級(jí)通過控制4個(gè)七段數(shù)碼管的使能信號(hào),控制4個(gè)輸入輪換有效,這就是動(dòng)態(tài)掃描的原理。只要輪換刷新的速率能夠“欺騙”人眼(大于24Hz),人們就可以看到每個(gè)數(shù)碼管的數(shù)字都不一樣。詳細(xì)內(nèi)容第五章再講,目前大家當(dāng)黑盒子使用就可以了。測(cè)試電路如下:

我們采用8bit加法電路對(duì)剛才的設(shè)計(jì)進(jìn)行驗(yàn)證,設(shè)計(jì)框架如圖4-8(b)所示。驗(yàn)證板的輸入撥碼開關(guān)sw為8bit,設(shè)計(jì)兩個(gè)數(shù)碼管分別顯示撥碼開關(guān)指示的高四位值和低四位值,另外兩個(gè)數(shù)碼管分別顯示撥碼開關(guān)指示值加1之后的高四位值和低四位值。代碼如程序4-10所示。圖4-8LED動(dòng)態(tài)掃描電路以及測(cè)試電路框圖

【程序4-10】七段數(shù)碼管測(cè)試電路。

modulehex_to_sseg_test

(

inputwireclk,

inputwire[7:0]sw,

outputwire[3:0]an,

outputwire[7:0]sseg

);

//信號(hào)聲明

wire[7:0]inc;

wire[7:0]led0,led1,led2,led3;

//增加輸入

assigninc=sw+1;

//例化四輸入十六進(jìn)制譯碼器

//例化低四位輸入

hex_to_ssegsseg_unit_0

(.hex(sw[3:0]),.dp(1'b0),.sseg(led0));

//例化高四位輸入

hex_to_ssegsseg_unit_1

(.hex(sw[7:4]),.dp(1'b0),.sseg(led1));

//例化低四位加法值

hex_to_ssegsseg_unit_2

(.hex(inc[3:0]),.dp(1'b1),.sseg(led2));

//例化高四位加法值

hex_to_ssegsseg_unit_3

(.hex(inc[7:4]),.dp(1'b1),.sseg(led3));

//例化7段數(shù)碼管多路選擇模塊

disp_muxdisp_unit

(.clk(clk),.reset(1'b0),.in0(led0),.in1(led1),

.in2(led2),.in3(led3),.an(an),.sseg(sseg));

endmodule

4.6.2帶符號(hào)加法器設(shè)計(jì)

整數(shù)可以表示成帶符號(hào)形式,最高位表示符號(hào)位。如果為1,則表示負(fù)數(shù),如果為0,則表示正數(shù),剩下位數(shù)表示數(shù)值。比如在四位帶符號(hào)數(shù)下表示:2表示為“0010”,-2表示為“1010”。

帶符號(hào)加法器需要執(zhí)行加法操作,可以根據(jù)這種特殊數(shù)據(jù)表示方法分情況討論:

(1)如果兩個(gè)操作數(shù)都是正的,直接對(duì)值進(jìn)行相加,并保持符號(hào)位;

(2)如果兩個(gè)操作數(shù)符號(hào)位不同,即一正一負(fù),那么用值相對(duì)大的操作數(shù)減去值小的操作數(shù),并保留值大的操作數(shù)的符號(hào)位為最終結(jié)果的符號(hào)位。設(shè)計(jì)過程可以分成兩個(gè)步驟:①將輸入值進(jìn)行分類,按照它們的值大小標(biāo)記為max和min信號(hào);②檢查符號(hào)位對(duì)值進(jìn)行加法或者減法操作。應(yīng)注意到,只要兩個(gè)輸入數(shù)經(jīng)過分類,最終結(jié)果的符號(hào)位就已確定為max的符號(hào)位。測(cè)試框圖如圖4-8所示。

代碼如程序4-11所示。為了描述清晰,可以讓輸入信號(hào)由內(nèi)部產(chǎn)生,并且符號(hào)位和數(shù)值信號(hào)分開,并定義參數(shù)N,表示加法器的位數(shù)。

【程序4-11】帶符號(hào)加法器。

modulesign_mag_add

#(

parameterN=4

)

(

inputwire[N-1:0]a,b,

outputreg[N-1:0]sum

);

//信號(hào)聲明

reg[N-2:0]mag_a,mag_b,mag_sum,max,min;

regsign_a,sign_b,sign_sum;

//主體部分

always@*

begin

//符號(hào)和數(shù)值位分開

mag_a=a[N-2:0];

mag_b=b[N-2:0];

sign_a=a[N-1];

sign_b=b[N-1];

//根據(jù)符號(hào)分類

if(mag_a>mag_b)

begin

max=mag_a;

min=mag_b;

sign_sum=sign_a;

end

else

begin

max=mag_b;

min=mag_a;

sign_sum=sign_b;

end

//符號(hào)位進(jìn)行加減

if(sign_a==sign_b)

mag_sum=max+min;

else

mag_sum=max-min;

//輸出邏輯

sum={sign_sum,mag_sum};

end

endmodule

測(cè)試電路如下:

我們采用4位帶符號(hào)加法器來驗(yàn)證電路操作,測(cè)試框架如圖4-9所示。兩個(gè)輸入數(shù)值由8位撥碼開關(guān)來輸入,符號(hào)位和數(shù)值位顯示在兩個(gè)七段數(shù)碼管上,兩個(gè)按鍵作為多路選擇器的輸入,從而選擇發(fā)送操作數(shù)或者結(jié)果值送數(shù)碼管顯示。第一個(gè)數(shù)碼管顯示結(jié)果值,通過將3bit值高位填0,送到十六進(jìn)制數(shù)到七段數(shù)碼管模塊,來顯示結(jié)果值。另外一個(gè)數(shù)碼管顯示符號(hào)位,如果為正,則不顯示任何值;如果為負(fù),則顯示數(shù)碼管中間一段,如圖4-7所示g段。兩個(gè)數(shù)碼管數(shù)值反饋到時(shí)序選擇模塊,也就是disp_mux。第五章將詳細(xì)講解。具體代碼如程序4-12所示。圖4-9帶符號(hào)加法器測(cè)試電路圖

【程序4-12】帶符號(hào)加法器測(cè)試電路。

modulesm_add_test

(

inputwireclk,

inputwire[1:0]btn,

inputwire[7:0]sw,

outputwire[3:0]an,

outputwire[7:0]sseg

);

//信號(hào)聲明

wire[3:0]sum,mout,oct;

wire[7:0]led3,led2,led1,led0;

//初始化加法器

sign_mag_add#(.N(4))sm_adder_unit

(.a(sw[3:0]),.b(sw[7:4]),.sum(sum));

//幅度顯示在最右端7-segLED上

assignmout=(btn==2‘b00)?sw[3:0]:

(btn==2’b01)?sw[7:4]:

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論