基于FPGA乒乓球游戏机Verilog设计

更新时间:2023-05-15 04:17:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于FPGA乒乓球游戏机Verilog设计

基于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 语言编写功能模块,然后用顶层原理图将各功能模块连接起来。设计的难点在于协调各模块工作,严格遵守各信号间时序关系。本系统采用

基于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 和计分值sum[1]信号,将两个信号组合成一个时钟信号, 并统一两个时钟的触发沿。因此最佳时钟触发方式如图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次低位sum[1]

output pp_en;

output[4:0] cnt; //pp_en信号个数

//----------------------------------------------------

reg sum_1_a,sum_1_b;

基于FPGA乒乓球游戏机Verilog设计

reg start_a,start_b;

reg[4: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+4'b1;

else

cnt_r <= cnt_r;

end

//----------------------------------------------------

assign cnt = cnt_r;

assign pp_en = (start_a^start_b) | (sum_1_a^sum_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;

input[4:0] cnt;

output[3:0] led_pose; //甲乙球权输出,0代表甲,1代表乙。

//---------------------------------------------------

reg[3:0] led_pose_r;

always @(posedge clk or negedge reset)

begin

if(!reset)

led_pose_r <= 4'd8;

else

if(pp_en)

begin

if(cnt == 5'b1)

led_pose_r <= {3'b0,data_rand};

else

基于FPGA乒乓球游戏机Verilog设计

led_pose_r <= !led_pose_r;

end

else

led_pose_r <= led_pose_r;

end

assign led_pose = led_pose_r;

endmodule

2. 3 乒乓球位置控制、 甲乙计分、 犯规音响控制乒乓球位置控制电路为 FPGA 控制端的核心, 依据比赛规则,采用了Mealy 型状态机[ 10]来实现,大大降低了设计难度。状态机共定义了7 个状态, 各状态定义如表1 所示,状态转换如图5 所示, 转换条件如表2 所示,具体程序如下。

基于FPGA乒乓球游戏机Verilog设计

基于FPGA乒乓球游戏机Verilog设计

乒乓球游戏机核心控制模块:

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;

output[4:0] sum;

output[3:0] score_a;

output[3:0] score_b;

output[5:0] led;

output speaker;

reg speaker;

//--------------------------------------------------------------

reg[5:0] led_move;

reg[3:0] score_a_r;

reg[3:0] score_b_r;

reg[6:0] state;

parameter[6:0] s0 = 7'b0000001,

s1 = 7'b0000010,

s2 = 7'b0000100,

s3 = 7'b0001000,

s4 = 7'b0010000,

s5 = 7'b0100000,

s6 = 7'b1000000;

always @(posedge clk_1s or negedge reset)

begin

if(!reset)

state <= s0;

else

if(!start)

基于FPGA乒乓球游戏机Verilog设计

begin

case(state)

s0:

begin

speaker <= 1;

if(score_a_r == 4'd11 || score_b_r == 4'd11)

begin

score_a_r <= 4'b0;

score_b_r <= 4'b0;

end

else if(!led_pose)

begin

led_move <= 6'b011111;

state <= s1;

end

else if(led_pose)

begin

led_move <= 6'b111110;

state <= s4;

end

end

s1:

begin

if(!key_a)

begin

led_move <= {led_move[0],led_move[5:1]};

state <= s2;

end

else if(!key_b)

begin

speaker <= 0;

state <= s0;

end

else state <= s1;

end

s2:

begin

if((led_move[2] == 0 || led_move[1] == 0 || led_move[0] == 0) && !key_b) state <= s6;

else if(((led_move[2] == 0 || led_move[1] == 0) && key_b) ||(led_move[5] == 0 || led_move[4] == 0 || led_move[3] == 0))

state <= s3;

else begin

score_a_r <= score_a_r+1;

基于FPGA乒乓球游戏机Verilog设计

s3: s4: state <= s0; end end begin led_move <= {led_move[0],led_move[5:1]}; state <= s2; end

begin

if(!key_b)

begin

led_move <= {led_move[4:0],led_move[5]};

state <= s5;

end

else if(!key_a)

begin

speaker <= 0;

state <= s0;

end

else state <= s4;

end

s5:

begin

if((led_move[3] == 0 || led_move[4] == 0 || led_move[5] == 0) && !key_a) state <= s3;

else if(((led_move[3] == 0 || led_move[4] == 0) && key_a) ||(led_move[0] == 0 || led_move[1] == 0 || led_move[2] == 0))

state <= s6;

else begin

score_b_r <= score_b_r+1;

state <= s0;

end

end

s6:

begin

led_move <= {led_move[4:0],led_move[5]};

state <= s5;

end

default:state <= s0;

endcase

end

else

begin

基于FPGA乒乓球游戏机Verilog设计

led_move <= 6'b110011;

speaker <= 1;

end

end

assign 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就能更稳的接住球。程序有点乱,没有优化,仅供参考!!

本文来源:https://www.bwwdw.com/article/473e.html

Top