feat(board): 支持 PS/2 键盘(与鼠标共用板载 USB HID 口),并修好 PS/2 帧校验
一、修 PS/2 接收器的真 bug —— 这就是上板“鼠标毫无反应”的根因
鼠标和键盘两个接收模块原来是同一个写法错误:
* 帧用整体右移 {data, frame_q[10:1]},判 frame_q[10] 时停止位还没移进来,判到的
其实是校验位;取数据 frame_q[8:1] 也因此整体错一位
* 校验位按“偶校验”判,而 PS/2 是“奇校验”
两者叠加让真设备发来的帧 100% 被丢掉(上板表现为 rx_count 恒为 0,看起来像硬件
或跳线问题)。现在按“位的下标”存帧(frame_q[i] = 第 i 位,所以字节 = frame_q[8:1]、
校验 = frame_q[9]),停止位直接在当前拍的 ps2_data 上判,校验按奇校验。
二、新增 PS/2 键盘解码 cpu21_ps2_kbd.v
扫描码集 2:E0 = 扩展前缀、F0 = 松开前缀,只对“按下”产生事件,并映射成与鼠标
完全相同的事件格式(↑↓←→ = dy/dx ±8,正好一格;Enter/空格 = 左键;左 Shift/F/C
= 右键 = 插旗),所以 saolei 的 C 代码一行都不用改;按住方向键 = 连续移动(用的是
键盘自己的重复码)。
三、顶层 cpu21_board_top:用 SW15 选设备
同一根 PS/2 线上只会插一个设备,但两个解码器都在听:键盘的扫描码会凑巧组成
“合法的鼠标包”,两路同时生效会让光标乱跳。因此新增端口 hid_sel(SW15):
0 = 键盘(默认),1 = 鼠标;诊断 LED 改显示“当前选中设备”收到的字节数。
四、其它
* XDC:hid_sel -> V10(SW15),引脚号在官方母版里核对过
* tb_board_top 补 hid_sel 端口,避免悬空
* 新增自测 srcs/tb/tb_ps2_mouse.v / tb_ps2_kbd.v:含“故意发一个校验位错的帧,
必须丢帧”的用例,两个都 ALL PASS
* README / saolei/README:新增“PS/2 键鼠”一节(接线方式、SW15、LED 诊断口诀、
键位表),修正显存格式(每格 2 字节、0x2000-0x2FFF)、扫雷难度与验证状态、
修好 riscv 工具链 -Prefix 路径
This commit is contained in:
+48
-25
@@ -19,7 +19,8 @@ saolei/
|
||||
|
||||
配套硬件在 Vivado 工程里(不在本目录):`srcs/rtl/cpu21_mmio.v`(外设中枢)、
|
||||
`cpu21_vga.v`(显示)、`cpu21_seg7.v`(数码管)、`cpu21_pointer.v`(按键当鼠标)、
|
||||
`cpu21_ps2_mouse.v`(可选真鼠标)、`srcs/board/cpu21_board_top.v`(上板顶层)。
|
||||
`cpu21_ps2_mouse.v` / `cpu21_ps2_kbd.v`(可选真鼠标/真键盘)、
|
||||
`srcs/board/cpu21_board_top.v`(上板顶层)。
|
||||
|
||||
---
|
||||
|
||||
@@ -148,36 +149,58 @@ copy build\saolei.hex <仓库>\pipelined-cpu\srcs\rom\saolei.hex
|
||||
`cpu21_board_top.v` 就会加载 `cpu21_saolei_rom.vh`;不定义仍是原来的跑马灯程序。
|
||||
接 VGA 显示器,按 `CPU_RESETN` 复位 → 出现开始界面(标题 + 绿色按钮 + 闪动光标框)。
|
||||
|
||||
**操作**(默认用板上 5 向按键):
|
||||
**操作**(板载 5 向按键一直有效):
|
||||
|
||||
| 操作 | 按键 |
|
||||
| ------------------------------------ | --------------------------------------- |
|
||||
| 移动光标 | `BTNU` / `BTND` / `BTNL` / `BTNR` |
|
||||
| 左键(揭开;在开始界面上 = 开始) | `BTNC` |
|
||||
| 插旗模式(拨上去后左键 = 插/取消旗) | `SW0` 或 `SW3` |
|
||||
| 返回上一层(关卡内) | 把光标移到盘面**左上角黄格**再按 `BTNC` |
|
||||
| 操作 | 板载按键 | PS/2 设备(SW15 选) |
|
||||
| ------------------------------------ | ------------------------------------- | ------------------------------------- |
|
||||
| 移动光标 | `BTNU` / `BTND` / `BTNL` / `BTNR` | 键盘 `↑↓←→`(按住 = 连续)/ 鼠标移动 |
|
||||
| 左键(揭开;开始界面 = 选难度/开始) | `BTNC` | 键盘 `Enter`/空格 / 鼠标左键 |
|
||||
| 右键(插旗 / 取消旗) | `SW3`(或 `SW0`)拨上 + `BTNC` | 键盘左 `Shift`/`F`/`C` / 鼠标右键 |
|
||||
| 返回上一层(关卡内) | 光标移到盘面**左上角黄格**再按左键 | 同上 |
|
||||
|
||||
**鼠标**:默认按键;想用真鼠标就把顶层参数 `USE_PS2_MOUSE` 设为 1(需要 Digilent
|
||||
Pmod PS2 插在 JA + 一个 PS/2 鼠标)。`cpu21_ps2_mouse.v` 只实现了**接收**(发 0xF4
|
||||
初始化要靠鼠标产生的时钟脉冲,不是固定延时能糊的,所以没写假的);多数鼠标上电即上报,
|
||||
需要 0xF4 的那种得自己补。USB 鼠标在这个核上不现实(协议栈放不下)。C 程序两种方式
|
||||
完全不用改。
|
||||
**PS/2 键鼠**(板载 USB HOST 口,也可把 Pmod PS/2 插在 JA):顶层参数
|
||||
`USE_PS2_MOUSE` 默认为 1,鼠标解码器和键盘解码器都挂在同一根 PS/2 线上,**用 SW15
|
||||
选哪个生效**(0 = 键盘,1 = 鼠标)。键盘解的是扫描码集 2(`E0` 扩展前缀、`F0` 松开
|
||||
前缀,只对按下产生事件),映射成与鼠标**完全一样**的事件格式,所以 C 代码一行不用改。
|
||||
接收器只做**接收**(不实现主机发 `0xF4` 使能上报):多数键鼠上电即上报。上板时用
|
||||
LED 诊断看“当前设备收到的字节数”(见根目录 README 的“PS/2 键鼠”一节)。
|
||||
USB 鼠标在这个核上不现实(协议栈放不下)。
|
||||
|
||||
**踩过的坑(值得写进报告)**:`cpu21_ps2_mouse.v` 早期把 11 位帧**整体右移**、又在
|
||||
停止位还没移进来时就判 `frame_q[10]`,并且把 PS/2 的**奇**校验当成**偶**校验判,结果
|
||||
真设备发来的帧**全部被丢掉** —— 上板表现就是“插上鼠标毫无反应、收到的字节数恒为 0”,
|
||||
很容易误判成硬件/跳线问题。现在帧按**位的下标**存(`frame_q[i]` = 第 i 位)、停止位
|
||||
单独判(它就在当前拍的 `ps2_data` 上)、校验按奇校验判,并且
|
||||
`srcs/tb/tb_ps2_mouse.v` / `tb_ps2_kbd.v` 两个自测里都带“故意发错校验 → 必须丢帧”
|
||||
的用例。
|
||||
|
||||
## 6. 验证状态(说实话)
|
||||
|
||||
| 部分 | 状态 |
|
||||
| ------------------------------------------------------------------------------------ | ------------------------------------------------------ |
|
||||
| C 工具链链路 | 本次修改后未验证:当前环境缺少 RISC-V 交叉编译器 |
|
||||
| `saolei.c` / `isr.c` / `start.c` / `linker.ld` | 本机 GCC 语法检查通过;目标 ISA 构建待工具链恢复后执行 |
|
||||
| `cpu21_mmio.v` 扩展、`cpu21_vga.v`、`cpu21_seg7.v`、`cpu21_pointer.v`、板级顶层、XDC | `xvlog` 编译通过;未综合、未上板 |
|
||||
| 部分 | 状态 |
|
||||
| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
|
||||
| C 工具链链路 | 已实测通过:`text=4608 B, data=0, bss=2508 B`,**1152 条指令全部通过 ISA 检查** |
|
||||
| 游戏逻辑(布雷、`count_adj`、三档难度、`draw_tile`) | PC 侧独立测试通过(3 难度 × 40 局重算比对 + 端到端显示测试) |
|
||||
| 仿真显示(`tb_saolei` / `tb_saolei_play` + `tools/fb2png.py`) | 通过:整屏 dump 能还原成 PNG,hard 盘面(30×16)整屏都能画出来 |
|
||||
| `cpu21_mmio.v` / `cpu21_vga.v` / `cpu21_seg7.v` / `cpu21_pointer.v` / 板级顶层 / XDC | `xvlog` 编译通过;已综合、已上板 |
|
||||
| 上板实测 | VGA 画面、开始界面、三档难度、开格/插旗、板载按键均已实测可用 |
|
||||
| PS/2 键鼠 | 接收器逻辑有自测(`tb_ps2_mouse` / `tb_ps2_kbd`);板载 USB HOST 口待复测 |
|
||||
|
||||
建议验证顺序:① 跑 `pipelined-cpu/tools/run_regress.ps1` 确认原来的跑马灯/中断/指令
|
||||
测试仍全 PASS;② 定义 `SAOLEI_ROM` 跑行为仿真,看有没有往 `0x2000` 起的显存写字节、
|
||||
按键后有没有跳进 `0x200`;③ 再上板。
|
||||
建议验证顺序:① 跑 `pipelined-cpu/tools/run_regress.ps1` 确认跑马灯/中断/指令测试仍全
|
||||
PASS;② 定义 `SAOLEI_ROM` 跑行为仿真(`tb_saolei` 会自动打完一局并 dump 显存);
|
||||
③ 上板看 VGA;④ 接键鼠时先用 `srcs/tb/tb_ps2_*` 确认解码无误,再看 LED 诊断确认板载
|
||||
桥接芯片到底有没有转发你插的那个设备。
|
||||
|
||||
## 7. 已知可改进项
|
||||
|
||||
- **文字显示**:显存现在每格占 2 字节,字形编号扩展到 6 位,RTL 内置 A-Z 和数字/游戏
|
||||
符号字模,开始界面显示 `MINES`、`EASY`、`NORMAL`、`HARD`、`START`。
|
||||
- 棋盘固定 16×16,开始界面可选 20/40/60 雷(16 是 2 的幂,索引全用移位,一次除法都不用)。
|
||||
- `run_regress.ps1` 里还没有扫雷的自动测试项。
|
||||
- **难度**:已按微软扫雷做成三档 —— `EASY` 9×9/10 雷、`NORMAL` 16×16/40 雷、
|
||||
`HARD` 30×16/99 雷。盘面尺寸是**运行期变量**(`g_bw/g_bh/g_mines/g_ncells`),
|
||||
开始界面上点那一行就即时切换、重新画盘面;所有索引走 `IDX_R/IDX_C` 宏。
|
||||
再想更大就要动 `bfs_q` 的打包方式(数据 RAM 只有 4 KB)。
|
||||
- **输入**:板载 5 向按键、PS/2 鼠标、PS/2 键盘三种事件源在顶层合并成同一种格式
|
||||
(±8 = 一格),键鼠用 SW15 切换(见上文“操作”)。
|
||||
- **文字显示**:显存每格 2 字节(字形[5:0] + 颜色[2:0]),RTL 内置 A-Z 和数字/游戏
|
||||
符号字模,开始界面显示 `MINES`、`EASY`、`NORMAL`、`HARD`、`START`。注意**字符颜色
|
||||
不能取黑色**(黑字画在黑背景上等于看不见)。
|
||||
- 回归覆盖:`run_regress.ps1` 里还没有扫雷的自动测试项(PS/2 接收器有单独的
|
||||
`tb_ps2_mouse` / `tb_ps2_kbd`);也还没有“自动玩一局 + 显存 dump + PNG 比对”的
|
||||
一键回归。
|
||||
|
||||
Reference in New Issue
Block a user