资源描述
基于FPGA乒乓球游戏机Verilog设计 整理者:G佑咡 江西师范大学 电子信息工程前言:此类程序鉴于网上大多是VHDL设计,所以我整理一份Verilog设计供初学者参考,因为时间关系,程序没有优化,也没有注释,如有不妥的地方,请大家多提意见。摘 要:本文使用 FPGA 芯片来模拟实际的乒乓球游戏。本设计是基于 Altera 公司的FPGA Cyclone II 芯片 EP2C5T144C8 的基础上实现,运用 Verilog HDL 语言编程,在 Quartus II 软件上进行编译、仿真,最终在开发板上成功实现下载和调试。1 乒乓球游戏机系统组成乒乓球比赛游戏机的组成如图1 所示。比赛规则约定:五局三胜; 1 分一局; 裁判发出比赛开始信号,触发FPGA 内部随机数发生器模块产生首次发球权方;比赛进行中,选手连续两次获得发球权后, 发球权交予对方,如未获发球权方发球, 裁判端犯规音响电路鸣响;6 个LED 排列成行模拟乒乓球台(因为我的开发板上只有6个LED灯,比赛开始时候中间两个灯亮,如果有条件的话有10来个灯最好了); 点亮的LED 模拟乒乓球,受 FPGA 控制从左到右或从右到左移动; 比赛选手通过按钮输入模拟击球信号, 实现 LED 移位方向的控制; 若发亮的LED 运动在球台中点至对方终点之间时,对方未能及时按下击球按钮使其向相反方向移动, 即失去一分。2 功能模块设计图1 中,基于FPGA 设计的控制端为整个系统的核心,其内部主要由简易随机数发生器、 发球权控制器、 乒乓球位置控制器、 甲乙方计分控制器、 犯规音响控制器等模块组成。整个控制端采用模块化设计,先用 Verilog 语言编写功能模块,然后用顶层原理图将各功能模块连接起来。设计的难点在于协调各模块工作,严格遵守各信号间时序关系。本系统采用50MHz系统时钟。2. 1 简易随机数发生器比赛首次发球权由随机数发生器产生的数据决定,其随机性要求不严, 因此,采用非常简单的模式产生,即一旦FPGA 上电, 系统时钟百分频产生一方波信号square,当裁判闭合开始比赛开关产生 start 信号上升沿时,读取此时squar e信号值作为随机数发生器输出data_rand。模块仿真如图 2 所示, 结果满足设计要求。此模块设计时保证了 square 信号周期应远大于 start 信号上升沿建立时间, 保证随机数据的正确读取。2. 2 发球权控制器发球权控制器的控制过程为: 如果按下复位按钮,发球权数码管显示8, 否则, 开始比赛开关闭合时, 显示随机数发生器的值( 0 或 1, 0 代表甲方、 1 代表乙方) 。而在比赛中,为遵守发球权交换规则, 设计甲乙双方计分器总和信号sum是不为0 的偶数时(即计分总次低位变化时) , 发球权数码管显示由0变为1 或由1 变为0。此模块设计中, 发球权数码管的信号控制受多个时钟的控制,即开始比赛开关start 和计分值sum1信号,将两个信号组合成一个时钟信号, 并统一两个时钟的触发沿。因此最佳时钟触发方式如图3 所示的qq_en信号。为满足这种时序要求, 借助计分总和次低位 sum_1 信号和启动信号start设计qq_en信号。 图3 pp_en信号产生模块仿真pp_en信号产生模块如下:module pp_en(clk,start,sum_1,pp_en,cnt);input clk;input start; /裁判启动信号input sum_1; /总局数sum次低位sum1output pp_en;output4:0 cnt; /pp_en信号个数/-reg sum_1_a,sum_1_b;reg start_a,start_b; reg4:0 cnt_r;always (posedge clk)begin start_a = start; start_b = start_a; sum_1_a = sum_1; sum_1_b = sum_1_a;end/-always (posedge clk)begin if(pp_en) cnt_r = cnt_r+4b1; else cnt_r = cnt_r;end/-assign cnt = cnt_r;assign pp_en = (start_astart_b) | (sum_1_asum_1_b);endmodule根据pp_en信号和随机数data_rand控制甲乙球权模块:module pp_possession(clk,reset,data_rand,pp_en,cnt,led_pose);input clk;input reset;input data_rand;input pp_en;input4:0 cnt;output3:0 led_pose; /甲乙球权输出,0代表甲,1代表乙。/-reg3:0 led_pose_r;always (posedge clk or negedge reset)begin if(!reset) led_pose_r = 4d8; else if(pp_en) begin if(cnt = 5b1) led_pose_r = 3b0,data_rand; else led_pose_r = !led_pose_r; end else led_pose_r = led_pose_r;endassign led_pose = led_pose_r;endmodule2. 3 乒乓球位置控制、 甲乙计分、 犯规音响控制乒乓球位置控制电路为 FPGA 控制端的核心, 依据比赛规则,采用了Mealy 型状态机 10来实现,大大降低了设计难度。状态机共定义了7 个状态, 各状态定义如表1 所示,状态转换如图5 所示, 转换条件如表2 所示,具体程序如下。乒乓球游戏机核心控制模块:module led_con(clk_1s,reset,start,key_a,key_b,led_pose,sum,score_a,score_b,speaker,led);input clk_1s;input reset;input start;input key_a;input key_b;input led_pose;output4:0 sum;output3:0 score_a;output3:0 score_b;output5:0 led;output speaker;reg speaker;/-reg5:0 led_move;reg3:0 score_a_r;reg3:0 score_b_r;reg6:0 state;parameter6:0 s0 = 7b0000001, s1 = 7b0000010, s2 = 7b0000100, s3 = 7b0001000, s4 = 7b0010000, s5 = 7b0100000, s6 = 7b1000000;always (posedge clk_1s or negedge reset)begin if(!reset) state = s0; else if(!start) begincase(state)s0:begin speaker = 1; if(score_a_r = 4d11 | score_b_r = 4d11) beginscore_a_r = 4b0;score_b_r = 4b0; end else if(!led_pose) beginled_move = 6b011111;state = s1; end else if(led_pose) beginled_move = 6b111110;state = s4; endends1:begin if(!key_a)begin led_move = led_move0,led_move5:1; state = s2;end else if(!key_b) begin speaker = 0; state = s0; end else state = s1;ends2:begin if(led_move2 = 0 | led_move1 = 0 | led_move0 = 0) & !key_b)state = s6; else if(led_move2 = 0 | led_move1 = 0) & key_b) |(led_move5 = 0 | led_move4 = 0 | led_move3 = 0) state = s3; else begin score_a_r = score_a_r+1; state = s0; endends3:begin led_move = led_move0,led_move5:1; state = s2;ends4:begin if(!key_b)begin led_move = led_move4:0,led_move5; state = s5;end else if(!key_a) begin speaker = 0; state = s0; end else state = s4;ends5:begin if(led_move3 = 0 | led_move4 = 0 | led_move5 = 0) & !key_a)state = s3; else if(led_move3 = 0 | led_move4 = 0) & key_a) |(led_move0 = 0 | led_move1 = 0 | led_move2 = 0) state = s6; else begin score_b_r = score_b_r+1; state = s0;endends6:begin led_move = led_move4:0,led_move5; state = s5;enddefault:state = s0;endcase end else begin led_move = 6b110011; speaker = 1; endendassign score_a = score_a_r;assign score_b = score_b_r;assign led = led_move;assign sum = score_a_r+score_b_r;endmodule 基于 FPGA乒乓球比赛游戏机顶层原理图 后记:因为时间关系,资料没有整理的很理顺,请大家谅解,整个工程会给出,在板子上已调试成功,因为乒乓球位置控制模块所用的时钟为clk_1000ms,所以按键停留最好超过1s就能更稳的接住球。程序有点乱,没有优化,仅供参考!
展开阅读全文