Verilog测试平台(testbench)技术(五)
6. 交互式测试平台
在下面的几个测试平台里,我们采用了新的待测状态机,如下面代码所示。它是一个有开始 (start) 和复位 (rst) 控制的 1101Moore 序列检测器。它共有 5 个状态,在序列检测器的检测过程中,如果 start 的值变为 0 ,那么状态机复位到初始状态。当前状态到达 e 状态时,输出为 1 。
/*************************************************************************/
// 带开始 (start) 和复位 (rst) 控制的 1101More 序列检测器
`timescale 1ns/100ps
module Moore_detector (input x, start,rst, clk, output z);
parameter a=0,b=1,c=2,d=3,e=4;
reg [2:0] current;
always @( posedge clk )
begin
if( rst )
current <= a;
else if(~start)
current <= a;
else
case ( current )
a: current <= x?b:a;
b: current <= x?c:a;
c: current <= x?c:d;
d: current <= x?e:a;
e: current <= x?c:a;
default: current <= a;
endcase
end
assign z = (current==e);
endmodule
/*************************************************************************/
对于这个状态机,我们使用一个交互式测试平台,如下代码所示。
/*************************************************************************/
module test_moore_detector;
reg x=0,start,reset=1,clock=0;
wire z;
Moore_detector MUT(x,start,reset,clock,z);
initial
begin
#24 reset = 1'b0;
start = 1'b1;
wait(z==1'b1);
#11 start=1'b0;
#13 start=1'b1;
repeat(3)
begin
#11 start=1'b0;
#13 start=1'b1;
wait(z==1'b1);
end
#50 $stop;
end
always #5 clock=~clock;
always #7 x=$random;
endmodule
/*************************************************************************/
在一个 initial 块中,测试平台与待测模块通信。输入 x 和 clock 由两个 always 块生成。 clock 是连续周期信号, x 是周期产生的随机信号。
首先对 reset 和 start 的值分别赋值为 0 和 1 ,于是状态机开始工作,然后是一个 wait 语句,用于等待待测模块的结果 z 在输入 x 和 clock 的作用下变为 1 。当 z 变为 1 后, 11ns 后 start 变为 0 ,再过 13ns 后 start 变为 1 ,这是重启状态机的过程。 repeat 语句将重复 3 次这样的等待和重启过程。 repeat 语句执行完毕后 50ns ,运行系统 $stop ,仿真结束。
下图所示为测试平台的部分仿真波形。
下面介绍序列检测器的另一个交互式测试平台,代码如下所示。这个测试平台采用层次化命名访问待测模块里的参数 e 和变量 current 。系统任务 $display 和 $strobe 用于观测当状态机到达 e 状态时的电路输出。
/*************************************************************************/
// 使用显示任务的测试平台
module test_moore_detector;
reg x=0,start,reset=1,clock=0;
wire z;
Moore_detector MUT(x,start,reset,clock,z);
initial
begin
#24 reset = 1'b0;
start = 1'b1;
end
always
begin: Output_Display
wait (MUT.current == MUT.e);
$display("$display task shows:The output is %b",z);
$strobe("$strobe task shows:The output is %b",z);
#2 $stop;
end
always #5 clock=~clock;
always #7 x=$random;
endmodule
/*************************************************************************/
注:系统任务 $strobe 的功能同 $display 相似,不同的是使用 $display 显示的值是执行到 $display 语句时变量的值,而使用 $strobe 显示的值是当仿真时间介绍后变量的值。
在 Output_Display 这个 always 块中,当 current 的值等于 e 时 (current 和 e 都在待测模块中 ) ,系统任务 $display 和 $strobe 显示输出 z 的值。在这个测试平台的 always 块里,由于没有在检测到状态为 e 后加入时间延迟,所有系统任务 $display 显示的是 z 变化前的值。另外,当检测到状态为 e 后,经过一个仿真周期, z 值变为 1 , $strobe 会正确显示这个输出。
仿真输出及仿真部分波形显示如下:
# $display task shows:The output is 1
# $strobe task shows:The output is 1