当前位置:首页 >> 信息与通信 >>

具有自动乐曲演奏功能的电子琴设计


具有自动乐曲演奏功能的电子琴设计

先给出设计结果视频链接:

具有自动乐曲演奏功能的电子琴-视频实录

本文为本人于 2012 年下学期做的 EDA 数字系统设计,文章详细介绍了“具有自动乐 曲演奏功能的电子琴”的 FPGA 设计原理与方法,使用了 ROM 存储音符和节拍,矩阵键盘 控制整个系统。 一、选题目的 电子设计自动化,简称 EDA(Electronic Design Automation) ,发展迅速,应用范围 日益扩大。它以计算机为工具,设计者在 EDA 软件平台上,用硬件描述语言 VHDL 完成设 计文件, 然后由计算机自动地完成逻辑编译、 化简、 分割、 综合、 优化、 布局、 布线和仿真, 直至对于特定目标芯片的适配编译、逻辑映射和编程下载等工作。EDA 技术的出现,极大 地提高了电路设计的效率和可操作性,减轻了设计者的劳动强度。 本文应用 VHDL 硬件描述语言, 以 QuartusⅡ8.0 为开发工具设计了一个具有自动演奏乐 曲功能的电子琴系统,它能将预先存储在 ROM 中的多首乐曲自动播放出来,并同时显示音 符,此外,还具有电子琴弹奏的功能。选题新颖、实用,趣味性、综合性较强。 二、设计目标 1. 采用 44 矩阵键盘作为:电子琴按键,高、中、低音选择键,自动播放和电子琴弹奏功能 选择键,乐曲选择键。 2. 使用 ROM 存储乐曲,达到只要在其中存储乐曲音符节拍的信息即可自动播放的目的, 对乐曲的编码要简单易用。 3. 可自动播放《世上只有妈妈好》 、 《长亭送别》 、 《十年》三首歌曲,带选歌和自动循环播 放的功能。

4. 实时显示正在播放的音符。 5. 设计要具有模块化,层次化的特点。 6. 波形仿真时采用时序仿真,以更加贴近实际,使系统的实际效果达到最佳。

三、实现方案 1. 原理框图 具有自动乐曲演奏功能的电子琴系统的原理结构框图如下:

图 1 硬件系统结构框图

图 2 软件系统结构框图

图 3 乐曲自动播放模块结构框图

图 4 乐曲弹奏模块结构框图 2. 设计流程图 具有自动乐曲演奏功能的电子琴系统的 VHDL 程序设计流程图如下图 5:

图 5 程序设计流程图 四、设计过程 1. 音乐基础知识 简谱应该说是一种比较简单易学的音乐记谱法。它的最大好处是仅用 7 个阿拉伯数字 ----1234567, 就能将万千变化的音乐曲子记录并表示出来, 并能使人很快记住而终身不忘; 同时涉及其他的音乐元素也基本可以正确显示。 简谱虽然不是出现在中国, 但是好像只有在 中国得到非常广泛的传播。 乐音的特性:它由四个方面组成:音高、音值、音量、音色。 音高:由物体在一定的时间内震动的次数决定,震动次数多,因则高,反之,则低。

音值:即音的长短,是由音的延续时间的不同而决定的,音的延续时间长,音则长, 反之,则短。 音量:即音的强与弱,由震幅的大小决定,震幅大,音则强,反之,则弱。 音色:有发音体的性质决定,发音体的形状及泛音的多少决定音色的不同,例如,小 提琴、钢琴等各种乐器的音色都是不同的,在合奏时,人们可清楚地辨认。 乐音体系:在音乐使用中有固定音高的音的总和叫乐音体系。 音级:乐音体系中的各音叫音级,音级有基本音级与变化音级两种。 基本音级:在音乐中经常使用的七个具有独立名称的音叫基本音级。基本音级的名称 用字母或唱名两种方式来标记。 音名:用 C、D、E、F、G、A、B 来标记基本音级的叫音名,它表示一定的音高,简 谱中用 1,2,3,4,5,6,7 来标记。 唱名:用 do、re、mi、fa、sol、la、si 作为音级名称的叫唱名。 音符: 用以记录音的长短高低的符号叫音符 (以符头在谱表上的位置来表示音的高低, 以形状表示音的长短,音符有符头、符干、符尾三部分或其中某些部分组成,而在简谱中以 1 2 3 4 5 6 7 或其上下加点来表示不同音高,以短下划线(_)或横(—)来表示音的长短) 。 下面重点介绍组成音乐的两个最基本的要素:每个音符发音的频率及其持续的时间。 1.1 音符和频率的关系 乐曲的十二平均律规定:每 2 个八度音(如简谱中的中音 1 与高音 1)之间的频率相 差一倍。在 2 个八度音之间,又可分为 12 个半音,每 2 个半音的频率比为 。另外,简

谱中的低音 6 的频率为 440Hz,音符 7 到 1 之间、3 到 4 之间为半音,其余为全音。由此 可计算出简谱中从低音 1 至高音 7 之间每个音符的频率,如下表 1 所示: 表 1 简谱中音符与频率的关系

音名 频率(Hz) 音名 频率(Hz) 音名 频率(Hz) 低音 1 261.6 低音 2 293.7 低音 3 329.6 低音 4 349.2 低音 5 392 低音 6 440 低音 7 493.9 1.2 音符的长短 表示音乐的长短需要有一个相对固定的时间概念。简谱里将音符分为全音符、二分音 符、四分音符、十六分音符、三十二分音符等,如下表 2。在这几个音符里面最重要的是四 分音符,它是一个基本参照度量长度,即四分音符为一拍。这里一拍的概念是一个相对时间 度量单位。一拍的长度没有限制,可以是 1 秒 也可以是 2 秒或半秒。假如一拍是一秒的长 度,那么二拍就是两秒;一拍定为半秒的话,两拍就是一秒的长度。一旦这个基础的一拍定 下来,那么比一拍长或短的符号就相对容易了。正如五线谱的附点一样,数字后方加一点会 将音符长度增加一半。 中音 1 523.3 中音 2 587.3 中音 3 659.3 中音 4 698.5 中音 5 784 中音 6 880 中音 7 987.8 高音 1 1046.5 高音 2 1174.7 高音 3 1318.5 高音 4 1396.9 高音 5 1568 高音 6 1760 高音 7 1975.5

表 2 简谱中音符长度 音符名称 全音符 二分音符 记法 时值 编码 16 8

5 — — — 四拍 5— 二拍

四分音符 八分音符 十六分音符 三十二分音符 2. VHDL 程序设计 2.1 顶层文件

5

一拍 半拍

4 2

四分之一拍 1 八分之一拍

采用原理图输入法设计,其原理图如下:

图 6 music_player 原理图 各模块的设计如下。 2.2 音符的编码及音乐的存储 2.2.1 音符的编码 休止符的编码为:0;音符长度的编码见表 2。音名的编码如下表 3 所示:

表 3 音名的编码 音名 编码 音名 编码 音名 编码 低音 1 11 低音 2 12 低音 3 13 低音 4 14 低音 5 15 低音 6 16 低音 7 17 2.2.2 音乐的存储 以十进制将音乐分别存储于 note_rom 和 tick_rom 两个模块中,前者为音 符,后者为 音符的长度,下面给出《世上只有妈妈好》的存储过程。在 Quartus II 主窗体中选择 Tools—MegaWizardPluge-In Manager…,弹出如下对话框,单击 Next 继续。 中音 1 1 中音 2 2 中音 3 3 中音 4 4 中音 5 5 中音 6 6 中音 7 7 高音 1 21 高音 2 22 高音 3 23 高音 4 24 高音 5 25 高音 6 26 高音 7 27

图 7 MegaWizardPluge-In Manager 第一页 按下图选择并填入文件名,点击 Next。

图 8 MegaWizardPluge-In Manager 第二页 由于音符编在 16 到 32 之间,所以 q 选为 5 位即可,容量选为 1024 个字如下图所 示

图 9 数据和地址宽度的选择 在下图中取消“q’output port”前面的勾,点击 Next 继续。

图 10 寄存器信号的选择 在下图中,按图示选择并填入 note_rom.mif,点击 Next 继续。

图 11 指明 ROM 初始化文件

图 12 完成 ROM 的定制 2.2.3 建立 ROM 初始化文件 初始化 ROM 的数据文件有.mif 格式和.hex 格式,这里采用.mif 格式,可以用文本编辑 器编辑,也可以用 Quartus II 自带的功能产生 ROM 数据文件。 定制一个 512*8 的 ROM 的初始化.mif 文件可按下列步骤进行:选择菜单 File | New,在对 话框中选择 Memory Initialization File,然后输入 512 和 8,如下图 13(a)所示,点击 OK

随即打开.mif 文件,如下图 13(b)所示,然后可在其中输入数据,默认为十进制。

(a)ROM 的初始化设置 图 13 ROM 初始化 2.2.4 在 ROM 中存储音乐

(b)初始化的空的 ROM 文件

以《世上只有妈妈好》为例,其简谱如下图所示:

图 14 世上只有妈妈好简谱

根据前述对音符的编码规则, 可知第一个音为中音 6, 时值为

拍, 存储为 6 和 6;

再如第二个音符为中音 5, 时值

拍, 存储为 5 和 2; 又如第五个音符为高音 5, 时值 1 拍,

存储为 21 和 4。依此类推,可将整首乐曲存储如下:

(a)note_rom.mif 文件

(b)tick_rom.mif 文件

图 15 世上只有妈妈好简谱在 ROM 中的存储 其它两首乐曲的存储与此类似, 且存储在同一个 note_rom.mif 和 tick_rom.mif 文件中即可。 3.键盘控制模块 3.1 扫描及编码 矩阵式键盘是一种常见的输入装置,根据其电路连接有共阴极和共阳极两种连接方 式,可以采用逐行或逐列扫描法获得按键值。本文根据实验室提供的共阳极矩阵键盘设计, 其示意图如图 16 所示, 定义各功能键如下图 17 所示, 其中 1~7 对应简谱的 1~7 音符, H、 M、 L 分别为高、 中、 低音选择键, AP (Auto Play) 为自动播放选择键, EO (Electronic Organ) 为电子琴弹奏选择键,Song 为自动播放时的歌曲选择键,三个短“-”代表休止符。

图 16 共阳极矩阵式键盘示意图

图 17 本系统矩阵键盘功能键示意

下面介绍扫描原理,采取逐行扫描法,以 0111、1011、1101、1110 的顺序依次扫 描,然后读取列引脚的电平信号即可判断哪个按键按下。例如,当扫描信号为 1011 时,表 示在扫描第二行,若列读出的电平信号为 1101,则可知第 3 列的键被按下,即第二行第 3 列的键“7”被按下,其它按键依次类推,下表 4 中列出了 4*4 矩阵键盘扫描时的情况 表 4 按键扫描信息对照表 列 0111 1011 1101 1110 1111 行 0111 1 1011 5 1101 AP 2 6 3 7 4 H 无 无 无

EO Song M

1110 -

-

-

L



对 该 矩 阵 键 盘 按 从 上 到 下 、 从 左 至 右 的 顺 序 编 码 , 依 次 为 : 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 。 扫描时,选取的扫描频率为 1KHz,由 1MHz 分频得到,具体见源程序。 3.2 消抖 通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性 作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭 合及断开的瞬间均伴随有一连串的抖动,如右图。抖动时间的长短由按键的机械特性决定, 一般为 5ms~10ms。这是一个很重要的时间参数,在很多场合都要用到。

图 18 按键抖动 常见的消抖方法有采样型防抖微分电路、D 型触发器、移位寄存器、计数器,结合 各消抖法的特点,本文采用计数器法。 3.3 键盘控制模块如右图 9 所示

图 19 键盘控制模块 键盘控制模块(Key_Control.vhd)仿真波形如下图 20 所示:

图 20 键盘控制模块仿真波形 为方便仿真及观察仿真结果, 仿真时采用周期为 100ns 的 clk, 且将 Key_Control.vhd 中的获得 clk_kb 信号的程序中的 if cnt=499 then, (即具体见源程序中斜体注释部分)改为 if cnt=10 then,再将延时近程中 clk_kb 改为 clk,count 改为 3 位,然后对 KBCol[0..3]赋值 (如图) ,即可得到上图所示结果。 注意观察图中圈圈的部分,可以看出,第一个圈,对应“AP”键,他不在音符范围内, 故 Key_Note 为 0,且 play,sel 均为 1,表示选择自动播放;第二个圈,对应“5”键,在音 符范围内,故 Key_Note 为 5;第三个圈,对应“EO”键,他不在音符范围内,故 Key_Note 为 0,且 play,sel 均为 0,表示选择电子琴弹奏;第四个圈,对应“Song”键,产生一个脉 冲,仔细分析还应当发现由于消抖,使输出迟了 1 个扫描时钟(0.001s) ,但对本系统无影

响。 4. 乐曲自动播放模块 此模块的框图如图 3 所示,元件符号如右图下 21 所示,包含以下模块:ROM 数据 读取控制、音符 ROM、节拍 ROM,如下图 22 所示:

图 21 乐曲自动播放模块符号

图 22 乐曲自动播放模块 4.1 ROM 数据读取控制 该分模块从 tick_rom 中读取节拍,控制读取 ROM 数

据的速度,从而实现音乐的节奏。该模块通过可调模值计数器实现,具体参见源程序。 乐曲自动播放模块仿真波形如下:

图 23 乐曲自动播放模块仿真波形 为方便仿真, 将 counter_rom.vhd 源程序中的 CLK_FREQ 这一常量的值改为仿真时 的时钟信号频率 100Hz,三首乐曲的前几个音符如右图所示,第一首的起始音符为中音 6, 时值一又二分之一拍;第二首的起始音符为中音 5,时值为 1 拍;第三首的起始音符为 0, 接着为 1,2,时值分别为二分之一拍、四分之一拍、四分之一拍。对照仿真结果,可知仿真 结果正确,程序正确。

图 24 三首乐曲的第一句简谱

5. 电子琴模块

此模块主要完成将上一级键盘控制模块送来的音符按键进行译码输出,元件符号如 右图 11 所示。 如图 12 所示,使能有效后,开始输出音符码:2,第一个圈中 key 值为 8,说明下 面的音符将转为高音,如后面的 23,26;第二个圈中 key 值为 12, 说明下面的音符将转为 中音,如其后的 6。可见,程序正确无误。

图 25 电子琴模块

图 26 电子琴模块仿真波形 6. 音符发声及显示模块 该模块主要将前端送来的音符码转换成相应的声音频率以驱动扬声器发声,并在七 段数码管(实验室提供的为 八段数码管,但本设计只需七段)上显示音符,且有高 低音指示灯。元件符号如右图。 七段数码管的原理及使用很简单, 在此不再熬述! 本文设计的具有自动乐曲演奏功能的电子琴系统选择的基基准频率为 1MHz, 根据表 1 可计算出对应的音符的分频系数(divider_mod) ,如下表 5:

表 5 1MHz 下简谱中音符分频数 音名 分频系数 音名 分频系数 音名 分频系数 低音 1 3283 低音 2 3405 低音 3 3034 低音 4 2863 低音 5 2551 低音 6 2273 低音 7 2025 中音 1 1911 中音 2 1703 中音 3 1517 中音 4 1432 中音 5 1276 中音 6 1137 中音 7 1012 高音 1 956 高音 2 851 高音 3 758 高音 4 716 高音 5 638 高音 6 568 高音 7 506

为方便仿真,需将 Aud_Pro_Dis.vhd 源程序中的 divider_mod 值改的小些,下面给 出的仿真波形中,将中音 6、低音 6、及高音 6 对应的 divider_mod 值分别改为 40、80、 20,clk 周期为 100ns,分别给 note_code 赋以下值:6,16,26,即中音 6、低音 6、及高音 6。

图 27 音符发声及显示模块仿真波形 由上图可见, 数码管显示均为 6, 但高低音指示灯的值不同, pitch 为高低音指示灯, pitch[1]为高位,且“00”代表中音,“01”代表低音,“10”代表高音。可见仿真结果及程序均正 确。

7. 五二输入或门 由于本系统有自动播放和电子琴弹奏两个模块组成,每次只能其中一个有效,但要 共用音符发声及显示模块, 故需要将输出的音符码相或后送予后级处理, 由于本模块比较简 单,在此仅给出仿真波形,如下。

图 28 五二输入或门 五、遇到问题及解决方法 1. 矩阵键盘的扫描是一个重点和难点,程序写好之初效果并不理想,仔细分析后, 发现是没有消抖造成的,后来加入了消抖的进程,效果得到改善。 2. 电子琴弹奏模块的实现过程中也出现了一个问题: 高、 中、 低音的选择不起作用, 此模块仅有一个进程,如下: process(key,play,EN) variable sign :integer range 0 to 2:=0; begin if play='0' and EN='0' then if key=12 then sign:=0;--mid elsif key=16 then sign:=1;--low elsif key=8 then

sign:=2;--high end if; if key>=1 and key<=7 then--1~7 note_code<=key+10*sign; else note_code<=0;--stop end if; end if; else note_code<=0; sign:=0; end if; end process; 但仿真结果令人惊讶,只能输出高音,仿真波形如下,错误处已经用叉号标记出来

图 29 未加入 clk 时钟信号时的仿真结果

解决办法:给该模块加入时钟驱动,用上升沿触发事件,结果得到了想要的结果,如下图, 程序见该模块源代码。

图 30 加入 clk 时钟信号时的仿真结果 六、实现结果 1.拨动开关,使 start 为 1,此时数码管显示短横,扬声器不发声; 2.按下矩阵键盘的“AP”键, 系统开始自动播放乐曲, 顺序: 《世上只有妈妈好》 、 《长亭送别》 、 《十年》循环播放; 3.按下歌曲选择键:“Song”,自动切换到下一首播放; 4.按下“EO”键,扬声器不发声,按数字键 1~7,发出 do~si 的音符; 5.按下“H”、“M”、“L”键,可切换高、中、低音; 6.拨动开关,使 start 为 0,此时数码管显示短横,扬声器不发声; 本文设计的具有自动演奏乐曲功能的电子琴系统,实现了所有设计目标,效果优秀,极具综 合性、趣味性! 此系统的功能还可以进一步完善, 如增加手动改变音乐播放的节奏、 长时间无按键系统自动 关闭、手动输入音符再自动播放(当然需将 ROM 换成 RAM)等功能。 此系统是我独立开发的一个小型系统,且实现的效果很好,很有成就感,更加激发我搞科研 的热情! 七、编程调试 1. 具有自动演奏乐曲功能的电子琴系统的所有 VHDL 源代码 1.1 顶层文件 music_player.bdf 如下:

图 31 music_player.bdf 文件

1.2 键盘控制模块(Key_Control.vhd)VHDL 源程序如下: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;

entity Key_Control is port (clk,start: in std_logic; KBCol:instd_logic_vector(0 to 3); song:bufferstd_logic; play:outstd_logic;--1music_play; 0:Elc_keyboard; sel:outstd_logic;--1:music_play; 0:Elc_keyboard; Key_Note:buffer integer range 0 to 16; KBRow:bufferstd_logic_vector(0 to 3) );

end entity;

architecture control of Key_Control is signal clk_kb:std_logic; signal cnt:integer range 0 to 1000;

signal temp:STD_LOGIC_VECTOR (7 downto 0); signal state:std_logic_vector(1 downto 0):="00"; signal count:std_logic_vector(1 downto 0):="00"; signal key:integer range 0 to 16; signal keynum:integer range 0 to 16; signal TempKey:integer range 0 to 16; signal song_chg:std_logic:='0';

begin

process(clk) --产生键盘扫描 begin if rising_edge(clk)then if start='1' then if cnt=499 then--仿真时改为 if cnt=10 then clk_kb<=not clk_kb;

cnt<=0; else cnt<=cnt+1; end if; end if; end if; end process; process(clk_kb) begin if rising_edge(clk_kb) then if state="11" then state<="00"; else state<=state+1; end if; end if; end process; process(state) begin case state is when "00"=>KBRow<="1110"; when "01"=>KBRow<="1101";

when "10"=>KBRow<="1011"; when "11"=>KBRow<="0111"; when others =>KBRow<="1111"; end case; end process;

temp<=KBRow&KBCol; process(clk_kb) begin if start='1' then if falling_edge(clk_kb) then if KBCol="1111" then if count="11" then key<=0; count<="00"; else count<=count+1; end if; else --count<="00"; case temp is when"11101110"=>key<=16;

when"11101101"=>key<=15; when"11101011"=>key<=14; when"11100111"=>key<=13; when"11011110"=>key<=12; when"11011101"=>key<=11; when"11011011"=>key<=10; when"11010111"=>key<=9; when"10111110"=>key<=8; when"10111101"=>key<=7; when"10111011"=>key<=6; when"10110111"=>key<=5; when"01111110"=>key<=4; when"01111101"=>key<=3; when"01111011"=>key<=2; when"01110111"=>key<=1; when others =>key<=0; end case; end if; end if; else key<=0; end if;

end process;

process(clk) variable count:std_logic_vector(4 downto 0);--仿真时改为(1 downto 0) begin if rising_edge(clk) then if key/=TempKey then TempKey<=key; count:="00000"; -- 仿真时改为”00” else if count="11111" then--仿真时改为”11” keynum<=key; count:="00000";--仿真时改为”00” else count:=count+1; end if; end if; end if; end process;

process(clk_kb) begin

if start='1'then if(rising_edge(clk_kb))then if(keynum<9 or keynum=12 or keynum=16)then Key_Note<=keynum; song<='0'; else Key_Note<=0; if keynum=11 then song<='1';--产生脉冲 else song<='0'; if(keynum=9)then play<='1'; sel<='1'; elsif(keynum=10)then play<='0'; sel<='0'; end if; end if; end if; end if; else

play<='1'; sel<='0'; Key_Note<=0;--stop song<='0'; end if;

end process; end control;

1.3 电子琴(Electronic_keyboard.vhd)源文件 library ieee; use ieee.std_logic_1164.all;

entity Electronic_keyboard is port (clk:instd_logic; play:instd_logic; EN:instd_logic;--0:Elc_keyboard; key:in integer range 0 to 16; note_code:OUT integer range 0 to 31 ); end entity;

architecture Elc_keyBoard of Electronic_keyboard is

begin process(key,play,EN,clk) variable sign :integer range 0 to 2:=0; begin if play='0' and EN='0' then if(rising_edge(clk))then if key=12 then sign:=0;--mid elsif key=16 then sign:=1;--low elsif key=8 then sign:=2;--high end if; if key>=1 and key<=7 then--1~7 note_code<=key+10*sign; else note_code<=0;--stop end if; end if; else

note_code<=0; sign:=0; end if; end process; end Elc_keyBoard; 1.4 乐曲自动演奏模块(music_Play.bdf)文件

图 32 music_Play.bdf 文件 1.4.1 ROM 数据读取控制模块(counter_rom.vhd)源文件 library ieee; use ieee.std_logic_1164.all; entity counter_rom is port ( tick_num : in integer range 0 to 31; clk : in std_logic;

song play EN q );

: in std_logic; : in std_logic; : in std_logic; : out integer range 0 to 511

end entity;

architecture rtl of counter_rom is constant CLK_FREQ :integer:=1000000;--1MHz constant SONG1_ADDR:integer:=7;--乐曲 1 存储地址 constant SONG2_ADDR:integer:=80;--乐曲 2 存储地址 constant SONG3_ADDR:integer:=184;--乐曲 3 存储地址 constant SONG_LEN:integer:=500; signal SONG_ADDR:integer range 0 to 1000:=0;--乐曲存储地址 signal song_chg :std_logic:='0'; signal chg_ok :std_logic:='0'; signal num:integer range 0 to 2:=0; signal start:std_logic:='0'; --signal meter begin process(song,play,EN)

begin if(start='1')then if (song'event and song='1') then if num<2 then num<=num+1; else num<=0; end if; song_chg<='1'; else end if; case num is when 0=>SONG_ADDR<=SONG1_ADDR;--song1 when 1=>SONG_ADDR<=SONG2_ADDR;--song2 when 2=>SONG_ADDR<=SONG3_ADDR;--song3 when others=>SONG_ADDR<=null; end case; else num<=0; end if; if(chg_ok='1')then song_chg<='0';

end if; end process; -------------------process(play,EN) begin start<=play and EN; end process; ---------ROM 数据读取控制-------------process (clk,start) variable count variable cnt begin if (start='1'and count<SONG_LEN) then if(rising_edge(clk))then if song_chg = '1' then -- Reset the counter to SONG_ADDR count := SONG_ADDR; chg_ok<='1'; cnt:=0; else chg_ok<='0'; end if; : integer range 0 to SONG_LEN; : integer range 0 to 4*CLK_FREQ;

if(cnt<(tick_num*CLK_FREQ)/4)then cnt:=cnt+1; else cnt:=0; count:=count+1; end if; end if; else count:=0; cnt:=0; end if; -- Output the current count q <= count;

end process; end rtl; 1.4.2 note_rom 和 tick_rom 文件的建立,见 2.2.2 音乐的存储

1.5 音符发声和显示模块 library ieee; use ieee.std_logic_1164.all; entity Aud_Pro_Dis is

port(clk : in std_logic; note_code:in integer range 0 to 31; pitch :outstd_logic_vector(1 downto 0); disp7 :out std_logic_vector(6 downto 0); --digtal display sound_out:outstd_logic ); end entity;

architecture behav of Aud_Pro_Dis is

signal divider_mod:integer range 0 to 4096; signal count: integer range 0 to 4096 :=0; begin process(note_code) begin case note_code is when 11 =>divider_mod<=3822;pitch<="01";disp7<="0110000";--low1 when 12 =>divider_mod<=3405;pitch<="01";disp7<="1101101"; when 13 =>divider_mod<=3034;pitch<="01";disp7<="1111001"; when 14 =>divider_mod<=2863;pitch<="01";disp7<="0110011"; when 15 =>divider_mod<=2551;pitch<="01";disp7<="1011011"; when 16 =>divider_mod<=2273;pitch<="01";disp7<="1011111"; --divider_mod

when 17 =>divider_mod<=2025;pitch<="01";disp7<="1110000";--low7 when 1 =>divider_mod<=1911;pitch<="00";disp7<="0110000";--mid1 when 2 =>divider_mod<=1703;pitch<="00";disp7<="1101101"; when 3 =>divider_mod<=1517;pitch<="00";disp7<="1111001"; when 4 =>divider_mod<=1432;pitch<="00";disp7<="0110011"; when 5 =>divider_mod<=1276;pitch<="00";disp7<="1011011"; when 6 =>divider_mod<=1137;pitch<="00";disp7<="1011111";--1137 when 7 =>divider_mod<=1012;pitch<="00";disp7<="1110000";--mid7 when 21 =>divider_mod<=956;pitch<="10";disp7<="0110000";--high1 when 22 =>divider_mod<=851;pitch<="10";disp7<="1101101"; when 23 =>divider_mod<=758;pitch<="10";disp7<="1111001"; when 24 =>divider_mod<=716;pitch<="10";disp7<="0110011"; when 25 =>divider_mod<=638;pitch<="10";disp7<="1011011"; when 26 =>divider_mod<=568;pitch<="10";disp7<="1011111"; when 27 =>divider_mod<=506;pitch<="10";disp7<="1110000";--high7 when 0 =>divider_mod<=0;pitch<="00";disp7<="0000001";--stop when others =>divider_mod<=0;pitch<="00";disp7<="0000001";-end case; end process;

process(clk) begin

--50%占空比偶数分频

if (clk'event and clk='1') then if(divider_mod/=0)then if(count<divider_mod-1)then count<=count+1; else count<=0; end if; if(count<divider_mod/2)then sound_out<='1'; else sound_out<='0'; end if; else sound_out<='0'; end if; end if; end process; end behav;

1.6 五二输入或门(five_or2.vhd) library ieee; use ieee.std_logic_1164.all;

entity five_or2 is port(INA:instd_logic_vector(4 downto 0); INB:instd_logic_vector(4 downto 0); OUTY:outstd_logic_vector(4 downto 0):="00000" ); end five_or2; architecture f_or2 of five_or2 is begin OUTY<=INA or INB; end f_or2; 2. 调试下载运行效果图 各管脚的分配如下图 33 所示。

图 33 引脚分配 运行效果图如下图 34 所示。

图 34 运行效果图 八、对该课程的实施意见及建议 希望能多给些时间练习,做一些更具挑战性,更加高级的设计,以使我们完全掌握 FPGA 的设计方法,并将其应用到工程项目,实际生活中。



相关文章:
电子琴的设计
1.1.2 发挥部分 设计乐曲自动演奏器, 由用户自己编制乐曲存入电子琴, 电子琴可以完成自动演奏功能。 1.2 总体设计方案 1.2.1 设计思路 通过可编程逻辑...
电子琴的设计
系统由乐曲自动演奏模块、音调发生模块和数控分频模块三个部分组成。系统实现 是...超高速硬件描述语言VHDL设计的一个具有若干功能的简易电子琴,其理论基础来源于计...
21按键简易电子琴可自动播放乐曲_图文
。共 7 个音阶信号,进行弹奏; 3) 用指示灯显示节拍; 4) *能对弹奏乐曲...仿真以及对仿真波形的调试 1.2 设计要求(简易电子琴功能) 1、 设计一个能...
用Quartus_II设计电子琴
9 用 Quartus_II 设计电子琴 1.设计题目:用 Quartus_II 设计电子琴 2.设计任务及要求: (1)设计一个八音电子琴。 (2)由键盘输入控制音响,同时可自动演奏乐曲...
电子琴的设计
硬件电子琴电路模块设计一、实验目的: 学习利用数控...songer.v 是顶层设计文件,其内部五个功能模块(...“梁祝”乐曲演奏数据,编写并加载.COE 文件放置 ...
电子琴初学者入门
电子琴初学者入门一 常用指法介绍弹奏乐曲时,指法...各种音色和具有自动伴奏功能,这些是电子琴最基本的...自动伴奏设计的是否丰富,和增加了其他制作,编曲等...
硬件电子琴---《梁祝》乐曲演奏的实现
关于近代电子的硬件电子琴---《梁祝》乐曲演奏的...的工作原理; 3.进一步熟习 Verilog HDL 的设计方法...当乐曲一遍演奏完成后, 乐曲发生器能自动从头开始循环...
电子琴教学设计
电子琴教学设计_总结/汇报_实用文档。电子琴教学设计 音乐教案(电子琴教案) 一.指导思想电子琴以其丰富的音色, 多变的节奏, 较容易掌握的演奏方法赢得了小朋友 ...
简易电子琴
专业 电气工程系 电子信息工程 指导教师 2010 年 7 月 9 日 一、 设计任务及要求: 1、系统设计要求 (1)设计一个简易的八音符电子琴 (2)能够自动演奏乐曲。...
电子琴教学_图文
这种奏法用于学琴的初 级阶段和乐曲的分句。电子琴基本演奏技术及要领。 二、...具有自动和弦功能的电子琴,其键盘可以分为两部分,左手伴 奏键盘部分和右手旋律...
更多相关标签: