Verilog 的“命名事件(Named Events)”機制 進行一次系統、專業的培訓。該機制在 Verilog 中是比較冷門但重要的仿真控制特性,主要用于 模塊間同步、行為仿真觸發、事件通信,在復雜的 Testbench、行為模型中尤為重要。
一、命名事件是什么?
命名事件(Named Event) 是 Verilog 提供的一種可以顯式創建、顯式觸發、顯式等待的“同步信號”,和 event
關鍵詞相關。它們不是信號,也不是變量,而是一種 仿真時間上的觸發機制。
它不是綜合語法,只用于 仿真(Simulation only)。
二、基本語法與操作
1. 定義事件
event my_event;
定義了一個命名事件變量 my_event
。
2. 觸發(trigger)事件
-> my_event;
或:
->> my_event; // 延遲觸發(Verilog-2005)
這表示立即觸發事件 my_event
,供其它地方監聽。
3. 等待事件發生
@(my_event); // 等待 my_event 被觸發
也可以和其他觸發條件組合:
@(posedge clk or my_event);
三、案例分析:事件觸發與等待
module event_example;event done_event; // 定義一個事件initial begin$display("T=%0t: Waiting for event...", $time);@(done_event); // 等待事件觸發$display("T=%0t: Event triggered!", $time);endinitial begin#50; // 延遲 50 時間單位-> done_event; // 觸發事件$display("T=%0t: Event sent", $time);endendmodule
輸出:
T=0: Waiting for event...
T=50: Event sent
T=50: Event triggered!
四、事件機制使用場景
1. 多模塊同步(仿真側)
// DUT 和 TB 控制之間通過事件同步開始測試
2. 行為級通信
在 FSM 中一個狀態機等待另一個模塊觸發完成事件。
3. Testbench 編寫中常用
- 等待某個模擬行為完成(如 DMA 傳輸完成)
- 協調不同
initial
塊之間的動作順序 - 等待某個周期性過程完成再發下一組數據
五、多個事件組合(進階)
1. 多個事件等待
@(event_a or event_b);
2. 多次觸發也可以
repeat(3) @(event_x);
六、事件的傳遞與參數化
事件是 傳引用的,因此可以作為參數傳入子模塊:
task wait_for_event(event e);@(e); // 等待傳入的事件
endtask
或者在 fork-join
結構中,通過共享事件做子任務完成的同步。
七、Verilog-2005 延遲觸發 ->>
->> event_name; // 表示下一時間單位才觸發
這在一些 race condition 下非常有用,避免當前時間立刻觸發帶來的不確定行為。
八、仿真工具支持與注意事項
特性 | 支持情況 |
---|---|
仿真支持 | ? ModelSim、VCS、Verilator 等均支持 |
語義層面綜合支持 | ? 絕不用于綜合 RTL |
多線程并發場景 | ? 搭配 fork-join 同步子任務 |
建議用法 | ? 僅限 Testbench 和驗證模型中使用 |
九、命名事件 VS 信號控制的對比
方面 | 命名事件 | 觸發信號 |
---|---|---|
本質 | 模擬器中的同步機制 | 電平/邊沿 |
仿真可用 | ? | ? |
RTL綜合 | ? | ? |
可追蹤性 | 模擬器內部事件(不可見) | 信號波形可觀察 |
用途 | 高層行為建模與協調 | 真實電路邏輯 |
十、總結與工程建議
建議內容 | 說明 |
---|---|
? 推薦在 Testbench 中使用命名事件協調流程控制 | 適合用于多個線程/過程的同步,如等待初始化完成、總線傳輸結束等 |
? 不要用于 RTL 模塊或計劃綜合的代碼中 | 不屬于綜合語法,綜合工具會忽略或報錯 |
? 與 fork-join 、任務、函數配合使用更具威力 | 實現多線程任務的完成同步 |