基于FPGA音乐硬件演奏电路设计.

  • 格式:docx
  • 大小:551.98 KB
  • 文档页数:18

设计报告

课程名称

任课教师

设计题目 乐曲硬件演奏电路

班级

姓名

学号 日期一 . 题目分析

1、利用可编程逻辑器件 FPGA,设计乐曲硬件演奏电路,其结构框图如下图所示:

2、功能要求

利用数控分频器设计硬件乐曲电路,由键盘输入控制音响,同时可自动演奏乐曲。演奏时 可选择键盘输入乐曲或者已存入的乐曲,并配以一个扬声器,该设计产生的音乐选自“梁祝” 片段。

二、方案选择

与利用微处理器来实现乐曲演奏相比,以纯硬件完成乐曲演奏电路的逻辑要复 杂得多,如果不借助功能强大的 EDA 工具和硬件描述语言, 仅凭传统的数字逻辑技 术,即使最简单的演奏电路也难以实现。

三、细化框图

(1) 音乐硬件演奏电路基本原理 硬件电路的发声原理,声音的频谱范围约在几十到几千赫兹,若能利用程序来 控制 FPGA芯片某个引脚输出一定频率的矩形波 ,接上扬声器就能发出相应频率的声 音。乐曲中的每一音符对应着一个确定的频率,要想 FPGA发出不同音符的音调,实 际上只要控制它输出相应音符的频率即可。乐曲都是由一连串的音符组成,因此按 照乐曲的乐谱依次输出这些音符所对应的频,就可以在扬声器上连续地发出各个音 符的音调。而要准确地演奏出一首乐曲,仅仅让扬声器能够发生是不够的,还必须 准确地控制乐曲的节奏,即乐曲中每个音符的发生频率及其持续时间是乐曲能够连 续演奏的两个关键因素。

(2) 音符频率的获得 多个不同频率的信号可通过对某个基准频率进行分频器获得。由于各个音符的 频率多为非整数,而分频系数又不能为小数,故必须将计算机得到的分频系数四舍

五入取整。若基准频率过低,则分频系数过小,四舍五入取整后的误差较大。若基 准频率过高,虽然可以减少频率的相对误差,但分频结构将变大。实际上应该综合 考虑这两个方面的因素,在尽量减少误差的前提下,选取合适的基准频率。本设计 中选取 750KHz的基准频率。由于现有的高频时钟脉冲信号的频率为 12MH,z 故需先 对其进行 16 分频,才能获得 750KHz的基准频率。对基准频率分频后的输出信号是 一些脉宽极窄的尖脉冲信号(占空比

=1/分频系数) 。为提高输出信号的驱动能力, 以使扬声器有足够的功率发音,需要再通过一个分频器将原来的分频器的输出脉冲 均衡为对称方波(占空比 =1/2 ),但这时的频率将是原来的 1/2 。下表中各音符的 分频系数就是从 750KHz的基准频率二分频得到的 375KHz频率基础上计算得到的。 由于最大分频系数是 1274,故分频器采用 11 位二进制计数器能满足要求,乐曲中 的休止符,只要将分频系数设为 0,即初始值 =211-1=2047,此时扬声器不会发声。

音符名 频 率 (Hz) 分频 计数初值 音符名 频 率 (Hz) 分频 计数

系数 系数 初值

休止符 375000 0 2047 中音 4 796.178 468 1579

低音 1 294.349 1274 773 中音 5 882.353 425 1622

低音 2 330.396 1135 912 中音 6 989.446 379 1668

低音 3 370.92 1011 1036 中音 7 1136.363 330 1717

低音 4 386.598 970 1077 高音 1 1175.549 319 1728

低音 5 394.737 950 1197 高音 2 1353.790 277 1770

低音 6 495.376 757 1290 高音 3 1512.097 248 1799

低音 7 555.56 675 1372 高音 4 1609.442 233 1814

中音 1 588.697 637 1410 高音 5 1802.884 208 1839

中音 2 638.84 587 1480 高音 6 2027.027 185 1862

中音 3 742.574 505 1542 高音 7 2272.727 165 1882

各个音符的频率及其对应的分频系数(基准频率 375KHz)

3) 乐曲节奏的控制

本设计中的梁祝的乐曲,最小的节拍为 1/4 拍,若将 1拍的时间定为 1 秒,则 只需要提供一个 4Hz 的时钟频率即可产生 1/4 拍的时长( 0.25 秒),对于其它占用 时间较长的节拍(必为 1/4 拍的整数倍)则只需要将该音符连续输出相应的次数即 可。

计数时钟信号作为输出音符快慢的控制信号,时钟快时输出节拍速度就快,演 奏的速度也就快,时钟慢时输出节拍的速度就慢,演奏的速度自然降低。

(4) 乐谱发生器

本文将乐谱中的音符数据存储在 LPM-ROM中,如“梁祝”乐曲中的第一个音符 为“3”,此音在逻辑中停留了 4个时钟节拍,即 1 秒的时间,相应地,音符“ 3” 就要在

LPM-ROM中连续的四个地址上都存储。当一个 4Hz 的时钟来时,相应地就从 LPM-ROM中输出一个音符数据。

(5)音乐硬件演奏电路总体设计流程

当一个 4Hz的时钟脉冲来到时,乐谱发生器模块输出一个音符数据给分频系数 模块,分频系数模块输出此音符相应的分频系数 ,将分频系数送给数控分频器模块, 当 12MHz的时钟脉冲来到时 ,数控分频器就根据分频系数输出相应的频率 ( 即此音符 所对应的发生频率 )给扬声器,扬声器就可发出对应音符的声音来 . 连续的 4Hz的时 钟脉冲就将乐谱发生器里所存储的音符数据一个接一个的送给了分频系数模块,再 经过数控分频模块 , 最后扬声器一个接一个的发出音符数据所对应的声音来。 曲子也 就流畅的播放出来了。

音乐硬件演奏电路主要是用 VHDL语言来设计,并利用 Quartus6.0 软件工具来 编译、测试和仿真,音乐硬件演奏电路设计总体设计方框图如下图所示

四、程序与仿真

4.1 单元模块程序设计

根据顶层原理图,共分为 music 模块、地址发生器模块、分频预置数模块、十 六进制模块、数控分频模块这五个模块。 music 模块存放乐曲中的音符数据,地址 发生器模块作为

music 模块中所定制的音符数据 ROM的地址发生器,分频预置数模 块提供分频预置数即给数控分频模块提供计数初值,十六进制模块对 12MHz的时钟

脉冲进行 16 分频,得到 750KHz的频率,给数控分频模块提供时钟脉冲。数控分频 模块根据分频预置数输出各个音符所对应的频率。

4.1.1 音乐节拍和音调发生器模块

NoteTabs

clk ToneIndex[3..0]

SEL

RST

inst

(2) 地址发生器模块

地址发生器模块设置了一个 8 位二进制计数器 ( 计数最大值为 256),作为音符

数据 ROM的地址发生器。每来一个时钟脉冲信号 (Clk) ,8 位二进制计数器就计数一 次, ROM文件中的地址也就随着递增,音符数据 ROM中的音符也就一个接一个连续 的取出来了。

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

例如, 地址发生器在以下的 VHDL逻辑描述中,“梁祝”乐曲的第一个音符为“ 3”,此音在 逻辑中停留了 4个时钟节拍,即 1 秒时间。那么相应随着程序 [4]

中的计数器按 4Hz 的时钟频率作加法计数时,即随地址递增时,将从音符数据 ROM中将连续取出 4 个 音符“ 3”通过 toneindex[3..0] 端口输向分频预置数模块。这样梁祝乐曲中的音符 就一个接一个的通过 toneindex[3..0] 端口输向分频预置数模块。

4.2 音乐谱对应分频预制数查表电路模块

(1) 音乐谱分频预置数模块

ToneTaba

HIGH

Tone[10..0]

inst

(2) 音乐谱对应分频预制数查表电路 VHDL程序设计 (1) 音乐节拍和音调发生器模块 RTL电路图

ToneIndex[3..0]

Index[3..0] CODE[3..0] clk Tone[10..0] 音乐谱分频预置数模块是乐曲简谱码对应的分频预置数查表电路。它提供了每

个音符所对应的分频预置数,即给数控分频模块提供计数初值,这里以“梁祝”乐

曲为例,列出了在这个乐曲中所用到的 13 个音符的分频预置数。

在这个模块的 VHDL逻辑描述中设置了四四拍乐曲中全部音符所对应的分频预

置数,共 13 个,每一音符的停留时间由音乐节拍和地址发生器模块的时钟( Clk) 的输入频率决定,在此为 4Hz。这13个值的输出由程序 [3] 的 4位输入值 index[3..0]

确定。输向程序 [4] 中 index[3..0] 的值又由地址发生器模块的输出 toneindex[3..0] 的输出值和持续时间决定。

模块的功能是输出各个音符所对应的分频预置数, 即当 index 是“0000”,tone 输出为 2047,即休止符的分频预置数;当 index 是“ 0101”时, tone 输出为

1197 即低音 5的分频预置数;当 index 是“1111”时, tone 输出为 1728即高音 1的分 频预置数等等其它状态时, tone 分别输出相应音符的分频预置数。

4.3 音乐符数控 11 分频电路模块

(1) 音乐符数控 11 分频电路模块

Speakera

clk SpkS

Tone[10..0]

inst

(2) 音乐符数控 11 分频电路模块 RTL电路图

Add1

11' h

MUX21 Equal0

A[11..0]

OUT

Add0 \DivideCLK:Count4[3..0]

OUT[3..0]

h B[3..0]

ADDER LessThan0 PRE

2' h7FF -- \GenSpkS:Count11[10..0

B[11..0]

EQUAL