基于FPGA的多功能电子琴设计与实现.docx
《基于FPGA的多功能电子琴设计与实现.docx》由会员分享,可在线阅读,更多相关《基于FPGA的多功能电子琴设计与实现.docx(35页珍藏版)》请在冰豆网上搜索。
基于FPGA的多功能电子琴设计与实现
西南科技大学
电子专业综合设计报告
设计名称:
基于FPGA的多功能电子琴的设计与实现
姓名:
学号:
班级:
指导教师:
起止日期:
2013年11月22日-2013年12月10日
西南科技大学信息工程学院制
综合设计任务书
学生班级:
电子1001学生姓名:
学号:
设计名称:
基于FPGA的多功能电子琴的设计与实现
起止日期:
2013.11.22-2013.12.10指导教师:
设计要求:
1、按键对应不同的音符.可以通过按键进行演奏;
2、可以通过按键控制实现自动播放已经存储的曲子;
3、可以通过按键控制实现单曲循环播放和多曲循环播放。
综合设计学生日志
时间
设计内容
2013.年11月22日
安装QuartusII编程软件.同时熟悉并掌握其相应的编程编译、引脚封装等过程。
2013年11月23日至2013年11月24日
实现按键对应不同音符.同时可以通过按键进行演奏的相关程序的编译:
编写按键模块。
2013年11月25日至2013年11月28日
编写通过按键的控制实现自动播放已经存储的曲子:
编写曲目1、曲目2模块、曲目1和曲目2循环播放模块。
2013年11月29日
编写顶层模块.并调试.下载板子上进行验证及预演
2013年11月30日至2013年12月1日
改进和完善程序
2013年12月2日
撰写课程设计报告
基于FPGA的多功能电子琴的设计与实现
摘要:
随着科学技术的日新月异.人们的生活也在发生在变化.电子产品也随之增多.比如现在流行的电子琴.已经逐渐代替了曾经的手动风琴了。
文章中所介绍的多功能电子琴的设计在QuartusII平台上.采用VerilogHDL语言和模块化的设计方法.设计出一个能够通过按键控制不同的音符.同时也可以通过按键进行演奏已经存储的曲子的多功能电子琴。
本系统主要由五个个模块组成:
顶层模块.曲目1模块.曲目2模块.按键模块.曲目循环播放模块。
关键词:
FPGA;电子琴;VerilogHDL;音符
FPGA-baseddesignandimplementationofmulti-organ
Abstract:
Withthedevelopmentofscienceandtechnology,alsooccursinpeople'sliveschange,electronicproductsalsoincrease,suchasthenowpopularorgan,hasreplacedtheformermanualorgan.MultifunctionkeyboarddesignasdescribedinthearticleontheQuartusIIplatform,usingVerilogHDLlanguageandmodulardesignmethod,designabuttoncontrolthroughdifferentnote,youcanalsoplaymusicalreadystoredbykeysmultifunctionkeyboard.Thesystemconsistsoffivemodules:
thetop-levelmodule,amoduletracks,track2modules,keymodule,trackloopmodule.
Keywords:
FPGA,Keyboard,VerilogHDL,Note
一、设计目的和意义
目的:
1.1、在掌握计算机组成原理理论相关的基础上.了解EDA技术.掌握VerilogHDL硬件描述语言的设计方法和思想;
1.2、培养综合运用知识和独立开展实践创新的能力;
1.3、深入学习VerilogHDL.了解其编程环境;
1.4、学会运用QuartusII等编程仿真软件;
1.5将硬件语言编程与硬件实物功能演示相结合.加深理解VerilogHDL的学习。
意义:
电子琴由于操作相对比较简单.并且能够模拟几乎所有传统乐器的音色.因而深受广大消费者的喜爱。
近年来.在数字系统的设计领域融入了一种新型的设计技术:
数字系统设计的自动化技术EDA(ElectronicDesignAutomation)。
该技术优越之处在于系统设计的效率高、保密性强、集成度好、易于修改和实现等。
因此.一跃成为当下数字系统设计领域的主流技术.并被越来越广泛地应用到相关领域中.其中.被应用到电子琴的设计与实现中去就是一个相当重要的尝试及应用。
二、控制要求
2.1、软件:
QuartusII等编程仿真软件;
2.2、硬件:
FPGA开发板。
三、设计方案论证
方案一:
采用单片机实现.通过软件编程.仿真后将程序用编程器写入到单片机芯片上.该方案成本低.稳定度也比较好.但外围电路多.特别是播放音乐时需要用到大容量的外部存储器.这样就增加了编程难度.调试不够直观.也不够灵活方便。
方案二:
采用可编程逻辑器件(FPGA)制作.将所有器件集成在一块芯片上.大大减小了电子琴的体积.用VerilogHDL编程实现时更加方便.而且易于进行功能扩展.并可调试仿真。
综上.本次课程设计选择方案二
四、系统设计
1、总体实现方案:
1.1简易电子琴的设计通过软硬件结合实现.硬件系统包括主控器芯片、9个按键、蜂鸣器等.软件资源包括编写VerilogHDL程序的仿真软件QuartusII。
电子琴有按键代替琴键的弹奏功能、自动播放功能、循环播放功能。
1.2整个程序总共分5个模块:
顶层模块.曲目1:
bell模块.曲目2:
bell2模块.按键模块:
buzzer.曲目循环播放模块:
bell_bell2.整个方案总共用了9个按键(k2-k8).按键k2-k8作为琴键.通过这七个按键键入不同的音阶。
主模块中k9、k10两个按键用于选择是自动播放还是弹奏曲目.令mm=(k10、k9).用mm值的不同选择调用不同模块。
如果mm=11.则程序调用按键模块;如果mm=01.则调用曲目1模块.播放曲目1;如果mm=10.则调用曲目2模块.播放曲目2;如果mm=00.则调用循环模块。
2、原理框图
9个按键:
k2-k10;k2-k8控制按键buzzer模块.k10、k9是选择按键.当k10k9=11.选择buzzer模块.输出out3;当k10k9=01.选择bell模块.输出out1;当k10k9=10.选择bell2模块.输出out2;当k10k9=00.选择bell_bell2模块.输出out4。
3、输入输出
4、音符与音频
乐曲中不同的音符实质上表示的是不同频率的声音。
只要产生不同频率的脉冲.再通过喇叭等播放出来即可。
又由于方波容易用定时器产生.故使用方波脉冲。
4.1要产生音频脉冲:
1、算出某一音频的脉冲的周期(1/频率)
2、然后将此周期除以2.即为半周期的时间。
3、利用定时器.计时这个半周期的时间.每当计时到后.就将输出脉冲的I/O反相。
4、重复计时此半周期的时间再对I/O反相.就可以在I/O脚上得到此频率的脉冲。
例如.频率为523Hz.其周期为1/523 S=1912uS.因此只要令计数器计时956.在每计数956次时就将I/O反接.就可得到中音Do(532Hz)。
4.2音阶及其对应频率
音阶
频率/Hz
周期/us
半周期/us
分频数
中音
1
523
1912
956
11472
2
578
1684
842
10380
3
659
1518
759
9104
4
698
1432
716
8595
5
784
1276
638
7653
6
880
1136
568
6818
7
988
1012
506
6073
五、设计结果及分析
5.1功能仿真
5.2所有引脚锁定
5.3总体电路图
5.3分析
仿真结果;设置输入信号k2-k10为低电平有效.因此.当不按下按键时.所有的按键均为高电平。
此时k10~key9=11.即mm=11.即在按键模块.输出out3连接输出端outclk;当按下k10时.即mm=01.此时选择曲目1模块.输出out1连接到输出端outclk;当按下k9时.即mm=10.此时选择曲目2模块.输出out2连接输出端outclk;当同时按下k9k10时.输出out4连接输出端outclk。
5.3.1硬件测试结果:
在时序验证后下载.通过硬件测试.实验达到预期效果.当mm(k10-k9)=11时.通过k2-k8这7个按键的键入蜂鸣器可以发出Do、re、mi、fa、so、la、xi的七个音阶的音.即表示了电子琴的按键弹奏功能;当mm=01时.播放了第一首歌;mm=10时.播放了第二首歌;当mm=00时.循环播放。
通过硬件的测试.所有的设计目标均实现。
5.3.2对结果和结论的问题讨论:
实验过程中.程序刚一下载.蜂鸣器就开始发声音.后来.经过查证.蜂鸣器的驱动是低电平有效.因此.最开始时.将蜂鸣器初始化为高电平。
实验结果中七个音节的区分不是特别明显.因为音节的频率都相差不是很大。
结束语
通过这近一个月天的学习和努力.让我收获颇多。
刚开始的时候还不知道如何下手.并且对所用的软件QuartusⅡ不熟悉.因为之前所用的软件是XilinxISE.但是通过一次次的努力和摸索.发现其实这两款软件还是有很多共同的地方.自己对新的软件应用也越来越得心应手了。
此外.在这次的课程设计中.我越来越认识到一点.编程对项目实现有着至关重要的作用.我们在硬件开发的过程中必须重视编程.将编程看作是完善开发的不可缺少的一部分。
在一次次的反复设计、论证和测试中.不仅提高了逻辑分析能力、全面分析问题的能力.还提升了发现问题、解决问题的能力.不懂的地方在经过思考还是无果的情况下.就要向他人请教了.他人一点小小的点拨.会为你带来灵感.这也将是问题的解决方法。
虽然设计过程比较繁琐.大大小小也出现了许多问题.但这却磨练了我的意志。
通过各方面的学习.使我的知识面进一步拓宽了。
通过这次课程设计.我不但熟悉了quartusII软件.也了解了开发的最基本流程和方法.也进一步加深了对VerilogHDL编程语言的理解.最重要的是锻炼了我独立思考和分析的逻辑能力.通过至顶向下的设计方法.一步步实现.然后将整个设计串套起来.是我对设计的流程以及编程有了很大的提高。
同时.通过本次课程设计.我也发现了自己的不足.例如:
逻辑分析能力不突出.编程能力不足.解决问题的能力不足.不是特别细心.这些使我认识到在以后的学习中在这些方面要多加努力.加以改进.提升自我能力。
我相信通过这次课程设计的学习.对我以后的学习和工作都有着十分重要的影响和作用。
参考文献(递增引用.引用相关内容)
【1】刘桂华.《基于FPGA的现代数字系统设计》.西安电子科技大学出版社第1-101页
【2】袁海林.基于FPGA的具有存储功能的电子琴的设计[J].中国信息科技.2007.19:
88-89
【3】曹曼.基于FPGA的电子琴设计.科技传播.2012-03-08
【4】张亮.基于FPGA的电子琴的设计[J].电子技术.2007.
(2)
【5】华清远见嵌入式培训中心编著《FPGA应用开发入门与典型实例》人民邮电出版社第145-161页
附录(程序、电路图等)
1、顶层模块程序:
moduledianziqin(inclk,outclk,k2,k3,k4,k5,k6,k7,k8,k9,k10);
inputinclk;
inputk2,k3,k4,k5,k6,k7,k8,k9,k10;
outputoutclk;
regoutclk,clk_6M;
reg[3:
0]c;
wireout1,out2,out3;
wire[1:
0]key;
reg[1:
0]mm;
assignkey={k10,k9};//由按键拼键为变量key
//调用子调块
buzzerm1(
.inclk(inclk),
.k2(k2),
.k3(k3),
.k4(k4),
.k5(k5),
.k6(k6),
.k7(k7),
.k8(k8),
.beep3(out3)
);
bellm2(
.inclk(inclk),
.beep1(out1)
);
bell2m3(
.inclk(inclk),
.beep2(out2)
);
bell_bell2m4(.inclk(inclk),
.beep4(out4)
);
always@(posedgeinclk)
begin
if(c<4'd8)
c<=c+4'd1;
else
begin
c<=4'd0;
clk_6M<=~clk_6M;
end
end
always@(posedgeclk_6M)//在时钟的上升沿检测是否有按键按下
begin
if(key==2'b01)
mm<=2'b01;
elseif(key==2'b10)
mm<=2'b10;
elseif(key==2'b11)
mm<=2'b11;
elseif(key==2’b00)
mm<=2'b00;
elsemm<=2’bzz;
end
always@(mm)//按键响应
begin
if(mm==2'b01)
outclk<=out1;
elseif(mm==2'b10)
outclk<=out2;
elseif(mm==2'b11)
outclk<=out3;
elseif(mm==2’b00)
outclk<=out4;
elseoutclk<=0;
end
endmodule
2、按键模块:
modulebuzzer(inclk,k2,k3,k4,k5,k6,k7,k8,beep3);
inputinclk,k2,k3,k4,k5,k6,k7,k8;
outputbeep3;
wire[6:
0]key_code;
reg[3:
0]c;
regclk_6M;
regbeep_r;
reg[15:
0]count;
reg[15:
0]count_end;
parameterDo=7'b1111110;
re=7'b1111101;
mi=7'b1111011;
fa=7'b1110111;
so=7'b1101111;
la=7'b1011111;
si=7'b0111111;
assignkey_code={k8,k7,k6,k5,k4,k3,k2};
assignbeep3=beep_r;//输出音乐
always@(posedgeinclk)
begin
if(c<4'd8)
c<=c+4'd1;
else
begin
c<=4'd0;
clk_6M<=~clk_6M;
end
end
always@(posedgeclk_6M)//分频模块.得出乐谱
begin
count<=count+16'd1;
if(count_end==0)
beep_r<=1;//计数器加1
elseif(count==count_end)
begin
count<=16'd0;//计数器清零
beep_r<=!
beep_r;
end
end
always@(posedgeclk_6M)//状态机.根据按键状态.选择不同的音符输出
begin
case(key_code)
Do:
count_end<=16'd3822;
re:
count_end<=16'd3405;
mi:
count_end<=16'd3034;
fa:
count_end<=16'd2865;
so:
count_end<=16'd7802;
la:
count_end<=16'd6802;
si:
count_end<=16'd6060;
default:
count_end<=16'h0;
endcase
end
endmodule
3、曲目1模块:
modulebell(inclk,beep1);
inputinclk;//系统时钟
outputbeep1;//蜂鸣器输出端
reg[3:
0]high,med,low;
reg[15:
0]origin;
regbeep_r;//寄存器
reg[7:
0]state;
reg[15:
0]count;
assignbeep1=beep_r;//输出音乐
regclk_6MHz;//时钟频率6MHz
reg[2:
0]cnt1;
always@(posedgeinclk)
begin
if(cnt1<3'd8)
cnt1<=cnt1+3'b1;
else
begin
cnt1<=3'b0;
clk_6MHz<=~clk_6MHz;
end
end
regclk_4Hz;//时钟频率4Hz
reg[24:
0]cnt2;
always@(posedgeinclk)
begin
if(cnt2<25'd13000000)//
cnt2<=cnt2+25'b1;
else
begin
cnt2<=25'b0;
clk_4Hz<=~clk_4Hz;
end
end
always@(posedgeclk_6MHz)
begin
count<=count+1'b1;//计数器加1
if(count==origin)
begin
count<=16'h0;//计数器清零
beep_r<=!
beep_r;//输出取反
end
end
always@(posedgeclk_4Hz)
begin
case({high,med,low})
12'b000000010000:
origin=11466;//mid1
12'b000000100000:
origin=10216;//mid2
12'b000000110000:
origin=9101;//mid3
12'b000001000000:
origin=8590;//mid4
12'b000001010000:
origin=7653;//mid5
12'b000001100000:
origin=6818;//mid6
12'b000000000101:
origin=14447;//low5
endcase
end
always@(posedgeclk_4Hz)//歌曲1
begin
if(state==63)state=0;//计时.以实现循环演奏
else
state=state+1;
case(state)
0,1:
{high,med,low}=12'b000000010000;//mid1
2,3:
{high,med,low}=12'b000000100000;//mid2
4,5:
{high,med,low}=12'b000000110000;//mid3
6,7:
{high,med,low}=12'b000000010000;//mid1
8,9:
{high,med,low}=12'b000000010000;//mid1
10,11:
{high,med,low}=12'b000000100000;//mid2
12,13:
{high,med,low}=12'b000000110000;//mid3
14,15:
{high,med,low}=12'b000000010000;//mid1
16,17:
{high,med,low}=12'b000000110000;//mid3
18,19:
{high,med,low}=12'b000001000000;//mid4
20,21,22,23:
{high,med,low}=12'b000001010000;//mid5
24,25:
{high,med,low}=12'b000000110000;//mid3
26,27:
{high,med,low}=12'b000001000000;//mid4
28,29,30,31:
{high,med,low}=12'b000001010000;//mid5
32:
{high,med,low}=12'b000001010000;//mid5
33:
{high,med,low}=12'b000001100000;//mid6
34:
{high,med,low}=12'b000001010000;//mid5
35:
{high,med,low}=12'b000001000000;//mid4
36,37:
{high,med,low}=12'b000000110000;//mid3
38,39:
{high,med,low}=12'b000000010000;//mid1
40:
{high,med,low}=12'b000001010000;//mid5
41:
{high,med,low}=12'b000001100000;//mid6
42:
{high,med,low}=12'b000001010000;//mid5
43:
{high,med,low}=12'b000001000000;//mid4
44,45:
{high,med,low}=12'b000000110000;//mid3
46,47:
{high,med,low}=12'b000000010000;//mid1
48,49:
{high,med,low}=12'b000000100000;//mid2