Banner Image

From miniRV to VGA image generation

A Trail of the project 一生一心

By Ansen Lin March 4, 2026

First meet with RISC-V, and first time to write a project blog

2026-03-03 开发日志:从 miniRV 到 VGA 图形验证

1. 工作简介

接触“一生一芯”项目的第一天,大致完成了F部分的任务目标:文档的要求是在Logisim上搭建出用8条指令实现rsc32基本功能的minirv。通过自己编写的mem/sum测试了add / addi / lui / lw / lbu / sw / sb / jalr8条指令的功能实现,确保功能没问题后跑通vga测试,生成“一生一芯”项目logo。

我的工作环境是MacOS。由于logisim电路搭建效率低,我决定直接基于icarus-verilog采用 iverilog + vvp 的方式将 rtl/minirv.v + tb/minirv_tb.v 编译成可执行仿真程序(build/simv / build/simv_vga),再进行vvp仿真,仿真结果通过check_output.c验证是否符合官方指导文档中的结果。

由于icarus-verilog无法直接解析官方v3.0 hex格式(该格式带有logisim识别用代码头),我通过logisim_hex_to_words.c将其转换为icarus-verilog可解析的word-hex格式。执行完vga测试后,通过fb_to_ppm.c将结果转换为可视化图片。

以上流程整理在Makefile中,CLI中 make test 执行,总耗时为4min。

2. 代码结构(目录与职责)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RV32/
├── rtl/
│ └── minirv.v # 处理器核心(8条指令,两拍FSM)
├── tb/
│ └── minirv_tb.v # testbench:RAM模型 + VGA MMIO + FINAL输出
├── tools/
│ ├── gen_tests.c # 生成基础自测程序 tests/mem.hex, tests/sum.hex
│ ├── logisim_hex_to_words.c # 官方v3.0 hex格式转普通word-hex
│ ├── check_output.c # 解析日志并检查 pc/a0 与图像像素条件
│ └── fb_to_ppm.c # VGA写事件/帧数据还原为 PPM 图片
├── tests/
│ ├── mem.hex
│ ├── sum.hex
│ └── logisim-bin/
│ ├── mem.hex / sum.hex / vga.hex # 官方测试输入
│ └── mem.txt / sum.txt / vga.txt # 对应反汇编说明
├── Makefile # 一键编译/仿真/检查入口
├── README.md # 项目说明

3. 知识点复盘

miniRV 指令集

ADD

1
result = rs1_data + rs2_data

ADDI

1
result = rs1_data + imm

LUI

1
result = imm

JALR(会修改 PC)

1
2
result = rs1_data + imm
next_pc = result & ~1

SW

1
2
3
4
addr = rs1_data + imm_s
mem_addr = addr & ~3 (对齐到32-bit word)
mem_we = 1
mem_wdata = rs2_data (整32位写入)

SB

1
2
3
4
5
6
7
addr = rs1_data + imm_s
mem_addr = addr & ~3 (对齐到32-bit word)
byte_sel = addr[1:0]
old_word = mem_rdata (先读出原32位)
new_word = (old_word & ~(8'hFF << (byte_sel*8))) | ((rs2_data[7:0]) << (byte_sel*8))
mem_we = 1
mem_wdata = new_word (读-改-写实现byte写)

LBU

1
2
3
4
5
addr = rs1_data + imm_i
mem_addr = addr & ~3 (对齐到32-bit word)
byte_sel = addr[1:0]
byte = (mem_rdata >> (byte_sel*8)) & 8'hFF
result = zero_extend(byte) ({24'b0, byte})

LW

1
2
3
addr = rs1_data + imm_i
mem_addr = addr & ~3 (对齐到32-bit word)
result = mem_rdata (读出的32位直接写回)

2 关于 icarus-verilog

可以使用同样开源的 Verilator

Verilator 是一个开源的 Verilog/SystemVerilog 编译型模拟器
它将 Verilog 代码转换成高效的 C++/SystemC
模块,然后生成本地可执行程序
其仿真速度远快于解释式模拟器

MacOS 安装方式:

1
brew install verilator

4. Github

现有版本基本实现单周期minirv功能,项目已部署到https://github.com/Kingprotea787/RISC-V