FPGA上的CHIP-8游戏机模拟器

这是一个在FPGA芯片(具体为TinyFPGA BX)上运行的CHIP-8游戏机模拟器

实现注释与思考

编写单元测试(见cpu,gpu,bcd)对我的帮助极大,使我能够对大部分指令进行仿真测试。我还编写了一些简单的汇编程序,并使用Tortilla-8项目将其编译为CHIP-8格式。

为了使屏幕和键盘功能正常工作,还需要一些手动测试。我为芯片编写了简单程序运行,并修正了对CHIP-8行为的一些误解(例如,内存读写涉及多个寄存器,以及图形绘制可以环绕边界)。在这个过程中,我也修正了我的Rust语言编写的CHIP-8模拟器,有趣的是,尽管之前的理解有误,它仍能运行许多游戏。

CHIP-8规范包括16个一字节寄存器(V0到VF)和20个两字节栈空间。最初我想让它们成为独立数组,但很难协调访问以实现为RAM合成,因此我决定将它们映射到内存中(参见[cpu.v]顶部描述的内存映射)。

屏幕内容也被映射到了系统内存中,这意味着CPU和屏幕模块需要竞争内存访问。我决定,在读取屏幕内容时暂停CPU(即不执行下一条指令)。

处理屏幕显示是令人烦恼的,我按行存储帧数据(每个字节代表8像素的水平条),而我使用的屏幕期待的是8像素的垂直条,因此需要额外逻辑来旋转这些数据。

BCD指令(将字节转换为三个十进制数字)在电路中实现较为困难,因为它涉及到除以10的操作。我采用了Hacker's Delight一书中描述的方法,该方法涉及位移操作和手动调整。详细可见[bcd.v]。

向内存加载游戏很有趣。IceStorm工具提供了icebram实用程序,可以在已准备好的比特流中替换内存内容,这样就不必每次想玩不同的游戏时都重复整个漫长的(约30秒)构建过程。

TinyFPGA BX的默认时钟速度为16MHz,这对CHIP-8游戏来说太快了。所以我将整体速度限制为每秒500条指令。

我还添加了一个“调试模式”,同时按下1和F键激活。这时,我会渲染寄存器、堆栈和部分程序内存而不是屏幕缓冲区,观看其运作十分有趣。

随机数生成使用了Xorshift算法,每一周期计算一次新值,若检测到按键则迭代计算两次,确保结果受用户输入影响。

最后,由于我是Verilog的新手,项目在某些方面显得笨拙:

  • 单条指令大约需20个周期。
  • 内存访问遵循“读-确认”循环,其间有一个不必要的单周期暂停。
  • iCE40内存是双端口的,理论上可同时读写,但我并未利用这一点。
  • 整个项目占用1600多个LUT,我相信可以优化至少于1000个LUT,以便能适应更小的iCEstick。

硬件配置

我使用了以下硬件:

  • TinyFPGA BX,搭载Lattice iCE40-LP8K芯片
  • SparkFun的16按钮键盘
  • WaveShare的128x64像素单色OLED屏幕

源码概述

Verilog模块:

  • chip8.v —— 专为TinyFPGA BX设计的顶层模块
  • cpu.v —— 包含内存控制器的CPU
  • mem.v —— 系统内存
  • gpu.v —— 图形精灵绘制
  • bcd.v —— BCD转换电路
  • rng.v —— 虚拟随机数生成器
  • screen_bridge.v —— OLED屏幕与CPU之间的桥接,以访问帧缓冲区

测试文件:

  • *_tb.v —— 模块的测试平台(见下方如何运行)
  • asm/ —— 各种汇编程序
相关文件下载地址
*该资源需回复评论后下载,马上去发表评论?
©下载资源版权归作者所有;本站所有资源均来源于网络,仅供学习使用,请支持正版!
本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/8958.html

"愿我的文字能带给您一丝美好"

还没有人赞赏,支持一下

评论

A 为本文作者,G 为游客总数:0
加载中…

提交评论

游客,您好,欢迎参与讨论。

我的购物车

购物车为空

优惠券

没有优惠券