《數字電路設計及Verilog HDL實現》課件第3章_第1頁
《數字電路設計及Verilog HDL實現》課件第3章_第2頁
《數字電路設計及Verilog HDL實現》課件第3章_第3頁
《數字電路設計及Verilog HDL實現》課件第3章_第4頁
《數字電路設計及Verilog HDL實現》課件第3章_第5頁
已閱讀5頁,還剩121頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

3.1VerilogHDL程序的基本結構

3.2VerilogHDL的數據類型

3.3VerilogHDL的運算符

3.4VerilogHDL的基本語句

3.5模塊化程序設計

第3章VerilogHDL的基本語法

VerilogHDL程序由模塊(module)組成,模塊的基本結構如圖3.3.1所示。一個完整的模塊由模塊端口定義和模塊內容兩部分組成,模塊內容包括I/O聲明、信號類型聲明和功能描述。3.1VerilogHDL程序的基本結構圖3.1.1VerilogHDL程序模塊結構例如,定義一個1位全加器full_addr模塊,其輸入/輸出端口有5個:a、b是全加器的兩個加數輸入;cin是低位的進位輸入;s是全加器的和輸出;cout是全加器向高位的進位輸

出。其格式如下:

modulefull_addr(s,cout,a,b,cin);//模塊端口定義

inputa,b,cin;//I/O聲明

outputs,cout;

assign{cout,s}=a+b+cin;//功能描述

endmodule模塊的設計遵循以下規則:

(1)模塊內容位于module和endmodule之間;每個模塊都有一個名字,即模塊名,如full_addr,模塊名中可以包含英文字母、數字和下劃線,并以英文字母開頭。

(2)除endmodule外,所有的語句后面必須有分號“;”。

(3)語句可以是單條語句,也可以是用begin和end兩個保留字包圍起來的由多條語句組成的復合語句。

(4)可以用“/*…*/”或“//…”對程序的任何部分作注釋,增加程序的可讀性和可維護性。3.1.1模塊端口定義

模塊端口定義用來聲明設計模塊的輸入/輸出端口,其格式如下:

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

模塊的端口是設計電路模塊與外部聯系的全部輸入/輸出端口信號,是設計實體的對外引腳,是使用時外界可以看到的部分(不包括電源線和地線),多個端口之間用逗號“,”隔開。3.1.2模塊內容

模塊內容用于對信號的I/O狀態及信號類型進行聲明,并描述模塊的功能。

1.I/O聲明

模塊的I/O聲明用來聲明各端口信號流動方向,包括輸入(input)、輸出(output)和雙向(inout)。I/O聲明格式如下:

1)輸入聲明

如果信號位寬為1位,那么聲明格式為

input端口1,端口2,端口3,…;

如果信號位寬大于1位,那么聲明格式為

input[msb:lsb]端口1,端口2,端口3,…;

其中,msb和lsb分別表示信號最高位和最低位的編號。

2)輸出聲明

如果信號位寬為1位,那么聲明格式為

output端口1,端口2,端口3,…;

如果信號位寬大于1位,那么聲明格式為

output[msb:lsb]端口1,端口2,端口3,…;

3)輸入、輸出聲明

如果信號位寬為1位,那么聲明格式為

inout端口1,端口2,端口3,…;

如果信號位寬大于1位,那么聲明格式為

inout[msb:lsb]端口1,端口2,端口3,…;

2.信號類型聲明

信號類型聲明用來說明電路的功能描述中所用信號的數據類型,常用的信號類型有連線型(wire)、寄存器型(reg)、整型(integer)、實型(real)、時間型(time)等。

3.功能描述

功能描述是VerilogHDL程序的主要部分,用來描述設計模塊內部結構和模塊端口間的邏輯關系,在電路上相當于器件的內部結構。功能描述可以用assign語句、實例化元件、always塊語句、initial塊等語句來實現。

1)用assign語句實現

這種方式很簡單,只要在assign后面加一個賦值語句即可。assign語句一般適合對組合邏輯進行描述,稱為連續賦值方式。

例如,描述一個兩輸入的與門可寫為

assigna=b&c;

2)用實例元件實現

用實例化元件實現就是利用VerilogHDL提供的元件庫來實現一個邏輯關系。

例如,用實例化元件表示一個兩輸入的與門可以寫為

andu1(q,a,b);

其中,and是VerilogHDL元件庫中與門的元件名;u1是實例化后的與門名稱;q是與門的輸出;a、b是與門的輸入端。要求模塊中每個實例化后的元件名稱必須是唯一的。

3)用always塊實現

always塊語句可以實現各種邏輯,常用于組合和時序邏輯的功能描述。一個程序設計模塊中可以包含一個或多個always塊語句。程序運行中,在某些條件滿足時,就重復執行always塊中的語句。

例如,表示一個帶有異步清除端的D觸發器可寫為

always@(posedgeclkorposedgeclr)

begin

if(clr)q<=0;

elseq<=d;

end

4)用initial塊實現

initial塊語句與always塊語句類似,不過在程序中initial塊語句只被執行一次,常用于電路的初始化。3.2.1常量

在程序運行過程中,其值不能改變的量稱為常量。在VerilogHDL中有三類常量:整型、實型和字符串型。

1.整型常量

在VerilogHDL中,整型常量的表示格式為

<位寬>′<進制><數值>3.2VerilogHDL的數據類型位寬:位寬是對應的二進制寬度。當定義的位寬比常數實際的位寬大時,在常數的左邊自動填補0,但如果常數的最左邊一位是x或z時,那么就在左邊自動填補x或z;當定義的位寬比常數實際的長度小時,在最左邊的相應位就被截斷。

進制:整型數有四種進制形式:

(1)二進制(b或B)。

(2)十進制(d或D)。

(3)八進制(o或Q)。

(4)十六進制(h或H)。數值:二進制數值可以用下列四種基本的值來表示:

(1)0:邏輯0或“假”。

(2)1:邏輯1或“真”。

(3)x:未知。

(4)z:高阻。

這四種值的解釋都內置于語言中,如一個為0的值是指邏輯0,一個為1的值是指邏輯1,一個為z的值是指高阻抗,一個為x的值是指邏輯不定值。x值和z值都是不區分大小寫的。例如:

6′B10X1Z0//6位二進制數,從低位數起第2位為高阻,第4位為不定值

5′O37

//5位八進制數

4′D98

//4位十進制數

7′H1A

//7位十六進制數

8′h4Z

//8位十六進制值,即0100zzzz

-8′D76

//8位十進制值,即-76,符號必須寫在最前邊另外,整型常量還有兩種表示方式,其格式為

′<進制><數值>

<數值>

在不指定位寬時,缺省位寬由機器系統決定,但至少為32位;如果數值中既無位寬,也無進制,則缺省為十進制數。例如:

′O35//位寬為32位的八進制數

′H67//位寬為32位的十六進制數

92

//十進制數92

-100//十進制數-100

2.實型常量

實型數可以用十進制計數法和科學計數法兩種格式表示。在表示小數時,小數點兩邊必須都有數字,否則為非法的表示形式。

例如:

7.56//十進制數計數法

4.

//非法表示,小數點后應有數字

34.56e2//科學計數法,其值為3456(e與E相同)

6E-2//科學計數法,其值為0.06

3.字符串型常量

字符串是用雙引號括起來的字符序列,它必須寫在同一行,不能分行書寫。字符串中的每個字符都是以其ASCII碼進行存放的,一個字符串可以看做是8位的ASCII碼值序列。

例如:

″hello!″//按字母順序存放,每個字母為8位ASCII碼

另外,還存在一些特殊字符,這些特殊字符又稱轉義字符,用“\”來說明。常用的特殊字符的表示及含義如表3.2.1所示。表3.2.1特殊字符的表示及含義

4.參數常量

在VerilogHDL中用parameter來定義常量,即用parameter定義一個標識符代表一個常量,稱為參數常量或符號常量,這樣可以增加程序的可讀性和可維護性。

參數常量定義格式如下:

parameter標識符1=表達式1,標識符2=表達式2,…,標識符n=表達式n;

例如:

parameterPI=3.14,A=8′B10110101,WORD_LENGTH=16;3.2.2變量

在程序運行過程中,其值可以改變的量稱為變量。在VerilogHDL中,變量的數據類型很多,這里只對常用的幾種變量類型進行介紹。

1.wire型

wire是網絡數據類型之一,表示結構實體之間的物理連接。網絡類型的變量不僅不能儲存值,而且必須受到驅動器的驅動。如果沒有驅動器連接到網絡型的變量上,那么其值為高阻值。網絡型數據有很多種,但最常用的是wire型。

wire型變量常用來表示以assign語句生成的組合邏輯信號,輸入/輸出信號在默認情況下自動定義為wire型。wire型信號可作為任何語句中的輸入,也可作為assign語句和實例化元件的輸出。

wire型變量的定義格式如下:

wire[msb:lsb]變量1,變量2,…,變量n;

其中,wire是定義符;[msb:lsb]中的msb和lsb分別表示wire型變量的最高位和最低位的編號,位寬由msb和lsb確定,如果不指定位寬,那么位寬自動默認為1;定義多個變量時,變量之間用逗號隔開。例如:

wirea,b;//定義了兩個1位wire型變量a、b

wire[7:0]m,n;//定義了兩個8位wire型變量m、n,最低位為第0位,最高位為第7位

wire[8:1]x,y;//定義了兩個8位wire型變量x、y,最低位為第1位,最高位為第8位

2.reg型

reg是寄存器類型,是數據存儲單元的抽象,其對應的是具有狀態保持功能的電路元件,如觸發器、鎖存器等。

reg型變量只能在always和initial塊中被賦值,通過賦值語句改變reg型變量的值,若reg型變量未被初始化,則其值為未知值x。reg型變量與wire型變量的區別是:wire型變量需要持續地驅動,而reg型變量保持最后一次的賦值。

reg型變量的定義格式如下:

reg[msb:lsb]變量1,變量2,…,變量n;

其中,reg是定義符;[msb:lsb]中的msb和lsb分別表示reg型變量的最高位和最低位的編號,位寬由msb和lsb確定,如果不指定位寬,則自動默認為1。例如:

regx0,y0;//定義了兩個1位reg型變量x0、y0

reg[7:0]d,q;//定義了兩個8位reg型變量d、q,最低位為第0位,最高位為第7位

reg[8:1]sum;//定義了一個8位reg型變量sum,最低位為第1位,最高位為第8位

3.memory型

memory型是存儲器型,是通過建立reg型數組來描述的,可以描述RAM存儲器、ROM存儲器和reg文件。

memory型變量的定義格式如下:

reg[msb:lsb]存儲單元1[n1:m1],存儲單元2[n2:m2],…,存儲單元i[ni:mi];

其中,[n1:m1],[n2:m2],…,[ni:mi]分別表示存儲單元的編號范圍。例如:

regmemory1[1023:0];//存儲器為1024個單元,每個單元為1位

reg[7:0]memory2[15:0];//存儲器為16個單元,每個單元為8位

reg[32:1]memory2[1:512];//存儲器為512個單元,每個單元為32位

值得注意的是,對存儲單元的訪問可以通過數組的索引進行。例如,以下語句分別用于定義4個存儲單元,每個單元為8位,單元編號為0~3,然后給每個存儲單元賦值。

reg[8:1]RAM[3:0];

RAM[0]=8′H1A;

RAM[1]=8′H00;

RAM[2]=8′H55;

RAM[3]=8′H31;

4.integer型

integer型是32位帶符號整型變量,用于對循環控制變量的說明,典型應用是高層次的行為建模,它與后面的time和real類型一樣是不可綜合的。也就是說,這些類型是純數學的抽象描述,不與任何物理電路相對應。

integer型變量的定義格式如下:

integer變量1,變量2,…,變量n;例如:

integeri,j;//定義了兩個整型變量i,j

integerd[1:8];//定義了一個含有8個數據的整型數組

5.time型

time類型用于存儲和處理時間,是64位無符號數。

time型變量的定義格式如下:

time變量1,變量2,…,變量n;

6.real型

real型是64位帶符號實型變量,用于存儲和處理實型數據。

real型變量的定義格式如下:

real變量1,變量2,…,變量n;1.算術運算符

算術運算符包括:

+(加法運算符或正值運算符,如x+y,+8)

-(減法運算符或負值運算符,如x-y,-90)

*(乘法運算符,如x*y)

/(除法運算符,如x/y)

%(取模運算符,如x%y)3.3VerilogHDL的運算符

2.邏輯運算符

邏輯運算符包括:

&&(邏輯與)

||(邏輯或)

!(邏輯非)

邏輯運算符操作的結果為0(假)或1(真)。例如,假設:

a=′b0;//0為假

b=′b1;//1為真

那么:

A&&b結果為0(假)

a||b結果為1(真)

!a結果為1(真)

!b結果為0(假)在判斷一個數是否為真時,以0代表“假”,以非0代表“真”。

例如,假設:

ABus=′b0111;

BBus=′b0101;

那么:

ABus||BBus結果為1(真)

ABus&&BBus結果為1(真)

!ABus結果為0(假)

3.關系運算符

關系運算符包括:

<

(小于)

<=

(小于等于)

>

(大于)

>=

(大于等于)

關系運算符是用來確定指定的兩個操作數之間的關系是否成立的,如果成立,結果為1(真);如果不成立,結果為0(假)。例如,假設:

m=19;

n=5;

那么:

m>n結果為1(真)

a>=b結果為1(真)

m<n結果為0(假)

a<=b結果為0(假)

4.等值運算符

等值運算符包括:

==(邏輯相等)

!=(邏輯不等)

===(全等)

!==(非全等)“==”運算符稱為邏輯相等運算符,而“===”稱為全等運算符,兩個運算符都是比較兩個數是否相等的。如果兩個操作數相等,那么運算結果為邏輯值1;如果兩個操作數不相等,那么運算結果為邏輯0。不同的是由于操作數中的某些位可能存在不定值x或高阻值z,這時邏輯相等在進行比較時,結果為不定值x,而全等運算符是按位進行比較的,對這些不定位或高阻位也進行比較,只要兩個操作數完全一致,則結果為1(真),否則結果為0。

與“==”和“===”相同,“!=”的運算結果可能為1、0或x,而“!==”的運算結果只有兩種狀態,即1或0。例如,假設:

d1=4′b010x;

d2=4′b010x;

那么:

d1==d2結果為x

d1===d2結果為1

5.位運算符

位運算符包括:

~

(非)

&

(與)

~&

(與非)

|

(或)

~|

(或非)

^

(異或)

^~或~^(同或)位運算符是對兩個操作數按位進行邏輯運算的。當兩個操作數的位數不同時,自動在位數較少的操作數的高位補0。

例如,假設:

x=8′b01011111;

y=4′b1100;

那么:

x&y=8′b00001100

x|y=8′b01011111

~x=8′b10100000

~y=4′b0011

x~&y=8′b11110011

x~|y=8′b10100000

x^y=8′b01010011

x^~y=8′b10101100

6.縮減運算符

縮減運算符包括:

&

(與)

~&

(與非)

|

(或)

~|

(或非)

^

(異或)

^~

(同或)

縮減運算符與邏輯運算符的法則一樣,但縮減運算符是對單個操作數按位進行邏輯遞推運算的,運算結果為1位二進制數。例如:

reg[7:0]a;

regb

b=&a;

程序中,“b=&a;”語句與“b=a[0]&a[1]&a[2]&a[3]&a[4]&a[5]&a[6]&a7];”語句等價。

7.移位運算符

移位運算符包括:

<<(左移)

>>(右移)

左移和右移運算符是對操作數進行邏輯移位操作的,空位用0進行填補。

移位運算的格式為

a<<n或a>>n

其中,a為操作數;n為移位的次數。例如,假設:

i=8;

m=3

那么:

i<<m結果為64

i>>m結果為1

8.條件運算符

條件運算符是:

?:

條件運算符是唯一的一個三目運算符,即條件運算符需要三個操作數。

條件運算符格式如下:

條件?表達式1:表達式2

條件表達式的含義是:如果條件為真,則結果為表達式1的值;如果條件為假,則結果為表達式2的值。例如:

a=10,b=20;

y=a>b?a:b;

由于a>b條件為假,因此,y的值為b的值。

9.拼接運算符

拼接運算符是:

{}

拼接運算符用來將兩個或多個數據的某些位拼接起來。

拼接運算符格式如下:

{數據1的某些位,數據2的某些位,…,數據n的某些位}

例如:

X={a[7:4],b[3],c[2:0]}

表示X是由a的第7~4位、b的第3位和c的第2~0位拼接而成的。

10.運算符的優先級

在一個表達式中出現多種運算符時,其運算的優先級順序如表3.3.1所示。表3.3.1運算符的運算優先級3.4.1賦值語句

在VerilogHDL中,賦值語句有兩種:連續賦值語句和過程賦值語句。

1.連續賦值語句

連續賦值語句用來驅動wire型變量,這一變量必須事先定義過。使用連續賦值語句時,只要輸入端操作數的值發生變化,該語句就重新計算并刷新賦值結果。連續賦值語句用來描述組合邏輯。3.4VerilogHDL的基本語句連續賦值語句格式如下:

assign#(延時量)wire型變量名=賦值表達式;

語句的含義是:只要右邊賦值表達式中有變量發生變化,就重新計算表達式的值,新結果在指定的延時時間單位以后賦值給wire型變量。如果不指定延時量,則延時量默認為0。

例如,下面語句表示只要a或b發生變化,就重新計算a和b相與的值,計算結果賦值給c。

wirea,b,c;

assignc=a&b;

2.過程賦值語句

過程賦值語句是在initial或always語句塊內賦值的,它用于對reg型、memory型、integer型、time型和real型變量賦值,這些變量在下一次過程賦值之前保持原來的值。過程賦值語句分為兩類,分別為阻塞賦值和非阻塞賦值。

1)阻塞賦值

阻塞賦值的賦值符為“=”,它在該語句結束時就完成賦值操作。

阻塞賦值格式如下:

變量=賦值表達式;

2)非阻塞賦值

非阻塞賦值的賦值符為“<=”,它在塊結束時才完成賦值操作。

非阻塞賦值格式如下:

變量<=賦值表達式;

過程中使用阻塞賦值與非阻塞賦值的主要區別是:一條阻塞賦值語句執行時,下一條語句被阻塞,即只有當一條語句執行結束,下條語句才能執行;非阻塞賦值語句中,各條語句是同時執行的。也可以理解為,阻塞賦值是串行執行的,非阻塞賦值是并行執行的。為了理解這兩種賦值,下面分析兩段程序的執行過程。程序段1:

begin

r1=2;

r2=r1;

r3=r2;

end

程序段2:

begin

r1<=2;

r2<=r1;

r3<=r2;

end3.4.2條件語句

1.if…else語句

if語句是用來判斷給定的條件是否滿足,根據判定的結果為真或假決定執行的操作。

VerilogHDL語言提供了三種形式的if語句。

1)if(表達式)語句

例如:

if(x>y)q=x;

2)if(表達式)語句1else語句2

例如:

if(Reset)

Q=0;

else

Q=D;

3)if(表達式1)語句1

elseif(表達式2)語句2

elseif(表達式3)語句3

elseif(表達式m)語句m

else語句n

例如:

if(x>y)Q=in1;

if(x==y)Q=in2;

else

Q=in3;

2.case語句

case語句是一種多分支語句,if語句每次只能有兩個分支可供選擇,而實際應用中常常需要多分支選擇,VerilogHDL語言中的case語句可以直接處理多分支選擇。

case語句格式如下:

case(控制表達式)

分支項表達式1:語句1

分支項表達式2:語句2

分支項表達式m:語句m

default:語句n

endcase

case語句首先對控制表達式求值,然后依次對各分支項表達式求值并進行比較,遇到第一個與控制表達式值相匹配分支中的語句被執行。一個case結構中可以有多個分支,但這些值必須互斥。缺省分支覆蓋所有沒有被分支表達式覆蓋的其他分支。

分支表達式和各分支項表達式不必都是常量表達式。在case語句中,x值和z值作為文字值進行比較。例如,下面case結構表示的是一個3:8譯碼器的程序。

moduleseg(SW,Q);

input[2:0]SW;//SW為3位輸入端口

output[7:0]Q;//Q為3:8譯碼器的8個輸出端口

reg[7:0]Q;

always@(SW)//SW中有狀態改變時,執行case結構的語句

begin

case(SW)

3′b000:Q=8′b11111110;

3′b001:Q=8′b11111101;

3′b010:Q=8′b11111011;

3′b011:Q=8′b11110111;

3′b100:Q=8′b11101111;

3′b101:Q=8′b11011111;

3′b110:Q=8′b10111111;

3′b111:Q=8′b01111111;

endcase

end

endmodule3.4.3循環語句

VerilogHDL中有四類循環語句,它們是:

(1)forever循環。

(2)repeat循環。

(3)while循環。

(4)for循環。

1.forever循環語句

forever循環語句用于連續執行過程,其格式如下:

forever語句

forever循環語句常用于產生周期性的波形。它與always語句不同之處在于它不能獨立寫在程序中,而必須寫在initial塊中。例如:

initial

begin

clock=0;

#5forever

#10clock=~clock;

end

2.repeat循環語句

repeat循環語句是用于執行指定循環次數的過程語句,其格式如下:

repeat(表達式)語句

repeat循環語句中的表達式通常為常量表達式,表示循環的次數。如果循環計數表達式的值不確定,即為x或z時,那么循環次數按0處理。例如,下面是用repeat語句完成算式S=1+2+3+4+…+100的程序。

initial

begin

s=0;

i=1;

repeat(100)

begin

s=s+i;

i=i+1

end

end

3.while循環語句

while循環執行過程賦值語句直到指定的條件為假,其格式如下:

while(條件)語句

執行while時,先對條件進行判斷,如果條件為真,那么執行該語句;如果條件為假,那么退出循環;如果條件在開始時就為假,那么就不執行該語句;如果條件為x或z,那么按0(假)處理。

例如,下面是用while語句完成對定義的256個存儲單元初始化的程序段。

reg[7:0]memory[0:255];

initial

begin

reg[7:0]i;

i=0;

while(i<=255)

memory[i]=0;

i=i+1

end

4.for循環語句

for循環語句按照指定的次數重復執行過程賦值語句若干次,其格式如下:

for(初值表達式;條件;循環變量增值)語句

for循環的執行過程為

(1)計算初值表達式。

(2)進行條件判斷,若條件為真,繼續第(3)步;若條件為假,則轉到第(5)步。

(3)執行過程語句,對循環變量進行增值。

(4)轉回第(2)步繼續執行。

(5)執行for循環下面的語句。例如,下面是用for語句、加法語句和移位語句實現x×y的程序。

reg[15:0]x,;

reg[31:0]s;

initial

begin

reg[3:0]i;

s=0;

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

if(y[i])s=s+(x<<i);

end3.4.4結構聲明語句

VerilogHDL中任何過程模塊都從屬于四種結構說明語句:

initial說明語句、always說明語句、task說明語句和function說明語句。

1.initial說明語句

initial語句常用于對各變量的初始化。一個程序模塊中可以有多個initial語句,所有initial語句在程序一開始時同時執行,并且只執行一次。

initial語句格式如下:

initial語句例如:

initial

begin

reset=1;

#3reset=0;

#5reset=1;

end

2.always說明語句

與initial語句一樣,一個程序中可以有多個always語句,always語句也是在程序一開始時立即被執行的,不同的是always語句不斷地重復運行。但always語句后跟的語句是否執行要看其敏感事件列表是否滿足,若有條件滿足,則運行一次語句。

always語句格式如下:

always@(敏感事件列表)語句

always語句后面是一個敏感事件列表,該敏感事件列表的作用是激活always語句執行的條件,敏感事件可以是電平觸發,也可以是邊沿觸發。電平觸發的always塊常用于描述組合邏輯的行為,而邊沿觸發的always塊常用于描述時序行為。

always語句后面的敏感事件可以是單個事件,也可以是多個事件,多個事件之間用or連接。在敏感事件列表中,如果敏感事件是電平信號,那么直接列出信號名;如果敏感事件是邊沿信號,那么可分為上升沿和下降沿,上升沿觸發的信號前加關鍵字posedge,下降沿觸發的信號前加關鍵字negedge。例如,用clk的上升沿使count加1的程序為

reg[7:0]count

always@(posedgeclk)

begin

count=count+1b′1;

end

如果要用clk的下降沿使count加1,只需將程序中的敏感事件改為negedgeclk即可。例如,一個電平敏感型鎖存器的程序如下:

modulelatch(enable,date,q)

inputenable;

input[7:0]data;

output[7:0]q;

reg[7:0]q;

always@(enableordata)

begin

if(enable)

q<=data;

end

3.task說明語句

1)任務定義語句

任務定義語句的格式如下:

task任務名;

端口聲明語句;

類型聲明語句;

語句

endtask

2)任務的調用

任務調用的格式如下:

任務名(端口名列表);

例如,在運算器中,經常用到加法運算,加法運算有8位加法、16位加法、32位加法等,16位加法和32位加法又可以用8位加法器實現。這樣就可以定義一個任務實現8位加法運算,而16位加法和32位加法通過多次調用8位加法運算的任務來實現。

下面代碼中,定義了一個任務adder8完成8位二進制數加法運算,通過在always塊中兩次調用任務adder8實現了16位數a和b的加法運算,相加結果存放在sum中,進位存放在cout中。

moduleadd16(a,b,cin,sum,cout);

input[15:0]a,b;

inputcin;

output[15:0]sum;

outputcout;

reg[15:0]sum;

regcout;

regc8;

always@(aorborcin)

begin

adder8(a[7:0],b[7:0],cin,sum[7:0],c8);

adder8(a[15:8],b[15:8],c8,sum[15:8],cout);

end

taskadder8;

input[7:0]ta,tb;

inputtcin;

output[7:0]tsum;

outputtcout;

begin

{tcout,tsum}=ta+tb+tcin;

end

endtask

endmodule使用任務時,需要注意以下幾點:

(1)任務的定義和調用必須在同一個模塊內。任務定義不能出現在任何一個過程塊內部,任務的調用應在always塊、initial塊或另一個任務中。

(2)任務定義時,task語句后沒有端口名列表,輸入輸出端口名是通過端口聲明語句進行順序聲明的;一個任務也可以沒有輸入輸出端口。

(3)當任務被調用時,任務被激活。如果一個任務有輸入輸出端口,調用時需列出端口名列表,其順序和類型應與任務定義中完全一致。

(4)進行任務調用時,參數的傳遞是按值傳遞的,不能按址傳遞。

(5)一個任務可以調用別的任務或函數,可調用的任務和函數的個數不受限制。

4.function說明語句

function說明語句用來定義函數。函數類似高級語言中的函數,用來單獨完成某項具體的操作。函數可以作為表達式中的一個操作數,也可被模塊、任務或其他函數調用,函數調用時有一個返回值。

1)函數語句定義

function定義格式如下:

function〈返回值的類型或范圍〉函數名

端口聲明語句;

類型聲明語句;

語句

endfunction

2)函數的調用

function函數的調用格式如下:

函數名(端口名列表);

函數與任務一樣,也是用來完成一個獨立的任務的,但函數與任務有以下不同點:

(1)函數只能有一個返回值,而任務卻可以有多個或沒有返回值。函數的返回值只是通過函數名返回的,而任務的返回值則是通過輸出端口傳遞的。

(2)函數至少有一個輸入變量,而任務可以沒有或有多個任何類型的變量。

(3)函數只能與主模塊共用一個仿真時間,而任務可以定義自己的仿真時間單位。

(4)函數不能調用任務,而任務能調用其他任務和函數。例如,下面程序是一個用function函數實現將兩位十六進制數轉換成對應的兩個共陽極七段LED顯示代碼的例子。其中,SW用于輸入兩位十六進制數,十六進制數要在七段LED上進行顯示,必須將其轉換成其對應的七段顯示代碼,hex0和hex1就是分別用來輸出的對應的七段共陰極LED顯示代碼。moduledisplay(SW,hex0,hex1);

input[7:0]SW;

output[6:0]hex0;

reg[6:0]hex0;

output[6:0]hex1;

reg[6:0]hex1;

always@(SW)

begin

hex0=seg_7(SW[3:0]);

hex1=seg_7(SW[7:4]);

end

function[6:0]seg_7;

input[3:0]num;

case(num)

4′h1:seg_7=7′b1111001;

4′h2:seg_7=7′b0100100;

4′h3:seg_7=7′b0110000;

4′h4:seg_7=7′b0011001;

4′h5:seg_7=7′b0010010;

4′h6:seg_7=7′b0000010;

4′h7:seg_7=7′b1111000;

4′h8:seg_7=7′b0000000; 4′h9:seg_7=7′b0011000;

4′ha:seg_7=7′b0001000;

4′hb:seg_7=7′b0000011;

4′hc:seg_7=7′b1000110;

4′hd:seg_7=7′b0100001;

4′he:seg_7=7′b0000110;

4′hf:seg_7=7′b0001110;

4′h0:seg_7=7′b1000000;

endcase

endfunction

endmodule3.4.5編譯預處理語句

1.宏定義(′define和′undef)

′define指令是用一個標識符代替一個字符串,其定義格式如下:

′define宏名字符串

例如:

′defineWORDSIZE16

reg[′WORDSIZE-1:0]data1;//相當于reg[15:0]data1;對于宏的定義應注意以下幾點:

(1)宏名可以用小寫字母,也可以用大寫字母,為了與變量名區別,建議使用大寫字母。

(2)宏定義語句后不跟分號,如果加了分號,則連同分號一起進行置換。

(3)宏定義語句可以在模塊內,也可以在模塊外。

(4)在引用宏時,必須在宏名前加符號“′”。宏定義將在整個文件內起作用,若要取消宏前面定義的宏,則用′undef指令。

例如:

′defineBYTE8

wire[′BYTE-1:0]bus;//相當于wire[7:0]bus;

′undefBYTE//在′undef后,BYTE的宏定義不再有效

2.文件包含(′include)

′include語句用來實現文件的包含操作,它可以將一個源文件包含到本文件中。其語句格式為

′include″文件名″

例如:

′include″d:\eda\s1.v″

編譯時,這一行由d:\eda\s1.v文件中的內容替代。

3.時間尺度(′timescale)

在VerilogHDL模型中,所有時延都用單位時間表述。使用′timescale預編譯指令將時間單位與實際時間相關聯。該指令用于定義時間單位和時間精度。

′timescale預編譯指令格式為

′timescale時間單位/時間精度其中,時間單位用來定義模塊中仿真時間的基準單位,時間精度用來聲明模塊仿真時間的精確程度,該參數用于對時間值進行取整操作。時間單位和時間精度由值1、10和100以及單位s、ms、μs、ns、ps和fs組成。例如:

′timescale1ns/100ps

表示時延單位為1ns,時延精度為100ps。′timescale編譯指令在模塊說明外部出現,并且影響后面所有的時延值。例如:

′timescale10ns/100ps

always#1.55clock=~clock;

′timescale語句表示模塊中的時間值均為10ns的整數倍,延時時間的最小分辨率為十分之一納秒(100ps),即延時時間可表示為帶一位小數的實型數。這樣,根據時間精度,1.55取整為1.6,那么,clock變反的時間間隔為16ns。在編譯過程中,′timescale指令影響這一編譯指令后面所有模塊中的時延值,直至遇到另一個′timescale指令。當一個設計中的多個模塊帶有自身的′timescale編譯指令時,則用最小的時間精度來決定仿真時間單位。例如:

′timescale1ns/100ps

moduleAndFunc(Z,A,B);

outputZ;

inputA,B;

and#5.22Al(Z,A,B);

endmodule

′timescale10ns/1ns

moduleTB;

regPutA;

initial

begin

PutA=0;

#5.21PutA=1;

#10.4PutA=0;

end

endmodule在這個例子中,每個模塊都有自身的′timescale編譯指令。在第一個模塊中,5.22對應5.2ns;在第二個模塊中,5.21對應52ns,10.4對應104ns。如果仿真模塊TB,那么設計中的所有模塊最小時間精度為100ps,因此,所有延遲將換算成精度為100ps,延遲52ns現在對應520*100ps,104對應1040*100ps。更重要的是,仿真使用100ps為時間精度。若仿真模塊AndFunc,則由于模塊TB不是模塊AddFunc的子模塊,因此模塊TB中的′timescale程序指令將不再有效。

4.條件編譯(′ifdef、′else、′endif)

一般情況下,源程序中的所有語句行都參加編譯。但是有時希望其中一部分語句只在條件滿足時才進行編譯,條件不滿足時不編譯這些語句,或者編譯另外一組語句,這就是條件編譯。條件編譯語句格式如下:

′ifdefCOMPUTER-PC

parameterWORD_SIZE=16

′else

parameterWORD_SIZE=32

′endif在實際的應用系統設計時,如果將所有功能用一個模塊完成,會造成模塊設計復雜,可讀性差。為了便于設計,可以將一個大的系統分層次、分模塊進行設計,

溫馨提示

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

評論

0/150

提交評論