数字电路与逻辑设计实验报告.docx
- 文档编号:24179457
- 上传时间:2023-05-25
- 格式:DOCX
- 页数:28
- 大小:419.79KB
数字电路与逻辑设计实验报告.docx
《数字电路与逻辑设计实验报告.docx》由会员分享,可在线阅读,更多相关《数字电路与逻辑设计实验报告.docx(28页珍藏版)》请在冰豆网上搜索。
数字电路与逻辑设计实验报告
北京邮电大学
数字电路与逻辑设计
实验报告
课题名称:
简易钢琴游戏
姓名:
学号:
班级:
学院:
实验指导教师:
一.课题要求
设计制作一个简易钢琴游戏机。
1.原理概述:
根据声乐知识,产生音乐的两个因素是音乐频率的持续时间,音乐的十二平均率规定,每两个八音度之间的频率相差一倍,在两个八音度之间,又可分为12个半音。
每两个半音的频率比为4。
另外,音名A(乐谱中的低音6)的频率为440HZ,音名B到C之间,E到F之间为半音,其余为全音。
由此可以计算出乐谱中从低音1到高音1之间每个音名的频率如表1所示。
2.基本要求:
1、用8×8点阵进行游戏显示。
2、BTN1~BTN7七个按键模拟钢琴演奏时的“1234567”七个音符。
点阵的第一列对应音符“1”,第二列对应音符“2”,依此类推,低中高音自定。
3、光点在点阵第一行随机出现,逐点下落,下落速度为0.2秒/行,如图1所示。
4、在光点下落到点阵最后一行之前的过程中,如果按下与该列点阵相应的音符键,该光点消失,蜂鸣器演奏相应的音符声音,计分器加1。
如果在光点下落到最后一行依然没有进行相应的按键操作,该光点消失,计分器不加分。
计分器由数码管显示。
5、每隔1秒在点阵的不同列的第一行出现一个光点,如图2所示。
6、游戏时间为30秒,数码管倒计时显示。
3.提高要求:
1、光点在点阵某行随机出现,然后逐点下落。
2、下落速度随机变化。
3、光点按照存储的乐曲顺序和速度的出现。
4、自拟其它功能。
二.系统设计
1.设计思路
将整个系统分为几个模块,分别设计各个模块,最后把模块连接成系统。
这种分模块设计容易实现,易于纠错,对一个模块的修改不影响其他模块,设计思路清晰明了,整个系统规整有序。
将不同的模块在quartus中制作成器件,在顶层框图中用连线进行相应的连接,加上输入与输出,便完成了整个系统的设计。
2.系统框图
3.分块设计
(1)分频器模块:
把50MHz的时钟频率分别分成1kHz、5HZ和1HZ,分别用于数码管与点阵扫描、光点下落频率、随机数生成与倒计时;
(2)防抖模块:
用于按键的防抖;
(3)随机数生成模块:
每隔一秒产生一个随机数,并判断按键的正确与否;
(4)倒计时模块:
从30开始计时;
(5)数码显示模块:
记录分数,同时将分数与倒计时输出到数码管,用于显示;
(6)点阵模块:
根据分频得到的频率与随机数发生器产生的随机数生成两个扫描频率,分别为行扫描与列扫描,输出到相应管脚;
(7)蜂鸣器模块:
根据按键btn1-btn7七个按钮,结合拨码开关状态(低中高),将50MHz原始时钟进行21中不同的分频,分频系数M=50M/f。
将得到分频信号输出到beep管脚就能够发出相应的音符。
三.仿真波形与波形分析
我是分模块进行仿真的,对每个模块我都新建了一个工程进行仿真。
由于50MHz时钟在Quartus中不好仿真,因此包括分频的模块如分频模块、防抖模块与蜂鸣器模块就没有做仿真了。
1随机数发生器
Clear是清零复位端。
memorize与random是产生的两个随机数,图中的随机数是循环加一的。
Clk_out3是时钟输入。
BTN是按键输入,若按键输入与随机数对应,则匹配值match等于1.
2点阵模块
Memorize与random为两个随机数,clk_out1是扫描频率,clk_out2为光点的下落频率,a为行扫描row,b为列扫描col。
由于时钟频率的关系,仿真图不容易观察,并且由于程序还存在一些问题,可以看出行扫描与列扫描存在不匹配。
3倒计时
Clear是清零端,复位值为30。
clk_out3是时钟输入,time1是个位,time2是十位,从30开始减一,直到均为零。
4计分器与数码管显示
Clear用于清零,clk_out1作为时钟输入。
Cat0是计分的个位,cat1是计分的十位,match是匹配判断值,当match在上升沿等于1时,cat0加1,若cat0等于9,则向cat1进位。
四.代码源程序
①防抖模块
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYfangdouIS
PORT(clk_out2:
INSTD_LOGIC;
btn_in:
instd_logic_vector(6downto0);
btn:
outstd_logic_vector(6downto0)
);
ENDfangdou;
ARCHITECTUREbehaveOFfangdouIS
signalbtntmp1,btntmp2:
std_logic_vector(6downto0);
BEGIN
PROCESS(clk_out2)--防抖
BEGIN
IF(clk_out2'EVENTANDclk_out2='0')THEN
btntmp2<=btntmp1;
btntmp1<=btn_in;
ENDIF;
ENDPROCESS;
btn(0)<=clk_out2andbtntmp1(0)and(notbtntmp2(0));
btn
(1)<=clk_out2andbtntmp1
(1)and(notbtntmp2
(1));
btn
(2)<=clk_out2andbtntmp1
(2)and(notbtntmp2
(2));
btn(3)<=clk_out2andbtntmp1(3)and(notbtntmp2(3));
btn(4)<=clk_out2andbtntmp1(4)and(notbtntmp2(4));
btn(5)<=clk_out2andbtntmp1(5)and(notbtntmp2(5));
btn(6)<=clk_out2andbtntmp1(6)and(notbtntmp2(6));
endbehave;
用于BTN0-BTN7按键的防抖,按键的持续时间为0.2S。
②分频模块
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityfenpinis
port(clk:
instd_logic;
clk_out1,clk_out2,clk_out3:
outstd_logic
);
endfenpin;
architecturebehaveoffenpinis
signaltemp1,temp2,temp3:
integerrange0to50000000;
signalclk_out_1,clk_out_2:
std_logic;
begin
p1:
PROCESS(clk)
BEGIN
--ifclear<='1'then
--temp1<=0;
IFclk'EVENTANDclk='1'THEN
IFtemp1=2THEN
temp1<=0;clk_out_1<=notclk_out_1;
ELSE
temp1<=temp1+1;
ENDIF;
ENDIF;
ENDPROCESSp1;
clk_out1<=clk_out_1;
p4:
PROCESS(clk_out_1)
BEGIN
--ifclear<='1'then
--temp2<=0;
IFclk_out_1'EVENTANDclk_out_1='1'THEN
IFtemp2=2THEN
temp2<=0;clk_out_2<=notclk_out_2;
ELSE
temp2<=temp2+1;
ENDIF;
ENDIF;
ENDPROCESSp4;
clk_out2<=clk_out_2;
p6:
PROCESS(clk_out_2)
BEGIN
--ifclear<='1'then
--temp1<=0;
IFclk_out_2'EVENTANDclk_out_2='1'THEN
IFtemp3=5THEN
temp3<=0;
ELSE
temp3<=temp3+1;
ENDIF;
ENDIF;
ENDPROCESSp6;
p7:
PROCESS(temp3)
BEGIN
--IFclk'EVENTANDclk='1'THEN
IFtemp3<3THEN
clk_out3<='0';
ELSE
clk_out3<='1';
ENDIF;
--endif;
ENDPROCESSp7;
endbehave;
用50MHz原始时钟进行分频,分频输出频率分别为1kHz、5Hz、1Hz,占空比为50%。
③随机数发生器
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityrandomeris
port(clk_out3:
instd_logic;
clear:
instd_logic;
match:
outstd_logic;
random,memorize:
outintegerrange0to9;
btn:
instd_logic_vector(6downto0)
);
endrandomer;
architecturebehaveofrandomeris
signalrandom1,memorize1:
integerrange0to9;
begin
p3:
process(clk_out3,clear)--随机数发生器
begin
ifclear='1'then
memorize1<=0;
random1<=1;
elsIFclk_out3'eventandclk_out3='1'THEN
ifrandom1=6then
random1<=0;
else
memorize1<=random1;
random1<=random1+1;
endif;
endif;
endprocessp3;
p4:
process(random1,btn,memorize1)
begin
match<='0';
casebtnis
when"1000000"=>ifrandom1=0ormemorize1=0thenmatch<='1';endif;
when"0100000"=>ifrandom1=1ormemorize1=1thenmatch<='1';endif;
when"0010000"=>ifrandom1=2ormemorize1=2thenmatch<='1';endif;
when"0001000"=>ifrandom1=3ormemorize1=3thenmatch<='1';endif;
when"0000100"=>ifrandom1=3ormemorize1=4thenmatch<='1';endif;
when"0000010"=>ifrandom1=5ormemorize1=5thenmatch<='1';endif;
when"0000001"=>ifrandom1=6ormemorize1=6thenmatch<='1';endif;
whenothers=>null;
endcase;
endprocessp4;
random<=random1;
memorize<=memorize1;
endbehave;
随机数模块我没有做完,不知道怎么做,没有头绪,用M序列做的话感觉转化比较麻烦。
我只以循环加一的的方式生成了两个数。
另外,当有BTN键输入的时候,判断是否与生成的随机数匹配,若匹配,则match等于1,否则等于0。
④点阵模块
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitydianzhenis
port(clk_out1,clk_out2:
instd_logic;
a,b:
outstd_logic_vector(7downto0);
random,memorize:
inintegerrange0to9);
enddianzhen;
architecturebehaveofdianzhenis
signaltmp:
integerrange0to4;
begin
p8:
process(clk_out2)
begin
IFclk_out2'EVENTANDclk_out2='1'THEN
iftmp=4then
tmp<=0;
else
tmp<=tmp+1;
endif;
endif;
endprocessp8;
p9:
PROCESS(clk_out1,tmp,random,memorize)--点阵扫描
BEGIN
CASEclk_out1is
when'0'=>
casetmpis
WHEN0=>
caserandomis
when0=>a<="01111111";b<="10000000";
when1=>a<="01111111";b<="01000000";
when2=>a<="01111111";b<="00100000";
when3=>a<="01111111";b<="00010000";
when4=>a<="01111111";b<="00001000";
when5=>a<="01111111";b<="00000100";
when6=>a<="01111111";b<="00000010";
whenothers=>a<="01111111";b<="00000000";
endcase;
WHEN1=>
caserandomis
when0=>a<="10111111";b<="10000000";
when1=>a<="10111111";b<="01000000";
when2=>a<="10111111";b<="00100000";
when3=>a<="10111111";b<="00010000";
when4=>a<="10111111";b<="00001000";
when5=>a<="10111111";b<="00000100";
when6=>a<="10111111";b<="00000010";
whenothers=>a<="11111111";b<="00000000";
endcase;
WHEN2=>
caserandomis
when0=>a<="11011111";b<="10000000";
when1=>a<="11011111";b<="01000000";
when2=>a<="11011111";b<="00100000";
when3=>a<="11011111";b<="00010000";
when4=>a<="11011111";b<="00001000";
when5=>a<="11011111";b<="00000100";
when6=>a<="11011111";b<="00000010";
whenothers=>a<="11011111";b<="00000000";
endcase;
WHEN3=>
caserandomis
when0=>a<="11101111";b<="10000000";
when1=>a<="11101111";b<="01000000";
when2=>a<="11101111";b<="00100000";
when3=>a<="11101111";b<="00010000";
when4=>a<="11101111";b<="00001000";
when5=>a<="11101111";b<="00000100";
when6=>a<="11101111";b<="00000010";
whenothers=>a<="11111111";b<="00000000";
endcase;
WHEN4=>
caserandomis
when0=>a<="11110111";b<="10000000";
when1=>a<="11110111";b<="01000000";
when2=>a<="11110111";b<="00100000";
when3=>a<="11110111";b<="00010000";
when4=>a<="11110111";b<="00001000";
when5=>a<="11110111";b<="00000100";
when6=>a<="11110111";b<="00000010";
whenothers=>a<="11111111";b<="00000000";
endcase;
endcase;
when'1'=>
casetmpis
WHEN0=>
casememorizeis
when0=>a<="11111011";b<="10000000";
when1=>a<="11111011";b<="01000000";
when2=>a<="11111011";b<="00100000";
when3=>a<="11111011";b<="00010000";
when4=>a<="11111011";b<="00001000";
when5=>a<="11111011";b<="00000100";
when6=>a<="11111011";b<="00000010";
whenothers=>a<="11111011";b<="00000000";
endcase;
WHEN1=>
casememorizeis
when0=>a<="11111101";b<="10000000";
when1=>a<="11111101";b<="01000000";
when2=>a<="11111101";b<="00100000";
when3=>a<="11111101";b<="00010000";
when4=>a<="11111101";b<="00001000";
when5=>a<="11111101";b<="00000100";
when6=>a<="11111101";b<="00000010";
whenothers=>a<="11111101";b<="00000000";
endcase;
WHEN2=>
casememorizeis
when0=>a<="11111110";b<="10000000";
when1=>a<="11111110";b<="01000000";
when2=>a<="11111110";b<="00100000";
when3=>a<="11111110";b<="00010000";
when4=>a<="11111110";b<="00001000";
when5=>a<="11111110";b<="00000100";
when6=>a<="11111110";b<="00000010";
whenothers=>a<="11111110";b<="00000000";
endcase;
whenothers=>null;
endcase;
endcase;
endprocessp9;
endbehave;
我使用了两个频率,一个为1kHz,用于行扫描(a)与列扫描(b),另一个为5Hz,用于光点的下落。
根据随机数的值使相应的点发光。
⑤倒计时
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitytimingis
port(clk_out3:
instd_logic;
clear:
instd_logic;
time1,time2:
outintegerrange0to9
);
endtiming;
architecturebehaveoftimingis
signaltime3,time4:
integerrange0to9;
begin--倒计时
p20:
PROCESS(clk_out3,clear)
BEGIN
ifclear='1'then
time3<=0;
time4<=3;
--endif;
elsifclk_out3'EVENTANDclk_out3='1'THEN
iftime3=0then
iftime4/=0then
time3<=9;
time4<=time4-1;
endif;
elsetime3<=time3-1;
endif;
endif;
time1<=time3;time2<=time4;
ENDPROCESSp20;
endbehave;
倒计时模块相对比较简单,用clear作为清零端,初值为30,每隔一秒个位减一,若个位不够向十位借一,直到个位与十位均为零。
⑥计分与数码管显示
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitycounteris
port(clk_out1:
instd_logic;
btn:
instd_logic_vector(6downto0);
count:
outstd_logic_vector(5downto0);
coutout:
outstd_logic_vector(6downto0);
random,memorize:
inintegerrange0to9;
time1,time2:
inintegerrange0to9;
match:
instd_logic;
clear:
instd_logic
);
endcounter;
architecturebehaveofcounteris
signalcnt:
integerrange0TO3;
signalcat0,cat1:
integerrange0to9;
begin
p1:
process(btn,random,memorize,clear)--计分器
begin
ifclear='1'then
cat0<=0;
cat1<=0;
elsifmatch'eventandmatch='1'then
ifcat0=9then
cat0<=0;
cat1<=cat1+1;
else
cat0<=cat0+1;
endif;
endif;
endprocessp1;
p15:
PROCESS(clk_out1)
BEGIN
IF(clk_out1'EVENTANDclk_out1='1')THEN
IFcnt=3THEN
cnt<=0;
ELSE
cnt<=cnt+1;
ENDIF;
ENDIF;
ENDPROCESSp15;
p16:
process(cnt,cat0,cat1,time1,time2)
begin
CASEcntIS
WHEN0=>count<="011111";
casecat0is
when0=>coutout<="1111110";
when1=>coutout<="0110000";
when2=>couto
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数字电路 逻辑设计 实验 报告