基于 FPGA 的乐曲发生器设计
[日期:
2006-8-31]
来源:现代电子技术 作者:杭州商学院 姜
田华
[字体:大 中
小]
1 概 述
随着 EDA 技术的进展,基于可编程 ASIC 的数字电子系统设计的完整方案越来
越受到人们的重视,并且以 EDA 技术为核心的能在可编程 ASIC 上进行系统芯片
集成的新设计方法,也正在快速地取代基于 PCB 板的传统设计方式。
与利用微处理器(CPU 或 MCU)来实现乐曲演奏相比,以纯硬件完成乐曲演奏电
路的逻辑要复杂得多,如果不借助于功能强大的 EDA 工具和硬件描述语言,仅凭
传统的数字逻辑技术,即使最简单的演奏电路也难以实现。如何使用 EDA 工具设
计电子系统是人们普遍关心的问题,本设计在美国 ALTERA 公司 MAX + plusⅡ的
EDA 软件平台上,使用层次化设计方法,实现了乐曲发生器的设计。乐曲选取《梁
祝》中化蝶部分,其简谱如图 1 所示。
2 音符与频率的关系
我们知道,组成乐曲的每个音符的发音频率值及其持续的时间是乐曲能连续演
奏所需的 2 个基本要素,首先让我们来了解音符与频率的关系。
乐曲的 12 平均率规定:每 2 个八度音(如简谱中的中音 1 与高音 1)之间的频率
相差 1 倍。在 2 个八度音之间,又可分为 12 个半音,每 2 个半音的频率比为 12√2。
另外,音符 A(简谱中的低音 6)的频率为 440Hz,音符 B 到 C 之间、E 到 F 之间为
半音,其余为全音。由此可以计算出简谱中从低音 l 至高音 1 之间每个音符的频率,
如表 1 所示。
产生各音符所需的频率可用一分频器实现,由于各音符对应的频率多为非整数,
而分频系数又不能为小数,故必须将计算得到的分频数四舍五入取整。若分频器时
钟频率过低,则由于分频系数过小,四舍五入取整后的误差较大;若时钟频率过高,
虽然误差变小,但会增加分频器的分频级数。实际的设计应综合考虑两方面的因素,
在尽量减小频率误差的前提下取合适的时钟频率。本文设计的乐曲发生器选取
6MHz 的基准频率。若无 6MHz 的时钟频率,则可以先分频得到 6MHz 或换一个新
的基准频率。实际上,只要各个音符间的相对频率关系不变,演奏出的乐曲听起来
都不会"走调"。
化蝶简谱中各音符对应的分频系数如表 2 所示。为了减小输出的偶次谐波分量,
最后输出到扬声器的波形应为对称方波,因此在到达扬声器之前,有一个二分频的
分频器。表 2 中的分频系数是从 6MHz 频率二分频得到的 3MHz 频率基础上计算
得出的。由于最大的分频系数为 9101,故采用 14 位二进制计数器已能满足分频要
求。
每个音符持续的时间是乐曲能连续演奏所需的另一个基本要素。化蝶的最小的
节拍为 1/4 拍,将 1 拍的时间长度定为 1s,则只需要再提供一个 4Hz 的时钟频
率即可产生 1/4 拍的时长。演奏的时间控制通过记录来完成,对于占用时间较长
的节拍(一定是 1/4 拍的整数倍,如 2/4 拍),只需将该音符连续记录 2 次即可。
3 层次化设计
我们在美国 AI。TERA 公司 MAX + plusⅡ的 EDA 软件平台上,使用层次化设
计手段,实现了化蝶乐曲发生器的设计。图 2 为化蝶乐曲发生器的顶层电路。
音符的频率可以由 PUI。SE 元件的输出 SPEAK 获得,这是一个数控分频器,
由其 CLK 6MHz 端输入 6MHz 脉冲信号,分频比由预置输入端 D[13..0]决定。
输出为方波信号,其频率为 3 000 000/(1+D[13..0]),单位为 Hz。
音符的持续时间需根据乐曲的速度及每个音符的节拍数来确定,TABLE 元件首
先是为 PULSE 元件提供决定所发音符的分频预置数,而此数停留的时间即为此音
符的节拍值。在 TABLE 元件中设置了一个 8 位二进制计数器(计数最大值为 138),
这个计数器的计数频率选为 4 Hz,所以每一计数值的停留时间为 0.25s,即四四
拍的 4 分音符持续时间。例如,化蝶乐曲的第一个音符?quot;低音 3"(1 拍),停留
的时间需用 4 个计数时钟节拍,即 1s。相应地,所对应的"低音 3"音符分频预置值
为 9 100,其值在 AF[13..0]输出端停留了 1s。随着 TABLE 元件中的计数器按
4Hz 的时钟速率作加法计数时,化蝶乐曲就开始连续自然地演奏起来了。
底层元件的 VHDL 逻辑描述如下:
--PULSE 元件
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY pulse IS
PORT(clk:INSTD_LOGIC; 一一待分频时钟
d:IN STD_LOGIC_VECTOR(13 DOWNTO 0);
--分频预置数输入
fout:OUTSTD_LOGIC); 一一发音输出
END pulses
ARCHITECTURE behav OF pulse IS
SIGNAL count : STD_LOGIC-VECTOR(13DOWNTO 0);
SIGNAL cao,caoo1,cao2,load:STD_LOGIC'
BEGIN
PROCESS(clk,load,d)
BEGIN
IF clk'EVENT AND clk='l'THEN
IF load='1'THEN count<=d;
ELSE count<=count 一 1;
END IF;
END IF;
END PROCESS;
PROCESS(count)
BEGIN
IF count=0 THEN cao<='l';
ELSE cao<='0'; END IF;
load<=cao;
END PROCESS;
PROCESS(clk) --去毛刺
BEGIN
IF clk'EVENT ANDclk='1'THEN
caol<=cao;
END IF;
END PROCESS;
PROCESS(cao1)
BEGIN
IF cao1'EVENT AND cao1='1'THEN
ca02<=NOT cao2;
END IF
fout<=cao2;
END PROCESS;
END behav;
一一 TABLE 元件
IBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY table IS
PORT(clk:IN STD_LOGIC;
af:OUT INTEGER RANGE 0 TO 16#3FFF#)
一一 14 位二进制数
END;
ARCHITECTURE one OF table IS
CONSTANT 1ow_3:INTEGER:=9100;
CONSTANT 1ow_5;INTEGER:=7652;
CONSTANT 1ow_6:INTEGER:=6817;
CONSTANT 1ow_7:INTEGER:=6073;
CONSTANT mid_1:INTEGER;=5732;
CONSTANT mid_2:INTEGER:=5107;
CONSTANT mid_3:INTEGER:=4550;
CONSTANT mid_5:INTEGER:=3826;
CONSTANT mid_6:INTEGER:=3408;
CONSTANT highl:INTEGER: =2866
CONSTANT stop:INTEGER:=0;
--休止符分频系数
SIGNAL counter:INTEGER RANGE 0 TO 138;
BEGIN
PROCESS(clk)
BEGIN
IF counter=138 THEN counter<=0;
ELSIF(clk'EVENT AND clk='l')THEN
counter<=counter+1;
END IF;
END PROCESS;
PROCESS(counter)
BEGIN
CASE counter IS
WHEN 00=>af<=low_3; --低音 3
WHEN 01=>af<=low_3;
WHEN 02=>af<=low_3;
WHEN 03=>af<=low_3;
WHEN 04?gt;af<=low_5;
WHEN 05=>af<=low_5;
WHEN 06=>af<=low_5;
WHEN 07=>af<=low_6;
WHEN 08=>af<=low_1;
WHEN 09=>af<=low_1;
WHEN 10=>af<=low_1;
WHEN 11=>af<=low_2;
……
WHEN 134=>af<=low_5;
WHEN 135=>>af<=low_5;
WHEN 136=>>af<=stop;
WHEN 137=>af<=stop;
WHEN 138=>>af<=stop;
WHEN OTHERS=>NULL;
END CASE;
END PROCESS;
END;
4 实验验证
需要说明的是不同的数字系统其引脚锁定是不一样的,为了便于在实验系统上
验证设计结果,必须按照实验系统的结构对输入和输出引脚进行锁定。本设计采用
的是杭州康芯电子有限公司生产的 GW48-CK 实验系统,FPGA 目标芯片的型号为
EPFl0K10LC84。芯片配置成功后即可进行硬件测试:选择实验电路结构图 NO.6,
使 CLK 6MH2 与 C10ck9 相接(接受 6MHz 时钟频率),CLK 4Hz 与 Clock2 相接(接
受 4Hz 时钟频率),发音输出接 SPEAK,当乐曲一遍演奏完成后,乐曲发生器能自
动从头开始循环演奏。