Alpha
|
b8c62c2726
|
tb: 无显示器扫雷联调套件(完整一局通关 216/216)
- srcs/tb/tb_saolei.v:VGA 帧缓冲截图、RAM 变量观察、PC 热点、跳转探针,
完整一局流程(点 START -> 首点击放雷 -> 带落位校验的全盘扫描 -> 通关)
- saolei/tools/fb2png.py:把仿真 dump 渲染成 640x480 PNG(无第三方依赖)
|
2026-09-19 19:43:07 +08:00 |
|
Alpha
|
47d2f22d07
|
fix(saolei): 修好鼠标事件链路三处 RTL bug —— 仿真里扫雷已能正常游玩
1) cpu21_pointer.v: sel 的位映射写错了(pend[2]->bit1, pend[1]->bit0, pend[0]->bit2),
而输出读的是 sel[1]=-dx / sel[2]=+dy / sel[3]=-dy / sel[0]=+dx。
后果:方向全乱(按下变左移、按右变下移),更致命的是清除逻辑
press_pend_q <= pend_next & ~sel 清不掉被选中的那一位 -> ev_valid_o 永久为 1
-> 鼠标中断线一直挂着 -> CPU 只收到一个上升沿、之后再无事件。改成一一对应。
2) cpu21_board_top.v: 鼠标中断与 LEVEL 软件中断的接线正好对调
(mouse 接 irq_vec[0]=IRQ1=0x100=关卡入口, level 接 irq_vec[1]=IRQ2=0x200=鼠标)。
后果:第一个鼠标事件把关卡叫起来画棋盘, 而鼠标 ISR 永不执行 -> FIFO 不弹空。
按 linker.ld/mmio.h 约定交换;拨码开关 SW[2:0] 仍按位 OR 进来。
3) cpu21_mmio.v: 同步中断线注释。
仿真验证(tb_saolei + fb2png): 事件队列正常出入(h/t 同步增长)、光标方向正确、
点击 START 进关卡、关卡内点击揭开格子(fb_we +90)、数字场 1/2/3 与大片 BFS 展开均正确
|
2026-09-19 19:33:18 +08:00 |
|
Alpha
|
3f765ae4c5
|
fix(saolei): 修显存窗口译码 + 段间空洞填 NOP; 新增无显示器调试台(仿真截图)
- cpu21_mmio.v: sel_fb 原写成 addr[12] && !addr[11](那是 0x1000-0x17FF),
导致 0x2000+ 的显存读写全不命中, 而鼠标/显示寄存器写反而落进显存。
改为 bit13=1 && bit12=0 && bit11=0 后扫雷画面才正常:
修复前仿真 fb_we 只有 6 次写(画面全空), 修复后开始界面 1246 次、进关卡后 2775 次
- cpu21_board_top.v: 新增 POINTER_SAMPLE_DIV 参数(默认仍为上板的 50000),
仿真传 50 即可让按键在几十微秒内被识别(defparam 对 generate 块内实例无效)
- saolei/tools/elf2hex.py: .text.isr1/2/3 之间的空洞(0 字)填 NOP —— objcopy 留下的
0x00000000 在本 CPU 上等同自跳指令, PC 掉进去就出不来
- saolei/tools/fb2png.py + srcs/tb/tb_saolei.v: 无 VGA 显示器的调试台 —— 跑板级顶层、
按键当鼠标、把 40x30 显存 dump 成文本, 再按 cpu21_vga.v 的字库/调色板还原 PNG,
并附 ASCII 图 + RAM 变量视图 + PC 热点直方图
|
2026-09-19 19:26:26 +08:00 |
|
Alpha
|
e44680a114
|
feat(board): 新增课程新版中断测试上板(多级中断 + 附加 SLL/SB/BLTU)
- programs/risc-v-intrupt-sllsb.asm/.hex: 课程原始程序(344 字,hex 已去掉 Logisim
的 v2.0 raw 头),保留原文件以便追溯
- tools/adapt_intrupt_sllsb.py: 把它适配到本 CPU 上板(只改 ROM 内容,地址不变)
- 课程用 addi a7,zero,34 + ecall 显示,本 CPU 里那是空操作 -> 每条显示点原地换成
一次调用:主程序 jal ra,DISP_DLY;ISR 用 add a7,a0,zero + jal a0,DISP_DLY_ISR
(三个 ISR 都没保存 ra,所以 ISR 版把链接寄存器放 a0、显示值放 a7)
- DISP_DLY / DISP_DLY_ISR 各 8 条,追加在 uret 之后,中断入口 0x0AC/0x240/0x3E8 不变
- 返回地址存 sp+256(越过 ISR 最多 192 字节的栈区),嵌套中断也破坏不了
- 脚本自带跳转目标自检(曾发现 ISR 侧 jal 偏移少算一条指令的问题)
- srcs/board/cpu21_board_top.v: 新增 RISC_V_INTRUPT_SLLSB_ROM 分支(ROM 选择、
CPU 分频用 CLK_DIV_INTRUPT、中断向量 0x0AC/0x240/0x3E8)
- srcs/board/risc-v-intrupt-sllsb.vh: 生成的 ROM 初始化(1024 字,程序 360 字)
- create_project.tcl: 新增 use_intrupt_sllsb 开关(默认 1,已把 ccab 置 0)
实测:Vivado 2020.2 建工程 + 综合通过(sources_1 verilog_define =
RISC_V_INTRUPT_SLLSB_ROM,synth_design Complete! 100%)
|
2026-09-19 16:10:19 +08:00 |
|
Anccend
|
f7844b7b1c
|
feat(board): 中断综合测试程序上板 + 可变分频/刷新率;README 大幅扩写
板级顶层(srcs/board/cpu21_board_top.v)
- ROM 增加 RISC_V_INTRUPT_CCAB_ROM 分支,中断入口 0x0AC/0x1E4/0x308;
与 SAOLEI_ROM / BOARD_ROM_FAST / 默认跑马灯构成 ifdef 链
- 新增参数 CLK_DIV_INTRUPT:跑中断测试程序时用更慢的 CPU 时钟(默认 32
= 3.125 MHz),让数码管上每个数值停留约 160 ms 便于观察
- 数码管扫描分频随 CPU 分频缩放(SEG_REFRESH_DIV = 100000/CPU_DIV),
保证每位数码管仍是 125 Hz(不闪);数码管改显示 MMIO 的 led_data;
LED[2:0] 改为锁存式中断指示(请求上升沿点亮、对应 ISR 执行 uret 后熄灭)
- 复位同步器/led_we 指示等注释同步更新;srcs/rtl/cpu21_seg7.v 分频计数
加宽到 20 位以容纳随主频变化的 REFRESH_DIV
工具与程序
- tools/adapt_intrupt_ccab.py:把课程中断测试镜像适配成上板 ROM。六处适配
(ISR 停机 ecall、显示改 MMIO+DISP_DLY、ISR2/ISR3 出栈顺序、ISR3 SB 测试
用未保存寄存器、ISR 破坏 ra 的 DISP_DLY_ISR),全部 2 字换 2 字,
不移动任何指令地址;带断言与 jal 目标自检
- programs/risc-v-intrupt-ccab.asm/.hex:课程中断综合测试程序(含六处适配说明)
- create_project.tcl:新增 use_intrupt_ccab / use_saolei 开关,自动把对应
ROM 头文件按 Verilog Header 加入 sources_1 并定义宏
- tools/rars_f0c874c.jar:课程 RARS 汇编器移到 tools/
文档(README.md)
- 新增"各模块的实现方式":按流水线主体 / 外设 / 板级逐模块讲实现要点
- 新增"内置程序与宏的用法":ROM 宏表(含各自的中断入口)、GUI/Tcl/命令行
三种定义方式、中断程序的适配流程与仿真验证方法
- 新增"分频与刷新率一览":CLK_DIV / CLK_DIV_INTRUPT / SEG_REFRESH_DIV /
led_we 时长 / DISP_DLY 延时常量分别在哪里改、怎么换算
- 修正引脚表(LED[2:0] 中断指示、led_we 0.34 s、CPU_DIV)与 ROM/RAM 说明
(ROM 8192 字 = 32 KB),补充中断程序上板现象与 ROM 头文件清单
验证:不带宏 / 带 RISC_V_INTRUPT_CCAB_ROM 两种配置 xvlog 编译均无错误;
三路嵌套与 IRQ3 抢占 ISR1 的仿真通过(level 逐级升降、uepc 正确恢复、
halted=0);tools/check_rtl_text.ps1 体检 OK。
|
2026-09-19 15:44:47 +08:00 |
|
Alpha
|
3512238965
|
fix(rtl): 修 cpu21_ps2_mouse 三处真 bug, 综合已通过 (0 errors / 0 critical warnings)
- frame_q[8:1][3] 是 Verilog-2001 非法写法(part-select 再取位), 综合报
[Synth 8-2599] range is not allowed in a prefix 与 [Synth 8-1008] frame_q is not a memory
-> 改为 frame_q[4] (= 数据字节 frame_q[8:1] 的 bit3)
- dx/dy 互换: 事件里把 dy 当 dx 上报
- 鼠标按键位错位: {2'b0, pkt_q[2], pkt_q[1]} 丢掉左键
-> {2'b0, pkt_q[2], pkt_q[1], pkt_q[0]} (对齐 cpu21_mmio / mmio.h: bit0=左键, bit1=右键, bit2=中键)
- tools/check_rtl_text.ps1: 修 tag 变量引用解析错、修块注释漏报、字符串中文误报
- create_project.tcl 头注: Vivado 版本改为 2020.2 (本机实测: 建工程 + 综合均通过)
|
2026-09-18 16:16:53 +08:00 |
|
Alpha
|
e4d58a3439
|
fix(saolei): 修复被编辑器覆盖的 board_top 端口行; 自检脚本支持 -Fix; tcl 默认定义 SAOLEI_ROM
- cpu21_board_top.v: PS/2 例化里 .ev_valid_o 被一行 README 正文覆盖, 综合报
[Synth 8-2715] non-printable character 0xe4 / syntax error near ...
- tools/check_rtl_text.ps1: 修掉块注释导致的漏报(board_top 就是被漏掉的那个);
改为按 UTF-8 原始字节读写(保持中文/换行/BOM 不变); 整行正文可用 -Fix 自动删除
- create_project.tcl: 新增 use_saolei 开关并定义宏 SAOLEI_ROM (1=扫雷, 0=走马灯)
|
2026-09-18 16:13:47 +08:00 |
|
Alpha
|
df7b3aee6d
|
fix(rtl): 清除被工具反复注入到 .v 末尾的 README 残行; 新增 RTL 文本自检脚本
- cpu21_pointer.v / cpu21_ps2_mouse.v / cpu21_vga.v 末尾多出一行 README 正文
(Tcl ...), 会导致 Vivado: ERROR: [Synth 8-2715] non-printable character 0xe4
- 新增 pipelined-cpu/tools/check_rtl_text.ps1: 综合前秒级自检, 检出代码位置上
的非 ASCII 文本/粘贴进来的正文行
|
2026-09-18 16:02:02 +08:00 |
|
Alpha
|
4e3525ffe2
|
fix(saolei): 修复被文本工具改坏的 RTL —— 这是综合失败的直接原因
## 现象(Vivado 2020.2 综合日志)
`synth_design -top cpu21_board_top -part xc7a100tcsg324-1` 报 13 个
`ERROR: [Synth 8-2715] syntax error`,指向:
- `cpu21_pointer.v:106`、`cpu21_board_top.v:308`、`cpu21_vga.v:242`
—— `non-printable character with the hex value '0xe4'`(UTF-8 中文字的首字节)
- `cpu21_board_top.v:139` —— `syntax error near "="`
- `cpu21_ps2_mouse.v:45 / 47 / 145` —— `0xe3`、`syntax error near "ta_s1"`
- `cpu21_board_rom.vh:3...` —— 一连串 `syntax error near "="`(前一处错误的级联)
## 根因
**不是 RTL 设计问题,是工作区文件被改坏**(编辑器/格式化类的文本改动把 README 的
片段插进了 Verilog 文件里):
1. `cpu21_pointer.v`、`cpu21_vga.v`、`cpu21_ps2_mouse.v` 文件末尾被追加了一行
来自 README 的 `Tcl 一键重建`(于是合成器在 `endmodule` 之后遇到中文字节);
2. `cpu21_board_top.v` 里被插入了同样的残行,**顶掉了 VGA 例化的 `.vga_hs` 那一行**;
3. `cpu21_board_top.v` 的 ROM 段被吞掉一整块:
`reg [31:0] rom [...]` / `integer i;` / `initial begin` 全部消失,
只剩下 `for (i = 0; ...) rom[i] = ...;` —— 这也正是 `cpu21_board_rom.vh`
里 `syntax error near "="` 的由来(`initial` 块没了,`rom[i]=...` 成了非法语句);
4. `cpu21_ps2_mouse.v` 的 `reg ps2_clk_s1, ps2_clk_s2, ps2_data_s1, ps2_data_s2;`
声明被拼进了 `assign ps2_data_oe_o = 1'b0` 里(变成
`assign ps2_data_oe_o = 1'b02_data_s1, ps2_data_s2;`),注释残片
`。本模块只接收,两条线都不驱动。` 夹在中间。
## 修复
- 删除 3 处 README 残行,恢复 `cpu21_board_top.v` 的 `.vga_hs` 端口连接;
- 补齐 `cpu21_board_top.v` ROM 段的 `reg/integer/initial begin`;
- 恢复 `cpu21_ps2_mouse.v` 被拼掉的 `reg` 声明,并整理开漏赋值的注释;
- 全量扫描 `srcs/**` 确认:无残留 README 文本碎片、`module/endmodule` 与
`` `ifdef/`endif `` 配对正常、四个受损文件的关键结构与例化(ROM/RAM/CPU/VGA/
数码管/按键、16 个字形表、PS2 状态机、按键去抖)均完整。
## 状态
- 本次只改 RTL 文本,未改任何逻辑/端口/地址。
- 本机没有 Vivado / xsim / iverilog,**无法在本地复验语法**,需要重新跑一次综合确认。
|
2026-09-18 15:58:13 +08:00 |
|
Alpha
|
f50639e90f
|
feat(saolei): 新增纯 C 扫雷(MMIO 显示 + 中断读鼠标),扩展 CPU 外设并清理仓库
## 背景
在原有五级流水 CPU 的基础上,用一颗 RISC-V 工具链把"纯 C 写的扫雷"编译成机器码
固化进片内 ROM 运行,并为此把 MMIO 外设从"只有一个 LED 寄存器"扩展成
显示(VGA 显存)+ 七段数码管 + 鼠标事件(含中断)的完整子系统。
原 LED MMIO 的语义保持不变,原有跑马灯/中断/指令回归不受影响。
## 硬件(pipelined-cpu/srcs)
- cpu21_mmio.v:扩展成 MMIO 中枢,新增
* 七段数码管寄存器(0x1004,8 位十六进制)
* 鼠标寄存器组(0x1100+):STATUS/DATA/ACK/CTRL/INPUT/TIME/FRAME/EVCNT/LEVEL/MAGIC
—— 含 16 项事件 FIFO 与 mouse_irq_o(读空自动回 0,不丢事件)
* 显示控制器(0x1140+):CTRL(光标可见/背景色)、CURSOR(列、行)
* 显存窗口(0x2000-0x27FF):写端口输出到板级顶层的双口 RAM,读保持组合读
* LEVEL(0x1120):软件中断寄存器,写 1 拉起 level_irq_o(用作"关卡入口")
* 地址译码、字节写合并、读数据 mux 全部按原风格实现
- 新增外设 RTL:cpu21_vga.v(640x480@60 按格子扫描,8x8 字模放大 2 倍)、
cpu21_seg7.v(8 位数码管动态扫描)、cpu21_pointer.v(5 向按键→鼠标事件,1 ms 去抖
+ 事件排队)、cpu21_ps2_mouse.v(可选真鼠标,PS/2 11 位帧接收 + 3 字节包解析)
- cpu21_riscv_redirect_int_bpb.v:新增外设总线端口(显存写/读回、鼠标事件输入、
中断输出、数码管数据、帧脉冲),例化扩展后的 cpu21_mmio
- cpu21_board_top.v:接入显存双口 RAM + VGA + 数码管 + 鼠标事件源,中断接线为
irq_i = {SW2, LEVEL|SW1, 鼠标|SW0};ROM 宏切换(定义 SAOLEI_ROM 加载扫雷程序);
ROM_WORDS 1024→8192
- cpu21_board_top.xdc:新增按键、SW[3]、8 位数码管、VGA、PS/2 的全部引脚约束
- tb_board_top.v:新端口显式接 0/1,避免悬空影响原跑马灯回归
- create_project.tcl:把 cpu21_saolei_rom.vh 按 Verilog Header 条件加入
## 软件(saolei/)
- sw/mmio.h:全部 MMIO 地址与格子编码(换地址只改这一个文件)
- sw/saolei.c:纯 C 扫雷 —— 背景"伪操作系统" main()(开始界面)+ 关卡 level_main()
(在 IRQ1 里跑完整局)+ 棋盘位图/布雷(首点安全)/BFS 展开/插旗/胜负判定/逐格绘制
- sw/isr.c:**中断读鼠标的代码**。三个固定地址入口:
* isr1_entry(.text.isr1=0x100)关卡入口:保存全部调用者保存寄存器 +
csrrsi 打开 MIE(让鼠标中断可嵌套)→ level_main
* isr2_entry(.text.isr2=0x200)鼠标读取:只存 ra → 纯 C 主体 isr_body
* isr3_entry(.text.isr3=0x300)备用:直接 uret
- sw/start.c:设 sp、清 .bss、进 main(只有这一处必要内联汇编)
- sw/linker.ld:复位 0x0、三个中断入口 0x100/0x200/0x300、栈顶 0x0FFC;
用 ASSERT 禁止 .data/.rodata(这颗核读不到 ROM 里的数据)
## 构建与工具链适配(saolei/tools)
- build.ps1:一键 C → .o → ELF → .hex + cpu21_saolei_rom.vh,任一步失败立刻停止
- check_isa.py:用"指令白名单"逐条检查反汇编,出现本核未实现的指令即报错并给修复提示
- elf2hex.py:裸二进制 → $readmemh hex + ROM 初始化头文件
- 三处针对本核的关键配置(都已写进脚本注释):
1) -march=rv32im_zicsr(GCC 15 起 rv32im 不含 Zicsr,csrrsi 会报错)
2) 不能禁链接器松弛:gcc 函数调用默认是 auipc+jalr,靠松弛压成 jal,
禁掉后 35 条 auipc 会留在代码里(本核没有 auipc);
用 -msmall-data-limit=0 防止松弛引入 gp 相对寻址
3) 中断入口地址必须写在段声明上(.text.isr1 0x100 : ...),
只写 ". = 0x100;" 会被 ld 忽略(实测 isr1 掉到了 0x14)
- 实测结果:text=3368B、data=0、bss=1436B,842 条指令全部通过 ISA 检查,
入口地址 _start=0x0 / isr1_entry=0x100 / isr2_entry=0x200 / isr3_entry=0x300
## 仓库清理
- 删除被工程取代的 saolei/hw、saolei/constrs(外设已并入 srcs/rtl)
- 删除全部 Vivado 生成物:.xpr、.runs、.sim、.cache、.hw、.ip_user_files、.Xil、
vivado.jou/log —— 需要工程时用 source create_project.tcl 一键重建(约 0.3 MB 源文件)
- .gitignore 增加 saolei/build/(构建产物可一键重建)
## 文档
- README:更新目录结构、仓库约定(不放生成物)、MMIO 地址表、文件与模块划分表、
上板说明,新增"扫雷程序(saolei/)"章节
- saolei/README.md:重写 —— 程序结构(背景/关卡/鼠标 + 三个中断入口)、
本核指令子集与对应写法、构建步骤与实测数据、MMIO 地址表、上板/仿真步骤、
操作说明、验证状态与已知可改进项
## 验证状态(如实说明)
- 已实测:C 工具链链路(编译/链接/ISA 检查/hex 生成/入口地址逐条核对)
- 未验证:所有 RTL 未经综合与仿真(本机无 Vivado),C 程序也未在仿真器/硬件上运行过;
建议先跑 tools/run_regress.ps1 确认原回归仍全 PASS,再用 SAOLEI_ROM 宏做行为仿真
|
2026-09-16 20:11:00 +08:00 |
|