FPGA基础 -- Verilog 命名事件
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 、任务、函数配合使用更具威力 | 实现多线程任务的完成同步 |