Menu Close

Verilog 语言中event 语法

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仿真代码下载(可仿真, 不可以综合)

Posted in FPGA, FPGA 教材教案, Verilog, 教材与教案, 文章

发表回复

相关链接