Verilog HDL的程序結(jié)構(gòu)
首先我們不開始講Verilog HDL的語法,我們從Verilog HDL的程序結(jié)構(gòu)出發(fā)。相信大家都看過芯片吧,它有個名字,有個外殼,外殼向外伸出有引腳(BGA封裝的那種請不要亂攪和),然后芯片它可以實現(xiàn)一定的功能。
Ok,知道這些之后,我們就來看看Verilog HDL的描述數(shù)字電路的程序結(jié)構(gòu)吧。
在解釋結(jié)構(gòu)的時候,我拿芯片設(shè)計這個例子來打一個不恰當(dāng)?shù)谋确健?/p>
VerilogHDL程序的大致結(jié)構(gòu)就是這么一個形式,每一個模塊的結(jié)構(gòu)都是一致的只不過語句之間存在一些差別,每一部分的具體描述將在后面進行。
二、verilog程序結(jié)構(gòu)的簡單描述
OK,現(xiàn)在讓我們現(xiàn)在開始了解一下一些語法和注意事項(注意,我這里不會把語法講得很細很細,我主要是描述一些(我,或者初學(xué)者)易忘的,關(guān)鍵的語法和知識點),描述的順序不一定按照上面的各個部分喲,我們先描述一些VerilogHDL程序必須的。
首先是模塊說明:
module 和 endmodule ,這兩個關(guān)鍵詞成對出現(xiàn),一般的內(nèi)容都會囊括在這兩個兩個關(guān)鍵詞之間。一個verilog(.v)文件可以有多個module 。。.endmodule,但是為了方便管理,建議只實現(xiàn)一個。
此外無論是能夠綜合成電路的verilog程序還是只是仿真的程序,都需要以模塊的形式給出。
模塊名:
①模塊名的定義要符合標(biāo)識符的定義,至于什么是標(biāo)識符,以后會說的。此外也要注意書寫的規(guī)范性。
端口說明:
①端口可以比方成芯片的輸入輸入管腳,它只有三種類型:輸入,輸出,雙向;
②端口有一些附加屬性,如數(shù)據(jù)類型、符號特性、位寬等;input端口只能是線網(wǎng)類型,output可以是寄存器類型也可以是線網(wǎng)類型,inout也只能是線網(wǎng)類型。至于線網(wǎng)類型和寄存器類型,在以后的數(shù)據(jù)類型中會介紹。
③當(dāng)端口是總線類型時,可以簡單地理解為端口有多位時,對應(yīng)于同時描述芯片的多個管腳時,可以給端口加上位寬。即input wire [M:N] a;如果M》N,則為降序,a[M]為最高位,位寬為M-N+1位;如果M《N,則最高位位a[N]位,位寬位N-M+1位;
④端口的屬性聲明順序可以是:
端口的輸入輸出 數(shù)據(jù)類型 有無符號 位寬 端口名稱 ;
如:output reg signed [7:0] a;
注:數(shù)據(jù)類型沒有寫則默認為wire 型,有無符號沒有寫默認為無符號型;位寬沒有寫默認為1bit 。
⑤當(dāng)書寫完端口聲明是,括號后面的‘;’千萬不要忘記。
程序主體:
①前面我們提及到verilog的描述層次中有一個結(jié)構(gòu)化描述,結(jié)構(gòu)化的描述就是一點一點地例化(子模塊、單元門)來實現(xiàn)系統(tǒng)/設(shè)計的功能。程序的主體可以是只例化一些門單元,但是verilog的這種純結(jié)構(gòu)化方式的顯然是無法滿足現(xiàn)代設(shè)計要求的,因此純結(jié)構(gòu)化方式已經(jīng)被遺棄。
②程序的主體可以是行為描述,也就是通過一些verilog的行為語句來實現(xiàn)設(shè)計的要求/功能。行為描述主要有:控制流描述,過程描述,塊語句,時序控制等。對于行為描述,有可綜合的,有不可綜合的,可綜合的行為描述語句/語法就可以認為是RTL級描述時用到的,而不可綜合的行為描述語句/語法可以認為是仿真/建模時用到的。
③下面大概說一下行為描述情況,也就是行為描述中無論是可綜合還是不可綜合都可以使用的情況,具體的可綜合和不可綜合的行為級描述語法在后面會描述。
控制流描述:以assign關(guān)鍵字開頭的語句描述稱為控制流描述,主要用來實現(xiàn)一些簡單的組合邏輯。
塊語句:包含在關(guān)鍵字begin.。.end 、fork 。。.join之間的語句稱為塊語句。
過程描述:由initial模塊、always模塊、function模塊、task模塊這四個模塊實現(xiàn)的過程。
時序控制:延時控制、敏感信號控制語句等
④塊語句可以有一個名字,寫在begin/fork后面(如beign:adder_disc ),給它一個名字有什么好處呢?好處有兩個,一個是可以在塊內(nèi)部定義寄存器變量(注意哦,只能寄存器變量,這個寄存器變量在塊內(nèi)部使用),另外一個就是可以用disable這個關(guān)鍵字來中斷語句塊的執(zhí)行(具體怎么弄,請參看其他書籍,這里不詳述)
⑤begin.。.end內(nèi)的語句是串行的,這是從語法的結(jié)果上講的,但是它是可以綜合的,綜合出來的實際電路是并行的,也就是實際電路中,各條語句之間并不全是串行的,這里需要建立一個概念,方便講解以后的阻塞賦值和非阻塞賦值。而fork.。.join 內(nèi)的語句是同時進行的,然而這是不可綜合的。
⑥一個程序的主體中可以有多個initial模塊、always模塊、function模塊、task模塊。Function模塊和task模塊以后介紹。多個Initial模塊、always模塊之間是并行的,但是initial只執(zhí)行一次,而always是反復(fù)執(zhí)行。
initial一般是不可綜合的,用在仿真當(dāng)中;在進行仿真時,通常被用來描述測試模塊的初始化、監(jiān)視、波形生成等功能。
always用在可綜合的描述當(dāng)中,一般情況下由敏感列表觸發(fā)(至于什么是敏感列表,敏感列表怎么用,請參考其他書籍,我后面也會做一些記載),也就是用在描述RTL級的描述當(dāng)中,通常被用來對硬件的功能進行描述,可以實現(xiàn)組合邏輯和實現(xiàn)邏輯的功能。
上面沒有給出initial格式和always格式只是提了一下簡單應(yīng)用。
⑦程序的主體大多可以由結(jié)構(gòu)描述和行為描述構(gòu)成
模塊的例化:
①模塊的例化主要是為實現(xiàn)總體的功能,比如說我要設(shè)計一塊芯片,這個芯片的某個功能可以有某個芯片來完成,那我就可以調(diào)用這個芯片,例化就是調(diào)用這么一個概念。
②例化可以使用位置映射,也可使用名稱映射,由于位置映射可讀性太差,容易出錯,所有建議使用名稱映射。下面是名稱映射的格式:
被調(diào)用(例化)的模塊名字 自定義的例化模塊名(
被調(diào)用(例化)模塊的端口名 (本模塊中的線網(wǎng)變量名),
被調(diào)用(例化)模塊的端口名 (本模塊中的線網(wǎng)變量名)
③懸空處理:
在模塊例化時,如果被例化的模塊輸入管腳懸空,則該輸入為高阻Z,相當(dāng)于與外界隔絕,但是實際電路中。。。
如果將輸出管腳懸空,則該輸出管腳將被廢棄掉。
④不同端口位寬處理
當(dāng)模塊例化端口和被例化的端口位寬不同時,端口通過無符號數(shù)的右對齊截斷方式進行匹配。舉個例子說:
參數(shù)定義與映射:
①參數(shù)定義就是parameter 那一部分了,也就是可以用一個標(biāo)識符表示一個固定的參數(shù),當(dāng)然`define這種宏定義也可以實現(xiàn)這種功能,這樣子提高程序的可維護性和可讀性。
使用`define時語法為:`define A 2‘b10 或者`define A 2.
一般把`define宏定義語句放在模塊最前面,并且要注意,無論是在子模塊還是頂層模塊中,A 的值都代表2(調(diào)用時為 `A)(全局參數(shù))。
使用parameter定義的語法為 parameter A = 2或者parameter A= 2’d2;
一般放在模塊名字和模塊端口列表之間:模塊名 #(parameter A = XX,。。。。。)(端口列表);使用parameter定義的參數(shù)只在當(dāng)前模塊中有用(局部參數(shù))
localparam定義時,上層模塊不能調(diào)用傳遞參數(shù)。
②參數(shù)傳遞:
參數(shù)傳遞就是在編譯或者仿真的時候,進行維護時,對參數(shù)空閑重新復(fù)制而更改其值。傳遞的參數(shù)是子模塊中定義的parameter,傳遞的方法有兩種:
(1)使用’#’符號:在同一模塊中使用’#’符號,參數(shù)賦值順序必須與原始模塊定義的順序相同,并不是一定要給所以的參數(shù)賦值,但是不允許跳過任何一個參數(shù),即使是保持不變的值也要寫在相應(yīng)的位置。說了這么一大坨,還是舉個例子吧:
這樣子,A_WITH就是x1,B_WITH不改變,但是要寫在相應(yīng)的位置。
(2)使用defparam關(guān)鍵字
直接上格式:
評論
查看更多