15. 強制類型轉換 Verilog不能將一個值強制轉換成不同的數據類型。SystemVerilog通過使用 int’ (2.0 * 3.0) // 將結果轉換為int類型 mytype’ (foo) // 將foo轉換為mytype類型 一個值還可以通過在強制轉換操作符前指定一個10進制數來轉換成不同的向量寬度,例如: 17’ (x - 2) // 將結果轉換為17位寬度 也可以將結果轉換成有符號值,例如: signed’ (x) // 將x轉換為有符號值 16. 操作符 Verilog沒有C語言的遞增(++)和遞減(--)操作符。而SystemVerilog加入了幾個新的操作符: ++和--:遞增和遞減操作符; +=、-=、*=、/=、%=、&=、^=、|=、<<=、>>=、<<<=和>>>=賦值操作符; 17. 唯一性和優先級決定語句 在Verilog中,如果沒有遵循嚴格的編碼風格,它的if-else和case語句會在RTL仿真和RTL綜合間具有不一致的結果。如果沒有正確使用full_case和parallel_case綜合指令還會引起一些其它的錯誤。 SystemVerilog能夠顯式地指明什么時候一條決定語句的分支是唯一的,或者什么時候需要計算優先級。我們可以在if或case關鍵字之前使用 unique或requires關鍵字。這些關鍵字可以向仿真器、綜合編譯器、以及其它工具指示我們期望的硬件類型。工具使用這些信息來檢查if或 case語句是否正確建模了期望的邏輯。例如,如果使用unique限定了一個決定語句,那么在不希望的case值出現的時候仿真器就能夠發布一個警告信息。 bit [2:0] a; unique if ((a==0) || (a==1)) y = in1; else if (a==2) y = in2; else if (a==4) y = in3; // 值3、5、6、7會引起一個警告 priority if (a[2:1]==0) y = in1; // a是0或1 else if (a==0) y = in2; // a是2或3 else y = in3; // 如果a為其他的值 unique case (a) 0, 1: y = in1; 2: y = in2; 4: y = in3; endcase // 值3、5、6、7會引起一個警告 priority casez (a) 2’b00? : y = in1; // a是0或1 2’b0?? : y = in2; // a是2或3 default : y = in3; //如果a為其他的值 endcase 18. 底部檢測的循環 Verilog包含for、while和repeat循環,這幾個循環都是在循環的起始處檢測循環條件。SystemVerilog加入了一個do-while循環,這種循環在執行語句的結尾處檢測循環條件。 19. 跳轉語句 在語句的執行過程中,C語言提供了幾種方式來跳轉到新的語句,包括:return、break、continue和goto。在Verilog中除了通過使用disable語句跳轉到語句組的尾部外,沒有提供任何其它跳轉語句。使用disable語句執行中止和繼續功能要求加入塊的名字,并且會產生不直觀的代碼。SystemVerilog加入了C語言的break和continue關鍵字,這兩個關鍵字不要求使用塊名字。另外,SystemVerilog還加入了一個return關鍵字,它可以用來在任何執行點上退出一個任務或函數。 break:退出一個循環,與C語言相同; continue:跳轉到一個循環的尾部,與C語言相同; return 表達式:退出一個函數; return:退出一個任務或void類型的函數。 SystemVerilog沒有包含C語言中的goto語句。 20. 塊名字和語句標簽 在Verilog中,我們可以通過在begin或fork關鍵字之后指定名字來為begin-end或fork-jion語句指定名字。這個指定的名字代表整個語句塊。SystemVerilog還允許在end或jion關鍵字之后指定一個匹配的塊名字。這種機制很容易將end或jion與對應的 begin或fork聯系起來,尤其是在一個長的塊或嵌套的塊中。塊結尾處的名字是可選的,但如果使用的話,它必須與塊起始處的名字相同。例如: begin: foo// 在begin之后的塊名字 … fork: bar // 具有名字的嵌套的塊 … jion: bar // 必須具有相同的名字 … end: foo // 必須具有相同的名字 SystemVerilog還允許像C語言一樣為單個語句設置標簽。語句標簽放置在語句的前面,用來標識這條語句。例如: initial begin test1: read_enable = 0; … test2: for (i=0; i<=255; i++) … end 21. 對事件控制的增強 Verilog使用@標記來控制基于特定事件的執行流,SystemVerilog增強了@事件控制。 *有條件的事件控制 @標記的一個基本應用就是推斷一個具有使能輸入的鎖存器。下面的例子演示了一個鎖存器建模的基本風格。 always @(data or en) if (en) y <= data; 這種編碼風格對仿真來說是效率低下的,因為即使在使能輸入無效的時候,數據輸入的每次改變都會觸發事件控制。 SystemVerilog在事件控制中加入了一個iff條件。只有iff條件為真的條件下,事件控制才會被觸發。通過將使能判斷移入到事件控制里面,使得只有在鎖存器輸出能夠改變的時候事件控制才會被觸發。例如: always @(a or en iff en==1) y <= a; * 事件控制中的表達式 Verilog允許在@事件控制列表中使用表達式,例如: always @((a * b)) always @(memory[address]) 在第一個例子中,是當操作數發生改變的時候還是只有當運算結果發生改變的時候才會觸發事件控制?在第二個例子中,是當memory的地址發生變化的時候還是只有當memory的值發生變化的時候才會觸發事件控制?當@事件控制中包含表達式的時候,IEEE Verilog標準允許仿真器進行不同的優化。這就可能導致在不同的仿真器間有不同的仿真結果,可能還會導致仿真與綜合之間的結果不一致。 SystemVerilog加入了一個changed關鍵字,在事件控制列表中它被用作一個修飾符。@(changed (表達式))能夠顯式地定義只有當表達式的結果發生改變的時候才會觸發事件控制。例如: always @(changed (a * b)) always @(changed memory[address]) * 事件控制中的賦值 Verilog不允許在事件控制中使用賦值。SystemVerilog允許在事件控制中使用賦值表達式。事件控制僅僅敏感于賦值表達式右側的變化。例如: always @(y = a * b) 22. 新的過程 Verilog使用always過程來表示時序邏輯、組合邏輯和鎖存邏輯的RTL模型。綜合工具和其它軟件工具必須根據過程起始處的事件控制列表以及過程內的語句來推斷always過程的意圖。這種推斷會導致仿真結果和綜合結果之間的不一致。SystemVerilog增加了三個新的過程來顯式地指示邏輯的意圖。 always_ff:表示時序邏輯的過程; always_comb:表示組合邏輯的過程; always_latch:表示鎖存邏輯的過程。 例如: always_comb @(a or b or sel) begin if (sel) y = a; else y = b; end 軟件工具能夠檢查事件控制敏感列表和過程的內容來保證邏輯的功能匹配過程的類型。例如,工具能夠檢查一個always_comb過程能夠敏感過程內讀取的所有外部值,對邏輯的每一個分支的相同變量進行賦值,并且檢查分支是否覆蓋了所有可能的條件。如果任何一個條件沒有滿足,軟件工具均會報告該過程沒有正確建模組合邏輯。 23. 動態過程 Verilog通過使用fork-jion提供了一種靜態的并發過程。每一個分支都是一個分離的、并行的過程。fork-jion中任何語句的執行必須在組內的每一個過程完成后才會執行。例如: initial begin fork send_packet_task (1, 255, 0); send_packet_task (7, 128, 5); watch_result_task (1, 255, 0); watch_result_task (7, 128, 5); jion // 所有的任務必須完成后才會到達這里 end SystemVerilog通過process關鍵字加入了一個新的、動態的過程。它為一個過程產生分支,然后繼續執行而無需等待其他過程完成。過程不會阻塞過程或任務內的語句執行。這種方式能夠建模多線程的過程。例如: initial begin process send_packet_task (1, 255, 0); process send_packet_task (7, 128, 5); process watch_result_task (1, 255, 0); process watch_result_task (7, 128, 5); end // 所有的過程并行運行 24. 任務和函數增強 SystemVerilog為Verilog的任務和函數作了幾個增強。 * 靜態和自動的存儲 缺省情況下,在Verilog任務或函數內的所有存儲都是靜態的。Verilog-2001允許將任務和函數聲明成自動的。在SystemVerilog 中:(1). 在一個靜態任務和函數內的特定數據可以顯式地聲明成自動的。聲明成自動的數據在塊中具有完整的生命周期,并且在任務和函數調用的入口處初始化;(2). 在一個自動的任務或函數中的特定數據可以顯式地聲明成靜態的。自動的任務或函數中聲明成靜態的數據在一個塊的本地范圍內具有靜態的生命周期。 * 從任何點返回 Verilog在一個任務或函數中執行到endtask或endfunction關鍵字的時候返回。函數的返回值是給函數名賦的最后一個值。SystemVerilog加入了一個return關鍵字,使用這個關鍵字,一個任務或函數可以在任何點上返回。 *多語句 Verilog要求一個任務或函數只具有一個語句或語句塊。多條語句必須組合到一個單一的begin-end或fork-jion塊中。 SystemVerilog去除了這種限制。因此,多條語句可以在一個任務或函數中列出而無需使用的begin-end或fork-jion。每有分組的語句就像在begin-end中一樣順序執行。我們還可以產生一個沒有語句的任務或函數定義。 *void函數 Verilog要求一個函數具有一個返回值,函數的調用接收這個返回值。 SystemVerilog加入了一個void數據類型,這個數據類型可以作為一個函數的返回值類型。void函數可以像Verilog任務一樣進行調用,而無需接收一個返回值。 void函數和任務的差別在于函數存在幾個限制,例如沒有時間控制等。 *函數的輸入和輸出 Verilog標準要求一個函數至少具有一個輸入并且函數只能具有輸入。SystemVerilog去除了這些限制。函數可以具有任意數目的輸入、輸出以及輸入輸出,也可以什么也沒有。 25. 連續賦值的增強 在Verilog中,連續賦值語句的左側只能是線網類型,例如wire。連續賦值語句被認為是線網的驅動源,而線網可以擁有任意數據的驅動源。 SystemVerilog允許除reg類型以外的任何數據類型用于連續賦值語句的左側。與線網不同,所有其它數據類型被限制為只能有一個連續賦值語句驅動。為相同的變量混合使用連續賦值語句和過程賦值語句是不被允許的。 26. $bit系統函數 在Verilog中沒有類似于C語言中sizeof的函數。SystemVerilog加入一個新的$bit內建函數。這個函數返回保存一個值所需的硬件位的數目(一個四態值要求一個硬件位),這個函數還可以用來確定一個結構體所代表的硬件位的數目。 27. `define的增強 SystemVerilog增強了`define編譯器指令的能力以便支持將字符串作為宏的參數。宏的文本字符串中可以包含一個隔離的引號,它的前面必須具有一個反勾號(`”),這就允許字符串中包含宏參數。宏文本可以在行的尾部包含一個反斜杠(’’)來表示在下一行繼續。如果宏文本字符串中包含反斜杠,則反斜杠應該被放在兩個反勾號之間,這樣它就不會被認為是Verilog轉義標識符的開始。宏文本字符串還可以包含雙反勾號(``),它允許標識符能夠從參數中構建。這些增強使得`define指令更加靈活。例如:`include指令后可以緊跟一個宏名字來替代一個字符串。 `define f1 “../project_top/opcode_defines” `include `f1 28. 狀態機建模 SystemVerilog允許在更高的抽象層次上對狀態機建模。這些結構包括: *枚舉類型 *一個特殊的state數據類型; *一個遷移語句 *一個遷移操作符 29. 斷言 SystemVerilog中加入了斷言的功能來改善系統的驗證過程。 30. 結論 SystemVerilog為Verilog-2001標準提供了一系列的擴展。這些擴展使得大型設計的建模和驗證更加容易。 |