前言

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

目标

乐曲发生电路在节拍(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. kalinux 五笔安装

    1.输入命令 sudo apt-get install fcitx-table-wubi 2.配置,找到这个fcitx配置,运行,把五笔调到第2个 3.reboot重启系统

  2. kalinux实现自适用全屏、与物理主机共享文件方法

    1.执行虚拟机>安装VMware Tools菜单命令,自动挂载光驱(一般是自动挂载的,如果没有自动挂载请自行百度linux如何手动挂载光驱) 2.打开vm光驱的vmtools复制此文件到桌面: ...

  3. JAVA基础3---运算符大全

    Java中的运算符有以下种类:算术运算符.关系运算符.位运算符.逻辑运算符.赋值运算符.其他的运算符 现在假设定义 int A = 10,B = 5: 一.算术运算符 运算符 描述 案例 + 等同于数 ...

  4. 转:【专题七】UDP编程补充——UDP广播程序的实现

    上次因为时间的关系,所以把上一个专题遗留下的一个问题在本专题中和大家分享下,本专题主要介绍下如何实现UDP广播的程序,下面就直接介绍实现过程和代码以及运行的结果. 一.程序实现 UDP广播程序的实现代 ...

  5. how to backup your system of Autel MS908 Pro

    how to backup your system of Autel Scan Tool Autel MS908 Pro: Connect the tablet to a PC desktop or ...

  6. 目标检测论文阅读:Deformable Convolutional Networks

    https://blog.csdn.net/qq_21949357/article/details/80538255 这篇论文其实读起来还是比较难懂的,主要是细节部分很需要推敲,尤其是deformab ...

  7. mysql日志种类、二进制日志模式、mysqlbinlog解析二进制日志

    mysql日志的种类 二进制日志(binary log):记录数据更新的操作,mysqlbinlog 可查看二进制日志文件 错误日志(error log):记录mysql服务进程mysqld的启动.关 ...

  8. 注册登录二合一之bootstrap

    来源 https://bootsnipp.com/snippets/featured/login-and-register-tabbed-form jquery插件 需导入bootstrap插件 这个 ...

  9. 配置使用 git 秘钥连接 GitHub

    配置使用 git 秘钥连接 GitHub 在Linux下部署Git环境 1.安装Git. 使用命令安装 git . sudo apt-get install git 2.创建一个 Github 账号 ...

  10. vue 起步

    vue 官网 目前最火的前端框架当属Vue.js了,很多使用过vue的程序员这样评价它,“vue.js兼具angular.js和react.js的优点,并剔除了它们的缺点”.授予了这么高的评价的vue ...