verilog语言中是可以定义一个事件(event),在仿真测试程序中, 对事件(event )触发,检测。 当满足触发条件时,就可以触发相应的事件并且引发相应的事件处理。verilog事件(event)只能用于仿真,不能用于综合。event是一个新的数据类型, 与wire , reg 类似,需要使用event 来声明。这种声明又称为命名事件(named event)。
1 事件(event)语法格式:
事件声明:
event <event name>
使用event 关键字, 可以声明一个事件,也可以声明多个事件。event关键字不能赋初值,也不能使用向量的方式声明。正确的声明方式如下:
event reset_trigger;
event rest_trigger1, test_trigger2;
以下的事件声明是不正确的:
event reset_trigger = 1; //事件声明不能被赋值
event [3:0] reset_trigger; //不能以向量或者数组形式声明。
2 事件(event)触发方式:
-> <event name>
举例:
event reset_trigger;
initial
begin
#10;
-> reset_trigger;
#20 -> test_trigger;
end
always @ (posedge clk)
if(a == 3)
-> test_rigger1;
触发可以在过程块控制语句中
3 事件(event)捕获及引发的相关操作
在过程块中调用事件,并执行相关操作
initial
begin
@(reset_trigger);
$display ( ” reset trigger is here….”);
end
always @ (test_trigger)
if(led_r == 200)
$display (“led_r == 200”);
always @ (trigger_100)
if(led_r == 100)
$display (“led_r == 100”);
事件的引用和reg,wire 类型的变量没有区别,事件引用需放在敏感列表上,即可。event 可以被多个过程块引用(放入到敏感列表中)。
4 事件(event)使用注意事项:
- 可以在过程块内任何时间产生event。
- event没有时间延迟。
- 引用event之前,必须声明event。
- 使用event 的模块是不可以综合的,但是可以仿真. 即 -> 在综合的时候不能被识别。
- event 不能定义到端口上,即event不支持端口传递。有些仿真工具在端口上使用event,并不报错,但在模块引用时,会出错。
- event 不能使用posedge ,negedge的敏感信息。 有些仿真工具支持,但不是所有仿真工具都支持
reg [3:0] c = 1;
always @ (posedge test_trigger1)
begin
c = c + 1;
end
- event 支持上层引用下层的event
reg [3:0] d = 1;
always @ (event_top_inst.trigger_20)
begin
d = d + 1;
end
wire [7:0] led;
event_top event_top_inst
( // event_top module define an event trigger_20
.clk (clk),
.led (led),
.reset (reset)
);
- event 必须放到敏感列表中才能使用,不能在条件表达式中使用
reg [3:0] e = 1;
always @ (*)
begin
if(event_top_inst.trigger_20) // 错误使用event 方式,不能在过程中使用
e = e + 1;
end
- event 调用必须在敏感列表中使用个, 不能在连续赋值语句中使用
wire kkk = event_top_inst.trigger_20 ? 1'b1 : 1'b0; // 不能在连续赋值中使用 wire hhh = test_trigger1;
- event 不能在操作数之间使用
reg [3:0] f = 1;
always @ (posedge clk)
begin
f = f + event_top_inst.trigger_20; // 不能在运算中使用
end
- event 可以被输出到屏幕上, 但不能被$monitor 连续跟踪输出
initial
begin
$display("1: test_trigger1 = %s",test_trigger1);
$monitor("2: test_trigger1 = %s",test_trigger1); // 不能在$monitor时,触发输出
#125;
$display("3:test_trigger1 = %d",test_trigger1);
// $monitor("event_top_inst.trigger_20 = %s",event_top_inst.trigger_20);
end

不同的仿真工具, 输出的test_trigger1 数值有所不同, 但都是不能使用$monitor 连续跟踪的。
5 仿真工程实例:
仿真模块:
`timescale 1ns / 1ps
module event_top
(
input clk,
output [7:0] led,
input reset
);
event trigger_20;
reg [7:0] led_r = 0;
always @ (posedge clk or posedge reset)
if(reset) led_r <= 0;
else led_r <= led_r + 1;
always @ (posedge clk )
if(led_r == 20)
-> trigger_100;
always @ (trigger_20, reset)
$display ("trigger_20 happened... %t ", $time);
assign led = led_r;
endmodule
仿真测试文件:
`timescale 1ns / 1ps
module test_event(
);
reg clk = 0;
always #5 clk = ~clk;
reg reset = 1;
event start;
event test_trigger1, test_trigger2;
initial
begin
reset = 1;
#100;
reset = 1;
-> start;
#20;
reset = 0;
#2000;
$stop;
end
always @ (posedge clk)
if(reset == 0)
-> test_trigger1;
initial
begin
// while(reset);
// while(start);
// @(reset);
@(start);
$display("start testing.... %t", $time);
end
reg [3:0] b = 1;
always @ (test_trigger1)
begin
b = b + 1;
end
// reg [3:0] c = 1;
// always @ (posedge test_trigger1)
// begin
// c = c + 1;
// end
reg [3:0] d = 1;
always @ (event_top_inst.trigger_20)
begin
d = d + 1;
end
wire [7:0] led;
event_top event_top_inst
(
.clk (clk),
.led (led),
.reset (reset)
);
endmodule
仿真波形

always @ (trigger_20, reset)
$display (“trigger_20 happened… %t “, $time);
由于显示的信息有2个敏感列表 trigger_20, reset , 在reset = 1 , reset = 0 都改变敏感列表,打印输出。 在trigger_20 事件到达时,也会改变敏感列表。
Vivado仿真代码下载(可仿真, 不可以综合)
[content_control]
[/content_control]