6.4.1 设计要求
利用可编程逻辑器件FPGA,设计一个乐曲硬件演奏电路。由键盘输入控制音响,同时可自动演奏乐曲。演奏时可选择键盘输入乐曲或者已存入的乐曲,并配以一个小扬声器。其结构如图6-34所示,该设计产生的音乐选自"梁祝"片段。
图span806-34 乐曲演奏电路结构方框图
6.4.2 原理描述
产生音乐的两个因素是音乐频率和音乐的持续时间,以纯硬件完成演奏电路比利用微处理 器(CPU)来实现乐曲演奏要复杂的多如果不借助于功能强大的EDA工具和硬件描述语言,凭借传统的数字逻辑技术,即使最简单的演奏电路也难以实现。根据6.4.1的设计要求,乐曲硬件演奏电路系统主要由数控分频器和乐曲存储模块组成。数控分频器对FPGA的基准频率进行分频,得到与各个音阶对应的频率输出。乐曲存储模块产生节拍控制和音阶选择信号,即在此模块中可存放一个乐曲曲谱真值表,由一个计数器来控制此真值表的输出,而由计数器的计数时钟信号作为乐曲节拍控制信号。
1 音名与频率的关系
音乐的十二平均率规定:每两个八度音(如简谱中的中音1与高音1)之间的频率相差一倍.在两个八度音之间,又可分为十二个半音,每两个半音的频率比为4。另外,音名A(简谱中的低音6)的频率为440Hz,音名B到C之间,E到F之间为半音,其余为全音,由此可以计算出简谱中从低音1到高音1之间每个音名的频率如表6-3所示.
表6-3 简谱中的音名与频率的关系
音名 | 频率/Hz | 多任务手势音名 | 频率/Hz | 音名 | 频率/Hz |
低音1 | 261.63 | 中音1 | 532.25 | 高音1 | 1046.50 |
低音2 | 293.67 | 中音2 | 587.33 | 高音2 | 1174.66 |
低音3 | 329.63 | 中音3 | 659.25 | 高音3 | 1318.51 |
低音4 | 349.23 | 中音4 | 698.46 | 高音4 | 1396.92 |
低音5 | 391.99玻璃钢酸洗槽 | 中音5 | 783.99 | 高音5 | 1567.98 |
低音6 | 440 | 中音6 | 880 | 高音6 | 1760 |
低音7 | 493.88 | 中音7 | 987.76 | 高音7 | 1975.52 |
| | | | | |
由于音阶频率多为非整数,而分频系数又不能为小数,故必须将得到的分频数四舍五入取整。若基准频率过低,则由于分频系数过小,四舍五入取整后的误差较大,若基准频率过高,虽然误码差变小,但分频结构将变大。实际的设计应综合考虑两方面的因素,在尽量减小频率误差的前提下取舍合适的基准频率。本例中选取4MHz的基准频率,若无4MHz的时钟频率,实际上,只要各个音名间的相对品频率关系不变,C作1与D作1演奏出的音乐听起来都不会“走调”。
各音阶频率及相应的分频系数如表6-4所示。为了减少输出的偶次谐波分量,最后输出到扬声器的波形应为对称方波,因此在到达扬声器之前,有一个二分频的分频器。表6-4中的分频系数就是从4MHZ频率二分频得到的2MHZ频率基础上计算得出的。
表6-4 各音阶频率对应的分频值
音名 | 分频系数 | 初始值 | 音名 | 分频系数 | 初始值 | 音名 | 分频系数 | 初始值 |
低音1 | 7644 | 547 | 中音1 | 3822 | 4369 | 高音1 | 1911 | 6280 |
低音2 | 6810 | 1381 | 中音2 | 3405 | 4786 | 高音2 | 1270 | 6921 |
低音3 | 6067 | 2124 | 中音3 | 3034 | 5157 | 高音3 | 1517 | 6674 |
低音4 | 5727 | 2464 | 中音4 | 2864 | 5327 | 高音4 | 1432 | 6759 |
低音5 | 5102 | 3089 | 中音5 | 2551 | 5640 | 高音5 | 1256 | 6935 |
低音6 | 4545 | 3646 | 中音6 | 2273 | 5918 | 高音6 | 1137 | 7054 | 滚花铜螺母
低音7 | 4050 | 4141 | 中音7 | 2025 | 6166 | 高音7 | 1013 | 7178 |
| | | | | | | | |
由于最大的分频系数为7644,故采用13位二进制计数器已能满足分频要求。在表6-4,除给出了分频比以外,给出了对应于各个音阶频率时计数器不同的初始值,对于乐曲中的休止符,要将分频系数设为0,即初始值为8191即可,此时扬声器将不会发声。对于不同的分频系数,加载不同的初始值即可。用加载初始值而不是将分频输出译码反馈,可以有效地减少本设计占用可编程逻辑器件的资源,也是同步计数器的一个常用设计技巧。
2 控制音长的节拍发生器
该演奏电路演奏的乐曲是“梁祝”片段,其最小的节拍为1拍。将1拍的时长定为0.25秒,则只需要再提供一个4Hz的时钟频率即可产生1拍的时长,演奏的时间控制通过ROM查表的方式来完成。对于占用时间较长的节拍(一定是拍的整数倍),如全音符为4拍(重复4),2/4音符为2拍(重复2),1/4音符为1拍(重复1)。
要求演奏时能循环进行,因此需另外设置一个时长计数器,当乐曲演奏完成时,保证能自动从头开始演奏。该计数器控制真值表按顺序输出简谱。
6.4.3 乐曲硬件演奏电路的层次化设计方案
根据层次化的设计思路,可把乐曲硬件演奏电路分为三个模块,音乐节拍发生器NoteTabs模块,音符译码电路Tonetaba模块,数控分频模块(speaker)。下面给出其EDA设计过程:
1 音乐节拍发生器NoteTabs
该模块将利用FPGA的片内ROM存放乐曲简谱真值表,由一个二进制计数器为乐曲数据存储器ROM的地址发生器。该计数器的计数频率为4Hz,即每一计数值的停留时间为0.25秒,随着NoteTab中计数器按4Hz的时钟频率作加法计数时,即随地址值递增时,乐曲数据ROM中的音符数据,将从ROM中的输出口输向音符译码电路Tonetaba,所存储乐曲就开始连续自然地演奏起来。二进制计数器的位数将根据所存放乐曲简谱基本节拍数来决定,对于乐曲“梁祝”片段其最小节拍数为138,即选择计数器的位数为8即可,另外在此模块上增加一手动/自动选择按扭auto,auto=1时为自动演奏,auto=0时为手动输入。其设计流程如下:
1)利用MegaWizard Plug-In Manager定制音符数据存储器musica1
在QuartusII主窗口“Tools”菜单中选择“MegaWizard Plug-In Manager”命令,选择“Create a new custom megafunction”项。单击Next按钮后,在产生的对话框左栏中选择“storage”项下的LPM_ROM,再选择cyclone和VHDL语言方式,在Browse下的栏中键入输出文件存放的路径“G:/chapter6/music/”和定制模块的文件名musica1。根据第5章例5-12给出的LPM_ROM的定制流程,即可完成musica1模块的定制工作,其VHDL源程序如下:
LIBRARY IEEEE;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
ENTITY music1 IS
PORT
(address : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
clock : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) );
END music1;
ARCHITECTURE SYN OF music1 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0);
COMPONENT altsyncram
GENERIC (
intended_device_family: STRING;
width_a ,widthad_a,width_byteena_a,numwords_a: NATURAL;
operation_mode : STRING;
outdata_reg_a : STRING;
address_aclr_a : STRING;
outdata_aclr_a : STRING;
init_file : STRING;
lpm_hint : STRING;
lpm_type : STRING
);
PORT (
clock0 : IN STD_LOGIC ;
address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
q_a : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(3 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
intended_device_family => "Cyclone",
width_a => 4,
widthad_a => 8,
numwords_a => 256,
operation_mode => "ROM",
outdata_reg_a => "CLOCK0",
address_aclr_a => "NONE",
outdata_aclr_a => "NONE",
width_byteena_a => 1,
init_file => "DATA1.MIF",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram"
)
PORT MAP (
电热丝绕线机 clock0 => clock,
address_a => address,
q_a => sub_wire0);
END SYN;
在定制中选择ROM的数据位宽为8,地址位宽为8(共计256个字),ROM的类型选择为“Auto”,并指定ROM的初始化数据文件名为data1.mif,该数据文件指向文件夹G:/chapter6/music/。
2)定制ROM模块的初始化数据文件data1.mif
在QuartusII中选择File | New命令,在New窗口中的选择Other Files页,再选择Memory Initialization File项。单击按OK按钮后,进入ROM初始化数据文件大小编辑窗。进入编辑窗后,在编辑窗中,根据设计的要求,可选ROM的数据数(Number of words)为256字,数据位宽度(Word size)为8。
在数据文件编辑窗中,单击按OK按钮,将出现图6-35所示的mif数据表格,在表格中将“梁祝”片段的音符数据(共138个)以十进制数形式填入此表中,最后保存此数据文件名为data.mif,存盘路径为G:/chapter6/music/。
图6-35数据存储器musica1的初始化数据文件内容
3)音乐节拍发生器NoteTabs的VHDL设计
其VHDL源程序如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;