简易钢琴游戏实验报告副本文档格式.docx
《简易钢琴游戏实验报告副本文档格式.docx》由会员分享,可在线阅读,更多相关《简易钢琴游戏实验报告副本文档格式.docx(26页珍藏版)》请在冰点文库上搜索。
当reset=‘1’时,进行复位。
然后检测按键是否按下,不按下则不发声不加分;
若是停止按键,则是停止发声。
若有按键(address),则依次从点阵的最下一行开始检测按键是否正确(检测到第六行后应同时检测当前检测行的前五行为全0,以保证点阵上同时有两点时上面的一点不会被错误的消掉),按键正确则grade(得分)加分。
每隔0.2秒点阵个各行赋值依次下移一行。
Countdown(倒计时)每一秒减一,同时给点阵光点出现的初始位置赋一次值。
将输出的grade和countdown分别进行除10和对10取模操作,分别对应其十位和个位。
●数码管显示模块:
建立0-9十个数字相应的表,使用1M的时钟对输入的分数和倒计时分别扫描显示(show)。
●点阵显示模块:
使用1M时钟一次扫描点阵每一行的值,然后赋给col进行显示。
●蜂鸣器模块:
将传入的toneindex建表(tonetable)依次转化为相应的分频预置数,然后把12M的时钟按分频预置数进行分频,再进行二分频以使声音更清晰。
三、仿真波形及波形分析
1、1M分频:
图示为一个50分频器,本实验中使用的是50M的输入时钟,则可以分成一个1M的时钟,同时还分了一个12M的时钟,这里未给出。
2、按键转换
按键转换模块,从图中我们可以看出,根据输入的按键(address)分别转化为相应的toneindex,为后续用12M的时钟分成相应的音调做准备。
比如,address=”0001000”时代表的是按btn4,则转换成”100”;
当无按键的时候,即address=”0000000”时,toneindex=”000”蜂鸣器不发声。
3、转换成音调分频预置数
将输入的toneindex转化为相应的预置分频数,我们可以看到,当toneindex为111时,对应的预置分频数为1717
4、按预置数分频(1717)
我们可以通过这个波形图检测当分频预置数为1717时,分频比为12*(2047-1717)*2=7920,则对应的音调为12M/7920等于1975HZ。
对应高音7.
5、数码管显示
从图中我们可以看到数字0,对应的show为”1111110”,其他的1-9的数字都是依次对应show的值。
同时,通过一个1M的时钟进行扫描,使数码管无闪烁现象。
6、点阵显示
从图中我们可以看到,以1M的时钟逐行扫描点阵,使点阵看起来不会闪烁。
用row来控制各行的选通。
比如。
Row=”11111011”时,只有第三行有显示。
五、源程序
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
EntityPinaoMasteris
port(
clk:
instd_logic;
--输入50M时钟
address:
instd_logic_vector(6downto0);
--按键
reset:
--复位开始
beep:
outstd_logic;
--蜂鸣器
cat:
outstd_logic_vector(5downto0);
--数码管选通
row:
outstd_logic_vector(7downto0);
--行选通
col:
outstd_logic_vector(6downto0);
--列赋值
show:
outstd_logic_vector(6downto0));
--数码管显示
EndentityPinaoMaster;
ArchitectureoneofPinaoMasteris
signalclk1:
std_logic;
signalclk2:
signalpreclk:
signalfullspks:
signalscantmp:
std_logic_vector(2downto0);
signalLighttmp:
std_logic_vector(1downto0);
signaltoneindex:
signalcountdown:
integerrange0to30;
signalgrade:
integerrange0to99;
signalG1,G0,T1,T0:
integerrange0to9;
signaltone:
std_logic_vector(10downto0);
signalcol0:
std_logic_vector(6downto0);
signalcol1:
signalcol2:
signalcol3:
signalcol4:
signalcol5:
signalcol6:
signalcol7:
signaltime1:
signaltime0:
signalgrade1:
signalgrade0:
begin
clk12M:
process(clk)--12M分频,用于音调的设置
variablecnt:
integerrange0to1;
variabletmp:
if(clk'
eventandclk='
1'
)then
if(reset='
cnt:
=0;
elsifcnt>
=1then
cnt:
tmp:
=nottmp;
else
=cnt+1;
endif;
clk1<
=tmp;
endprocessclk12M;
clk1M:
process(clk)--1M分频,用于扫描
integerrange0to24;
elsifcnt>
=24then
clk2<
endprocessclk1M;
main:
process(clk2,reset)--主进程,对按键进行判断,并产生与分数、倒计时以及蜂鸣器相关的变化
variablecnt1:
integerrange0to199999;
--20万计数器将1M时钟做成0.2s的下降时间间隔
variablecnt2:
integerrange0to5;
--将0.2s变成1s首行重新赋值间隔
if(reset='
)then--复位
cnt1:
cnt2:
grade<
--分数初始化为0
countdown<
=30;
--倒计时初始化为30
col0<
="
0000000"
;
col1<
col2<
col3<
col4<
col5<
col6<
col7<
--点阵初始化
elsif(clk2'
eventandclk2='
if(cnt1=199999)then
cnt1:
cnt2:
=cnt2+1;
col0<
=col1;
col1<
=col2;
col2<
=col3;
col3<
=col4;
col4<
=col5;
col5<
=col6;
col6<
=col7;
col7<
--0.2s逐行下降
=cnt1+1;
if(address="
)then--判断没有按键则不发音或者停止按键则停止发音
toneindex<
000"
elsif(address=col0)then--从点阵的做下面一行开始判断按键是否正确
--若按键正确,把该行置0
=grade+1;
--分数加1
caseaddressis--将按键转化为相应的toneindex,为音调的分频做准备
when"
0000001"
=>
toneindex<
001"
0000010"
010"
0000100"
011"
0001000"
100"
0010000"
101"
0100000"
110"
1000000"
111"
whenothers=>
endcase;
elsif(address=col1)then
caseaddressis
elsif(address=col2)then
elsif(address=col3)then
--第4行和第5行光点正确加2分
=grade+2;
elsif(address=col4)then
elsif(address=col5andcol0="
)then--判断按键与第六行对应且第一行全为0
grade<
=grade+3;
--第6行和第7行正确加3分
caseaddressis
elsif(address=col6andcol1="
)then--判断按键与第七行对应且第二行全为0
elsif(address=col7andcol2="
)then--判断按键与第八行对应且第三行全为0
G1<
=grade/10;
G0<
=grademod10;
--grade/10给分数的十位赋值,grade对10取模给分数的个位赋值
if(cnt2=5)then
if(countdown/=0)then--判断倒计时不为0,则countdown继续减一
countdown<
=countdown-1;
casecountdownis--光点的初始位置,可以存歌曲
when30=>
col7<
when29=>
when28=>
when27=>
when26=>
when25=>
when24=>
when23=>
when22=>
when21=>
when20=>
when19=>
when18=>
when17=>
when16=>
when15=>
when14=>
when13=>
when12=>
when11=>
when10=>
when9=>
when8=>
when7=>
when6=>
when5=>
when4=>
when3=>
when2=>
when1=>
whenothers=>
endcase;
T1<
=countdown/10;
T0<
=countdownmod10;
--countdown/10给倒计时的十位赋值,grade对10取模给倒计时的个位赋值
endif;
endprocessmain;
--数码管显示模块
ShowTime1:
process(T1)--显示倒计时的十位
caseT1is--0-9数字的对应
when9=>
time1<
1111011"
--9
when8=>
1111111"
--8
when7=>
1110000"
--7
when6=>
1011111"
--6
when5=>
1011011"
--5
when4=>
0110011"
--4
when3=>
1111001"
--3
when2=>
1101101"
--2
when1=>
0110000"
--1
when0=>
1111110"
--0
whenothers=>
endprocessShowTime1;
ShowTime0:
process(T0)--显示倒计时的个位
caseT0is
time0<