3、Testbench基础:Testbench结构、initial/always块、时钟与复位生成、基本激励编写
好,咱们今天聊聊Testbench。说白了,Testbench就是咱们给DUT(Design Under Test)搭的一个“测试台”。你想想看,芯片流片前,你总得先验证一下它能不能干活吧?Testbench就是这个干活的平台。
我个人习惯,写Testbench之前,脑子里先画个草图。这个草图就是Testbench的结构。它不复杂,但每个部分都有讲究。
3.1 Testbench的基本结构
一个标准的Testbench,通常包含这么几个部分:
- DUT实例化:把你要测的模块“放”进来。
- 激励生成:给DUT喂数据、控制信号。
- 时钟与复位:提供最基本的“心跳”和“复位”信号。
- 结果监测:看DUT的输出对不对。
- 仿真控制:什么时候开始,什么时候结束。
嗯,这里要注意,Testbench本身是不需要端口的。它就是一个顶层模块,内部把所有信号都定义好,然后直接连到DUT上。
我给大家画个图,这样更直观:
你看,这个结构很清晰。激励从左边进来,DUT在中间处理,结果从右边出去。时钟和复位是全局的,仿真控制则负责协调整个流程。
3.2 initial 与 always 块
这两个是Verilog里最核心的过程块。我刚开始学的时候,也经常搞混它们。其实很简单:
- initial块:只执行一次。适合做初始化、配置、产生单次激励。
- always块:循环执行。适合做时钟、周期性信号、组合逻辑。
举个例子,你一看就明白:
// initial 块:只执行一次
initial begin
a = 0;
b = 1;
#10 a = 1;
#20 b = 0;
#30 $finish;
end
// always 块:永远循环
always begin
#5 clk = ~clk; // 产生周期为10的时钟
end
我在项目中遇到过一个问题:有人用initial块去驱动一个需要持续变化的信号,结果仿真跑了一会儿信号就停了。为什么?因为initial只执行一次啊!你想想看,如果你想让一个信号一直变化,就得用always块。
3.3 时钟与复位生成
时钟和复位,是Testbench的“心脏”和“开关”。没有它们,DUT根本动不起来。
时钟生成:
最常用的方法,就是用always块:
reg clk;
initial clk = 0;
always #5 clk = ~clk; // 50MHz时钟(周期10ns)
嗯,这里要注意,如果你需要多个不同频率的时钟,可以这样:
reg clk_100m, clk_50m;
initial begin
clk_100m = 0;
clk_50m = 0;
end
always #5 clk_100m = ~clk_100m; // 100MHz
always #10 clk_50m = ~clk_50m; // 50MHz
复位生成:
复位信号,我一般用initial块来产生:
reg rst_n;
initial begin
rst_n = 0; // 先复位
#100;
rst_n = 1; // 释放复位
#200;
rst_n = 0; // 再来一次复位(模拟复位抖动)
#50;
rst_n = 1;
end
3.4 基本激励编写
激励,就是你要喂给DUT的数据。怎么写呢?我给大家总结了几种常见模式:
模式一:直接赋值
最简单,适合控制信号:
initial begin
data_in = 8'h00;
#10 data_in = 8'hA5;
#20 data_in = 8'h5A;
end
模式二:循环赋值
适合批量数据:
integer i;
initial begin
for(i=0; i<256; i=i+1) begin
data_in = i;
#10;
end
end
模式三:任务封装
我个人最喜欢这种方式。把常用的激励写成任务,调用起来特别方便:
task write_reg(input [7:0] addr, input [7:0] data);
begin
@(posedge clk);
cs_n = 0;
wr_n = 0;
addr_bus = addr;
data_bus = data;
@(posedge clk);
cs_n = 1;
wr_n = 1;
end
endtask
initial begin
// 调用任务
write_reg(8'h01, 8'hFF);
#100;
write_reg(8'h02, 8'h00);
end
好了,关于Testbench的基础,咱们就聊这么多。记住,写Testbench就像搭积木,结构清晰了,剩下的就是往里面填内容。时钟、复位、激励,这三样东西搞定了,你的Testbench就成功了一大半。