名称:乒乓球游戏机 FPGA 设计 Verilog Vivado
软件:Vivado
语言:Verilog
功能介绍
本设计实现了一套基于 FPGA 的乒乓球游戏机,使用 Verilog HDL 在 Vivado 环境下完成逻辑设计。系统通过 LED 的依次点亮模拟乒乓球在双方之间移动,玩家通过两个按键完成发球、击球等交互操作,适合用于 FPGA 课程设计、数字逻辑综合设计和电子信息类毕业设计参考。
游戏规则围绕 11 分制乒乓球比赛展开。甲乙双方分别通过按键进行操作,当“球”移动到有效击球位置时,接球方按键可完成回击;如果提前击球或没有及时击中,则由对方得分。比分通过数码管进行显示,任意一方达到 11 分后可判定胜出,同时设计中包含获胜提示信号,可用于蜂鸣器提示。
系统还支持复位重新开局,便于反复演示和调试。整体功能覆盖按键输入、消抖处理、游戏状态控制、LED 球路显示、比分统计、数码管动态显示和提示输出,逻辑层次清晰,适合作为学习 FPGA 状态机设计、外设驱动和交互式小游戏实现的完整工程。
运行环境
开发语言:Verilog
开发软件:Vivado
主要工程文件:pingpang_game.xpr
约束文件:pins.xdc
顶层模块:pingpang_game
主要输入输出包括 50MHz 时钟、低电平复位、两路玩家按键、蜂鸣器提示、8 位 LED、数码管段选和位选信号。
设计思路
设计以 FPGA 为核心控制单元,将乒乓球游戏拆分为按键输入处理、游戏规则控制、LED 运动显示和比分显示几个部分。按键部分先经过消抖处理,避免机械按键抖动造成误触发;消抖后的按键信号再送入游戏控制逻辑,用于判断玩家是否在正确时机完成击球。
游戏控制模块负责维护球的移动方向、当前位置、得分状态和胜负提示。LED 用于模拟球台上的球路,通过灯光按方向移动来表现乒乓球从一方运动到另一方的过程。当球越过中间区域后,对应玩家需要在规定时机按键回击;若按键时机不符合规则,则由对方计分。该方式将抽象的比赛过程转换为可观察的硬件状态,便于在开发板上直接演示。
比分显示部分采用数码管输出,将双方分数分别显示出来。游戏控制模块输出 score_1 和 score_2 两组比分数据,显示模块负责完成数码管位选和段选控制,使玩家能够实时观察当前比分。顶层模块负责完成各子模块之间的连接,包括时钟、复位、按键、LED、蜂鸣器和数码管接口。
整体设计思路偏向模块化实现,按键消抖、游戏控制和显示输出相互独立,既方便单独调试,也便于后续扩展。例如可根据需要调整球速、修改胜利分值、增加发球权显示或扩展更多提示输出。
模块结构
工程主要由以下模块组成:
1. pingpang_game:顶层模块,连接时钟、复位、按键、蜂鸣器、LED 和数码管接口,完成各功能模块例化。
2. key_debounce:按键消抖模块,对玩家按键输入进行稳定化处理,并输出有效按键边沿信号。
3. game_ctrl:游戏控制模块,负责乒乓球移动逻辑、击球判断、得分统计、LED 显示控制和获胜提示输出。
4. display_num:数码管显示模块,根据双方比分生成数码管段选和位选信号。
5. pingpang_game_vlg_tst:测试相关文件,可用于工程仿真或逻辑验证参考。
开发板验证
本设计包含 Vivado 管脚约束文件 pins.xdc,并配套开发板实物及上板验证图片,可用于参考实际 FPGA 开发板连接方式。工程已生成实现结果和 bit 文件,接口覆盖时钟、复位、按键、LED、数码管和蜂鸣器等外设信号,适合在具备相应外设资源的 FPGA 开发板上进行下载演示。
开发板验证重点包括两路玩家按键输入、LED 球路显示、数码管比分显示以及蜂鸣提示输出。通过按键操作可以观察 LED 模拟球的移动方向和击球反馈,比分变化可在数码管上显示,复位信号可用于重新开始一局游戏。
仿真图/仿真说明/设计文档图片
设计文档包含乒乓球游戏机的研究背景、功能要求、设计方案和模块说明,内容围绕 FPGA 乒乓球游戏机的 11 分制计分、LED 模拟球路、按键击球、提前或未击中扣分、复位重新开局等功能展开。
工程中包含 Vivado 项目文件、Verilog 源码、约束文件、综合与实现结果,可作为仿真、综合、实现和上板调试的参考。
部分代码
以下展示顶层模块 pingpang_game 的部分代码,完整源码请下载压缩包查看。
module pingpang_game(
input clk_in,//50MHz
input reset_n,//低电平复位
input button_1,//选手1 push low
input button_2,//选手2 push low
output beep,//获胜提示
output [7:0] led,//led,高电平亮 high light
output [7:0] lednum_select,//数码管段选
output [3:0] bit_select//数码管位选
);
wire button_posedge_1;
wire button_posedge_2;
//按键消抖模块
key_debounce i1_key_debounce(
. clk(clk_in),
. rst_p(1\'b0),
. button_in(button_1),//输入
. button_neg(button_posedge_1)//消抖后按键下降沿
);
//按键消抖模块
key_debounce i2_key_debounce(
. clk(clk_in),
. rst_p(1\'b0),
. button_in(button_2),//输入
. button_neg(button_posedge_2)//消抖后按键下降沿
);
wire [7:0] score_1;
wire [7:0] score_2;
//游戏控制模块
game_ctrl i_game_ctrl(
. clk_in(clk_in),
. reset_p(~reset_n),//复位
. led(led),//led,高电平亮 high light
. beep(beep),
. button_posedge_1(button_posedge_1),//消抖后按键下降沿
. button_posedge_2(button_posedge_2),//消抖后按键下降沿
. score_1(score_1),//分数1
. score_2(score_2)//分数2
);
//数码管显示模块
display_num i_display_num(
. clk(clk_in),
. score_1(score_1),//分数1
. score_2(score_2),//分数2
. bit_select(bit_select),//数码管位选
. lednum_select(lednum_select)//数码管段选
);
endmodule
140