基于FPGA的音乐蜂鸣器设计
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。

图1 :蜂鸣器实物图
蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
压电式蜂鸣器 压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。有的压电式蜂鸣器外壳上还装有发光二极管。多谐振荡器由晶体管或集成电路构成。当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。
电磁式蜂鸣器电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
按照内部有无震荡源可以分为有源蜂鸣器和无源蜂鸣器。有源蜂鸣器内部带震荡源,所以只要一通电就会发出声音;而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用一定频率的方波去驱动它。
首先设计分频器,设计一个1KHz的方波,驱动蜂鸣器,观测蜂鸣器是否会有声音产生。
本小节研究如何利用蜂鸣器演唱一首曲子《世上只有妈妈好》。
下图为《世上只有妈妈好》的简谱。

图2:世上只有妈妈好的简谱
简谱是一种比较简单易学的音乐记谱法。据说简谱是由法国思想家卢梭于1742年发明的。而最早把简谱引进我国的是我国近代音乐教育家沈心工。简谱应该说是一种比较简单易学的音乐记谱法。它的最大好处是仅用7个阿拉伯数字----1234567,就能将万千变化的音乐曲子记录并表示出来.
在简谱中,用以表示音的高低及相互关系的基本符号为七个阿拉伯数字,即1、2、3、4、5、6、7,唱作do、re、mi、fa、sol、la、si,称为唱名。
音符:1234567
唱名:do re mi fa sol la si
汉字:哆来米发梭拉西
显然,单用以上七个音是无法表现众多的音乐形象的。在实际作品中,还有一些更高或更低的音,如在基本音符上方加记一个"·",表示该音升高一个八度,称为高音;加记两个" :",则表示该音升高两个八度,称为倍高音。在基本音符下方加记一个"·",表示该音降低一个八度,称为低音;加记两个" :",则表示该音降低两个八度,称为倍低音。
在一般歌曲中,无论是在基本音符上方或下方加记两个以上的"·"的音符都是很少见的。
在简谱中,1、2、3、4、5、6、7这七个基本音符,不仅表示音的高低,而且还是表示时值长短的基本单位,称为四分音符,其他音符均是在四分音符的基础上,用加记短横线"-"和附点"·"表示。
在基本音符右侧加记一条短横线,表示增长一个四分音符的时值。这类加记在音符右侧、使音符时值增长的短横线,称为增时线。增时线越多,音符的时值越长。
在基本音符下方加记一条短横线,表示缩短原音符时值的一半。这类加记在音符下方、使音符时值缩短的短横线,称为减时线。减时线越多,音符的时值越短。
在简谱中,加记在单纯音符的右侧的、使音符时值增长的小圆点"·",称为附点。加记附点的音符称为附点音符。附点本身并无一定的长短,其长短由前面的单纯音符来决定。附点的意义在于增长原音符时值的一半,常用于四分音符和小于四分音符的各种音符之后。
在《世上只有妈妈好》的简谱中,每两个竖线之间为2秒钟的时长。每两个竖线之间有4个音符时长,但是其中有较多半个音符的长,本设计采用1/4秒为基本单位。
蜂鸣器给予不同的频率是可以发出近似1、2、3、4、5、6、7这七个基本音符。

图3 :各个音符所对应的频率
此模块命名为music_beep,clk为50MHz的时钟,rst_n为低电平有效的复位,beep为蜂鸣器的驱动信号。

图4 :music_beep的模型
在设计时,首先将简谱中的音符存起来;利用计数器产生1/4秒为周期的脉冲,在此脉冲驱动下,将事先存好的音符一个个输出;根据音符的值,计算出分频比;根据分频比,产生对应频率的波形。将此波形输出即可。

图5 :架构图
在进行多模块设计时,可以对每个模块只设计端口,将架构完成后。再分别设计每个模块。
《世上只有妈妈好》的简谱中共有8个四拍,每个四拍我们用8个音符来表示,合计共64个音符。在speed_ctrl中,输出的cnt为6位,正好可以表示64个状态。
在speed_ctrl中,每1/8秒让cnt增加1即可。
|
module input input output ); parameter T_250ms = 12_500_000; reg [25:0] count; wire flag_250ms; always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) count <= 26'd0; else if (count < T_250ms - 1'b1) count <= count + 1'b1; else count <= 26'd0; end assign flag_250ms = (count == T_250ms - always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) cnt <= 6'd0; else if (flag_250ms == 1'b1) cnt <= cnt + 1'b1; else cnt <= cnt; end endmodule |
图6:speed_ctrl的设计代码
在music_mem中存储音符,存储方式为低音用1到7表示,中音用8到14表示,高音用15到21表示,music为5bit位宽。
|
module input input input output ); // 1 2 // 8 9 10 // 15 16 17 18 always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) music <= 5'd0; else case (cnt) 6'd0 : 6'd1 : 6'd2 : 6'd3 : 6'd4 : 6'd5 : 6'd6 : 6'd7 : 6'd8 : 6'd9 : 6'd10 : 6'd11 : 6'd12 : 6'd13 : 6'd14 : 6'd15 : 6'd16 : 6'd17 : 6'd18 : 6'd19 : 6'd20 : 6'd21 : 6'd22 : 6'd23 : 6'd24 : 6'd25 : 6'd26 : 6'd27 : 6'd28 : 6'd29 : 6'd30 : 6'd31 : 6'd32 : 6'd33 : 6'd34 : 6'd35 : 6'd36 : 6'd37 : 6'd38 : 6'd39 : 6'd40 : 6'd41 : 6'd42 : 6'd43 : 6'd44 : 6'd45 : 6'd46 : 6'd47 6'd48 : 6'd49 : 6'd50 : 6'd51 : 6'd52 : 6'd53 : 6'd54 : 6'd55 : 6'd56 : 6'd57 : 6'd58 : 6'd59 : 6'd60 : 6'd61 6'd62 : 6'd63 : default : endcase end endmodule |
图7 :music_mem的设计代码
根据频率和音符的关系,将音符对应的频率值取出来,根据频率值算出分频比。驱动时钟为50MHz,所以分频比为50M除以频率。
|
module input input input output ); reg [31:0] freq; always @ * begin case (music) 5'd1 5'd2 5'd3 5'd4 5'd5 5'd6 5'd7 5'd8 5'd9 5'd10 5'd11 5'd12 5'd13 5'd14 5'd15 5'd16 5'd17 5'd18 5'd19 5'd20 5'd21 default : freq = 32'd1; endcase end always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) divnum <= 32'd50_000_000; else divnum <= 50_000_000/freq; end endmodule |
图8 :cal_divmum的设计代码
知道分频数后,利用任意分频的方式,产生对的波形即可。
|
module input input input output ); reg [31:0] cnt; always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) cnt <= 32'd0; else if (cnt < divnum - 1'b1) cnt <= cnt + 1'b1; else cnt <= 32'd0; end always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) beep <= 1'b0; else if (cnt < divnum[31:1]) beep <= 1'b0; else beep <= 1'b1; end endmodule |
图9 :wave_gen的设计代码
设计好上述四个模块后,将它们之前设计架构的连接方式,连接起来。
|
module input input output ); wire [5:0] cnt; wire [4:0] music; wire [31:0] divnum; speed_ctrl speed_ctrl_inst( .clk (clk), .rst_n (rst_n), .cnt (cnt) ); music_mem music_mem_inst( .clk (clk), .rst_n (rst_n), .cnt (cnt), .music (music) ); cal_divnum cal_divnum_inst( .clk (clk), .rst_n (rst_n), .music (music), .divnum (divnum) ); wave_gen wave_gen_inst( .clk (clk), .rst_n (rst_n), .divnum (divnum), .beep (beep) ); endmodule |
图10 :music_beep的设计代码
RTL视图如下,和所设计架构相同。

图11 :RTL视图
在testbench中,将speed_ctrl_inst模块中的T_250ms改成10。
defparam可以重新定义参数。
|
`timescale module reg clk; reg rst_n; wire beep; defparam music_beep_inst.speed_ctrl_inst.T_250ms music_beep music_beep_inst( .clk (clk), .rst_n (rst_n), .beep (beep) ); initial clk = 1'b0; always # 10 clk = ~clk; initial begin rst_n = 1'b0; # 200 @ (posedge clk); # 2; rst_n = 1'b1; # 20000; $stop; end endmodule |
图12 :testbench代码
由于输出的频率都较低,所以仿真时间都很长。
将参数改小,也只是加快切换输出音符的频率。由于wave_gen模块和分频模块相同,故而不在验证。只看RTL视图中,分频数是不是正确即可。

图13 :RTL视图
在RTL视图中,也看到cnt每10个周期增长1,然后对应输出音符。音符得出频率,根据频率得出分频数。经过验证,数据都是正确的。
分配管脚,全编译形成下载文件,下板后就可以听到《世上只有妈妈好》的歌曲了。
通过更改speed_crtl中的控制音符前进的速度,可以控制播放的速度。如果将速度控制到1/2秒的话,那么听到的歌曲将会变慢。如果将速度控制到1/8秒的话,那么听到的歌曲将会变快。
设计者:郝旭帅 QQ:746833924 QQ交流群: 173560979
基于FPGA的音乐蜂鸣器设计的更多相关文章
- 基于FPGA的HDMI显示设计(三)
上一篇:基于FPGA的VGA显示设计(二) 10月10日 ~ 20日期间实习,令我万万没想到的是实习题目是 “便携式高清电视显示屏测试系统原型设计” 也就是 “基于FPGA的视频显示”. 实习要求用 ...
- 基于FPGA的VGA显示设计(二)
上一篇:基于FPGA的VGA显示设计(一) 参照 CrazyBingo 的 基于FPGA的VGA可移植模块终极设计代码 的工程代码风格,模块化处理了上一篇的代码,并增加了一点其它图形. 顶层 ...
- 基于FPGA的异步FIFO设计
今天要介绍的异步FIFO,可以有不同的读写时钟,即不同的时钟域.由于异步FIFO没有外部地址端口,因此内部采用读写指针并顺序读写,即先写进FIFO的数据先读取(简称先进先出).这里的读写指针是异步的, ...
- 基于FPGA的VGA显示设计(一)
前言 FPGA主要运用于芯片验证.通信.图像处理.显示VGA接口的显示器是最基本的要求了. 原理 首先需要了解 : (1)VGA接口协议:VGA端子_维基百科 .VGA视频传输标准_百度 引脚1 RE ...
- 优化基于FPGA的深度卷积神经网络的加速器设计
英文论文链接:http://cadlab.cs.ucla.edu/~cong/slides/fpga2015_chen.pdf 翻译:卜居 转载请注明出处:http://blog.csdn.net/k ...
- 基于FPGA的图像去噪
目录 结构图 其中FPGA 控制模块为核心,通过它实现视频图像数据的获取.缓存.处理和控制各模块间通讯[1].由CCD 相机对目标成像,高速图像数据由camera link 实时传输[2],经信号转换 ...
- 基于FPGA的DDS设计(一)
最近在学习基于FPGA的DDS设计,借此机会把学习过程记录下来,当作自己的学习笔记也希望能够帮助到学习DDS的小伙伴. DDS(Direct Digital Synthesizer)直接数字合成器,这 ...
- 基于FPGA的XPT2046触摸控制器设计
基于FPGA的XPT2046触摸控制器设计 小梅哥编写,未经许可,文章内容和所涉及代码不得用于其他商业销售的板卡 本实例所涉及代码均可通过向 xiaomeige_fpga@foxmail.com 发 ...
- 基于FPGA的VGA可移植模块终极设计【转】
本文转载自:http://www.cnblogs.com/lueguo/p/3373643.html 略过天涯 基于FPGA的VGA可移植模块终极设计 一.VGA的诱惑 首先,VGA的驱动,这事, ...
- 基于FPGA的SPI FLASH控制器设计
1.SPI FLASH的基本特征 本文实现用FPGA来设计SPI FLASH,FLASH型号为W25Q128BV.支持3种通信方式,SPI.Dual SPI和Quad SPI.FLASH的存储单元无法 ...
随机推荐
- 《Go程序设计语言》学习笔记之结构体
<Go程序设计语言>学习笔记之结构体 一. 环境 Centos8.5, go1.17.5 linux/amd64 二. 概念 结构体是将零个或者多个任意类型的命名变量组合在一起的聚合数据类 ...
- C# 调用C++DLL时释放非托管内存
方法一 改变非托管内存的分配方法,将其修改成采用COM的内存分配方法CoTaskMemAlloc来分配内存.这样封送拆收器在释放非托管内存时,就能自动调用COM的内存释放方法CoTaskMemFree ...
- 使用maven命令安装Oracle的jar包到本地仓库
mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.4 -Dpackaging=jar ...
- KingbaseES Create Index Concurrently 过程探究
前言: 我们知道Oracle 可以通过create index online 在线创建索引,而不影响其他会话修改数据,但Oracle 实际在online 创建索引的最后一步,实际还是需要进行锁升级,申 ...
- 京东一面挂在了CAS算法的三大问题上,痛定思痛不做同一个知识点的小丑
写在开头 在介绍synchronized关键字时,我们提到了锁升级时所用到的CAS算法,那么今天我们就来好好学一学这个CAS算法. CAS算法对build哥来说,可谓是刻骨铭心,记得是研二去找实习的时 ...
- Java生成Json字符串
public class Test01 { public static void main(String[] args) { // StringBuilder responseMsg = new St ...
- 【Java基础知识】东软面试(一面)
01 面向对象的特征 封装:隐藏部分对象的属性和实现细节,以不同的访问级别来保护对象内部的数据,防止外部程序的不当访问,对外提供公开的接口.[私有的属性,共有的方法] 继承:子类自动共享父类数据和方法 ...
- #差分,前缀和#nssl 1469 U
分析 考虑离线,因为异或和很难在线处理 然后可以用两个数组来差分斜与横的情况,然后将答案竖着传 时间复杂度\(O(n^2)\) 代码 #include <cstdio> #include ...
- CentOS 9 安装 Nginx 模块 `subs_filter`
sub_filter 和 subs_filter 区别 sub_filter( 0.7.24):替换响应体(Response Body)中的文本,只能设置一组替换. subs_filter:替换响应体 ...
- 未来已来,OpenHarmony 3.2 Release发布,迈入发展新阶段
2023年4月9日,在社区开发者的期盼中,在春风送暖万物更新的季节里,我们迎来了OpenAtom OpenHarmony(以下简称"OpenHarmony")3.2 Relea ...