《北邮数电实验报告简易钢琴.docx》由会员分享,可在线阅读,更多相关《北邮数电实验报告简易钢琴.docx(27页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、数字电路实验报告简易电子琴设计与实现 班级:201121XXXX 学号:201121XXXX 姓名:傻逼xxxx年11月8号目录一实验介绍21.实验目的22.实验所用仪器及元器件23.实验内容2基本内容2提高要求34.实验原理3二实验设计与实现41.实验思路42.程序设计53仿真波形及分析9三故障及debug过程10四实验总结10一实验介绍1.实验目的(1)进一步掌握VHDL和Quartus II软件的使用;(2)理解状态机的工作原理和设计方法;(3)掌握利用EDA工具进行自顶向下的电子系统设计方法。2.实验所用仪器及元器件(1)计算机;(2)EDA开发板及相应元器件。3.实验内容(1)基本内
2、容1、用 88 点阵进行游戏显示。2、BTN1BTN7 七个按键模拟钢琴演奏时的“1 2 3 4 5 6 7”七个音符。点阵的第一列对应音符“1”,第二列对应音符“2”,依此类推,低中高音自定。3、光点在点阵第一行随机出现,逐点下落,下落速度为 0.2 秒 /行,如图1 所示。4、在光点下落到点阵最后一行之前的过程中,如果按下与该列点阵相应的音符键,该光点消失,蜂鸣器演奏相应的音符声音,计分器加1。如果在光点下落到最后一行依然没有进行相应的按键操作,该光点消失,计分器不加分。计分器由数码管显示。5、每隔 1 秒在点阵的不同列的第一行出现一个光点。6、游戏时间为 30 秒,数码管倒计时显示。(2
3、)提高要求1、光点在点阵某行随机出现,然后逐点下落。2、下落速度随机变化。3、光点按照存储的乐曲顺序和速度的出现。4、自拟其它功能。4.实验原理因为音阶的频率我们是知道的,设为f,而max2板上的clk信号是50MHz,所以要得到需要的f,只需要n=50M/f 就可以得到分频的倍数了。以下是已知的所需频率f。音名频率(Hz)音名频率(Hz)音名频率(Hz)低音1261.63中音1523.25高音11046.50低音2293.67中音2587.33高音21174.66低音3329.63中音3659.25高音31381.51低音4349.23中音4698.46高音41396.92低音5391.99
4、中音5783.99高音51567.98低音6440中音6880高音61760低音7439.88中音7987.76高音71975.52二实验设计与实现1.实验思路逻辑实验图如下: 开始 档位选择 高音档位低音档位中音档位Btn按钮不同档位不同分频,点阵上对应点消失蜂鸣器2.程序设计整个程序我分成了三个大块,五个小块,三个大块分别是点阵、蜂鸣器分频、数码管,蜂鸣器分频最为简单。(1)首先从点阵说起,点阵我分成了两个小块,一部分负责扫描,即通过扫描显示输入图形,一部分负责图像的输入,这样做能简化程序结构,让程序思路更清晰。点阵图像的输入部分,又可简单地分为三个功能的实现:每0.2秒点下落+每一秒产生
5、一个新的点+按钮按下时对应的点消失。编写思路如下:两个计时器,计时到0.2秒时,用连接符&实现逻辑右移,产生下落的效果,计时到1秒时,将存储的音符译码成对应的输入,把每一列的最高位置零,看起来就是点阵第一行产生了一个新的点,btn按钮嵌套在最外层,当7个btn中有一个为高电平时,把对应的列置为“11111111”。点阵的扫描模块,用列扫描的方式,因为点是一列一列下落的。代码有点长,所以附在了最后面,具体的实现是这样的:扫描模块:先将时钟分频,分一个不太高但又能产生视觉暂留的频率,基本上几百hz就行,尽量让每一个状态停留的时间长一些,产生点就会更亮一些,再挂上一个range 0 to 7的cou
6、nt计数器,对应点阵的八个输入,讲8个状态依次译码,每一状态下,分别让第一列亮、第二列亮、第三列亮,同时给一个不同的row输入,输入由点阵图像模块产生。图像模块:先将50MHz分频,得到一个5Hz的时钟,在5Hz的时钟下再挂上一个range 0 to 4的count计数器,count每循环一轮就是一秒钟,每变一次就是0.2秒,所以在count的第一个状态给该产生点的那一列赋值,即“01111111”,同时其他7列向下移位。在count的另外四个状态下,8列都向下移位,不赋值。按键的值写成一个case语句,对应起7个按键,没有按键按下时不做操作,一旦对应的按键按下时,将该列置为“11111111
7、”,并将score信号取反,score信号作为数码管的输入,检测到上升沿或下降沿就出发数码管加1.按键检测代码:分这样5个状态的好处是:所有的赋值全部在一个if语句里,不会出现不同进程对同一变量重复赋值的情况,如果下落和产生新点写成两个进程的话,就必然会造成重复赋值。定义一个新的“数字串”type用来储存音符,音符用06表示,对应简谱的17,音符在count的第一个状态下被译码,每隔1秒后移一位,得到下一个音符。在自动播放模式的时候,就自动将对应的按键置1就行了。(2)再说数码管模块,数码管模块分成倒计时和计分两个部分,cat0、cat1用来计分,cat2、cat3用来倒计时。计分分成高位和低
8、位分别显示,计时也分成高位和低位。倒计时模块:将时钟分频成1Hz,挂上一个计数器,计数器每一次加1,倒计时的低位减1.低位减到0时,低位置9,高位减1,低位高位均减到0时,游戏结束。计分模块:Score时钟沿来临时,低位加1,低位加到10时,低位置0,高位加1.扫描显示:依然是将时钟分一个比较低又能造成视觉暂留的频率,四个管子依次亮,两个高位两个低位都赋给一个temp变量,对temp进行译码,对应09输出显示。(3)再说蜂鸣器分频,算是最简单的一部分了,给蜂鸣器输入一个频率,他就能发出对应的声音,所以一个按键按下就对应一个分频系数,写出一个case语句,分别对应7个按键按下的情况,每一种情况输
9、出一个分频系数,分频系数再输入给分频器,分频的输出给beep蜂鸣器。三个档位用一个switch切换,写成三个if语句3仿真波形及分析1.数码管计分器仿真:时钟输入是 50MHz,触发输入5MHzCat0 cat1交替变换对应给abcdefg管脚的输出,截图中从左往右依次是0110000、1101101、1111001、0110011,即数码管依次显示1、2、3、4屏幕长度有限,两个灯管交替扫描、显示2位数的波形没能呈现出来2.点阵扫描模块的仿真最上面是col的输出,从图形可看出是逐列扫描中间密集的部分是输入的时钟频率,50MHz下面是row的输出,随意设的,图中可清楚地看出从左往右每一轮扫描的
10、输出依次是10000000010000000010000000010000001000000100000010000000000100003.点阵图像模块的仿真图中可清楚地看到,当btn(0)被按下且时钟的上升沿到来时,dot_row0被置为全1Btn(1)一直没被按下,所以dot_row1中的0依次左移,对应点等时间间隔下落三故障及debug1. Case语句要定义每一种情况,不然会报错,新定义的一个arrayinteger的type,必须要指明长度,还必须全部赋上初值2.vhdl是并行的程序,很多最初或者最后的赋值写在前面还是后面都一样,但是不能在两个地方给同一个变量赋值,如点阵的那个地方
11、,不能把向下移位和最高位置0写在不同的进程里。3.输出的变量不能读取,所以很多地方需要设一个中转量,中转量变来变去变完以后最后再把值给输出端口。Quartus也建议可以把输出变量改成buffer型,不过那样程序的稳定性就不好了。4.vhdl里面并列的语句之间要写分号,而不能写逗号。5.因为是硬件编程,所以实验的结果跟设备也有关系,仿真正确不一定现象会正确,我就遇到过不少莫名其妙的问题,比如点下降的过程中会卡,蜂鸣器怎么按也按不响,这时候换一台机器就能好了,不过前提是你要确保你的程序绝对是对的。6.vhdl中需要分情况讨论的地方特别多,应该尽量写出case语句,让程序结构更清晰。7.有些运算需要
12、大量的逻辑门,如果除100、除1000等,如果定义整形信号时不定义范围,编译器会为你的计数器分配32根信号线用来计数,浪费大量资源,应该尽量避免。8.关于移位操作,移位操作我总共试过两个办法,vhdl的sll、srl、rol、ror这些操作符都是对bitvector定义的,所以要强制类型转换to_stdlogicvetor,实验我用连接符&的方法,要连接的字符放左边就是右移,放右边就是左移。四实验总结自己平时比较喜欢编程,没事就爱琢磨琢磨,不管软件编程还是硬件编程,都很有兴趣,上次数电实验之后自己又仔细研究过VHDL,所以这次实验课的编写比较顺利,也收获很多,知道很多之前不知道的操作,譬如逻辑
13、移位循环移位。通过和同学的讨论,自己也了解到了他们的想法,实现了共同进步,从头到尾所有的代码都是我自己手写的,付出了不少的心血,debug的时间都至少有30个小时,也仔细研究如何减少逻辑门的使用。遗憾的是,有些功能的实现还是没能想出一个较好的算法,尝试过但不太成功,希望以后自己能更有进步。附主要模块代码:点阵图像产生:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity dotMatrix_dot isport(dotMatrix_
14、dot_clk: in std_logic;btn: in std_logic_vector(6 downto 0);dot_row0: out std_logic_vector(7 downto 0);dot_row1: out std_logic_vector(7 downto 0);dot_row2: out std_logic_vector(7 downto 0);dot_row3: out std_logic_vector(7 downto 0);dot_row4: out std_logic_vector(7 downto 0);dot_row5: out std_logic_ve
15、ctor(7 downto 0);dot_row6: out std_logic_vector(7 downto 0);dot_row7: out std_logic_vector(7 downto 0);end dotMatrix_dot;architecture a of dotMatrix_dot istype arrayinteger is array(0 to 6)of integer range 0 to 6;signal tmp1: integer range 0 to 99999999;signal tmp2: std_logic_vector(3 downto 0):=000
16、0;signal clk_5hz: std_logic;signal clk_1hz: std_logic;signal row0,row1,row2,row3,row4,row5,row6,row7: std_logic_vector(7 downto 0):=11111111;constant melody: arrayinteger:=(0,1,2,3,4,5,6);signal pointer: integer range 0 to 60;begindot_row0=row0;dot_row1=row1;dot_row2=row2;dot_row3=row3;dot_row4=row4
17、;dot_row5=row5;dot_row6=row6;dot_row7=row7;-row7=11111111;p3:process(dotMatrix_dot_clk)beginif dotMatrix_dot_clkevent and dotMatrix_dot_clk=1 thenif tmp1=9 thentmp1=0;elsetmp1=tmp1+1;end if;end if;end process p3;p4:process(tmp1)beginif tmp14 thenclk_5hz=0;elseclk_5hz=1;end if;end process p4;p1:proce
18、ss(clk_5hz)beginif(clk_5hzevent and clk_5hz=1) thenif(tmp2=1001) then tmp2=0000;else tmp2 = tmp2+1;end if;end if;end process;p5:process(tmp2(0),btn)beginif(btn=00000000)thenif tmp2(0)event and tmp2(0)=1 thenrow0=1&row0(7 downto 1);row1=1&row1(7 downto 1);row2=1&row2(7 downto 1);row3=1&row3(7 downto
19、1);row4=1&row4(7 downto 1);row5=1&row5(7 downto 1);row6=1&row6(7 downto 1);row7row0(7)=0;if(pointer6)thenpointer=pointer+1;elsepointerrow1(7)=0;if(pointer6)thenpointer=pointer+1;elsepointerrow2(7)=0;if(pointer6)thenpointer=pointer+1;elsepointerrow3(7)=0;if(pointer6)thenpointer=pointer+1;elsepointerr
20、ow4(7)=0;if(pointer6)thenpointer=pointer+1;elsepointerrow5(7)=0;if(pointer6)thenpointer=pointer+1;elsepointerrow6(7)=0;if(pointer6)thenpointer=pointer+1;elsepointer row0 row1 row2 row3 row4 row5 row6end case;end if;end process p5;end a;点阵扫描:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC
21、_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity dotMatrix_scan isport(dotMatrix_clk: in std_logic;row0: in std_logic_vector(7 downto 0);row1: in std_logic_vector(7 downto 0);row2: in std_logic_vector(7 downto 0);row3: in std_logic_vector(7 downto 0);row4: in std_logic_vector(7 downto 0);row5: in s
22、td_logic_vector(7 downto 0);row6: in std_logic_vector(7 downto 0);row7: in std_logic_vector(7 downto 0);col: out std_logic_vector(7 downto 0);row: out std_logic_vector(7 downto 0);end dotMatrix_scan;architecture a of dotMatrix_scan issignal count:integer range 0 to 7;signal div: integer range 0 to 9
23、999;signal clk_low: std_logic;beginp1:process(dotMatrix_clk)beginif dotMatrix_clkevent and dotMatrix_clk=1 thenif div=9999 then div=0;elsediv=div+1;end if;end if;end process p1;p2:process(div)beginif div4999 thenclk_low=1;elseclk_low=0;end if;end process p2;p3:process(clk_low)beginif clk_lowevent an
24、d clk_low=1 thenif count=7 thencount=0;elsecountcol=10000000;rowcol=01000000;rowcol=00100000;rowcol=00010000;rowcol=00001000;rowcol=00000100;rowcol=00000010;rowcol=00000001;row=row7;end case;end process p4;end a;数码管:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_L
25、OGIC_UNSIGNED.ALL;entity led isport(clk_led: in std_logic;score: in std_logic;abcdefg: out std_logic_vector(6 downto 0);cat: out std_logic_vector(5 downto 0);end led;architecture a of led issignal score_high: integer range 0 to 9;signal score_low: integer range 0 to 9;signal score_temp: integer rang
26、e 0 to 9;signal count: integer range 0 to 999;beginp1:process(score)beginif scoreevent and score=1 thenif(score_low=9) thenscore_low=0;score_high=score_high+1;elsescore_low=score_low+1;end if;end if;end process p1;p2:process(count)beginif count499 thenscore_temp=score_low;cat=111110;elsescore_temp=score_high;catabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg=0000000;end case;if clk_ledevent and clk_led=1 thenif count=999 thencount=0;elsecount=count+1;end if;end if;end process p3;end a;27