目 录
竞赛题目
摘要
1 设计内容与要求
2 设计方案及原理
2.1 方案概述
2.2 音源产生原理
2.3 系统框图
3 模块程序与仿真
3.1 顶层程序与仿真
3.2 音阶发生器程序与仿真
3.3 数控分频模块程序与仿真
3.4 自动演奏模块程序与仿真
4 设计总结
附录
2
2
3
3
3
3
4
5
5
7
8
9
15
16
基于 FPGA 的乐曲演奏器的设计
摘 要
本设计采用 VHDL 语言和模块化的设计方法,在 EDA 开发工具 QuartusⅡ软件平台上,
通过音符编码的设计思想,根据数控分频原理设计出一个呢过产生 16 音阶信号的电子琴。
实现了音乐自动播放、琴键演奏、配有随音乐节奏而闪烁变化的 LED 以及乐谱显示等功能
的乐曲演奏器系统.使基于 FPGA 芯片的乐曲演奏器数字电路得到了优化,提高了它的灵活性
和可扩展性。本系统选用 EP1K30-144PIN FPGA 芯片对其进行引脚定义,下载源程
序后实现硬件仿真。
关键词: QuartusⅡ , VHDL, 数控分频,
16 音阶
Abstract
this design uses the VHDL language and the modular design method, in EDA
development kit Quartus Ⅱ In the software platform, through the note code design
concept, designs one according to the numerical control frequency division principle
to produce 16 scale signal electric piano.Realized the music automatic broadcast, the
key performance, had along with music rhythm glitters function and so on change
LED as well as music demonstration music performance systems. Enable to obtain the
optimization based on the FPGA chip music performance digital circuit, enhanced its
flexibility and the extendibility.This system selects EP1K30-144PIN the FPGA chip
to carry on the pin definition to it, after the downloading source program realizes the
hardware simulation.
Key word: QuartusⅡ VHDL, numerical control frequency division, 16 scales
一、设计内容与要求:
(1) 音乐自动播放,定制 LMP_ROM 存储 4 首歌以上,由键控选择播放
(2) 琴键演奏,含高低 16 个音调
(3) 配有随音乐节奏而闪烁变化的 LED 以及乐谱显示
利用 CPLD/FPGA 来实现,写出产品说明书和报告!
二、设计方案及原理:
2.1 方案概述
本硬件电子琴采用数控分频的原理,当输入端按下一个键时,就对应给定一
个不同输入数据时,将对输入的时钟信号有不同的分频比,从而控制扬声器产生不
同频率的声音.同时发光二极管同步响应信号.
为保证分频后输出频率在音频范围内,本设计时钟频率选 32mHz,通过基准的
2 分频后.再根据计数器的计数值的变化实现不同音阶的不同分频.计数器中的计
数初值由音阶按键控制不同数据设定.
2.2 音源产生原理
组成乐曲的每个音符的发音频率值及其持续的时间是乐曲能连续演奏所需的
2 个基本要素,音符与频率的关系如下:
乐曲的 12 平均率规定:每 2 个八度音(如简谱中的中音 1 与高音 1)之间
的频率相差 1 倍。在 2 个八度音之间,又可分为 12 个半音,每 2 个半音的频率
比为 12√2。另外,音符 A(简谱中的低音 6)的频率为 440Hz,音符 B 到 C 之间、
E 到 F 之间为半音,其余为全音。由此可以计算出简谱中从低音 l 至高音 1 之间
每个音符的频率,如表 1 所示。
产生各音符所需的频率可用一分频器实现,由于各音符对应的频率多为非整
数,而分频系数又不能为小数,故必须将计算得到的分频数四舍五入取整。若分
频器时钟频率过低,则由于分频系数过小,四舍五入取整后的误差较大;若时钟
频率过高,虽然误差变小,但会增加分频器的分频级数。实际的设计应综合考虑
两方面的因素,在尽量减小频率误差的前提下取合适的时钟频率。本文设计的乐
曲发生器选取 32mHZ 的基准频率。若无 32mHZ 的时钟频率,则可以先分频得
到 32mHZ 或换一个新的基准频率。实际上,只要各个音符间的相对频率关系不
变,演奏出的乐曲听起来都不会"走调"。
表 1 频率与音符表
频 率
分频
计数
(Hz)
系数
初值
符名
375000
0
2047
音 4
294.349
1274
330.396
1135
773
912
370.92
1011
1036
386.598
394.737
495.376
555.56
588.697
638.84
970
950
757
675
637
587
742.574
505
音 5
音 6
音 7
音 1
音 2
1077
1197
1290
音 3
1372
音 4
1410
音 5
1480
音 6
1542
音 7
分
频 率
频
计数
(Hz)
系
初值
数
796.178
882.353
989.446
1136.363
1175.549
1353.790
1512.097
1609.442
1802.884
2027.027
468
425
379
330
319
277
248
233
208
185
1579
1622
1668
1717
1728
1770
1799
1814
1839
1862
2272.727
165
1882
音
中
中
中
中
高
高
高
高
高
高
高
音
休
低
低
低
低
低
低
低
中
中
中
符名
止符
音 1
音 2
音 3
音 4
音 5
音 6
音 7
音 1
音 2
音 3
2.3 系统框图
系统框图如下图 1:
琴键(16 个)
额外示例音乐
控制键
音阶显示器
扬声器
发光二极管
EP1K30-
144PIN
FPGA 芯
片
LMP_ROM
存储歌曲
图 1 电子琴系统框图
三 模块程序与仿真
3.1.顶层程序与仿真
3.1.1 顶层 VHDL 程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity top is
Port ( clk32MHz
:in std_logic;
handTOauto : in std_logic;
--32MHz 系统时钟
--键盘输入/自动
演奏
号
tune_key
:in std_logic_vector(15 downto 0);
--键盘输入信
high1
:out std_logic;
--高低音节信号
tune_flinght : out std_logic;
--发光二极管跟随频率闪烁
tune_speaker : out std_logic;
--扬声器端口
tune_seg : out std_logic_vector(6 downto 0)); --一位数码音阶显示
end top;
architecture Behavioral of top is
component huanle
Port ( clk :in std_logic;
Auto: in std_logic;
tune_key2:in std_logic_vector(7 downto 0);
tune_key 0: out std_logic_vector(7 downto 0));
end component;
component laohu
Port ( clk :in std_logic;
Auto: in std_logic;
tune_key2:in std_logic_vector(7 downto 0);
tune_key 0: out std_logic_vector(7 downto 0));
end component;
component abc
Port ( clk :in std_logic;
Auto: in std_logic;
tune_key2:in std_logic_vector(7 downto 0);
tune_key 0: out std_logic_vector(7 downto 0));
end component;
component shuyazi
Port ( clk :in std_logic;
Auto: in std_logic;
tune_key2:in std_logic_vector(7 downto 0);
tune_key 0: out std_logic_vector(7 downto 0));
end component;
component tone
Port ( index : in std_logic_vector(15 downto 0);
tune_seg : out std_logic_vector(6 downto 0);
high : out std_logic;
tone0 : out integer range 0 to 2047);
end component;
component speaker
Port ( clk1 : in std_logic;
tone1 : in integer range 0 to 2047;
spks : out std_logic);
end component;
signal tone2: integer range 0 to 2047;
signal indx:std_logic_vector(7 downto 0);
begin
u0:huanle port map(clk=>clk32MHZ, tune_key 2=> tune_key, tune_key
0=>indx,Auto=>handtoAuto);
u0:laohu port map(clk=>clk32MHZ, tune_key 2=> tune_key, tune_key
0=>indx,Auto=>handtoAuto);
u0:sbc port map(clk=>clk32MHZ, tune_key 2=> tune_key, tune_key
0=>indx,Auto=>handtoAuto);
u0:shuyazi port map(clk=>clk32MHZ, tone_key => tune_key,
0=>indx,Auto=>handtoAuto);
u4: tone port map(index=>indx,tone0=>tone2, tune_seg
=>code1,high=>high1);
u5: speaker port map(clk1=>clk32MHZ,tone1=>tone2,spks=>
tune_speaker);
end Behavioral;
3.1.2 仿真
顶层文件仿真图如图 2 所示。
图 2 顶层文件仿真图
3.2 音阶发生器程序与仿真
3.2.1 音阶发生器 VHDL 程序
--功能:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity tone is
Port ( index : in std_logic_vector(15 downto 0);
: out std_logic_vector(6 downto 0);
tune_seg
high
tone0 : out integer range 0 to 1274);
: out std_logic;
--音符输入信号
--音符显示信号
--高低音显示信号
--音符的分频系数
end tone;
architecture Behavioral of tone is
begin
search :process(index)
示,高低音阶
begin
--此进程完成音符到音符的分频系数译码,音符的显
case index is
when"0000000000000001"=>tone0<=1274;tune_seg<="0000110";high<='0';
when "0000000000000010"=> tone0<=1135; tune_seg <="1011011";high<=’0;
when "000000000000100" => tone0<=1011; tune_seg <="1001111";high<='0';
when "000000000001000" => tone0<=970; tune_seg <="1100110";high<='0';
when "000000000010000" => tone0<=950; tune_seg <="1101101";high<='0';
when "000000000100000" => tone0<=757; tune_seg <="1111101";high<='0';
when "000000001000000" => tone0<=675; tune_seg <="0000111";high<='0';
when "000000010000000" => tone0<=637; tune_seg <="1111111";high<='0';
when "0000000000000001" => tone0<=587; tune_seg <="0000110";high<='1';
when "0000000000000010"=> tone0<=505; tune_seg <="1011011";high<=’1;
when "000000000000100" => tone0<=468; tune_seg <="1001111";high<='1';
when "000000000001000" => tone0<=425; tune_seg <="1100110";high<='1';
when "000000000010000" => tone0<=379; tune_seg <="1101101";high<='1';
when "000000000100000" => tone0<=330; tune_seg <="1111101";high<='1';
when "000000001000000" => tone0<=319; tune_seg <="0000111";high<='1';
when "000000010000000" => tone0<=277; tune_seg <="1111111";high<='1';
when
=> tone0<=1440;code<="0000000";high<='0';
others
end case;
end process;
end Behavioral;
3.2.2 音阶发生器程序仿真
音阶发生器程序仿真图如图 3 所示。
图 3 音阶发生器仿真图
3.3. 数控分频模块程序与仿真
3.3.1 数控分频模块 VHDL 程序
--功 能:实现数控分频。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity speaker is
Port ( clk1
: in std_logic;
tone1 : in integer range 0 to 30624;
spks
end speaker;
: out std_logic);
preclk,fullspks:std_logic;
architecture Behavioral of speaker is
signal
begin
pulse1:process(clk1)
4 分频
variable count:integer range 0 to 8;
begin
if clk1'event and clk1='1' then count:=count+1;
if count=2 then preclk<='1';
elsif count=4 then preclk<='0';count:=0;
end if;
--系统时钟
--音符分频系数
--驱动扬声器的音频信号
--此进程对系统时钟进行