當我們使用Verilog HDL代碼來描述硬件功能的時候,可採用三種不同方式或混合方式對設計進行建模,這些方式包括:結構化方式—使用門和模塊實例語句描述建模;數據流方式—使用連續賦值語句方式建模;行爲描述方式—使用過程化結構建模。
1. 結構化方式
1.1門級結構建模(內置門原語)
Verilog HDL 中有關門類型的關鍵字共有26個,下面列舉了8個基本的門類型(gatetype)關鍵字和它們所代表門的類型:
and——與門;
nand——與非門;
nor——或非門;
or——或非門;
xor——異或門;
xnor——異或非門;
buf——緩衝器;
not——非門;
門與開關的說明語法可以用標準的聲明語句格式和一個簡單的實例引用加以說明。
門聲明語句格式如下:
<門的類型> [<驅動能力><延時>] <門實例1>[,<門實例2>,……,<門實例n>];
nand #10 nd1(a,data,clock,clear);
門的類型是門聲明語句所必須的,它可以是Verilog HDL 語法規定的26種門類型中的任意一種。上述該例說明在模塊中聲明瞭nand與非門語句。
驅動能力和延時是可選項,可根據不同的情況選不同的值或不選。上述該例中#10說明輸出與輸入延時了10個單位時間。
<門實例1>是在本模塊中引用的第一個這種類型的門,而<門實例n>是引用的第n個這種類型的門。上述該例在模塊中使用了一個名爲nd1的與非門,輸入爲data,clock和clear,輸出爲a。(在聲明門實例時可能編譯會報錯。)
邏輯圖:
模塊代碼示例(1位全加器對應上述邏輯圖):
module FA_Str(A,B,Cin,Sum,Cout);
input A,B,Cin;
output Sum,Cout;
/*門實例由線網類型變量S1,T1,T2和T3互連*/
wire S1,T1,T2,T3;
/*由於沒有指定順序,門實例語句可以以任何順序出現*/
/*X1,X2,A1等都是實例名稱,緊跟在每個門後的信號列表是它的互連*/
/*列表中的第一個是門的輸出,餘下的是輸入*/
xor
X1(S1,A,B), //注意結束時用逗號,最後才用分號
X2(Sum,S1,Cin); //表示X1和X2都是xor異或門
and
A1(T3,A,B),
A2(T2,B,Cin),
A3(T1,A,Cin);
or
O1(Count,T1,T2,T3);
endmodule
在這個結構描述的模塊中,FA_Str定義了模塊名,設計上層模塊時可以用模塊名(FA_Str)調用這個模塊。
由已經設計成的模塊構成更高一層的模塊
如果已經編制了一個模塊,如上例中的FA_Str,可以在另外的模塊中引用這個模塊,引用的方法與門類型的實例引用非常類似,只須在前面寫上已編的模塊名,緊跟着寫上引用的實例名,按順序寫上實例的端口名即可,也可以用已編模塊的端口名按對應原則逐一填入,詳見以下兩種語句:(注意在FA_Str1實例中端口已經申明,只須將對應信號的連接點註明)
(1)FA_Str FA_Str1(FA[1],FB[1],FTemp[1],FSum[1],FCount[1]);
(2)FA_Str FA_Str1(.B(FB[1]),.A(FA[1]),.Cin(FCin),.Sum(FSum[1]),.Count(FTemp[2]))
這兩條語句都表示實例FA_Str1引用已編模塊FA_Str,也可以將FA_Str實例化了FA_Str1。從上面兩條語句可以看出在引用實例時,FA_Str1的端口信號與FA_Str的端口對應有兩種不同的表示方法,即模塊實例化的端口名可以有序排列,也可以不必按序排列,如果模塊的端口名按序排列,只須按序列出實例的端口名(見語句1),如果不按序排列,則實例的端口信號和被引用模塊的端口信號必須一一列出。(見語句2)
邏輯圖
模塊代碼實例(4位全加器對應上面邏輯圖)
/*四位全加器使用4個1位全加器模塊描述*/
module FourBitFA(FA,FB,FCin,FSum,FCout);
parameter SIZE = 4;
input [SIZE:1] FA,FB;
output [SIZE:1] FSum;
input FCin;
input FCout;
wire [1:SIZE-1] FTemp;
/*在模塊實例語句中,端口可以與名稱或位置關聯*/
FA_Str
/*FA1和FA2使用命名關聯方式,也就是說端口的名稱和它
連接的線網被顯示描述(每一個的形式都爲“.port_name(net_name)”)*/
/*如果不需要FA_Str端口的的某個端口,可以在FA1和FA2端口中省去,
即可以在FA1和FA2中不出現某端口*/
FA1(.A(FA[1]),.B(FB[1]),.Cin(FCin),.Sum(FSum[1]),.Cout(FTemp[2])),
FA2(.A(FA[2]),.B(FB[2]),.Cin(FTemp[1]),.Sum(FSum[2]),.Cout(FTemp[2])),
/*FA3和FA4使用位置關聯方式將端口與線網關聯,這裏的關聯順序很重要,
必須一一對應,例如在實例FA4中,第一個FA[4]與FA_Str的端口A連接,
第二個FB[4]與FA_Str的端口B連接,餘下的一一對應,由此類推。*/
/*如果不需要FA_Str端口的的某個端口,可以在FA3和FA4端口中省去,但逗號依然保留。
如,FA3(FA[3],FB[3],,FSum[3],FTemp[3])*/
FA3(FA[3],FB[3],FTemp[2],FSum[3],FTemp[3]),
FA4(FA[4],FB[4],FTemp[3],FSum[4],FCout);
endmodule
顯而易見,通過模塊實例引用,可以構成任何複雜結構的電路。這種以結構方式所建立的Verilog模型不僅可以仿真,也是可以綜合的,其本質表示電路的具體結構,也就是說,這種Verilog文件也是一種結構網表。
1.2開關級結構建模
通過調用Verilog HDL內部的基本開關元件來對硬件電路的結構進行說明,這種情況下的模塊由基本的開關級元件實例組成,這種抽象程度更低,基本不用掌握。
nmos 實例名(out,data,ctrl);
pmos 實例名(out,data,ctrl);
supply1 vdd;源極(邏輯1)
supply0 vdd;地級(邏輯0);
1.3用戶定義的原語(UDP)
and,or,not等邏輯門是Verilog HDL 自帶的內建語法,對這些門的描述是以原語的形式在Verilog HDL中定義的,即內置原語。
在實際設計中,有時會需要使用自己編寫的原語,這種原語就是用戶自定義原語(User Defined Primitive ,UDP),也就是說可以利用UDP來定義自己用於仿真的基本邏輯元件模塊並建立相應的原語庫,這樣就可以與調用Verilog HDL基本邏輯元件一樣的方法來調用原語庫中的相應元件模塊,並進行仿真。
與一般的用戶模塊相比,UDP更爲基本,它只能簡單描述簡單的能用真值表表示的組合或時序邏輯。UDP模塊結構與一般模塊類似,只是不用module而改用primitive關鍵詞開始,以endprimitive關鍵詞結束。
定義UDP語法
primitive 元件名(輸出端口名,輸入端口名1,輸入端口名2……)
output 輸出端口名;
input 輸入端口名1,輸入端口名2,……;
reg 輸出端口名;
initial begin
輸出端口寄存器或時序邏輯內部寄存器賦初值(0,1或X);
end
//這兩行在時序UDP中使用
table
//輸入1 輸入2 輸入3 …… : 輸出
邏輯值 邏輯值 邏輯值 …… : 邏輯值;
邏輯值 邏輯值 邏輯值 …… : 邏輯值;
邏輯值 邏輯值 邏輯值 …… : 邏輯值;
…… …… …… …… : ……;
endtable
endprimitive
注意點
(1) UDP只能有一個輸出端,而且必定是端口說明列表的第一項。
Output a,b;//多個輸出違法
(2) UDP可以有多個輸入端,最多允許有10個輸入端。
Input d3,d2,d2,d0;//合法
(3) UDP所有端口變量必須是標量,也就是必須是1位的。
Output [1:0] c;//多位輸出違法
Input [3:0] d;//多位輸入違法
(4) 時序電路的UDP需要保存狀態,所以時序電路UDP的輸出端口要聲明爲reg類型,且只有輸出端纔可以被定義成reg型變量。
(5) Initial語句用於爲時序電路內部寄存器賦初值,該語句可選,且只允許賦0,1,X3種邏輯值,默認值爲X。
(6) UDP與module同級別,所以模塊內部不能定義UDP,但可以在模塊內調用已定義的UDP,語法與門級調用完全相同。
(7) UDP的真值表項可以處理0,1,X值,不能處理Z值,本身UDP不能輸出Z值,輸入給UDP的Z值會被當做X值來處理。
(8) UDP中不能使用inout端口。
二輸入與非門(UDP)
primitive nand_udp(Y,A,B);
output Y;
input A,B;
table
/*輸入信號1 輸入信號2 : 輸出信號;*/
/*A B : Y,輸入信號的順序一定和UDP端口列表中的輸入信號順序相同*/
0 0 : 1;
0 1 : 1;
1 0 : 1; //輸入和輸出之間以“:”分開隔開,每一行結束處以“;”結束。
1 1 : 0;
/*狀態表中要包含所有確定輸出的輸入情況,即做到 每種可以得到確定
輸出值的輸入都有對應的列表行與之相對應。*/
endtable
endprimitive