CHIP-8 FPGA on 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 - 延迟时钟(Delay timer): 用来触发特定游戏事件,值可以被读和写。
- 音频时钟(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
|