当前位置: 代码迷 >> 综合 >> Verilog 中 task 的语法,及使用 task 来完成模块的 testbench
  详细解决方案

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

热度:61   发布时间:2023-12-24 23:33:59.0

概述

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 declarationsprocedural_statement or statement_group
endtask

序列检测模块

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

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

`timescale 1ns / 1nsmodule 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)
beginif(!rst_n)current_state <= IDLE;elsecurrent_state <= next_state;
endalways@ (*)
begincase(current_state)IDLE: begindetected = 0;if(data == 0)next_state = IDLE;elsenext_state = S0;endS0: begindetected = 0;if(data == 0)next_state = S1;elsenext_state = S0;endS1: beginif(data == 0)next_state = IDLE;elsenext_state = S2;endS2: beginif(data == 0)next_state = IDLE;elsenext_state = S3;endS3: beginif(data == 0)next_state = S4;elsenext_state = S0;endS4: begindetected = 1;if(data == 0)next_state = IDLE;elsenext_state = S0;endendcase
endendmodule

testbench

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

`timescale 1ns / 1psmodule 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
endtaskinitial beginclk = 0;rst_n = 0;@(negedge clk)rst_n = 1;series_gen(5'b10110);series_gen(5'b10111);
endalways begin#(PERIOD / 2) clk = ~clk;
endendmodule

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

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

  相关解决方案