数电实验报告乒乓球游戏机.docx
《数电实验报告乒乓球游戏机.docx》由会员分享,可在线阅读,更多相关《数电实验报告乒乓球游戏机.docx(28页珍藏版)》请在冰豆网上搜索。
数电实验报告乒乓球游戏机
数字系统与逻辑设计综合实验
——10秒倒计时+简易乒乓球游戏机
设计课题的任务要求
课题任务:
1.设计实现一个10秒倒计时电路,使用8×8点阵显示计时结果。
2.自拟功能:
简易乒乓球游戏机,倒计时至0后开始执行该功能。
两人乒乓游戏机是以8个发光二极管代表乒乓球台,中间两个发光管兼作球网,用发光管按一定的方向依次闪亮来表示球的运动。
在游戏机两侧各设一个发球/击球开关,当甲方发球时,靠近甲方的第一个发光管亮,然后依次点亮第二个……球向乙方移动,球过网后到达设计者的规定的球位乙方即可击球,若乙方提前击球或未击到球,则甲方得分。
然后重新发球进行比赛,直到某一方记分达到规定分,比赛结束。
1.以8个发光二极管代表乒乓球台,中间两个是球网,乒乓球的位置和移动方向由灯亮及依次点亮的方向决定;
2.球移动的速度0.5s;
3.用4个数码管分别显示双方的得分;
4.发3个球后换发球,最边上的发光二极管亮表示发球方;
5.设置复位键,按下后比分清零,重新10秒倒计时,双方重新开始比赛;
6.当某一方比分达到11分时,比赛结束。
设计思路及总体框图
总体电路外部框图:
总体电路外部接口说明:
框图中左边部分为输入信号,右边为输出信号。
输入信号中,clk为全局时钟信号,由实验板的晶振产生,频率为1MHz;h1、h2为双方的发球、击球按键,分别锁定到实验板的BTN4及BTN1上;reset为全局复位,当reset为高电平时,比分全部清零,重新倒计时,然后比赛重新开始,reset锁定到BTN2上。
输出信号中,row[7..0]为点阵行选择信号,col[7..0]为列选择信号,table[7..0]控制7个发光二极管(表示球的移动)、catch[3..0]为数码管选通信号,score[6..0]控制七段数码管(用来显示比分)。
总体框图:
各模块间电路连接图:
(详见电子版)
设计思路:
1.考虑到系统的功能比较多且复杂,故采用分块设计的方式,先设计好底层各模块,再到顶层进行综合。
根据功能,将系统分为六个底层模块:
分频模块,将高频时钟(1Mhz)分频,输出两个低频时钟clk1(2hz)和clk2(1hz),供倒计时模块和乒乓球控制模块使用;
10秒倒计时模块,从9秒开始倒计时,一直到0,利用逐列扫描的方式,对行像素分别编码,利用人眼视觉暂留效应,以1MHZ的频率扫描列,点阵上就会出现稳定的数字。
若按下”reset”后,重新开始计时,然后开始兵乓球游戏。
当计时结束后输出一个控制信号,点阵熄灭,开始兵乓球游戏;
兵乓球控制模块,完成控制球的移动、判断击球、复位、计分等功能,其中包括两个译码显示模块,实现在七段数码管上显示双方的比分;
数码管扫描显示控制模块,实现4个数码管动态扫描显示功能。
分块电路设计
分频器模块
分频器模块由高频时钟输入和两个低频时钟输出组成,输出时钟clk1(2hz)在乒乓球模块中控制球的移动,clk2(1hz)在倒计时模块中控制计数器的变化。
倒计时模块
用变量count记录输入时钟(1hz)的个数,每来一个时钟,修改一次变量count的值,用count控制8x8点阵显示的数字,从而实现10秒倒计时。
当计时结束后,把sw信号置高,点阵熄灭,开始兵乓球游戏。
并且设有复位键”reset”,按下后比分清零,重新开始计时,然后开始兵乓球游戏。
计时流程图如下:
比如数字6的点阵行编码为:
casetmp3is
when2=>r<="11111110";
when5=>r<="10011110";
when3|4=>r<="10010010";
whenothers=>r<="00000000";
endcase;
乒乓球控制模块
主控模块主要控制击球和状态的转移,模块的接口主要有时钟、倒计时结束信号、双方击球信号,球台显示及计分部分,同时将双方比分送至译码显示模块,将其译成数码管的显示信号。
总体的设计思路及状态转移图如下:
流程图:
状态转移图:
在这个模块中,采用了状态机,共设七个状态,分别为waitfor、begin1、begin2、to1、to2、allow1、allow2,这七个状态所代表的含义及相关状态转移时的设计思路如下:
●waitfor状态:
等待开始状态,当一局比赛结束时便处于这个状态,此状态下根据发球权信号(当发球计数器计数到3,则交换发球)决定转移到begin1或begin2状态,并且点亮靠近发球方的发光二极管。
●begin1/begin2:
准备发球状态,等待具有发球权一方按下发球/击球键,发球后若对方立即击球,则一球结束,进行加分,并转移到waitfor状态;否则,转移到to2/to1状态。
●to2/to1:
球从一方向另一方移动,发光二极管以0.5秒的速度依次点亮,此状态下若对方击球,则一球结束,进行加分,发球计数器加1,并转移到waitfor状态;否则,当靠近接球方的第2个灯点亮时转移到allow1或allow2状态。
allow1/allow2:
等待接球方击球,若接球方按下击球按,转移到球向相反方向移动的状态to2/to1。
否则,一球结束,进行加分,发球计数器加1,并转移到waitfor状态。
数码管扫描控制模块
利用人眼视觉暂留效应,让一个高频时钟(1Mhz)对4个七段数码管不断进行选通扫描,使其稳定的显示双方的比分
仿真波形
1.倒计时电路的仿真:
由于实际clk1为1Mhz,clk2为1hz,不易仿真。
以下的仿真假设高频时钟clk1周期为0.5us,用来控制列扫描信号,低频时钟clk2周期为16us,每来一个clk2改变一次显示的数字。
从9开始倒计时,点阵列管脚从高到低进行扫描,依次赋值为低电平。
同时对该列的行管脚进行编码赋值,以较高的频率进行重复扫描,便可以稳定显示相应的数字。
从以上的仿真波形中,可以比较明显的看出显示的数字。
若按下复位键”st”,则重新开始计时。
倒计时到0后,点阵熄灭,sw被置高,控制乒乓球游戏开始。
2.乒乓球控制模块仿真
波形1:
clkp为分频后的低频时钟,sA发球后,控制球移动的二极管依次被点亮,当靠近sB的最后一个灯点亮时,sB成功击球,之后球向sA移动,sA没有击球,球出界,sB得分。
波形2:
sB成功击球后,球向sA移动,当靠近sA的最后一个灯点亮时,sA击球,球向sB移动,之后sB提前击球,sA得分。
波形3:
若按下复位键,则sw被清零,比分也被清零。
直到倒计时结束,sw被置高,乒乓球游戏重新开始。
源程序
分频器模块:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_arith.all;
entitydivideis
port(
clk0:
instd_logic;--clk0为1MHz高频时钟输入
clk1,clk2:
outstd_logic--clk1为2Hz时钟输出,clk2为1Hz时钟输出
);
enddivide;
architectureaofdivideis
signalclk_b:
std_logic;--产生2hz信号的中间信号
signaltmp:
std_logic;--产生1hz信号的中间信号
begin
p1:
process(clk0)--500000分频,产生2hz信号
variabletmp2:
integerrange0to249999;;--产生2hz信号的计数器
begin
ifclk0'eventandclk0='1'then
iftmp2=249999then
tmp2:
=0;
clk_b<=notclk_b;
else
tmp2:
=tmp2+1;
endif;
endif;
endprocessp1;
p2:
process(clk_b)--2分频,产生1hz信号
begin
ifclk_b'eventandclk_b='1'then
tmp<=nottmp;
endif;
endprocessp2;
clk1<=clk_b;
clk2<=tmp;
enda;
倒计时模块:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_arith.all;
entitybcountis
port(
clk1:
instd_logic;--1Mhz
clk2:
instd_logic;--1hz
sw:
outstd_logic;
st:
instd_logic;
col,row:
outstd_logic_vector(7downto0)
);
endbcount;
architectureaofbcountis
signalcount:
integerrange0to9;
signalf:
std_logic;
signalc:
std_logic_vector(7downto0);
signalr:
std_logic_vector(7downto0);
signaltmp3:
integerrange0to7;
begin
p1:
process(clk2)
begin
ifclk2'eventandclk2='1'then
ifst='0'then
ifcount=9then
count<=9;
f<='1';
else
count<=count+1;
f<='0';
endif;
else
count<=0;
f<='0';
endif;
endif;
endprocessp1;
p2:
process(clk1,count)
begin
ifclk1'eventandclk1='1'then
iftmp3=7then
tmp3<=0;
else
tmp3<=tmp3+1;
endif;
casetmp3is
when0=>c<="01111111";
when1=>c<="10111111";
when2=>c<="11011111";
when3=>c<="11101111";
when4=>c<="11110111";
when5=>c<="11111011";
when6=>c<="11111101";
when7=>c<="11111110";
whenothers=>c<="00000000";
endcase;
iff='0'then
casecountis
when0=>
casetmp3is
when2=>r<="11110010";
when5=>r<="11111110";
when3|4=>r<="10010010";
whenothers=>r<="00000000";
endcase;
when1=>
casetmp3is
when2|5=>r<="11111110";
when3|4=>r<="10010010";
whenothers=>r<="00000000";
endcase;
when2=>
casetmp3is
when2|3|4=>r<="10000000";
when5=>r<="11111110";
whenothers=>r<="00000000";
endcase;
when3=>
casetmp3is
when2=>r<="11111110";
when5=>r<="10011110";
when3|4=>r<="10010010";
whenothers=>r<="00000000";
endcase;
when4=>
casetmp3is
when2=>r<="11110010";
when5=>r<="10011110";
when3|4=>r<="10010010";
whenothers=>r<="00000000";
endcase;
when5=>
casetmp3is
when2=>r<="11110000";
when3|5=>r<="00010000";
when4=>r<="01111110";
whenothers=>r<="00000000";
endcase;
when6=>
casetmp3is
when5=>r<="11111110";
when2|3|4=>r<="10010010";
whenothers=>r<="00000000";
endcase;
when7=>
casetmp3is
when2=>r<="10011110";
when5=>r<="11110010";
when3|4=>r<="10010010";
whenothers=>r<="00000000";
endcase;
when8=>
casetmp3is
when4=>r<="11111110";
whenothers=>r<="00000000";
endcase;
whenothers=>
casetmp3is
when2|5=>r<="11111110";
when3|4=>r<="10000010";
whenothers=>r<="00000000";
endcase;
endcase;
else
r<="00000000";
endif;
endif;
endprocessp2;
col<=c;
row<=r;
sw<=f;
enda;
乒乓球控制模块:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_arith.all;
entitytennisis
port(
clkp:
instd_logic;--2hz时钟信号
sw:
instd_logic;--计时结束信号
sA,sB:
instd_logic;--双方击球,
score11:
outstd_logic_vector(6downto0);--甲得分(个位)
score12:
outstd_logic_vector(6downto0);--甲得分(十位)
score21:
outstd_logic_vector(6downto0);--乙得分(个位)
score22:
outstd_logic_vector(6downto0);--乙得分(十位)
light:
outstd_logic_vector(7downto0)--发光二极管的显示
);
endtennis;
architectureaoftennisis
componentled--七段数码管译码显示模块
port(
cn:
instd_logic_vector(3downto0);--输入分数
ag1:
outstd_logic_vector(6downto0);--译码输出(十位)
ag2:
outstd_logic_vector(6downto0)--译码输出(个位)
);
endcomponent;
signalscore1,score2:
std_logic_vector(3downto0);--双方的得分
signallit:
integerrange0to8;--7个二极管的控制信号
signalm:
integerrange0to2;--发球计数器
signalsend:
std_logic;--发球权信号
typessis(waitfor,begin1,to2,begin2,to1,allow1,allow2);--设置7个状态
signalstate:
ss;
begin
p1:
process(clkp,sA,sB)
begin
ifclkp'eventandclkp='1'then
ifsw='1'then--倒计时结束,游戏开始
ifm=3then
m<=0;
send<=notsend;--发3个球后,交换发球
endif;
if(score1="1011"orscore2="1011")then--比分达到11分时,一局结束
lit<=0;--灯全灭
m<=0;--发球计数器清零
send<='0';--sA先发球
score1<="0000";score2<="0000";--双方比分清零
state<=waitfor;--进入等待状态,开始新的一局
else
casestateis
whenwaitfor=>--等待状态
casesendis
when'0'=>lit<=1;state<=begin1;--若sA发球,则L1亮
when'1'=>lit<=8;state<=begin2;--若sB发球,则L8亮
whenothers=>lit<=0;--灯全灭
endcase;
whenbegin1=>
ifsA='1'then--甲发球
lit<=2;--L2亮
ifsB='1'then
lit<=0;
score1<=score1+1;state<=waitfor;--乙接球判负
else
state<=to2;
endif;
elsestate<=waitfor;
endif;
whenbegin2=>
ifsB='1'then--乙发球
lit<=7;--L7亮
ifsA='1'then
lit<=0;
score2<=score2+1;state<=waitfor;--甲接球判负
else
state<=to1;
endif;
elsestate<=waitfor;
endif;
whento1=>--乙接球后的状态
ifsA='1'then
lit<=0;
score2<=score2+1;m<=m+1;state<=waitfor;--甲接球判负
elsiflit=2then
lit<=1;
state<=allow1;--进入甲接球状态
elselit<=lit-1;--控制灯的走向
endif;
whento2=>--甲接球后的状态
ifsB='1'then
lit<=0;
score1<=score1+1;m<=m+1;state<=waitfor;--乙接球判负
elsiflit=7then
lit<=8;
state<=allow2;--进入乙接球状态
elselit<=lit+1;--控制灯的走向
endif;
whenallow1=>--甲接球状态
ifsA='1'then
state<=to2;--甲接球进入向乙移动的状态
else
score2<=score2+1;m<=m+1;lit<=0;state<=waitfor;
--甲未接球乙加分
endif;
whenallow2=>--乙接球状态
ifsB='1'then
state<=to1;--乙接球进入向甲移动的状态
else
score1<=score1+1;m<=m+1;lit<=0;state<=waitfor;
--甲未接球乙加分
endif;
endcase;
endif;
else--倒计时没有结束,比分清零,游戏终止
lit<=0;
score1<="0000";score2<="0000";
m<=0;
send<='0';
endif;
endif;
endprocessp1;
withlitselect--控制亮灯的顺序
light<="00000000"when0,
"00000001"when1,
"00000010"when2,
"00000100"when3,
"00001000"when4,
"00010000"when5,
"00100000"when6,
"01000000"when7,
"10000000"when8,
"00000000"whenothers;
q1:
ledportmap(cn=>score1,ag2=>score11,ag1=>score12);--译码模块,显示甲得分
q2:
ledportmap(cn=>score2,ag2=>score21,ag1=>score22);--译码模块,显示乙得分
enda;
译码显示模块:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_arith.all;
entityledis
port(
cn:
instd_logic_vector(3downto0);--输入的分数信号
ag1:
outstd_logic_vector(6downto0);--译码输出(十位)
ag2:
outstd_logic_vector(6downto0)--译码输出(个位)
);
endled;
architectureaofledis
begin
process(cn)
begin
casecnis
when"0000"=>ag1<="1111110";ag2<="1111110";--显示0
when"0001"=>ag1<="111111