【verilator】仿真生成 .fst / .vcd波形文件
——SZTU-小羊同学
#前言
FST格式的波形文件大致是VCD格式的1/50, 但它仅能被GTKWave支持. 尽管如此, 我们还是推荐你使用它.
——摘自ysyx讲义
这里就不赘述如何使用 Verilator 了,详情见 Verilator 手册:
Verilator User’s Guide — Verilator Devel 5.029 documentation
下面我们直接从如何生成波形文件开始。
一. 修改 Makefile 编译部分
启用波形输出:
在编译时,使用 --trace
或 --trace-fst
编译选项开启 VCD 或 FST 格式的波形生成。
示例:
假设你已经使用 Verilator 编译了你的 Verilog 代码,接下来的步骤展示如何生成 FST 文件。
verilator (--trace / --trace-fst) -cc top.v --exe sim_main.cpp
make -j -C obj_dir/ -f Vtop.mk Vtop
./obj_dir/Vtop
其中的 (--trace / --trace-fst)
为二选一。根据手册中的描述,--trace-fst
和 --trace
会相互覆盖,注意不能同时存在。
手册描述(机翻版):
--trace
使用 VCD 格式向模型添加波形跟踪代码。这将覆盖 --trace-fst
。
Verilator 将生成必须编译的其他 <prefix>__Trace*.cpp
文件。此外,verilated_vcd_sc.cpp
(对于 SystemC 跟踪)或 verilated_vcd_c.cpp
(对于两者)必须编译和链接。如果使用 Verilator 生成的 Makefile,这些文件将自动添加到您的源文件列表中。如果您不使用 Verilator Makefile,则需要手动将这些文件添加到 Makefile 中。
即使在模型执行期间未打开跟踪,编译跟踪也可能会导致轻微的性能损失。
当使用 --threads
时,VCD 跟踪是并行的,使用与传递给 --threads
相同数量的线程。
--trace-fst
在模型中启用 FST 波形跟踪。这将覆盖 --trace
。另请参阅 --trace-threads
选项。
二. 修改 C++ 仿真主函数部分
在你的 sim.cpp
中(假设叫这个名字),为了生成 VCD / FST 波形文件,你还需要添加几个关键语句。
1. 引入头文件
#include "verilated.h"
#include "verilated_fst_c.h"
#include "Vtop.h" // Your top module
#include "verilated.h"
:引入 Verilator 核心库,提供了仿真所需的基本功能,如仿真控制、信号追踪等。#include "verilated_fst_c.h"
:引入用于生成 FST 格式波形文件的 Verilator 头文件。VerilatedFstC
是 Verilator 提供的用于生成 FST 波形文件的类。#include "Vtop.h"
:Vtop
是通过 Verilator 编译生成的模块的类定义文件,它对应 Verilog 设计中的顶层模块top.v
。编译 Verilog 文件时,Verilator 会为 Verilog 模块生成相应的 C++ 类文件。
其中
#include "verilated_fst_c.h"
可替换为#include "verilated_vcd_c.h"
,后续均以此类推
2. 仿真主函数
int main(int argc, char **argv) {
Verilated::commandArgs(argc, argv);
int main(int argc, char **argv)
:这是程序的主函数。argc
和argv
是命令行参数,传递给 Verilator 用于控制仿真的一些选项。Verilated::commandArgs(argc, argv)
:Verilator 使用这行代码来初始化和解析命令行参数。该函数会将命令行参数传递给 Verilator 库,以便用于仿真配置(如传递给仿真模型的参数)。
3. 实例化顶层模块
Vtop *top = new Vtop;
Vtop *top = new Vtop;
:创建顶层模块top
的实例。Vtop
是通过 Verilator 生成的 C++ 类,表示 Verilog 文件中的顶层模块。这里使用new
关键字在堆上分配该对象,top
指向这个实例。在仿真过程中,该实例将被用于模拟硬件行为。
4. 初始化波形输出
VerilatedFstC* tfp = new VerilatedFstC;
Verilated::traceEverOn(true); // Trace enabled
top->trace(tfp, 99); // Trace signals
tfp->open("waveform.fst"); // Output FST file
VerilatedFstC* tfp = new VerilatedFstC;
:创建VerilatedFstC
类的实例,用于生成 FST 格式的波形文件。Verilated::traceEverOn(true);
:启用波形追踪功能,告诉 Verilator 仿真器在仿真过程中记录信号的变化。设置为true
以启用追踪。top->trace(tfp, 99);
:将top
模块的信号与tfp
关联起来,并指定追踪深度为99
。追踪深度控制仿真器记录信号的层级数,99
表示可以追踪到非常深的模块嵌套。tfp->open("waveform.fst");
:打开一个名为waveform.fst
的文件,并准备将波形数据写入该文件。生成的 FST 文件可以通过波形查看器(如 GTKWave)进行查看。
5. 仿真主循环
while (!Verilated::gotFinish()) {
// Simulate your design
// Update the top signals, clock, reset, etc.
top->eval();
}
while (!Verilated::gotFinish())
:这是仿真循环,Verilated::gotFinish()
返回false
,表示仿真还没有结束,循环将持续运行。通常,仿真结束条件是在设计中通过某种机制(如外部信号或仿真时间结束)触发。top->eval();
:每次循环调用top->eval()
,对设计进行一次评估。eval()
会执行 Verilog 设计的行为,计算新的信号值,并更新内部状态。这是仿真器每一时钟周期或事件触发时执行的核心函数。你可以在循环中添加时钟信号更新、复位信号等,用于完整的仿真控制。
6. 关闭波形文件和清理资源
tfp->close(); // Close the FST file at the end of simulation
delete top;
return 0;
}
tfp->close();
:关闭波形文件,确保所有波形数据写入文件并完成文件的关闭操作。仿真结束后,所有信号变化将写入waveform.fst
文件,供后续分析使用。delete top;
:释放顶层模块top
的内存。在堆上分配的对象需要手动删除以避免内存泄漏。return 0;
:程序正常退出。
三. 运行代码并查看vcd/fst波形文件
make run //这里由你自己编写的makefile脚本命令为准
gtkwave waveform.vcd / gtkwave waveform.vcd //根据生成的波形文件类型选择
即可查看波形文件