乐器演奏电路设计vhdl.docx
《乐器演奏电路设计vhdl.docx》由会员分享,可在线阅读,更多相关《乐器演奏电路设计vhdl.docx(17页珍藏版)》请在冰点文库上搜索。
乐器演奏电路设计vhdl
重庆交通大学计算机与信息学院
设计性实验报告
班级:
通信工程专业07级2班
姓名(学号):
实验项目名称:
乐器演奏电路设计
实验项目性质:
设计性
实验所属课程:
VHDL
实验室(中心):
指导教师:
徐雯娟
实验完成时间:
2009年12月13日
一、实验目的
1,了解普通扬声器的工作原理;
2,了解QuartusII4.1中提供了宏功能元件库mega_lpm。
3,使用LPM_ROM参数化存储模块。
二、实验内容及要求
要求能够演奏出《友谊地久天长》的曲调或可另选一段较完整的曲调。
(扩展要求:
能够从数码管上显示出当前曲调的简谱和频率)
三、实验原理
1,音符的频率:
可以由上图中的U3获得,这是一个数控分频器。
由其clk端输入一具有较高频率(这里是12MHz)的信号,通过U3分频后由SPKOUT输出,U3对clk输入信号的分频比由11位预置数Tone[10..0]决定。
SPKOUT的输出频率将决定每一音符的音调,这样,分频计数器的预置值Tone[10..0]与SPKOUT的输出频率,就有了对应关系。
2,音符的持续时间:
须根据乐曲的速度及每个音符的节拍数来确定,图中模块U2的功能首先是为U3提供决定所发音符的分频预置数,而此数在U3输入口停留的时间即为此音符的节拍值。
模块U2是乐曲简谱码对应的分频预置数查表电路,其中设置了乐曲全部音符所对应的分频预置数(一共8个),每一音符的停留时间由音乐节拍和音调发生器模块U1的clk的输入频率决定(如为4Hz),这8个值的输出由对应于U2的3位输入值Index[2..0]确定。
3,乐谱的存储:
在U1中设置了一个7位二进制计数器(计数最大值为65),作为音符数据ROM的地址发生器。
这个计数器的计数频率若选为4Hz,即每一计数值的停留时间为0.25秒,恰为当全音符设为1秒时,四四拍的4分音符持续时间。
随着U1中的计数器按4Hz的时钟速率作加法计数时,即随地址值递增时,音符数据ROM中的音符数据将从ROM中通过ToneIndex[2..0]端口输向U2模块,乐曲就开始连续自然地演奏起来了。
音高频率对照表(徐老师给定发的原频率对照表中频率偏低)
1
2
3
4
5
6
7
低音
261
293
329
349
396
440
493
中音
523
587
659
698
784
880
988
高音
1047
1175
1319
1397
1568
1760
1975
四、实验仪器、材料
1,2MHZ和4HZ的信号源
2,ACEX1KEP1K30TC144—1芯片
3,扬声器
五、方案设计(设计性实验需要,综合性实验无该项)
1,音符的产生:
音符的产生是利用数控分频器模块SPKEAR对输入的时钟信号CLK400KHZ进行分频,预置数为TONE[10..0],然后分频得出频率为CLK/2*(2048-TONE[10..0]),通过控制输入预置数TONE[10..0]来达到不同的输出频率,以达到控制扬声器发出不同的声音。
例如:
当设置预置数TONE[10..0]为1538时,输出SPKEAR频率为396,为低音5。
2,频率的分频:
由于实验给定信号源为12MHZ,不满足数控分频器模块SPKEAR对输入时钟信号的要求,遂其进行30分频(PULSE30),产生0.4MHZ的时钟信号。
3,预置数的产生:
预置数TONE[10..0]由模块TONETAB产生。
模块TONETAB有输入端口INDEX[2..0]送入音符,模块由CASE选择语句产生与INDEX[2..0]输入端口送入的音符相对应的预置数TONE[10..0],也同时产生其音符CODE[2..0]送入音符显示模块DISPCODE,和频谱频率frenquence[9..0]送入频率显示模块DISPFREN。
例如:
当输入端口INDEX[2..0]送入000(为低音5对应的编码),有CAES选择语句产生TONE[10..0]为1538,frenquence[9..0]为396以及CODE[2..0]为101的输出。
4,音符的存储:
音符的持续时间须根据乐曲的速度及每个音符的节拍数来确定。
由存储模块music_rom_data控制,以四分之一节拍为1个单位在LPM_ROM中进行存储音符的编码(例如本实验《友谊地久天长》中频谱共涉及了8个音符,使用3个二进制数分别对其编码进行存储;又有二分之一节拍数的音符存储2个单元,以此类推,直到对整首歌曲的乐谱存储结束)。
存储模块music_rom_data的输出为数控分频器模块TONETAB的输入端INDEX[2..0]。
音符与编码对照表:
音符
5(低音)
1
2
3
5
6
1(高音)
6(低音)
编码
000
001
010
011
100
101
110
111
5,音符的输出驱动:
音符的存储由计数器模块LPM_COUNTE控制。
计数器在时钟CLK4HZ的控制下,没0.25s送出一个6位数值q[5..0],作为存储模块music_rom_data的地址输入端口。
这样便达到每个存储单元以同一频率进行有控制的输出。
6,频谱显示模块DISPCODE和频率显示模块DISPFRENQUENCE有本组另一同学(袁亮)设计。
六、实验过程及原始记录
1,制作存储模块music_rom_data.
(1)定制LPM_ROM初始化数据文件
建立.mif格式文件:
选择File—>New—>MemoryInitializationFile项,选择数据位为256,数据宽度为8,建立.mif格式文件,将歌曲频谱以编码的形式,以四分之一节拍为一单位进行存储。
(其实128位数据位已经够本实验歌曲《友谊地久天长》使用)
形成如下图的数据文件:
(2),定制LPM_ROM元件
①LPM宏功能模块设定
②选择ROM_DATA模块数据线和地址线宽度
③调入ROM初始化数据文件
④LPM_ROM设计完成
生成用于例化的LPM_ROM的VHDL文件music_data_rom.vhd:
LIBRARYieee;
USEieee.std_logic_1164.all;
LIBRARYlpm;
USElpm.lpm_components.all;
ENTITYmusic_data_romIS
PORT(address:
INSTD_LOGIC_VECTOR(5DOWNTO0);
q:
OUTSTD_LOGIC_VECTOR(2DOWNTO0));
ENDmusic_data_rom;
ARCHITECTURESYNOFmusic_data_romIS
SIGNALsub_wire0:
STD_LOGIC_VECTOR(2DOWNTO0);
COMPONENTlpm_rom
GENERIC(
intended_device_family:
STRING;
lpm_width:
NATURAL;
lpm_widthad:
NATURAL;
lpm_address_control:
STRING;
lpm_outdata:
STRING;
lpm_file:
STRING;
lpm_type:
STRING);
PORT(address:
INSTD_LOGIC_VECTOR(5DOWNTO0);
q:
OUTSTD_LOGIC_VECTOR(2DOWNTO0));
ENDCOMPONENT;
BEGIN
q<=sub_wire0(2DOWNTO0);
lpm_rom_component:
lpm_rom
GENERICMAP(intended_device_family=>"ACEX1K",
lpm_width=>3,
lpm_widthad=>6,
lpm_address_control=>"UNREGISTERED",
lpm_outdata=>"UNREGISTERED",
lpm_file=>"music_rom_data.mif",
lpm_type=>"LPM_ROM")
PORTMAP(address=>address,
q=>sub_wire0);
ENDSYN;
2,制作计数器模块COUNTER
实验步骤如上:
生成用于例化的LPM_COUNTER的VHDL文件counter.vhd:
LIBRARYieee;
USEieee.std_logic_1164.all;
LIBRARYlpm;
USElpm.all;
ENTITYcounterIS
PORT(clk_en:
INSTD_LOGIC;
clock:
INSTD_LOGIC;
q:
OUTSTD_LOGIC_VECTOR(5DOWNTO0));
ENDcounter;
ARCHITECTURESYNOFcounterIS
SIGNALsub_wire0:
STD_LOGIC_VECTOR(5DOWNTO0);
COMPONENTlpm_counter
GENERIC(lpm_direction:
STRING;
lpm_port_updown:
STRING;
lpm_type:
STRING;
lpm_width:
NATURAL);
PORT(clk_en:
INSTD_LOGIC;
clock:
INSTD_LOGIC;
q:
OUTSTD_LOGIC_VECTOR(5DOWNTO0));
ENDCOMPONENT;
BEGIN
q<=sub_wire0(5DOWNTO0);
lpm_counter_component:
lpm_counter
GENERICMAP(
lpm_direction=>"UP",
lpm_port_updown=>"PORT_UNUSED",
lpm_type=>"LPM_COUNTER",
lpm_width=>6)
PORTMAP(clk_en=>clk_en,
clock=>clock,
q=>sub_wire0);
ENDSYN;
3,制作数控分频器SPKEAR模块
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYspeakerIS
PORT(CLK:
INSTD_LOGIC;
tone:
INintegerrange0to2048;
spks:
outstd_logic);
ENDspeaker;
ARCHITECTUREONEOFspeakerIS
SIGNALFULL:
STD_LOGIC;
BEGIN
P_REG:
PROCESS(CLK)
VARIABLECNT8:
integerrange0to2048;
BEGIN
IFCLK'EVENTANDCLK='1'THEN
IFCNT8=2048THEN
CNT8:
=tone;
FULL<='1';
ELSECNT8:
=CNT8+1;
FULL<='0';
ENDIF;
ENDIF;
ENDPROCESSP_REG;
P_DIV:
PROCESS(FULL)
VARIABLECNT2:
STD_LOGIC;
BEGIN
IFFULL'EVENTANDFULL='1'THEN
CNT2:
=NOTCNT2;
IFCNT2='1'THENspks<='1';
ELSEspks<='0';
ENDIF;
ENDIF;
ENDPROCESSP_DIV;
ENDONE;
4,制作TONETAB模块
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitytonetabis
port(index:
instd_logic_vector(2downto0);
tone:
outintegerrange0to2048;
frequence:
outintegerrange0to990;
code:
outstd_logic_vector(2downto0));
endentity;
architecturebehave_tonetaboftonetabis
begin
process(index)
begin
caseindexis
when"000"=>frequence<=396;code<="101";tone<=1538;
when"001"=>frequence<=523code<="001";tone<=1666;
when"010"=>frequence<=587;code<="010";tone<=1708;
when"011"=>frequence<=659;code<="011";tone<=1745;
when"100"=>frequence<=784;code<="101";tone<=1794;
when"101"=>frequence<=1047;code<="110";tone<=1821;
when"110"=>frequence<=1175;code<="001";tone<=1857;
when"111"=>frequence<=440;code<="110";tone<=1595;
endcase;
endprocess;
endbehave_tonetab;
5,制定PULSE30模块
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
entitypulse30is
port(clk:
instd_logic;
fout:
outstd_logic);
end;
architecturebehave_pulse30ofpulse30is
SIGNALFULL:
STD_LOGIC;
BEGIN
P1:
PROCESS(CLK)
VARIABLECNT30:
integerrange1to30;
BEGIN
IFCLK'EVENTANDCLK='1'THEN
IFCNT30=30THEN
CNT30:
=1;
FULL<='1';
ELSECNT30:
=CNT30+1;
FULL<='0';
ENDIF;
ENDIF;
ENDPROCESSP1;
P2:
PROCESS(FULL)
VARIABLECNT2:
STD_LOGIC;
BEGIN
IFFULL'EVENTANDFULL='1'THEN
CNT2:
=NOTCNT2;
IFCNT2='1'THENfout<='1';
ELSEfout<='0';
ENDIF;
ENDIF;
ENDPROCESSP2;
ENDbehave_pulse30;
七、实验结果及分析
实验结果:
当en_clock=’1’时,即clock有效时,试验箱端扬声器演奏出乐曲《友谊地久天长》的音乐。
当en_clock=’0’时,停止演奏。
实验分析:
例如二分之一得音符低音5的实验流程运转:
首先计数器COUNTER在时钟clk4hz的驱动之下以每个数据0.25s的频率(即每个四分之一节拍音符持续的时间)将产生的数据000000和000001,并将其依次送入存储模块music_rom_data;其对应的存储地址为音符低音5的编码000,并将其作为输出送入tonetab模块中。
在tonetab模块中以case选择语句,输出音符频率frequence=396,音符编码code=101以及预置数tone=1538,依次送入模块dispfrenquence,dispcode以及speaker中。
然后预置数tone在模块speaker中,将时钟0.4MHZ进行CLK/2*(2048-TONE[10..0])分频得到输出speak为396;由此类推。
address=000000—>index=000—>tone=1538—>speak=396(持续时间0.25s);
address=000001—>index=000—>tone=1538—>speak=396(持续时间0.25s);
address=000010—>index=001—>tone=1666—>speak=523(持续时间0.25s);
address=000011—>index=001—>tone=1666—>speak=523(持续时间0.25s);
address=000100—>index=001—>tone=1666—>speak=523(持续时间0.25s);
address=000101—>index=001—>tone=1666—>speak=523(持续时间0.25s);
……
八、实验体会
在实验题目拿到手里的那一刻,还不知意味着什么,只是感觉看着好难,但是也好新奇。
心里面有跃跃一试的激动,但是又因为之前从来没有设计过此类的设计项目,也有一些胆颤。
于是我专门找了一整块的时间来研究此道设计题,待到抬头时却发现徐老师给的有关实验题目和原理的课件上面已经将实验的步骤和方法以及思想,罗列的清晰可现。
我想要是再真的做不出来可真是对不起自己的时间,对不起这张课件上面的字迹,也浪费了徐老师的心思!
但在实验实现的过程中却遇到了麻烦,
(1)首先是制作存储模块music_rom_data,因为之前没有遇到过LPM宏功能模块的使用,还有上课时没有认真听这方面的讲课内容(挺不好意思的),所以不知从何下手,从图书馆查找资料也只是对LPM宏模块本身的理解及应用,没有使用步骤,也不知道应该以怎样德形式将频谱存入.mif格式文件,这对于实验就不知要怎样实现。
周五的晚上于是我对自己说:
你什么时候想好实验的存储方法就什么时候睡觉,这样持续到了2:
30,突然恍然大悟,觉醒,于是将音符以编码的形式将其存储(好像我有点笨了,呵呵)。
(2)然后在进行模块SPEAKER的设计时,发现若以设计题目给定的12MHZ进行分频,那预置数TONE[10..0]将为负数,于是计算过后,发现若进行30分频将时钟信号调制为0.4MHZ则可以正常进行试验。
接下来整个实验一气呵成!
待到周六本组另外一同学袁亮将无误的显示模块连接,呵呵,实验编译成功!
在这了还要感谢袁亮同学对我的信任!
当周日的时候,进入了实验室,心里有点小紧张,也有点小兴奋。
想一定会成功的。
带着忐忑的心里,在链接编译下载之后却发现实验箱中的扬声器不争气的没有半点生气,很是郁闷。
待徐老师的耐心指导之下,发现是少了用来驱动存储模块的计数器模块COUNTER。
重新下载之后,发现扬声器发出的只是低鸣声……结果换了一个实验箱仍然是这样的结果,排除了试验箱的扬声器的问题;然后从新计算了例化语言VHDL,发现没有计算问题,也没有逻辑问题;遂于是去参考一下别的组的实验数据才发现是使用了偏低的音频频率!
从新计算了数据带入,结果不出所料的正确了的发出了《友谊地久天长》的音乐。
从实验布置下来的时间开始,虽然我觉得有点点难,但是我知道既然老师把这个设计项目布置了下来就有她的道理,就说明我们有能力去完成这个实验。
我不惧怕!
但是当听到有同学说:
这个实验真的好难,不会有同学做出来了,我不要做了……等等的话,我真的有写生气,于是我说对她们说:
我已经想出来方法了,其实徐老师也已经说的很明白了,都是我们之前有遇到知识,你们去看一下……而此时我的实验还没有眉目,我想不要半途而废,要竭尽所能!
实验是结束了,本学期的VHDL课程也将结束。
但是我知道这仅仅是VHDL的入门学。
其语言的精髓我们还没有真正的体会到,感受到,学习到!
但是却已经发现它的强大。
带着无穷的兴趣去学习,去思考,收获亦将无穷!
九、思考题
1,每一音符的节拍长短的变化是由什么控制的?
答:
是将音乐的以四分之一节拍为1个单元进行ROM存储,于是就会有二分之一节拍进行2个单元的ROM存储,以此类推。
每个单元持续时间为1个单位时间(本实验采用了0.25s),就会有二分之一节拍的音符持续了2个单位时间,四分之三节拍的音符将会持续3个单位的时间。
2,该变时钟CLK4HZ的频率,乐曲有什么变化?
答:
将时钟CLK4HZ的频率进行调整,发现乐曲的演奏速度,即音符的持续时间随之发生变化,即当时钟频率调整高于4HZ,则乐曲的演奏速度加快,反之,若将时钟频率调整低于4HZ,乐曲的演奏速度减慢。
3,填入新的乐曲。
答:
若要填入新的乐曲,则要将实验的LPM_ROM初始化数据文件进行重新填写。
若有新的音符加入,则需在实验模块中加入新的编码,预置数,频谱,编码等对应数据。