硬核 FPGA:用 Verilog 搓一个贪吃蛇游戏
前言:软件工程师不懂的浪漫
对于软件工程师来说,写一个贪吃蛇也就是几百行 Python/C++ 的事情。
但对于硬件工程师来说,这意味着:
- 没有操作系统帮你管理内存。
- 没有显卡驱动帮你画图,每一个像素点的 RGB 信号都要你亲自控制。
- 没有 CPU 帮你顺序执行指令,所有的逻辑都是并行发生的。
今天,我们要用 Verilog HDL (Hardware Description Language) 在一块普通的 Cyclone IV FPGA 开发板上,实现经典的贪吃蛇游戏,并通过 VGA 接口显示在显示器上。
这将是一场关于时序、状态机和逻辑门电路的硬核探险。
1. VGA 显示原理:电子束的独舞
要显示图像,首先得搞定 VGA 时序。
VGA 标准(这里以 640x480 @ 60Hz 为例)要求我们控制两个核心信号:
- HSYNC (行同步): 告诉显示器换行了。
- VSYNC (场同步): 告诉显示器这一帧画完了,回到左上角。
根据标准,我们需要一个 25.175 MHz 的像素时钟。
1 | |
看,硬件就是这么直接,你是在用计数器直接去控制显示器的电子枪!
2. 游戏核心逻辑:有限状态机 (FSM)
贪吃蛇的逻辑本质上是一个状态机。
stateDiagram-v2
[*] --> IDLE
IDLE --> PLAY: Start Button
PLAY --> DIE: Hit Wall/Body
DIE --> IDLE: Retry Button
state PLAY {
axis_x: Update Snake Position
axis_y: Check Collision
axis_z: Render Apple
}
蛇身的存储
蛇身怎么存?在 CPU 上我们会用 LinkedList。但在 FPGA 上,动态内存分配是不存在的。
我们通常用 Register Array (寄存器数组)。
1 | |
移动逻辑
蛇的移动,其实就是:
- 第
i节的位置变成第i-1节的位置(从尾巴开始循环)。 - 蛇头(第 0 节)根据当前方向(上/下/左/右)更新坐标。
这在软件里是一个 for 循环。但在 Verilog 里,这是一个并在的赋值,在一个时钟周期内完成!
1 | |
注意:这里不能直接用 VGA 的像素时钟 (25MHz),蛇跑得太快了人眼看不见。我们需要一个分频后的 logic_clk,比如 5Hz(每秒走 5 格)。
3. 图像渲染:即时合成
FPGA 没有显存(或者说片上 Block RAM 很贵,存不下一整帧 640x480 的图)。
所以我们通常采用 即时合成 (Just-In-Time Rendering) 的策略。
VGA 驱动告诉你当前扫描到 (pixel_x, pixel_y) 了,你就在下一刻告诉它这个点是什么颜色。
1 | |
这种方式不需要 Frame Buffer,极其节省内存,但对逻辑延迟要求很高。如果判断逻辑太复杂,赶不上像素时钟,画面就会抖动。
4. 总结:并行思维的力量
写完这个 FPGA 贪吃蛇,你最大的感触会是思维方式的转变。
在 CPU 上,我们思考的是步骤:先做A,再做B。
在 FPGA 上,我们思考的是时空:在时钟上升沿到来那一瞬间,所有信号同时改变。
FPGA 让我们可以用积木搭建起属于自己的简易计算架构。虽然用来写贪吃蛇有点杀鸡用牛刀,但同样的逻辑,改一改就能用来做 高频交易系统的行情解析 或者 AI 推理的矩阵由速器。这就是硬件的魅力。
下一篇,我们将深入计算机体系结构,去探究 CPU 内部是如何通过乱序执行来榨干每一滴性能的。