1.预学习

主要参考

  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. 赋值语句

  • 连续赋值: 用于为 wire 类型变量赋值。
1
2
verilogCopy code
assign w = expression;
  • 过程赋值: 包括 alwaysinitial 语句块内的赋值,主要用于为 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

image-20240408214422838

安装波型查看器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 的线程

运行文件并输出:

image-20240409111720849


创建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
// top模块 模块定义
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
//sim_main.cpp
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include <verilated.h> // 访问验证程序例程的库
#include <verilated_vcd_c.h> // 向VCD文件中写入波形
#include "Vtop.h" // 包含top模型的顶层文件
#define MAX_SIM_TIME 20 // 最大仿真时间
vluint64_t sim_time = 0;
int main(int argc, char** argv) {
//构建VerilatedContext以保留模拟时间
VerilatedContext* contextp = new VerilatedContext;
contextp->commandArgs(argc, argv);
//用VerilatedContext实例化自己的顶层类
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 # 可视化波形信号

image-20240409203828500

接入nvboard

阅读文件夹中的readme文件

#安装依赖

sudo apt-get install libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev

#添加环境变量

export NVBOARD_HOME=/home/liangzhou/Desktop/ysyx/ysyx-workbench/nvboard

image-20240409210330340

在nvboard 上实现双控开关

要想在nvboard上实现双控开关,得先弄懂nvboard 的工作原理 用

先使用make clean 清空编译的文件,然后用tree命令查看 example文件夹结构

constr中的top.nxdc文件 用于引脚绑定 用法可见readme文件

csrc中的main.cpp文件 实现代码

vsrc 包含Verilog代码

image-20240412204540650

所以我们想要在 nvboard上实现双控开关

  1. 将双控开关的top.v文件放在vsrc文件中
  2. 在top.nxdc中 定义接口 定义规则见 readme文档
    1. image-20240412205440885
  3. 修改main.c代码
  4. 修改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> //向VCD文件中写入波形

static TOP_NAME dut; // 创建dut对象 TOP_NAME宏定义

void nvboard_bind_all_pins(TOP_NAME* top); // 将所有引脚绑定nvboard

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 #定义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))

# constraint file 引脚自动绑定
SRC_AUTO_BIND = $(abspath $(BUILD_DIR)/auto_bind.cpp)
$(SRC_AUTO_BIND): $(NXDC_FILES)
python3 $(NVBOARD_HOME)/scripts/auto_pin_bind.py $^ $@

# project source
VSRCS = $(shell find $(abspath ./vsrc) -name "*.v")
CSRCS = $(shell find $(abspath ./csrc) -name "*.c" -or -name "*.cc" -or -name "*.cpp")
CSRCS += $(SRC_AUTO_BIND)

# rules for NVBoard
include $(NVBOARD_HOME)/scripts/nvboard.mk

# rules for verilator
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") # DO NOT REMOVE THIS LINE!!!
verilator --Wall --trace -cc ./vsrc/top.v --exe ./csrc/main.cpp
make -C obj_dir -f Vtop.mk Vtop ./nvboard.a -lsDL2 -lSDL2_image

初始状态:

image-20240412220547572

0

image-20240412220634891

1

image-20240412220706401

双控状态

image-20240412221307079