CHIP-8FPGAon GoWin MinistarBoard背景
作为开发爱好者,硬件体系本身并不是本人专长,之前偶尔购得同样是GoWin FPGA芯片的tang nano开发板,也浅尝点灯成功为止,这次有幸参与Gowin星核计划开发者竞赛,希望能在FPGA的应用领域掌握更多的知识,给自己更大的挑战,这次计划将CHIP8完成FPGA的实现。
对比同样小巧的tang nano开发板,这次赛事举办方提供的ministar开发板上的芯片性能要强很多,
tang nano的开发板板载芯片为 GW1N-LV1QN48C6/I5,搭载了 1152 LUT4 的逻辑资源,1 PLL 和 4 Block 合计 72Kbit SRAM。而这次的ministar的开发板载芯片为 GW1NSR-LV4CQN48P 提供了 4608 LUT4的逻辑资源, 2 PLL以及180K的Block SRAM, 可用资源比nano要近四倍,这也对之前希望在FPGA上开发一款硬件模拟的8位怀旧电脑提供了很好的开发环境。
希望能够模拟的硬件平台是一款70年代的流行电脑,其开发环境名为CHIP8,它同时也是一种翻译性质的语言,由Joseph We***ecker发明,最早在1970年代的COSMA VIP和Telmac 1800 8位电脑上出现,也是最早的游戏开发语言。大家非常熟悉的Pong,SpaceInvader游戏也在该语言上开发过。
硬件平台
- ministar开发板
- 0.96寸OLED12864液晶屏I2C 驱动ssd1315
|
- 4x4矩阵键盘
系统设计
CHIP8作为一个虚拟机似的的语言系统,最早是直接实现在4KB的系统下,例如Cosmac VIP和Telmac1800。这些机器是具有4096(0x1000)的内存地址,8bit(1Byte)位宽。但CHIP8翻译器会占据开头的512Bytes地址空间,应用程序只能开始于512B(0x200)的内存地址处,且不能访问低于0x200的地址空间,而最高的地址空间的256Bytes(0xF00-0xFFF)则作为display的刷新,再向下的96Bytes(0xEA0-0xEFF)则作为调用栈等内部使用。
寄存器16个8位寄存器
名字为V0到VF, VF同时作为flag寄存器使用,例如在加法操作中,VF作为carry标记,在draw操作中,VF作为pixel collision标记。
地址寄存器I
地址寄存器I,位宽16bits, 在内存访问相关操作中使用。
栈
栈只作为保存调用的返回地址使用。
时钟
CHIP8具有两个时钟,都执行在60Hz上,递减至0
- 延迟时钟(Delaytimer): 用来触发特定游戏事件,值可以被读和写。
- 音频时钟(Sound timer): 只用来播放音频,当它的值非零时会播放beep声。
输入
4x4 16位键盘0至F, 其中8,4,6,2通常用于方向。有3条指令用于读取键盘输入,具体功能参考opcode table
显示
64x32像素单色显示,图像通过sprite的方式绘制到屏幕上,sprite是8像素宽,可以是1至16个像素高。当前绘制的sprite对屏幕已有的像素作一次XOR。如果这次操作对屏幕的像素进行了反转,那么VF寄存器保存1,反之0,这样可以检测当前绘制是否和屏幕已有像素产生碰撞。
声音
音频时钟非零时播放beep
指令表(Opcode Table)
CHIP8具有35个opcodes, 2Bytes长,按照Big-endian方式编码,格式说明如下:
- NNN: 地址
- KK: 8位常量
- K: 4位常量
- X和Y: 4位寄存器编号
- PC: 指令计数器
- I: 16位内存范围出寄存器
- VN: 16个已知值,可以是0至F 另外需要说明的是CHIP8指令至1978年以来有多种实现,下面的指令表里的是基于1991年的SUPER-CHIP规范里的。
标准码[td]
指令码 |
类型 |
汇编码 |
说明 |
00E0 |
显示 |
CLS |
清屏幕 |
00EE |
控制 |
RET |
从函数里返回 |
1NNN |
控制 |
JP addr |
跳转到地址 |
2NNN |
控制 |
CALL addr |
调用函数地址 |
3XKK |
条件 |
SE Vx, byte |
如果 Vx==KK, 跳过下条指令 |
4XKK |
条件 |
SNE Vx, byte |
如果 Vx != KK, 跳过下条指令 |
5XY0 |
条件 |
SE Vx, Vy |
如果 Vx == Vy, 跳过下条指令 |
6XKK |
常量 |
LD Vx, byte |
将Vx的值设为KK |
7XKK |
常量 |
ADD Vx, byte |
将Vx的值累加KK |
8XY0 |
设置 |
LD Vx, Vy |
将Vx的值设为Vy |
8XY1 |
位操作 |
OR Vx, Vy |
将Vx的值设为Vx or Vy (位或) |
8XY2 |
位操作 |
AND Vx, Vy |
将Vx的值设为Vx and Vy (位与) |
8XY3 |
位操作 |
XOR Vx, Vy |
将Vx的值设为Vx xor Vy (位异或) |
8XY4 |
算术 |
ADD Vx, Vy |
将Vx的值设为Vx+Vy, VF会设为1如果有carry |
8XY5 |
算术 |
SUB Vx, Vy |
将Vx的值设为Vx-Vy, VF会设为1如果有borrow |
8XY6 |
位操作 |
SHR Vx{,Vy} |
将Vx的最低位保存至VF, 然后Vx右移1位 |
8XY7 |
算术 |
SUBN Vx, Vy |
将Vx的值设为Vx-Vy, VF会设为0如果有borrow, 1反之 |
8XYE |
位操作 |
SHL Vx{,Vy} |
将Vx的最高位保存至VF, 然后Vx左移1位 |
9XY0 |
条件 |
SNE Vx, Vy |
如果 Vx!= Vy, 跳过下条指令 |
Annn |
内存 |
LD I, addr |
设置addr至内存寄存器I |
Bnnn |
控制 |
JP V0, addr |
跳转至V0+addr的地址执行 |
CXKK |
算术 |
RND Vx, byte |
将Vx设为rand() and byte值 |
DXYN |
显示 |
DRW Vx, Vy, nibble |
在Vx, Vy处绘制一个宽8像素,高N像素, 像素的bits从内存寄存器I中获得 |
EX9E |
输入 |
SKP Vx |
如果Vx中保存的keycode对应的按键被按住, 跳过下条指令 |
EXA1 |
输入 |
SKNP Vx |
如果Vx中保存的keycode对应的按键未被按住, 跳过下条指令 |
FX07 |
时钟 |
LD Vx, DT |
设置Vx的值为延迟时钟的值(Delay timer) |
FX0A |
输入 |
LD Vx, K |
等的K(keycode值)的按键按下,然后设到Vx寄存器里 |
FX15 |
时钟 |
LD DT, Vx |
设置延迟时钟的值为Vx |
FX18 |
音频 |
LD ST, Vx |
设置音频时钟的值为Vx |
FX1E |
内存 |
ADD I, Vx |
将Vx的值加入I, VF不受影响 |
FX29 |
内存 |
LD F, Vx |
设置I的值为字符Sprite地址,Vx存放字符index |
FX33 |
算术 |
LD B, Vx |
设置从Vx中转化的BCD编码的值至寄存器I所指向的内存地址, 最高位至入I, 其他3组分别至入I+1,I+2,I+3 |
FX55 |
内存 |
LD [I], Vx |
将V0至Vx寄存器里的值依次保存值内存地址I起始,但不修改I的值 |
FX65 |
内存 |
LD Vx, [I] |
将内存地址I里的值依次写回V0至Vx, 不修改I的值 |
扩展指令 (Super Chip-48)[td]
指令码 |
类型 |
汇编码 |
说明 |
00Cn |
显示 |
SCD nibble |
|
00FB |
显示 |
SCR |
|
00FC |
显示 |
SCL |
|
00FD |
|
EXIT |
|
00FE |
|
LOW |
|
00FF |
|
HIGH |
|
DXY0 |
显示 |
DRW Vx, Vy, 0 |
|
FX30 |
|
LD HF, Vx |
|
FX75 |
|
LD R, Vx |
|
FX85 |
|
LD Vx, R |
|
软件设计
模块框图
[td]
模块 |
功能 |
进度 |
TestBench |
chip8.v |
top模块,组合核心和外设 |
50% |
N/A |
clock.v |
从主clk拆出更低的clk给各个模块用 |
80% |
Ready |
cpu.v |
指令处理解码,内存和gpu控制 |
50% |
Ready |
gpu.v |
完成对显示内存的控制,提供DRW相关指令操作 |
80% |
Ready |
mem.v |
模拟4KB内存模块,提供读/写操作 |
100% |
Ready |
bcd.v |
BCD转换,提供BCD相关指令操作 |
100% |
Ready |
rand.v |
伪随机,提供rand相关指令 |
100% |
N/A |
oled.v |
OLED显示, 驱动spi给SSD1315的显示外设 |
10% |
Ready |
disp.v |
framebuffer至OLED显示 |
50% |
N/A |
key.v |
处理键盘访问指令 |
0% |
N/A |
工具使用OpenSourceFPGA toolchainGowinIDE硬件连接参考
项目链接:(持续更新) https://gitee.com/sammulk/chip8-ministar
|