乐曲硬件演奏电路设计
一、 实验目的:学习利用数控分频器设计硬件乐曲演奏电路
二、 实验原理:主系统由三个模块组成,其内部有三个功能模块:tonetaba.vhd,notetabs.vhd,spearera.vhd如图1所示。
图1
1. 音符的频率可由上图中的speakera获得,这是一个数控分频器,由其clk端输入一较高频率(12MHz)的信号,通过speakera分频后由spkout输出。
2. 音符的持续时间需根据乐曲的速度及每个音符的节拍数来确定,图1中的tonetaba的功能首先是为speakera提供决定所发音符的分频预置数,而此数在speakera输入口停留的时间即为此音符的节拍值。模块tonetaba是乐曲简谱码对应的分频预置数查表电路,其中设置了“梁祝”乐曲的全部音符锁对应的分频预置数,共13个,每一个音符的停留时间由音乐节拍和音调发生器模块notetabs的clk的输入频率决定,在此为4Hz。这13个值的输出由对应的tonetaba的4位输入值index[3..0]确定,而index[3..0]最多由16种可选值。输向tonetaba中index[3..0]的值tonetabaindex[3..0]的输出值与持续时间由模块notetabs决定。
3. 在notetabs中设置了一个8位二进制计数器(最大值位138),作为音符数据ROM的地址发生器。这个计数器的计数频率选为4MHz,即每一个数值的停留时间为0.25s,恰为当全音符设为1秒时。四四拍的4分音符持续时间。随着notetabs中的计数器按4MHz的时钟速度作加法计数时,即随地址值递增时,音符数据ROM中的音符数据将从ROM中通过index[3..0]端口输向tonetaba模块,“梁祝”乐曲就开始连续自然的演奏起来了。
三、 系统框图
图2
四、 系统流程图
图3
五、 实验内容
1. 定制图1中的notetabs模块中的音符数据ROM“music”.该ROM中的音符数据如下:
width=4;
depth=256;
address_radix=hex;
data_radix=dec;
content begin
00:3;01:3;02:3;03:3;04:5;05:5;06:5;07:6;08:8;09:8;
10:8;11:9;12:6;13:8;14:5;15:5;16:12;17:12;18:15;19:9;
20:13;21:12;22:10;23:12;24:9;25:9;26:9;27:9;28:9;29:9;
30:9;31:0;32:9;33:9;34:9;35:10;36:7;37:7;38:6;39:6;
40:5;41:5;42:5;43:6;44:8;45:8;46:9;47:9;48:3;49:3;
50:8;51:8;52:6;53:5;54:6;55:8;56:5;57:5;58:5;59:5;
60:5;61:5;62:5;63:5;64:10;65:10;66:10;67:12;68:7;69:7;
70:9;71:9;72:6;73:8;74:5;75:5;76:5;77:5;78:5;79:5;
80:3;81:5;82:3;83:3;84:5;85:6;86:7;87:9;88:6;89:6;
90:6;91:6;92:6;93:6;94:5;95:6;96:8;97:8;98:8;99:9;
100:12;101:12;102:12;103:10;104:9;105:9;106:10;107:9;108:8;109:8;
110:6;111:5;112:3;113:3;114:3;115:3;116:8;117:8;118:8;119:8;
120:6;121:8;122:6;123:5;124:3;125:5;126:6;127:8;128:5;129:5;
130:5;131:5;132:5;133:5;134:5;135:5;136:5;137:0;138:0;
end;
注意该数据表中的数据位宽、深度和数据的表达类型。最后对ROM进行仿真,其仿真图如下图4示.
图4
2. 根据给出的乘法器逻辑原理图及其各模块的VHDL描述,在MaxplusII上完成全部的设计,包括编辑、编译、综合和仿真等操作。绘出仿真图(如图4示)。
3. 硬件验证,选择实验电路模式1,先将引脚锁定,使CLK12Mhz与clock09相接,接受12MHz时钟频率;CLK8Hz与clock2相接,接受4Hz频率,发音输出SPKOUT接speaker;与演奏发音相对应的简码输出显示可由CODE1在数码管5显示;HIGH1为高8度音指示,可由发光管D5指示,最后向目标芯片下载SOF逻辑文件。
六、 主要仪器设备
GW48CK/ES EDA 系统和GWDVP-B应用板。
七、 操作方法和实验步骤
1.硬件演奏电路顶层设计:
-- ============================================================
-- File Name: e_piano.vhd
-- edit:hulei
-- email:hulei920@yahoo.com.cn
-- date:2006.12.26
--============================================================
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY e_piano IS
PORT ( clk12MHz:in std_logic;
clk8Hz: in std_logic;
code1:out std_logic_vector(3 downto 0);
high1:out std_logic;
spkout:out std_logic);
END;
architecture one of e_piano is
component notetabs
port( clk:in std_logic;
toneindex:out std_logic_vector(3 downto 0));
end component;
component tonetaba
port( index:in std_logic_vector(3 downto 0);
code:out std_logic_vector(3 downto 0);
high:out std_logic;
tone:out std_logic_vector(10 downto 0));
end component;
component speakera
port(clk:in std_logic;
tone:in std_logic_vector(10 downto 0);
spks:out std_logic);
end component;
signal tone:std_logic_vector(10 downto 0);
signal toneindex:std_logic_vector(3 downto 0);
begin
u1:notetabs port map(clk=>clk8Hz,toneindex=>toneindex);
u2:tonetaba port map(index=>toneindex,tone=>tone,code=>code1,high=>high1);
u3:speakera port map(clk=>clk12MHz,tone=>tone,spks=>spkout);
end;
2.梁祝音乐的ROM程序:
-- ===========================================================
-- File Name: music.vhd
-- Megafunction Name(s):
-- lpm_rom
-- edit:hulei
-- email:hulei920@yahoo.com.cn
-- date:2006.12.26
--============================================================
-- ************************************************************
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY music IS
PORT
(
address : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
inclock : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END music;
ARCHITECTURE SYN OF music IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0);
COMPONENT lpm_rom
GENERIC (
lpm_width : NATURAL;
lpm_widthad : NATURAL;
lpm_address_control : STRING;
lpm_outdata : STRING;
lpm_file : STRING
);
PORT (
address : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
inclock : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(3 DOWNTO 0);
lpm_rom_component : lpm_rom
GENERIC MAP (
LPM_WIDTH => 4,
LPM_WIDTHAD => 8,
LPM_ADDRESS_CONTROL => "REGISTERED",
LPM_OUTDATA => "UNREGISTERED",
LPM_FILE => "D:/maxplus_work/design/liangzhu.mif"
)
PORT MAP (
address => address,
inclock => inclock,
q => sub_wire0
);
3.notetabs程序:
--============================================================
-- File Name: notetabs.vhd
--edit:hulei
--email:hulei920@yahoo.com.cn
-- date:2006.12.26
--============================================================
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_unsigned.all;
entity notetabs is
port( clk : IN STD_LOGIC ;
toneindex : out std_logic_vector(3 downto 0));
end;
architecture one of notetabs is
component music
port(address:in std_logic_vector(7 downto 0);
inclock:in std_logic;
q:out std_logic_vector(3 downto 0));
end component;
signal Counter:std_logic_vector(7 downto 0);
begin
cnt8:process(clk)
begin
if Counter=138 then Counter<="00000000";
elsif (clk'event and clk='1')then Counter <=Counter+1;
end if;
end process;
u1:music port map (address=>Counter,q=>toneindex,inclock=>clk);
end;
4.乐曲简谱码对应的分频预置数查表电路程序:
--============================================================
-- File Name: Tonetaba.vhd
-- edit:hulei
-- email:hulei920@yahoo.com.cn
-- date:2006.12.26
--============================================================
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY Tonetaba IS
PORT ( Index : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
CODE : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
HIGH : OUT STD_LOGIC;
Tone : OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END;
ARCHITECTURE one OF Tonetaba IS
BEGIN
Search : PROCESS(Index)
BEGIN
CASE Index IS --transform band, select style,ctrol prenum of tone
WHEN "0000" => Tone <= "11111111111"; CODE <= "0000"; HIGH <= '0';
WHEN "0001" => Tone <= "01100000101"; CODE <= "0001"; HIGH <= '0';
WHEN "0010" => Tone <= "01110010000"; CODE <= "0010"; HIGH <= '0';
WHEN "0011" => Tone <= "10000001100"; CODE <= "0011"; HIGH <= '0';
WHEN "0101" => Tone <= "10010101101"; CODE <= "0101"; HIGH <= '0';
WHEN "0110" => Tone <= "10100001010"; CODE <= "0110"; HIGH <= '0';
WHEN "0111" => Tone <= "10101011100"; CODE <= "0111"; HIGH <= '0';
WHEN "1000" => Tone <= "10110000010"; CODE <= "0001"; HIGH <= '1';
WHEN "1001" => Tone <= "10111001000"; CODE <= "0010"; HIGH <= '1';
WHEN "1010" => Tone <= "11000000110"; CODE <= "0011"; HIGH <= '1';
WHEN "1100" => Tone <= "11001010110"; CODE <= "0101"; HIGH <= '1';
WHEN "1101" => Tone <= "11010000110"; CODE <= "0110"; HIGH <= '1';
WHEN "1111" => Tone <= "11011000000"; CODE <= "0001"; HIGH <= '1';
WHEN OTHERS =>null;
END CASE;
END PROCESS;
END;
5.音调发生器模块程序:
-- ===========================================================
-- File Name: Speakera.vhd
-- edit:hulei
-- email:hulei920@yahoo.com.cn
-- date:2006.12.26
--============================================================
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY Speakera IS
PORT ( clk : IN STD_LOGIC;
Tone : IN std_logic_vector(10 downto 0);
SpkS : OUT STD_LOGIC );
END;
ARCHITECTURE one OF Speakera IS
SIGNAL PreCLK , FullSpkS : STD_LOGIC;
BEGIN
DivideCLK : PROCESS(clk)
VARIABLE Count4 : std_logic_vector(3 downto 0);
BEGIN
PreCLK <= '0';
IF Count4 >11 THEN PreCLK <= '1'; Count4 := "0000";
ELSIF clk'EVENT AND clk='1' THEN Count4 := Count4 + 1;
END IF;
END PROCESS;
GenSpkS : PROCESS(PreCLK, Tone)
VARIABLE Count11 : std_logic_vector(10 downto 0);
BEGIN
IF PreCLK'EVENT AND PreCLK = '1' THEN
IF Count11=16#7FF# THEN Count11 := Tone; FullSpkS <= '1';
ELSE Count11:=Count11 + 1; FullSpkS <= '0';
END IF;
END IF;
END PROCESS;
DelaySpkS : PROCESS(FullSpkS)
VARIABLE Count2 : STD_LOGIC;
BEGIN
IF FullSpkS'EVENT AND FullSpkS = '1' THEN Count2 := NOT Count2;
IF Count2 = '1' THEN SpkS <= '1';
ELSE SpkS <= '0';
END IF;
END IF;
END PROCESS;
END;
程序调试综合完毕后,打开试验板电源,下载到目标芯片。步骤如下图示:
图5
即可欣赏由硬件演奏的乐曲“梁祝”。
八、 参考文献
《EDA技术实用教程》(第二版) 潘松 黄继业 科学出版社
《在系统编程技术实验讲义》 谭敏 胡云龙 合肥学院电子信息与电气工程系