Verilog HDL的程式結構及其描述

2021-08-06 00:07:43 字數 4224 閱讀 4930

一、verilog hdl的程式結構

首先我們不開始講verilog hdl的語法,我們從verilog hdl的程式結構出發。相信大家都看過晶元吧,它有個名字,有個外殼,外殼向外伸出有引腳(bga封裝的那種請不要亂攪和...),然後晶元它可以實現一定的功能。

ok,知道這些之後,我們就來看看verilog hdl的描述數位電路的程式結構吧。

在解釋結構的時候,我拿晶元設計這個例子來打乙個不恰當的比方。

veriloghdl程式的大致結構就是這麼乙個形式,每乙個模組的結構都是一致的只不過語句之間存在一些差別,每一部分的具體描述將在後面進行。

二、verilog程式結構的簡單描述

ok,現在讓我們現在開始了解一下一些語法和注意事項(注意,我這裡不會把語法講得很細很細,我主要是描述一些(我,或者初學者)易忘的,關鍵的語法和知識點),描述的順序不一定按照上面的各個部分喲,我們先描述一些veriloghdl程式必須的。

首先是模組說明:

此外無論是能夠綜合成電路的verilog程式還是只是**的程式,都需要以模組的形式給出。

模組名:

①模組名的定義要符合識別符號的定義,至於什麼是識別符號,以後會說的。此外也要注意書寫的規範性。

埠說明:

①埠可以比方成晶元的輸入輸入管腳,它只有三種型別:輸入,輸出,雙向;

②埠有一些附加屬性,如資料型別、符號特性、位寬等;input埠只能是線網型別,output可以是暫存器型別也可以是線網型別,inout也只能是線網型別。至於線網型別和暫存器型別,在以後的資料型別中會介紹。

③當埠是匯流排型別時,可以簡單地理解為埠有多位時,對應於同時描述晶元的多個管腳時,可以給埠加上位寬。即input wire  [m:n]  a;如果m>n,則為降序,a[m]為最高位,位寬為m-n+1位;如果m

④埠的屬性宣告順序可以是:

埠的輸入輸出   資料型別   有無符號   位寬   埠名稱 ;

如:output  reg  signed  [7:0] a;

注:資料型別沒有寫則預設為wire 型,有無符號沒有寫預設為無符號型;位寬沒有寫預設為1bit 。

⑤當書寫完埠宣告是,括號後面的『;』千萬不要忘記。

程式主體:

①前面我們提及到verilog的描述層次中有乙個結構化描述,結構化的描述就是一點一點地例化(子模組、單元門)來實現系統/設計的功能。程式的主體可以是只例化一些門單元,但是verilog的這種純結構化方式的顯然是無法滿足現代設計要求的,因此純結構化方式已經被遺棄。

②程式的主體可以是行為描述,也就是通過一些verilog的行為語句來實現設計的要求/功能。行為描述主要有:控制流描述,過程描述,塊語句,時序控制等。對於行為描述,有可綜合的,有不可綜合的,可綜合的行為描述語句/語法就可以認為是rtl級描述時用到的,而不可綜合的行為描述語句/語法可以認為是**/建模時用到的。

③下面大概說一下行為描述情況,也就是行為描述中無論是可綜合還是不可綜合都可以使用的情況,具體的可綜合和不可綜合的行為級描述語法在後面會描述。

控制流描述:以assign關鍵字開頭的語句描述稱為控制流描述,主要用來實現一些簡單的組合邏輯。

塊語句:包含在關鍵字begin...end 、fork ...join之間的語句稱為塊語句。

過程描述:由initial模組、always模組、function模組、task模組這四個模組實現的過程。

時序控制:延時控制、敏感訊號控制語句等

④塊語句可以有乙個名字,寫在begin/fork後面(如beign:adder_disc ),給它乙個名字有什麼好處呢?好處有兩個,乙個是可以在塊內部定義暫存器變數(注意哦,只能暫存器變數,這個暫存器變數在塊內部使用),另外乙個就是可以用disable這個關鍵字來中斷語句塊的執行(具體怎麼弄,請參看其他書籍,這裡不詳述)

⑤begin...end內的語句是序列的,這是從語法的結果上講的,但是它是可以綜合的,綜合出來的實際電路是並行的,也就是實際電路中,各條語句之間並不全是序列的,這裡需要建立乙個概念,方便講解以後的阻塞賦值和非阻塞賦值。而fork...join 內的語句是同時進行的,然而這是不可綜合的。

⑥乙個程式的主體中可以有多個initial模組、always模組、function模組、task模組。function模組和task模組以後介紹。多個initial模組、always模組之間是並行的,但是initial只執行一次,而always是反覆執行。

initial一般是不可綜合的,用在**當中;在進行**時,通常被用來描述測試模組的初始化、監視、波形生成等功能。

always用在可綜合的描述當中,一般情況下由敏感列表觸發(至於什麼是敏感列表,敏感列表怎麼用,請參考其他書籍,我後面也會做一些記載),也就是用在描述rtl級的描述當中,通常被用來對硬體的功能進行描述,可以實現組合邏輯和實現邏輯的功能。

上面沒有給出initial格式和always格式只是提了一下簡單應用。

⑦程式的主體大多可以由結構描述和行為描述構成

模組的例化:

①模組的例化主要是為實現總體的功能,比如說我要設計一塊晶元,這個晶元的某個功能可以有某個晶元來完成,那我就可以呼叫這個晶元,例化就是呼叫這麼乙個概念。

②例化可以使用位置對映,也可使用名稱對映,由於位置對映可讀性太差,容易出錯,所有建議使用名稱對映。下面是名稱對映的格式:

被呼叫(例化)的模組名字     自定義的例化模組名(

.被呼叫(例化)模組的埠名     (本模組中的線網變數名),

....被呼叫(例化)模組的埠名     (本模組中的線網變數名));

③懸空處理:

在模組例化時,如果被例化的模組輸入管腳懸空,則該輸入為高阻z,相當於與外界隔絕,但是實際電路中...

如果將輸出管腳懸空,則該輸出管腳將被廢棄掉。

④不同埠位寬處理

當模組例化埠和被例化的埠位寬不同時,埠通過無符號數的右對齊截斷方式進行匹配。舉個例子說:

引數定義與對映:

①引數定義就是parameter 那一部分了,也就是可以用乙個識別符號表示乙個固定的引數,當然`define這種巨集定義也可以實現這種功能,這樣子提高程式的可維護性和可讀性。

使用`define時語法為:`define  a  2'b10 或者`define a 2.

一般把`define巨集定義語句放在模組最前面,並且要注意,無論是在子模組還是頂層模組中,a 的值都代表2(呼叫時為 `a)(全域性引數)。

使用parameter定義的語法為 parameter  a = 2或者parameter a= 2』d2;

一般放在模組名字和模組埠列表之間:模組名 #(parameter a = xx,.....)(埠列表);使用parameter定義的引數只在當前模組中有用(區域性引數)

localparam定義時,上層模組不能呼叫傳遞引數。

②引數傳遞:

引數傳遞就是在編譯或者**的時候,進行維護時,對引數空閒重新複製而更改其值。傳遞的引數是子模組中定義的parameter,傳遞的方法有兩種:

(1)使用』#』符號:在同一模組中使用』#』符號,引數賦值順序必須與原始模組定義的順序相同,並不是一定要給所以的引數賦值,但是不允許跳過任何乙個引數,即使是保持不變的值也要寫在相應的位置。說了這麼一大坨,還是舉個例子吧:

這樣子,a_with就是x1,b_with不改變,但是要寫在相應的位置。

(2)使用defparam關鍵字

直接上格式:

COBOL的程式結構

cobol程式的結構比較嚴格。乙個完整的cobol程式由4部 division 組成 identification division.標識部 environment division.環境部 data division.資料部 procedure division.過程部 而每個部又由若干節 sec...

C的程式結構

認識c程式的組成結構,是c開發的基礎。比如,乙個簡單的c程式 include define pi 3.14 void test int a int main void test int a hello c 3 4 3.140000 對比上面的程式,c語言的程式結構如下 1 包含指令 2 定義常量 3...

C 程式結構

c 中的組織結構的關鍵概念是程式 program 命名空間 namespace 型別 type 成員 member 和程式集 assembly 命名空間 型別 成員 類 class 資料成員 字段 函式成員 方法,屬性,索引器,事件,運算子,構造 析構函式 介面 inte ce 函式成員 附經典理解...