過程語句和子程式
任務與函數之間的差別
任務可以消耗時間,而函數不能。即函數裡不能帶有#100,@(posedge clk),wait(ready)之類的阻塞語句。Verilog中函數不能調用任務,而SystemVerilog中可以,但隻能由fork…join_none語句(不影響函數執行,不消耗時間)生成的線程中調用。
是以,一般來說,不消耗時間的任務最好都定義成void函數,以友善被任何函數或任務調用。可以使用void’(function)來忽略函數的傳回值。
子程式參數
子程式的參數預設的類型和方向是logic輸入。(verilog中input output預設是wire)
ref參數可以避免子程式将參數複制進去,而是直接引用原參數,是以子程式中的修改是會影響到原參數的。
參數可以設定預設值。參數傳遞也有類似子產品端口連接配接的方式。
function void printsum(ref bit [31:0] a[],
input bit [31:0] low=0, /*這裡沒有指明端口則預設為ref*/
input int high = 1);
endfunction
printsum(.a(a),.low(low),.high(high));
局部資料存儲
預設情況下,module和program都是靜态存儲的,内部變量在仿真開始時就有了初始值,并且多次調用會覆寫先前的值。可以利用automatic參數實作自動存儲。
時間值
可以使用timeunit以及timeprecision代替timescale語句。
timeunit 1ns;
timeprecision 1ps;
$timeformat(-9,3,"ns",8);/*時間标度,-9即ns;小數點精度;時間值字尾字元串;顯示數值的最小寬度*/
連接配接設計與測試平台
驗證一個設計的步驟是,生成輸入激勵,捕獲輸出相應,決定對錯和衡量進度。需要一個測試平台,将設計、激勵、輸出包裹起來進行驗證。
為了解決子產品之間大量的連接配接問題,需要使用接口。
interface arb_if (input bit clk);
logic [1:0] grant, request;
logic rst;
/*使用時鐘塊控制同步信号*/
clocking cb @(posedge clk);
output request;
input grant;
endclocking
/*利用modport指定方向*/
modport TEST (output rst,
clocking cb);
modport DUT (input request,rst,clk,
output grant);
modport MONITOR (input request,grant,rst,clk);
endinterface
測試與設計平台之間可能存在競争狀态。當測試平台給出一個起始信号,如果其他相關信号在這之後給出,那麼設計平台就無法及時獲得這些信号的最新值。
接口信号的采樣和驅動
時鐘塊的預設時序是在#1step延時之後采樣輸入信号,在#0延時之後驅動輸出信号。1step延時規定了信号在前一個時間片的Postponed區域,在設計有任何新動作之前被采樣,這樣可以在時鐘上升之前捕獲輸出值。
可以從下面兩張圖看出其中差異。
這是采樣過程。DUT中的grant輸出發生變化,驗證平台能夠在時鐘上升沿之前捕獲,并在下一個上升沿到來後,立即反應出來。
這是驅動過程。驗證平台驅動request之後,DUT會在下一個時鐘上升沿展現出來。如果在時鐘上升沿之間驅動,那麼則不會被捕獲。
程式塊中不允許使用always塊
因為程式塊會在initial塊都執行完成後結束,如果有always塊,則無法自動結束,應當用initial forever代替。