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
相关推荐
FPGA的花路10 小时前
UDP协议
fpga开发·以太网·udp协议
LCMICRO-1331084774619 小时前
长芯微LPS123完全P2P替代ADP123,高性能、低压差的线性稳压器
单片机·嵌入式硬件·fpga开发·硬件工程·dsp开发·线性稳压器
fei_sun21 小时前
面经、笔试(持续更新中)
fpga开发·面试
xixixi7777721 小时前
通信领域的“中国速度”:从5G-A到6G,从地面到星空
人工智能·5g·安全·ai·fpga开发·多模态
Nobody331 天前
Verilog always语句详解:从组合逻辑到时序逻辑
fpga开发
李嘉图Ricado1 天前
FPGA 时序约束与分析
fpga开发
白又白、1 天前
时序优化和上板调试小结
fpga开发
Z22ZHaoGGGG1 天前
verilog实现采样电流有效值的计算
fpga开发
fei_sun1 天前
牛客Verilog刷题篇
fpga开发