Verilog的基礎知識

Verilog的基本介紹:

硬件描述語言發展至今已有二十多年曆史,當今業界的標準中( IEEE標準)主要有VHDL和Verilog HDL 這兩種硬件描述語言。
一個設計往往從系統級設計開始,把系統劃分成幾個大的基本的功能模塊,每個功能模塊再按一定的規則分成下一個層次的基本單元,如此一直劃分下去。自頂向下的設計方法可用下面的樹狀結構表示:

主要功能


1, 基本邏輯門,例如and 、 or 和nand 等都內置在語言中。
2, 開關級基本結構模型,例如pmos 和nmos 等也被內置在語言中。
3, 可採用三種不同方式或混合方式對設計建模。這些方式包括:行爲描述方式—使用過程化結構建模;數據流方式—使用連續賦值語句方式建模;結構化方式—使用門和模塊實例語句描述建模。
4, Verilog HDL 中有兩類數據類型:線網數據類型和寄存器數據類型。線網類型表示構件間的物理連線,而寄存器類型表示抽象的數據存儲元件。
5, 能夠描述層次設計,可使用模塊實例結構描述任何層次。
6, 設計的規模可以是任意的;語言不對設計的規模(大小)施加任何限制。
7, Verilog HDL 不再是某些公司的專有語言而是I E E E 標準。
8, 人和機器都可閱讀Verilog 語言,因此它可作爲E D A 的工具和設計者之間的交互語言。
9, 設計能夠在多個層次上加以描述,從開關級、門級、寄存器傳送級(RT L )到算法級。
10, 能夠使用內置開關級原語在開關級對設計完整建模。
11, 同一語言可用於生成模擬激勵和指定測試的驗證約束條件,例如輸入值的指定。
12, Verilog HDL 能夠監控模擬驗證的執行,即模擬驗證執行過程中設計的值能夠被監控和顯示。這些值也能夠用於與期望值比較,在不匹配的情況下,打印報告消息。
13, 在行爲級描述中, Verilog HDL 不僅能夠在RT L 級上進行設計描述,而且能夠在體系結構級描述及其算法級行爲上進行設計描述。
14, 能夠使用門和模塊實例化語句在結構級進行結構描述。
15, 對高級編程語言結構,例如條件語句、情況語句和循環語句,語言中都可以使用。
下圖顯示了Verilog HDL 的混合方式建模能力,即在一個設計中每個模塊均可以在不同設計層次上建模。

模塊


模塊(module)是Verilog 的基本描述單位,用於描述某個設計的功能或結構及與其他模塊通信的外部端口。
模塊在概念上可等同一個器件就如我們調用通用器件(與門、三態門等)或通用宏單元(計數器、 ALU、 CPU)等,因此,一個模塊可在另一個模塊中調用。
一個電路設計可由多個模塊組合而成,因此一個模塊的設計只是一個系統設計中的某個層次設計,模塊設計可採用多種建模方式。
 

例[1] 加法器
module addr (a, b, cin, count, sum);
input [2:0] a;
input [2:0] b;
input cin;
output count;
output [2:0] sum;
assign {count,sum} = a +b + cin;
endmodule
例[2] 比較器
module compare (equal, a, b);
input [1:0] a,b; // declare the input signal ;
output equare ; // declare the output signal;
assign equare = (a == b) ? 1:0 ;
/ * if a = b , output 1, otherwise 0; */
endmodule

/* .... */ 和 // ... 表示註釋部分


模塊的端口定義部分:


如上例: module addr (a, b, cin, count, sum); 其中module 是模塊的保留字, addr 是模塊的名字,相當於器件名。()內是該模塊的端口聲明,定義了該模塊的管腳名,是該模塊與其他模塊通訊的外部接口,相當於器件的pin 。
模塊的內容,包括I/O說明,內部信號、調用模塊等的聲明語句和功能定義語句。
I/O說明語句如: input [2:0] a; input [2:0] b; input cin; output count; 其 中 的 input 、output、 inout 是保留字,定義了管腳信號的流向, [n:0]表示該信號的位寬(總線或單根信號線)。

邏輯功能描述部分如: assign  d_out = d_en ? din :'bz;  

對每個模塊都要進行端口定義,並說明輸入、輸出口,然後對模塊的功能進行邏輯描述,當然,對測試模塊,可以沒有輸入輸出口。
除endmodule 語句外,每個語句後面需有分號表示該語句結束。
 

時延


信號在電路中傳輸會有傳播延時等,如線延時、器件延時。時延就是對延時特性的HDL描述。舉例如下:
assign # 2 B = A;
表示 B信號在2個時間單位後得到A信號的值。如下圖:
 

在Verilog HDL中,所有時延都必須根據時間單位進行定義,定義方式爲在文件頭添加如下語句:
`timescale 1ns /100ps
其中’ timescale 是Verilog HDL 提供的預編譯處理命令, 1ns 表示時間單位是1ns , 100ps表示時間精度是100ps。根據該命令,編譯工具纔可以認知 #2 爲2ns。

三種建模方式
 

主要有結構化描述方式、數據流描述方式和行爲描述方式
結構化描述方式
結構化的建模方式就是通過對電路結構的描述來建模,即通過對器件的調用( HDL概念稱爲例化),並使用線網來連接各器件的描述方式。這裏的器件包括Verilog HDL的內置門如與門and,異或門xor等,也可以是用戶的一個設計。結構化的描述方式反映了一個設計的層次結構。
一位全加器
 

module FA_struct (A, B, Cin, Sum, Count);
input A;
input B;
input Cin;
output Sum;
output Count;
wire S1, T1, T2, T3;
// -- statements -- //
xor x1 (S1, A, B);
xor x2 (Sum, S1, Cin);
and A1 (T3, A, B );
and A2 (T2, B, Cin);
and A3 (T1, A, Cin);
or O1 (Cout, T1, T2, T3 );
endmodule

該實例顯示了一個全加器由兩個異或門、三個與門、一個或門構成。 S1、 T1、 T2、 T3則是門與門之間的連線。代碼顯示了用純結構的建模方式,其中xor 、 and、 or 是Verilog HDL 內置的門器件。以 xor x1 (S1, A, B) 該例化語句爲例:xor 表明調用一個內置的異或門,器件名稱xor ,代碼實例化名x1(類似原理圖輸入方式)。括號內的S1, A, B 表明該器件管腳的實際連接線(信號)的名稱 ,其中 A、 B是輸入, S1是輸出

數據流描述方式
數據流的建模方式就是通過對數據流在設計中的具體行爲的描述的來建模。最基本的機制就是用連續賦值語句。在連續賦值語句中,某個值被賦給某個線網變量(信號),語法如下:
assign [delay] net_name = expression;
如: assign #2 A = B;
在數據流描述方式中,還必須藉助於HDL提供的一些運算符,如按位邏輯運算符 :邏輯與(&),邏輯或(|)等。
一位全加器:

`timescale 1ns/100ps
module FA_flow(A,B,Cin,Sum,Count)
input A,B,Cin;
output Sum, Count;
wire S1,T1,T2,T3;
assign # 2 S1 = A ^ B;
assign # 2 Sum = S1 ^ Cin;
assign #2 T3 = A & B;
assign #2 T1 = A & Cin;
assign #2 T2 = B & Cin ;
endmodule

注意在各assign 語句之間,是並行執行的,即各語句的執行與語句之間的順序無關。如上,當A有個變化時, S1、 T3、 T1 將同時變化, S1的變化又會造成Sum的變化。

行爲描述方式
行爲方式的建模是指採用對信號行爲級的描述(不是結構級的描述)的方法來建模。在表示方面,類似數據流的建模方式,但一般是把用initial 塊語句或always 塊語句描述的歸爲行爲建模方式。行爲建模方式通常需要藉助一些行爲級的運算符如加法運算符(+),減法運算符(-)等。
以下舉個例子,對initial 和always 語句的具體應用可看相關章節的介紹,這裏,先對行爲建模方式有個概念。
 

例[1] 一位全加器的行爲建模
module FA_behav1(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

需要先建立以下概念:
1、只有寄存器類型的信號纔可以在always和initial 語句中進行賦值,類型定義通過reg語句實現。
2、 always 語句是一直重複執行,由敏感表(always 語句括號內的變量)中的變量觸發。
3、 always 語句從0 時刻開始。
4、在begin 和end 之間的語句是順序執行,屬於串行語句。

混合設計描述
在實際的設計中,往往是多種設計模型的混合。一般地,對頂層設計,採用結構描述方式,對低層模塊,可採用數據流、行爲級或兩者的結合。兩bit 全加器,對頂層模塊採用結構描述方式對低層進行例化,對低層模塊(FA)可採用結構描述、數據流描述或行爲級描述

標識符

標識符( identifier)用於定義模塊名、端口名、信號名等。 Verilog HDL 中的標識符( identifier)可以是任意一組字母、數字、 $符號和_(下劃線)符號的組合,但標識符的第一個字符必須是字母或者下劃線。另外,標識符是區分大小寫的。以下是標識符的幾個例子:
Count
COUNT //與Count 不同。
R56_68
FIVE$
關鍵詞
Verilog HDL 定義了一系列保留字,叫做關鍵詞,附錄A 列出了語言中的所有保留字。注意只有小寫的關鍵詞纔是保留字。例如,標識符always (這是個關鍵詞)與標識符ALWAYS(非關鍵詞)是不同的。
 

數字值集合


值集合
Verilog HDL中規定了四種基本的值類型:
0:邏輯0或“假”;
1:邏輯1或“真”;
X:未知值;
Z:高阻。
注意這四種值的解釋都內置於語言中。如一個爲z 的值總是意味着高阻抗,一個爲0 的值通常是指邏輯0 。在門的輸入或一個表達式中的爲“z ”的值通常解釋成“x ”。
此外, x 值和z 值都是不分大小寫的,也就是說,值0x1z 與值0X1Z 相同。
Verilog HDL 中的常量是由以上這四類基本值組成的。
 

常量
Verilog HDL 中有三種常量:
整型、實型、字符串型。
下劃線符號(_)可以隨意用在整數或實數中,它們就數量本身沒有意義。它們能用來提高易
讀性;唯一的限制是下劃線符號不能用作爲首字符。
下面主要介紹整型和字符串型。


整型
整型數可以按如下兩種方式書寫:
1) 簡單的十進制數格式
2) 基數格式
A. 簡單的十進制格式
這種形式的整數定義爲帶有一個可選的“+”(一元)或“-”(一元)操作符的數字序列。
下面是這種簡易十進制形式整數的例子。
32 十進制數32
-15 十進制數-15
B. 基數表示法
這種形式的整數格式爲:
[size ] 'base value
size 定義以位計的常量的位長; base 爲o 或O(表示八進制), b 或B(表示二進制), d 或D(表示十進制), h 或H (表示十六進制)之一; value 是基於base 的值的數字序列。值x 和z 以及十六進制中的a 到f 不區分大小寫。
下面是一些具體實例:
5 'O37 5 位八進制數(二進制 11111 )
4 'D2 4 位十進制數 (二進制0011)
4 'B1x_01 4 位二進制數
7 'Hx 7位x(擴展的x), 即xxxxxxx
4 'hZ 4 位z(擴展的z) , 即zzzz
4 'd-4 非法:數值不能爲負
8 'h 2A 在位長和字符之間,以及基數和數值之間允許出現空格
3' b 001 非法: ` 和基數b 之間不允許出現空格
(2+3)'b10 非法:位長不能夠爲表達式
注意, x (或z )在十六進制值中代表4 位x(或z ),在八進制中代表3 位x(或z ),在二進
制中代表1 位x (或z )。
基數格式計數形式的數通常爲無符號數。這種形式的整型數的長度定義是可選的。如果沒有
定義一個整數型的長度,數的長度爲相應值中定義的位數。下面是兩個例子:

'o 721
'h AF
9 位八進制數
8 位十六進制數

如果定義的長度比爲常量指定的長度長,通常在左邊填0 補位。但是如果數最左邊一位爲x 或z ,就相應地用x 或z 在左邊補位。例如:
10'b10 左邊添0 佔位, 0000000010
10'bx0x1 左邊添x 佔位, x x x x x x x 0 x 1
如果長度定義得更小,那麼最左邊的位相應地被截斷。例如:
3 ' b1001 _ 0011 與3'b011 相等
5'H0FFF 與5'H1F 相等

字符串型
字符串是雙引號內的字符序列。字符串不能分成多行書寫。例如:
"INTERNAL ERROR"
" REACHED->HERE "
用8 位ASCII 值表示的字符可看作是無符號整數。因此字符串是8 位ASCII 值的序列。爲存儲
字符串“INTERNAL ERROR ”,變量需要8 * 1 4 位。
r e g [1: 8*14] Message;
Message = "INTERNAL ERROR"

數據類型


Verilog HDL 主要包括兩種數據類型
線網類型(net type) 和 寄存器類型(reg type)。
線網類型
1. wire 和 tri 定義
線網類型主要有wire 和tri 兩種。線網類型用於對結構化器件之間的物理連線的建模。如器件的管腳,內部器件如與門的輸出等。以上面的加法器爲例,輸入信號A, B是由外部器件所驅動,異或門X1的輸出S1是與異或門X2輸入腳相連的物理連接線,它由異或門X1所驅動。
由於線網類型代表的是物理連接線,因此它不存貯邏輯值。必須由器件所驅動。通常由assign進行賦值。如 assign A = B ^ C;
當一個wire 類型的信號沒有被驅動時,缺省值爲Z(高阻)。
信號沒有定義數據類型時,缺省爲 wire 類型。
如上面一位全加器的端口信號 A, B, SUM等,沒有定義類型,故缺省爲wire 線網類型。
2. 兩者區別
tri 主要用於定義三態的線網。

寄存器類型
1. 定義
reg 是最常用的寄存器類型,寄存器類型通常用於對存儲單元的描述,如D型觸發器、 ROM等。存儲器類型的信號當在某種觸發機制下分配了一個值,在分配下一個值之時保留原值。但必須注意的是, reg 類型的變量,不一定是存儲單元,如在always 語句中進行描述的必須用reg 類型的變量。
reg 類型定義語法如下:
reg [msb: lsb] reg1, reg2, . . . r e g N;
msb 和lsb 定義了範圍,並且均爲常數值表達式。範圍定義是可選的;如果沒有定義範圍,缺省值爲1 位寄存器。例如:

reg [3:0] Sat;
reg Cnt;
// S a t 爲4 位寄存器。
//1 位寄存器。

reg [1:32] Kisp, Pisp, Lisp ;
寄存器類型的值可取負數,但若該變量用於表達式的運算中,則按無符號類型處理,如:
reg A ;
A = -1;
則A的二進制爲 1111,在運算中, A總按 無符號數15 來看待。
2. 寄存器類型的存儲單元建模舉例
用寄存器類型來構建兩位的D觸發器如下:
reg [1: 0] Dout ;
always@(posedge Clk)
Dout <= Din;
用寄存器數組類型來建立存儲器的模型,如對2個8位的RAM建模如下:
reg [7: 0] Mem[0: 1] ;
對存儲單元的賦值必須一個個第賦值,如上2個8位的RAM的賦值必須用兩條賦值語句:
Mem[0] = ’ h 55;
Mem[1] = ’ haa;
對數組類型,請按降序方式,如[7: 0] ;

運算符和表達式

算術運算符
在常用的算術運算符主要是 :
加法(二元運算符):“+”;
減法 (二元運算符): “-”;
乘法(二元運算符):“*”;
在算術運算符的使用中,注意如下兩個問題:
1. 算術操作結果的位數長度
算術表達式結果的長度由最長的操作數決定。在賦值語句下,算術操作結果的長度由操作符
左端目標長度決定。考慮如下實例:
reg [3:0] Arc, Bar, Crt;
reg [5:0] Frx;
. . .
Arc = Bar + Crt;
Frx = Bar + Crt;
第一個加的結果長度由Bar , Crt 和A rc 長度決定,長度爲4 位。
第二個加法操作的長度同樣由Frx 的長度決定( Frx 、 Bat 和Crt 中的最長長度),長度爲6位。
在第一個賦值中,加法操作的溢出部分被丟棄;而在第二個賦值中,任何溢出的位存儲在結果位Frx [ 4 ]中。
在較大的表達式中,中間結果的長度如何確定?在Verilog HDL 中定義瞭如下規則:表達式中的所有中間結果應取最大操作數的長度(賦值時,此規則也包括左端目標)。考慮另一個實例:
wire [4:1] Box, Drt;
wire [5:1] Cfg;
wire [6:1] Peg;
wire [8:1] Adt;
. . .
assign Adt = (Box + Cfg) + (Drt + Peg) ;
表達式右端的操作數最長爲6 ,但是將左端包含在內時,最大長度爲8 。所以所有的加操作使用8 位進行。例如: Box 和Cfg 相加的結果長度爲8 位。
2. 有符號數和無符號數
在設計中,請先按無符號數進行。
關係運算符
關係運算符有:
?>(大於)
?<(小於)
?>=(不小於)
?<=(不大於)
= = (邏輯相等)
! = (邏輯不等)
關係操作符的結果爲真( 1 )或假( 0 )。如果操作數中有一位爲X 或Z ,那麼結果爲X 。
例:
23 > 45
結果爲假( 0 ),而:
52 < 8'hxFF
結果爲x 。
如果操作數長度不同,長度較短的操作數在最重要的位方向(左方)添0 補齊。例如:
'b1000 > = 'b01110
等價於:
'b01000 > = 'b01110
結果爲假( 0 )。
在邏輯相等與不等的比較中,只要一個操作數含有x 或z,比較結果爲未知 ( x),如:
假定:
Data = 'b11x0;
Addr = 'b11x0;
那麼:
Data = = Addr 比較結果不定,也就是說值爲x 。
邏輯運算符
邏輯運算符有:
&& (邏輯與)
|| (邏輯或)
! (邏輯非)
用法爲:(表達式1) 邏輯運算符 (表達式2) ....
這些運算符在邏輯值0(假) 或1(真) 上操作。邏輯運算的結果爲0 或1 。例如, 假定:
Crd = 'b0; //0 爲假
Dgs = 'b1; //1 爲真
那麼:
Crd && Dgs 結果爲0 (假)
Crd || Dgs 結果爲1 (真)
! D g s 結果爲0 (假)
按位邏輯運算符
按位運算符有:
?~(一元非):(相當於非門運算)
?&(二元與):(相當於與門運算)
?|(二元或): (相當於或門運算)
?^(二元異或):(相當於異或門運算)
?~ ^, ^ ~(二元異或非即同或) :(相當於同或門運算)
wire [7:0] Dbus;
assign Dbus [7:4] = {Dbus [0], Dbus [1], Dbus[2], Dbus[ 3 ] } ;
/ /以反轉的順序將低端4 位賦給高端4 位。
assign Dbus = {Dbus [3:0], Dbus [ 7 : 4 ] } ;
 

條件語句:

if(Sum < 60)
begin
Grade = C;
Total_C = Total _c + 1;
end
else if(Sum < 75)
begin
Grade = B;
Total_B = Total_B + 1;
end
else
begin
Grade = A;
Total_A = Total_A + 1;
end

case語句:

case (HEX)
4'b0001 : LED = 7'b1111001; // 1
4'b0010 : LED = 7'b0100100; // 2
4'b0011 : LED = 7'b0110000; // 3
4'b0100 : LED = 7'b0011001; // 4
4'b0101 : LED = 7'b0010010; // 5
4'b0110 : LED = 7'b0000010; // 6
4'b0111 : LED = 7'b1111000; // 7
4'b1000 : LED = 7'b0000000; // 8
4'b1001 : LED = 7'b0010000; // 9
4'b1010 : LED = 7'b0001000; // A
4'b1011 : LED = 7'b0000011; // B
4'b1100 : LED = 7'b1000110; // C
4'b1101 : LED = 7'b0100001; // D
4'b1110 : LED = 7'b0000110; // E
4'b1111 : LED = 7'b0001110; // F
default :LED = 7'b1000000; // 0
endcase

case 的缺省項必須寫,防止產生鎖存器
 

實例化語句
在我另一篇博客有例子

https://blog.csdn.net/qq_38531460/article/details/106862846

懸空端口的處理
在我們的實例化中,可能有些管腳沒用到,可在映射中採用空白處理,如:
DFF d1 (
.Q(QS),
.Qbar ( ),
.Data (D ) ,
.Preset ( ), // 該管腳懸空
.Clock (CK)
); //名稱對應方式。
對輸入管腳懸空的,則該管腳輸入爲高阻 Z,輸出管腳被懸空的,該輸出管腳廢棄不用。


不同端口長度的處理
當端口和局部端口表達式的長度不同時,端口通過無符號數的右對齊或截斷方式進行匹配。
例如:
module Child (Pba, Ppy) ;
input [5:0] Pba;
output [2:0] Ppy;
. . .
endmodule
module Top;
wire [1:2] Bdl;
wire [2:6] M p r;
Child C1 (Bdl, Mpr) ;
endmodule
在對Child 模塊的實例中, Bdl[2]連接到Pba[ 0 ], Bdl[1] 連接到Pba[ 1 ],餘下的輸入端口Pba[5]、 Pba[4]和Pba[3]懸空,因此爲高阻態z 。與之相似, Mpr[6]連接到Ppy[0], Mpr[5]連接到Ppy[1], Mpr[4] 連接到Ppy[2 ]。參見下圖:
 

過程賦值語句


Verilog HDL 中提供兩種過程賦值語句 initial 和 always 語句,用這兩種語句來實現行爲的建
模。這兩種語句之間的執行是並行的,即語句的執行與位置順序無關。這兩種語句通常與語句塊
(begin ....end)相結合,則語句塊中的執行是按順序執行的。
1. initial 語句
initial 語句只執行一次,即在設計被開始模擬執行時開始( 0時刻)。通常只用在對設計進行
仿真的測試文件中,用於對一些信號進行初始化和產生特定的信號波形。
 

initial
begin
#2 Stream = 1;
#5 Stream = 0;
#3 Stream = 1;
#4 Stream = 0;
#2 Stream = 1;
#5 Stream = 0;
end

always 語句
always 語句與initial 語句相反,是被重複執行,執行機制是通過對一個稱爲敏感變量表的事件驅動來實現的,下面會具體講到。 always 語句可實現組合邏輯或時序邏輯的建模。
例[1]:
initial
Clk = 0 ;
always
#5 Clk = ~Clk;
因爲always 語句是重複執行的,因此, Clk 是初始值爲0 的,週期爲10 的方波。
 

例[2] D 觸發器
always @ ( posedge Clk or posedge Rst )
begin
if Rst
Q <= ‘ b 0;
else
Q <= D;

上面括號內的內容稱爲敏感變量,即整個always 語句當敏感變量有變化時被執行,否則不執行。因此,當Rst 爲1 時, Q被複位,在時鐘上升沿時, D被採樣到Q。 有@ 的用來描述一個時序器件。
注意以下幾點:
1、對組合邏輯的always 語句,敏感變量必須寫全,敏感變量是指等式右邊出現的所有標識符
如上的a, b和條件表達式中出現的所以標識符 如上例3的sel。
2、對組合邏輯器件的賦值採用阻塞賦值 “=”
3、時序邏輯器件的賦值語句採用非阻塞賦值 “<=”,如上的 Q 〈= D;
 

"文件包含"處理`include

所謂"文件包含"處理是一個源文件可以將另外一個源文件的全部內容包含進來,即將另外的文件包含到本文件之中。Verilog HDL語言提供了`include命令用來實現"文件包含"的操作。其一般形式爲:

`include "文件名"

在編譯的時候,需要對`include命令進行"文件包含"預處理:將File2.v的全部內容複製插入到`include "File2.v"命令出現的地方,即將File2.v被包含到File1.v中,得到圖C的結果。在接着往下進行編譯中,將"包含"以後的File1.v作爲一個源文件單位進行編譯。

1)文件aaa.v

module aaa(a,b,out);
input a, b;
output out;
wire out;
assign out = a^b;
endmodule
(2)文件 bbb.v

`include "aaa.v"
module bbb(c,d,e,out);
input c,d,e;
output out;
wire out_a;
wire out;
aaa aaa(.a(c),.b(d),.out(out_a));
assign out=e&out_a;
endmodule

在上面的例子中,文件bbb.v用到了文件aaa.v中的模塊aaa的實例器件,通過"文件包含"處理來調用。模塊aaa實際上是作爲模塊bbb的子模塊來被調用的。在經過編譯預處理後,文件bbb.v實際相當於下面的程序文件bbb.v:

module aaa(a,b,out);
input a, b;
output out;
wire out;
assign out = a ^ b;
endmodule

module bbb( c, d, e, out);
input c, d, e;
output out;
wire out_a;
wire out;
aaa aaa(.a(c),.b(d),.out(out_a));
assign out= e & out_a;
endmodule

關於"文件包含"處理的四點說明:

1) 一個`include命令只能指定一個被包含的文件,如果要包含n個文件,要用n個`include命令。注意下面的寫法是非法的`include"aaa.v""bbb.v"

2) `include命令可以出現在Verilog HDL源程序的任何地方,被包含文件名可以是相對路徑名,也可以是絕對路徑名。例如:'include"parts/count.v"

3) 可以將多個`include命令寫在一行,在`include命令行,只可以出空格和註釋行。例如下面的寫法是合法的。

'include "fileB" 'include "fileC" //including fileB and fileC

4) 如果文件1包含文件2,而文件2要用到文件3的內容,則可以在文件1用兩個`include命令分別包含文件2和文件3,而且文件3應出現在文件2之前。

define宏定義+`inlude "file.v"文件包含來實現參數模塊化設計

1.新建參數模塊文件(我命名爲para.v);

  2.在para.v文件中使用'define宏定義參數(部分、有錯誤): 

     //`define+name+參數  
    `define   STATE_INIT     3'd0
    `define   STATE_IDLE    3'd1
    `define   STATE_WRIT   3'd2
    `define   STATE_READ  3'd3
    `define   STATE_WORK      3'd4
    `define   STATE_RETU  3'd5

  3.在需要調用參數的文件init.v中使用`include "para.v":

    `include "para.v"

  4.在init.v文件需要參數的地方使用`name 調用(部分):

    state_init <= `INIT_0;

若直接在module中通過localparam或者parameter進行參數定義的話,會帶來兩個問題:

    1.代碼長度增加,不夠美觀;

    2.不利於參數和代碼修改;

`define 與localparam和parameter最大的區別就是`define 可以跨文件傳遞參數;parameter只能在模塊間傳遞參數;localparam只能在其所在的module中起作用,不能參與參數傳遞。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章