集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 2832|回复: 10

简易电子琴设计

[复制链接]
zxopenyz 发表于 2020-1-8 08:50:44 | 显示全部楼层 |阅读模式
本帖最后由 zxopenyz 于 2020-1-8 08:52 编辑

题目分析
1、分析要求,确定总体方框图
本设计基本部分是用VHDL语言设计一个简易的八音符电子琴,在 Quartus II 平台下下载到Cyclone系列的EP1C12Q240C8芯片中,该电路设计能够实现DO、RE、MI、FA等八个音调的电子琴,发挥部分是设计一乐曲自动演奏器,用户自己编制乐曲存入电子琴,电子琴可以完成自动演奏。
电子琴音乐产生原理及硬件设计由于一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了。
根据系统设计要求,系统设计采用自顶向下的设计方法,系统的整体组装设计原理图如图1所示,它由乐曲自动演奏模块AUTO、音调发生模块TONE和数控分频模块FENPIN三部分组成。


2、最终完成的技能指标
(1)设计一个简易的八音符电子琴,它可通过按键输入来控制音响。
(2)演奏时可以选择是手动演奏(由键盘输入)还是自动演奏已存入的乐曲。
 楼主| zxopenyz 发表于 2020-1-8 08:51:03 | 显示全部楼层
选择方案
通过可编程逻辑器件(PLD)和VHDL硬件描述引言来实现电子琴的基本部分和发挥部分的设计。对于基本部分,设计的主体是数控分频器,对输入的频率进行分频,得到各个音阶对应的频率最为输出。当按下不同的键时发出不同的声音。对于发挥部分,则在原设计的基础上,增加一个乐曲存储模块,代替了键盘输入,产生节拍控制(index数据存留时间)和音阶选择信号,即在此模块中可存放一个乐曲曲谱真值表,由一个计数器来控制此真值表的输出,而由此计数器的计数时钟信号作为乐曲节拍控制信号,从而可以设计出一个纯硬件的乐曲自动演奏电路。 
方案一:由单片机来完成设计。可用单片机控制键盘的输入,以及产生相应的频率信号作为输出。目前,单片机的功能已比较强大,集成度日益增高且其设计和控制比较容易。但是由于在传统的单片机设计系统中必须使用许多分立元件组成单片机的外围电路,如锁存器,译码器等都需要单独的电路,因此整个系统显得十分复杂,抗干扰性差,在运行过程中容易死机或进入死循环,可靠性降低,而功耗费用增高。 
方案二:利用PLC来完成设计。目前利用PLC的技术已经比较成熟。PLC有其优点, 其性能优异,体积小,可靠性和精度都比较好,在电子琴的设计中可采用PLC来完成硬件的控制,但是用PLC实现编程相对比较复杂,对于电子琴这种小型设计来说成本过高。 
方案三:利用可编程逻辑器件PLD来完成该设计。利用PLD可以很好的解决上述的问题。它的成品体积小,适合电子琴这种小型设计。其性能稳定,控制精度高(Xilinx公司的高密度,高速可预测延时,高性能系列芯片),易于管理和屏蔽,抗干扰能力强,可靠性高。
综上,在本设计中选择第三种方案最优。
 楼主| zxopenyz 发表于 2020-1-8 08:52:34 | 显示全部楼层
各模块及其原理明天更
 楼主| zxopenyz 发表于 2020-1-9 09:00:13 | 显示全部楼层
各模块原理及其程序
1、乐曲自动演奏模块
乐曲自动演奏模块(AUTO.VHD)的作用是产生8位发声控制输入信号/当进行自动演奏时,由存储在此模块中的8位二进制数作为发声控制输入,从而自动演奏乐曲。
为了实现扩展部分的设计,便需要多加上一个音乐存储模块,该模块的作用是产生8位发声控制输入index,auto为0或1时可以选择自动演奏或者键盘输入,如果auto为0,则而由存储在此模块中的8位二进制数来作为发声控制输入,由此便可自动演奏乐曲。此模块的VHDL语言中包括两个进程,首先是对基准脉冲进行分频得到4Hz的脉冲,作为第二个进程的时钟信号,它的目的是控制每个音阶之间的停顿时间,此处便是1/4=0.25s,第二个进程是音乐的存储,可根据需要编写不同的乐曲。 
这段模块的原理图如图2所示:

图2乐曲自动演奏模块原理图
乐曲自动演奏模块可以由VHDL语言来实现,下面是一段主要代码:
BEGIN
IF AUTO ='0' THEN
CASE COUNT0 IS
WHEN 0=>INDEX0<="00000100";  --3
WHEN 1=>INDEX0<="00000100";  --3
WHEN 2=>INDEX0<="00000100";  --3
WHEN 3=>INDEX0<="00000100";  --3
WHEN 4=>INDEX0<="00010000";  --5
WHEN 5=>INDEX0<="00010000";  --5
WHEN 6=>INDEX0<="00010000";  --5
WHEN 7=>INDEX0<="00100000";  --6
WHEN 8=>INDEX0<="10000000";  --8
WHEN 9=>INDEX0<="10000000";  --8
WHEN 10=>INDEX0<="10000000";  --8
WHEN 11=>INDEX0<="00000100";  --3
WHEN 12=>INDEX0<="00000010";  --2
WHEN 13=>INDEX0<="00000010";  --2
WHEN 14=>INDEX0<="00000001";  --1
WHEN 15=>INDEX0<="00000001";  --1
WHEN 16=>INDEX0<="00010000";  --5
WHEN 17=>INDEX0<="00010000";  --5
WHEN 18=>INDEX0<="00001000";  --4
WHEN 19=>INDEX0<="00001000";  --4
WHEN 20=>INDEX0<="00001000";  --4
WHEN 21=>INDEX0<="00000100";  --3
WHEN 22=>INDEX0<="00000010";  --2
WHEN 23=>INDEX0<="00000010";  --2
WHEN 24=>INDEX0<="00010000";  --5
WHEN 25=>INDEX0<="00010000";  --5
WHEN 26=>INDEX0<="00001000";  --4
WHEN 27=>INDEX0<="00001000";  --4
WHEN 28=>INDEX0<="00000100";  --3
WHEN 29=>INDEX0<="00000100";  --3
WHEN 30=>INDEX0<="00000010";  --2
WHEN 31=>INDEX0<="00000010";  --2
WHEN OTHERS =>NULL;
END CASE;
ELSE INDEX0<=INDEX2;
END IF;
END PROCESS;
END BEHAVIORAL;
 楼主| zxopenyz 发表于 2020-1-9 09:00:36 | 显示全部楼层
2、音调发生模块
音调发生模块(TONE.VDL)的作用是产生获得音阶的分频预置值。当8位发声控制输入index中的某一位为高电平时,则对应某一音阶的数值将以端口tone输出,作为获得该音阶的分频预置值,该值作为数控分频器的输入,来对4MHz的脉冲进行分频,由此得到每个音阶相应的频率,例如输入index="00000010",即对应的按键是2,产生的分频系数便是6809;由code输出对应该音阶简谱的显示数码;由high输出指示音阶高8度的显示,低电平有效。&#160;
这段模块的原理图如图3所示:

图3 音调发生模块原理图
音调发生模块可以由VHDL语言来实现,下面是一段主要代码:
BEGIN
CASE INDEX IS
WHEN "00000001"=>TONE0 <=773;CODE<="1001111";HIGH<='1';
WHEN "00000010"=>TONE0 <=912;CODE<="0010010";HIGH<='1';
WHEN "00000100"=>TONE0 <=1036;CODE<="0000110";HIGH<='1';
WHEN "00001000"=>TONE0 <=1116;CODE<="1001100";HIGH<='1';
WHEN "00010000"=>TONE0 <=1197;CODE<="0100100";HIGH<='1';
WHEN "00100000"=>TONE0 <=1290;CODE<="0100000";HIGH<='0';
WHEN "01000000"=>TONE0 <=1372;CODE<="0001111";HIGH<='0';
WHEN "10000000"=>TONE0 <=1410;CODE<="0000000";HIGH<='0';
WHEN OTHERS =>TONE0<=2047;CODE<="0000001";HIGH<='0';
END CASE;
END PROCESS;
3、数控分频模块
在对EDA的学习中,我们知道数控分频器的功能是在输入端输入不同数据时,对输入时钟产生不同的分频比,输出不同频率的时钟,以改变输出信号的频率。本设计中数控分频模块是利用并行预置数的减法计数器对时基脉冲进行分频,得到与1、2、3、4、5、6、7七个音符相对应的频率。
该模块的VHDL描述中包含了三个进程。首先对32MHz的基准脉冲进行分频得到8MHz的脉冲,然后按照tone1输入的分频系数对4MHz的脉冲再次分频,得到的便是所需要的频率。而第三个进程的作用是在音调输出时再进行二分频,将脉冲展宽,以使扬声器有足够功率发音。
这段模块的原理图如图4所示:

                    图4 数控分频模块原理图
数控分频模块可以由VHDL语言来实现,下面是一段主要代码:
BEGIN
PROCESS(CLK1)
    VARIABLE COUNT:INTEGER RANGE 0 TO 8;
BEGIN
IF (CLK1'EVENT AND CLK1='1')THEN
   COUNT:=COUNT +1;
  IF COUNT=2 THEN
   PRECLK<='1';
  ELSIF COUNT =4 THEN
   PRECLK<='0';COUNT:=0;
  END IF ;
END IF ;
END PROCESS;
PROCESS(PRECLK,TONE1)
VARIABLE COUNT11:INTEGER RANGE 0 TO 2047;
BEGIN
IF (PRECLK'EVENT AND PRECLK='1')THEN
IF COUNT11<TONE1 THEN
COUNT11:=COUNT11+1;FULLSPKS<='1';
ELSE
COUNT11:=0;FULLSPKS<='0';
END IF ;
END IF ;
END PROCESS;
PROCESS(FULLSPKS)
VARIABLE  COUNT2 :STD_LOGIC:='0';
BEGIN
IF (FULLSPKS'EVENT AND FULLSPKS='1')THEN
COUNT2:=NOT COUNT2;
IF COUNT2='1'THEN
SPKS<='1';
ELSE
SPKS<='0';
END IF ;
END IF;
END PROCESS;
月影星痕 发表于 2020-1-9 09:28:23 | 显示全部楼层
简易电子琴设计
 楼主| zxopenyz 发表于 2020-1-10 09:03:13 | 显示全部楼层
顶层设计
该DIANZIQIN模块是整个电子琴设计的核心,也是VHDL程序的主程序,前面3个源程序都是作为子程序分别实现电子琴的某一功能,而DIANZIQIN模块则通过调用子程序最终实现乐曲演奏的目的,奏出美妙的乐曲。利用VHDL语言COMPONENT将三个模块组合起来,其中3个模块和DIANZIQIN模块的输入输出是一一对应的
 楼主| zxopenyz 发表于 2020-1-10 09:04:04 | 显示全部楼层
编程下载测试
1、功能仿真
功能仿真用于综合前检查设计的逻辑功能是否符合设计要求。仿真过程中可以通过观察检测设计的输入信号,输出信号以及内部信号以检测设计的逻辑功能。如果仿真都通过的话就可以进行引脚锁定,然后下载程序,在实验箱上可以直观的看到结果。
2、锁定引脚
3、硬件测试结果
    选择模式3,PIO31控制是否自动播放预置歌曲或手动键入歌曲,可通过按键1—8演奏歌曲。
 楼主| zxopenyz 发表于 2020-1-10 09:04:20 | 显示全部楼层
本帖最后由 zxopenyz 于 2020-1-10 09:07 编辑

附录
源程序如下:

1、自动演奏模块程序(AUTO.VHD):
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY AUTO IS
PORT ( CLK :  IN STD_LOGIC;   --系统时钟;键盘输入/自动演奏
       AUTO : IN STD_LOGIC; &#160;--键盘输入信号&#160;
       CLK2 : BUFFER STD_LOGIC;  --音符信号输出
       INDEX2 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
       INDEX0 : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END AUTO;
ARCHITECTURE BEHAVIORAL OF AUTO IS
       SIGNAL COUNT0: INTEGER RANGE 0 TO 31;
BEGIN
PULSE0 : PROCESS(CLK,AUTO) &#160;
--此进程完成对系统时钟8M的分频,得到4Hz的信号clk2
       VARIABLE COUNT :INTEGER RANGE 0 TO 8;  
--定义计数器变量,值从0到8
BEGIN
IF AUTO ='1' THEN  --键盘输入为1
       COUNT := 0;CLK2<='0';  --计数器值指0,时钟信号为0
ELSIF(CLK'EVENT AND CLK ='1')THEN  --时钟输入信号为1
       COUNT :=COUNT +1;  --计数器加1
IF COUNT =4 THEN
       CLK2 <='1';
ELSIF COUNT =8 THEN
       CLK2<='0'; COUNT:=0;
END IF ;
END IF ;
END PROCESS;
MUSIC: PROCESS(CLK2)   --此进程完成自动演奏部分曲的地址累加
BEGIN
IF (CLK2'EVENT AND CLK2='1')THEN
    IF (COUNT0=31)THEN
      COUNT0<=0;
    ELSE
      COUNT0<=COUNT0+1;
   END IF ;
END IF ;
END PROCESS;
COM1: PROCESS(COUNT0,AUTO,INDEX2)
BEGIN
IF AUTO ='0' THEN
CASE COUNT0 IS  --此case语句:存储自动演奏部分的曲
WHEN 0=>INDEX0<="00000100";  --3
WHEN 1=>INDEX0<="00000100";  --3
WHEN 2=>INDEX0<="00000100";  --3
WHEN 3=>INDEX0<="00000100";  --3
WHEN 4=>INDEX0<="00010000";  --5
WHEN 5=>INDEX0<="00010000";  --5
WHEN 6=>INDEX0<="00010000";  --5
WHEN 7=>INDEX0<="00100000";  --6
WHEN 8=>INDEX0<="10000000";  --8
WHEN 9=>INDEX0<="10000000";  --8
WHEN 10=>INDEX0<="10000000";  --8
WHEN 11=>INDEX0<="00000100";  --3
WHEN 12=>INDEX0<="00000010";  --2
WHEN 13=>INDEX0<="00000010";  --2
WHEN 14=>INDEX0<="00000001";  --1
WHEN 15=>INDEX0<="00000001";  --1
WHEN 16=>INDEX0<="00010000";  --5
WHEN 17=>INDEX0<="00010000";  --5
WHEN 18=>INDEX0<="00001000";  --4
WHEN 19=>INDEX0<="00001000";  --4
WHEN 20=>INDEX0<="00001000";  --4
WHEN 21=>INDEX0<="00000100";  --3
WHEN 22=>INDEX0<="00000010";  --2
WHEN 23=>INDEX0<="00000010";  --2
WHEN 24=>INDEX0<="00010000";  --5
WHEN 25=>INDEX0<="00010000";  --5
WHEN 26=>INDEX0<="00001000";  --4
WHEN 27=>INDEX0<="00001000";  --4
WHEN 28=>INDEX0<="00000100";  --3
WHEN 29=>INDEX0<="00000100";  --3
WHEN 30=>INDEX0<="00000010";  --2
WHEN 31=>INDEX0<="00000010";  --2
WHEN OTHERS =>NULL;
END CASE;
ELSE INDEX0<=INDEX2;  --此进程完成自动演奏部分曲的地址累加
END IF;
END PROCESS;
END BEHAVIORAL;

2、数控分频模块程序(FENPIN.VHD):
LIBRARY  IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY FENPIN IS
    PORT(CLK1: IN STD_LOGIC;  --定义系统时钟
          TONE1: IN INTEGER RANGE 0 TO 2047;  
--定义音符分频系数,从0到2047Hz
           SPKS:    OUT STD_LOGIC);  --定义驱动扬声器的音频信号
END ENTITY FENPIN;
ARCHITECTURE ART OF FENPIN IS
    SIGNAL   PRECLK:STD_LOGIC;
    SIGNAL   FULLSPKS:STD_LOGIC;
BEGIN
PROCESS(CLK1)
    VARIABLE COUNT:INTEGER RANGE 0 TO 8;  --此进程对系统时钟进行4分频
BEGIN
IF (CLK1'EVENT AND CLK1='1')THEN  
   COUNT:=COUNT +1;
  IF COUNT=2 THEN
   PRECLK<='1';
  ELSIF COUNT =4 THEN
   PRECLK<='0';COUNT:=0;
  END IF ;
END IF ;
END PROCESS;
PROCESS(PRECLK,TONE1)  --此进程按照tone1输入
==分频系数对8MHz的脉冲再次分频,得到所需要的音符频率
VARIABLE COUNT11:INTEGER RANGE 0 TO 2047;
BEGIN
IF (PRECLK'EVENT AND PRECLK='1')THEN
IF COUNT11<TONE1 THEN
COUNT11:=COUNT11+1;FULLSPKS<='1';
ELSE
COUNT11:=0;FULLSPKS<='0';  --此进程对FULLSPKS进行2分频
END IF ;
END IF ;
END PROCESS;
PROCESS(FULLSPKS)
VARIABLE  COUNT2 :STD_LOGIC:='0';
BEGIN
IF (FULLSPKS'EVENT AND FULLSPKS='1')THEN
COUNT2:=NOT COUNT2;
IF COUNT2='1'THEN
SPKS<='1';
ELSE
SPKS<='0';
END IF ;
END IF;
END PROCESS;
END ART;

3、音调发生模块程序(TONE.VHD):
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY TONE IS
    PORT (INDEX:    IN STD_LOGIC_VECTOR(7 DOWNTO 0);  --音符输入信号
          CODE:     OUT STD_LOGIC_VECTOR(6 DOWNTO 0);  --音符显示信号
          HIGH:      OUT STD_LOGIC;  --高低音显示信号
          TONE0:     OUT INTEGER RANGE 0 TO 2047);  --音符的分频系数
END TONE;
ARCHITECTURE ART OF TONE IS
  BEGIN
  SEARCH : PROCESS(INDEX)  
--此进程完成音符到音符的分频系数移码,音符的显示,高低音阶。
BEGIN
CASE INDEX IS
WHEN "00000001"=>TONE0 <=773;CODE<="1001111";HIGH<='1';
WHEN "00000010"=>TONE0 <=912;CODE<="0010010";HIGH<='1';
--音符第7位为1,分频数912Hz,音符显示为0010010,属高音
WHEN "00000100"=>TONE0 <=1036;CODE<="0000110";HIGH<='1';
WHEN "00001000"=>TONE0 <=1116;CODE<="1001100";HIGH<='1';
WHEN "00010000"=>TONE0 <=1197;CODE<="0100100";HIGH<='1';
WHEN "00100000"=>TONE0 <=1290;CODE<="0100000";HIGH<='0';
WHEN "01000000"=>TONE0 <=1372;CODE<="0001111";HIGH<='0';
WHEN "10000000"=>TONE0 <=1410;CODE<="0000000";HIGH<='0';
WHEN OTHERS =>TONE0<=2047;CODE<="0000001";HIGH<='0';
    END CASE;
  END PROCESS;
END ART;
zxopenljx 发表于 2023-7-18 18:18:39 | 显示全部楼层
简易电子琴设计
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-11-27 22:26 , Processed in 0.066241 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表