FPGA开发:音乐播放器

        FPGA开发板上的蜂鸣器可以用来播放音乐,只需要控制蜂鸣器信号的方波频率、占空比和持续时间即可。

1、简谱原理

        简谱上的4/4表示该简谱以4分音符为一拍,每小节4拍,简谱上应该也会标注每分钟多少拍。音符时值对照表如下图所示,这表示了每个音符的演奏时长。

        音符是记录音的高低和长短的符号,简谱中的音符是七个阿拉伯数字,它们是:1(Do)、2(Re)、3(Mi)、4(Fa)、5(Sol)、6(La)、7(Ti),为了标记更高或更低的音,则在基本符号的上面或下面加上小圆点。在简谱中,不带点的基本符号叫中音。记在简谱基本音符号下面的小圆点,叫低音点,它表示将基本音符降低一个音组,即降低一个纯八度。在基本符号下面加一个点叫低音,加两个点叫倍低音,加三个点叫超低音。记在简谱基本音符号上面的小圆点,叫高音点,它表示将基本音符升高一个音组,即升高一个纯八度。在基本符号上面加一个点叫高音,加两个点叫倍高音,加三个点叫超高音

        音符所对应的频率如下表所示。

音符频率
低音1261Hz
低音2293Hz
低音3329Hz
低音4349Hz
低音5392Hz
低音6440Hz
低音7499Hz
中音1523Hz
中音2587Hz
中音3659Hz
中音4698Hz
中音5784Hz
中音6880Hz
中音7998Hz
高音11046Hz
高音21174Hz
高音31318Hz
高音41396Hz
高音51568Hz
高音61760Hz
高音71976Hz

2、结构设计

2.1、按键消抖模块

        由于要是用按键控制音乐开始播放,所以需要一个按键消抖模块,具体可以在FPGA开发:按键消抖一文中找到。

Debounce debounce_0
(.clk             (clk),.rst             (rst_n),.button_in       (button_in),.button_out      (button_out)
);

        同时我们还需要一个边沿检测的机制来保证一次按下只触发一次按键操作。

always @ (posedge clk or posedge rst)beginif(rst == 1'b1)beginbutton_out_d0 <= 1'b1;button_negedge <= 1'b0;endelse beginbutton_out_d0 <= button_out;button_negedge <= button_out_d0 & ~button_out;end	
end

2.2、ROM模块

        使用ROM保存音符时长和音调,创建ROM的过程可以根据不同的FPGA开发环境而定,如果是Quartus的话步骤如下:

        首先新建两个个MIF文件,它们是用来初始化ROM的,如下图所示。

         根据你的简谱长度,设置深度,如下图所示。

        随后根据简谱填入对应信息并保存,如下图所示。 

        接着在IP窗口搜索ROM IP,如下图所示。

         选好模块名和HDL类型并保存,这里选择Verilog HDL,如下图所示。

        在ROM创建菜单中选择创建的ROM大小(这里应该要和刚才的MIF文件一致),如下图所示。

        在初始化界面,选择使用刚才创建的MIF文件并Finish即可完成ROM的创建,如下图所示。

2.3、频率译码模块

         规定中音1使用十进制数11表示,而低音1使用01表示,中音2使用12表示。译码模块根据对应的音符频率,输出相应的周期,其中CLK_FRE根据开发板的频率而定。

module music_hz(
input  [7:0]  hz_sel,
output reg [19:0] cycle
);parameter CLK_FRE = 50 ;always @(*)begincase(hz_sel)8'h01   : cycle = CLK_FRE*1000000/261  ;  //low 1         261Hz8'h02   : cycle = CLK_FRE*1000000/293  ;  //low 2         293Hz8'h03   : cycle = CLK_FRE*1000000/329  ;  //low 3         329Hz8'h04   : cycle = CLK_FRE*1000000/349  ;  //low 4         349Hz8'h05   : cycle = CLK_FRE*1000000/392  ;  //low 5         392Hz8'h06   : cycle = CLK_FRE*1000000/440  ;  //low 6         440Hz8'h07   : cycle = CLK_FRE*1000000/499  ;  //low 7         499Hz8'h11   : cycle = CLK_FRE*1000000/523  ;  //middle 1      523Hz8'h12   : cycle = CLK_FRE*1000000/587  ;  //middle 2      587Hz8'h13   : cycle = CLK_FRE*1000000/659  ;  //middle 3      659Hz8'h14   : cycle = CLK_FRE*1000000/698  ;  //middle 4      698Hz8'h15   : cycle = CLK_FRE*1000000/784  ;  //middle 5      784Hz8'h16   : cycle = CLK_FRE*1000000/880  ;  //middle 6      880Hz8'h17   : cycle = CLK_FRE*1000000/998  ;  //middle 7      998Hz8'h21   : cycle = CLK_FRE*1000000/1046 ;  //high 1        1046Hz8'h22   : cycle = CLK_FRE*1000000/1174 ;  //high 2        1174Hz8'h23   : cycle = CLK_FRE*1000000/1318 ;  //high 3        1318Hz8'h24   : cycle = CLK_FRE*1000000/1396 ;  //high 4        1396Hz8'h25   : cycle = CLK_FRE*1000000/1568 ;  //high 5        1568Hz8'h26   : cycle = CLK_FRE*1000000/1760 ;  //high 6        1760Hz8'h27   : cycle = CLK_FRE*1000000/1976 ;  //high 7        1976Hzdefault : cycle = 20'd0 ;endcaseend
endmodule

2.4、状态机演奏模块

        状态机设有四个状态,IDLE,PLAY,PLAY_WAIT和PLAY_END,其中PLAY状态使用一个计数器对每个音符的演奏时长进行计数,PLAY_WAIT用于检查是否全部音符演奏完毕,如果否,则会对演奏时长计数器清零并再次进入PLAY状态。

always @(*)begincase(state)IDLE:beginif (button_negedge)next_state = PLAY;elsenext_state = IDLE; endPLAY:beginif (play_cnt == music_time)  next_state = PLAY_WAIT;elsenext_state = PLAY;endPLAY_WAIT:beginif (music_cnt == music_len - 1)next_state = PLAY_END;elsenext_state = PLAY;endPLAY_END:next_state = IDLE;default:next_state = IDLE;endcase
end

        周期计数器用于对音符的每个周期进行计数,并提供计数值给输出信号模块。

always @(posedge clk or negedge rst_n)beginif (~rst_n)hz_cnt <= 20'd0;  else if (state == PLAY || state == PLAY_WAIT)beginif (hz_cnt == cycle - 1)hz_cnt <= 20'd0;elsehz_cnt <= hz_cnt + 1'b1;endelse hz_cnt <= 20'd0;
end	

        输出信号模块根据计数值输出信号,其中还可以控制占空比。

always @(posedge clk or negedge rst_n)beginif (~rst_n)buzzer <= 1'b1;  else if (state == PLAY || state == PLAY_WAIT)beginif (hz_cnt < cycle/32) //控制占空比buzzer <= 1'b0;elsebuzzer <= 1'b1;endelse if (state == IDLE || state == PLAY_END)buzzer <= 1'b1;
end

        演奏时长计数器用于对每个音符的演奏时间计数。

always @(posedge clk or negedge rst_n)beginif (~rst_n)play_cnt <= 32'd0;  else if (state == PLAY)play_cnt <= play_cnt + 1'b1;else play_cnt <= 32'd0;
end

        演奏个数计数器用于对演奏的音符数计数。

always @(posedge clk or negedge rst_n)beginif (~rst_n)music_cnt <= 32'd0;  else if (state == PLAY_WAIT)music_cnt <= music_cnt + 1'b1;else if (state == IDLE || state == PLAY_END)music_cnt <= 32'd0;
end

        最后实例化ROM,并且注意,这里规定演奏时长rom值以8为一拍,所以读取rom值后需要进行转换,假设一分钟85拍。

music_hz hz0
(.hz_sel(rom_hz_data),.cycle(cycle) 
) ;music_rom hz_rom
(.address(music_cnt[8:0]),.clock(clk),.q(rom_hz_data));music_time_rom time_rom
(.address(music_cnt[8:0]),.clock(clk),.q(rom_time_data));always @(posedge clk or negedge rst_n)beginif (~rst_n)music_time <= 32'hffff_ffff;  elsemusic_time <= rom_time_data*(CLK_FRE*1000000*60/85/8);
end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/77726.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件工程专业应该学什么?

昨天&#xff0c;我朋友的孩子报考了软件工程专业&#xff0c;问我软件工程到底学啥&#xff1f;所以我给他开列了一个书单。 现在高校开了一堆花名头的专业&#xff1a; 偏技术类&#xff1a;云计算、大数据、人工智能、物联网 偏应用类&#xff1a;电子商务、信息管理 但我个…

MySQL|查看事务加锁情况

文章目录 使用information_schema数据库中的表获取锁信息INNODB_TRXINNODB_LOCKSINNODB_LOCK_WAITS 使用SHOW ENGINE INNODB STATUS获取信息补充 使用information_schema数据库中的表获取锁信息 在information_schema数据库中&#xff0c;有几个与事务和锁紧密相关的表 INNOD…

3个命令定位CPU飙高

top 指令找出消耗CPU最厉害的那个进程的pid top -H -p 进程pid 找出耗用CPU资源最多的线程pid printf ‘0x%x\n’ 线程pid 将线程pid转换为16进制 结合jstack 找出哪个代码有问题 jstack 进程pid | grep 16进制的线程pid -A 多少行日志 jstack 进程pid | grep 16进制的线程…

Source Insight_突出显示对选定字符的引用

1、突出显示对选定字符的引用 在Source Insight中&#xff0c;当我们选中一个函数或者变量的时候&#xff0c;关于它的所有引用地方都高亮显示&#xff0c;想要实现效果如下。 2、配置方法 (1)点击"Options"→“File Type options...” (2)勾选“Highlight referenc…

Python - 【socket】 客户端client重连处理简单示例Demo(一)

一. 前言 在Python中&#xff0c;使用socket进行网络通信时&#xff0c;如果连接断开&#xff0c;可以通过以下步骤实现重连处理 二. 示例代码 1. 定义一个函数&#xff0c;用于建立socket连接 import socketdef connect_socket(host, port):while True:try:# 建立socket连…

CMake:检测python解释器和python库

CMake:检测python解释器和python库 导言检测python解释器CMakeLists.txt输出附录 检测python库项目结构CMakeLists.txt相关源码附录 导言 python是一种非常流行的语言。许多项目用python编写的工具&#xff0c;从而将主程序和库打包在一起&#xff0c;或者在配置或构建过程中使…

当服务器域名出现解析错误的问题该怎么办?

​  域名解析是互联网用户接收他们正在寻找的域的地址的过程。更准确地说&#xff0c;域名解析是人们在浏览器中输入时使用的域名与网站IP地址之间的转换过程。您需要站点的 IP 地址才能知道它所在的位置并加载它。但&#xff0c;在这个过程中&#xff0c;可能会出现多种因素…

小白解密ChatGPT大模型训练;Meta开源生成式AI工具AudioCraft

&#x1f989; AI新闻 &#x1f680; Meta开源生成式AI工具AudioCraft&#xff0c;帮助用户创作音乐和音频 摘要&#xff1a;美国公司Meta开源了一款名为AudioCraft的生成式AI工具&#xff0c;可以通过文本提示生成音乐和音频。该工具包含三个核心组件&#xff1a;MusicGen用…

Win32 EditControl多行文本框自动换行,并在添加新行时自动将光标移到末尾

【文本框属性设置】 设为多行文本框&#xff1a;MultilineTrue 允许按回车键换行&#xff1a;Want ReturnTrue 自动换行&#xff1a;Auto HScrollFalse 在最后一行按回车键&#xff0c;自动向上滚动&#xff1a;Auto VScrollTrue 显示垂直滚动条&#xff1a;Vertical ScrollTru…

maven的下载与安装

文章目录 1 官网下载地址2 设置环境变量3 设置仓库地址4 添加阿里云的中央镜像 1 官网下载地址 https://maven.apache.org/ 下载 2 设置环境变量 MAVEN_HOME PATH mvn -v验证 3 设置仓库地址 仓库地址 4 添加阿里云的中央镜像 阿里云中央镜像

【探索Linux】—— 步步学习强大的命令行工具 P.1(Linux简介)

目录 前言 一、Linux简介 二、linux的不同发行版本 三、Linux的开源性质 四、Linux的特点 五、Linux代码演示&#xff08;仅供参考&#xff09; 总结 前言 前面我们讲了C语言的基础知识&#xff0c;也了解了一些数据结构&#xff0c;并且讲了有关C的一些知识&#xff…

Redis

Redis进阶 讨论问题&#xff1a; 数据存放的位置有哪些&#xff08;磁盘&#xff0c;内存&#xff0c;数据库&#xff09; 为什么做缓存&#xff1f; 速度&#xff1a;内存 >10 倍固态硬盘 > 10 倍机械硬盘 一、SpringBoot操作Redis 1、 添加redis依赖 spring Boo…

Java源码规则引擎:jvs-rules 8月新增功能介绍

JVS-rules是JAVA语言下开发的规则引擎&#xff0c;是jvs企业级数字化解决方案中的重要配置化工具&#xff0c;核心解决业务判断的配置化&#xff0c;常见的使用场景&#xff1a;金融信贷风控判断、商品优惠折扣计算、对员工考核评分等各种变化的规则判断情景。 8月是收获的季节…

JVM入门到精通

一、JVM概念 1.1、什么是JVM Java Virtual Machine&#xff1a;Java虚拟机&#xff0c;用来保证Java语言跨平台 Java虚拟机可以看做是一台抽象的计算机&#xff0c;如同真实的计算机那样&#xff0c;它有自己的指令集以及各种运行时内存区域 Java虚拟机与Java语言并没有必然…

Pytorch入门学习——快速搭建神经网络、优化器、梯度计算

我的代码可以在我的Github找到 GIthub地址 https://github.com/QinghongShao-sqh/Pytorch_Study 因为最近有同学问我如何Nerf入门&#xff0c;这里就简单给出一些我的建议&#xff1a; &#xff08;1&#xff09;基本的pytorch&#xff0c;机器学习&#xff0c;深度学习知识&a…

ChatGPT“侵入”校园,教学评价体制受冲击,需作出调整

北密歇根大学的教授奥曼在学生作业中发现了一篇关于世界宗教的“完美论文”。“这篇文章写得比大多数学生都要好......好到不符合我对学生的预期&#xff01;”他去问ChatGPT&#xff1a;“这是你写的吗&#xff1f;”ChatGPT回答&#xff1a;“99.9%的概率是的。” ChatGPT“侵…

HTTP——八、确认访问用户身份的认证

HTTP 一、何为认证二、BASIC认证BASIC认证的认证步骤 三、DIGEST认证DIGEST认证的认证步骤 四、SSL客户端认证1、SSL 客户端认证的认证步骤2、SSL 客户端认证采用双因素认证3、SSL 客户端认证必要的费用 五、基于表单认证1、认证多半为基于表单认证2、Session 管理及 Cookie 应…

ORB算法在opencv中实现方法

在OPenCV中实现ORB算法&#xff0c;使用的是&#xff1a; 1.实例化ORB orb cv.xfeatures2d.orb_create(nfeatures)参数&#xff1a; nfeatures: 特征点的最大数量 2.利用orb.detectAndCompute()检测关键点并计算 kp,des orb.detectAndCompute(gray,None)参数&#xff1a…

数据结构---B树

目录标题 B-树的由来B-树的规则和原理B-树的插入分析B-树的插入实现准备工作find函数insert中序遍历 B-树的性能测试B-树的删除B树B树的元素插入B*树的介绍 B-树的由来 在前面的学习过程中&#xff0c;我们见过很多搜索结构比比如说顺序查找&#xff0c;二分查找&#xff0c;搜…

一文学透设计模式——抽象工厂模式

创建者模式 抽象工厂模式 概念 抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这是很多地方对于抽象工厂模式的描述&#xff0c;说实话感觉不是特别好懂。…