基于FPGA的电子琴制作Word文件下载.docx
《基于FPGA的电子琴制作Word文件下载.docx》由会员分享,可在线阅读,更多相关《基于FPGA的电子琴制作Word文件下载.docx(15页珍藏版)》请在冰豆网上搜索。
1.1课题分析
随着电子技术的高速发展,由于FPGA/CPLD具有高速、高可靠性、串并行工作方式等突出优点,所以在电子设计中受到广泛的应用,并且它代表着未来EDA设计的方向。
FPGA/CPLD的设计采用了高级语言,例如VHDL语言,AHDL语言。
从而进一步打破了软硬件之间的界限,加速了产品的开发过程,缩短了设计周期。
所以采用FPGA/CPLD取代传统的标准集成电路、接口电路已经成为电子技术发展的必然趋势。
EDA(电子设计自动化)代表了当今电子设计技术的最新发展方向,它的基本特征是:
设计人员按照“自顶向下”的设计方法,对整个系统进行方案设计和功能划分,系统的关键电路用一片或几片集成电路(FPGA/CPLD)实现。
电子琴是数字电路中的一个典型应用。
在实际的硬件设计中用到的器件非常多,连线比较复杂,同时会产生比较大的延时,从而造成测量误差较大,可靠性不好。
以EDA工具作为开发手段,运用VHDL硬件描述语言将使整个系统大大简化,提高了电子琴整体的性能和可靠性。
1.2VHDL语言和QuartusⅡ环境简介
1.2.1VHDL语言简介
VHDL是超高速集成电路硬件描述语言,是一种用于电路设计的高级语言。
它出现于80年代后期,最初是由美国国防部开发出来的,是为了供美军用来提高设计的可靠性和缩减开发周期的一种使用范围较小的设计语言。
VHDL主要是应用在数字电路的设计中。
目前,它在中国的应用多数是用在FPGA/CPLD/EPLD的设计中,同时也被一些实力较为雄厚的单位用来设计ASIC。
VHDL具有多层次描述系统硬件功能的能力,支持自顶向下和基于库的设计特点。
其开发流程:
在顶层用方框图或硬件语言对电路的行为进行描述后,进行系统仿真验证和纠错。
再用逻辑综合优化工具生成具体的门级逻辑电路的网表。
然后通过适配器将网表文件配置于指定的目标器件,产生最终下载文件或配置文件。
最后把适配后生成的下载或配置文件通过编程器或编程电缆下载到具体的FPGA/CPLD器件中去,以便进行硬件调试和验证,而实现可编程的专用集成电路ASIC的设计。
VHDL主要用于描述数字系统的结构,行为,功能和接口。
除了含有许多具有硬件特征的语句外,VHDL的语言形式和描述风格与句法是十分类似于一般的计算机高级语言。
VHDL系统设计与其他硬件描述语言相比,VHDL具有更强的行为
表2-1简谱音名与频率的对应关系
表2-2简谱音名与分频系数的对应关系
3.1CycloneⅢ简介
低成本Cyclone®
IIIFPGA是Altera®
Cyclone系列的第三代产品。
CycloneIIIFPGA系列前所未有地同时实现了低功耗、低成本和高性能,进一步扩展了
FPGA在成本敏感大批量领域中的应用。
采用台湾半导体生产公司(TSMC)的65-nm低功耗(LP)工艺技术,CycloneIII器件对芯片和软件采取了更多的优化措施,在所有65-nmFPGA中是功耗最低的,在对成本和功耗敏感的大量应用中,提供丰富的特性推动宽带并行处理的发展。
CycloneIII系列包括8个型号,容量在5K至120K逻辑单元(LE)之间,最多534个用户I/O引脚。
如表1所示,CycloneIII器件具有4-Mbit嵌入式存储器、288个嵌入式18x18乘法器、专用外部存储器接口电路、锁相环(PLL)以及高速差分I/O等。
CycloneIIIFPGA系列为成本敏感的各种大批量应用提供多种器件和封装选择。
CycloneIII器件结温在-40°
C至125°
C之间,有三种温度等级,支持各种工作环境。
3.2按键模块及其功能
设计初期采用的是开关控制,效果并不好,后期将采用键盘进行控制已充分模拟电子琴的弹奏效果。
3.3显示模块及其功能
3个LED灯显示低中高音。
一个共阴极的数码管显示对应简谱值。
其中共阴极的数码管如图所示:
4.1系统的流程
本设计采用Altera公司的EDA软件系统EP2C8Q208C8来完成。
采用自顶向下的设计方法。
图4-1为其软件流程图:
4.1系统的流程图
软件设计采用结构化程序设计方法,功能模块各自独立,实际上在设计中将键盘输入和乐曲存储放在了一个音乐输入模块中,软件设计的核心部分是数控分频器,键盘输入和乐曲储存都是提供给它相应的分频比。
对输入的系统时钟进行
分频,得到50%占空比的信号,最终输出的就是想得到的音阶的频率。
4.2顶层设计模块
本系统主要由三个功能模块组成:
music.vhd、speaker.vhd和tone.vhd。
系统顶层设计原理图如图4-2所示,该系统有4个输入,3个输出端口。
其原理图如4-2:
4.2顶层设计模块organ6.vhd
4.3音频播放模块
音频播放模块通过对系统时钟(50MHz)按特定的分频系数进行分频,得到音符的频率输入到喇叭中。
为了更好的驱动喇叭,有两种方法可以获得占空比约为50%的方波。
方案一为通过对系统分频到2倍频程然后再通过二分频获得占空比50%的方波。
我用的是方案二,通过vhdl代码内部约束,在分频过程中通过
not
语句实现时钟信号的翻转,具体如下:
div_clk:
process(clk)
beginif(clk'
eventandclk='
1'
)thenif(tone_index=0)thenclk_tone<
='
0'
;
variablecount:
integerrange0to200000:
=1;
variablestop:
elsif(count<
=tone_index)thencount:
=count+1;
elsecount:
=0;
clk_tone<
=notclk_tone;
endif;
if(clk'
andcount=0)thenclk_tone<
spks<
=clk_tone;
endprocess;
endbhv;
4.3speaker.vhd
4.4音调发生模块
通过case语句对外部输入产生的二进制分情况对号入座,此模块输出的high_tone和hex0直接驱动LED灯和数码管的显示。
而输出的分频系数输入到speaker.vhd模块中。
4.4tone.vhd
4.5音乐输入模块
音乐输入分为自动输入和手动输入两部分,由auto键控制。
乐谱通过case语句存在此模块中,通过mux21切换两首歌曲。
通过外部输入转换到对应9位二进制编码,2位用于区分低中高音,7位分别表示1-2-3-4-5-6-7,譬如100000001表示高音的1。
4.5music.vhd
第五章硬件系统测试
通过数据线下载到FPGA开发板上,外接喇叭,数码管,开关,按键和LED灯。
经测试,效果良好。
6.1实验中遇到的问题和解决过程
1.开始准备做这个项目的时候遇到的第一个问题就是电子琴的发音原理,通过查阅网上资料得知电子琴每个音都有自己特定的频率,从而想到通过计数器分频的方法,通过扬声器发出这些特定频率的方波。
2.乐谱的存储过程中,由于每个音的节拍不同,需要响的时间长短也不同,由于大部分电子琴演奏的歌曲每个音符所需的最短时间是1/4节拍,故设定play_speed为16Hz。
3.外接喇叭时,对空引脚的分配过程中出现了很多问题导致喇叭无声,通过阅读FPGA自带文档的数据手册,手动分配引脚解决。
1.对于连续相同的两个音,除利用1/4节拍的休止符外,考虑可以用与时钟相与的方法,选取合适的时钟频率相与,制造出人耳可分辨又不影响节奏的间隔。
2.开关输入只是一种模拟的手段,考虑到开发板是上可外接键盘,故可以使用键盘来弹奏乐曲,可以更加真实地模拟弹奏的场景。
3.利用VGA插口可以通过显示器显示,已达到更加完美的效果。
附录Ⅰ:
Part1:
顶层原理图
Part2:
音频播放模块(speaker.vhd)
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityspeakeris
port(clk:
instd_logic;
tone_index:
inintegerrange0to200000;
spks:
outstd_logic);
endentity;
architecturebhvofspeakerissignalclk_tone:
std_logic:
begin
div_clk:
Part3:
音调发生模块(tone.vhd)libraryieee;
entitytoneis
port(index:
instd_logic_vector(8downto0);
outintegerrange0to200000;
high_tone:
outstd_logic_vector(2downto0);
hex0:
outstd_logic_vector(6downto0));
endentity;
architecturebhvoftoneis
begin
process(index)
begincaseindexiswhen"
000000000"
=>
tone_index<
=0;
high_tone<
="
001"
hex0<
1111111"
--nullwhen"
000000001"
=191110;
1111001"
--1when"
000000010"
=170265;
0100100"
--2
when"
000000100"
=151685;
0110000"
--3when"
000001000"
=143172;
0011001"
--4when"
000010000"
=127551;
0010010"
--5when"
000100000"
=113636;
0000010"
--6when"
001000000"
=101239;
1111000"
--7------------------------------------------------------------------------when"
010000000"
010"
010000001"
=95557;
--2when"
010000010"
=85131;
010000100"
=75844;
010001000"
=71586;
010010000"
=63776;
010100000"
=56818;
011000000"
=50620;
100000000"
100"
100000001"
=47778;
100000010"
=42566;
100000100"
=36192;
100001000"
=35793;
100010000"
=31888;
100100000"
=28409;
--6
101000000"
=25310;
--7whenothers=>
null;
endcase;
Part4:
音乐输入模块(music.vhd)
entitymusicis
auto:
--selectmodemux21:
--selectsongkey_index:
music_index:
outstd_logic_vector(8downto0));
architecturebhvofmusicis
signalnote1:
integerrange0to500;
--thelengthofsong1
signalnote2:
--thelengthofsong2signalclk_speed:
std_logic;
--theshortestplay-speedbegin
div:
process(clk,auto)
variablecount:
integerrange0to5000000;
beginif(auto='
)thenif(clk'
)thenif(count<
3125000)thencount:
clk_speed<
=notclk_speed;
song1:
process(clk_speed,note1)
beginif(clk_speed'
eventandclk_speed='
)thenif(note1=127)thennote1<
elsenote1<
=note1+1;
if(clk_speed'
)thenif(note2=127)thennote2<
elsenote2<
=note2+1;
if(auto='
)then--automaticmodeif(mux21='
)thencasenote1is--song1:
twotigerswhen0=>
music_index<
--1when1=>
--1when2=>
--1when3=>
--1when4=>
--2when5=>
--2when6=>
--2when7=>
when8=>
--3when9=>
--3when10=>
--3when11=>
--3when12=>
--1when13=>
--1when14=>
--1when15=>
--1------------------------------------when16=>
--1when17=>
--1when18=>
--1when19=>
--1when20=>
--2when21=>
--2when22=>
--2when23=>
--2when24=>
--3when25=>
--3when26=>
--3when27=>
--3when28=>
--1
when29=>
--1when30=>
--1when31=>
--1------------------------------------when32=>
--3when33=>
--3when34=>
--3when35=>
--3when36=>
--4when37=>
--4when38=>
mus