1.预学习
主要参考:
- 搭建verilator仿真环境 | 官方文档 (oscc.cc)
Verilog基本语法: — GPT4.0
Verilog 语言是一种用于电子设计自动化和硬件描述的硬件描述语言(HDL)。它使设计者能够以文本形式描述复杂的电子系统。Verilog 的基本语法元素包括:
1. 模块 (Modules)
模块是 Verilog 中的基本结构单元,用于封装硬件设计的各个部分。一个模块可以表示一个简单的门电路,一个复杂的微处理器,或者任何中间规模的组件。
1 2 3
| verilogCopy codemodule moduleName(input input1, output output1); // 模块体 endmodule
|
2. 数据类型
- 网线 (wire): 用于连接模块内部的组件,或模块间的连接。它代表一个物理连接,可以携带一个信号。
- 寄存器 (reg): 用于在模块内部存储值。与 wire 不同,reg 可以保持其值,直到被新的值更新。
1 2
| verilogCopy codewire w; // 声明一个 wire 类型的变量 reg r; // 声明一个 reg 类型的变量
|
3. 运算符
Verilog 提供了多种运算符,包括算术运算符、逻辑运算符、比较运算符等。
- 算术运算符:
+
, -
, *
, /
, %
(取余)
- 逻辑运算符:
&&
(与), ||
(或), !
(非)
- 比较运算符:
==
(等于), !=
(不等于), <
(小于), >
(大于), <=
(小于等于), >=
(大于等于)
- 位运算符:
&
(位与), |
(位或), ^
(异或), ~
(位非), <<
(左移), >>
(右移)
4. 赋值语句
1 2
| verilogCopy code assign w = expression;
|
- 过程赋值: 包括
always
和 initial
语句块内的赋值,主要用于为 reg 类型变量赋值。
1 2 3
| verilogCopy codealways @(trigger) begin r = expression; end
|
5. 控制结构
- 条件语句: 如
if
, case
用于实现条件逻辑。
1 2 3 4 5
| verilogCopy codeif (condition) begin // 代码 end else begin // 代码 end
|
- 循环语句: 如
for
, while
用于实现循环。
1 2 3
| verilogCopy codefor (initialization; condition; increment) begin // 代码 end
|
6. 实例化 (Instantiation)
用于在一个模块内部创建另一个模块的实例,允许模块复用。
1 2
| verilogCopy code moduleName instanceName(.input1(signal1), .output1(signal2));
|
7. 任务和函数
- 任务 (task): 用于封装可以执行多个语句的代码块,可以有输入和输出参数,但不返回值。
- 函数 (function): 用于封装执行单个返回值的代码块,可以有输入参数。
1 2 3 4 5 6 7
| verilogCopy codetask taskName; // 任务体 endtask
function functionName; // 函数体 endfunction
|
1.1verilator仿真环境搭建
verilator:
Verilator 是一款开源的硬件描述语言(HDL)模拟器,它主要用于将 Verilog 代码转换成 C++ 或 SystemC 代码,进而允许在仿真环境中高效地执行硬件设计。这款工具特别适合于大规模复杂的数字设计项目,因为它在处理大型代码库时速度非常快,同时也支持大部分 Verilog-2005 标准的特性。
主要特点
- 高性能:Verilator 生成的模拟代码是编译型的,与解释型仿真器相比,这可以显著提升仿真速度。
- 开源:作为一个开源工具,Verilator 受到了广泛的社区支持,用户可以自由地使用、修改和分发它。
- 灵活性:Verilator 允许用户通过 C++ 或 SystemC 代码与仿真模型进行交互,这为高级仿真提供了极大的灵活性。
- 支持多种操作系统:包括 Linux、macOS 和 Windows,使其适用于多种开发环境。
以上来自 GPT4.0
安装verilator
按照环境依赖:
1 2 3 4 5 6
| sudo apt-get install help2man sudo apt-get install git perl python3 make autoconf g++ flex bison ccache sudo apt-get install libgoogle-perftools-dev numactl perl-doc sudo apt-get install libfl2 # Ubuntu only (ignore if gives error) sudo apt-get install libfl-dev # Ubuntu only (ignore if gives error) sudo apt-get install zlibc zlib1g zlib1g-dev # Ubuntu only
|
最后一条会报错,暂时忽略它
然后在新建一个文件夹用于存放源码,使用git命令克隆
1
| git clone https://github.com/verilator/verilator
|
切换到v5.008
版本
1 2 3 4 5 6 7 8 9 10 11 12 13
| cd verilator git chechout v5.008 #然后使用下面命令进行安装 autoconf unset VERILATOR_ROOT ./configure make -j `nproc`
#最后 sudo make install
#检测安装的版本 verilator --version
|
安装波型查看器GTKwave
1
| sudo apt-get install gtkwave
|
至此 环境配置搭建完成
verilator示例:
在官方手册中:Verilator (veripool.org)
根据示例进行操作
创建二进制的执行文件
新建一个verilog 文件 然后写入文件内容“
1 2 3 4 5
| cat >our.v <<'EOF' module our; initial begin $display("Hello World"); $finish; end endmodule EOF
|
编译文件
1 2 3
| verilator --binary -j 0 -Wall our.v #--binary 创建一切所需要的可执行文件 #-j 0 尽可能多使用cpu 的线程
|
运行文件并输出:
创建c++执行文件
根据示例创建即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| mkdir test_our cd test_our cat >our.v <<'EOF' module our; initial begin $display("Hello World"); $finish; end endmodule EOF
cat >sim_main.cpp <<'EOF' #include "Vour.h" #include "verilated.h" int main(int argc, char** argv) { VerilatedContext* contextp = new VerilatedContext; contextp->commandArgs(argc, argv); Vour* top = new Vour{contextp}; while (!contextp->gotFinish()) { top->eval(); } delete top; delete contextp; return 0; } EOF
#编译 --cc c++输出 --exe 创建一个可执行文件 --build 调用cmake verilator --cc --exe --build -j 0 -Wall sim_main.cpp our.v
|
双控开关
做这个之前先可以做一些官方教程指代的DUT实验,通过DUT 可以了解波形输出之类的
下面是双控开关:双控开关是一个应用通过两个开关(a,b)联合控制一盏灯的亮灭
Verilog 顶层模块代码 top.v文件
1 2 3 4 5 6 7 8
| module top( input a, input b, output f ); assign f = a ^ b; endmodule
|
使用指令将Verilog代码转换为C++代码
verilator –cc top.v
创建sim_main.cpp 文件 并在文件中添加记录波形代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include<stdio.h> #include<stdlib.h> #include<assert.h> #include <verilated.h> #include <verilated_vcd_c.h> #include "Vtop.h" #define MAX_SIM_TIME 20 vluint64_t sim_time = 0; int main(int argc, char** argv) { VerilatedContext* contextp = new VerilatedContext; contextp->commandArgs(argc, argv); Vtop* top = new Vtop{contextp}; Verilated::traceEverOn(true); VerilatedVcdC *m_trace = new VerilatedVcdC; top->trace(m_trace, 5); m_trace->open("waveform.vcd"); while (sim_time < MAX_SIM_TIME) { int a = rand() &1; int b = rand() &1; top->a = a; top->b = b; top->eval(); m_trace->dump(sim_time); sim_time++; printf("a = %d, b = %d,f = %d\n",a,b,top->f); assert(top->f == (a^b)); } m_trace->close(); top->final(); delete top; return 0; }
|
使用下面指令重新链接
1 2 3 4
| verilator -Wall--trace -cc top.v --exe sim_main.cpp make -C obj_dir -f Vtop.mk Vtop ./obj_dir/Vtop #运行可执行程序 gtkwave waveform.vcd # 可视化波形信号
|
接入nvboard
阅读文件夹中的readme文件
#安装依赖
sudo apt-get install libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev
#添加环境变量
export NVBOARD_HOME=/home/liangzhou/Desktop/ysyx/ysyx-workbench/nvboard
在nvboard 上实现双控开关
要想在nvboard上实现双控开关,得先弄懂nvboard 的工作原理 用
先使用make clean 清空编译的文件,然后用tree命令查看 example文件夹结构
constr中的top.nxdc文件 用于引脚绑定 用法可见readme文件
csrc中的main.cpp文件 实现代码
vsrc 包含Verilog代码
所以我们想要在 nvboard上实现双控开关
- 将双控开关的top.v文件放在vsrc文件中
- 在top.nxdc中 定义接口 定义规则见 readme文档
- 修改main.c代码
- 修改makefile文件
下面是修改的文件内容
top.v
1 2 3 4 5 6 7
| module top( input a, input b, output f ); assign f = a ^ b; endmodule
|
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <nvboard.h> #include <Vtop.h> #include<stdio.h> #include<stdlib.h> #include<assert.h> #include <verilated.h> #include <verilated_vcd_c.h>
static TOP_NAME dut;
void nvboard_bind_all_pins(TOP_NAME* top);
int main() { nvboard_bind_all_pins(&dut); nvboard_init();
while(1) { nvboard_update(); dut.eval(); assert(dut.f == (dut.a^dut.b)); } return 0; }
|
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| TOPNAME = top NXDC_FILES = constr/top.nxdc INC_PATH ?=
VERILATOR = verilator VERILATOR_CFLAGS += -MMD --build -cc \ -O3 --x-assign fast --x-initial fast --noassert
BUILD_DIR = ./build OBJ_DIR = $(BUILD_DIR)/obj_dir BIN = $(BUILD_DIR)/$(TOPNAME)
default: $(BIN)
$(shell mkdir -p $(BUILD_DIR))
SRC_AUTO_BIND = $(abspath $(BUILD_DIR)/auto_bind.cpp) $(SRC_AUTO_BIND): $(NXDC_FILES) python3 $(NVBOARD_HOME)/scripts/auto_pin_bind.py $^ $@
VSRCS = $(shell find $(abspath ./vsrc) -name "*.v") CSRCS = $(shell find $(abspath ./csrc) -name "*.c" -or -name "*.cc" -or -name "*.cpp") CSRCS += $(SRC_AUTO_BIND)
include $(NVBOARD_HOME)/scripts/nvboard.mk
INCFLAGS = $(addprefix -I, $(INC_PATH)) CXXFLAGS += $(INCFLAGS) -DTOP_NAME="\"V$(TOPNAME)\""
$(BIN): $(VSRCS) $(CSRCS) $(NVBOARD_ARCHIVE) @rm -rf $(OBJ_DIR) $(VERILATOR) $(VERILATOR_CFLAGS) \ --top-module $(TOPNAME) $^ \ $(addprefix -CFLAGS , $(CXXFLAGS)) $(addprefix -LDFLAGS , $(LDFLAGS)) \ --Mdir $(OBJ_DIR) --exe -o $(abspath $(BIN))
all: default
run: $(BIN) @$^
clean: rm -rf $(BUILD_DIR)
.PHONY: default all clean run
sim: $(call git_commit, "sim RTL") verilator --Wall --trace -cc ./vsrc/top.v --exe ./csrc/main.cpp make -C obj_dir -f Vtop.mk Vtop ./nvboard.a -lsDL2 -lSDL2_image
|
初始状态:
0
1
双控状态