Verilog 中 task 的语法,及使用 task 来完成模块的 testbench

本文介绍了Verilog中的task语法及其在testbench中的应用。task作为一种不可综合的语法,常用于testbench,提供代码共享和过程分解能力。文中通过序列检测模块的示例,展示了如何使用task编写testbench,并给出了仿真成功的案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

Verilog 中的 task 是一种不可综合的语法,它既提供了从不同位置执行公共过程的能力(因为这样可以实现代码共享),也提供了把大过程切分成小过程的能力(因为小过程更便于阅读和调试)。相较于 function, task 的 input 和 output 是可选项,同时其中也可以包含延迟控制语句,常被用在 testbench 中。

task 的语法

task的使能,就是从一条包含有传进去的参数和用于接受结果的变量的调用语句,控制从调用的过程转到 task。当 task 完成的时候,控制再传回调用的过程。所以如果 task 包含时序控制的语句,那么调用 task 的时间和退出 task 的时间可以是不一样的。 task 可以再使能(调用)其他 task,没有数量的限制。

task 声明的语法如下:

task [automatic] task_name (
	port_declaration port_name, port_name, ... ,
	port_declaration port_name, port_name, ... );
	local variable declarations
	procedural_statement or statement_group
endtask

序列检测模块

只要理解了 task 的用法,我们就可以自然而然地把它用到各种模块的 testbench 编写中。

下面是一个检测“10110”序列的模块,在检测到后令 detected = 1.

`timescale 1ns / 1ns

module detector
(
 input clk ,
 input rst_n ,
 input data ,
 output reg detected
);

localparam IDLE = 3'b000 ,
             S0 = 3'b001 ,
             S1 = 3'b010 ,
             S2 = 3'b011 ,
             S3 = 3'b100 ,
             S4 = 3'b101 ;

reg [2:0] current_state, next_state;

always@ (posedge clk or negedge rst_n)
begin
  if(!rst_n)
    current_state <= IDLE;
  else
    current_state <= next_state;
end

always@ (*)
begin
  case(current_state)
    IDLE: begin
      detected = 0;
      if(data == 0)
        next_state = IDLE;
      else
        next_state = S0;
    end
    S0: begin
      detected = 0;
      if(data == 0)
        next_state = S1;
      else
        next_state = S0;
    end
    S1: begin
      if(data == 0)
        next_state = IDLE;
      else
        next_state = S2;
    end
    S2: begin
      if(data == 0)
        next_state = IDLE;
      else
        next_state = S3;
    end
    S3: begin
      if(data == 0)
        next_state = S4;
      else
        next_state = S0;
    end
    S4: begin
      detected = 1;
      if(data == 0)
        next_state = IDLE;
      else
        next_state = S0;
    end
  endcase
end

endmodule

testbench

使用 task,我们可以便捷地实现激励信号的输入。下面展示了序列检测器的 testbench。

`timescale 1ns / 1ps

module tb_detector;
parameter PERIOD = 2;
reg clk, rst_n, data;
wire detected;

detector d1(.clk(clk), .rst_n(rst_n), .data(data), .detected(detected));

reg [4:0] buffer;
integer i;
task series_gen(input [4:0] series);
  buffer = series;
  for(i = 4; i >= 0; i = i - 1) begin
    @(negedge clk)
      data = buffer[i];
  end
endtask

initial begin
  clk = 0;
  rst_n = 0;
  @(negedge clk)
  rst_n = 1;
  series_gen(5'b10110);
  series_gen(5'b10111);
end

always begin
  #(PERIOD / 2) clk = ~clk;
end

endmodule

仿真波形显示正确地产生了激励。
激励产生

在定义了产生激励信号的 series_gen task之后,每次需要产生激励信号时,我们只需要向这个 task 中填入参数就可以了,真是便捷啊。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值