《基于FPGA的現(xiàn)代數(shù)字系統(tǒng)設(shè)計》課件第3章_第1頁
《基于FPGA的現(xiàn)代數(shù)字系統(tǒng)設(shè)計》課件第3章_第2頁
《基于FPGA的現(xiàn)代數(shù)字系統(tǒng)設(shè)計》課件第3章_第3頁
《基于FPGA的現(xiàn)代數(shù)字系統(tǒng)設(shè)計》課件第3章_第4頁
《基于FPGA的現(xiàn)代數(shù)字系統(tǒng)設(shè)計》課件第3章_第5頁
已閱讀5頁,還剩282頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第3章基于VerilogHDL語言的設(shè)計3.1VerilogHDL概述3.2門級建模3.3數(shù)據(jù)流建模3.4行為級建模3.5VerilogHDL的可綜合設(shè)計3.6Testbench文件與設(shè)計3.7VerilogHDL在ISE軟件中設(shè)計示例小結(jié)習(xí)題實驗項目 3.1VerilogHDL概述

硬件描述語言支持層次化的設(shè)計、IPCore可重用設(shè)計,在EDA工具、FPGA芯片支持下,實現(xiàn)了一種貫穿設(shè)計、綜合、仿真和下載等多個環(huán)節(jié)的數(shù)字系統(tǒng)快速實現(xiàn)的方法。設(shè)計者可以在較為抽象的層次上用HDL對電路進(jìn)行描述,將繁瑣的實現(xiàn)細(xì)節(jié)交由EDA工具完成,極大地降低了設(shè)計復(fù)雜度,縮短了開發(fā)周期。

使用硬件描述語言設(shè)計的數(shù)字系統(tǒng),可不依賴特定的廠商和器件,可移植性好。常用的HDL語言有VerilogHDL和VHDL兩種。

VerilogHDL由GDA公司的PhilMoorby在1983年末首創(chuàng),1989年CADENCE公司收購了GDA公司,1990年CADENCE公司公開發(fā)表了VerilogHDL,成立了OVI(OpenVerilogInternational)組織。隨后IEEE制定了VerilogHDL的IEEE標(biāo)準(zhǔn),進(jìn)一步推動了VerilogHDL的應(yīng)用。

VHDL(VHSICHardwareDescriptionLanguage)中的VHSIC是VeryHighSpeedIntegeratedCircuit的縮寫。VHDL是美國國防部為了解決項目的多個承包人的信息交換困難、設(shè)計維修困難的問題而提出的,由TI、IBM和INTERMETRICS公司完成,于1987年制定為IEEE標(biāo)準(zhǔn),即IEEEstd1076-1987[LRM87],后又進(jìn)行一些修改,成為新的標(biāo)準(zhǔn)版本。

VHDL和VerilogHDL兩種語言的主要功能差別不大,它們的描述能力類似,相比較而言,VHDL較VerilogHDL系統(tǒng)描述能力稍強(qiáng),VerilogHDL的底層描述能力比VHDL強(qiáng)得多。VerilogHDL擁有廣泛的設(shè)計群體,成熟的資源比VHDL豐富;完成同一功能描述,VerilogHDL的描述較VHDL更為簡潔;VerilogHDL也較易于學(xué)習(xí),只要有C語言的編程基礎(chǔ),一般經(jīng)過2~3個月的認(rèn)真學(xué)習(xí)和實際操作就能掌握,而VHDL設(shè)計不很直觀,一般需要有半年多的專業(yè)培訓(xùn)才能掌握。

本節(jié)通過用VerilogHDL描述幾個簡單的數(shù)字電路,總結(jié)出VerilogHDL的基本特點、設(shè)計規(guī)則,并建立層次建模的概念,實現(xiàn)VerilogHDL學(xué)習(xí)的快速入門。3.1.1幾個簡單的VerilogHDL例子

例3-1

設(shè)計一個二選一電路,實現(xiàn)表3.1的功能。

modulemux21(a,b,sel,c);

inputa,b;

inputsel;

outputc;

wirec;

assignc=sel?b:a;

endmodule從例3-1可以看出:

(1)?VerilogHDL的程序描述必須位于關(guān)鍵詞module和endmodule之間。

(2)每個模塊必須有一個模塊名,如上例的mux21。

(3)需要對模塊的輸入、輸出端口進(jìn)行說明,如上例程序的第二、三、四行表述模塊的輸入端口是a、b、sel,輸出端口是c。

(4)模塊的變量說明,如程序的第五行聲明了一個線網(wǎng)變量c。

(5)第六行語句使用條件操作符,實現(xiàn)模塊的功能,即判斷sel是否等于1,如果等于1,b的值賦給c,否則a的值賦給c。這段程序描述通過綜合工具,可轉(zhuǎn)換成圖3.1的門級電路圖。圖3.1二選一的電路圖例3-2用VerilogHDL描述一個用時鐘上升沿觸發(fā)、同步復(fù)位的D觸發(fā)器。

moduleDflop(d,reset,clk,q);

inputd,clk;

inputreset;

outputq;

regq;

always@(posedgeclk)

if(reset==1)

q<=0;

else

q<=d;

endmodule從例3-2可以看出:

(1)模塊名是Dflop,輸入端口有三個:d、clk和reset,輸出端口是q。

(2)程序的第五行聲明了一個寄存器變量q。

(3)always語句描述模塊的功能是:在每個clk上升沿時,首先檢測reset的值,當(dāng)reset=1時,輸出端口q復(fù)位為0,否則將輸入值d賦給輸出端口q。

(4)例3-2實現(xiàn)了圖3.2的數(shù)字時序電路。圖3.2D觸發(fā)器

例3-3

調(diào)用例3-2的D觸發(fā)器實現(xiàn)一個四位的移位寄存器。

寄存器存儲的數(shù)據(jù)在移位時鐘clock的作用下依次右移,這樣構(gòu)成移位寄存器。移位寄存器既可以存儲代碼,也可以用來實現(xiàn)數(shù)據(jù)的串行到并行的轉(zhuǎn)換。電路結(jié)構(gòu)如圖3.3所示。圖3.3四位的移位寄存器調(diào)用例3-2設(shè)計的D觸發(fā)器按照圖3.3的結(jié)構(gòu)連接,在每次時鐘上升沿時,數(shù)據(jù)依次向右移動一位。經(jīng)過四個周期時鐘信號后,串行輸入的四位數(shù)據(jù)全部移入到移位寄存器中。如果在四個觸發(fā)器的輸出端引出數(shù)據(jù),就可實現(xiàn)數(shù)據(jù)傳輸?shù)拇?并轉(zhuǎn)換。程序如下:

moduleshift_flop(D,reset,clock,Q);

//端口聲明

inputD,clock,reset;

output[3:0]Q;

wire[3:0]Q;//變量說明

/*調(diào)用D觸發(fā)器Dflop四次,例化名分別命名成u1、u2、u3和u4,同時連接對應(yīng)的端口,

組成四位移位寄存器*/

Dflopu1(D,reset,clock,Q[3]);

Dflopu2(Q[3],reset,clock,Q[2]);

Dflopu3(Q[2],reset,clock,Q[1]);

Dflopu4(Q[1],reset,clock,Q[0]);

endmodule從例3-3可以看到,VerilogHDL很好地支持了“自頂向下”的設(shè)計理念。

VerilogHDL支持測試激勵模塊的設(shè)計。在仿真軟件,如Modelsim(詳見第5章)的支持下,將測試模塊描述的激勵信號傳輸?shù)酱郎y的功能模塊中,在仿真軟件中可以觀察功能模塊的輸出情況,從而實現(xiàn)對功能模塊的軟件測試,及早發(fā)現(xiàn)設(shè)計中的問題。

例3-4

對例3-3設(shè)計的模塊編寫測試文件。

`timescale1ns/100ps //定義測試文件中一個時間的單位是1ns、時間精度是100ps

moduletestbench();

//說明測試輸入端口

regD;

regclock;

regreset;

wire[3:0]Q;

//例化待測試的移位寄存器

shift_flopu1(D,reset,clock,Q);

//產(chǎn)生時鐘信號

initial

begin

clock=0;

forever#10clock=~clock;

end

//產(chǎn)生輸入信號D,復(fù)位信號reset

initial

begin

D=1'b1;reset=0;

#20reset=1;

#15D=1'b0;

#20D=1'b1;

#100reset=0;

#10$stop;

end

endmodule3.1.2VerilogHDL的基礎(chǔ)知識

1.VerilogHDL的基本結(jié)構(gòu)

VerilogHDL可以描述數(shù)字系統(tǒng)的邏輯功能,描述組合成為一個系統(tǒng)的多個數(shù)字模塊之間的連接,并建立測試文件等功能。

模塊(module)是VerilogHDL設(shè)計的基本單元,VerilogHDL模塊可分為兩種類型:一種是功能模塊,描述數(shù)字電路系統(tǒng)的結(jié)構(gòu)和功能,在EDA工具的支持下轉(zhuǎn)換成電路結(jié)構(gòu),完成布局、布線、下載,最后在FPGA上實現(xiàn)目標(biāo)系統(tǒng),功能模塊也可以僅以向仿真軟件提供仿真模型為目的,從而對設(shè)計方案進(jìn)行快速驗證;另一種是測試模塊,為功能模塊的測試提供信號激勵、輸出數(shù)據(jù)監(jiān)測,完成功能模塊的仿真測試。測試模塊的設(shè)計詳見3.6節(jié)。一般而言,模塊包括模塊名、端口名說明、I/O端口聲明、各類型變量聲明和模塊功能描述等。VerilogHDL模塊的一般結(jié)構(gòu)如以下程序所示。

module模塊名(input_port1,…input_portn,

output_port1,…output_portN,模塊名及模塊端口羅列

inout_port1,…inout_portM);

input[width_1-1:0]input_port1;

input[width_n-1:0]input_portn;下面介紹模塊中的基本內(nèi)容。

1)模塊名、端口名說明

格式:

module模塊名(端口1,端口2,端口3,…,端口n);

VerilogHDL程序的模塊名是必須的,所有程序必須位于關(guān)鍵詞module、endmodule之間。

為便于工程管理,模塊名一般和實現(xiàn)的功能相關(guān),如halfadder(半加器)、top(頂層模塊)、testbench(測試模塊)等。命名的字符串必須符合VerilogHDL對字符串的規(guī)定。端口名說明是一個可選項。

(1)當(dāng)模塊與外界沒有信息交互、無端口連接時,聲明中就不需要無端口名的羅列。如包含了待測模塊和激勵信號的測試模塊,可聲明為moduletestbench();

(2)當(dāng)模塊和外界有信息交互時,各端口名必須全部羅列,相互之間用逗號隔開,如

modulemux21(a,b,sel,c);

對于外界環(huán)境來說,模塊內(nèi)部是一個“黑盒子”,對模塊的例化(instance或稱調(diào)用)都是通過對模塊端口的操作來完成的。

2)?I/O端口聲明

所有聲明的端口都必須說明端口類型、位寬。端口之間需用逗號隔開,語句用分號結(jié)束。

根據(jù)信號的方向不同,VerilogHDL中的端口類型有以下三種:

(1)輸入端口:其聲明格式為

input[width-1:0]端口名1,端口名2,…,端口名n;

(2)輸出端口:其聲明格式為

output[width-1:0]端口名1,端口名2,…,端口名n;

(3)輸入/輸出端口:其聲明格式為

inout[width-1:0]端口名1,端口名2,…,端口名n;

width是端口的位寬,如果無位寬說明,系統(tǒng)將默認(rèn)位寬為1。例如,

input[7:0]data_in; //一個名為data_in,位寬為8位的輸入數(shù)據(jù)

outputS,CO; //名為S和CO,位寬均為1位的兩個輸出數(shù)據(jù)

3)數(shù)據(jù)類型說明

對于模塊端口信號和模塊內(nèi)部信號,需有相應(yīng)的數(shù)據(jù)類型說明。VerilogHDL的常用的數(shù)據(jù)類型分為線網(wǎng)型和寄存器型。線網(wǎng)型表示結(jié)構(gòu)化元件之間的物理連線,寄存器型表示數(shù)據(jù)的存儲單元。為盡可能地反映真實硬件電路的工作情況,可對數(shù)字信號的邏輯、強(qiáng)度進(jìn)行建模,變量的邏輯值有0、1、x和z。x表示未初始化或者未知的邏輯值,z表示高阻狀態(tài)。

VerilogHDL定義了八種信號強(qiáng)度用于判斷數(shù)字電路中不同強(qiáng)度的驅(qū)動源之間的賦值沖突,如表3.2所示。多個信號驅(qū)動同一個線網(wǎng)時,輸出信號邏輯強(qiáng)度的建立可以按如下方法判斷:

(1)邏輯值相同而強(qiáng)度不同的多個信號驅(qū)動時,輸出信號的邏輯值和強(qiáng)度由強(qiáng)度大的信號決定。

(2)邏輯值不同,但強(qiáng)度相同的多個信號驅(qū)動時,輸出信號的邏輯值可能會得到不定值。

4)模塊功能說明

模塊邏輯功能的描述是模塊中最重要的部分,可根據(jù)設(shè)計需要選用以下四類常用方法:

(1)用連續(xù)賦值語句“assign”進(jìn)行數(shù)據(jù)流建模。描述數(shù)據(jù)在各個寄存器、邏輯門之間的傳遞,詳見3.3節(jié)。

(2)調(diào)用已設(shè)計好的子模塊,組合成更復(fù)雜的系統(tǒng)。VerilogHDL支持“自頂向下”的設(shè)計方法,大型的、復(fù)雜的數(shù)字系統(tǒng)逐層分解成多個簡單的模塊構(gòu)成,在分別完成各個子模塊設(shè)計后,通過上層模塊例化(或稱調(diào)用)低層模塊的方式,完成目標(biāo)系統(tǒng)的組合。

(3)使用結(jié)構(gòu)說明語句“always”、“initial”可以進(jìn)行變量初始化、組合電路和時序電路塊的描述,具體語法詳見3.4節(jié)。

(4)編寫任務(wù)(task)和函數(shù)(function),對重復(fù)使用的功能進(jìn)行描述,為復(fù)雜系統(tǒng)的設(shè)計提供支持,具體語法詳見3.4節(jié)。

2.模塊的例化

通過模塊的例化(或稱調(diào)用),VerilogHDL可以支持層次化設(shè)計,實現(xiàn)“自頂向下”的設(shè)計思路,模塊例化的基本格式為

<模塊名><例化名>(<端口列表>);

根據(jù)被調(diào)用的低層模塊與上層模塊的端口連接方式描述的不同,有兩種例化方法:

(1)按端口順序連接:低層模塊定義時聲明的端口順序與上層模塊相應(yīng)的連接端口順序保持一致,其格式為

模塊名例化名(PORT_1,PORT_2,…,PORT_N);

(2)按端口名稱連接:被調(diào)用的低層模塊和上層模塊是通過端口名稱進(jìn)行連接,其格式為

模塊名例化名(.port_1(PORT_1),.port_2(PORT_2),…,.port_n(PORT_N));

其中:port_1,port_2,…,port_n表示被調(diào)用模塊設(shè)計聲明的各個端口;

PORT_1,PORT_2,…,PORT_N表示上一層模塊調(diào)用時對應(yīng)的端口名稱。

這種連接端口的順序可以是任意的,只要保證上層模塊的端口名和被調(diào)用模塊端口的對應(yīng)即可。如果被調(diào)用模塊有不需要連接的端口,該端口可懸空寫成.port_n(),也可將此端口忽略。例如,port_2不需要和外界連接,可以寫成:

模塊名例化名(.port_1(PORT_1),.port_2(),…,.port_n(PORT_N));

或者

模塊名例化名(.port_1(PORT_1),,…,.port_n(PORT_N));/*注意,port_2雖然未寫出,但其位置仍然保留*/

當(dāng)被調(diào)用模塊有較多端口時,根據(jù)端口名稱進(jìn)行信號連接,可避免因記錯端口順序而出錯,并且在被調(diào)用模塊因修改使得端口順序發(fā)生變化時,只要端口名稱、功能不變,上層模塊調(diào)用就可以不更改。

在實際應(yīng)用中,可根據(jù)設(shè)計的復(fù)雜程度和設(shè)計習(xí)慣來選擇例化的方法。例3-5通過調(diào)用半加器模塊、或門模塊來實現(xiàn)一位全加器。

半加器模塊的端口如圖3.4所示。圖3.4半加器模塊的端口

(1)設(shè)計半加器。

modulehalfadder(A,B,CO,S);

inputA,B;

//輸入兩個1位的數(shù)據(jù)作為加數(shù)、被加數(shù)

outputS; //加法器輸出的和

outputCO; //加法器輸出的進(jìn)位

wireS,CO;

assignS=A^B;

assignCO=A&B;

endmodule

(2)設(shè)計一位全加器。

根據(jù)數(shù)字邏輯電路關(guān)系,調(diào)用半加器、或門組成一位全加器,其電路連接圖如圖3.5所示。圖3.5全加器電路連接圖

VerilogHDL可用以下兩種方法描述:

方法一:采用按端口順序連接

modulefulladder(a,b,co_in,co_out,s);

inputa,b,co_in;

outputco_out,s;

halfadderu1(a,b,co_temp1,s_temp);

halfadderu2(s_temp,co_in,co_temp2,s);

oru3(co_out,co_temp1,co_temp2);

endmodule方法二:采用按端口名稱連接

modulefulladder(a,b,co_in,co_out,s);

inputa,b,co_in;

outputco_out,s;

halfadderu1(.A(a),.B(b),.CO(co_temp1),.S(s_temp));

halfadderu2(.A(s_temp),.B(co_in),.CO(co_temp2),.S(s));

oru3(co_out,co_temp1,co_temp2);

endmodule

3.?VerilogHDL基本概念

1)詞法約定

VerilogHDL中的基本詞法約定與C語言類似,可以有空白、注釋、分隔符、數(shù)字、字符串、標(biāo)識符和關(guān)鍵詞等,其中關(guān)鍵詞全是小寫字母。

(1)注釋:為加強(qiáng)程序的可讀性和文檔管理,設(shè)計程序中應(yīng)適當(dāng)?shù)丶尤胱⑨寖?nèi)容。注釋有兩種方式:單行注釋和多行注釋。

①單行注釋以“//”開始,只能寫在一行中。例如,

assignc=a+b;//?c等于a,b的和

②多行注釋以“/*”開始,以“*/?”結(jié)束,注釋的內(nèi)容可以跨越多行,例如,

assignc=a+b;/*?c等于a,b的和,本語句可綜合成一個加法器,實現(xiàn)加法的組合邏輯*/

(2)標(biāo)識符(identifier):用于定義模塊名、端口名、連線、信號名等。標(biāo)識符可以是任意一組字母、數(shù)字、$?符號和?_?(下劃線)符號的組合,但標(biāo)識符的第一個字符必須是字母或者下劃線,字符數(shù)不能多于1024個。此外,標(biāo)識符區(qū)分大、小寫。例如,

state,State //這兩個標(biāo)識符是不同的

2and,&write //非法標(biāo)識符

(3)空白符:由空格(\b)、制表符(\t)和換行符定義而成,除了出現(xiàn)在字符串里,VerilogHDL中其它位置的空白符僅僅用于分隔標(biāo)識符,在編譯階段被忽略。

2)數(shù)據(jù)類型

在程序設(shè)計中,數(shù)據(jù)有常量和變量兩種,下面分別進(jìn)行介紹。

(1)常量:是指在程序運行中,其值不能改變的量。

①數(shù)字:其表達(dá)方式為

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

說明:

●?<位寬>:用十進(jìn)制表示的數(shù)字的位數(shù),如果缺省,位寬由具體機(jī)器系統(tǒng)決定(至少為32位)。

●?<進(jìn)制>:可以用四種進(jìn)制表示:二進(jìn)制(b或B)、八進(jìn)制(o或O)、十進(jìn)制(d或D)、十六進(jìn)制(h或H)。缺省時為十進(jìn)制。●?<數(shù)值>:可以是所選進(jìn)制表述的任意有效數(shù)字,包括不定值x和高阻態(tài)z。當(dāng)<數(shù)值>位寬大于指定的大小時,截去高位。

例如,

8'b11001100 //位寬為8的二進(jìn)制數(shù),'b表示二進(jìn)制

'h1f23 //十六進(jìn)制數(shù),采用機(jī)器的默認(rèn)位寬

2'b110x //表示2'b0x,因為當(dāng)數(shù)值大于指定的大小時,截去高位

16'h1z0x //位寬為16位的十六進(jìn)制數(shù),其值的二進(jìn)制表示為16'b0001zzzz0000xxxx

可在數(shù)字之間使用下劃線“_”對數(shù)字進(jìn)行分隔,下劃線只增加數(shù)字的可讀性,在編譯階段將被忽略,如8'b1100_1100。②參數(shù)型(parameter):可以用parameter為關(guān)鍵詞,指定一個標(biāo)識符(即名字)來代表一個常數(shù),參數(shù)的定義常用在信號位寬定義,延遲時間定義等位置,以增加程序的可讀性,方便程序的修改,其格式為

parameter標(biāo)識符1?=?表達(dá)式1,標(biāo)識符2?=?表達(dá)式2,…標(biāo)識符n?=?表達(dá)式n;

這里的表達(dá)式可以是常數(shù),也可以是以前定義過的標(biāo)識符。例如,

parameterwidth=8; //定義了一個常數(shù)參數(shù)

input[width-1:0]data_in; //表示輸入信號data_in的位寬為8

parametera=1,b=3; //定義了兩個常數(shù)參數(shù)

parameterc=a+b; //表示c的值是前面定義的a、b值的和

(2)變量:指在程序運行中,其值可以改變的量。VerilogHDL中常用的三種數(shù)據(jù)類型為wire型、reg型和memory型,其它數(shù)據(jù)類型的說明請查閱VerilogHDL的相關(guān)手冊。

①線網(wǎng)wire型變量:wire型線網(wǎng)變量表示硬件單元之間的連接,它的值由驅(qū)動元件的值決定。如果沒有驅(qū)動元件連接到線網(wǎng),線網(wǎng)的缺省值為z。VerilogHDL模塊端口信號的數(shù)據(jù)類型如無定義,默認(rèn)為wire型,其定義格式為

wire[width-1:0]變量名1,變量名2,…,變量名n;說明:

●?[width-1:0]指明了變量的位寬,缺省此項時默認(rèn)變量位寬為1。

●?wire為關(guān)鍵詞,多個變量名之間用逗號隔開。

●?模塊的輸入/輸出信號的數(shù)據(jù)類型默認(rèn)為wire型。

例如,

wire[7:0]a,b; //位寬為8的wire型變量a和b

wirec; //?wire型變量c,位寬為1②reg型:reg型寄存器變量表示一個抽象的數(shù)據(jù)存儲單元,只能在initial語句和always語句中被賦值。寄存器型變量的默認(rèn)值是不定值x。其定義格式為

reg[width-1:0]變量名1,變量名2,…,變量名n;

例如,

reg[7:0]b,c; //兩個位寬為8的reg型變量b和c

rega; //?reg型變量a,位寬為1③memory型:memory型數(shù)據(jù)常用于寄存器文件,以及ROM、RAM的建模等。memory型數(shù)據(jù)是將reg型變量進(jìn)行地址擴(kuò)展而得到的,其格式為

reg[n-1:0]存儲器名[N-1:0];//定義位寬為n,深度為N的寄存器組

例如,

reg[7:0]mem[255:0]; //每個寄存器位寬為8,共有256個寄存器的寄存器組

對一組存儲單元進(jìn)行讀寫,必須指定該單元的地址,如對上例的mem寄存器的第200個存儲單元進(jìn)行賦0值的操作語句為

mem[200]=0; //對存儲器mem的第200個存儲單元賦值為0

需要注意memory型數(shù)據(jù)和reg型數(shù)據(jù)的區(qū)別。例如,

regmem[N-1:0]; //由N個位寬為1的寄存器組成的寄存器組mem

reg[N-1:0]a; //一個N位的寄存器變量a3.1.3VerilogHDL的描述層次

根據(jù)對電路描述的抽象程度不同,VerilogHDL描述有四個層次。

(1)行為級或算法級:這是VerilogHDL支持的最高抽象級別,在這一級別上設(shè)計者關(guān)注算法的實現(xiàn),不關(guān)心具體的硬件實現(xiàn)細(xì)節(jié),幾乎可以使用VerilogHDL提供的所有語句。

(2)數(shù)據(jù)流級:通過描述模塊內(nèi)部數(shù)據(jù)流的情況來描述該邏輯單元的功能,在這一級別上設(shè)計者關(guān)注數(shù)據(jù)的處理及其如何在線網(wǎng)上和寄存器間的傳遞。

一般情況下,寄存器傳輸級(RTL)描述指的是能夠通過綜合工具轉(zhuǎn)化為門級電路的行為級描述和數(shù)據(jù)流級描述。

(3)門級:調(diào)用已設(shè)計好的邏輯門基本單元(原語),如與門、或門、異或門等,描述邏輯門之間的連接,構(gòu)成電路。

(4)開關(guān)級:這是VerilogHDL支持的最低抽象層次,通過描述器件中的晶體管、存儲節(jié)點及其它們的互聯(lián)來設(shè)計模塊。

由于開關(guān)級描述的應(yīng)用較少,本章將從門級建模、數(shù)據(jù)流級建模和行為級建模等三個層次對VerilogHDL的語法進(jìn)行討論。 3.2門級建模

3.2.1門的類型

VerilogHDL定義了兩類基本的邏輯門:與/或門類(and/or)、緩沖/非門類(buf/not),稱為預(yù)定義的邏輯門,在使用預(yù)定義的邏輯門原語例化邏輯門時,可以直接使用相關(guān)原語,無需再次聲明定義。預(yù)定義邏輯門調(diào)用時,例化名可選,其格式為

<預(yù)定義邏輯門名><例化名>(端口列表);

例如,調(diào)用與門可以寫成

oror1(out,in1,in2);

或or(out,in1,in2);

1.與/或門類(見表3.3所示)

說明:

(1)與/或門類都有一個輸出端和多個輸入端,門端口列表中的第一個端口必定是輸出端口,其它是輸入端口。

(2)在門的例化調(diào)用中,如果輸入端口的個數(shù)超過兩個,只需將輸入端口直接排列在端口列表中即可,VerilogHDL根據(jù)輸入端口數(shù)自動選擇合適端口的邏輯門。

例如,設(shè)輸出端口為out,輸入端口為in1、in2、in3和in4。

andu1(out,in1,in2); //二輸入與門

xorx1(out,in1,in2,in3,in4); //四輸入異或門,輸入端口數(shù)目超過2個

(3)基本門的真值表如表3.4所示。表3.4基本門的真值表

(4)如果輸入端口多于兩個,則可以通過重復(fù)使用兩輸入真值表來計算輸出的值。

2.緩沖/非門類

VerilogHDL提供了緩沖器和非門原語,其邏輯符號和功能如表3.5所示。說明:

(1)緩沖/非門類邏輯門具有一個輸入,多個輸出,端口列表的最后一個端口是輸入端口,其它是輸出端口。

(2)如果輸出端口多于一個,只需將所有的輸出端口排列在端口列表中,VerilogHDL可以根據(jù)端口自動選擇合適的邏輯門。

例如,設(shè)in是輸入端口,out、out1、out2和out3是輸出端口。

buf(out,in); //單輸出緩沖門

not(out,in); //單輸出非門

bufb2(out1,out2,out3,in);//多輸出緩沖門,例化名為b2

notn2(out1,out2,in);//多輸出非門,例化名為n2

(3)緩沖器和非門的真值表如表3.6所示。

(4)?VerilogHDL還支持四個帶控制的條件緩沖器和條件反相器,它們有輸出、輸入和控制三個引腳,其功能和符號見表3.7,相關(guān)真值表見表3.8。例如,設(shè)out是輸出端口,in是輸入端口,control是控制端口。

bufif1u1(out,in,control);

bufif0u2(out,in,control);

notif1u3(out,in,control);

notif0u4(out,in,control);

在調(diào)用四種條件緩沖器和條件反相器時,注意端口羅列的順序規(guī)則。3.2.2實例數(shù)組(ArrayofInstances)

在實際應(yīng)用中,常會對某種邏輯門進(jìn)行多次調(diào)用,實現(xiàn)多位寬數(shù)據(jù)的邏輯運算,這可以通過實例數(shù)組的方式來表述,以簡化書寫,其格式為

<邏輯門名字><實例名字><位寬>(端口列表);例3-6實現(xiàn)兩個3位數(shù)據(jù)的或運算。3.2.3應(yīng)用舉例

下面用預(yù)定義邏輯門原語設(shè)計三個數(shù)據(jù)的奇偶校驗位電路。

由于信道的噪聲干擾、傳輸中斷等原因容易使傳送的數(shù)據(jù)產(chǎn)生誤碼,奇偶校驗是比較常用的檢錯碼。它是一種通過增加冗余位使得碼字中1或0的個數(shù)恒為奇數(shù)或偶數(shù)的方法。

例3-7

設(shè)輸入是A、B、C,輸出的校驗位碼字是F,其真值表如表3.9所示。

可以使用異或邏輯門來實現(xiàn)這個電路,其奇偶校驗位電路如圖3.6所示。表3.9奇偶校驗位的真值表圖3.6三個數(shù)據(jù)的奇偶校驗位電路

邏輯圖與VerilogHDL的描述有一一對應(yīng)的關(guān)系。奇偶校驗位電路的VerilogHDL門級描述如下:

moduleCRC_test(A,B,C,F(xiàn)); //端口說明

inputA,B,C;

outputF;

wiretemp; //內(nèi)部線網(wǎng)temp聲明

xor(temp,B,C); //調(diào)用兩輸入的異或門

xor(F,temp,A);

endmodule3.2.4門延遲

1.上升、下降和關(guān)斷延遲

在VerilogHDL中,定義了三種輸入到輸出的延遲:

(1)上升延遲:邏輯門的輸出從低電平0、未知態(tài)x、高阻態(tài)z變化成為高電平1所需的時間。

(2)下降延遲:邏輯門的輸出從高電平1、未知態(tài)x、高阻態(tài)z變化成低電平0所需的時間。

(3)關(guān)斷延遲:邏輯門的輸出從高電平1、低電平0、未知態(tài)x變化成高阻態(tài)z所需的時間。

在VerilogHDL中,用戶可以使用表3.10中的三種方法指定邏輯門延時。

2.最小/典型/最大延遲

由于受集成電路制造工藝過程的影響,真實器件的延時會有一個變化的范圍。在VerilogHDL中,除了支持上述的三種延時以外,還可以分別指定每種延時的最小值、最大值和典型值。

(1)最小值(min_delay_time):邏輯門所具有的最小延時。

(2)典型值(typical_delay_time):邏輯門所具有的典型延時。

(3)最大值(max_delay_time):邏輯門所具有的最大延時。格式:

<邏輯門名>#(min_delay_time:typical_delay_time:max_delay_time)(portdeclare);

用戶可以在仿真一開始就指定具體選用哪一種延時值(最大值/典型值/最小值),以建立不同的仿真模型。用戶也可以在仿真過程中控制延遲值的使用,具體的控制方法與使用的仿真器和操作系統(tǒng)有關(guān)。例如,

and#(4:5:6)(out,a,b);/*只聲明了一個延時時間,所有延時的最小值=4,典型值=5,最大值=6*/

or#(4:5:6,5:6:7)(out,c,d);/*聲明了兩個延時,上升延時的最小值?=?4,典型值?=?5,最大值?=?6;下降延時的最小值?=?5,典型值?=?6,最大值=7*/

xor#(4:5:6,6:7:8,7:8:9)(out,in1,in2);/*聲明了三個延時,

上升延時的最小值?=4,典型值?=?5,最大值?=?6

下降延時的最小值?=6,典型值?=?7,最大值?=?8

關(guān)斷延時的最小值?=7,典型值?=?8,最大值?=?9*/ 3.3數(shù)?據(jù)?流?建?模

3.3.1連續(xù)賦值語句

連續(xù)賦值語句常用于數(shù)據(jù)流行為建模,以assign為關(guān)鍵詞,操作符是“=”。

assign賦值語句執(zhí)行將數(shù)值賦給線網(wǎng),可以完成門級描述,也可從更抽象的角度對線網(wǎng)電路進(jìn)行描述,多用于組合邏輯電路的表述,其格式為

assign賦值目標(biāo)線網(wǎng)?=?表達(dá)式;

例如,

assigna=b|c; //兩輸入的或門

assign{c,sum[3:0]}=a[3:0]+b[3:0]+c_in;/*一個四位的加法器,a、b是加數(shù)和被加數(shù),

c_in是進(jìn)位,sum、c分別是相加后的和、進(jìn)位*/

assignc=max(a,b);//調(diào)用了求最大值的函數(shù)max,將函數(shù)返回值賦給c說明:

(1)式子左邊的“賦值目標(biāo)線網(wǎng)”只能是線網(wǎng)變量,不能是寄存器變量。

(2)式子右邊表達(dá)式的操作數(shù)可以是線網(wǎng)、寄存器,也可以是函數(shù)調(diào)用。

(3)一旦等式右邊任何一個操作數(shù)發(fā)生變化,右邊的表達(dá)式就會立刻被重新計算,再進(jìn)行一次新的賦值。

(4)assign可以使用條件運算符進(jìn)行條件判斷后再賦值,如下述語句:

assigndata_out=sel?a:b;/*如果sel等于1,將a賦給data_out,否則將b賦給data_out,

?實現(xiàn)一個二選一的電路*/

(5)可用賦值延時控制對線網(wǎng)賦予新值的延時時間,延時值位于關(guān)鍵詞assign的后面,但標(biāo)注的延時時間在編譯過程中將被忽略。

assign#10data_out=data_in1&data_in2;/*計算data_in1&data_in2的值,延遲10個時間單位賦給data_out,時間單位由'timescale給定*/3.3.2表達(dá)式、運算符和操作數(shù)

表3.11運算符的分類和優(yōu)先級根據(jù)參加運算的操作數(shù)的數(shù)目,運算符可分為

(1)單目運算符:對一個操作數(shù)進(jìn)行運算的運算符,如clock=~clock。

(2)雙目運算符:對兩個操作數(shù)進(jìn)行運算的運算符,如a=b&c。

(3)三目運算符:對三個操作數(shù)進(jìn)行運算的運算符,如D_out=condition?D_in1:D_in2。

1.算術(shù)運算符

算術(shù)運算符有加法(?+?)、減法(?-?)、乘法(?*?)、除法(?/?)和取模(%)。

例如,設(shè)a?=4'b0101,b=4'b0010

a+b //?a和b相加,等于4'b0111

a/b //?a除以b,等于4'b0010,余數(shù)部分舍棄,取整

a%b //?a對b取模,即求a、b相除的余數(shù)部分,結(jié)果等于1

注意:在算術(shù)運算時,如有一個操作數(shù)是不定值x,則運算結(jié)果將不能得到確定數(shù)值。如果使用“+”、“-”運算符作為操作數(shù)的正、負(fù)表示時,它們的優(yōu)先級比雙目運算符更高。

2.邏輯運算符

邏輯運算符有邏輯與(&&)、邏輯或(?||?)和邏輯非(?!?)。

說明:

(1)“&&”和“||”是雙目運算符,“!”是單目運算符。

(2)邏輯運算符的計算結(jié)果是一個一位的值,可以是:邏輯假(0)、邏輯真(1)和不確定(x)。

(3)如果操作數(shù)為具體數(shù)值時,操作數(shù)不等于0,等價于邏輯真(1);操作數(shù)等于0,等價于邏輯假(0);操作數(shù)的任何一位為不定值x或者高阻態(tài)z,等價于不定值。例如,設(shè)a?=?2,b?=?0

a&&b //等于0,相當(dāng)于(邏輯1&&邏輯0)

a||b //等于1,相當(dāng)于(邏輯1||邏輯0)

!a //等于0,相當(dāng)于邏輯1取反

(a==3)&&(b==0)/*等于0,相當(dāng)于兩個表達(dá)式是否成立(為真),即如果a=3成立,則(a==3)

為邏輯1,否則為邏輯0*/

x&&a //等于x,相當(dāng)于(x&&邏輯1)

3.按位運算符

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

說明:

(1)取反運算是單目運算符,其余是雙目運算符。

(2)按位運算是對操作數(shù)中的每一位進(jìn)行按位操作。若兩個數(shù)的位寬不相同,系統(tǒng)先將兩個操作數(shù)右對齊,較短的操作數(shù)左端補(bǔ)0,使得兩個操作數(shù)位寬相同,然后再按位運算。

(3)注意按位運算和邏輯運算的差別,邏輯運算結(jié)果是一個一位的邏輯值,按位運算產(chǎn)生一個與較長位寬操作數(shù)等寬的數(shù)值。例如,設(shè)a?=4'b0011,b?=4'b1010,c?=3'b011,d=4'b11x0

~a //按位取反,結(jié)果等于4'b1100

b&c //按位與運算,結(jié)果等于4'b0010

a^~d //按位同或運算,結(jié)果等于4'b00x0

a&b //按位與運算,結(jié)果等于4'b0010

下句與前句比較:

a&&b//邏輯與運算,等價于1&&1,結(jié)果等于1

4.關(guān)系運算符

關(guān)系運算符包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)。

在運算中,如果表達(dá)式成立,運算結(jié)果是真(1);如果表達(dá)式不成立,運算結(jié)果為假(0);如果操作數(shù)中某一位是不確定的,則表達(dá)式的結(jié)果是不定值。

例如,設(shè)a=4'b1010,b=4'b0001,c=4'b1xz0

a>b //結(jié)果等于邏輯值1

a<=c //結(jié)果等于邏輯值x

13–a>b /*由于算術(shù)運算優(yōu)先級較高,先進(jìn)行13–a的計算,得到3,再和b進(jìn)行比較,結(jié)果等于邏輯值1*/

13–(a>b) /*由于括號表明了關(guān)系運算的優(yōu)先級,a>b成立,結(jié)果是真值為1,所以算術(shù)

結(jié)果等于12*/

5.等式運算符

等式運算符包括邏輯等(==)、邏輯不等(!=)、case等(===)、case不等(!==)。

說明:

(1)若兩個操作數(shù)位寬不等,先將兩個操作數(shù)右對齊,用0填充較短數(shù)的左邊。

(2)邏輯等(==)和邏輯不等(!=)中,如果兩操作數(shù)中某一位是不確定的,則返回值是x;在邏輯等運算時,如果兩個數(shù)相同,返回邏輯值1,否則返回邏輯0。邏輯不等運算,反之同理。

例如,設(shè)a=4'b1010,b=4'b1100,d=4'b101x

a==b; //結(jié)果為邏輯值0

a!=b; //結(jié)果為邏輯1

a==d; //結(jié)果為邏輯x

(3)?case等(===)、case不等(!==)與邏輯等式運算符不同。在對兩個操作數(shù)進(jìn)行逐位比較時,即使有x、z位,也要進(jìn)行精確比較。在case等運算中,只有在兩者完全相等的情況下結(jié)果為1,否則為0。case等運算符的結(jié)果不可能為x。

例如,設(shè)a=4'b1010,b=4'b1xzz,c=4'b1xzz,d=4'b1xzx

a===b; //結(jié)果為邏輯值0

b===c; //結(jié)果為邏輯值1(兩個數(shù)每一位都相同,包括x、z)

b===d; //結(jié)果為邏輯值0

b!==d; //結(jié)果為邏輯值1

6.縮減運算符

縮減運算符包括縮減與(?&?)、縮減與非(?~&?)、縮減或(?|?)、縮減或非(?~|?)、縮減異或(?^?)、縮減同或(?~^?)。這類操作符將對操作數(shù)由左向右進(jìn)行操作,它們的運算規(guī)則和按位操作符相同。

注意:縮減運算符只有一個操作數(shù),按位運算符有兩個操作數(shù)。

例如,設(shè)a=4'b1010

b=&a //?b=1&0&1&0=0

b=|a //?b=1|0|1|0=1

b=^a //?b=1^0^1^0=0

可以看到,用縮減異或、縮減同或可以產(chǎn)生一個向量的奇偶校驗位。

7.移位運算符

移位運算符有右移(>>)、左移(<<)。右移(>>)和左移(<<)是分別將操作數(shù)向右、向左移動指定的位數(shù),空出的位置用0補(bǔ)足。

例如,設(shè)a=4'b1010

b=a>>1; //右移1位,結(jié)果是b=4'b0101

b=a<<2; //左移2位,結(jié)果是b=4'b1000

移位運算符在具體設(shè)計中有很多應(yīng)用,如乘法運算可以轉(zhuǎn)換成移位相加來完成,可以進(jìn)行移位寄存器的移位操作等。

8.拼接運算符

位拼接運算符{}可以將兩個或多個操作數(shù)的某些位拼接起來成為一個操作數(shù)。拼接運算時,需要將拼接的操作數(shù)按照順序羅列出來,其間用逗號隔開,操作數(shù)的類型可以是線網(wǎng)變量、寄存器、線網(wǎng)向量、有確定位寬的常數(shù)等。

注意:進(jìn)行拼接的每個操作數(shù)必須是確定位寬的,因為系統(tǒng)進(jìn)行拼接時必須要確定拼接結(jié)果的位寬。例如,設(shè)a=1'b1,b=3'b101,c=4'b1010

X={a,b,c}; //結(jié)果是X=8'b11011010

Y={a,b,2'b01}; //結(jié)果是Y=6'b110101

Z={b[1:0],c[1],c[0]}; //結(jié)果是Z=4'b0110

位拼接可以使用重復(fù)操作、嵌套的方式來簡化表達(dá)式。例如,

3{1'b1}=3'b111

{1'b0,3{1'b1}}=4'b0111

{1'b0,{3{2'b01}}=7'b0010101

9.條件運算符

條件運算符是一個三目的運算符,其格式為

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

判斷過程是首先計算條件表達(dá)式:

(1)如果條件表達(dá)式為真,計算表達(dá)式1的值。

(2)如果條件表達(dá)式為假,計算表達(dá)式2的值。

(3)如果表達(dá)式為不確定值x,且表達(dá)式1和表達(dá)式2的值不相等,輸出結(jié)果為不確定值。

例如,

assignc=a>b?a:b//?a>b如果成立(真),c=a;反之,c=b3.3.3舉例

對同一個電路,可以從門級、數(shù)據(jù)流級和行為級不同角度進(jìn)行描述。現(xiàn)在從數(shù)據(jù)流級的角度設(shè)計一個四選一電路和一位全加器。

例3-8

用數(shù)據(jù)流建模方式描述四選一選擇器,四選一選擇器模塊端口如圖3.7所示。

modulemux4_1(in1,in2,in3,in4,sel,out);

inputin1,in2,in3,in4;

input[1:0]sel;

outputout;

assignout=sel[1]?(sel[0]?in4:in3)

:(sel[0]?in2:in1);

endmodule圖3.7四選一選擇器模塊端口例3-9

用數(shù)據(jù)流建模方式設(shè)計一位全加器,電路圖如圖3.8所示。

modulefulladder(a,b,cin,s,co);

inputa,b;

inputcin;

outputs;

outputco;

assign{co,s}=a+b+cin;

endmodule圖3.8全加器電路圖 3.4行?為?級?建?模

3.4.1順序塊和并行塊語句

VerilogHDL中使用塊語句將多條語句組合成一條復(fù)合語句。塊語句分為順序塊語句和并行塊語句。

1.順序塊

順序塊中的語句按書寫順序執(zhí)行,由begin…end標(biāo)識,其格式為

beginbegin塊名

執(zhí)行語句1;塊內(nèi)變量、參數(shù)定義;

執(zhí)行語句2;或者執(zhí)行語句1;

…?執(zhí)行語句2;

end…

end說明:

(1)塊名是可選的,它是一個塊的標(biāo)識名。

(2)塊內(nèi)可以根據(jù)需要定義變量,聲明參數(shù),但這些內(nèi)容只能在塊內(nèi)使用,類似于局部變量和局部聲明。

(3)順序塊內(nèi)的語句是按照語句的書寫順序執(zhí)行的。在仿真開始時執(zhí)行第一條語句,后面語句的開始執(zhí)行時間和前一條語句的執(zhí)行時間是相關(guān)的,如果有延時,延時也是相對于前一條語句執(zhí)行完的仿真時間而言的。當(dāng)塊內(nèi)的最后一條語句執(zhí)行完后,才跳出該順序塊。

2.并行塊

并行塊中的語句并行執(zhí)行,由fork…join標(biāo)識,其格式為

forkfork塊名

執(zhí)行語句1;塊內(nèi)變量、參數(shù)定義語句;

執(zhí)行語句2;或者執(zhí)行語句1;

…?執(zhí)行語句2;

join…

join說明:

(1)塊名、塊內(nèi)變量、參數(shù)定義語句的理解與順序塊相同。

(2)并行塊的語句是同時執(zhí)行的,可以將每一條語句看成一個獨立的進(jìn)程,語句的書寫順序不會影響到語句的執(zhí)行結(jié)果。應(yīng)注意避免并行塊中的多條語句對同一個變量進(jìn)行改變,否則可能會引起競爭。

(3)塊內(nèi)每條語句的起始執(zhí)行時間是相同的,當(dāng)塊中執(zhí)行時間最長的語句執(zhí)行完后,跳出并行塊的執(zhí)行。例3-10寫出下面兩個順序塊和并行塊程序的執(zhí)行結(jié)果。

順序塊:

begin

s=0;

#2s=1;

#4s=0;

#5s=1;

#1s=0;

end并行塊:fork

s=0;

#2s=1;

#4s=0;

#5s=1;

#1s=0;?join

例3-10的順序塊和并行塊完成了對變量s的賦值過程,假設(shè)塊語句都從仿真時刻0開始執(zhí)行,其實現(xiàn)的賦值過程如表3-12所示。3.4.2條件語句

1.if語句

if語句和它的變化形式是條件語句的常見形式。常見格式如下:

(1)?if(表達(dá)式)

<語句>;

(2)?if(表達(dá)式)

<語句1>;

else

<語句2>;

(3)?if(表達(dá)式1)

<語句1>;

elseif(表達(dá)式2)

<語句2>;

elseif(表達(dá)式n)

<語句n>;

else

<語句n+1>;說明:

(1)?if后面的表達(dá)式,可以是邏輯表達(dá)式或關(guān)系表達(dá)式。如果表達(dá)式的值是真(1),執(zhí)行緊接在后的語句;如果是假(0),執(zhí)行else后的語句。

(2)?if后的表達(dá)式還可以是操作數(shù)。如果操作數(shù)是0、x、z等價于邏輯假,反之為邏輯真。下式是一種表達(dá)式的簡化寫法:

if(reset)等價于if(reset==1)

(3)?else不能作為單獨的語句使用,必須與if語句配對使用。

(4)如果if和else后有多個執(zhí)行語句,可以用begin…end塊將其整合在一起。例如,

if(a>b)

begin

data_out1<=a;

data_out2<=b;

end

else

(5)?if語句可以嵌套使用,但是在嵌套使用過程中,應(yīng)注意與if配對的else語句。通常,else與最近的if語句配對。例如,

if(a>b)//第一個if語句

if(c) //第二個if語句

data_out<=c+1;

else //與第二個if語句的配對else

data_out<=a+1;

else //與第一個if語句的配對else

data_out<=b;特別在if-else數(shù)目不一致時,最好使用begin-end塊,如同算術(shù)表達(dá)式的括號一樣,確定if-else的配對關(guān)系,避免邏輯描述錯誤。例如,

if(…)

begin

if(…)

執(zhí)行語句

if(…)

執(zhí)行語句;

else

執(zhí)行語句;

end

else

(6)如果不能正確使用else,可能會生成不需要的鎖存器。例如,

always@(aorb)//當(dāng)a或者b的數(shù)值發(fā)生變化時,觸發(fā)always塊執(zhí)行

begin

if(a)

data_out<=a;

end

如果設(shè)計者的設(shè)計意圖是:當(dāng)a不為0時,data_out賦值為a,否則被賦值為b。但上例描述的電路,在a等于0時,data_out仍為前一個a值,從而生成了一個不希望的鎖存器。

(7)?if-else表達(dá)了條件選擇的設(shè)計意圖,它與條件操作符有重要的區(qū)別。

條件操作符可以出現(xiàn)在一個表達(dá)式中,而這個表達(dá)式可以使用在過程賦值中或者連續(xù)賦值中,可進(jìn)行行為建模,也可以進(jìn)行門級建模。

if-else語句只能出現(xiàn)在always、initial塊語句、函數(shù)和任務(wù)中,一般只能在行為建模中使用。

2.case語句

if-else語句提供了選擇操作,但如果選擇項數(shù)目較多,使用會很不方便,如果判斷用的條件是同一個表達(dá)式時,使用case語句就很簡便。

case是一種多分支選擇語句,其格式為:

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

分支表達(dá)式1:語句1;

分支表達(dá)式2:語句2;

分支表達(dá)式n:語句n;

default:默認(rèn)語句;

endcase控制表達(dá)式常表示為控制信號的某些位,分支表達(dá)式是這些控制信號的具體狀態(tài)值。

語句執(zhí)行時,先計算case后的控制表達(dá)式,然后將得到的值與后面的分支表達(dá)式的值進(jìn)行比較,當(dāng)控制表達(dá)式的值與某分支表達(dá)式的值相等時,執(zhí)行該分支表達(dá)式后的語句,如果沒有匹配的分支表達(dá)式,執(zhí)行default后的默認(rèn)語句。

case語句的作用類似于多路選擇器。用case語句可以容易、簡潔地實現(xiàn)四選一、八選一、十六選一等電路描述。

例3-11

使用case語句設(shè)計數(shù)據(jù)選擇器MUX,其系統(tǒng)模塊圖和功能表如圖3.9所示。圖3.9選擇器的模塊圖和功能表

modulemux(data_in1,data_in2,sel,data_out);

input[1:0]data_in1,data_in2;

input[1:0]sel;

output[1:0]data_out;

always@(data_in1,data_in2,sel)

begin

case(sel)

2′b00:data_out<=data_in1^data_in2;

2′b01:data_out<=data_in1|data_in2;

2′b10:data_out<=data_in1&data_in2;

2′b11:data_out<=~data_in1;

default:data_out<=2‘bxx;

endcase

end

endmodule應(yīng)該注意:

(1)每個分支表達(dá)式的值必須是互不相同的,否則會出現(xiàn)同一個控制表達(dá)式值有多種執(zhí)行語句的矛盾。

(2)case語句執(zhí)行中,逐位對控制表達(dá)式的值和分支表達(dá)式的值進(jìn)行比較,每一位的值可能是0、1、x、z。如果兩者的位寬不一致,在較短數(shù)據(jù)左端加0,調(diào)整使兩者位寬相等。如果多個不同的狀態(tài)值有相同的執(zhí)行語句,可以用逗號將各個狀態(tài)隔開。例如,

case(select)

2'b00:data_out<=data_in1;

2'b11:data_out<=data_in4;

//如果select中有不確定位x,輸出值是x

2'b0x,2'bx0,2'b1x,2'bx1,2'bxx:data_out<=4'bxxxx;

//如果select中有高阻態(tài)位,輸出值是z

2'b0z,2'bz0,2'b1z,2'bz1,2'bzz:data_out<=4'bzzzz;

default:$display("thecontrolsignalisinvalid");

endcase

(3)default語句是可選的,一個case語句中只能有一個default選項。建議在case語句中最好加入default分支,以避免因分支表達(dá)式未能對控制表達(dá)式的所有狀態(tài)進(jìn)行窮舉,而生成不需要的鎖存器。

(4)?case與if-else-if的比較。

①if-else-if結(jié)構(gòu)中的條件表達(dá)式更具一般性,更直觀。

②case語句為表達(dá)式值存在不定值x、高阻值z位的情況提供了逐位比較,執(zhí)行對應(yīng)語句的操作。

case語句還有兩種變形,關(guān)鍵詞為casez和casex。這可以在比較中對不關(guān)心的值進(jìn)行忽略。其中,casex將條件表達(dá)式或者分支表達(dá)式中的不定態(tài)x的位視為不關(guān)心的位,casez則將高阻態(tài)z視為不關(guān)心的位,這樣設(shè)計者就可以根據(jù)具體要求,只對信號的某些位進(jìn)行比較。具體請查閱VerilogHDL相關(guān)手冊。3.4.3循環(huán)語句

循環(huán)語句只能在initial、always塊中使用。VerilogHDL中有四種循環(huán)語句:for、forever、repeat、while,它們的語法規(guī)則類似于C語言的循環(huán)語句。

1.for語句

for語句格式:

for(表達(dá)式1;表達(dá)式2;表達(dá)式3)語句;說明:

(1)表達(dá)式1是初始條件表達(dá)式,表達(dá)式2是循環(huán)終止條件,表達(dá)式3是改變循環(huán)控制變量的賦值語句。

(2)語句執(zhí)行過程:

第一步:求解表達(dá)式1。

第二步:求解表達(dá)式2,如果其值為真(非0),執(zhí)行for語句中內(nèi)嵌的語句組,然后執(zhí)行第三步;如果為假(等于0),結(jié)束循環(huán),執(zhí)行for循環(huán)后的語句。

第三步:求解表達(dá)式3,得到新的循環(huán)控制變量的值,轉(zhuǎn)到第二步繼續(xù)執(zhí)行。例3-12

用for語句對存儲器組進(jìn)行初始化。

reg[7:0]my_memory[511:0]; //定義寄存器型數(shù)組,有變量512個,變量位寬是8

integeri;

initial

begin

for(i=0;i<512;i=i+1)

my_memory[i]<=8'b0; //把數(shù)組中所有變量賦0值

end

2.while語句

while語句格式:

while(條件表達(dá)式)語句;

語句執(zhí)行過程:先求解條件表達(dá)式的值,如果值為真(等于1),執(zhí)行內(nèi)嵌的執(zhí)行語句(組),否則結(jié)束循環(huán)。如果一開始就不滿足條件表達(dá)式,則循環(huán)一次都不執(zhí)行。

例3-13

用while語句求從1加到100的值,加法完成后打印結(jié)果。

modulecount(clk,data_out);

inputclk;

output[12:0]data_out;

reg[12:0]data_out;

integerj;

initial//?data_out和j賦初值為0

begin

data_out=0;

j=0;

end

always@(posedgeclk)

begin

while(j<=100)/*如果j小于等于100,則執(zhí)行循環(huán)內(nèi)容,執(zhí)行100次后,j大于100之后,跳出循環(huán)*/

begin

data_out=data_out+j;

j=j+1;

end

$display(“thesumis%d,j=%d”,data_out,j);

end

endmodule

3.forever語句

forever語句格式:

forever語句;

forever表示永久循環(huán),無條件地?zé)o限次執(zhí)行其后的語句,相當(dāng)于while(1),直到遇到系統(tǒng)任務(wù)?$finish、$stop才結(jié)束循環(huán),如果需要從循環(huán)中退出,可以使用disable語句。

forever不能獨立寫在程序中,必須寫在initial塊中。

例3-14

使用forever語句生成一個周期為20個時間單位的時鐘信號。

regclock;

initial

begin

clock=0;

//對clock賦初始值

forever#10clock=~clock; /*每過10個仿真時間,clock的值進(jìn)行一次翻轉(zhuǎn),從而生成的時鐘周期是20個時間單位*/

end

這段程序常用于測試文件的編寫中。

4.repeat語句

語句格式:

repeat(表達(dá)式)語句;

repeat語句執(zhí)行表達(dá)式所指定的固定次數(shù)的循環(huán)操作,其表達(dá)式通常是常數(shù),也可以是一個變量,或者一個信號。如果是變量或者信號,循環(huán)次數(shù)是循環(huán)開始時刻變量或信號的值,而不是循環(huán)執(zhí)行期間的值

溫馨提示

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

最新文檔

評論

0/150

提交評論