?
今天給大俠帶來的是一周掌握FPGA Verilog HDL 語法,今天開啟第一天,下面咱們廢話就不多說了,一起來看看吧。?在學習中,學習任何東西都有一個過程,一個初步認識到慢慢了解再到精通掌握的過程,當然,學習Verilog HDL語法也是一樣,首先你要了解什么是Verilog HDL,然后結合實踐再遵從理論,你才可能理解的更加迅速更加透徹。 ? ? ?Verilog HDL是一種用于數字邏輯電路設計的語言。用Verilog HDL描述的電路設計就是該電路的Verilog HDL模型。Verilog HDL既是一種行為描述的語言也是一種結構描述的語言。這也就是說,既可以用電路的功能描述也可以用元器件和它們之間的連接來建立所設計電路的Verilog HDL模型。Verilog模型可以是實際電路的不同級別的抽象。這些抽象的級別和它們對應的模型類型共有以下五種。
-
系統級(system):用高級語言結構實現設計模塊的外部性能的模型。
-
算法級(algorithm):用高級語言結構實現設計算法的模型。
-
RTL級(Register Transfer Level):描述數據在寄存器之間流動和如何處理這些數據的模型。
-
門級(gate-level):描述邏輯門以及邏輯門之間的連接的模型。?
-
開關級(switch-level):描述器件中三極管和儲存節點以及它們之間連接的模型。
?
?
一個復雜電路系統的完整Verilog HDL模型是由若干個Verilog HDL模塊構成的,每一個模塊又可以由若干個子模塊構成。其中有些模塊需要綜合成具體電路,而有些模塊只是與用戶所設計的模塊交互的現存電路或激勵信號源。利用Verilog HDL語言結構所提供的這種功能就可以構造一個模塊間的清晰層次結構來描述極其復雜的大型設計,并對所作設計的邏輯電路進行嚴格的驗證。Verilog HDL行為描述語言作為一種結構化和過程性的語言,其語法結構非常適合于算法級和RTL級的模型設計。這種行為描述語言具有以下功能:
- 可描述順序執行或并行執行的程序結構。?
- 用延遲表達式或事件表達式來明確地控制過程的啟動時間。?
- 通過命名的事件來觸發其它過程里的激活行為或停止行為。?
- 提供了條件、if-else、case、循環程序結構。?
- 提供了可帶參數且非零延續時間的任務(task)程序結構。?
- 提供了可定義新的操作符的函數結構(function)。?
- 提供了用于建立表達式的算術運算符、邏輯運算符、位運算符。?
?
??
Verilog HDL語言作為一種結構化的語言也非常適合于門級和開關級的模型設計。因其結構化的特點又使它具有以下功能:?
- 提供了完整的一套組合型原語(primitive);?
- 提供了雙向通路和電阻器件的原語;?
- 可建立MOS器件的電荷分享和電荷衰減動態模型。
?
Verilog HDL的構造性語句可以精確地建立信號的模型。這是因為在Verilog HDL中,提供了延遲和輸出強度的原語來建立精確程度很高的信號模型。信號值可以有不同的的強度,可以通過設定寬范圍的模糊值來降低不確定條件的影響。Verilog HDL作為一種高級的硬件描述編程語言,有著類似C語言的風格。其中有許多語句如:if語句、case語句等和C語言中的對應語句十分相似。如果讀者已經掌握C語言編程的基礎,那么學習Verilog HDL并不困難,我們只要對Verilog HDL某些語句的特殊方面著重理解,并加強上機練習就能很好地掌握它,利用它的強大功能來設計復雜的數字邏輯電路。下面我們將對Verilog HDL中的基本語法逐一加以介紹。 ? ? ? ?簡單的Verilog HDL模塊 ? ? ??
簡單的Verilog HDL程序介紹
下面先介紹幾個簡單的Verilog HDL程序,然后從中分析Verilog HDL程序的特性。
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
上面這個例子通過連續賦值語句描述了一個名為adder的三位加法器可以根據兩個三比特數a、b和進位(cin)計算出和(sum)和進位(count)。從例子中可以看出整個Verilog HDL程序是嵌套在module和 endmodule 聲明語句里的。 ? ?module adder ( count,sum,a,b,cin );
input [2:0] a,b;
input cin;
output count;
output [2:0] sum;
assign {count,sum} = a + b + cin;
endmodule
?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
module compare ( equal,a,b );
?
??input?[1:0]?a,b;?//聲明輸入信號a,b??
output equal; //聲明輸出信號equal
? assign equal=(a==b)?1:0;?
???/*如果a、b 兩個輸入信號相等,輸出為1。否則為0*/?
endmodule
上面這個程序通過連續賦值語句描述了一個名為compare的比較器。對兩比特數 a、b 進行比較,如a與b相等,則輸出equal為高電平,否則為低電平。在這個程序中,/*........*/和//.........表示注釋部分,注釋只是為了方便程序員理解程序,對編譯是不起作用的。
?
??
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
module trist2(out,in,enable);
input in, enable;
output out;
??bufif1?mybuf(out,in,enable);?
??
endmodule
上面這個程序描述了一個名為trist2的三態驅動器。程序通過調用一個在Verilog語言庫中現存的三態驅動器實例元件bufif1來實現其功能。
?
??
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
module trist1(out,in,enable);
input in, enable;
output out;
mytri?tri_inst(out,in,enable);?//調用由mytri模塊定義的實例元件tri_inst?
endmodule?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
module mytri(out,in,enable);
input in, enable;
output out;
assign out = enable? in : 'bz;
endmodule
這個程序例子通過另一種方法描述了一個三態門。在這個例子中存在著兩個模塊。模塊trist1調用由模塊mytri定義的實例元件tri_inst。模塊trist1是頂層模塊。模塊mytri則被稱為子模塊。?
?
??
通過上面的例子可以了解到:
-
Verilog HDL程序是由模塊構成,每個模塊的內容都是嵌在module和endmodule兩個語句之間。每個模塊實現特定的功能。模塊是可以進行層次嵌套的。正因為如此,才可以將大型的數字電路設計分割成不同的小模塊來實現特定的功能,最后通過頂層模塊調用子模塊來實現整體功能。
-
每個模塊要進行端口定義,并說明輸入輸出口,然后對模塊的功能進行行為邏輯描述。
-
Verilog HDL程序的書寫格式自由,一行可以寫幾個語句,一個語句也可以分寫多行。
-
除了endmodule語句外,每個語句和數據定義的最后必須有分號。
-
可以用/*.....*/和//.......對Verilog HDL程序的任何部分作注釋。一個有使用價值的源程序都應當加上必要的注釋,以增強程序的可讀性和可維護性。
?
??
模塊的結構
Verilog的基本設計單元是“模塊”(block)。一個模塊是由兩部分組成的,一部分描述接口,另一部分描述邏輯功能,即定義輸入是如何影響輸出的。下面舉例說明:- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
module block (a,b,c,d);
input a,b;
output c,d;
assign c= a | b ;
assign d= a & b;
endmodule
上面的例子,程序模塊下面是一個電路圖的符號。在眾多時候,程序模塊和電路圖符號是一致的,這是因為電路圖符號的引腳也就是程序模塊的接口。而程序模塊描述了電路圖符號所實現的邏輯功能。上面的Verilog設計中,模塊中的第3、第4行說明接口的信號流向,第6、第7行說明了模塊的邏輯功能。以上就是設計一個簡單的Verilog程序模塊所需的全部內容。從上面的例子可以看出,Verilog結構完全嵌在module和endmodule聲明語句之間,每個Verilog程序包括四個主要部分:端口定義、I/O說明、內部信號聲明、功能定義。 ? ?
?
模塊的端口定義
模塊的端口聲明了模塊的輸入輸出口。
其格式如下:module 模塊名(口1,口2,口3,口4, ………);?
?
??
模塊內容?
模塊的內容包括I/O說明、內部信號聲明、功能定義。
1、I/O說明的格式如下:
輸入口:input 端口名1,端口名2,………,端口名i; //(共有i個輸入口)?
輸出口:output 端口名1,端口名2,………,端口名j; //(共有j個輸出口)
I/O說明也可以寫在端口聲明語句里。其格式如下:?
- ?
module module_name(input port1,input port2,…output port1,output port2… );
?
2、內部信號說明:
在模塊內用到的和與端口有關的 wire 和 reg 變量的聲明。?
如:reg [width-1 : 0] R變量1,R變量2 。。。。;?
wire [width-1 : 0] W變量1,W變量2 。。。。;……
?
3、功能定義:?
模塊中最重要的部分是邏輯功能定義部分。有三種方法可在模塊中產生邏輯。
1). 用“assign”聲明語句。
如:assign a = b & c; 這種方法的句法很簡單,只需寫一個“assign”,后面再加一個方程式即可。例子中的方程式描述了一個有兩個輸入的與門。
2).?用實例元件 。
如:and and_inst( q, a, b ); 采用實例元件的方法象在電路圖輸入方式下,調入庫元件一樣。鍵入元件的名字和相連的引腳即可,表示在設計中用到一個跟與門(and)一樣的名為and_inst的與門,其輸入端為a, b,輸出為q。要求每個實例元件的名字必須是唯一的,以避免與其他調用與門(and)的實例混淆。?
3). 用“always”塊。
- ?
- ?
- ?
- ?
- ?
always @(posedge clk or posedge clr)
begin
if(clr) q <= 0;
else if(en) q <= d;
end
采用“assign”語句是描述組合邏輯最常用的方法之一。而“always”塊既可用于描述組合邏輯也可描述時序邏輯。上面的例子用“always”塊生成了一個帶有異步清除端的D觸發器。“always”塊可用很多種描述手段來表達邏輯,例如上例中就用了if...else語句來表達邏輯關系。如按一定的風格來編寫“always”塊,可以通過綜合工具把源代碼自動綜合成用門級結構表示的組合或時序邏輯電路。
注意:如果用Verilog模塊實現一定的功能,首先應該清楚哪些是同時發生的,哪些是順序發生的。上面三個例子分別采用了“assign”語句、實例元件和“always”塊。這三個例子描述的邏輯功能是同時執行的。也就是說,如果把這三項寫到一個 VeriIog 模塊文件中去,它們的次序不會影響邏輯實現的功能。這三項是同時執行的,也就是并發的。?
然而,在“always”模塊內,邏輯是按照指定的順序執行的。“always”塊中的語句稱為“順序語句”,因為它們是順序執行的。請注意,兩個或更多的“always”模塊也是同時執行的,但是模塊內部的語句是順序執行的。看一下“always”內的語句,你就會明白它是如何實現功能的。if..else… if必須順序執行,否則其功能就沒有任何意義。如果else語句在if語句之前執行,功能就會不符合要求。為了能實現上述描述的功能,“always”模塊內部的語句將按照書寫的順序執行。
?
??
?
? ? ?數據類型及其常量、變量 ? ? ??
Verilog HDL中總共有十九種數據類型,數據類型是用來表示數字電路硬件中的數據儲存和傳送元素的。在這里我們先只介紹四個最基本的數據類型,它們是:?reg型、wire型、integer型、parameter型,其它數據類型在后面逐步介紹,也可以查閱相關Verilog HDL語法參考書,其它的類型如下:large型、medium型、scalared型、time型、small型、tri型、trio型、tri1型、triand型、trior型、trireg型、vectored型、wand型、wor型。這些數據類型除time型外都與基本邏輯單元建庫有關,與系統設計沒有很大的關系。在一般電路設計自動化的環境下,仿真用的基本部件庫是由半導體廠家和EDA工具廠家共同提供的。系統設計工程師不必過多地關心門級和開關級的Verilog HDL語法現象。Verilog HDL語言中也有常量和變量之分。它們分別屬于以上這些類型。下面就最常用的幾種進行介紹。 ? ??
? ? ?常量 ? ? ??
在程序運行過程中,其值不能被改變的量稱為常量。下面首先對在Verilog HDL語言中使用的數字及其表示方式進行介紹。
?
一.數字型?
整數:?
在Verilog HDL中,整型常量即整常數有以下四種進制表示形式:
1) 二進制整數(b或B)
2) 十進制整數(d或D)?
3) 十六進制整數(h或H)?
4) 八進制整數(o或O)?
數字表達方式有以下三種:?
1) <位寬><進制><數字>這是一種全面的描述方式。
2) <進制><數字>在這種描述方式中,數字的位寬采用缺省位寬(這由具體的機器系統決定,但至少32位)。
3) <數字>在這種描述方式中,采用缺省進制十進制。在表達式中,位寬指明了數字的精確位數。例如:一個4位二進制數的數字的位寬為4,一個4位十六進制數的數字的位寬為16(因為每單個十六進制數就要用4位二進制數來表示)。見下例: 8'b10101100 //位寬為8的數的二進制表示, 'b表示二進制 8'ha2 //位寬為8的數的十六進制,'h表示十六進制。
?
x和z值:?
在數字電路中,x代表不定值,z代表高阻值。一個x可以用來定義十六進制數的四位二進制數的狀態,八進制數的三位,二進制數的一位。z的表示方式同x類似。z還有一種表達方式是可以寫作?。在使用case表達式時建議使用這種寫法,以提高程序的可讀性。見下例: 4'b10x0 //位寬為4的二進制數從低位數起第二位為不定值 4'b101z //位寬為4的二進制數從低位數起第一位為高阻值 12'dz //位寬為12的十進制數其值為高阻值(第一種表達方式) 12'd? //位寬為12的十進制數其值為高阻值(第二種表達方式) 8'h4x //位寬為8的十六進制數其低四位值為不定值。
?
負數:?
一個數字可以被定義為負數,只需在位寬表達式前加一個減號,減號必須寫在數字定義表達式的最前面。注意減號不可以放在位寬和進制之間也不可以放在進制和具體的數之間。見下例: -8'd5 //這個表達式代表5的補數(用八位二進制數表示) 8'd-5 //非法格式。
?
下劃線(underscore_):?
下劃線可以用來分隔開數的表達以提高程序可讀性。但不可以用在位寬和進制處,只能用在具體的數字之間。
見下例:?
16'b1010_1011_1111_1010 //合法格式?
8'b_0011_1010 //非法格式?
?
當常量不說明位數時,默認值是32位,每個字母用8位的ASCII值表示。?例:?
10=32’d10=32’b1010 21
1=32’d1=32’b1?
-1=-32’d1=32’hFFFFFFFF?
‘BX=32’BX=32’BXXXXXXX…X?
“AB”=16’B01000001_01000010
?
二.參數(Parameter)型?
在Verilog HDL中用parameter來定義常量,即用parameter來定義一個標識符代表一個常量,稱為符號常量,即標識符形式的常量,采用標識符代表一個常量可提高程序的可讀性和可維護性。parameter型數據是一種常數型的數據,其說明格式如下:
parameter 參數名1=表達式,參數名2=表達式, …, 參數名n=表達式;
parameter是參數型數據的確認符,確認符后跟著一個用逗號分隔開的賦值語句表。在每一個賦值語句的右邊必須是一個常數表達式。也就是說,該表達式只能包含數字或先前已定義過的參數。見下例:
- ?
- ?
- ?
- ?
- ?
parameter msb=7; //定義參數msb為常量7
parameter e=25, f=29; //定義二個常數參數
parameter r=5.7; //聲明r為一個實型參數
parameter byte_size=8, byte_msb=byte_size-1; //用常數表達式賦值
parameter average_delay = (r+f)/2; //用常數表達式賦值
參數型常數經常用于定義延遲時間和變量寬度。在模塊或實例引用時可通過參數傳遞改變在被引用模塊或實例中已定義的參數。下面將通過兩個例子進一步說明在層次調用的電路中改變參數常用的一些用法。
- ?
- ?
- ?
- ?
- ?
- ?
module Decode(A,F);
parameter Width=1, Polarity=1;
??……………
??
endmodule?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
module Top;
wire[3:0] A4;
wire[4:0] A5;
wire[15:0] F16;
wire[31:0] F32;
Decode #(4,0) D1(A4,F16);
Decode #(5) D2(A5,F32);
endmodule
引用Decode實例時,D1,D2的Width將采用不同的值4和5,且D1的Polarity將為0。可用例子中所用的方法來改變參數,即用 #(4,0)向D1中傳遞 Width=4,Polarity=0; 用#(5)向D2中傳遞Width=5,Polarity仍為1。
?
??
- ?
- ?
- ?
- ?
- ?
- ?
Module Test;
wire W;
Top T ( );
emdmodule
- ?
- ?
- ?
- ?
- ?
- ?
- ?
module Top;
wire W
Block B1 ( );
Block B2 ( );
endmodule
- ?
- ?
- ?
- ?
- ?
module Block;
Parameter P = 0;
endmodule
- ?
- ?
- ?
- ?
- ?
- ?
- ?
module Annotate;
defparam
Test.T.B1.P = 2,
Test.T.B2.P = 3;
endmodule
上面是一個多層次模塊構成的電路,在一個模塊中改變另一個模塊的參數時,需要使用defparam命令。Day 1 就到這里,Day 2 繼續開始變量,大俠保重,告辭。
審核編輯:湯梓紅
評論
查看更多