SystemVerilog Clocking用法詳解
SystemVerilog 的 clocking
塊(Clocking Block)是一種專門用于定義信號時序行為的構造,主要用于驗證環境(如 UVM)中,以精確控制信號的采樣和驅動時序。clocking
塊通過將信號與特定時鐘關聯,簡化了測試環境中對時序敏感信號的處理,減少了手動時序管理的復雜性。本文將詳細介紹 SystemVerilog 中 clocking
塊的各種用法,包括基本定義、輸入輸出信號、時序控制、接口中的使用、以及在驗證中的應用,并提供示例代碼和最佳實踐。
1. Clocking 塊概述
clocking
塊是 SystemVerilog 中用于封裝信號與時鐘關系的構造,通常定義在 interface
或模塊中。它的主要功能是:
- 信號采樣與驅動:定義信號相對于時鐘的采樣和驅動時序。
- 時序抽象:屏蔽底層時序細節,簡化測試用例開發。
- 驗證支持:在驗證環境中(如 UVM)提供標準化的時序控制接口。
- 避免競爭:通過明確的采樣和驅動時間點,減少仿真中的競爭與冒險。
主要用途
- 在驗證環境中精確控制信號的采樣和驅動。
- 簡化測試環境中對 DUT(待測設計)的時序交互。
- 與
interface
結合,提供模塊化的時序接口。
基本語法
clocking clocking_name @(clock_event);input input_signal;output output_signal;
endclocking
clocking_name
:時鐘塊的名稱。clock_event
:觸發時鐘塊的時鐘事件(如@(posedge clk)
)。input_signal
:輸入信號,定義采樣時序。output_signal
:輸出信號,定義驅動時序。
2. 基本 Clocking 塊定義與使用
clocking
塊通過指定信號的采樣和驅動時序,簡化了驗證代碼的編寫。
示例:基本 Clocking 塊
module top;logic clk = 0;logic [7:0] data;logic valid;// 定義 clocking 塊clocking cb @(posedge clk);input data;input valid;endclocking// 測試邏輯initial beginforever #5 clk = ~clk;endinitial begin@(cb); // 等待 clocking 塊的時鐘邊沿if (cb.valid)$display("Sampled data: %h", cb.data);end
endmodule
說明:
clocking cb
定義了一個時鐘塊,基于clk
的上升沿。input data
和input valid
指定信號在時鐘上升沿前采樣。- 測試邏輯通過
cb.data
和cb.valid
訪問同步信號。
優點:
- 信號采樣自動與時鐘邊沿對齊,避免手動時序控制。
- 提高了代碼的可讀性和可維護性。
3. 輸入與輸出信號的時序控制
clocking
塊支持通過 input
和 output
關鍵字定義信號的采樣和驅動時序,并可以通過延遲指定具體的時序偏移。
3.1 輸入信號采樣
input
信號在時鐘邊沿前采樣,默認采樣時間點為時鐘邊沿前的非阻塞賦值(NBA)區域。可以通過 input #delay
指定采樣延遲。
3.2 輸出信號驅動
output
信號在時鐘邊沿后驅動,默認驅動時間點為時鐘邊沿后的非阻塞賦值區域。可以通過 output #delay
指定驅動延遲。
示例:帶時序延遲的 Clocking 塊
interface simple_bus (input logic clk);logic [7:0] data;logic valid;logic ready;clocking cb @(posedge clk);input #1ns data, valid; // 采樣延遲 1nsoutput #2ns ready; // 驅動延遲 2nsendclocking
endinterfacemodule receiver (simple_bus bus);always @(bus.cb) beginbus.cb.ready <= 1; // 在時鐘邊沿后 2ns 驅動 readyif (bus.cb.valid)$display("Received data: %h", bus.cb.data);end
endmodulemodule top;logic clk = 0;always #5 clk = ~clk;simple_bus bus_inst(.clk(clk));receiver u_receiver (.bus(bus_inst));initial beginbus_inst.data = 8'hA5;bus_inst.valid = 1;#20 $finish;end
endmodule
說明:
input #1ns
表示data
和valid
在時鐘上升沿前 1ns 采樣。output #2ns
表示ready
在時鐘上升沿后 2ns 驅動。- 模塊通過
bus.cb
訪問同步信號。
注意:
- 延遲值必須為非負,且在仿真中有效(綜合通常忽略)。
- 延遲值應根據 DUT 的時序要求設置。
4. Clocking 塊與 Interface 的結合
clocking
塊通常定義在 interface
中,與信號和 modport
結合,提供模塊化的時序接口。
示例:接口中的 Clocking 塊
interface simple_bus (input logic clk);logic [7:0] data;logic valid;logic ready;clocking cb @(posedge clk);input data, valid;output ready;endclockingmodport slave (input data, valid,output ready);
endinterfacemodule receiver (simple_bus.slave bus);always @(bus.cb) beginbus.cb.ready <= 1;if (bus.cb.valid)$display("Received data: %h", bus.cb.data);end
endmodulemodule top;logic clk = 0;always #5 clk = ~clk;simple_bus bus_inst(.clk(clk));receiver u_receiver (.bus(bus_inst));initial beginbus_inst.data = 8'hA5;bus_inst.valid = 1;#20 $finish;end
endmodule
說明:
clocking cb
定義在interface
中,與接口信號關聯。receiver
模塊通過bus.cb
訪問同步信號。modport slave
定義了信號方向,增強接口的模塊化。
優點:
- 將時序控制與信號封裝結合,簡化驗證代碼。
- 支持模塊化的 DUT 和測試環境連接。
5. 多時鐘 Clocking 塊
clocking
塊支持定義多個時鐘塊,用于處理多時鐘域的信號。
示例:多時鐘 Clocking 塊
interface multi_clock_bus (input logic clk1, clk2);logic [7:0] data;logic valid;clocking cb1 @(posedge clk1);input data, valid;endclockingclocking cb2 @(posedge clk2);input data, valid;endclocking
endinterfacemodule monitor (multi_clock_bus bus);always @(bus.cb1) beginif (bus.cb1.valid)$display("clk1 domain: data = %h", bus.cb1.data);endalways @(bus.cb2) beginif (bus.cb2.valid)$display("clk2 domain: data = %h", bus.cb2.data);end
endmodulemodule top;logic clk1 = 0, clk2 = 0;always #5 clk1 = ~clk1;always #7 clk2 = ~clk2;multi_clock_bus bus_inst(.clk1(clk1), .clk2(clk2));monitor u_monitor (.bus(bus_inst));initial beginbus_inst.data = 8'hA5;bus_inst.valid = 1;#50 $finish;end
endmodule
說明:
cb1
和cb2
分別基于clk1
和clk2
定義時鐘塊。monitor
模塊在不同時鐘域中采樣信號。- 支持多時鐘域驗證。
注意:
- 確保時鐘信號正確連接到接口。
- 在多時鐘域中,注意信號的跨時鐘域處理。
6. Clocking 塊在驗證中的應用
clocking
塊在驗證環境(如 UVM)中廣泛使用,用于連接 DUT 和測試環境,提供標準化的時序接口。
示例:UVM 驗證中的 Clocking 塊
interface simple_bus (input logic clk);logic [7:0] data;logic valid;logic ready;clocking cb @(posedge clk);input data, valid;output ready;endclocking
endinterfacemodule dut (simple_bus bus);always @(posedge bus.clk) beginif (bus.valid && bus.ready)$display("DUT received: %h", bus.data);end
endmoduleprogram testbench;import uvm_pkg::*;`include "uvm_macros.svh"logic clk = 0;always #5 clk = ~clk;simple_bus bus_if(.clk(clk));initial begin// 設置 UVM 接口uvm_config_db#(virtual simple_bus)::set(null, "*", "bus_if", bus_if);run_test();end
endprogram
說明:
simple_bus
包含clocking cb
,為測試環境提供同步信號訪問。- UVM 測試環境通過
uvm_config_db
獲取虛擬接口。 dut
通過接口與測試環境交互。
優點:
- 簡化了 UVM 驅動器和監視器的時序控制。
- 提供標準化的信號訪問接口。
7. Clocking 塊的高級用法
7.1 默認時鐘塊
可以使用 default clocking
指定默認的時鐘塊,簡化代碼中的時序引用。
interface simple_bus (input logic clk);logic [7:0] data;logic valid;clocking cb @(posedge clk);input data, valid;endclockingdefault clocking cb; // 設置默認時鐘塊
endinterfacemodule monitor (simple_bus bus);always @(*) beginif (valid) // 直接引用信號,等效于 bus.cb.valid$display("Data: %h", data);end
endmodule
說明:
default clocking cb
將cb
設置為默認時鐘塊。- 信號可以直接引用(如
valid
),等效于bus.cb.valid
。
注意:
- 默認時鐘塊在復雜接口中可能降低可讀性,謹慎使用。
7.2 動態時序調整
clocking
塊支持在仿真中動態調整時序(通過屬性),但主要用于驗證。
interface simple_bus (input logic clk);logic [7:0] data;logic valid;clocking cb @(posedge clk);input #1step data, valid; // 使用 1step 采樣endclocking
endinterface
說明:
#1step
表示在時鐘邊沿前的最小時間步長采樣。- 適合需要精確時序控制的驗證場景。
8. 注意事項與最佳實踐
-
時序定義:
- 確保采樣和驅動延遲與 DUT 的時序要求一致。
- 避免過大的延遲值,以免影響仿真性能。
-
接口結合:
- 將
clocking
塊定義在interface
中,與信號和modport
結合。 - 使用
modport
明確信號方向,增強模塊化。
- 將
-
驗證環境:
- 在 UVM 中,使用虛擬接口傳遞
clocking
塊。 - 結合
clocking
塊簡化驅動器和監視器的開發。
- 在 UVM 中,使用虛擬接口傳遞
-
綜合限制:
clocking
塊主要用于驗證,不支持綜合。- 確保 DUT 代碼不依賴
clocking
塊。
-
多時鐘域:
- 為每個時鐘域定義獨立的
clocking
塊。 - 注意跨時鐘域信號的同步。
- 為每個時鐘域定義獨立的
-
代碼可讀性:
- 為
clocking
塊和信號提供清晰的命名。 - 添加注釋說明采樣和驅動時序。
- 為
-
調試與驗證:
- 使用仿真工具驗證
clocking
塊的時序行為。 - 檢查采樣和驅動時間點是否符合預期。
- 使用仿真工具驗證
9. 總結
SystemVerilog 的 clocking
塊是一種強大的驗證工具,用于定義信號的采樣和驅動時序,簡化測試環境的時序管理。通過基本定義、輸入輸出信號、時序控制、接口結合、多時鐘支持等功能,clocking
塊在 UVM 等驗證環境中發揮了關鍵作用。特別是在復雜設計中,clocking
塊與 interface
的結合提供了模塊化的時序接口,顯著提高了驗證效率和代碼質量。遵循最佳實踐并根據具體場景選擇合適的 clocking
用法,能夠有效提升驗證的可靠性和可維護性。
10. 設計工具推薦
- SZ901:
SZ901 是一款基于XVC協議的FPGA網絡下載器。- 最高支持53M
- 支持4路JTAG獨立使用
- 支持端口合并
- 支持國產FLASH燒寫
- 下載器無限擴展
- 配備專屬程序固化軟件,一鍵燒寫,能大大減小程序固化時間!