前言

无源蜂鸣器在直流信号下不会响,需要方波驱动。输入不同频率的方波会发出不同音调的声音,方波的幅值决定了声音的响度。

目标

乐曲发生电路在节拍(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 乐曲演奏电路设计的更多相关文章

  1. c语言乐曲演奏——《千本樱》

    这个程序着实花费了我好长的时间,我本身对音乐一窍不通,先是跟着girl friend学习了简谱,根据c调44拍的<千本樱>写下了下面的程序. #include<stdio.h> ...

  2. 基于VHDL的8255可编程并行接口电路设计

    一.实验题目名称: 8255可编程并行接口电路设计 二.实验目的.任务和要求: 实验目的:学习掌握基本的数字系统设计方法,建立自顶向下的设计思维,能够使用VHDL语言编写简单的应用IP核,掌握基本的F ...

  3. [转]MIDI常识20条

    原文链接:http://www.midifan.com/modulearticle-detailview-488.htm Keyboard杂志老资格编辑Jim Aikin在纪念MIDI诞生20的时候发 ...

  4. 详解树莓派Model B+控制蜂鸣器演奏乐曲

    步进电机以及无源蜂鸣器这些都需要脉冲信号才能够驱动,这里将用GPIO的PWM接口驱动无源蜂鸣器弹奏乐曲,本文基于树莓派Mode B+,其他版本树莓派实现时需参照相关资料进行修改! 1 预备知识 1.1 ...

  5. 如何用C程序简单演奏乐曲

    如何用C程序简单演奏乐曲 首先我们要介绍一个函数: Beep(Frequency,time) 如果我们在程序中运行这个函数 Int main(void) { Beep(Frequency,time); ...

  6. verilog实验1:基于FPGA蜂鸣器演奏乐曲并数码管显示

    一.实验任务 利用FPGA进行代码开发,使蜂鸣器演奏出乐曲<生日快乐>,将音调显示在数码管.原理为蜂鸣器为交流源蜂鸣器,在引脚上加一定频率的方波就可以发声,而且发声的频率由所加方波决定.这 ...

  7. Raspberry Pi开发之旅-控制蜂鸣器演奏乐曲

    一.无源蜂鸣器和有源蜂鸣器 步进电机以及无源蜂鸣器这些都需要脉冲信号才能够驱动,这次尝试用GPIO的PWM接口驱动无源蜂鸣器弹奏一曲<一闪一闪亮晶晶>. 无源蜂鸣器: 无源内部没有震荡源, ...

  8. 基于VHDL利用PS2键盘控制的电子密码锁设计

    基于VHDL利用PS2键盘控制的密码锁设计 附件:下载地址 中文摘要 摘 要:现代社会,人们的安全意识正在不断提升.按键密码锁由于其具有方便性.低成本等特征,还是大有用武之地的.但是通常的按键密码锁开 ...

  9. 3. 戏说VHDL之入门游戏一:流水灯

    一.   流水灯 1.1流水灯原理 流水灯是每个学电子的入门“游戏” ,示意图如图1,其原理极其简单,但是可玩性却极强,可以就8个LED写出不同花样的程序.在1.2中我们列出两个不同思路的代码作为VH ...

随机推荐

  1. linux环境下tab键自动缩进4个空格

    1. 进入 root 模式 su root 2. 编辑 /etc/vimrc 文件 root@localhost /home/xiluhua/tscripts $ vi /etc/vimrc 3. 文 ...

  2. activiti 报 next dbid

    记录一下吧. 今天将生产环境的几个服务节点改成集群模式,其中包含activiti审批服务节点,其中各个服务几点间数据通信采用MQ(与本文无关). 然后报出如题错误. 究其原因就是,在启动activit ...

  3. Android Auto开发初探

    一.Android Auto 概述 二.Android Auto 使用方法 四.Android Auto应用开发 五.Android Auto开发总结 一.Android Auto 概述 最近物联网是 ...

  4. glog日志库移植Android平台

    1.在linux平台下使用ndk交叉编译链编译glog生成libglog.a静态库. 2.将生成的库文件与头文件放到Android项目中,使用JNI方法调用. 3.编译遇到错误“stderr.stdo ...

  5. 【linux应用】将一个大文件按行拆分成小文件

    例如将一个BLM.txt文件分成前缀为 BLM_ 的1000个小文件,后缀为系数形式,且后缀为4位数字形式 先利用 wc -l BLM.txt #读出BLM.txt有多少行. 再利用 split 命令 ...

  6. Tomcat启动报错:[Failed to start component]的解决方案

    在MyEclipse中启动Tomcat,该Tomcat仅部署了一个报错项目,启动Tomcat Server的全部信息如下: usage: java org.apache.catalina.startu ...

  7. ES6知识整理(9)--class的基本语法

    (总结完知识点,出去滑板刷街) promise的catch 上一节promise中漏了一个知识点: promise对象可以使用catch来避免每个then中都加error判断,让错误时都进到catch ...

  8. Caused by: java.net.BindException: Address already in use: bind

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'brandService ...

  9. 原生态JDBC

    原生态JDBC JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API.JDBC是java访问数据库的标准规范,可以为不同的关系 ...

  10. VMware Workstation Pro14安装

    1. 下载VMware Workstation Pro14,注意,这个链接支持win7 64及以上系统 2.  点击进入安装 3. 接受许可协议 4. 选择安装目录,是否选择增强型键盘驱动程序 5. ...