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)begin
	if(rst == 1'b1)begin
		button_out_d0 <= 1'b1;
		button_negedge <= 1'b0;
	end
	else begin
		button_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 @(*)begin
    case(hz_sel)
      8'h01   : cycle = CLK_FRE*1000000/261  ;  //low 1         261Hz
      8'h02   : cycle = CLK_FRE*1000000/293  ;  //low 2         293Hz
      8'h03   : cycle = CLK_FRE*1000000/329  ;  //low 3         329Hz
      8'h04   : cycle = CLK_FRE*1000000/349  ;  //low 4         349Hz
      8'h05   : cycle = CLK_FRE*1000000/392  ;  //low 5         392Hz
      8'h06   : cycle = CLK_FRE*1000000/440  ;  //low 6         440Hz
      8'h07   : cycle = CLK_FRE*1000000/499  ;  //low 7         499Hz
      8'h11   : cycle = CLK_FRE*1000000/523  ;  //middle 1      523Hz
      8'h12   : cycle = CLK_FRE*1000000/587  ;  //middle 2      587Hz
      8'h13   : cycle = CLK_FRE*1000000/659  ;  //middle 3      659Hz
      8'h14   : cycle = CLK_FRE*1000000/698  ;  //middle 4      698Hz
      8'h15   : cycle = CLK_FRE*1000000/784  ;  //middle 5      784Hz
      8'h16   : cycle = CLK_FRE*1000000/880  ;  //middle 6      880Hz
      8'h17   : cycle = CLK_FRE*1000000/998  ;  //middle 7      998Hz
      8'h21   : cycle = CLK_FRE*1000000/1046 ;  //high 1        1046Hz
      8'h22   : cycle = CLK_FRE*1000000/1174 ;  //high 2        1174Hz
      8'h23   : cycle = CLK_FRE*1000000/1318 ;  //high 3        1318Hz
      8'h24   : cycle = CLK_FRE*1000000/1396 ;  //high 4        1396Hz
      8'h25   : cycle = CLK_FRE*1000000/1568 ;  //high 5        1568Hz
      8'h26   : cycle = CLK_FRE*1000000/1760 ;  //high 6        1760Hz
      8'h27   : cycle = CLK_FRE*1000000/1976 ;  //high 7        1976Hz
      default : cycle = 20'd0 ;
    endcase
  end
endmodule

2.4、状态机演奏模块

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

always @(*)begin
  case(state)
    IDLE:begin
      if (button_negedge)
        next_state = PLAY;
      else
        next_state = IDLE; 
    end
    PLAY:begin
      if (play_cnt == music_time)  
        next_state = PLAY_WAIT;
      else
        next_state = PLAY;
    end
    PLAY_WAIT:begin
      if (music_cnt == music_len - 1)
        next_state = PLAY_END;
      else
        next_state = PLAY;
    end
    PLAY_END:next_state = IDLE;
    default:next_state = IDLE;
  endcase
end

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

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

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

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

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

always @(posedge clk or negedge rst_n)begin
  if (~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)begin
  if (~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)begin
  if (~rst_n)
    music_time <= 32'hffff_ffff;  
  else
    music_time <= rom_time_data*(CLK_FRE*1000000*60/85/8);
end

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Babel编译与Webpack

目录 Babel初识BabelBabel 使用方式使用 Babel 前的准备工作 WebpackWebpack介绍Webpack初体验Webpack核心概念入口&#xff08;entry&#xff09;出口&#xff08;output&#xff09;加载 (loader)插件&#xff08;plugins&#xff09; Babel Babel官网: https://babeljs.io/…

Emacs之编译系统文件cc-mode.el.gz(一百二十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

应用层协议——https

文章目录 1. HTTPS 是什么2. 什么是"加密"3. 常见的加密方式4. 数据摘要 && 数字签名5. HTTPS 的工作过程探究5.1 方案1 - 只使用对称加密5.2 方案2 - 只使用非对称加密5.3 方案3 - 双方都使用非对称加密5.4 方案4 - 非对称加密 对称加密5.5 中间人攻击5.6 …

pycharm 使用远程服务器 jupyter (本地jupyter同理)

1. 远程服务器miniconda 环境中创建jupyter环境 # 1. 激活环境 conda activate envname#2. 在环境中安装jupyter pip install jupyter # 或者 conda install jupyter#3. 生成jupyter_notebook_config.py文件 jupyter notebook --generate-config#4. 设置密码 jupyter noteboo…

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)【二】

文章目录 SSM--基础环境搭建【二】项目介绍项目功能/界面● SSM 整合项目界面 项目全局配置web.xmlSpringMVC 配置 SSM–基础环境搭建【二】 项目介绍 项目功能/界面 ● SSM 整合项目界面 项目全局配置web.xml 配置furns_ssm\src\main\webapp\WEB-INF\web.xml , 和项目全局…

mac安装nacos,M1芯片

第一步&#xff0c;官网下载 》nacos官网 去github中下载对应的版本&#xff0c;本人下载的是1.4.1版本 在这儿选择其他的版本&#xff0c;下面这里选择 tar.gz 压缩包 解压后放到一个非中文的目录下&#xff0c;我选择在 user目录下面创建一个other目录&#xff0c;将使用的环…

TCP拥塞控制详解 | 1. 概述

网络传输问题本质上是对网络资源的共享和复用问题&#xff0c;因此拥塞控制是网络工程领域的核心问题之一&#xff0c;并且随着互联网和数据中心流量的爆炸式增长&#xff0c;相关算法和机制出现了很多创新&#xff0c;本系列是免费电子书《TCP Congestion Control: A Systems …

IntelliJ IDEA 2023.2 最新版如何激活?IntelliJ IDEA 2023.2最新版激活方法及验证ja-netfilter配置成功提示

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Django系列之DRF简单使用

基于ModelViewSets的简单使用 models.py from django.db import modelsclass AuthorDetail(models.Model):gender models.CharField(max_length8)birthday models.DateField()telephone models.BigIntegerField()addr models.CharField(max_length64)class Author(models…

正则表达式速通

简介 正则表达式&#xff0c;我们可以看作通配符的增强版&#xff0c;可以帮我们匹配指定规则的字符串&#xff0c;在计算机中应用广泛&#xff0c;比如说爬虫、网站的登录表单等。 原视频&#xff1a;https://www.bilibili.com/video/BV1da4y1p7iZ 学习正则表达式的常用工具…

在云服务器上,clone github时报Connection timed outexit code: 128

文章目录 问题解决方案 问题 在执行pip install安装依赖时&#xff0c;需要clone github代码&#xff0c;此时报了Connection timed out&exit code: 128错误&#xff0c;原因是访问超时了&#xff0c;此时需要使用代理 fatal: unable to access https://github.com/hugg…

【项目设计】MySQL 连接池的设计

目录 &#x1f449;关键技术点&#x1f448;&#x1f449;项目背景&#x1f448;&#x1f449;连接池功能点介绍&#x1f448;&#x1f449;MySQL Server 参数介绍&#x1f448;&#x1f449;功能实现设计&#x1f448;&#x1f449;开发平台选型&#x1f448;&#x1f449;MyS…

快速开发框架若依的基础使用详解

Hi I’m Shendi 快速开发框架若依的基础使用详解 最近在为公司制作新的项目&#xff0c;经过了一段时间的技术沉淀&#xff0c;我开始尝试接触市面上用的比较多的快速开发框架&#xff0c;听的最多的当属若依吧 于是就选用了若依 介绍 为什么选&#xff1f;目的是为了提高开发…

远程访问本地mysql

文章目录 一、设置本地mysql允许外部访问找到mysql配置文件my.ini &#xff0c;linux环境是my.cnf配置mysql配置文件 二、创建外部访问的mysql用户三、配置mysql用户的权限四、配置防火墙端口五、连接查看本地ip地址 参考 连接命令 mysql -h <host> -P <port> -u &…

rknn模型在rv1126开发板上跑

在前面&#xff0c;已经将 onnx模型转为 rknn模型。 yolov5 onnx模型 转为 rknn模型_爱钓鱼的歪猴的博客-CSDN博客 这里探讨的是&#xff1a;rknn模型在rv1126开发板上运行 目录 1、rknn模型在PC端进行推理测试&#xff0c;评估模型精度 2、模型预编译 3、rknn模型部署到r…

配置GIt账号、配置公钥

1.设置账号和邮箱 打开终端输入以下命令&#xff1a; git config --global --unset-all user.name git config --global --unset-all user.email然后输入以下命令来设置新的账号和邮箱&#xff1a; git config --global user.name "your_username" git config --glo…

4 Promethues监控主机和容器

目录 目录 1. 监控节点 1.1 安装Node exporter 解压包 拷贝至目标目录 查看版本 1.2 配置Node exporter 1.3 配置textfile收集器 1.4 启动systemd收集器 1.5 基于Docker节点启动node_exporter 1.6 抓取Node Exporter 1.7 过滤收集器 2. 监控Docker容器 2.1 运行cAdviso…

matplotlib绘制方波圆周分解动画

1 方波的圆周分解 在学习傅里叶变换的时候&#xff0c;有一个经典的示例是方波的分解。我们知道&#xff0c;方波可以分解为无数个正弦波的叠加。而正弦波&#xff0c;又可以看作是圆周运动在一条直线上的投影。当时为了理解这个事情&#xff0c;恐怕大家也花了不少时间。 学…

8.Winform界面打包成DLL提供给其他的项目使用

背景 希望集成一个Winform的框架&#xff0c;提供权限菜单&#xff0c;根据权限出现各个Winform子系统的菜单界面。不希望把所有的界面都放放在同一个解决方案下面。用各个子系统建立不同的解决方案&#xff0c;建立代码仓库&#xff0c;进行管理。 实现方式 将Winform的UI界…

HCIP OSPF+BGP综合实验

题目 1、该拓扑为公司网络&#xff0c;其中包括公司总部、公司分部以及公司骨干网&#xff0c;不包含运营商公网部分。 2、设备名称均使用拓扑上名称改名&#xff0c;并且区分大小写。 3、整张拓扑均使用私网地址进行配置。 4、整张网络中&#xff0c;运行OSPF协议或者BGP协议…