1、 电子琴设计电子琴设计设计要求n设计一个八音电子琴。n由键盘输入控制音响,同时可自动演奏乐曲。n用户可以将自己编制的乐曲存入电子琴,演奏时可选择键盘输入乐曲或者已存入的乐曲。系统组成n系统由数控分频器和乐曲存储模块组成。n数控分频器对FPGA的基准频率进行分频,得到与各个音阶对应的频率输出。n乐曲存储模块产生节拍控制和音阶选择信号,即在此模块中可存放一个乐曲曲谱真值表,由一个计数器来控制此真值表的输出,而由计数器的计数时钟信号作为乐曲节拍控制信号。模块设计 n1.顶层模块的设计n2.自动演奏模块(automusic)的设计 n3.音调发生器(tone)模块的设计n4.数控分频模块(speake
2、r)的设计 1.顶层模块的设计n顶层模块由乐曲自动演奏(automusic),音调发生器(tone)和数控分频器(speaker)三个模块组成。n其中乐曲演奏部分又包括了键盘编码。n设置一个自动演奏/键盘输入切换auto,即当auto=“0”时,选择自动演奏音乐存储器里面的乐曲,auto=“1”时,选择键盘输入的信号。顶层设计原理图 2.自动演奏模块(automusic)的设计n音乐存储模块的作用是产生8位发声控制输入index。n当 auto为“0”时,由存储在此模块中的8位二进制数作为发声控制输入,可自动演奏乐曲。n此模块的VHDL程序中包括两个进程,首先是对时基脉冲进行分频得到4Hz的脉
3、冲,作为第二个进程的时钟信号,它用来控制每个音阶之间的停顿时间,1/4=0.25s;第二个进程是音乐的存储,可根据需要编写不同的乐曲。3.音调发生器(tone)模块的设计n音调发生器的作用是产生获得音阶的分频预置值。n当8位发声控制输入index中的某一位为高电平时,则对应某一音阶的数值将在端口tone输出,该数值即为该音阶的分频预置值,分频预置值控制数控分频器来对4MHz的脉冲进行分频,由此可得到每个音阶对应的频率。n例如输入index=“00000010”,即对应的按键是2,产生的分频系数便是6809;code输出对应该音阶简谱的显示数码;high输出指示音阶高8度,低电平有效。4.数控分
4、频模块(speaker)的设计n数控分频模块对时基脉冲进行分频,得到与1、2、3、4、5、6、7七个音符对应频率。n该模块的VHDL程序中包含了三个进程。n首先对FPGA的32MHz的时基脉冲进行分频得到8MHz的脉冲,n然后按照tone1输入的分频系数对8MHz的脉冲再次分频,得到所需要的音符频率。n第三个进程的作用是在音调输出时再进行二分频,将脉冲展宽,使扬声器有足够发声功率。电子琴程序设计与仿真电子琴程序设计与仿真n1.顶层程序与仿真n2.音阶发生器程序与仿真n3.数控分频模块程序与仿真n4.自动演奏模块程序与仿真 1.顶层程序与仿真n-文件名:top.vhdn-功能:顶层文件n-最后修
5、改日期:2004.3.20nlibrary IEEE;nuse IEEE.STD_LOGIC_1164.ALL;nuse IEEE.STD_LOGIC_ARITH.ALL;nuse IEEE.STD_LOGIC_UNSIGNED.ALL;nentity top isnPort(clk32MHz :in std_logic;-32MHz系统时钟n handTOauto:in std_logic;-键盘输入/自动演奏n code1 :out std_logic_vector(6 downto 0);-音符显示信号n index1 :in std_logic_vector(7 downto 0);-
6、键盘输入信号n high1 :out std_logic;-高低音节信号n spkout :out std_logic);-音频信号nend top;narchitecture Behavioral of top isncomponent automusicn Port(clk:in std_logic;n Auto:in std_logic;n index2:in std_logic_vector(7 downto 0);n index0:out std_logic_vector(7 downto 0);nend component;ncomponent tonen Port(index:i
7、n std_logic_vector(7 downto 0);n code:out std_logic_vector(6 downto 0);n high:out std_logic;n tone0:out integer range 0 to 2047);nend component;ncomponent speakern Port(clk1:in std_logic;n tone1:in integer range 0 to 2047;n spks:out std_logic);nend component;nsignal tone2:integer range 0 to 2047;nsi
8、gnal indx:std_logic_vector(7 downto 0);nbeginn u0:automusic port map(clk=clk32MHZ,index2=index1,index0=indx,Auto=handtoAuto);n u1:tone port map(index=indx,tone0=tone2,code=code1,high=high1);n u2:speaker port map(clk1=clk32MHZ,tone1=tone2,spks=spkout);nend Behavioral;(顶层文件仿真图)2.音阶发生器程序与仿真n-文件名:tone.v
9、hd。n-功能:音阶发生器程序。n-最后修改日期:2004.4.13。nlibrary IEEE;nuse IEEE.STD_LOGIC_1164.ALL;nuse IEEE.STD_LOGIC_ARITH.ALL;nuse IEEE.STD_LOGIC_UNSIGNED.ALL;nentity tone isnPort(index:in std_logic_vector(7 downto 0);-音符输入信号ncode :out std_logic_vector(6 downto 0);-音符显示信号nhigh :out std_logic;-高低音显示信号ntone0:out intege
10、r range 0 to 2047);-音符的分频系数nend tone;narchitecture Behavioral of tone isnbeginnsearch:process(index)-此进程完成音符到音符的分频系数译码,音符的显示,高低音阶nbeginncase index isnwhen 00000001=tone0=773;code=1001111;high tone0=912;code=0010010;high tone0=1036;code=0000110;high tone0=1116;code=1001100;high tone0=1197;code=010010
11、0;high tone0=1290;code=0100000;high tone0=1372;code=0001111;high tone0=1410;code=0000000;high tone0=2047;code=0000001;high=0;nend case;nend process;nend Behavioral;(音阶发生器仿真图)3.数控分频模块程序与仿真n-文件名:speaker.vhd。n-功 能:实现数控分频。n-最后修改日期:20004.3.19。nlibrary IEEE;nuse IEEE.STD_LOGIC_1164.ALL;nuse IEEE.STD_LOGIC
12、_ARITH.ALL;nuse IEEE.STD_LOGIC_UNSIGNED.ALL;nentity speaker isnPort(clk1 :in std_logic;-系统时钟ntone1:in integer range 0 to 2047;-音符分频系数nspks :out std_logic);-驱动扬声器的音频信号nend speaker;narchitecture Behavioral of speaker isnsignal preclk,fullspks:std_logic;nbeginnpulse1:process(clk1)-此进程对系统时钟进行4分频nvariabl
13、e count:integer range 0 to 8;nbeginn if clk1event and clk1=1 then count:=count+1;n if count=2 then preclk=1;n elsif count=4 then preclk=0;count:=0;n end if;n end if;nend process pulse1;ngenspks:process(preclk,tone1)-此进程按照tone1输入的-分频系数对8MHz的脉冲再次分频,得到所需要的音符频率nvariable count11:integer range 0 to 2047;n
14、Beginn if preclkevent and preclk=1 thenn if count11tone1 then count11:=count11+1;fullspks=1;n else count11:=0;fullspks=0;n end if;n end if;nend process;ndelaysps:process(fullspks)-此进程对fullspks进行2分频nvariable count2:std_logic:=0;nbeginn if fullspksevent and fullspks=1 then count2:=not count2;n if coun
15、t2=1 then spks=1;n else spks=0;n end if;n end if;nend process;nend Behavioral;(数控分频模块仿真图)4.自动演奏模块程序与仿真n-文件名:automusic.vhdn-功 能:实现自动演奏功能。n-最后修改日期:2004.3.19。nlibrary IEEE;nuse IEEE.STD_LOGIC_1164.ALL;nuse IEEE.STD_LOGIC_ARITH.ALL;nuse IEEE.STD_LOGIC_UNSIGNED.ALL;nentity automusic isnPort(clk,Auto:in s
16、td_logic;-系统时钟;键盘输入/自动演奏nindex2:in std_logic_vector(7 downto 0);-键盘输入信号nindex0:out std_logic_vector(7 downto 0);-音符信号输出nend automusic;narchitecture Behavioral of automusic isnsignal count0:integer range 0 to 31;-changensignal clk2:std_logic;nbeginnpulse0:process(clk,Auto)-此进程完成对系统时钟8M的分频,得到4Hz的信号clk
17、2nvariable count:integer range 0 to 8000000;nbeginn if Auto=1 then count:=0;clk2=0;n elsif clkevent and clk=1 then count:=count+1;n if count=4000000(4)then clk2=1;n elsif count=8000000(8)then clk2=0;count:=0;n end if;n end if;nend process;nmusic:process(clk2)-此进程完成自动演奏部分曲的地址累加nbeginn if clk2event an
18、d clk2=1 thenn if count0=31 then count0=0;n else count0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 index0 null;n end case;nelse index0=index2;-键盘输入音符信号输出nend if;nend process;nend Behavioral;n注:由于输入频率太高,实验条件所限,如按源程序仿真将 看不到输出波形,因此将原脉冲的分频点4000000和 8000000改为4和8,得到如图的仿真结果,在实际烧制 芯片中不作此处理。(自动演奏模块仿真图)