第二章 HDL指南
模塊
模塊是Verilog 的基本描述單位,用于描述某個(gè)設(shè)計(jì)的功能或結(jié)構(gòu)及其與其他模塊通信的外部端口。一個(gè)設(shè)計(jì)的結(jié)構(gòu)可使用開關(guān)級(jí)原語、門級(jí)原語和用戶定義的原語方式描述; 設(shè)計(jì)的數(shù)據(jù)流行為使用連續(xù)賦值語句進(jìn)行描述; 時(shí)序行為使用過程結(jié)構(gòu)描述。一個(gè)模塊可以在另一個(gè)模塊中使用。
一個(gè)模塊的基本語法如下:
module module_name (port_list);
Declarations:
reg, wire, parameter,
input, output, inout,
function, task, . . .
Statements:
Initial statement
Always statement
Module instantiation
Gate instantiation
UDP instantiation
Continuous assignment
endmodule
說明部分用于定義不同的項(xiàng),例如模塊描述中使用的寄存器和參數(shù)。語句定義設(shè)計(jì)的功能和結(jié)構(gòu)。說明部分和語句可以散布在模塊中的任何地方;但是變量、寄存器、線網(wǎng)和參數(shù)等的說明部分必須在使用前出現(xiàn)。為了使模塊描述清晰和具有良好的可讀性, 最好將所有的說明部分放在語句前。本書中的所有實(shí)例都遵守這一規(guī)范。
以下為建模一個(gè)半加器電路的模塊的簡(jiǎn)單實(shí)例。
module HalfAdder (A, B, Sum, Carry);
input A, B;
output Sum, Carry;
assign #2 Sum = A ^ B;
assign #5 Carry = A & B;
endmodule
模塊的名字是HalfAdder。 模塊有4個(gè)端口: 兩個(gè)輸入端口A和B,兩個(gè)輸出端口Sum和Carry。由于沒有定義端口的位數(shù), 所有端口大小都為1位;同時(shí), 由于沒有各端口的數(shù)據(jù)類型說明, 這四個(gè)端口都是線網(wǎng)數(shù)據(jù)類型。
模塊包含兩條描述半加器數(shù)據(jù)流行為的連續(xù)賦值語句。從這種意義上講,這些語句在模塊中出現(xiàn)的順序無關(guān)緊要,這些語句是并發(fā)的。每條語句的執(zhí)行順序依賴于發(fā)生在變量A和B上的事件。
在模塊中,可用下述方式描述一個(gè)設(shè)計(jì):
1) 數(shù)據(jù)流方式;
2) 行為方式;
3) 結(jié)構(gòu)方式;
4) 上述描述方式的混合。
下面幾節(jié)通過實(shí)例講述這些設(shè)計(jì)描述方式。不過有必要首先對(duì)Verilog HDL的時(shí)延作簡(jiǎn)要介紹。
時(shí)延
Verilog HDL模型中的所有時(shí)延都根據(jù)時(shí)間單位定義。 下面是帶時(shí)延的連續(xù)賦值語句實(shí)例。
assign #2 Sum = A ^ B;
#2指2個(gè)時(shí)間單位。
使用編譯指令將時(shí)間單位與物理時(shí)間相關(guān)聯(lián)。這樣的編譯器指令需在模塊描述前定義,如下所示:
` timescale 1ns /100ps
此語句說明時(shí)延時(shí)間單位為1ns并且時(shí)間精度為100ps (時(shí)間精度是指所有的時(shí)延必須被限定在0.1ns內(nèi))。 如果此編譯器指令所在的模塊包含上面的連續(xù)賦值語句, #2 代表2ns。
如果沒有這樣的編譯器指令, Verilog HDL 模擬器會(huì)指定一個(gè)缺省時(shí)間單位。IEEE Verilog HDL 標(biāo)準(zhǔn)中沒有規(guī)定缺省時(shí)間單位。
數(shù)據(jù)流描述方式
用數(shù)據(jù)流描述方式對(duì)一個(gè)設(shè)計(jì)建模的最基本的機(jī)制就是使用連續(xù)賦值語句。在連續(xù)賦值語句中,某個(gè)值被指派給線網(wǎng)變量。 連續(xù)賦值語句的語法為:
assign [delay] LHS_net = RHS_ expression;
右邊表達(dá)式使用的操作數(shù)無論何時(shí)發(fā)生變化, 右邊表達(dá)式都重新計(jì)算, 并且在指定的時(shí)延后變化值被賦予左邊表達(dá)式的線網(wǎng)變量。時(shí)延定義了右邊表達(dá)式操作數(shù)變化與賦值給左邊表達(dá)式之間的持續(xù)時(shí)間。如果沒有定義時(shí)延值, 缺省時(shí)延為0。
下面的例子顯示了使用數(shù)據(jù)流描述方式對(duì)2-4解碼器電路的建模的實(shí)例模型。
`timescale 1ns/ 1ns
module Decoder2x4 (A, B, EN, Z);
input A, B, EN;
output [ 0 :3] Z;
wire Abar, Bbar;
assign #1 Abar = ~ A; / / 語句 1。
assign #1 Bbar = ~ B; / / 語句 2。
assign #2 Z[0] = ~ (Abar & Bbar & EN) ; / / 語句 3。
assign #2 Z[1] = ~ (Abar & B & EN) ; / / 語句 4。
assign #2 Z[2] = ~ (A & Bbar & EN) ; / / 語句 5。
assign #2 Z[3] = ~ (A & B & EN) ; / / 語句 6。
endmodule
以反引號(hào)“ ` ”開始的第一條語句是編譯器指令, 編譯器指令`timescale 將模塊中所有時(shí)延的單位設(shè)置為1 ns,時(shí)間精度為1 ns。例如,在連續(xù)賦值語句中時(shí)延值#1和#2分別對(duì)應(yīng)時(shí)延1 ns和2 ns。
模塊Decoder2x4有3個(gè)輸入端口和1個(gè)4位輸出端口。線網(wǎng)類型說明了兩個(gè)連線型變量Abar和Bbar (連線類型是線網(wǎng)類型的一種)。此外,模塊包含6個(gè)連續(xù)賦值語句。
當(dāng)EN在第5 ns變化時(shí),語句3、4、5和6執(zhí)行。這是因?yàn)镋N是這些連續(xù)賦值語句中右邊表達(dá)式的操作數(shù)。Z[0]在第7 ns時(shí)被賦予新值0。當(dāng)A在第15 ns變化時(shí), 語句1、5和6執(zhí)行。執(zhí)行語句5和6不影響Z[0]和Z[1]的取值。執(zhí)行語句5導(dǎo)致Z[2]值在第17 ns變?yōu)?。執(zhí)行語句1導(dǎo)致Abar在第16 ns被重新賦值。由于Abar的改變,反過來又導(dǎo)致Z[0]值在第18 ns變?yōu)?。
請(qǐng)注意連續(xù)賦值語句是如何對(duì)電路的數(shù)據(jù)流行為建模的;這種建模方式是隱式而非顯式的建模方式。此外,連續(xù)賦值語句是并發(fā)執(zhí)行的,也就是說各語句的執(zhí)行順序與其在描述中出現(xiàn)的順序無關(guān)。
行為描述方式
設(shè)計(jì)的行為功能使用下述過程語句結(jié)構(gòu)描述:
1) initial語句:此語句只執(zhí)行一次。
2) always語句:此語句總是循環(huán)執(zhí)行, 或者說此語句重復(fù)執(zhí)行。
只有寄存器類型數(shù)據(jù)能夠在這兩種語句中被賦值。寄存器類型數(shù)據(jù)在被賦新值前保持原有值不變。所有的初始化語句和always語句在0時(shí)刻并發(fā)執(zhí)行。
下例為always語句對(duì)1位全加器電路建模的示例。
module FA_Seq (A, B, Cin, Sum, Cout);
input A, B, Cin;
output Sum, Cout;
reg Sum, Cout;
reg T1, T2, T3;
always
@ ( A or B or Cin ) begin
Sum = (A ^ B) ^ Cin;
T1 = A & Cin;
T2 = B & Cin;
T3 = A & B;
Cout = (T1| T2) | T3;
end
endmodule
模塊FA_Seq 有三個(gè)輸入和兩個(gè)輸出。由于Sum、Cout、T1、T2和T3在always 語句中被賦值,它們被說明為 reg 類型(reg 是寄存器數(shù)據(jù)類型的一種)。always 語句中有一個(gè)與事件控制(緊跟在字符@ 后面的表達(dá)式)。相關(guān)聯(lián)的順序過程(begin-end對(duì))。這意味著只要A、B或Cin 上發(fā)生事件,即A、B或Cin之一的值發(fā)生變化,順序過程就執(zhí)行。在順序過程中的語句順序執(zhí)行,并且在順序過程執(zhí)行結(jié)束后被掛起。順序過程執(zhí)行完成后,always 語句再次等待A、B或Cin上發(fā)生的事件。
在順序過程中出現(xiàn)的語句是過程賦值模塊化的實(shí)例。模塊化過程賦值在下一條語句執(zhí)行前完成執(zhí)行。過程賦值可以有一個(gè)可選的時(shí)延。
時(shí)延可以細(xì)分為兩種類型:
1) 語句間時(shí)延: 這是時(shí)延語句執(zhí)行的時(shí)延。
2) 語句內(nèi)時(shí)延: 這是右邊表達(dá)式數(shù)值計(jì)算與左邊表達(dá)式賦值間的時(shí)延。
下面是語句間時(shí)延的示例:
Sum = (A ^ B) ^ Cin;
#4 T1 = A & Cin;
在第二條語句中的時(shí)延規(guī)定賦值延遲4個(gè)時(shí)間單位執(zhí)行。就是說,在第一條語句執(zhí)行后等待4個(gè)時(shí)間單位,然后執(zhí)行第二條語句。下面是語句內(nèi)時(shí)延的示例。
Sum = #3 (A^ B) ^ Cin;
這個(gè)賦值中的時(shí)延意味著首先計(jì)算右邊表達(dá)式的值, 等待3個(gè)時(shí)間單位,然后賦值給Sum。
如果在過程賦值中未定義時(shí)延,缺省值為0時(shí)延,也就是說,賦值立即發(fā)生。這種形式以及在always 語句中指定語句的其他形式將在第8章中詳細(xì)討論。
下面是initial語句的示例:
`timescale 1ns / 1ns
module Test (Pop, Pid);
output Pop, Pid;
reg Pop, Pid;
initial
begin
Pop = 0; // 語句 1。
Pid = 0; // 語句 2。
Pop = #5 1; // 語句 3。
Pid = #3 1; // 語句 4。
Pop = #6 0; // 語句 5。
Pid = #2 0; // 語句 6。
end
endmodule
initial語句包含一個(gè)順序過程。這一順序過程在0 ns時(shí)開始執(zhí)行,并且在順序過程中所有語句全部執(zhí)行完畢后, initial語句永遠(yuǎn)掛起。這一順序過程包含帶有定義語句內(nèi)時(shí)延的分組過程賦值的實(shí)例。語句1和2在0 ns時(shí)執(zhí)行。第三條語句也在0時(shí)刻執(zhí)行,導(dǎo)致Pop 在第5 ns時(shí)被賦值。語句4在第5 ns執(zhí)行,并且Pid 在第8 ns被賦值。同樣,Pop在14 ns被賦值0,Pid在第16 ns被賦值0。第6條語句執(zhí)行后,initial語句永遠(yuǎn)被掛起。
結(jié)構(gòu)化描述形式
在Verilog HDL中可使用如下方式描述結(jié)構(gòu):
1) 內(nèi)置門原語(在門級(jí));
2) 開關(guān)級(jí)原語(在晶體管級(jí));
3) 用戶定義的原語(在門級(jí));
4) 模塊實(shí)例 (創(chuàng)建層次結(jié)構(gòu))。
通過使用線網(wǎng)來相互連接。下面的結(jié)構(gòu)描述形式使用內(nèi)置門原語描述的全加器電路實(shí)例。
module FA_Str (A, B, Cin, Sum, Cout);
input A, B, Cin;
output Sum, Cout;
wire S1, T1, T2, T3;
xor
X1 (S1, A, B),
X2 (Sum, S1, Cin);
and
A1 (T3, A, B),
A2 (T2, B, Cin),
A3 (T1, A, Cin),
or
O1 (Cout, T1, T2, T3);
endmodule
在這一實(shí)例中,模塊包含門的實(shí)例語句,也就是說包含內(nèi)置門xor、and和or 的實(shí)例語句。門實(shí)例由線網(wǎng)類型變量S1、T1、T2和T3互連。由于沒有指定的順序, 門實(shí)例語句可以以任何順序出現(xiàn);圖中顯示了純結(jié)構(gòu);xor、and和or是內(nèi)置門原語;X1、X2、A1等是實(shí)例名稱。緊跟在每個(gè)門后的信號(hào)列表是它的互連;列表中的第一個(gè)是門輸出,余下的是輸入。例如,S1與xor 門實(shí)例X1的輸出連接,而A和B與實(shí)例X1的輸入連接。
4位全加器可以使用4個(gè)1位全加器模塊描述。下面是4位全加器的結(jié)構(gòu)描述形式。
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( .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(FA[3], FB[3], FTemp[2], FSum[3], FTemp[3],
FA4(FA[4], FB[4], FTemp[3], FSum[4], FCout);
endmodule
在這一實(shí)例中,模塊實(shí)例用于建模4位全加器。在模塊實(shí)例語句中,端口可以與名稱或位置關(guān)聯(lián)。前兩個(gè)實(shí)例FA1和FA2使用命名關(guān)聯(lián)方式,也就是說,端口的名稱和它連接的線網(wǎng)被顯式描述(每一個(gè)的形式都為“.port_name (net_name))。最后兩個(gè)實(shí)例語句,實(shí)例FA3和FA4使用位置關(guān)聯(lián)方式將端口與線網(wǎng)關(guān)聯(lián)。這里關(guān)聯(lián)的順序很重要,例如,在實(shí)例FA4中,第一個(gè)FA[4]與FA_Str 的端口A連接,第二個(gè)FB[4]與FA_Str 的端口B連接,余下的由此類推。
評(píng)論
查看更多