1. 程式人生 > 其它 >Verilog語法之三:變數

Verilog語法之三:變數

本文首發於微信公眾號“花螞蟻”,想要學習FPGA及Verilog的同學可以關注一下。

變數即在程式執行過程中其值可以改變的量,在Verilog HDL中變數的資料型別有很多種,這裡只對常用的幾種進行介紹。

網路資料型別表示結構實體(例如門)之間的物理連線。網路型別的變數不能儲存值,而且它必需受到驅動器(例如門或連續賦值語句,assign)的驅動。

如果沒有驅動器連線到網路型別的變數上,則該變數就是高阻的,即其值為z常用的網路資料型別包括wire型和tri型。這兩種變數都是用於聯結器件單元,它們具有相同的語法格式和功能。

之所以提供這兩種名字來表達相同的概念是為了與模型中所使用的變數的實際情況相一致。wire型變數通常是用來表示單個門驅動或連續賦值語句驅動的網路型資料,tri型變數則用來表示多驅動器驅動的網路型資料。

如果wire型或tri型變數沒有定義邏輯強度(logic strength),在多驅動源的情況下,邏輯值會發生衝突從而產生不確定值。下表為wire型和tri型變數的真值表。

一. wire型

wire型資料常用來表示用於以assign關鍵字指定的組合邏輯訊號。Verilog程式模組中輸入輸出訊號型別預設時自動定義為wire型。wire型訊號可以用作任何方程式的輸入,也可以用作“assign”語句或例項元件的輸出。

wire型訊號的格式同reg型訊號的很類似。其格式如下:

wire [n-1:0] 資料名1,資料名2,…資料名i; //共有i條匯流排,每條匯流排內有n條線路 

wire [n:1] 資料名1,資料名2,…資料名i; 

wire是wire型資料的確認符,[n-1:0]和[n:1]代表該資料的位寬,即該資料有幾位。最後跟著的是資料的名字。如果一次定義多個數據,資料名之間用逗號隔開。宣告語句的最後要用分號表示語句結束。看下面的幾個例子。

wire a; //定義了一個一位的wire型資料
wire [7:0] b; //定義了一個八位的wire型資料
wire [4:1] c, d; //定義了二個四位的wire型資料

二. reg型

暫存器是資料儲存單元的抽象。暫存器資料型別的關鍵字是reg。通過賦值語句可以改變暫存器儲存的值,其作用與改變觸發器儲存的值相當。

Verilog HDL語言提供了功能強大的結構語句使設計者能有效地控制是否執行這些賦值語句。這些控制結構用來描述硬體觸發條件,例如時鐘的上升沿和多路器的選通訊號。reg型別資料的預設初始值為不定值,x。

reg型資料常用來表示用於“always”模組內的指定訊號,常代表觸發器。通常,在設計中要由“always”塊通過使用行為描述語句來表達邏輯關係。在“always”塊內被賦值的每一個訊號都必須定義成reg型。

reg型資料的格式如下:

reg [n-1:0] 資料名1,資料名2,… 資料名i;

reg [n:1]  資料名1,資料名2,… 資料名i;

reg是reg型資料的確認識別符號,[n-1:0]和[n:1]代表該資料的位寬,即該資料有幾位(bit)。最後跟著的是資料的名字。如果一次定義多個數據,資料名之間用逗號隔開。宣告語句的最後要用分號表示語句結束。看下面的幾個例子:

reg rega; //定義了一個一位的名為rega的reg型資料
reg [3:0]  regb; //定義了一個四位的名為regb的reg型資料
reg [4:1] regc, regd; //定義了兩個四位的名為regc和regd的reg型資料

對於reg型資料,其賦值語句的作用就象改變一組觸發器的儲存單元的值

在Verilog中有許多構造(construct)用來控制何時或是否執行這些賦值語句。這些控制構造可用來描述硬體觸發器的各種具體情況,如觸發條件用時鐘的上升沿等,或用來描述具體判斷邏輯的細節,如各種多路選擇器。

reg型資料的預設初始值是不定值x。reg型資料可以賦正值,也可以賦負值。但當一個reg型資料是一個表示式中的運算元時,它的值被當作是無符號值,即正值。例如:當一個四位的暫存器用作表示式中的運算元時,如果開始暫存器被賦以值-1,則在表示式中進行運算時,其值被認為是+15。

注意:

reg型只表示被定義的訊號將用在“always”塊內,理解這一點很重要。並不是說reg型訊號一定是暫存器或觸發器的輸出。雖然reg型訊號常常是暫存器或觸發器的輸出,但並不一定總是這樣。

初學者往往會對wire和reg的用法混淆,下面是對wire和reg用法的總結:

wire用法總結

1.wire可以在Verilog中表示任意寬度的單線/匯流排

2.wire可以用於模組的輸入和輸出埠以及一些其他元素並在實際模組宣告中

3.wire不能儲存值(無狀態),並且不能在always @塊內賦值(=或<=)左側使用。

4. wire是assign語句左側唯一的合法型別

5.wire只能用於組合邏輯

reg用法總結

1. 類似於電線,但可以儲存資訊(有記憶體,有狀態)允許連線到模組的輸入埠,但不能連線到例項化的輸出

2. 在模組宣告中,reg可以用作輸出,但不能用作輸入

3. 在always@(......)語句塊內,= 或者 <= 賦值語句的左邊必須是是reg變數

在initial語句塊內,= 賦值語句的左邊必須是是reg變數

4. Reg不能用於assign賦值語句的左側

5. 當與@(posedge clock)塊一起使用時,reg可用於建立暫存器

6. reg可用於組合邏輯和時序邏輯

構建一個模組module時

input必須是wire

output可以是wire也可以是reg

inout必須是wire

例化模組時

外部連線input埠的可以是wire也可以是reg

外部連線output埠的必須是wire

外部連線inout埠的必須是wire

三. memory型

Verilog HDL通過對reg型變數建立陣列來對儲存器建模,可以描述RAM型儲存器,ROM儲存器和reg檔案。陣列中的每一個單元通過一個數組索引進行定址。在Verilog語言中沒有多維陣列存在。 memory型資料是通過擴充套件reg型資料的地址範圍來生成的。其格式如下:

reg [n-1:0] 儲存器名[m-1:0];

在這裡,reg[n-1:0]定義了儲存器中每一個儲存單元的大小,即該儲存單元是一個n位的暫存器。儲存器名後的[m-1:0]或[m:1]則定義了該儲存器中有多少個這樣的暫存器。最後用分號結束定義語句。下面舉例說明:

reg [7:0] mema[255:0];

這個例子定義了一個名為mema的儲存器,該儲存器有256個8位的儲存器。該儲存器的地址範圍是0到255。注意:對儲存器進行地址索引的表示式必須是常數表示式。

另外,在同一個資料型別宣告語句裡,可以同時定義儲存器型資料和reg型資料。見下例:

parameter wordsize=16, //定義二個引數。
memsize=256;
reg [wordsize-1:0] mem[memsize-1:0],writereg, readreg;

儘管memory型資料和reg型資料的定義格式很相似,但要注意其不同之處。如一個由n個1位暫存器構成的儲存器組是不同於一個n位的暫存器的。見下例:

reg [n-1:0] rega;  //一個n位的暫存器
reg mema [n-1:0]; //一個由n個1位暫存器構成的儲存器組 

一個n位的暫存器可以在一條賦值語句裡進行賦值,而一個完整的儲存器則不行。見下例:

rega =0; //合法賦值語句
mema =0; //非法賦值語句 

如果想對memory中的儲存單元進行讀寫操作,必須指定該單元在儲存器中的地址。下面的寫法是正確的。

mema[3]=0; //給memory中的第3個儲存單元賦值為0。

進行定址的地址索引可以是表示式,這樣就可以對儲存器中的不同單元進行操作。表示式的值可以取決於電路中其它的暫存器的值。例如可以用一個加法計數器來做RAM的地址索引。

本文首發於微信公眾號“花螞蟻”,想要學習FPGA及Verilog的同學可以關注一下。