SystemVerilog是一種硬件描述和驗證語(yǔ)言(HDVL),它基于IEEE 1364-2001 Verilog硬件描述語(yǔ)言(HDL),并對其進(jìn)行了擴展,包括擴充了C語(yǔ)言數據類(lèi)型、結構、壓縮和非壓縮數組、接口、斷言等等,這些都使得SystemVerilog在一個(gè)更高的抽象層次上提高了設計建模的能力。 SystemVerilog由Accellera開(kāi)發(fā),它主要定位在芯片的實(shí)現和驗證流程上,并為系統級的設計流程提供了強大的連接能力。下面我們從幾個(gè)方面對SystemVerilog所作的增強進(jìn)行簡(jiǎn)要的介紹,期望能夠通過(guò)這個(gè)介紹使大家對SystemVerilog有一個(gè)概括性的了解。 1. 接口(Interface) Verilog模塊之間的連接是通過(guò)模塊端口進(jìn)行的。為了給組成設計的各個(gè)模塊定義端口,我們必須對期望的硬件設計有一個(gè)詳細的認識。不幸的是,在設計的早期,我們很難把握設計的細節。而且,一旦模塊的端口定義完成后,我們也很難改變端口的配置。另外,一個(gè)設計中的許多模塊往往具有相同的端口定義,在 Verilog中,我們必須在每個(gè)模塊中進(jìn)行相同的定義,這為我們增加了無(wú)謂的工作量。 SystemVerilog提供了一個(gè)新的、高層抽象的模塊連接,這個(gè)連接被稱(chēng)為接口(Interface)。接口在關(guān)鍵字interface和endinterface之間定義,它獨立于模塊。接口在模塊中就像一個(gè)單一的端口一樣使用。在最簡(jiǎn)單的形式下,一個(gè)接口可以認為是一組線(xiàn)網(wǎng)。例如,可以將PCI總線(xiàn)的所有信號綁定在一起組成一個(gè)接口。通過(guò)使用接口,我們在進(jìn)行一個(gè)設計的時(shí)候可以不需要首先建立各個(gè)模塊間的互連。隨著(zhù)設計的深入,各個(gè)設計細節也會(huì )變得越來(lái)越清晰,而接口內的信號也會(huì )很容易地表示出來(lái)。當接口發(fā)生變化時(shí),這些變化也會(huì )在使用該接口的所有模塊中反映出來(lái),而無(wú)需更改每一個(gè)模塊。下面是一個(gè)接口的使用實(shí)例: interface chip_bus; // 定義接口 wire read_request, read_grant; wire [7:0] address, data; endinterface: chip_bus module RAM (chip_bus io, // 使用接口 input clk); // 可以使用io.read_request引用接口中的一個(gè)信號 endmodule module CPU(chip_bus io, input clk); ... endmodule module top; reg clk = 0; chip_bus a; // 實(shí)例接口 // 將接口連接到模塊實(shí)例 RAM mem(a, clk); CPU cpu(a, clk); endmodule 實(shí)際上,SystemVerilog的接口不僅僅可以表示信號的綁定和互連。由于SystemVerilog的接口中可以包含參數、常量、變量、結構、函數、任務(wù)、initial塊、always塊以及連續賦值語(yǔ)句,所以SystemVerilog的接口還可以包含內建的協(xié)議檢查以及被使用該接口的模塊所共用的功能。 2. 全局聲明和語(yǔ)句 在Verilog中,除了一個(gè)模塊可以作為模塊實(shí)例引用其他模塊外,并不存在一個(gè)全局空間。另外,Verilog允許任意數目的頂層模塊,因此會(huì )產(chǎn)生毫無(wú)關(guān)聯(lián)的層次樹(shù)。 SystemVeriog增加了一個(gè)被稱(chēng)為$root的隱含的頂級層次。任何在模塊邊界之外的聲明和語(yǔ)句都存在于$root空間中。所有的模塊,無(wú)論它處于哪一個(gè)設計層次,都可以引用$root中聲明的名字。這樣,如果某些變量、函數或其它信息被設計中的所有模塊共享,那么我們就可以將它們作為全局聲明和語(yǔ)句。全局聲明和語(yǔ)句的一個(gè)使用實(shí)例如下: reg error _flag; // 全局變量 function compare (...); // 全局函數 always @(error_flag) // 全局語(yǔ)句 ... module test; chip1 u1 (...) endmodule module chip1 (...); FSM u2 (...); always @(data) error_flag = compare(data, expected); endmodule module FSM (...); ... always @(state) error_flag = compare(state, expected); endmodule 3. 時(shí)間單位和精度 在Verilog中,表示時(shí)間的值使用一個(gè)數來(lái)表示,而不帶有任何時(shí)間單位。例如: forever #5 clock = ~clock; 從這一句中我們無(wú)法判斷5代表的是5ns? 5ps? 還是其他。Verilog的時(shí)間單位和精度是作為每一個(gè)模塊的屬性,并使用編譯器指令`timescale來(lái)設置。使用這種方法具有固有的缺陷,因為編譯器指令的執行依賴(lài)于源代碼的編譯順序,編譯器總是將它遇到的最后一個(gè)`timescale設置的時(shí)間單位和精度作為之后的標準。那么,假如有些模塊之前沒(méi)有使用`timescale設置時(shí)間單位和精度,這就有可能出現同一個(gè)源代碼的不同仿真會(huì )出現不同結果的情況。 SystemVerilog為了控制時(shí)間單位加入了兩個(gè)重要的增強。首先,時(shí)間值可以顯式地指定一個(gè)單位。時(shí)間單位可以是s、ms、ns、ps或fs。時(shí)間單位作為時(shí)間值的后綴出現。例如: forever #5ns clock = ~clock; 其次,SystemVerilog允許使用新的關(guān)鍵字(timeunits和timeprecision)來(lái)指定時(shí)間單位和精度。這些聲明可以在任何模塊中指定,同時(shí)也可以在$root空間中全局指定。時(shí)間單位和精度必須是10的冪,范圍可以從s到fs。例如: timeunits 1ns; timeprecision 10ps; 4. 抽象數據類(lèi)型 Verilog提供了面向底層硬件的線(xiàn)網(wǎng)、寄存器和變量數據類(lèi)型。這些類(lèi)型代表了4態(tài)邏輯值,通常用來(lái)在底層上對硬件進(jìn)行建模和驗證。線(xiàn)網(wǎng)數據類(lèi)型還具有多個(gè)強度級別,并且能夠為多驅動(dòng)源的線(xiàn)網(wǎng)提供解析功能。 SystemVerilog包括了C語(yǔ)言的char和int數據類(lèi)型,它允許在Verilog模型和驗證程序中直接使用C和C++代碼。Verilog PLI不再需要集成總線(xiàn)功能模型、算法模型和C函數。SystemVerilog還為Verilog加入了幾個(gè)新的數據類(lèi)型,以便能夠在更抽象的層次上建模硬件。 char:一個(gè)兩態(tài)的有符號變量,它與C語(yǔ)言中的char數據類(lèi)型相同,可以是一個(gè)8位整數(ASCII)或short int(Unicode); int:一個(gè)兩態(tài)的有符號變量,它與C語(yǔ)言中的int數據類(lèi)型相似,但被精確地定義成32位; shortint:一個(gè)兩態(tài)的有符號變量,被精確地定義成16位; longint:一個(gè)兩態(tài)的有符號變量,它與C語(yǔ)言中的long數據類(lèi)型相似,但被精確地定義成64位; byte:一個(gè)兩態(tài)的有符號變量,被精確地定義成8位; bit:一個(gè)兩態(tài)的可以具有任意向量寬度的無(wú)符號數據類(lèi)型,可以用來(lái)替代Verilog的reg數據類(lèi)型; logic:一個(gè)四態(tài)的可以具有任意向量寬度的無(wú)符號數據類(lèi)型,可以用來(lái)替代Verilog的線(xiàn)網(wǎng)或reg數據類(lèi)型,但具有某些限制; shortreal:一個(gè)兩態(tài)的單精度浮點(diǎn)變量,與C語(yǔ)言的float類(lèi)型相同; void:表示沒(méi)有值,可以定義成一個(gè)函數的返回值,與C語(yǔ)言中的含義相同。 SystemVerilog的bit和其他數據類(lèi)型允許用戶(hù)使用兩態(tài)邏輯對設計建模,這種方法對仿真性能更有效率。由于Verilog語(yǔ)言沒(méi)有兩態(tài)數據類(lèi)型,因此許多仿真器都通過(guò)將這種功能作為仿真器的一個(gè)選項提供。這些選項不能夠在所有的仿真器之間移植,而且在需要時(shí)用三態(tài)或四態(tài)邏輯的設計中強制使用兩態(tài)邏輯還具有副作用。SystemVerilog的bit數據類(lèi)型能夠極大改進(jìn)仿真器的性能,同時(shí)在需要的時(shí)候仍然可以使用三態(tài)或四態(tài)邏輯。通過(guò)使用具有確定行為的數據類(lèi)型來(lái)代替專(zhuān)有的仿真器選項,兩態(tài)模型能夠在所有的SystemVerilog仿真器間移植。 SystemVerilog的logic數據類(lèi)型比Verilog的線(xiàn)網(wǎng)和寄存器數據類(lèi)型更加靈活,它使得在任何抽象層次上建模硬件都更加容易。logic類(lèi)型能夠以下面的任何一種方法賦值: 通過(guò)任意數目的過(guò)程賦值語(yǔ)句賦值,能夠替代Verilog的reg類(lèi)型; 通過(guò)單一的連續賦值語(yǔ)句賦值,能夠有限制地替代Verilog的wire類(lèi)型; 連接到一個(gè)單一原語(yǔ)的輸出,能夠有限制地替代Verilog的wire類(lèi)型; 由于logic數據類(lèi)型能夠被用來(lái)替代Verilog的reg或wire(具有限制),這就使得能夠在一個(gè)更高的抽象層次上建模,并且隨著(zhù)設計的不斷深入能夠加入一些設計細節而不必改變數據類(lèi)型的聲明。logic數據類(lèi)型不會(huì )表示信號的強度也不具有線(xiàn)邏輯的解析功能,因此logic數據類(lèi)型比 Verilog的wire類(lèi)型更能有效地仿真和綜合。 5. 有符號和無(wú)符號限定符 缺省情況下,Verilog net和reg數據類(lèi)型是無(wú)符號類(lèi)型,integer類(lèi)型是一個(gè)有符號類(lèi)型。Verilog-2001標準允許使用signed關(guān)鍵字將無(wú)符號類(lèi)型顯式地聲明成有符號類(lèi)型。SystemVerilog加入了相似的能力,它可以通過(guò)unsigned關(guān)鍵字將有符號數據類(lèi)型顯式地聲明成有無(wú)符號數據類(lèi)型。例如: int unsigned j; 值得注意的是unsigned在Verilog中是一個(gè)保留字,但并沒(méi)有被Verilog標準使用。 6. 用戶(hù)定義的類(lèi)型 Verilog不允許用戶(hù)定義新的數據類(lèi)型。SystemVerilog通過(guò)使用typedef提供了一種方法來(lái)定義新的數據類(lèi)型,這一點(diǎn)與C語(yǔ)言類(lèi)似。用戶(hù)定義的類(lèi)型可以與其它數據類(lèi)型一樣地使用在聲明當中。例如: typedef unsigned int uint; uint a, b; 一個(gè)用戶(hù)定義的數據類(lèi)型可以在它的定義之前使用,只要它首先在空的typedef中說(shuō)明,例如: typedef int48; // 空的typedef,在其他地方進(jìn)行完整定義 int48 c; 7. 枚舉類(lèi)型 在Verilog語(yǔ)言中不存在枚舉類(lèi)型。標識符必須被顯式地聲明成一個(gè)線(xiàn)網(wǎng)、變量或參數并被賦值。SystemVerilog允許使用類(lèi)似于C的語(yǔ)法產(chǎn)生枚舉類(lèi)型。一個(gè)枚舉類(lèi)型具有一組被命名的值。缺省情況下,值從初始值0開(kāi)始遞增,但是我們可以顯式地指定初始值。枚舉類(lèi)型的例子如下: enum {red, yellow, green} RGB; enum {WAIT=2’b01, LOAD, DONE} states; 我們還可以使用typedef為枚舉類(lèi)型指定一個(gè)名字,從而允許這個(gè)枚舉類(lèi)型可以在許多地方使用。例如: typedef enum {FALSE=1’b0, TRUE} boolean; boolean ready; boolean test_complete; 8. 結構體和聯(lián)合體 在Verilog語(yǔ)言中不存在結構體或聯(lián)合體,而結構體或聯(lián)合體在將幾個(gè)聲明組合在一起的時(shí)候非常有用。SystemVerilog增加了結構體和聯(lián)合體,它們的聲明語(yǔ)法類(lèi)似于C。 struct { reg [15:0] opcode; reg [23:0] addr; } IR; union { int I; shortreal f; } N; 結構體或聯(lián)合體中的域可以通過(guò)在變量名和域名字之間插入句點(diǎn)(.)來(lái)引用: IR.opcode = 1; // 設置IR變量中的opcode域 N.f = 0.0; // 將N設置成浮點(diǎn)數的值 我們可以使用typedef為結構體或聯(lián)合體的定義指定一個(gè)名字。 typedef struct { reg [7:0] opcode; reg [23:0] addr; } instruction; // 命名的結構體 instruction IR; // 結構體實(shí)例 一個(gè)結構體可以使用值的級聯(lián)來(lái)完整地賦值,例如: instruction = {5, 200}; 結構體可以作為一個(gè)整體傳遞到函數或任務(wù),也可以從函數或任務(wù)傳遞過(guò)來(lái),也可以作為模塊端口進(jìn)行傳遞。 9. 數組 在Verilog中可以聲明一個(gè)數組類(lèi)型,reg和線(xiàn)網(wǎng)類(lèi)型還可以具有一個(gè)向量寬度。在一個(gè)對象名前面聲明的尺寸表示向量的寬度,在一個(gè)對象名后面聲明的尺寸表示數組的深度。例如: reg [7:0] r1 [1:256]; // 256個(gè)8位的變量 在SystemVerilog中我們使用不同的術(shù)語(yǔ)表示數組:使用“壓縮數組(packed array)”這一術(shù)語(yǔ)表示在對象名前聲明尺寸的數組;使用“非壓縮數組(unpacked array)”這一術(shù)語(yǔ)表示在對象名后面聲明尺寸的數組。壓縮數組可以由下面的數據類(lèi)型組成:bit、logic、reg、wire以及其它的線(xiàn)網(wǎng)類(lèi)型。無(wú)論是壓縮數組還是非壓縮數組都可以聲明成多維的尺寸。 bit [7:0] a; // 一個(gè)一維的壓縮數組 bit b [7:0]; //一個(gè)一維的非壓縮數組 bit [0:11] [7:0] c; //一個(gè)二維的壓縮數組 bit [3:0] [7:0] d [1:10]; // 一個(gè)包含10個(gè)具有4個(gè)8位字節的壓縮數組的非壓縮數組 非壓縮尺寸在壓縮尺寸之前引用,這就允許將整個(gè)壓縮數組作為一個(gè)單一的元素進(jìn)行引用。在上面的例子中,d引用非壓縮數組的一個(gè)單一元素,這個(gè)元素是一個(gè)包含4個(gè)字節的數組。 10. 在為命名的塊中聲明 Verilog允許變量在一個(gè)命名的begin-end或fork-join語(yǔ)句組中聲明。相對于語(yǔ)句組來(lái)說(shuō),這些變量是本地的,但它們可以被層次化地引用。在SystemVerilog中,既可以在命名的塊中也可以在未命名的塊中聲明。在未命名的塊中,不能夠使用層次名來(lái)訪(fǎng)問(wèn)變量。所有的變量類(lèi)型,包括用戶(hù)定義的類(lèi)型、枚舉類(lèi)型、結構體和聯(lián)合體都可以在begin-end或fork-join語(yǔ)句組中聲明。 11. 常量 在Verilog中有三種特性類(lèi)型的常量:parameter、specparam和localparam。而在SystemVerilog中,允許使用const關(guān)鍵字聲明常量。例如: const char colon = “:”; 12. 可重定義的數據類(lèi)型 SystemVerilog擴展了Verilog的parameter,使其可以包含類(lèi)型。這個(gè)強大的功能使得一個(gè)模塊中的數據類(lèi)型在模塊的每一個(gè)實(shí)例中重新定義。例如: module foo; # (parameter type VAR_TYPE = shortint;) (input logic [7:0] i, output logic [7:0] o); VAR_TYPE j = 0; // 如果不重新定義,j的數據類(lèi)型為shortint … endmodule module bar; logic [3:0] i, o; foo #(.VAR_TYPE(int)) u1 (i, o); // 重新將VAR_TYPE定義成int類(lèi)型 endmodule 13. 模塊端口連接 在Verilog中,可以連接到模塊端口的數據類(lèi)型被限制為線(xiàn)網(wǎng)類(lèi)型以及變量類(lèi)型中的reg、integer和time。而在SystemVerilog中則去除了這種限制,任何數據類(lèi)型都可以通過(guò)端口傳遞,包括實(shí)數、數組和結構體。 14. 字母值 在Verilog中,當指定或賦值字母值的時(shí)候存在一些限制。而SystemVerilog則為字母值如何指定作了下面的增強: 一個(gè)字母值的所有位均可以使用`0、`1、`z或`x作相同的填充。這就允許填充一個(gè)任意寬度的向量,而無(wú)需顯式地指定向量的寬度,例如: bit [63:0] data; data = `1; //將data的所有位設置成1 一個(gè)字符串可以賦值成一個(gè)字符數組,象C語(yǔ)言一樣加入一個(gè)空結束符。如果尺寸不同,它象C中一樣進(jìn)行左調整,例如: char foo [0:12] = “hello worldn”; 加入了幾個(gè)特殊的串字符: v:垂直TAB f:換頁(yè) a:響鈴 x02:用十六進(jìn)制數來(lái)表示一個(gè)ASCII字符 數組可以使用類(lèi)似于C初始化的語(yǔ)法賦值成字符值,但它還允許復制操作符。括號的嵌套必須精確地匹配數組的維數(這一點(diǎn)與C不同),例如: int n [1: 2] [1:3] = {{0, 1, 2}, {3{4}}}; |