数字电路与逻辑设计简易乒乓游戏机Word下载.docx
《数字电路与逻辑设计简易乒乓游戏机Word下载.docx》由会员分享,可在线阅读,更多相关《数字电路与逻辑设计简易乒乓游戏机Word下载.docx(33页珍藏版)》请在冰点文库上搜索。
![数字电路与逻辑设计简易乒乓游戏机Word下载.docx](https://file1.bingdoc.com/fileroot1/2023-5/5/0109378b-0d04-42a8-82d7-368e03d79ea8/0109378b-0d04-42a8-82d7-368e03d79ea81.gif)
当有RESET时,对系统进行复位,即当前的分数,熄灭正在运动的球,否则进入游戏。
WAITING:
对一些结果的初始化等操作,由TURN变量控制发球权,当A有按键输入,进入STARTA状态,当B有按键输入,进入STARTB状态。
STARTA:
靠近A的第一个球亮,并进入MOVEB状态。
MOVEB:
球向B移动,当球移动到靠近B的第二个球,如果B有按键输入,则进入MOVEA状态,否则,如果B提前按键,或者球移出球台了,B还没有按键的话,进入SCOREA状态。
STARTB:
靠近B的第一个球亮,并进入MOVEA状态。
MOVEA:
球向A移动,当球移动到靠近A的第二个球,如果A有按键输入,则进入MOVEB状态,否则,如果A提前按键,或者球移出球台了,A还没有按键的话,进入SCOREB状态。
SCOREA:
暂存胜出的变量INCA置1,进入JUDGE状态
SCOREB:
暂存胜出的变量INCB置1,进入JUDGE状态
JUDGE:
如果A或者B的当前分数为11,则相应的大比分加1,并进入GAMEOVER状态,否则,进入游戏的开始等待状态,进入下一轮比赛。
GAMEOVER:
如果A或者B大比分有一个为2,则A或者B的胜利状态的变量置1,让点阵显示,哪一方胜利,并让蜂鸣器响,游戏结束。
否则游戏继续进入,进入下一轮开始状态。
2分频模块:
数码管显示的时钟频率CLK_DISP频率是固定的,500Hz。
而状态转移的时钟频率CLK_GAME由拔码开关决定,当没有拔码开关输入时,频率为1HZ,当QUICK输入有效时,频率为0.5HZ,当QUICKER输入有效时,频率为0.25HZ。
3计分模块:
如果状态机中INCA或者INCB有效时,AGET与BGET累加,输出到数码管显示。
4显示模块:
将当局分数和已赢局数都显示在数码管上。
5点阵显示模块:
当游戏进行时,以CLK_GAME的频率在上面显示“乒”“乓”“加”“油”和一个笑脸。
当游戏结束时,在上面显“左”,“右”,表示哪方胜利。
6总函数:
将各个小模块用信号连接起来。
五,仿真波形
分频器的仿真
说明:
实际中原始频率250MHZ太大,不好仿真,上图为调整频率和分频系数后的仿真。
1在实际的系统中,CLK_DISP是数码管显示的时钟频率,应该在300HZ以上。
它的分频系数是固定的。
上图中它是2分频。
2CLK_GAME是球移动,计分,点阵显示的频率,它的分频系数不是固定的,由QUICK,QUICKER决定。
上图中,当QUICKER=1时,是4分频,球移动的速度最快,当QUICK=1时,是6分频,球移动的速度居中,当QUICKER=0且QUICK=0时,是8分频,球移动的速度最慢。
计分器的仿真
当INCA,INCB(当局比赛结束)有效时,AGET,BGET(累积分数直到11分)开始计分,当CLEAR来到时,AGET,BGET都清零。
状态仿真
当A发球,球向B移动,到达BALL[6]时,B击球,球向A移动,到BALL[1]时,A反击,当球到达BALL[7]时,B没有接住,A加1分。
INCA=1。
当A发球,球向B移动,到达BALL[6]时,B击球,球向A移动,到BALL[1]时,A反击,还没有到达BALL[6],B提前击球,A赢,A加1分。
A发球,B击球,RESET复位,球灭,然后A发球,B没有击球,A加分,INCA=1;
数码管显示仿真
数码管从右到左依次显示B当局的分数,A当局的分数,B胜的次数,A胜的次数。
所以当数码管点亮时,从右到左依次显示5,0,1,1,2,1。
程序中对显示的设置如下:
WHEN0=>
DISP_SCORE<
="
0111111"
;
WHEN1=>
0000110"
WHEN2=>
1011011"
WHEN5=>
1101101"
点阵显示仿真
当PLEASURE为0,1,2,3,4,或者AWIN,BWIN为1时,COL列选扫描,ROW点要显示的点。
六,源程序
状态机模块
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYTTIS
PORT(CLK_GAME:
INSTD_LOGIC;
RESET:
KA:
KB:
AGET:
ININTEGERRANGE0TO11;
BGET:
A_GAME:
BUFFERINTEGERRANGE0TO2;
B_GAME:
VICTOR:
OUTSTD_LOGIC;
AWIN:
BWIN:
CLEAR:
INCA:
INCB:
MYAH:
BUFFERINTEGERRANGE0TO4;
BALL:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));
ENDENTITY;
ARCHITECTUREBOFTTIS
TYPEALL_STATEIS(WAITING,STARTA,STARTB,MOVEA,MOVEB,SCOREA,SCOREB,JUDGE,GAMEOVER);
SIGNALCURRENT_STATE:
ALL_STATE;
SIGNALSR:
INTEGERRANGE0TO8;
SIGNALTURN:
STD_LOGIC;
BEGIN
P1:
PROCESS(RESET,CLK_GAME,CURRENT_STATE)
BEGIN
IFRESET='
1'
THEN--当RESET有效时,当--前的分数,胜败的状态都清零,CLEAR有效
CLEAR<
='
AWIN<
0'
BWIN<
SR<
=0;
VICTOR<
CURRENT_STATE<
=WAITING;
TURN<
A_GAME<
B_GAME<
MYAH<
ELSIFCLK_GAME'
EVENTANDCLK_GAME='
THEN
CASECURRENT_STATEIS
WHENWAITING=>
--等待状态时,CLEAR无效,MYAH是点阵显示的--状态转移信号,让它从0到4之间依次变化
INCA<
INCB<
BWIN<
IFMYAH=4THENMYAH<
ELSEMYAH<
=MYAH+1;
ENDIF;
IFTURN='
THEN--TURN是控制发球权的变量
IF(KA='
ANDKB='
)THEN
CURRENT_STATE<
=STARTA;
TURN<
--当A有按键输入时,进入STARTA状态,
--同时,TURN变化,从而下一次发球由B发球
ELSE
--如果A没有按键输入,则继续等待
ELSE
IF(KA='
)THEN
=STARTB;
turn<
--当B有按键输入时,进入STARTB状态,同时,
--TURN变化,从而下一次发球由A发球
ELSE
current_STATE<
--如果B没有按键输入,则继续等待
WHENSTARTA=>
SR<
=1;
=MOVEB;
--A发完球后,球向B移动
WHENSTARTB=>
=8;
=MOVEA;
--B发完球后,球向A移动
WHENMOVEB=>
=SR+1;
IF(KB='
ANDSR=7)THENCURRENT_STATE<
--若在规定的地点,靠近B的第二个球,
--B有击球,则进入球向A移动状态
ELSIF(KB='
ANDSR/=7)THENCURRENT_STATE<
=SCOREA;
--若不在规定的地点,靠近B的第二个,
--B有击球,则进入A加分状态
ANDSR=8)THENCURRENT_STATE<
--若不在规定的地点,靠近B的第二个球之--后,B还没有击球,也进入A加分状态
ELSECURRENT_STATE<
--若B没有击球,球也没有到靠近B的第二个球--之后,则球继续向B移动
WHENMOVEA=>
=SR-1;
ANDSR=2)THENCURRENT_STATE<
--若在规定的地点,靠近A的第二个球,A
--有击球,则进入球向B移动状态
ELSIF(KA='
ANDSR/=2)THENCURRENT_STATE<
=SCOREB;
--若不在规定的地点,靠近A的第二个球之前,--A有击球,则进入B加分状态
ANDSR=1)THENCURRENT_STATE<
--若不在规定的地点,靠近A的第二个球--后,A还没有击球,也进入B加分状态
--若B没有击球,球也没有到靠近A的第二--个球之后,则球继续向A移动
WHENSCOREA=>
INCA<
=JUDGE;
--A胜一局,A加一分
WHENSCOREB=>
--B胜一局,A加一分
WHENJUDGE=>
--A或B加完一分后一定要记得复位,否则会一次记两分
IF(AGET=11)THENCLEAR<
A_GAME<
=A_GAME+1;
=GAMEOVER;
--A若满11,则A胜一局
ELSIF(BGET=11)THENCLEAR<
=B_GAME+1;
--B若满11,则A胜一局
WHENGAMEOVER=>
IFA_GAME=2THENAWIN<
VICTOR<
--若A或B胜两局,则游戏结束
ELSIFB_GAME=2THENBWIN<
ENDCASE;
ENDPROCESSP1;
P2:
PROCESS(CLK_GAME,SR)--球移动时,LED的显示,1表示点亮
IFCLK_GAME'
THEN
CASESRIS
BALL<
00000001"
00000010"
WHEN3=>
00000100"
WHEN4=>
00001000"
00010000"
WHEN6=>
00100000"
WHEN7=>
01000000"
WHEN8=>
10000000"
WHENOTHERS=>
00000000"
ENDIF;
ENDPROCESSP2;
ENDB;
分频模块
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
ENTITYFREQIS
PORT(CLK:
CLK_DISP:
CLK_GAME:
QUICKER:
QUICK:
INSTD_LOGIC
);
ENDFREQ;
ARCHITECTUREAOFFREQIS
SIGNALTMP_GAME:
INTEGERRANGE0TO25000000;
SIGNALTMP_DISP:
INTEGERRANGE0TO100000;
PROCESS(CLK)
ifCLK'
eventandCLK='
then------clk的上升沿到来时
IF(QUICKER='
)THEN
--若有按键QUICKER,则分频后频率为8HZ,控制速度最快
ifTMP_GAME<
6250000then
TMP_GAME<
=TMP_GAME+1;
------计数器未满时加1
else
------否则计数器重新计数
endif;
=3125000then--使其占空比为50%
CLK_GAME<
ELSIF(QUICK='
--若有按键QUICK,则分频后频率为4HZ,控制速度居中
12500000then
=6250000then--使其占空比为50%
25000000then
--若没有按键,则分频后频率为2HZ,控制速度最慢
=12500000then
--下面以同样的方法给数码管显示分频,分频后为500HZ。
ifTMP_DISP<
100000then
TMP_DISP<
=TMP_DISP+1;
=50000then
CLK_DISP<
ENDPROCESS;
ENDA;
计分模块
ENTITYCOUNTIS
PORT(CLK_GAME:
OUTINTEGERRANGE0TO11;
OUTINTEGERRANGE0TO11);
ARCHITECTURECOFCOUNTIS
SIGNALSA,SB:
INTEGERRANGE0TO11;
--设置此类型变量是为了能对分数进入IF语句里判断
PROCESS(CLK_GAME,CLEAR,INCA,INCB)
IF(CLEAR='
SA<
SB<
THEN
--时钟频率上升沿到来时击球,下降沿到来时开始计分
IF(INCA='
IF(SA=11)THEN
SA<
--若A到11分了,则清零,进入下一轮比赛
=SA+1;
--若A有胜一局,则累记一分
ELSIF(INCB='
)THEN
IF(SB=11)THEN
SB<
--若B到11分了,则清零,进入下一轮比赛
=SB+1;
--若B有胜一局,则累记一分
ENDIF;
AGET<
=SA;
--把累加后的值赋值给OUT类型输出信号
BGET<
=SB;
ENDC;
点阵显示模块
entitySHOWis
port(clk_scan:
instd_logic;
--扫描频率500hz
awin:
bwin:
--myah:
pleasure:
ININTEGERRANGE0TO4;
col:
outstd_logic_vector(7downto0);
--列选
row:
outstd_logic_vector(7downto0)--行选
end;
architectureoneofSHOWis
signalflag:
inintergerrange0to7;
begin
process(clk_scan,awin,bwin)
ifclk_scan'
eventandclk_scan='
then--时钟下降沿输出字符
ifawin='
then
--显示“左”,在实验室做时是倒着看的,所以在这里倒着写,在板子就可以正着看了
caseflagis
when0=>
row<
col<
11111110"
flag<
when1=>
11111100"
11111101"
=2;
when2=>
00100001"
11111011"
=3;
when3=>
01110010"
11110111"
=4;
when4=>
11101111"
=5;
when5=>
11111111"
11011111"
=6;
when6=>
10111111"
=7;
when7=>
01111111"
endcase;
elsifbwin='
then--同样,显示“右”字,表示B方获胜
01111100"
=