搜档网
当前位置:搜档网 › EDA-简易音乐播放器设计

EDA-简易音乐播放器设计

EDA-简易音乐播放器设计
EDA-简易音乐播放器设计

目录

1 引言 (2)

2 设计任务及设计要求 (2)

3 设计原理及总体思路 (2)

4 各单元模块的设计 (4)

*

5 总电路设计 (16)

6 设计调试体会与总结 (16)

参考文献 (22)

1 引言

《EDA课程设计》(注:EDA即电子设计自动化,Electronics Design Automation)是继《模拟电子技术基础》、《数字电子技术基础》、《电子技术基础实验》课程后,电气类、自控类和电子类等专业学生在电子技术实验技能方面综合性质的实验训练课程,是电子技术基础的一个部分,其目的和任务是通过一周的时间,让学生掌握EDA的基本方法,熟悉一种EDA软件,并能利用EDA软件设计一个电子技术综合问题,并在实验箱上成功下载,为以后进行工程实际问题的研究打下设计基础。

1.通过课程设计使学生能熟练掌握一种EDA软件的使用方法,能熟练进行设计输入、编译、管脚分配、下载等过程。

2.通过课程设计使学生能利用EDA软件进行至少一个电子技术综合问题的设计,设计输入可采用图形输入法或AHDL硬件描述语言输入法。

:

3.通过课程设计使学生初步具有分析寻找和排除电子电路中常见故障的能力。

4.通过课程设计使学生能独立写出严谨的、有理论根据的、实事求是的、文理通顺的字迹端正的课程设计报告。

2 设计任务及设计要求

设计一个简易硬件播放器并能播放多首音乐(最少四首),可通过按键手动控制音乐播放。在播放音乐的同时可实现音谱与音高的显示,并通过16个LED 小灯显示不同音调的变化。

使用VHDL语言设计音调发生模块,音调编码模块,乐曲存储模块,控制模

块,小灯控制模块,数字显示模块,音谱与音高输出模块等各个模块。

3 设计原理及总体思路

`

产生音乐的两个因素是音乐频率和音乐的持续时间,以纯硬件完成演奏电路比利用微处理器(CPU)来实现乐曲演奏要复杂的多如果不借助于功能强大的EDA 工具和硬件描述语言,凭借传统的数字逻辑技术,即使最简单的演奏电路也难以实现。根据设计要求,乐曲硬件演奏电路系统主要由音频发生模块和乐曲存储模块组成。音频发生模块对FPGA的基准频率进行分频,得到与各个音阶对应的频率输出。乐曲存储模块产生节拍控制和音阶选择信号,即在此模块中可存放一个乐曲曲谱真值表,由一个计数器来控制此真值表的输出,而由计数器的计数时钟信号作为乐曲节拍控制信号。

音名与频率的关系

音乐的十二平均率规定:每两个八度音(如简谱中的中音1与高音1)之间的频率相差一倍.在两个八度音之间,又可分为十二个半音,每两个半音的频率比为4。另外,音名A(简谱中的低音6)的频率为440Hz,音名B到C之间,E 到F之间为半音,其余为全音,由此可以计算出简谱中从低音1到高音1之间每个音名的频率如表3-1所示。

表3-1 简谱中的音名与频率的关系

由于音阶频率多为非整数,而分频系数又不能为小数,故必须将得到的分频数四舍五入取整。若基准频率过低,则由于分频系数过小,四舍五入取整后的误差较大,若基准频率过高,虽然误码差变小,但分频结构将变大。实际的设计应综合考虑两方面的因素,在尽量减小频率误差的前提下取舍合适的基准频率。本例中选取12MHz的基准频率,若无12MHz的时钟频率,实际上,只要各个音名间的相对品频率关系不变,C作1与D作1演奏出的音乐听起来都不会“走调”。各音阶频率及相应的分频系数如表2所示。为了减少输出的偶次谐波分量,最后输出到扬声器的波形应为对称方波,因此在到达扬声器之前,有一个二分频的分频器。表3-2中的分频系数就是从500KHZ频率二分频得到的250KHZ频率基础上计算得出的。

表3-2 各音阶频率对应的分频值

~

由于最大的分频系数为1274,故采用13位二进制计数器已能满足分频要求。在表3-2,除给出了分频比以外,给出了对应于各个音阶频率时计数器不同的初始值,对于乐曲中的休止符,要将分频系数设为0,即初始值为2047即可,此时扬声器将不会发声。对于不同的分频系数,加载不同的初始值即可。

节拍控制原理

该演奏电路演奏的乐曲是“梁祝”等片段,其最小的节拍为1拍。将1拍的时长定为秒,则需要再提供一个4Hz的时钟频率即可产生1拍的时长,演奏的时间控制通过音符的多次重复的方式来完成。

对于占用时间较长的节拍,如全音符为4拍(重复4),2/4音符为2拍(重复2),1/4音符为1拍(重复1)。

由于乐理规律对于任何一首音乐都是普遍适用的,所以以上原理对于其他三首乐曲同样适用。

4 各单元模块的设计

音频发生模块

}

模块引脚

图4-1 speaker模块

模块功能

如图4-1,en为使能引脚,当en引脚接高电平时speaker模块使能可正常工作。clk为时钟信号引脚,为speaker模块提供时钟信号。tone[10..0]为11位的音调初始值信号并行总线,可快速的为speaker模块输送音调初始值信号,保证乐曲演奏的流畅性。spks为电信号输出引脚,连接蜂鸣器将电信号转化为声信号。该模块中有一个4位的计数器用于将12MHz时钟信号进行十二分频产生1MHz的基准信号。一个11位的递增计数器用于赋音调初始值对基准信号进行频,最后进行二分频产生对称方波。

初始值D = 计数最大值N - 分频系数n (1) VHDL程序

library ieee;

,

use speaker is

port(

en : in std_logic;

clk : in std_logic;

tone : in integer range 0 to 16#7ff#; --"2047"

spks : out std_logic);

end speaker;

architecture behav of speaker is

;

signal preclk : std_logic;

signal fullspks : std_logic;

begin

divideclk: process(clk) --12分频variable count4 : integer range 0 to 15;

begin

preclk<='0';

if count4>11 then

preclk<='1';

count4:=0;

elsif clk'event and clk='1' then

count4:=count4+1;

end if;

end process;

genspks : process(preclk,tone)--"preclk=1MHZ";

variable count11 : integer range 0 to 16#7ff#;

"

begin

if preclk'event and preclk='1' then --频率控制

if count11=16#7ff# then --b"111,1111,1111"

count11:=tone; -- 初始值D = 计数最大值N - 分频系数n

fullspks<='1';

else count11:=count11+1;

fullspks<='0';

/

end if;

end if;

end process;

delay: process(fullspks)--"fullspks="; 二分频

variable count2 : std_logic;

begin

if fullspks'event and fullspks='1' then

count2:=not count2;

if en='0' then

spks<='0'; --gaile elsif count2='1' then

spks<='1';

else

spks<='0'; --"spks="

end if;

end if;

[

end process;

end behav;

音频编码模块

模块引脚

图4-2 tonetaba模块

模块功能

如图4-2,index[3..0]为4位的音符输入并行总线,用于为tonetaba 模块输送音符信号。tone[10..0]为11位的音调初始值信号输出并行总线,为speaker 模块提供音调初始值信号。code[3..0]为4位的音谱输出并行总线,为SELTIME 模块提供音谱信号。high[1..0]为2位的音高输出并行总线,为SELTIME 模块提供音高信号。该模块将输入的音符信号转化为音调初始值(tone),对应的音谱

(code)及音高(high)并输出。

VHDL程序

library ieee;

use tonetaba is

port(

index : in integer range 0 to 15;

tone : out integer range 0 to 16#7ff#; --"2047"

code : out integer range 0 to 15;

·

high : out integer range 0 to 2);

end tonetaba;

architecture behav of tonetaba is

begin

search:process(index)

begin

case index is

when 0=>tone<=2047; code<=0; high<=0;

when 1=>tone<=773; code<=1; high<=0;

when 2=>tone<=912; code<=2; high<=0;

when 3=>tone<=1036; code<=3; high<=0;

when 5=>tone<=1197; code<=5; high<=0;

when 6=>tone<=1290; code<=6; high<=0;

when 7=>tone<=1372; code<=7; high<=0;

when 8=>tone<=1410; code<=1; high<=1;

when 9=>tone<=1480; code<=2; high<=1;

when 10=>tone<=1542; code<=3; high<=1;

when 12=>tone<=1622; code<=5; high<=1;

when 13=>tone<=1668; code<=6; high<=1;

when 15=>tone<=1728; code<=1; high<=2;

when others=>null;

end case;

end process;

]

end behav;

乐曲储存模块

模块引脚

图4-3 notetabs模块

模块功能

如图4-3,clk为时钟信号引脚为模块提供时钟信号,clr为计数器清零引脚,当clr为高电平时notetabs 模块中的乐曲播放计数器清零。add[1..0]为2位的乐曲地址选择并行总线,可通过不同的地址值选择不同的乐曲。cs为片选信号引脚当cs为高电平时模块才能正常工作反之无法工作。index[3..0]为4位的音符信号输出并行总线,为tonetaba 模块和LED模块提供音符信号。该模块中有一个8位的播放计数器为乐谱的连续查询提供计数,当达到一定计数值后自动清零实现同一首乐曲的重复播放。

VHDL程序

/

library ieee;

use notetabs is

port(

clk,clr: in std_logic;

add : in std_logic_vector(1 downto 0);

cs: in std_logic;

index : out integer range 0 to 15);

end notetabs;

~

architecture behav of notetabs is

signal counter : integer range 0 to 255;

begin

cnt8: process(clk,cs)

begin

if cs='0' then

counter<=0;

elsif add="00" and counter=138 then

counter<=0; --每一首歌都循环播放

elsif add="01" and counter=127 then

counter<=0;

elsif add="10" and counter=183 then

counter<=0;

elsif add="11" and counter=131 then

counter<=0;

.

elsif clr='1' and clr'LAST_VALUE='0' then

counter<=0;

elsif clk'event and clk='1' then

counter<=counter+1;

end if;

end process;

search : process(counter)

begin

}

if add="00" then

case counter is

when 00=>index<=3;

when 01=>index<=3;

when 02=>index<=3;

--此处省略

when 135=>index<=5;

when 136=>index<=0;

|

when 137=>index<=0;

when 138=>index<=0;

when others=>null;

end case;

end if;

if add="01" then

case counter is

when 00=>index<=13;

$

when 01=>index<=13;

when 02=>index<=13;

--此处省略

when 124=>index<=5;

when 125=>index<=0;

when 126=>index<=0;

when 127=>index<=0;

when others=>null;

end case;

end if;

if add="10" then

case counter is

when 00=>index<=10;

when 01=>index<=10;

when 02=>index<=12;

--此处省略

?

when 180=>index<=8;

when 181=>index<=8;

when 182=>index<=8;

when 183=>index<=8;

when others=>null;

end case;

end if;

if add="11" then

case counter is

when 00=>index<=6;

when 01=>index<=6;

when 02=>index<=6;

--此处省略

when 128=>index<=6;

when 129=>index<=0;

when 130=>index<=0;

when 131=>index<=0;

when others=>null;

end case;

end if;

end process;

end behav;

控制模块

模块引脚

:

图4-4 control模块

模块功能

如图4-4,switch为控制引脚当其为上升沿时乐曲地址自动加一,当加到最大值时自动清零。en为使能引脚当刚en引脚为高电平时outcs引脚也为高电平,反之为低电平。add[1..0]为乐曲地址总线当add为00时选择第1首乐曲,为01时选择第2首乐曲,为10时选择第3首乐曲,为11时选择第4首乐曲。outcs 为notetabs 模块片选控制引脚,当outcs引脚为高电平时选中notetabs 模块。

VHDL程序

library ieee;

use control is

port(switch,en: in std_logic;

'

add: out std_logic_vector(1 downto 0);

outcs: out std_logic);

end control;

architecture one of control is

signal add_r:std_logic_vector(1 downto 0);

begin

add<=add_r;

{

process(switch,en)

begin

if en='0' then

outcs<='0';

else

outcs<='1';

end if;

if rising_edge(switch) then

add_r<=add_r+1;

end if;

end process;

end one;

小灯控制模块

模块引脚

图4-5 LED模块

模块功能

如图4-5,NUM[3..0]为4位的音符信号输入并行总线。LIGHT[15..0]为16位的LED灯控制并行总线,控制LED小灯的亮灭及其亮灭个数。能依次点亮并保

持不同数目的LED小灯且不同的音符对应由低到高的不同的亮灯个数。 VHDL程序

LIBRARY IEEE;

USE LED IS

PORT(

NUM: IN INTEGER RANGE 0 to 15;

LIGHT: OUT STD_LOGIC_VECTOR(15 DOWNTO 0)

);

END LED;

ARCHITECTURE ONE OF LED IS

BEGIN

PROCESS(NUM)

BEGIN

CASE NUM IS

·

WHEN 0=> LIGHT<="0000000000000001";

WHEN 1=> LIGHT<="0000000000000011";

WHEN 2=> LIGHT<="0000000000000111";

WHEN 3=> LIGHT<="0000000000001111";

WHEN 4=> LIGHT<="0000000000011111";

WHEN 5=> LIGHT<="0000000000111111";

WHEN 6=> LIGHT<="0000000001111111";

WHEN 7=> LIGHT<="00000000";

$

WHEN 8=> LIGHT<="00000001";

WHEN 9=> LIGHT<="00000011";

WHEN 10=>LIGHT<="00000";

WHEN 11=>LIGHT<="0000";

WHEN 12=>LIGHT<="000";

WHEN 13=>LIGHT<="001";

WHEN 14=>LIGHT<="011";

WHEN 15=>LIGHT<="111";

END CASE;

END PROCESS;

END ONE;

数字显示模块

模块引脚

图4-6 DELED模块

模块功能

;

如图,S[3..0] 为4位的十六进制数字输入并行总线。A,B,C,D,E,F,G,H各引脚分别连接数码管的对应段选引脚是数码管显示S[3..0]所输入的十六进制数字。

VHDL程序

LIBRARY IEEE;

USE DELED IS

PORT(

S: IN STD_LOGIC_VECTOR(3 DOWNTO 0);

A,B,C,D,E,F,G,H: OUT STD_LOGIC);

END DELED;

ARCHITECTURE BEHAV OF DELED IS

SIGNAL DATA:STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL DOUT:STD_LOGIC_VECTOR(7 DOWNTO 0);

BEGIN

DATA<=S;

PROCESS(DATA)

BEGIN

~

CASE DATA IS

WHEN "0000"=>DOUT<="00111111";

WHEN "0001"=>DOUT<="00000110";

WHEN "0010"=>DOUT<="01011011";

WHEN "0011"=>DOUT<="01001111";

WHEN "0100"=>DOUT<="01100110";

WHEN "0101"=>DOUT<="01101101";

WHEN "0110"=>DOUT<="01111101";

%

WHEN "0111"=>DOUT<="00000111";

WHEN "1000"=>DOUT<="01111111";

WHEN "1001"=>DOUT<="01101111";

WHEN "1010"=>DOUT<="01110111";

WHEN "1011"=>DOUT<="01111100";

WHEN "1100"=>DOUT<="00111001";

WHEN "1101"=>DOUT<="01011110";

WHEN "1110"=>DOUT<="01111001";

?

WHEN "1111"=>DOUT<="01110001";

WHEN OTHERS=>DOUT<="00000000";

END CASE;

END PROCESS;

H<=DOUT(7);

G<=DOUT(6);

F<=DOUT(5);

E<=DOUT(4);

>

D<=DOUT(3);

C<=DOUT(2);

B<=DOUT(1);

A<=DOUT(0);

END BEHAV;

音谱与音高输出模块

模块引脚

|

图4-7 SELTIME模块

模块功能

如图,code[3..0]为4位的音谱输入总线,输入音谱。high[1..0]为2位的音高输入总线,输入音高。clk为时钟输入引脚。daout[3..0]为4位的数据输出总线,输出音高和音谱信号。sel[2..0]为位选输出总线,输出数码管的位选。 VHDL程序

library ieee;

use SELTIME is

port(

code : in std_logic_vector(3 downto 0);

high : in std_logic_vector(1 downto 0);

clk : in std_logic;

daout: out std_logic_vector(3 downto 0);

sel : out std_logic_vector(2 downto 0));

end SELTIME;

architecture behav of SELTIME is

signal sec : std_logic_vector(2 downto 0);

begin

process(clk)

begin

if(clk'event and clk='1') then

if(sec="011") then

sec<="000";

else

sec<=sec+1;

#

end if;

end if;

end process;

process(sec,code(3 downto 0),high(1 downto 0))

begin

case sec is

when "000"=>daout<=code(3 downto 0);

when "001"=>daout<="0000";

$

when "010"=>daout<="0000";

when "011"=>daout(3)<='0';

daout(2)<='0';

daout(1)<=high(1);

daout(0)<=high(0);

when others=>daout<="XXXX";

end case;

end process;

^

sel<=sec;

end behav;

~

5 总电路设计

总体原理图

总体电路原理图如图5-1。

图5-1 总体电路原理图

总体功能介绍

该电路可以播放最多四首乐曲,可通过按按键的次数来切换曲目,接通电源后默认为播放第一首乐曲。

接通电源后按一次播放第二首乐曲,接通电源后按两次播放第三首乐曲,接通电源后按三次播放第四首乐曲,接通电源后按第四次地址归零播放第一首乐曲。

每按按键四次一个循环。可重复播放当前乐曲。在播放乐曲的同时十六位的LED小灯点亮,其点亮的个数与音调对应。四位数码管的第一位显示乐谱(1,2,3,4,5,6,7),第四位显示音高(0(低音),1(中音),2(高音)),其余位显示0。

}

6 设计调试体会与总结

各模块调试仿真

音频编码模块

图6-1 tonetaba模块仿真波形

图6-1中,当输入音符为2时其输出的音调初始值信号为912,音高为0(低音),对应的音谱为2。

当输入音符为9时其输出的分频系数为1480,音高为1(中音),对应的音谱为2。

与原理相符合。

乐曲储存模块

图6-2 notetabs模块仿真波形

图6-2中,当clr为高电平时每首乐曲的输出保持不变,当cs为高电平且clr为低电平时模块正常工作,当add[1..0]为2时输出第三首乐曲的音符。

与原理相符合。

控制模块

图6-3 control模块仿真波形

图6-3 中,引脚en与引脚outcs同步变化当en为高电平时outcs同样为高电平,反之亦然。当switch经历一次上升沿时add自动加1,当add大于3时自动归零,按键每按一次add继续自动加一,以此不断循环。

与原理相符合。

小灯控制模块

&

图6-4 LED模块仿真波形

图6-4中,当NUM[3..0]的输入为音符4时LIGHT[15..0]的输出的低5位都为高电平,当NUM[3..0]的输入为音符6时LIGHT[15..0]的输出的低7位都为高电平,当NUM[3..0]的输入为音符15时LIGHT[15..0]的输出的所有位都为高电平,LED小灯全点亮。不同的音符对应由低到高的不同的亮灯个数。

与原理相符合。

数字显示模块

相关主题