Verilog入门实战——第5讲:Testbench 仿真编写 + 波形查看与分析

文章目录

  • 一、前言
  • [二、Testbench 基本结构](#二、Testbench 基本结构)
  • 三、关键语法说明
  • [四、实战:全加器 Testbench 完整示例](#四、实战:全加器 Testbench 完整示例)
    • [1. 被测试模块(回顾)](#1. 被测试模块(回顾))
    • [2. 仿真模块 tb_full_adder.v](#2. 仿真模块 tb_full_adder.v)
  • 五、波形查看与简单分析
  • [六、通用 Testbench 模板](#六、通用 Testbench 模板)

一、前言

功能代码写完并不代表设计结束,必须通过**仿真(Simulation)**验证逻辑是否正确。Testbench就是专门给设计模块提供输入激励、采集输出结果的"测试程序",是数字电路学习与FPGA开发中必不可少的一环。

本篇只讲通用、可直接套用的Testbench写法,不涉及复杂语法,拿来就能用。

二、Testbench 基本结构

仿真模块与普通模块类似,但不需要定义输入输出端口,结构固定如下:

verilog 复制代码
// 测试模块名(一般 tb_xxx)
module tb_xxxx;

// 1. 激励信号定义(reg 型,给模块输入)
reg  clk;
reg  rst_n;
reg  in;

// 2. 输出信号定义(wire 型,接收模块输出)
wire out;

// 3. 例化被测试的设计模块(DUT)
xxxx u_xxxx(
    .clk    (clk),
    .rst_n  (rst_n),
    .in     (in),
    .out    (out)
);

// 4. 生成时钟激励(可选)
initial begin
    clk = 0;
    forever #10 clk = ~clk;
end

// 5. 生成复位、输入数据激励
initial begin
    // 初始化
    rst_n = 0;
    in    = 0;
    #20;
    rst_n = 1;

    // 输入变化
    #30 in = 1;
    #20 in = 0;

    // 结束仿真
    #100;
    $stop;
end

endmodule

三、关键语法说明

  1. reg 驱动输入,wire 接收输出

    • 给模块输入的信号:定义为 reg
    • 从模块输出的信号:定义为 wire
  2. initial 结构

    仿真开始时只执行一次,用于初始化、按时间给激励。

  3. #延时
    #20 表示延时20个仿真时间单位,仅用于仿真,不综合成电路。

  4. $stop / $finish

    • $stop:暂停仿真,方便看波形
    • $finish:结束仿真并退出
  5. forever

    循环执行,常用于生成时钟信号

四、实战:全加器 Testbench 完整示例

以第4讲的全加器为例,编写仿真激励。

1. 被测试模块(回顾)

verilog 复制代码
module full_adder(
    input  wire a,
    input  wire b,
    input  wire cin,
    output wire sum,
    output wire cout
);

wire sum1, cout1, cout2;

half_adder u_half1(.a(a),.b(b),.sum(sum1),.cout(cout1));
half_adder u_half2(.a(sum1),.b(cin),.sum(sum),.cout(cout2));

assign cout = cout1 | cout2;

endmodule

2. 仿真模块 tb_full_adder.v

verilog 复制代码
module tb_full_adder;

// 激励输入
reg a;
reg b;
reg cin;

// 输出采集
wire sum;
wire cout;

// 例化 DUT
full_adder u_full_adder(
    .a     (a),
    .b     (b),
    .cin   (cin),
    .sum   (sum),
    .cout  (cout)
);

// 测试激励
initial begin
    a    = 0;
    b    = 0;
    cin  = 0;
    #10;

    a   = 0; b=0; cin=1; #10;
    a   = 0; b=1; cin=0; #10;
    a   = 0; b=1; cin=1; #10;
    a   = 1; b=0; cin=0; #10;
    a   = 1; b=0; cin=1; #10;
    a   = 1; b=1; cin=0; #10;
    a   = 1; b=1; cin=1; #10;

    #100;
    $stop;
end

endmodule

五、波形查看与简单分析

  1. 在 Quartus 中启动仿真,或在 ModelSim 中加载工程
  2. 将信号 a/b/cin/sum/cout 添加到波形窗口
  3. 运行仿真,对照真值表检查:
    • 输入组合是否正确
    • 进位 cout 与和 sum 是否符合全加器逻辑
  4. 若输出与预期不一致,说明设计代码逻辑错误。

六、通用 Testbench 模板

verilog 复制代码
module tb_top;

// 输入激励
reg  in1;
reg  in2;

// 输出观测
wire out1;
wire out2;

// 例化
top u_top(
    .in1(in1),
    .in2(in2),
    .out1(out1),
    .out2(out2)
);

initial begin
    in1 = 0;
    in2 = 0;
    #10;

    // 自定义激励
    #100;
    $stop;
end

endmodule
相关推荐
xyx-3v1 天前
SOC相对于版上系统的优势是什么?
fpga开发
Aaron15882 天前
RFSOC+VU13P+GPU 在6G互联网中的技术应用
大数据·人工智能·算法·fpga开发·硬件工程·信息与通信·信号处理
stars-he2 天前
基于 Design Compiler 的 UDP Payload 追加控制模块综合与门级后仿真
笔记·fpga开发·udp
尤老师FPGA3 天前
HDMI数据的接收发送实验(十)
fpga开发
逻辑诗篇3 天前
破核拆解:PCIE719——基于Xilinx Zynq UltraScale+的高性能SAS扩展卡设计
fpga开发·架构
逻辑诗篇3 天前
高性能存储扩展利器|PCIE719 基于Zynq UltraScale+的企业级可编程SAS方案
fpga开发
liuluyang5303 天前
SV主要关键词详解
fpga开发·uvm·sv
happyDogg_3 天前
验证环境采样rtl时序数据遇到的问题
fpga开发
unicrom_深圳市由你创科技3 天前
项目分析和FPGA器件选型外包服务包括哪些内容?别让选错芯片毁了整个项目
fpga开发
Aaron15883 天前
27DR/47DR/67DR技术对比及应用分析
人工智能·算法·fpga开发·硬件架构·硬件工程·信息与通信·基带工程