VHDL 乐曲演奏电路设计
前言
无源蜂鸣器在直流信号下不会响,需要方波驱动。输入不同频率的方波会发出不同音调的声音,方波的幅值决定了声音的响度。
目标
乐曲发生电路在节拍(4Hz)的控制下根据乐谱产生合适的分频系数。分频器根据分频系数对时钟脉冲分频产生各种声调所需要的频率的信号。最后考虑到驱动蜂鸣器要足够的能量使用2分频器对信号进行二分频变为占空比50%的信号。
模块设计
分频器
上面的框图中预分频器、可预置数分频器都是分频器。可以采用上一个设计“数字时钟”设计的“数控N分频器”,不同之处是传入N的位宽(12位)要满足产生音调对应的频率所需分频系数大小(最大3822),通过给分频器传入数值N来对时钟信号进行N分频。得到的信号频率为原时钟信号的频率/N,占空比为1/N。
代码如下
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity ClkDiv is
port(
clk_i:IN STD_LOGIC;
N_i: IN STD_LOGIC_VECTOR(11 DOWNTO 0);
clk_o:OUT STD_LOGIC);
end ClkDiv;
architecture behavior of ClkDiv is
signal count:STD_LOGIC_VECTOR(11 DOWNTO 0):="000000000001";
signal clk_temp:STD_LOGIC:='0';
begin
process(clk_i)
begin
if(clk_i'EVENT and clk_i='1')then
if (count=N_i)then
count<="000000000001";
clk_temp<='1';
else
count<=count+1;
clk_temp<='0';
end if;
end if;
end process;
clk_o<=clk_temp;
end behavior;
仿真结果见“数字时钟设计”
乐曲发生器
乐曲发生电路在节拍(4Hz)的控制下根据乐谱产生合适的分频系数。在分频器输入为1Mhz的情况下,各个音调对应的声音的分频系数如下图所示。虽然我们设计的分频器输入为2Mhz,但是在驱动蜂鸣器前还进行了二分频,所以以下分频系数对我们的设计而言是合适的。
代码如下
--乐曲发生器Director 在4Hz的信号激励下,产生不同的预置数
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
entity Director is
port(
Director_i : IN STD_LOGIC;
Director_o: OUT STD_LOGIC_VECTOR(11 downto 0)
);
end Director;
architecture rtl of Director is
signal count :integer:=0;
signal s: STD_LOGIC_VECTOR(4 downto 0) :="00000";
signal Director_temp: STD_LOGIC_VECTOR(11 downto 0) :="000000000000";
begin
process(Director_i)
begin
if(Director_i'EVENT and Director_i='1')then
if(count>=47)then
count<=0;
else
count<=count+1;
end if;
if (count=0) then s<="00011"; --乐谱
elsif (count=1)then s<="00011";
elsif (count=2)then s<="00011";
elsif (count=3)then s<="00011";
elsif (count=4)then s<="00100";
elsif (count=5)then s<="00100";
elsif (count=6)then s<="00100";
elsif (count=7)then s<="00101";
elsif (count=8)then s<="00111";
elsif (count=9)then s<="00111";
elsif (count=10)then s<="00111";
elsif (count=11)then s<="01000";
elsif (count=12)then s<="00101";
elsif (count=13)then s<="00111";
elsif (count=14)then s<="00100";
elsif (count=15)then s<="00100";
elsif (count=16)then s<="01011";
elsif (count=17)then s<="01011";
elsif (count=18)then s<="01011";
elsif (count=19)then s<="01110";
elsif (count=20)then s<="01100";
elsif (count=21)then s<="01011";
elsif (count=22)then s<="01001";
elsif (count=23)then s<="01011";
elsif (count=24)then s<="01000";
elsif (count=25)then s<="01000";
elsif (count=26)then s<="01000";
elsif (count=27)then s<="01000";
elsif (count=28)then s<="01000";
elsif (count=29)then s<="01000";
elsif (count=30)then s<="01000";
elsif (count=31)then s<="01000";
elsif (count=32)then s<="01000";
elsif (count=33)then s<="01000";
elsif (count=34)then s<="01000";
elsif (count=35)then s<="01001";
elsif (count=36)then s<="00110";
elsif (count=37)then s<="00110";
elsif (count=38)then s<="00101";
elsif (count=39)then s<="00101";
elsif (count=40)then s<="00100";
elsif (count=41)then s<="00100";
elsif (count=42)then s<="00100";
elsif (count=43)then s<="00101";
elsif (count=44)then s<="00111";
elsif (count=45)then s<="00111";
elsif (count=46)then s<="01000";
elsif (count=47)then s<="01000";
end if;
end if;
end process;
-- process(Director_i)
-- begin
-- if(Director_i'EVENT and Director_i='1')then
-- if(count=9)then
-- count<=0;
-- else
-- count<=count+1;
-- end if;
-- if (count=0) then s<="00000"; --乐谱
-- elsif (count=1)then s<="00001";
-- elsif (count=2)then s<="00011";
-- elsif (count=3)then s<="00100";
-- elsif (count=4)then s<="00101";
-- elsif (count=5)then s<="00110";
-- elsif (count=6)then s<="00111";
-- elsif (count=7)then s<="01000";
-- elsif (count=8)then s<="01001";
-- elsif (count=9)then s<="01010";
-- end if;
-- end if;
-- end process;
process(s)
begin --预分频数
if (S="00000") then Director_temp<="111011101110";--低音1
elsif(S="00001") then Director_temp<="110101001101";--低音2
elsif(S="00010") then Director_temp<="101111011010";
elsif(S="00011") then Director_temp<="101100101111";
elsif(S="00100") then Director_temp<="100111110111";
elsif(S="00101") then Director_temp<="100011100001";
elsif(S="00110") then Director_temp<="011111101001";
elsif(S="00111") then Director_temp<="011101110111";--中音1
elsif(S="01000") then Director_temp<="011010100111";
elsif(S="01001") then Director_temp<="010111101101";
elsif(S="01010") then Director_temp<="010110011000";
elsif(S="01011") then Director_temp<="010011111100";
elsif(S="01100") then Director_temp<="010001110000";
elsif(S="01101") then Director_temp<="001111110100";
elsif(S="01110") then Director_temp<="001110111100";--高音1
elsif(S="01111") then Director_temp<="001101010011";
elsif(S="10000") then Director_temp<="001011110110";
elsif(S="10001") then Director_temp<="001011001100";
elsif(S="10010") then Director_temp<="001001111110";
elsif(S="10011") then Director_temp<="001000111000";
elsif(S="10100") then Director_temp<="000111111010";
end if;
end process;
Director_o<=Director_temp;
end rtl;
仿真结果如下,可以看到在4Hz输入信号的激励下,输出乐谱对应的分频系数
顶层模块
先对输入的时间脉冲33.8688MHz进行16分频得到2MHz的时间脉冲输入数控分频器。使用同样的方法得到4Hz脉冲输入乐曲发生电路得到音调对应的分频系数,把分频系数输入数控分频器得到音调对应的频率的信号,再对此信号二分频以增强驱动能力。
代码如下
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity TonePlayer is
port(
TonePlayerClk_i:IN STD_LOGIC;
TonePlayerBeep_o:OUT STD_LOGIC);
end TonePlayer;
architecture rtl of TonePlayer is
component ClkDiv is
port(
clk_i:IN STD_LOGIC;
N_i: IN STD_LOGIC_VECTOR(11 DOWNTO 0);
clk_o:OUT STD_LOGIC);
end component;
component Director is
port(
Director_i : IN STD_LOGIC;
Director_o: OUT STD_LOGIC_VECTOR(11 downto 0)
);
end component;
signal N1: STD_LOGIC_VECTOR(11 DOWNTO 0):="000000011001";
signal Clk2M: STD_LOGIC:='0';
signal N2: STD_LOGIC_VECTOR(11 DOWNTO 0):="001111101000";
signal Clk2K: STD_LOGIC:='0';
signal N3: STD_LOGIC_VECTOR(11 DOWNTO 0):="000111110100";
signal Clk4Hz: STD_LOGIC:='0';
signal DirectorTemp: STD_LOGIC_VECTOR(11 downto 0):="000000000000";
signal N4: STD_LOGIC_VECTOR(11 DOWNTO 0):="000000000010";
signal TonePlayerBeep_Temp: STD_LOGIC:='0';
begin
Clock_Map: ClkDiv port map(
clk_i=>TonePlayerClk_i,
N_i=>N1,
clk_o=>Clk2M);
Clock_Map2: ClkDiv port map(
clk_i=>Clk2M,
N_i=>N2,
clk_o=>Clk2K);
Clock_Map3: ClkDiv port map(
clk_i=>Clk2K,
N_i=>N3,
clk_o=>Clk4Hz);
Director_Map: Director port map(
Director_i =>Clk4Hz,
Director_o=>DirectorTemp);
CORE_Map4: ClkDiv port map(
clk_i=>Clk2M,
N_i=>DirectorTemp,
clk_o=>TonePlayerBeep_Temp);
Drive_Map: ClkDiv port map(
clk_i=>TonePlayerBeep_Temp,
N_i=>N4,
clk_o=>TonePlayerBeep_o);
end rtl;
仿真结果,DirectorTemp指示了当前输出的音调,可以看到在音调的分界线处,驱动蜂鸣器的TonePlayerBeep_o频率明显改变。而且占空比为50%具有较强的驱动能力
VHDL 乐曲演奏电路设计的更多相关文章
- c语言乐曲演奏——《千本樱》
这个程序着实花费了我好长的时间,我本身对音乐一窍不通,先是跟着girl friend学习了简谱,根据c调44拍的<千本樱>写下了下面的程序. #include<stdio.h> ...
- 基于VHDL的8255可编程并行接口电路设计
一.实验题目名称: 8255可编程并行接口电路设计 二.实验目的.任务和要求: 实验目的:学习掌握基本的数字系统设计方法,建立自顶向下的设计思维,能够使用VHDL语言编写简单的应用IP核,掌握基本的F ...
- [转]MIDI常识20条
原文链接:http://www.midifan.com/modulearticle-detailview-488.htm Keyboard杂志老资格编辑Jim Aikin在纪念MIDI诞生20的时候发 ...
- 详解树莓派Model B+控制蜂鸣器演奏乐曲
步进电机以及无源蜂鸣器这些都需要脉冲信号才能够驱动,这里将用GPIO的PWM接口驱动无源蜂鸣器弹奏乐曲,本文基于树莓派Mode B+,其他版本树莓派实现时需参照相关资料进行修改! 1 预备知识 1.1 ...
- 如何用C程序简单演奏乐曲
如何用C程序简单演奏乐曲 首先我们要介绍一个函数: Beep(Frequency,time) 如果我们在程序中运行这个函数 Int main(void) { Beep(Frequency,time); ...
- verilog实验1:基于FPGA蜂鸣器演奏乐曲并数码管显示
一.实验任务 利用FPGA进行代码开发,使蜂鸣器演奏出乐曲<生日快乐>,将音调显示在数码管.原理为蜂鸣器为交流源蜂鸣器,在引脚上加一定频率的方波就可以发声,而且发声的频率由所加方波决定.这 ...
- Raspberry Pi开发之旅-控制蜂鸣器演奏乐曲
一.无源蜂鸣器和有源蜂鸣器 步进电机以及无源蜂鸣器这些都需要脉冲信号才能够驱动,这次尝试用GPIO的PWM接口驱动无源蜂鸣器弹奏一曲<一闪一闪亮晶晶>. 无源蜂鸣器: 无源内部没有震荡源, ...
- 基于VHDL利用PS2键盘控制的电子密码锁设计
基于VHDL利用PS2键盘控制的密码锁设计 附件:下载地址 中文摘要 摘 要:现代社会,人们的安全意识正在不断提升.按键密码锁由于其具有方便性.低成本等特征,还是大有用武之地的.但是通常的按键密码锁开 ...
- 3. 戏说VHDL之入门游戏一:流水灯
一. 流水灯 1.1流水灯原理 流水灯是每个学电子的入门“游戏” ,示意图如图1,其原理极其简单,但是可玩性却极强,可以就8个LED写出不同花样的程序.在1.2中我们列出两个不同思路的代码作为VH ...
随机推荐
- PIVOT(透视转换)和UNPIVOT(逆透视转换)
一.原数据状态 二.手动写透视转换1 三.手动写透视转换2 四.PIVOT(透视转换)和UNPIVOT(逆透视转换)详细使用 使用标准SQL进行透视转换和逆视转换 --行列转换 create tabl ...
- PHP json_encode函数中需要注意的地方
在php中使用 json_encode() 内置函数可以使用得php中的数据更好的与其它语言传递与使用. 这个函数的功能是将数组转换成json数据存储格式: 1 <?php 2 $arr=arr ...
- Inferred type 'S' for type parameter 'S' is not within its bound;
在使用springboot 方法报错: Inferred type 'S' for type parameter 'S' is not within its bound; should extends ...
- jpg、gif、png-8、png-24的区别
一.gif格式的特点 1.透明性.gif是一种布尔透明类型,即它可以是全透明,也可以是全不透明,但是没有半透明 2.动画.gif支持动画 3.无损耗性.gif是一种无损耗的图像格式,这意味着你可以对g ...
- SQL Server中调用WebService
首先要启用Ole Automation Procedures,使用sp_configure 配置时如果报错"不支持对系统目录进行即席更新",可以加上WITH OVERRIDE选项. ...
- jquery的$post方法不发送空数组的解决办法
问题:jquery里的ajax在提交post请求时,如果数据里有一个空数组,则这个空数组不会提交上去 技术上的解决办法如下: 源代码: var params = { type : , ids:[] } ...
- Zookeeper本地模式安装
本地模式安装部署 1.安装前准备 (1)安装Jdk (2)拷贝Zookeeper安装包到Linux系统下 (3)解压到指定目录 tar -zxvf zookeeper-3.4.10.tar.gz -C ...
- BeanUtils工具的使用
beanutils的下载地址:http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgi 该压缩包有测试的代码: ...
- Mac下Homebrew的安装与使用
Homebrew简介,安装与使用 简介 Homebrew 官方网站 Homebrew是一个包管理器,用于安装Apple没有预装但你需要的UNIX工具.(比如著名的wget). Homebrew会将软件 ...
- Android之单元测试及数据库操作
一.安卓下的单元测试1.创建一个单元类,继承超类AndroidTestCase2.在AndroidManifest.xml配置清单中配置以下两点首先在manifest节点下添加节点instrument ...