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
相关推荐
風清掦15 小时前
【STM32学习笔记-14】WDG看门狗 - 14.2 WWDG窗口看门狗
笔记·stm32·单片机·嵌入式硬件·学习·fpga开发
尤老师FPGA18 小时前
HDMI数据的接收发送实验(十二)
fpga开发
坏孩子的诺亚方舟1 天前
FPGA神经网络数学基础0
人工智能·神经网络·线性代数·fpga开发
熠速1 天前
PolarBox高性能实时仿真系统
arm开发·fpga开发·嵌入式实时数据库·硬件在环半实物仿真
南檐巷上学1 天前
基于Zynq-7020的带有正弦波发生器的8051软核设计
单片机·嵌入式硬件·fpga开发·fpga
思尔芯S2C1 天前
FPGA原型验证中的内存模型应用:基于DDR5的Linux系统启动与测试
fpga开发·内存模型·ddr4·ddr5·memory model·hbm3·prototyping
hai3152475431 天前
RISC-V CVA6 AXI适配器+DMA桥蜂鸟E203处理器的总线接口单元(BIU)仲裁器
驱动开发·fpga开发·硬件架构·硬件工程·精益工程
高速上的乌龟2 天前
Lattice LFCPNX-100 HSB+Fpga开发详解:2.3 Hololink 顶层模块深度全解析
linux·fpga开发
ALINX技术博客2 天前
【FPGA 开发教程】基于 ALINX FPGA 开发板实现 USB3.2 高速通信(Z7-P+FL2010)
fpga开发·fpga·fmc子卡·usb3.2通信
Ricky05532 天前
搭载实时 FPGA 处理系统的航天器上用于海上监视的超分辨率YOLO目标检测技术(意大利2026年研究)
yolo·目标检测·fpga开发