Verilator——最简单、最细节上手教程

前言

此教程会以ubuntu22.04为例
从如何安装,到如何使用
全程帮助你学习和使用verilator

狂肝3h,倾心之作

如有笔误、问题,欢迎指出、讨论~

点赞,收藏,长期翻看~

工具安装

Verilator 安装

利用git进行快速安装(安装方法摘自官网Verilator

# 安装的前提:
sudo apt-get install git help2man perl python3 make autoconf g++ flex bison ccache
sudo apt-get install libgoogle-perftools-dev numactl perl-doc
sudo apt-get install libfl2  # 只有Ubuntu需要,如果报错就忽略
sudo apt-get install libfl-dev  # 只有Ubuntu需要,如果报错就忽略
sudo apt-get install zlibc zlib1g zlib1g-dev  # 只有Ubuntu需要,如果报错就忽略

git clone https://github.com/verilator/verilator   #只需克隆一次

# Every time you need to build:
unsetenv VERILATOR_ROOT  # 对csh操作,如果是使用bash就忽略
unset VERILATOR_ROOT  # 对bash操作
cd verilator
git pull         # 确保git的仓库是最新的
git tag          # 查看可选版本

#选择以下的其中一个执行:
#git checkout master      # 使用开发分支(例如最近的bug修复版本)
#git checkout stable      # 使用最新的稳定版本
#git checkout v{version}  # 切换到指定版本

autoconf         # 创建脚本
./configure      # 配置并创建makefile
make -j `nproc`  # 构建verilator (如果报错试试只输入“make”)
sudo make install

然后执行

verilator --version	#检查版本,检查是否安装成功

GTKwave 安装

用来查看verilator生成的波形文件

有两种安装方法:

  1. 直接从ubuntu自带的应用商城搜索gtkwave,即可安装在这里插入图片描述
  2. 使用apt-get命令来安装
sudo apt-get install gtkwave
gtkwave --version	//查看版本,检查是否安装成功

Verilator 基础用法

fst格式和vcd格式的wave文件

varilator可以生成两种格式的wave文件:

  1. fst格式
    • FST格式的波形文件大致是VCD格式的1/50
    • 该格式只能用gtkwave打开,其他波形查看软件不支持
  2. vcd格式
    • 文件大小较大
    • 可以用多种波形查看软件查看

鉴于fst格式的优点,以及网上很少关于生成fst格式的教程,因此我以生成fst为例,如若要生成vcd可以上网查阅资料

接下来我将介绍如何使用verilator

Verilator 的使用

cpp为例,并介绍如何生成fst wave文件的生成

可以看官方的例程 :官方c++例程
此处我挑出其中重点的部分来讲解

假设我们用verilog写一个双控开关:

//顶层文件名为top,因此等会include的头文件为Vtop
//若顶层文件名为example,则include的头文件名为Vexample
module top(
  input clk,
  input rst,
  input a,
  input b,
  output reg f
);

  always @(posedge clk) begin
    if(!rst) f <= a ^ b;
  end

endmodule

仿真过程用c++来描述,文件如下:

//与verilator无关的一些头文件
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//使用verilater必须include
#include "Vtop.h" //仿真模型的头文件,由top.v生成,如果顶层文件名更改则也需要更改
#include <verilated.h>

#define CONFIG_FST_WAVE_TRACE 1

// contextp用来保存仿真的时间
VerilatedContext *contextp = new VerilatedContext;

// 构建一个名为top的仿真模型
Vtop *top = new Vtop{contextp};

//如果生成FST格式的wave
#if CONFIG_FST_WAVE_TRACE
#include "verilated_fst_c.h"			//波形文件所需的头文件
VerilatedFstC *tfp = new VerilatedFstC; // 创建一个波形文件指针
#endif

//仿真的过程
int main(int argc, char **argv)
{
	// 传递参数给verilator
	contextp->commandArgs(argc, argv);

//如果生成FST格式的wave
#if CONFIG_FST_WAVE_TRACE
	contextp->traceEverOn(true);		  // 启用跟踪
	top->trace(tfp, 99);				  // 采样深度为99
	tfp->open("build/logs/cpu_wave.fst"); // 打开波形文件,文件地址和文件名可以自定义
#endif

	/***************对top端口的初始化*******************/
	top->clk = 0;
	top->rst = 0;
	
	int cycle = 50;	//定义仿真循环次数,即仿真50个循环后就自动结束
	/**************verilator的仿真循环*****************/
	while (cycle)	// 仿真50个循环后就自动结束
	{
	
		/************设置vtop仿真的输入信号************/
	int a = rand() & 1;
    int b = rand() & 1;
    top->a = a;
    top->b = b;
    top->clk = !top->clk; // 随着仿真时间倒转clk,产生时钟周期
    top->eval(); //更新电路状态
    printf("a = %d, b = %d, f = %d\n", a, b, top->f);	//按需打印想要的
    
    contextp->timeInc(1); //推动仿真时间
		
#if CONFIG_FST_WAVE_TRACE
		tfp->dump(contextp->time()); // 按照时间采样
#endif
	cycle--;
	
	}

/*****************仿真结束,一些善后工作***************/
#if CONFIG_FST_WAVE_TRACE
	tfp->close(); // 关闭波形文件
#endif

	// 清理top仿真模型,并销毁相关指针,并将指针变为空指针
	top->final();
	delete top;
	top = nullptr;
	delete contextp;
	contextp = nullptr;

	return 0;
}

完成文件的编写后,我们要让verilator编译并运行
在命令行中输入

verilator -Wall top.v top_main.cpp --cc --trace-fst --exe --build
rm -rf $(BUILD_DIR)/logs	//清空存放波形文件的文件夹
mkdir -p $(BUILD_DIR)/logs	//再创建新文件夹存放波形文件
./obj_dir/Vtop   //必须执行这个,才运行仿真,生成波形
gtkwave build/logs/cpu_wave.fst	//用gtk打开波形文件

Verilator 的进阶使用

与GDB搭配

gdb可以很方便得对仿真的过程进行调试

如何使用请详见 “与makefile搭配”

与makefile搭配

如果每次使用verilator都要在命令行中输入以上命令,有点太麻烦了
因此可以利用makefile

########### 不要在变量后面加多余空格,否则会导致变量名出问题 ###########
########### 因此也不要在变量后面加注释,以避免上述情况发生 ###########

#顶层文件的名字
TOPNAME = top

#指定verilator
VERILATOR = verilator

######################## 构建后的项目 ########################
#构建后的地址
BUILD_DIR = ./build/verilator

#构建后文件存放的地址
OBJ_DIR = $(BUILD_DIR)/obj_dir

#可执行文件的地址
BIN = $(OBJ_DIR)/$(TOPNAME)

######################## verilator选项 ########################
#创建生成文件的目录,存放生成的文件
VERILATOR_FLAGS += --Mdir $(OBJ_DIR)

#优化分配 
VERILATOR_FLAGS += -x-assign fast

#将所有warning 变成error
VERILATOR_FLAGS += -Wall

#Make waveforms,fst格式
VERILATOR_FLAGS += --trace-fst

#检查SystemVerilog断言
VERILATOR_FLAGS += --assert

#debug模式,生成更多调试信息
VERILATOR_FLAGS += --debug

#Add this trace to get a backtrace in gdb
VERILATOR_FLAGS += --gdbbt

# 可用gdb调试
VERILATOR_FLAGS += --gdb

#加速编译
VERILATOR_FLAGS += -j

#调用工具链来构建库,不加则由verilator自己构建
VERILATOR_FLAGS += --build

#指定顶层文件
VERILATOR_FLAGS += --top-module $(TOPNAME)

#生成C++可执行文件,并指定文件名字
VERILATOR_FLAGS += --cc --exe -o $(abspath $(BIN))

######################## 查找相关文件 ########################
#所有 .v 或者 .sv 文件
VSRCS = $(shell find $(abspath ./build/chisel) -name "*.v" -or -name "*.sv")

#所有 .c 或 .cc 或 .cpp 文件
CSRCS = $(shell find $(abspath ./src/main/cpp) -name "*.c" -or -name "*.cc" -or -name "*.cpp")

######################## 目标与命令 ########################
run:
	@echo "-------- VERILATE --- AND --- BUILD --------"
#清空再创建编译后文件放置的目录
	@rm -rf $(OBJ_DIR)
	@mkdir -p $(OBJ_DIR)

#使用verilator进行编译,产生可执行文件
	@$(VERILATOR) $(VERILATOR_FLAGS) $(VSRCS) $(CSRCS)

	@echo
	@echo "-------------------- RUN --------------------"

#清空再创建波形文件夹
	@rm -rf $(BUILD_DIR)/logs
	@mkdir -p $(BUILD_DIR)/logs

#执行可执行文件,运行并仿真,生成波形
	@$(BIN) +trace

	@echo
	@echo "-------------------- DONE --------------------"
	@echo "To see waveforms, open $(BUILD_DIR)/logs/cpu_wave.fst in a waveform viewer"
	@echo


gdb:
	@echo "-------- VERILATE --- AND --- BUILD --------"

#清空再创建编译后文件放置的目录
	@rm -rf $(OBJ_DIR)
	@mkdir -p $(OBJ_DIR)

#使用verilator进行编译,产生可执行文件
	@$(VERILATOR) $(VERILATOR_FLAGS) $(VSRCS) $(CSRCS)

	@echo
	@echo "-------------------- GDB --------------------"

#清空再创建波形文件夹
	@rm -rf $(BUILD_DIR)/logs
	@mkdir -p $(BUILD_DIR)/logs

#gbd执行可执行文件,运行并仿真,生成波形
	gdb -s $(BIN) --args $(BIN)

	@echo
	@echo "-------------------- DONE --------------------"
	@echo "To see waveforms, open $(BUILD_DIR)/logs/cpu_wave.fst in a waveform viewer"
	@echo

然后在当前目录下执行

make run	//执行仿真
make gdb	//使用gdb

即可

Verilator 的高阶用法

访问模块内部数据

前面的介绍中,我们要访问模块的数据,只能访问到顶层模块top的输入输出端口,假如我要访问其中内部的wire和reg数据该怎么办呢?

verilator为在将verilog文件编译为cpp文件进行仿真的时候,我们可以在仿真文件中访问verilator将.v文件转化后的cpp文件来访问数据

只需在上面的仿真文件中增加以下内容

#include "../build/obj_dir/Vtop___024root.h"

//然后就可以通过top来访问了
printf("data:%x",top->rootp->top__DOT__my_regfile__DOT__reg_f[1])
//my_regfile为实例化的模块名
//reg_f为模块中定义的reg型
//若你想输出你想要的数据可以在 ../build/obj_dir/Vtop___024root.h 头文件中寻找
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值