EDA技术及创新实践(设计报告)题目:乐曲硬件演奏电路设计姓名:漩涡鸣人学院:数理与信息工程学院专业:电子科学与技术班级:112学号:1886****20指导教师:汤大智2014年6 月一、设计目的及要求实验目的:1、理解音乐演奏的原理及分频器的原理与使用。
2、了解怎样控制音调的高低变化和音长,从而完成乐曲的自动循环演奏。
3、培养自主学习、正确分析和解决问题的能力。
要求:利用分频器设计硬件乐曲演奏电路;能通过数码管显示动态效果;通过一个开关实现两首乐曲的切换;在音乐播放的同时,会有led流水灯的闪烁。
二、设计原理乐曲演奏的原理是这样的:组成乐曲的每个音符的频率值(音调)及其持续的时间(音长)是乐曲能连续演奏所需的两个基本数据,因此只要控制输出到扬声器的激励信号频率的高低和持续的时间,就可以使扬声器发出连续的乐曲声。
图1、顶层模块图其中,乐谱产生电路用来控制音乐的音调和音长。
控制音调通过设置计数器的预置数来实现,预置不同的数值可以使计数器产生不同频率的信号,从而产生不同的音调。
控制音长是通过控制计数器预置数的停留时间来实现的,预置数停留的时间越长,则该音符演奏的时间越长。
每个音符的演奏时间都是0.25s的整数倍,对于节拍较长的音符,如2分音符,在记谱时将该音名连续记录两次即可。
1、音调的控制频率的高低决定了音调的高低。
音乐的十二平均率规定:每两个8度音(如简谱中的中音1与高音1)之间的频率相差一倍。
在两个8度音之间,又可分为12个半音,每两个半音的频率比为12√2。
另外,音名A(简谱中的低音6)的频率为440Hz,音名B到C之间、E到F之间为半音,其余为全音[4]。
由此可以计算出简谱中从低音1至高音1之间每个音名对应的频率,如表2所示:表2简谱中的音名与频率的关系所有不同频率的信号都是从同一个基准频率分频得到的。
由于音阶频率多为非整数,而分频系数又不能为小数,故必须将计算得到的分频数四舍五入取整。
若基准频率过低,则由于分频比太小,四舍五入取整后的误差较大;若基准频率过高,虽然误差变小,但分频数将变大。
实际的设计综合考虑这两方面的因素,在尽量减小频率误差的前提下取合适的基准频率。
本例中选取6MHz为基准频率。
若无6MHz的基准频率,则可以先分频得到6MHz,或换一个新的基准频率。
实际上,只要各个音名间的相对频率关系不变,演奏出的乐曲听起来都不会"走调"。
本例需要演奏的是梁祝乐曲,该乐曲各音阶频率及相应的分频比如表2所示。
为了减小输出的偶次谐波分量,最后输出到扬声器的波形应为对称方波,因此在到达扬声器之前,有一个二分频的分频器。
表2中的分频比就是从6MHz 频率二分频得到的3MHz频率基础上计算得出的。
由于最大的分频系数为9102,故采用14位二进制计数器分频可满足需要。
在表2中,除给出了分频比以外,还给出了对应于各个音阶频率时计数器不同的预置数。
对于不同的分频系数,只要加载不同的预置数即可。
采用加载预置数实现分频的方法比采用反馈复零法节省资源,实现起来也容易一些,如表3所示:表3各音阶频率对应的分频比及预置数此外,对于乐曲中的休止符,只要将分频系数设为0,即初始值为2141=16383即可,此时扬声器将不会发声。
音长的控制音符的持续时间必须根据乐曲的速度及每个音符的节拍数来确定。
本例演奏的梁祝片段,最短的音符为4分音符,如果将全音符的持续时间设为1s的话,则只需要再提供一个4Hz的时钟频率即可产生4分音符的时长。
三、底层模块设计由顶层模块图可以看到本方案分成8个模块。
1、48MHz分频成12MHz波形分频器,源代码和顶层模块如下//48mhz分成12mhz的分频模块module div_clk12mhz(clk_48mhz,clk_12mhz);input clk_48mhz;output clk_12mhz;reg clk_12mhz;reg [21:0] cnt;always @(posedge clk_48mhz)if(cnt<1) cnt=cnt+1; // (48mhz/12mhz=4,cnt<[4/2-1=1])else begin cnt=0; clk_12mhz =!clk_12mhz; endendmodule2、12MHz分频成6MHz波形分频器,源代码和顶层模块如下://12mhz分成6mhz的分频模块,提供给song模块modulediv_clk6mhz(clk_12mhz,clk_6mhz); input clk_12mhz;output clk_6mhz;reg clk_6mhz;reg cnt;always @(posedge clk_12mhz) clk_6mhz=!clk_6mhz; endmodule3、12MHz分频成4Hz波形分频器,源代码和顶层模块如下://12mhz分成4hz的分频模块,提供给song模块module div_clk4hz(clk_12mhz,clk_4hz); input clk_12mhz;output clk_4hz;reg clk_4hz;reg [21:0] cnt;always @(posedge clk_12mhz)if(cnt<1499999) cnt=cnt+1; // (12mhz/4hz=3000000,cnt<[3000000/2 -1=1499999])else begin cnt=0; clk_4hz =! clk_4hz; endendmodule4、12MHz分频成1mhz波形分频器,源代码和顶层模块如下://12mhz分成1mhz的分频模块,提供给quma模块module div_clk1mhz(clk_12mhz,clk_1mhz);input clk_12mhz;output clk_1mhz;reg clk_1mhz;reg [21:0] cnt;always @(posedge clk_12mhz)if(cnt<5) cnt=cnt+1; // (12mhz/1mhz=12,cnt<[12/2-1=5])else begin cnt=0; clk_1mhz =! clk_1mhz; endendmodule5、12MHz分频成1khz波形分频器,源代码和顶层模块如下://12mhz分成1khz的分频模块,提供给quma模块modulediv_clk1khz(clk_12mhz,clk_1khz);input clk_12mhz;output clk_1khz;reg clk_1khz;reg [21:0] cnt;always @(posedge clk_12mhz)if(cnt<5999) cnt=cnt+1; // (12mhz/1khz=12000,cnt<[12000/2-1= 5999])else begin cnt=0; clk_1khz =! clk_1khz; endendmodule6、song模块源代码和顶层模块如下://音乐产生模块modulesong(clk_6mhz,clk_4hz,speaker,high,me d,low,k);input clk_6mhz,clk_4hz;input k;output speaker;output[3:0] high,med,low;reg[3:0] high,med,low;reg[13:0] divider,origin;reg[9:0] counter;reg speaker;wire carry;assign carry=(divider==16383); always @(posedge clk_6mhz)begin if(carry) divider<=origin;elsedivider<=divider+1;endalways @(posedge carry)begin speaker<=~speaker;end always @(posedge clk_4hz)begincase({high,med,low})'b000000000011:origin<=7281; //低音3'b000000000101:origin<=8730; //低音5'b000000000110:origin<=9565; //低音6'b000000000111:origin<=10310; //低音7'b000000010000:origin<=10647; //中音1'b000000100000:origin<=11272; //中音2'b000000110000:origin<=11831; //中音3'b000001010000:origin<=12556; //中音5'b000001100000:origin<=12974;//中音6'b000001110000:origin<=13347; //中音7'b000100000000:origin<=13516; //高音1'b000000000000:origin<=16383; //休止符endcaseendalways @(posedge clk_4hz)if (k==0)beginif(counter==149) counter<=0;elsecounter<=counter+1;case(counter)//记谱0:{high,med,low}<='b000000000011; //低音"3"1:{high,med,low}<='b000000000011; //持续4个时钟节拍2:{high,med,low}<='b000000000011;3:{high,med,low}<='b000000000011;4:{high,med,low}<='b000000000101; //低音"5"5:{high,med,low}<='b000000000101; //发3个时钟节拍6:{high,med,low}<='b000000000101;7:{high,med,low}<='b000000000110; //低音"6"8:{high,med,low}<='b000000010000; //中音"1"9:{high,med,low}<='b000000010000; //发3个时钟节拍10:{high,med,low}<='b000000010000;11:{high,med,low}<='b000000100000; //中音"2"12:{high,med,low}<='b000000000110; //低音"6"13:{high,med,low}<='b000000010000; //中音"1"14:{high,med,low}<='b000000000101; //低音"5"15:{high,med,low}<='b000000000101;16:{high,med,low}<='b000001010000; //中音"5"17:{high,med,low}<='b000001010000; //发3个时钟节拍18:{high,med,low}<='b000001010000;19:{high,med,low}<='b000100000000; //高音"1"20:{high,med,low}<='b000001100000; //中音"6"21:{high,med,low}<='b000001010000; //中音"5"22:{high,med,low}<='b000000110000; //中音"3"23:{high,med,low}<='b000001010000; //中音"5"24:{high,med,low}<='b000000100000; //中音"2"25:{high,med,low}<='b000000100000;//持续11个时钟节拍26:{high,med,low}<='b000000100000;27:{high,med,low}<='b000000100000;28:{high,med,low}<='b000000100000;29:{high,med,low}<='b000000100000;30:{high,med,low}<='b000000100000;31:{high,med,low}<='b000000100000;32:{high,med,low}<='b000000100000;33:{high,med,low}<='b000000100000;34:{high,med,low}<='b000000100000;35:{high,med,low}<='b000000110000; //中音"3"36:{high,med,low}<='b000000000111; //低音"7"37:{high,med,low}<='b000000000111;38:{high,med,low}<='b000000000110; //低音"6"39:{high,med,low}<='b000000000110;40:{high,med,low}<='b000000000101; //低音"5"41:{high,med,low}<='b000000000101;42:{high,med,low}<='b000000000101;43:{high,med,low}<='b000000000110; //低音"6"44:{high,med,low}<='b000000010000;//中音"1"45:{high,med,low}<='b000000010000;46:{high,med,low}<='b000000100000; //中音"2"47:{high,med,low}<='b000000100000;48:{high,med,low}<='b000000000011; //低音"3"49:{high,med,low}<='b000000000011;50:{high,med,low}<='b000000010000; //中音"1"51:{high,med,low}<='b000000010000;52:{high,med,low}<='b000000000110; //低音"6"53: {high,med,low}<='b000000000101; //低音"5"54:{high,med,low}<='b000000000110; //低音"6"55:{high,med,low}<='b000000010000; //中音"1"56:{high,med,low}<='b000000000101; //低音"5"57:{high,med,low}<='b000000000101; //持续8个时钟节拍58:{high,med,low}<='b000000000101;59:{high,med,low}<='b000000000101;60:{high,med,low}<='b000000000101;61:{high,med,low}<='b000000000101;62:{high,med,low}<='b000000000101;63:{high,med,low}<='b000000000101;64:{high,med,low}<='b000000110000; //中音"3"65:{high,med,low}<='b000000110000; //发3个时钟节拍66:{high,med,low}<='b000000110000;67:{high,med,low}<='b000001010000; //中音"5"68:{high,med,low}<='b000000000111; //低音"7"69:{high,med,low}<='b000000000111;70:{high,med,low}<='b000000100000; //中音"2"71:{high,med,low}<='b000000100000;72:{high,med,low}<='b000000000110; //低音"6"73:{high,med,low}<='b000000010000; //中音"1"74:{high,med,low}<='b000000000101; //低音"5"75:{high,med,low}<='b000000000101; //持续4个时钟节拍76:{high,med,low}<='b000000000101;77:{high,med,low}<='b000000000101;78:{high,med,low}<='b000000000000; //休止符79:{high,med,low}<='b000000000000;80:{high,med,low}<='b000000000011; //低音"3"81:{high,med,low}<='b000000000101; //低音"5"82:{high,med,low}<='b000000000101;83:{high,med,low}<='b000000000011; //低音"3"84:{high,med,low}<='b000000000101; //低音"5"85:{high,med,low}<='b000000000110; //低音"6"86:{high,med,low}<='b000000000111; //低音"7"87:{high,med,low}<='b000000100000; //中音"2"88:{high,med,low}<='b000000000110; //低音"6"89:{high,med,low}<='b000000000110; //持续6个时钟节拍90:{high,med,low}<='b000000000110;91:{high,med,low}<='b000000000110;92:{high,med,low}<='b000000000110;93:{high,med,low}<='b000000000110;94:{high,med,low}<='b000000000101; //低音"5"95:{high,med,low}<='b000000000110;//低音"6"96:{high,med,low}<='b000000010000; //中音"1"97:{high,med,low}<='b000000010000; //发3个时钟节拍98:{high,med,low}<='b000000010000;99:{high,med,low}<='b000000100000; //中音"2"100:{high,med,low}<='b000001010000; //中音"5"101:{high,med,low}<='b000001010000;102:{high,med,low}<='b000000110000; //中音"3"103:{high,med,low}<='b000000110000;104:{high,med,low}<='b000000100000; //中音"2"105:{high,med,low}<='b000000100000;106:{high,med,low}<='b000000110000; //中音"3"107:{high,med,low}<='b000000100000; //中音"2"108:{high,med,low}<='b000000010000; //中音"1"109:{high,med,low}<='b000000010000;110:{high,med,low}<='b000000000110; //低音"6"111:{high,med,low}<='b000000000101; //低音"5"{high,med,low}<='b000000000011; //低音"3"113:{high,med,low}<='b000000000011; //持续4个时钟节拍114:{high,med,low}<='b000000000011;115:{high,med,low}<='b000000000011;116:{high,med,low}<='b000000010000; //中音"1"117:{high,med,low}<='b000000010000; //持续4个时钟节拍118:{high,med,low}<='b000000010000;119:{high,med,low}<='b000000010000;120:{high,med,low}<='b000000000110;121:{high,med,low}<='b000000010000; //中音"1"122:{high,med,low}<='b000000000110; //低音"6"123:{high,med,low}<='b000000000101; //低音"5"124:{high,med,low}<='b000000000011; //低音"3"125:{high,med,low}<='b000000000101; //低音"5"126:{high,med,low}<='b000000000110; //低音"6"127:{high,med,low}<='b000000010000; //中音"1"{high,med,low}<='b000000000101; //低音"5"129:{high,med,low}<='b000000000101; //持续6个时钟节拍130:{high,med,low}<='b000000000101;131:{high,med,low}<='b000000000101;132:{high,med,low}<='b000000000101;133:{high,med,low}<='b000000000101;134:{high,med,low}<='b000000110000; //中音"3"135:{high,med,low}<='b000001010000; //中音"5"136:{high,med,low}<='b000000100000;137:{high,med,low}<='b000000110000; //中音"3"138:{high,med,low}<='b000000100000; //中音"2"139:{high,med,low}<='b000000010000; //中音"1"140:{high,med,low}<='b000000000111; //低音"7"141:{high,med,low}<='b000000000111;142:{high,med,low}<='b000000000110; //低音"6"143:{high,med,low}<='b000000000110;144:{high,med,low}<='b000000000101;//低音"5"145:{high,med,low}<='b000000000101; //持续8个时钟节拍146:{high,med,low}<='b000000000101;147:{high,med,low}<='b000000000101;148:{high,med,low}<='b000000000101;149:{high,med,low}<='b000000000101; endcaseendelse if( k==1)beginif(counter==149) counter<=0; //计时,以实现循环演奏elsecounter<=counter+1;case(counter)//记谱0:{high,med,low}<='b000000110000; //中音"3"1:{high,med,low}<='b000000110000; //持续2个时钟节拍2:{high,med,low}<='b000000100000; //中音23:{high,med,low}<='b000000100000; //持续2个时钟节拍4:{high,med,low}<='b000000110000; //中音"3"5:{high,med,low}<='b000000110000; //发10个时钟节拍6:{high,med,low}<='b000000110000;7:{high,med,low}<='b000000110000;8:{high,med,low}<='b000000110000;9:{high,med,low}<='b000000110000;10:{high,med,low}<='b000000110000;11:{high,med,low}<='b000000110000;12:{high,med,low}<='b000000110000;13:{high,med,low}<='b000000110000;14:{high,med,low}<='b000000100000; //中音215:{high,med,low}<='b000000100000; //持续2个时钟节拍16:{high,med,low}<='b000000110000; //中音"3"17: {high,med,low}<='b000000110000; //发2个时钟节拍18:{high,med,low}<='b000000100000; //中音219:{high,med,low}<='b000000100000; //中音220:{high,med,low}<='b000000010000; //中音"1"21:{high,med,low}<='b000000010000;22:{high,med,low}<='b000000010000;23:{high,med,low}<='b000000010000;24:{high,med,low}<='b000000010000;25:{high,med,low}<='b000000010000;26:{high,med,low}<='b000000010000;27:{high,med,low}<='b000000010000;28:{high,med,low}<='b000000010000;29:{high,med,low}<='b000000010000;30:{high,med,low}<='b000000010000;31:{high,med,low}<='b000000010000;32:{high,med,low}<='b000000000110;//低633:{high,med,low}<='b000000000110;34:{high,med,low}<='b000000010000;//中音"1"35:{high,med,low}<='b000000010000;36: {high,med,low}<='b000000100000; //中2 有6个37:{high,med,low}<='b000000100000;38:{high,med,low}<='b000000100000;39:{high,med,low}<='b000000100000;40:{high,med,low}<='b000000100000;41:{high,med,low}<='b000000100000;42:{high,med,low}<='b000000110000; //中音343:{high,med,low}<='b000000110000;44:{high,med,low}<='b000000100000; //中音"2"45:{high,med,low}<='b000000100000;46:{high,med,low}<='b000000010000; //中音"1"47:{high,med,low}<='b000000010000;48:{high,med,low}<='b000000000110; //低音"6"49:{high,med,low}<='b000000000110;50:{high,med,low}<='b000000010000; //中音"1"51:{high,med,low}<='b000000010000;52:{high,med,low}<='b000000000101; //低音"5"53:{high,med,low}<='b000000000101; //低音"5"54: {high,med,low}<='b000000000101;55:{high,med,low}<='b000000000101;56:{high,med,low}<='b000000000101; //低音"5"57:{high,med,low}<='b000000000101;58:{high,med,low}<='b000000000101;59:{high,med,low}<='b000000000101;60:{high,med,low}<='b000000000101;61:{high,med,low}<='b000000000101;62:{high,med,low}<='b000000000101;63:{high,med,low}<='b000000000101;64:{high,med,low}<='b000000000101;65:{high,med,low}<='b000000000101;66:{high,med,low}<='b000000000101;67:{high,med,low}<='b000000000101;68:{high,med,low}<='b000000110000; //中音"3"69:{high,med,low}<='b000000110000;70:{high,med,low}<='b000000100000; //中音"2"71:{high,med,low}<='b000000100000;72:{high,med,low}<='b000000110000; //中音"3"73:{high,med,low}<='b000000110000; //中音"3"74:{high,med,low}<='b000000110000; //中音"3"75:{high,med,low}<='b000000110000; //中音"3"76:{high,med,low}<='b000000110000; //中音"3"77:{high,med,low}<='b000000110000; //中音"3"78:{high,med,low}<='b000000110000; //中音"3"79:{high,med,low}<='b000000110000; //中音"3"80:{high,med,low}<='b000000110000; //中音"3"81://中音"3"82:{high,med,low}<='b000000100000; //中音"2"83:{high,med,low}<='b000000100000;84:{high,med,low}<='b000000110000; //中音"3"85:{high,med,low}<='b000000110000; //中音"3"86:{high,med,low}<='b000000100000; //中音"2"87:{high,med,low}<='b000000100000; //中音"2"88:{high,med,low}<='b000000010000; //中音"1"{high,med,low}<='b000000010000; //中音"1"90:{high,med,low}<='b000000010000; //中音"1"91:{high,med,low}<='b000000010000; //中音"1"92:{high,med,low}<='b000000010000; //中音"1"93:{high,med,low}<='b000000010000; //中音"1"94:{high,med,low}<='b000000010000; //中音"1"95:{high,med,low}<='b000000010000; //中音"1"96://中音"1"97:{high,med,low}<='b000000010000; //中音"1"98:{high,med,low}<='b000000010000; //中音"1"99:{high,med,low}<='b000000010000; //中音"1"100:{high,med,low}<='b000000010000; //中音"1"101:{high,med,low}<='b000000010000; //中音"1"102:{high,med,low}<='b000000010000; //中音"1"103:{high,med,low}<='b000000010000;104:{high,med,low}<='b000000010000; //中音"1"105:{high,med,low}<='b000000000110; //低音"6"106:{high,med,low}<='b000000000110; //低音"6"107:{high,med,low}<='b000000010000; //中音"1"108:{high,med,low}<='b000000010000; //中音"1"109:{high,med,low}<='b000000100000; //中音"2"110:{high,med,low}<='b000000100000; //中音"2"111:{high,med,low}<='b000000100000; //中音"2"112:{high,med,low}<='b000000100000; //中音"2"113:{high,med,low}<='b000000100000; //中音"2"114:{high,med,low}<='b000000100000; //中音"2"115:{high,med,low}<='b000000110000; //中音3116:{high,med,low}<='b000000110000;117:{high,med,low}<='b000000100000; //中音"2"118:{high,med,low}<='b000000100000;119:{high,med,low}<='b000000010000; //中音"1"120:{high,med,low}<='b000000010000;121:{high,med,low}<='b000000000110; //低音"6"122:{high,med,low}<='b000000000110;123:{high,med,low}<='b000000010000; //中音"1"124:{high,med,low}<='b000000010000;125:{high,med,low}<='b000000100000; //中音"2"126:{high,med,low}<='b000000100000; //中音"2"127:{high,med,low}<='b000000100000; //中音"2"128:{high,med,low}<='b000000100000; //中音"2"129:{high,med,low}<='b000000100000; //中音"2"130:{high,med,low}<='b000000100000; //中音"2"131:{high,med,low}<='b000000100000; //中音"2"132:{high,med,low}<='b000000100000; //中音"2"133:{high,med,low}<='b000000100000; //中音"2"134:{high,med,low}<='b000000100000; //中音"2"135:{high,med,low}<='b000000100000; //中音"2"136:{high,med,low}<='b000000100000; //中音"2"137:{high,med,low}<='b000000100000; //中音"2"138:{high,med,low}<='b000000100000; //中音"2"139:{high,med,low}<='b000000100000; //中音"2"140:{high,med,low}<='b000000100000; //中音"2"141:{high,med,low}<='b000000110000; //中音"3"142:{high,med,low}<='b000000110000; //持续2个时钟节拍143:{high,med,low}<='b000000100000;//中音2144:{high,med,low}<='b000000100000; //持续2个时钟节拍145:{high,med,low}<='b000000110000; //中音"3"146:{high,med,low}<='b000000110000; //发10个时钟节拍147:{high,med,low}<='b000000110000;148:{high,med,low}<='b000000110000;149:{high,med,low}<='b000000110000; endcaseendendmodule //模块结束7、取码模块源代码和顶层模块如下://取码模块,从song模块取得数码管显示部分的位码和段码modulequma(high,med,low,clk_1mhz,dig,duan );input [3:0] high,med,low;input clk_1mhz;reg[7:0] dig;output [7:0]dig;//定义输出八位位码reg [7:0] duan;output [7:0] duan;//定义用于输出的段码的代码always @(posedge clk_1mhz)//扫描high,med,low三个寄存器的值,取出位码和段码的代码beginif (high!=0)begin dig<=8'b11111011;case (high)1:duan<=8'b00000001;2:duan<=8'b00000010;3:duan<=8'b00000011;4:duan<=8'b00000100;5:duan<=8'b00000101;6:duan<=8'b00000110;7:duan<=8'b00000111;endcaseendelse if (med!=0)// 如果med的值不为0,则只输出med 的值begin dig<=8'b11111101;case (med )1:duan<=8'b00000001;2:duan<=8'b00000010;3:duan<=8'b00000011;4:duan<=8'b00000100;5:duan<=8'b00000101;6:duan<=8'b00000110;7:duan<=8'b00000111;endcaseendelse if (low!=0)//如果low的值不为0,则只输出low的值begin dig<=8'b11111110;case (low )1:duan<=8'b00000001;2:duan<=8'b00000010;3:duan<=8'b00000011; 4:duan<=8'b00000100; 5:duan<=8'b00000101; 6:duan<=8'b00000110; 7:duan<=8'b00000111;endcase endend endmodule8、disp:显示模块,每位输出转换为七段数码管显示。