电子音乐发生器设计实验报告
一. 实验要求
1. 2种电子音乐播放模式的自动循环播放。
2. 手动选择某一模式的循环播放。
3. 数码管显示该播放模式。
二. 工作原理
1)简谱中音名所对应的频率(HZ)如下表所示
2)音阶频率的获得
由硬件实验装置的晶振频率经过适当的分频系数和输出音频整形(对称方波)就可以得到音阶频率。
为了使输出的频率为对称的方波,故在分频系数计算时要除以2,在最后输出到交流蜂鸣器前要进行将输出频率二分频恢复原音名频率。例如以10M为基准频率,要将低音3频率为392.6hz音频信号送出。
假设硬件实验的晶振频率为10M,则: 分频系数K=(10M/392.6)/2=12736
将10M基准频率进行12736分频得到的是低音3频率的倍频信号392.6*2=592.4hz.
在输出到交流蜂鸣器前再将592.4hz进行2分频得到的是392.6hz低音3对称方波信号的频率。
3)节拍控制器
乐曲节拍1拍定义为1秒,2/8拍为0.25秒以此类推,根据节拍将所编辑的音乐输出到交流蜂鸣器。一般以一首曲的最低节拍为基准节拍。基准节拍可通过分频电路获得。
4)乐曲输入模块
根据所选乐曲将简谱转换成频率信号,根据节拍输出乐曲频率信号。
三. 实验步骤
初步设计:由设计流程图画出顶层原理图草稿。
模块设计和调试:设计各个模块。对每一模块进行功能仿真,验证其逻辑或时序是否符合设计要求。
总体设计调试:完成时钟设计顶层原理。根据所选芯片型号,定义LOG,进行设计实现调试。
硬件验证:将程序通过数据电缆由电脑下载到芯片,在演示板上进行设计功能硬件验证。
四. 设计方框图
五. 实验电路图
六. 实验程序
1)音频控制器ypkz2:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity ypkz2 is
Port ( clk : in STD_LOGIC;
en : in STD_LOGIC;
ch : in STD_LOGIC;
btype : out STD_LOGIC_VECTOR (3 downto 0);
ypfp : out STD_LOGIC_VECTOR (4 downto 0));
end ypkz2;
architecture folow of ypkz2 is
signal a:integer range 0 to 334;
signal c:integer range 0 to 334;
signal b:std_logic_vector(1 downto 0);
type memory is array(0 to 167) of integer range 0 to 21;
signal ROM1: memory;
signal ROM2: memory;
begin
ROM1<=(10,9,10,12,13,12,15,13,
12,10,12,12,12,12,13,13,
15,15,16,17,16,15,13,15,
12,12,12,12,0,0,0,0,
12,12,10,10,12,12,13,13,
15,15,16,17,15,13,12,12,
12,12,9,9,10,12,10,9,
8,6,8,8,8,8,0,0,
10,9,8,8,9,9,0,10,
12,12,13,15,13,13,12,12,
12,12,10,9,10,12,10,9,
8,9,6,6,6,6,8,8,
9,9,0,10,8,9,8,6,
8,6,5,5,5,5,0,0,
10,9,8,8,9,9,0,10,
12,12,13,15,13,13,12,12,
12,10,9,9,10,12,10,9,
8,9,6,6,6,6,8,8,
16,16,0,17,15,16,15,13,
12,13,15,17,16,15,13,15,
12,12,12,12,0,0,0,0);
ROM2<=( 17,17,0,16,16,16,16,17,
15,15,0,0,0,0,0,0,
12,12,8,8,13,12,10,10,
12,12,0,0,0,0,0,0,
12,12,12,13,15,15,8,15,
13,13,15,15,10,10,0,0,
12,12,12,13,12,12,10,9,
9,9,0,0,0,0,0,0,
17,17,0,0,16,16,16,17,
15,15,0,0,0,0,0,0,
10,10,15,15,13,12,10,10,
12,12,0,0,0,0,0,0,
12,12,12,13,15,15,15,15,
13,13,12,13,10,10,0,10,
17,17,17,17,17,17,16,13,
8,8,0,0,0,0,0,0,
15,15,0,0,14,14,13,14,
10,10,0,0,0,0,0,0,
12,12,12,13,13,0,10,9,
9,9,0,0,0,0,0,0,
10,10,0,12,13,13,13,13);
process(clk,c)
begin
if rising_edge(clk) then
if a=c then
a<=0;
else
a<=a+1;
end if;
end if;
end process ;
PROCESS( clk,a,en,ch1)
begin
b<=en&ch1;
if rising_edge(clk) then
if b="10" then
btype<="0001";
c<=167;
ypfp<=conv_std_logic_vector(ROM1(a),5);
elsif b="11" then
btype<="0010";
c<=167;
ypfp<=conv_std_logic_vector(ROM2(a),5);
else
btype<="ZZZZ";
ypfp<="00000";
end if;
end if;
END process ;
end folow;
2)分频器fp1_4
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity fp1_4 is
Port ( clk : in STD_LOGIC;
cp : out STD_LOGIC);
end fp1_4;
architecture Behavioral of fp1_4 is
signal a:integer range 0 to 20000000;
begin
process(clk)
begin
if rising_edge(clk) then
if a=1249999 then
a<=0;
else
a<=a+1;
end if;
case a is
when 0 to 624999 =>cp<='1';
when 625000 to 1249999=>cp<='0';
when others=>cp<='Z';
end case;
end if;
end process;
end Behavioral;
3)节拍控制器ypfp:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity ypfp is
Port ( clk : in STD_LOGIC;
datafp : in STD_LOGIC_VECTOR (4 downto 0);
cp : out STD_LOGIC);
end ypfp;
architecture Behavioral of ypfp is
signal a:integer range 0 to 10000;
signal b:integer range 0 to 10000;
signal pclk,pulse:std_logic:='0';
begin
process(clk)
begin
if rising_edge(clk) then
a<=a+1;
if a=b then
a<=0;
pulse<='1';
else
pulse<='0';
end if;
end if;
end process;
process(pulse)
begin
if rising_edge(pulse)then
pclk<=not(pclk);
end if;
end process;
process(clk)
begin
case datafp is
when "00001"=> b<=9567 ;
when "00010"=> b<=8511 ;
when "00011"=> b<=7584 ;
when "00100"=> b<=7158 ;
when "00101"=> b<=6377 ;
when "00110"=> b<=5681 ;
when "00111"=> b<=5061 ;
when "01000"=> b<=4776 ;
when "01001"=> b<=4256 ;
when "01010"=> b<=3791 ;
when "01011"=> b<=3579 ;
when "01100"=> b<=3188 ;
when "01101"=> b<=2840 ;
when "01110"=> b<=2530 ;
when "01111"=> b<=2390 ;
when "10000"=> b<=2127 ;
when "10001"=> b<=1895 ;
when "10010"=> b<=1789;
when "10011"=> b<=1593 ;
when "10100"=> b<=1419 ;
when "10101"=> b<=1265 ;
when others=> b<=0;
end case;
end process ;
cp<=pclk;
end Behavioral;
4)解码器decode:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity decode_1 is
Port ( en : in STD_LOGIC;
q : in STD_LOGIC_VECTOR (3 downto 0);
x : out STD_LOGIC_VECTOR (6 downto 0);
d : out STD_LOGIC_VECTOR (2 downto 0));
end decode_1 ;
architecture Behavioral of decode_1 is
begin
process(en,q)
begin
if en='0' then
x<="0000000";
d<="101";
else
d<="101";
case q is
when "0001"=>x<="0110000";
when "0010"=>x<="1101101";
when "0011"=>x<="1111001";
when others=>x<="0000000";
end case;
end if;
end process;
end Behavioral;
5)2分频器twofp:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity twopf is
Port ( en : in STD_LOGIC;
clk : in STD_LOGIC;
cp : out STD_LOGIC);
end twopf;
architecture Behavioral of twopf is
signal a:std_logic:='0';
begin
process(en,clk)
begin
if en='0' then
a<='0';
elsif rising_edge(clk) then
a<=not a;
end if;
cp<=a;
end process;
end Behavioral;
4.按键接口
cp output p17
ch1 input p23
clk0 input p125
d<0> output p76
d<1> output p77
d<2> output p78
en input p20
x<0> output p73
x<1> output p70
x<2> output p69
x<3> output p65
x<4> output p60
x<5> output p57
x<6> output p55
七. 实验总结
本次实验实现了两首音乐的播放以及显示播放曲目的编号。当按下en键后就会播放曲目1,同时显示模块上显示编号为1;当按下ch键后就会播放曲目2,同时显示模块上显示编号为2。
除了书本上的两首歌以外,还可以通过其他乐谱来播放其他音乐,但是内存的大小需要进行更改,使得两者相等。
这个实验结合了分频器,显示模块,二选一电路等模块,将以前学习过的知识进行了整合,对我来说是一次很好地锻炼。而且音乐发生器本身也很有趣味,这次实验让我受益匪浅。
2013.7.18