VLSI設計 - Verilog入門



Verilog是一種硬體描述語言(HDL)。它是一種用於描述數字系統(如網路交換機、微處理器、儲存器或觸發器)的語言。這意味著,使用HDL,我們可以描述任何級別的數字硬體。用HDL描述的設計與技術無關,設計和除錯非常容易,通常比原理圖更有用,尤其對於大型電路。

Verilog支援多個抽象級別的設計。主要的三個級別是:

  • 行為級
  • 暫存器傳輸級
  • 門級

行為級

此級別使用併發演算法(行為級)來描述系統。每個演算法都是順序的,這意味著它由一系列逐一執行的指令組成。函式、任務和塊是主要元素。不考慮設計的結構實現。

暫存器傳輸級

使用暫存器傳輸級的設計使用操作和暫存器之間的資料傳輸來指定電路的特性。現代RTL程式碼的定義是“任何可綜合的程式碼都稱為RTL程式碼”。

門級

在邏輯級別內,系統的特性由邏輯連結及其時序特性描述。所有訊號都是離散訊號。它們只能具有確定的邏輯值(`0`,`1`,`X`,`Z`)。可用的操作是預定義的邏輯原語(基本門)。門級建模可能不是邏輯設計的正確方法。門級程式碼是使用綜合工具生成的,其網表用於門級模擬和後端。

詞法標記

Verilog語言源文字檔案是詞法標記流。一個標記由一個或多個字元組成,每個字元都精確地在一個標記中。

Verilog HDL使用的基本詞法標記類似於C程式語言中的標記。Verilog區分大小寫。所有關鍵字都小寫。

空白符

空白符可以包含空格、製表符、換行符和換頁符。除非這些字元用於分隔標記,否則它們會被忽略。

空白符字元包括空格、製表符、回車符、換行符和換頁符。

註釋

有兩種形式表示註釋:

  • 1) 單行註釋以標記 // 開始,以回車符結束。

例://這是單行語法

  • 2) 多行註釋以標記 /* 開始,以標記 */ 結束。

例:/* 這是多行語法 */

數字

您可以以二進位制、八進位制、十進位制或十六進位制格式指定數字。負數以二進位制補碼錶示。Verilog允許整數、實數以及有符號和無符號數。

語法如下:<size> <radix> <value>

可以在 <Size> 中定義大小或無大小數字,<radix> 定義它是二進位制、八進位制、十六進位制還是十進位制。

識別符號

識別符號是用於定義物件(例如函式、模組或暫存器)的名稱。識別符號應以字母字元或下劃線字元開頭。例:A_Z,a_z,_

識別符號是字母、數字、下劃線和 $ 字元的組合。它們最多可以包含 1024 個字元。

運算子

運算子是用於設定條件或操作變數的特殊字元。有時會使用一個、兩個或三個字元來對變數執行操作。

例:>,+,~,&!=。

Verilog關鍵字

在Verilog中具有特殊含義的詞稱為Verilog關鍵字。例如,assign、case、while、wire、reg、and、or、nand和module。它們不應用作識別符號。Verilog關鍵字還包括編譯器指令以及系統任務和函式。

門級建模

Verilog具有內建的原語,如邏輯閘、傳輸門和開關。這些很少用於設計工作,但在綜合後用於ASIC/FPGA單元建模。

門級建模具有兩個特性:

驅動強度 - 輸出門的強度由驅動強度定義。如果與源直接連線,則輸出最強。如果連線是透過導通電晶體,則強度降低;如果透過上拉/下拉電阻連線,則強度最低。通常不指定驅動強度,在這種情況下,強度預設為 strong1 和 strong0。

延遲 - 如果未指定延遲,則門沒有傳播延遲;如果指定兩個延遲,則第一個表示上升延遲,第二個表示下降延遲;如果只指定一個延遲,則上升和下降延遲相等。在綜合中可以忽略延遲。

門原語

Verilog中使用具有一個輸出和多個輸入的基本邏輯閘。GATE 使用 and、nand、or、nor、xor、xnor 這些關鍵字中的一個,用於 Verilog 中 N 個輸入和 1 個輸出。

Example:  
   Module gate() 
   Wire ot0; 
   Wire ot1; 
   Wire ot2; 
   
   Reg in0,in1,in2,in3; 
   Not U1(ot0,in0); 
   Xor U2(ot1,in1,in2,in3); 
   And U3(ot2, in2,in3,in0) 

傳輸門原語

傳輸門原語包括緩衝器和反相器。它們具有單個輸入和一個或多個輸出。在下方的門例項化語法中,GATE 代表關鍵字 buf 或 NOT 門。

示例:Not,buf,bufif0,bufif1,notif0,notif1

Not – n 輸出反相器

Buf – n 輸出緩衝器

Bufifo – 三態緩衝器,低電平使能

Bufif1 – 三態緩衝器,高電平使能

Notifo – 三態反相器,低電平使能

Notif1 – 三態反相器,高電平使能

Example:  
   Module gate() 
   Wire out0; 
   Wire out1; 
   
   Reg in0,in1;
   Not U1(out0,in0); 
   Buf U2(out0,in0); 

資料型別

值集

Verilog 主要由四個基本值組成。Verilog 中使用到的所有 Verilog 資料型別都儲存這些值:

0(邏輯零,或假條件)

1(邏輯一,或真條件)

x(未知邏輯值)

z(高阻態)

x 和 z 的使用在綜合中非常有限。

線網 (Wire)

線網用於表示電路中的物理線,並用於連線門或模組。線網的值只能讀取,不能在函式或塊中賦值。線網不能儲存值,但始終由連續賦值語句或將線網連線到門/模組的輸出驅動。其他特定型別的線網包括:

Wand(線與) - Wand 的值取決於連線到它的所有裝置驅動器的邏輯與。

Wor(線或) - Wor 的值取決於連線到它的所有裝置驅動器的邏輯或。

Tri(三態) - 連線到 tri 的所有驅動器必須為 z,只有一個例外(它決定 tri 的值)。

Example: 
   Wire [msb:lsb] wire_variable_list; 
   Wirec // simple wire 
   Wand d; 
   
   Assign d = a; // value of d is the logical AND of 
   Assign d = b; // a and b 
   Wire [9:0] A; // a cable (vector) of 10 wires. 
   
   Wand [msb:lsb] wand_variable_list; 
   Wor [msb:lsb] wor_variable_list; 
   Tri [msb:lsb] tri_variable_list; 

暫存器 (Register)

reg(暫存器)是一個數據物件,它儲存從一個過程賦值到下一個過程賦值的值,並且僅用於不同的函式和過程塊。reg 是一個簡單的 Verilog 變數型別暫存器,不能暗示物理暫存器。在多位暫存器中,資料以無符號數的形式儲存,並且不使用符號擴充套件。

示例:

reg c; // 單個 1 位暫存器變數

reg [5:0] gem; // 一個 6 位向量;

reg [6:0] d, e; // 兩個 7 位變數

輸入 (Input)、輸出 (Output)、雙向 (Inout)

這些關鍵字用於宣告任務或模組的輸入、輸出和雙向埠。這裡的輸入和 inout 埠是線網型別,輸出埠配置為線網、暫存器、wand、wor 或 tri 型別。預設始終為線網型別。

示例

Module sample(a, c, b, d);  
Input c;   // An input where wire is used. 

Output a, b;  // Two outputs where wire is used. 
Output [2:0] d;  /* A three-bit output. One must declare type in a separate statement. */ 
reg [1:0] a;  // The above ‘a’ port is for declaration in reg.

整數 (Integer)

整數用於通用變數。它們主要用於迴圈索引、常量和引數。它們是“reg”型別的資料型別。它們將資料儲存為有符號數,而顯式宣告的 reg 型別將它們儲存為無符號資料。如果在編譯時未定義整數,則預設大小為 32 位。

如果整數儲存一個常量,則綜合器會在編譯時將其調整為所需的最小寬度。

示例

Integer c;   // single 32-bit integer 
Assign a = 63;  // 63 defaults to a 7-bit variable. 

Supply0,Supply1

Supply0 定義連線到邏輯 0(接地)的線網,Supply1 定義連線到邏輯 1(電源)的線網。

示例

supply0 logic_0_wires; 
supply0 gnd1;  // equivalent to a wire assigned as 0 

supply1 logic_1_wires; 
supply1 c, s;

時間 (Time)

時間是一個 64 位量,可以與 $time 系統任務一起使用以儲存模擬時間。時間不支援綜合,因此僅用於模擬目的。

示例

time time_variable_list; 
time c; 
c = $time;   //c = current simulation time

引數 (Parameter)

引數定義一個常量,可以在使用模組時設定,允許在例項化過程中自定義模組。

Example 
Parameter add = 3’b010, sub = 2’b11; 
Parameter n = 3; 
Parameter [2:0] param2 = 3’b110; 

reg [n-1:0] jam; /* A 3-bit register with length of n or above. */ 
always @(z) 
y = {{(add - sub){z}};  

if (z)
begin 
   state = param2[1];
else
   state = param2[2]; 
end 

運算子

算術運算子

這些運算子執行算術運算。+ 和 - 用作一元 (x) 或二元 (z-y) 運算子。

包含在算術運算中的運算子為:

+(加法)、-(減法)、*(乘法)、/(除法)、%(模)

示例

parameter v = 5;
reg[3:0] b, d, h, i, count; 
h = b + d; 
i = d - v; 
cnt = (cnt +1)%16; //Can count 0 thru 15.

關係運算符

這些運算子比較兩個運算元,並將結果返回為一位,1 或 0。

線網和暫存器變數為正。因此,(-3'd001) == 3'd111 和 (-3b001) > 3b110。

包含在關係運算中的運算子為:

  • ==(等於)
  • !=(不等於)
  • >(大於)
  • >=(大於或等於)
  • <(小於)
  • <=(小於或等於)

示例

if (z = = y) c = 1; 
   else c = 0; // Compare in 2’s compliment; d>b 
reg [3:0] d,b; 

if (d[3]= = b[3]) d[2:0] > b[2:0]; 
   else b[3]; 
Equivalent Statement 
e = (z == y);

按位運算子

按位運算子對兩個運算元進行逐位比較。

包含在按位運算中的運算子為:

  • &(按位與)
  • |(按位或)
  • ~(按位非)
  • ^(按位異或)
  • ~^ 或 ^~(按位異或非)

示例

module and2 (d, b, c); 
input [1:0] d, b; 
output [1:0] c; 
assign c = d & b; 
end module 

邏輯運算子

邏輯運算子是按位運算子,僅用於單位元運算元。它們返回一位值,0 或 1。它們可以作用於整數或位組、表示式,並將所有非零值視為 1。邏輯運算子通常用於條件語句,因為它們作用於表示式。

包含在邏輯運算中的運算子為:

  • !(邏輯非)
  • &&(邏輯與)
  • ||(邏輯或)

示例

wire[7:0] a, b, c; // a, b and c are multibit variables. 
reg x; 

if ((a == b) && (c)) x = 1; //x = 1 if a equals b, and c is nonzero. 
   else x = !a; // x =0 if a is anything but zero.

歸約運算子

歸約運算子是按位運算子的一元形式,作用於運算元向量的所有位。這些也返回一位值。

包含在歸約運算中的運算子為:

  • &(歸約與)
  • |(歸約或)
  • ~&(歸約與非)
  • ~|(歸約或非)
  • ^(歸約異或)
  • ~^ 或 ^~(歸約異或非)

示例

Module chk_zero (x, z); 

Input [2:0] x; 
Output z; 
Assign z = & x; // Reduction AND 
End module

移位運算子

移位運算子根據語法中第二個運算元指定的位數,對第一個運算元進行移位。對於左移和右移,空位都填充零(不使用符號擴充套件)。

包含在移位運算中的運算子為:

  • <<(左移)
  • >>(右移)

示例

Assign z = c << 3; /* z = c shifted left 3 bits;

空位填充 0 */

連線運算子

連線運算子將兩個或多個運算元組合成一個更大的向量。

包含在連線運算中的運算子為:{ }(連線)

示例

wire [1:0] a, h; wire [2:0] x; wire [3;0] y, Z; 
assign x = {1’b0, a}; // x[2] = 0, x[1] = a[1], x[0] = a[0] 
assign b = {a, h}; /* b[3] = a[1], b[2] = a[0], b[1] = h[1], 
b[0] = h[0] */ 
assign {cout, b} = x + Z; // Concatenation of a result 

複製運算子

複製運算子用於建立專案的多個副本。

在複製運算中使用的運算子為:{n{item}}(專案的 n 倍複製)

示例

Wire [1:0] a, f; wire [4:0] x; 
Assign x = {2{1’f0}, a}; // Equivalent to x = {0,0,a } 
Assign y = {2{a}, 3{f}}; //Equivalent to y = {a,a,f,f} 
For synthesis, Synopsis did not like a zero replication.

For example:- 
Parameter l = 5, k = 5; 
Assign x = {(l-k){a}}

條件運算子

條件運算子綜合成一個多路選擇器。它與C/C++中使用的型別相同,根據條件計算兩個表示式中的一個。

條件運算中使用的運算子為:

(條件) ? (條件為真時的結果) :

(條件為假時的結果)

示例

Assign x = (g) ? a : b; 
Assign x = (inc = = 2) ? x+1 : x-1; 
/* if (inc), x = x+1, else x = x-1 */ 

運算元

字面量

字面量是在Verilog表示式中使用的常量值運算元。兩種常用的Verilog字面量是:

  • 字串 - 字串字面量運算元是一個字元的一維陣列,用雙引號 (" ") 括起來。

  • 數值 - 常量數值運算元以二進位制、八進位制、十進位制或十六進位制表示。

示例

n - 表示位數的整數

F - 四種可能的基數格式之一:

b表示二進位制,o表示八進位制,d表示十進位制,h表示十六進位制。

“time is”  // string literal 
267        // 32-bit decimal number 
2’b01      // 2-bit binary 
20’hB36F   // 20-bit hexadecimal number 
‘062       // 32-bit octal number 

線網、暫存器和引數

線網、暫存器和引數是Verilog表示式中用作運算元的資料型別。

位選擇“x[2]”和部分選擇“x[4:2]”

位選擇和部分選擇分別用於使用方括號“[ ]”從線網、暫存器或引數向量中選擇一位和多位。位選擇和部分選擇也像它們的主要資料物件一樣用作表示式中的運算元。

示例

reg [7:0] x, y; 
reg [3:0] z; 
reg a; 
a = x[7] & y[7];      // bit-selects 
z = x[7:4] + y[3:0];  // part-selects 

函式呼叫

在函式呼叫中,函式的返回值直接用於表示式,無需先將其賦值給暫存器或線網。只需將函式呼叫作為一種運算元型別即可。需要確保知道函式呼叫的返回值的位寬。

Example  
Assign x = y & z & chk_yz(z, y); // chk_yz is a function 

. . ./* Definition of the function */ 
Function chk_yz; // function definition 
Input z,y; 
chk_yz = y^z; 
End function 

模組

模組宣告

在Verilog中,模組是主要的電路設計單元。它指明模組名稱和埠列表(引數)。接下來的幾行指定每個埠的輸入/輸出型別(input、output或inout)和位寬。預設埠位寬為1位。埠變數必須用wire、wand…、reg宣告。預設埠變數為wire。通常,輸入為wire,因為它們的資料在模組外部鎖存。如果輸出訊號儲存在模組內部,則輸出為reg型別。

示例

module sub_add(add, in1, in2, out); 
input add; // defaults to wire 
input [7:0] in1, in2; wire in1, in2; 

output [7:0] out; reg out; 
... statements ... 
End module 

連續賦值

模組中的連續賦值用於將值賦給線網,這是在always或initial塊外部使用的常規賦值。此賦值使用顯式的assign語句完成,或者在宣告線網時為其賦值。連續賦值在模擬期間連續執行。賦值語句的順序不影響它。如果任何右側輸入訊號發生變化,它將改變左側輸出訊號。

示例

Wire [1:0] x = 2’y01;   // assigned on declaration 
Assign y = c | d;       // using assign statement 
Assign d = a & b; 
/* the order of the assign statements does not matter. */ 

模組例化

模組宣告是建立實際物件的模板。模組在其他模組內部例化,每個例化都從該模板建立一個單個物件。例外情況是頂層模組,它本身就是一個例化。模組的埠必須與模板中定義的埠匹配。它被指定為:

  • 按名稱,使用點“ .模板埠名 (連線到埠的線網名稱)” 。或者

  • 按位置,將埠放在模板和例項的埠列表中的相同位置。

示例

MODULE DEFINITION 
Module and4 (x, y, z); 
Input [3:0] x, y; 
Output [3:0] z; 
Assign z = x | y; 
End module 
廣告
© . All rights reserved.