梁祝乐曲_乐曲硬件演奏电路的VHDL设计_eda课程设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、设计题目:乐曲硬件演奏电路的VHDL设计
二、设计目标:
了解一般乐曲演奏电路设计设计方法,学习VHDL语言,熟悉EDA设计软件QuartusII和MAX+plusⅡ,加强独立完成电子设计的能力。

(1)能够播放“梁祝”乐曲。

(2)能够通过LED显示音阶。

(3)(选作)具有“播放/停止”功能,并在此基础上实现“按键演奏”的电子琴功能。

主芯片型号为FLEX10K10LC84-4
三、实验电路的工作原理:(演奏电路逻辑图)
组成乐曲的每个音符的发音频率值及其持续的时间是乐曲能够连续演奏所需的两个基本要素,设计演奏电路的关键就是获得这两个要素所对应的数值以及通过纯硬件的手段来利用这些数值实现所希望乐曲的演奏效果。

演奏电路逻辑图有三部分:音乐节拍和音调发生器、简谱码对应的分频预置数查表电路、数控分频与演奏发生器。

演奏电路逻辑图:
四、设计内容:
1.完成程序的编辑工作。

2.将音乐数据制作成LMP_ROM文件.
3.将程序加载到MAX+plusⅡ中进行编译、仿真,并保存仿真结果。

4.到实验室进行下载验证。

引脚进行锁定,然后下载到实验芯片中观察实验结果。

五、仿真结果:
1.音乐节拍和音调发生器(NoteTabs.VHD)
notetabs模块中设置了一个8位二进制计数器(计数最大值138),作为音符数据ROM的地址发生器。

这个计数器的计数频率选为4Hz,即每一个计数值的停留时间为0.25秒,恰为当全音符设为1秒时,四四拍的4分音符持续时间。

随着notetabs模块中的计数器按4Hz的时钟速率作为加法计数时,即随地址值递增时,音符数据ROM中的音符数据将从ROM中通过ToneIndex[3..0]端口输向ToneTaba模块,“梁祝”乐曲就开始连续自然的演奏起来了。

Notetabs模块仿真图:
2.简谱码对应的分频预置数查表电路(ToneTaba.VHD)
音符的持续时间需根据乐曲的速度及每个音符的节拍数来确定,tonetaba 模块的功能首先是为speakera提供决定所发音符的预置数,而此数在speakera 输入口停留的时间即为此音符的节拍值。

Tonetaba模块是乐曲简码对应的分频预置数查表电路。

其中设置了“梁祝”乐曲全部音符所对应的分频预置数,共13个,每一音符的停留时间由音乐节拍和音调发生器模块NoteTabs的clk的输入频率决定。

这13个值的输出由对应于ToneTaba的4位输入值Index[3..0]确
定,而Index[3..0]最多有16种可选值。

输向ToneTaba中Index[3..0]的值ToneIndex[3..0]的输出值与持续时间有模块notetabs决定。

Tonetaba仿真图:
4.数控分频与演奏发生器(Speakera.VHD)
音符的频率可由次模块获得,这是一个数控分频器,由其clk端输入一个具有较高频率的信号,通过speakera分频后由spkout输出,由于直接从数控分频器中出来的输出信号是脉冲较窄的脉冲信号,为了有助于驱动扬声器,需另加一个D 触发器以均衡其占空比,但这时的频率是原来的1/2。

Speakera对clk输入信号的分频的预置数Tone[10..0]与spkout的输出频率就有了对应关系。

Sperkera模块仿真图:
5.《梁祝》music.vhd(音乐数据):
将数据保存为.mif格式然后制作成LMP_ROM文件。

六、实验结果:(程序下载验证是否通过)
试验成功!
将设计出的演奏电路的程序经过编译(Compiler)后,选择FLEX10K系列中EPF10K10LC84-4作为目标器件(Assign/Device),并进行管脚锁定(Floorplan Editor)。

器件编程(Programmer),将编译生成的*.sof文件下载到目标芯片。

观察到数码管5显示出演奏时的音乐简谱,发光二极管D5指示音调高低,同时实验箱自带蜂鸣器(Speaker)奏出“梁祝”那凄美动人的旋律,实验成功。

七、总结:
本次乐曲硬件演奏电路的VHDL设计主要采用数控分频原理来实现,在本次EDA课程设计中,我与其他同学相互交流,相互学习,提高了用VHDL语言编程的技能及进一步加强了MAX+plusⅡ对这种EDA流行软件的应用,通过这次设计,我们温故了已学的理论知识和实践操作技能,同时也学习了更多的新的知识和技能,为以后进一步的学习和工作打下了坚实的基础。

本设计得到的电路可以作为一个乐曲演奏模块,如果要演奏出另外一首曲子,只需将该曲子出现的简谱分频预置数写入ToneTaba.VHD,再将该曲子的节拍表制作成ROM文件输入到NoteTabs.VHD中,编译后,编程下载即可。

具体代码:
library ieee;
use ieee.std_logic_1164.all;
entity songer is
port(clk4MHz:in std_logic;
clk4Hz:in std_logic;
clk:in std_logic;
sel:out std_logic_vector(2 downto 0);
sm:out std_logic_vector(6 downto 0);
spk:out std_logic);
end;
architecture one of songer is
component notetabs
port(clk:in std_logic;
toneindex:out integer range 0 to 15);
end component;
component tonetaba
port(index:in integer range 0 to 15;
low:out std_logic_vector(3 downto 0);
mid:out std_logic_vector(3 downto 0);
high:out std_logic_vector(3 downto 0);
tone:out integer range 0 to 16#1FFF#);
end component;
component speakera
port(clk:in std_logic;
tone:in integer range 0 to 16#1FFF#;
spks:out std_logic);
end component;
signal tone:integer range 0 to 16#1FFF#;
signal toneindex:integer range 0 to 15;
signal q_s:std_logic_vector(3 downto 0);
signal tmp:integer range 0 to 2;
signal low1,mid1,high1:std_logic_vector(3 downto 0);
begin
u1:notetabs port map(clk=>clk4Hz,toneindex=>toneindex);
u2:tonetaba port
map(index=>toneindex,tone=>tone,low=>low1,mid=>mid1,high=>high1); u3:speakera port map(clk=>clk4MHz,tone=>tone,spks=>spk);
process(clk)
begin
if (clk'event and clk='1')then
tmp<=tmp+1;
end if ;
end process;
process(tmp)
begin
if tmp=0 then q_s<=low1;
sel<="001";
elsif tmp=1 then q_s<=mid1;
sel<="010";
elsif tmp=2 then q_s<=high1;
sel<="100";
end if ;
end process;
process(q_s)
begin
case q_s is
when"0000"=>sm<="1111110";
when"0001"=>sm<="0110000";
when"0010"=>sm<="1101101";
when"0011"=>sm<="1111001";
when"0100"=>sm<="0110011";
when"0101"=>sm<="1011011";
when"0110"=>sm<="1011111";
when"0111"=>sm<="1110000";
when"1000"=>sm<="1111111";
when"1001"=>sm<="1111011";
when others =>sm<="0000000";
end case;
end process;
end;
音乐节拍和音调发生器(NoteTabs.VHD)LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL; ENTITY NoteTabs IS
PORT (clk:IN STD_LOGIC;
ToneIndex : OUT integer range 0 to 15); END;
ARCHITECTURE one OF NoteTabs IS SIGNAL Counter :integer range 0 to 138; BEGIN
CNT8 :PROCESS(clk)
BEGIN
IF Counter=138 THEN Counter <= 0;
ELSIF clk'EVENT AND clk = '1' THEN Counter <= Counter+1;
END IF;
END PROCESS;
SEARCH:PROCESS(COUNTER) begin
case counter is
when 00=>toneindex<=3;
when 01=>toneindex<=3;
when 02=>toneindex<=3;
when 03=>toneindex<=3;
when 04=>toneindex<=5;
when 05=>toneindex<=5;
when 06=>toneindex<=5;
when 07=>toneindex<=6;
when 08=>toneindex<=8;
when 09=>toneindex<=8;
when 10=>toneindex<=8;
when 11=>toneindex<=9;
when 12=>toneindex<=6;
when 13=>toneindex<=8;
when 14=>toneindex<=5;
when 15=>toneindex<=5;
when 16=>toneindex<=12;
when 17=>toneindex<=12;
when 18=>toneindex<=12;
when 19=>toneindex<=15;
when 20=>toneindex<=13;
when 21=>toneindex<=12;
when 22=>toneindex<=10;
when 23=>toneindex<=12;
when 24=>toneindex<=9;
when 25=>toneindex<=9;
when 26=>toneindex<=9;
when 27=>toneindex<=9;
when 28=>toneindex<=9;
when 29=>toneindex<=9;
when 30=>toneindex<=9;
when 31=>toneindex<=0;
when 32=>toneindex<=9;
when 33=>toneindex<=9;
when 34=>toneindex<=9;
when 35=>toneindex<=10;
when 36=>toneindex<=7;
when 37=>toneindex<=7;
when 38=>toneindex<=6;
when 40=>toneindex<=5; when 41=>toneindex<=5; when 42=>toneindex<=5; when 43=>toneindex<=6; when 44=>toneindex<=8; when 45=>toneindex<=8; when 46=>toneindex<=9; when 47=>toneindex<=9; when 48=>toneindex<=3; when 49=>toneindex<=3; when 50=>toneindex<=8; when 51=>toneindex<=8; when 52=>toneindex<=6; when 53=>toneindex<=5; when 54=>toneindex<=6; when 55=>toneindex<=8; when 56=>toneindex<=5; when 57=>toneindex<=5; when 58=>toneindex<=5; when 59=>toneindex<=5; when 60=>toneindex<=5; when 61=>toneindex<=5; when 62=>toneindex<=5; when 63=>toneindex<=5; when 64=>toneindex<=10; when 65=>toneindex<=10; when 66=>toneindex<=10; when 67=>toneindex<=12; when 68=>toneindex<=7; when 69=>toneindex<=7; when 70=>toneindex<=9; when 71=>toneindex<=9; when 72=>toneindex<=6; when 73=>toneindex<=8; when 74=>toneindex<=5; when 75=>toneindex<=5; when 76=>toneindex<=5; when 77=>toneindex<=5; when 78=>toneindex<=5; when 79=>toneindex<=5; when 80=>toneindex<=3; when 81=>toneindex<=5; when 82=>toneindex<=3;
when 84=>toneindex<=5; when 85=>toneindex<=6; when 86=>toneindex<=7; when 87=>toneindex<=9; when 88=>toneindex<=6; when 89=>toneindex<=6; when 90=>toneindex<=6; when 91=>toneindex<=6; when 92=>toneindex<=6; when 93=>toneindex<=6; when 94=>toneindex<=5; when 95=>toneindex<=6; when 96=>toneindex<=8; when 97=>toneindex<=8; when 98=>toneindex<=8; when 99=>toneindex<=9; when 100=>toneindex<=12; when 101=>toneindex<=12; when 102=>toneindex<=12; when 103=>toneindex<=10; when 104=>toneindex<=9; when 105=>toneindex<=9; when 106=>toneindex<=10; when 107=>toneindex<=9; when 108=>toneindex<=8; when 109=>toneindex<=8; when 110=>toneindex<=6; when 111=>toneindex<=5; when 112=>toneindex<=3; when 113=>toneindex<=3; when 114=>toneindex<=3; when 115=>toneindex<=3; when 116=>toneindex<=8; when 117=>toneindex<=8; when 118=>toneindex<=8; when 119=>toneindex<=8; when 120=>toneindex<=6; when 121=>toneindex<=8; when 122=>toneindex<=6; when 123=>toneindex<=5; when 124=>toneindex<=3; when 125=>toneindex<=5; when 126=>toneindex<=6;
when 128=>toneindex<=5;
when 129=>toneindex<=5;
when 130=>toneindex<=5;
when 131=>toneindex<=5;
when 132=>toneindex<=5;
when 133=>toneindex<=5;
when 134=>toneindex<=5;
when 135=>toneindex<=5;
when 136=>toneindex<=0;
when 137=>toneindex<=0;
when 138=>toneindex<=0;
when others=>null;
end case;
end process;
END;
简谱码对应的分频预置数查表电路(ToneTaba.VHD)
library ieee;
use ieee.std_logic_1164.all;
entity tonetaba is
port( index:in integer range 0 to 15;
low:out std_logic_vector(3 downto 0);
mid:out std_logic_vector(3 downto 0);
high:out std_logic_vector(3 downto 0);
tone:out integer range 0 to 16#1FFF#);
end;
architecture one of tonetaba is
begin
search:process(index)
begin
case index is
when 0=>tone<=8191;low<="0000";mid<="0000";high<="0000";
when 3=>tone<=2124;low<="0011";mid<="0000";high<="0000";
when 5=>tone<=3089;low<="0101";mid<="0000";high<="0000";
when 6=>tone<=3646;low<="0110";mid<="0000";high<="0000";
when 7=>tone<=4141;low<="0111";mid<="0000";high<="0000";
when 8=>tone<=4369;low<="0000";mid<="0001";high<="0000";
when 9=>tone<=4786;low<="0000";mid<="0010";high<="0000";
when 10=>tone<=5157;low<="0000";mid<="0011";high<="0000";
when 12=>tone<=5640;low<="0000";mid<="0101";high<="0000";
when 13=>tone<=5918;low<="0000";mid<="0110";high<="0000";
when 15=>tone<=6280;low<="0000";mid<="0000";high<="0001";
when others=>null;
end case;
end process;
end;
数控分频与演奏发生器(Speakera.VHD)
library ieee;
use ieee.std_logic_1164.all;
entity speakera is
PORT (clk : IN STD_LOGIC;
Tone : IN integer range 0 to 16#1FFF#;
SpkS : OUT STD_LOGIC );
END;
ARCHITECTURE one OF Speakera IS
SIGNAL PreCLK, FullSpkS : STD_LOGIC; BEGIN
DivideCLK : PROCESS(clk)
V ARIABLE Count4 : integer range 0 to 15 ; BEGIN
PreCLK <= '0';
IF Count4>13 THEN
PreCLK <= '1'; Count4 := 0;
ELSIF clk'EVENT AND clk = '1' THEN
Count4 := Count4 + 1;
END IF;
END PROCESS;
GenSpkS : PROCESS(PreCLK, Tone)
V ARIABLE Count13 : integer range 0 to 16#1FFF#; BEGIN
IF PreCLK'EVENT AND PreCLK = '1' THEN
IF Count13 = 16#1FFF# THEN
Count13 := Tone ;
FullSpkS <= '1';
ELSE Count13 := Count13 + 1;
FullSpkS <= '0';
END IF;
END IF;
END PROCESS;
DelaySpkS : PROCESS(FullSpkS)
V ARIABLE 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;
设置引脚
Clk 2
Clk4hz 1
Clk4MHZ 43
Sel0 5
Sel1 6
Sel2 7
Sm0 24
Sm1 23
Sm2 22
Sm3 21
Sm4 19
Sm5 18
Sm6 17
Spk 3
波形图:Speakera.vhd
Tonetaba.vhd
Notetabs.vhd
Songer.vhd。

相关文档
最新文档