wujing 发表于 2019-3-14 14:26:29

FPGA音乐播放器

第1部分 实验介绍
1.1 实验题目
简易音乐播放器
1.2 实验摘要
本系统是采用EDA技术设计的一个简易的5音符电子琴和音乐播放器,该系统基于计算机中时钟分频器的原理,采用自顶向下的设计方法来实现,它可以通过按键输入来控制音响。系统实现是用硬件描述语言VHDL按模块化方式进行设计,然后进行编程、时序仿真、整合。本系统功能比较齐全,有一定的使用价值
1.3 任务及可实现功能
1. 播放器内预存3 首乐曲;
2. 播放模式:顺序播放、随机播放,或者自动弹奏模式,LED显示当前播放模式;
顺序播放:按内部给定的顺序依次播放3 首乐曲;
随机播放:随机产生一个顺序播放3 首乐曲;
自动弹奏:可以手动弹奏想要的乐曲;
3. 用数码管显示当前播放乐曲的顺序号;
4. 设置开始/暂停键,乐曲播放过程中按该键则暂停播放,再按则继续播放;
5. 设置Nexttone,Lasttone 和Previous 键,按Nexttone 键可以听下一首,按Lasttone 键可以听上一首,按Previous 键回到本首重新开始;
6.用户可以自行设定播放顺序,设置完成后,播放器按该顺序依次
播放乐曲;
7. 用户可以自行选择想听的歌曲,选择那首播放哪首
8.led等跟随音乐闪烁不同的颜色
9.点阵凭跟随音乐显示跳动的心
第2部分 设计概要

2.1 设计目的


(1)熟悉VHDL语言和Quartus2软件的使用
(2)理解状态机的工作原理和设计方法
(3)掌握利用EDA工具进行自顶向下的电子系统设计方法

2.2设计思路
根据VHDL自顶向下的设计思路,把简易乐曲播放器电路分为3个主要模块,即音乐播放music模块,音调发生tonet模块,数控分频speakera模块。分好模块之后,编写每个模块的程序,分别生成项目符号,最后把生成的个项目符号用原理图的方式连接起来,然后编译、下载即可。
由图例表示如下:
输入(曲)                                                      输出(曲)
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps1.pngfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps2.pngfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps3.png
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps4.pngfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps5.pngfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps6.pngfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps7.png


2.3 设计功能说明


1.音乐播放music模块
音乐播放模块的作用是产生发声控制输入信号。当进行演奏时,有自此模块中的数作为发声控制输入,从而自动演奏音乐。

2.音调发生tone模块
音调发生模块的作用是产生音阶分频预置值。当8位发生控制输入信号中的某一位为高电平时,则对应某一音阶的数值将输出,该数值即为该音阶的分频预置值,分频预置值控制数频分频模块进行分频,由此可得到每个音节对应的频率。

3.数控分频frequency模块
数控分频模块是对时基脉冲进行分频,得到与1,2,3,4,5,6,7七个音符相对应的频率。

4.灯光模块
控制led小灯,会跟着音乐打节拍。

5.点阵模块
控制点阵变化图形,跟随音乐,显示跳动的心脏第3部分 实验结果


3.1主程序流程图


file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps8.pngfile:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps9.png

3.2主要功能模块代码
A.顶层函数mymusic
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_signed.all;
ENTITY mine IS
PORT
   (CLK50MHZ :IN STD_LOGIC;               --主频50M
      reset:IN STD_LOGIC;
      hang,lie,hangnew:out std_logic_vector(7 downto 0); --点阵
      LED: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);--彩灯功能
      SOC : IN STD_LOGIC;                     --暂停或播放
      SHOW : OUT STD_LOGIC;                   --播放模式显示
      NEXTONE : IN STD_LOGIC;               --下一首
      LASTONE : IN STD_LOGIC;               --上一首
      PREVIOUS : IN STD_LOGIC;                --本首重来
      SPKOUT: OUT STD_LOGIC;                  --音频输出
      MODE: IN STD_LOGIC;                   --播放模式
      SEG:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);   --歌曲序号显示
      CAT:OUT STD_LOGIC_VECTOR(5 DOWNTO 0);   --第1个数码管显示歌曲序号
      STOP: IN STD_LOGIC
      );
END;

ARCHITECTURE one OF mine IS            
COMPONENT NoteTabs
   PORT ( clk :IN STD_LOGIC;                        --4Hz
         ToneIndex : OUT INTEGER RANGE 0 TO 15;      --音调
         SEG:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);       --7段数码管输出
         RANDOM: IN STD_LOGIC;
         SOC : IN STD_LOGIC;                         --播放或暂停STOP OR CONTINUE
         NEXTONE: IN STD_LOGIC;                     --下一首
         LASTONE : IN STD_LOGIC;                      --上一首
         PREVIOUS : IN STD_LOGIC ;                  --本首重来
         MODE : IN STD_LOGIC;                         --播放模式
         SHOW :OUT STD_LOGIC;                         --播放模式显示
         CAT:OUT STD_LOGIC_VECTOR(5 DOWNTO 0);--第1个数码管显示歌曲序号
         reset3:in std_logic;       
           hang3:out std_logic_vector(7 downto 0);
           hangnew3:out std_logic_vector(7 downto 0);
           lie3:out std_logic_vector(7 downto 0)   
         );
END COMPONENT;

COMPONENT ToneT
    PORT ( Index: IN INTEGER RANGE 0 TO 15;--音调
         
         LED : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
         Tone : OUT INTEGER RANGE 0 TO 16#7FF#--――分频系数
      );
END COMPONENT;

COMPONENT Speakera
PORT
(clk:IN STD_LOGIC;--1Mhz
Tone:IN INTEGER RANGE 0 TO 16#7FF#;--分频系数
SpkS:OUT STD_LOGIC);--给蜂鸣器的频率信号
END COMPONENT;

COMPONENT divide
            port(
                clk:IN STD_LOGIC;
                clk_out:OUT STD_LOGIC);
            END COMPONENT;

SIGNAL Tone : INTEGER RANGE 0 TO 16#7FF#;
SIGNAL ToneIndex :INTEGER RANGE 0 TO 15;
SIGNAL T:STD_LOGIC;                     --分频信号
SIGNAL CLK1MHZ:STD_LOGIC;
--signal clk_tmp1:std_logic;
signal state:integer range 0 to 2;   
signal h3,hnew3,l3:std_logic_vector(7 downto 0);

CONSTANT LENGTH:POSITIVE:=8;         
CONSTANT TAP1:POSITIVE:=8;
CONSTANT TAP2:POSITIVE:=4;
SIGNAL PRBS:STD_LOGIC;
SIGNAL PRREG:STD_LOGIC_VECTOR(LENGTH DOWNTO 0);

BEGIN
PROCESS(CLK50MHZ)                      --T分50M
VARIABLE b:INTEGER RANGE 0 TO 24;
BEGIN
IF(CLK50MHZ'EVENT AND CLK50MHZ='1')THEN
IF(b=24)THEN
   b:=0;
       CLK1MHZ<=NOT CLK1MHZ;
ELSE
      b:=b+1;
END IF;
END IF;
END PROCESS;

PROCESS(CLK1MHZ)                      --T分1M频为4Hz
VARIABLE C:INTEGER RANGE 0 TO 124999;
BEGIN
IF(CLK1MHZ'EVENT AND CLK1MHZ='1')THEN
IF(C=124999)THEN
       C:=0;
       T<=NOT T;
ELSE
       C:=C+1;
END IF;
END IF;
END PROCESS;



process(T,STOP)         --产生一个伪随机信号
begin
    if STOP='1' then
      prreg<=(others=>'0');
      prreg(0)<='1';
    elsif T'event and T='1' then
      prreg<=(prreg((length-1)downto 0)&
      (prreg(tap1)xor prreg(tap2)));
    end if;
end process;
prbs<=prreg(length);      --prbs随机为0或1

--fp: divide PORT MAP(clk=>CLK50MHZ,clk_out=>clk_tmp1);
u1: NoteTabs PORT MAP(clk=>T,MODE=>MODE,SHOW=>SHOW, ToneIndex => ToneIndex,
                      RANDOM=>PRBS,SEG=>SEG,SOC=>SOC,NEXTONE=>NEXTONE,LASTONE=>LASTONE,PREVIOUS=>PREVIOUS,CAT=>CAT,hang3=>h3,hangnew3=>hnew3,lie3=>l3,reset3=>reset);
u2: ToneT PORT MAP(Index=>ToneIndex, Tone=>Tone,LED=>LED);
u3: Speakera PORT MAP(clk=>CLK1MHZ,Tone=>Tone ,SpkS=>SPKOUT);
   

END;
B 音乐播放模块notetabs
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_signed.all;
ENTITY NoteTabs IS
    PORT ( clk :IN STD_LOGIC;                        --4Hz
         ToneIndex : OUT INTEGER RANGE 0 TO 15;      --音调
         SEG:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);       --7段数码管输出
         RANDOM: IN STD_LOGIC;
         SOC : IN STD_LOGIC;                         --播放或暂停STOP OR CONTINUE
         NEXTONE: IN STD_LOGIC;                     --下一首
         LASTONE : IN STD_LOGIC;                      --上一首
         PREVIOUS : IN STD_LOGIC ;                  --本首重来
         DUO:IN STD_LOGIC;                            --1
         MODE : IN STD_LOGIC;                         --播放模式
         SHOW :OUT STD_LOGIC;                         --播放模式显示
         CAT:OUT STD_LOGIC_VECTOR(5 DOWNTO 0);      
         clk3,reset3:in std_logic;       
           hang3:out std_logic_vector(7 downto 0);
           hangnew3:out std_logic_vector(7 downto 0);
           lie3:out std_logic_vector(7 downto 0)   
         );
END;
ARCHITECTURE one OF NoteTabs IS
SIGNAL Counter : INTEGER RANGE 0 TO 152;
signal chushi:std_logic_vector(14 downto 0):="000000000000000";       
signal gaowei:std_logic_vector(1 downto 0);           
signal diwei:std_logic_vector(2 downto 0);   
BEGIN

    CNT8: PROCESS(clk,SOC,MODE, RANDOM,NEXTONE,LASTONE,PREVIOUS)
   BEGIN
IF(clk'EVENT AND clk='1') THEN
   IF( NEXTONE='0' AND LASTONE='0' AND PREVIOUS='0' AND MODE='0'AND SOC='0' ) THEN      --顺序播放模式下
       SHOW<='0';       --灯灭
       IF Counter=152 THEN Counter <=0;
       ELSECounter<=Counter+1;
       END IF;
    ELSIF (NEXTONE='0'AND LASTONE='0' AND PREVIOUS='0' AND MODE='1'AND SOC='0' )THEN   --随机播放模式下
       SHOW<='1';       --灯亮
         
             IF Counter=47 THEN                           --每首歌完后,如果随机信号为0则播放下一首歌
             IF RANDOM='0'    THEN Counter<=48;            --如果为1,则播放前一首歌。这一切都可由改变状态
             ELSIF RANDOM='1' THEN Counter<=97;      --计数器Counter来实现
             END IF;
         ELSIF Counter=96 THEN
             IF RANDOM='0' THEN Counter<=97;            
             ELSIF RANDOM='1' THEN Counter<=00;
             END IF;
         ELSIF Counter=152 THEN
             IF RANDOM='0' THEN Counter<=00;
             ELSIF RANDOM='1' THEN Counter<=48;
             END IF;
         ELSECounter<=Counter+1;
         END IF;


    ELSIF SOC='1' THEN                --如果暂停了,计数器暂停计数
          Counter<=Counter;
    ELSIF (NEXTONE='1' AND LASTONE='0'AND PREVIOUS='0') THEN      --选择下一首,将计数器改为下首歌曲开始的一个数
         IF(Counter<=47)   THENCounter<=48;
         ELSIF(Counter>=48 and Counter<=96)THEN Counter<=97;
         ELSIF(Counter>=97)THEN Counter<=00;
         END IF;
    ELSIF(NEXTONE='0' AND LASTONE='1' AND PREVIOUS='0') THEN    --选择上一首,将计数器直改为上首歌曲开始的一个数
         IF(Counter<=47)   THENCounter<=97;
         ELSIF(Counter>=48 and Counter<=96)THEN Counter<=00;
         ELSIF(Counter>=97)THEN Counter<=48;
         END IF;
    ELSIF(NEXTONE='0' AND LASTONE='0' AND PREVIOUS='1') THEN    --选择本首重放,将计数器改为本首开始的状态数
         IF(Counter<=47)   THENCounter<=00;
         ELSIF(Counter>=48 and Counter<=96)THEN Counter<=48;
         ELSIF(Counter>=97)THEN Counter<=97;
      END IF;         
    END IF;
   END IF;   
   END PROCESS;
PROCESS(clk)                  --歌曲序号显示,通过状态数的大小判断
BEGIN

if(reset3='1')then
chushi<="000000000000000";
elsif(reset3='0')then
if(clk3'event and clk3='1')then
chushi<=chushi+1;
end if;   
end if;

    gaowei(1 downto 0)<=chushi(14 downto 13);       
diwei(2 downto 0)<=chushi(2 downto 0);       
case diwei is                           --xianshihang
                    when"000"=>lie3<="01111111";
                    when"001"=>lie3<="10111111";
                    when"010"=>lie3<="11011111";
                    when"011"=>lie3<="11101111";
                    when"100"=>lie3<="11110111";
                    when"101"=>lie3<="11111011";
                    when"110"=>lie3<="11111101";
                    when"111"=>lie3<="11111110";
                end case;   
            if gaowei="00"then                             --waiquanhongxin
                hangnew3<="00000000";
                case diwei is                           
                    when"000"=>hang3<="01100110";
                    when"001"=>hang3<="10011001";
                    when"010"=>hang3<="10000001";
                    when"011"=>hang3<="10000001";
                    when"100"=>hang3<="10000001";
                    when"101"=>hang3<="01000010";
                    when"110"=>hang3<="00100100";
                    when"111"=>hang3<="00011000";
                end case;
            elsif gaowei="01"then                       --xianshi0
                case diwei is                              
                    when"000"=>hang3<="00000000";hangnew3<="00000000";
                    when"001"=>hang3<="00100100";hangnew3<="00100100";
                    when"010"=>hang3<="01011010";hangnew3<="01011010";
                    when"011"=>hang3<="01000010";hangnew3<="01000010";
                    when"100"=>hang3<="01000010";hangnew3<="01000010";
                    when"101"=>hang3<="00100100";hangnew3<="00100100";
                    when"110"=>hang3<="00011000";hangnew3<="00011000";
                    when"111"=>hang3<="00000000";hangnew3<="00000000";
                end case;
            elsif gaowei="10"then                          --xianshi1
               
                case diwei is               
                    when"000"=>hangnew3<="00000000";hang3<="00000000";
                    when"001"=>hangnew3<="00000000";hang3<="00000000";
                    when"010"=>hangnew3<="00100100";hang3<="00000000";
                    when"011"=>hangnew3<="00111100";hang3<="00000000";
                    when"100"=>hangnew3<="00111100";hang3<="00000000";
                    when"101"=>hangnew3<="00011000";hang3<="00000000";
                    when"110"=>hangnew3<="00000000";hang3<="00000000";
                    when"111"=>hangnew3<="00000000";hang3<="00000000";
                end case;
            elsif gaowei="11"then                          --xian shi1
                case diwei is            
                    when"000"=>hang3<="01100110";hangnew3<="00000000";
                    when"001"=>hang3<="10111101";hangnew3<="00100100";
                    when"010"=>hang3<="11011011";hangnew3<="01111110";
                    when"011"=>hang3<="11000011";hangnew3<="01111110";
                    when"100"=>hang3<="11000011";hangnew3<="01111110";
                    when"101"=>hang3<="01100110";hangnew3<="00111100";
                    when"110"=>hang3<="00111100";hangnew3<="00011000";
                    when"111"=>hang3<="00011000";hangnew3<="00000000";
                end case;
          end if;
         
    IF    Counter<=47 THEN CAT<="011111";               --之让第一个7段数码管显示歌曲序号
          SEG<="0110000";
    ELSIF Counter>=48 AND Counter<=96 THENCAT<="101111";
          SEG<="1101101";
    ELSIF Counter>=97 THEN   CAT<="110111";
    SEG<="1111001";   
    END IF;
END PROCESS;


Search : PROCESS(Counter)
BEGIN
CASE Counter IS
WHEN 0 =>ToneIndex <=15;--第一首歌《小星星》
WHEN 1 =>ToneIndex <=15;
WHEN 2 =>ToneIndex <=0;
WHEN 3 =>ToneIndex <=14;
WHEN 4 =>ToneIndex <=14;
WHEN 5 =>ToneIndex <=0;
WHEN 6 =>ToneIndex <=13;
WHEN 7 =>ToneIndex <=13;
WHEN 8 =>ToneIndex <=0;
WHEN 9 =>ToneIndex <=12;
WHEN 10 =>ToneIndex <=12;
WHEN 11 =>ToneIndex <=0;
WHEN 12 =>ToneIndex <=11;
WHEN 13 =>ToneIndex <=11;
WHEN 14 =>ToneIndex <=0;
WHEN 15 =>ToneIndex <=10;
WHEN 16 =>ToneIndex <=10;
WHEN 17 =>ToneIndex <=0;
WHEN 18 =>ToneIndex <=9;
WHEN 19 =>ToneIndex <=9;
WHEN 20 =>ToneIndex <=0;
WHEN 21 =>ToneIndex <=8;
WHEN 22 =>ToneIndex <=8;
WHEN 23 =>ToneIndex <=0;
WHEN 24 =>ToneIndex <=7;
WHEN 25 =>ToneIndex <=7;
WHEN 26 =>ToneIndex <=0;
WHEN 27 =>ToneIndex <=6;
WHEN 28 =>ToneIndex <=6;
WHEN 29 =>ToneIndex <=0;
WHEN 30 =>ToneIndex <=5;
WHEN 31 =>ToneIndex <=5;
WHEN 32 =>ToneIndex <=0;
WHEN 33 =>ToneIndex <=4;
WHEN 34 =>ToneIndex <=4;
WHEN 35 =>ToneIndex <=0;
WHEN 36 =>ToneIndex <=3;
WHEN 37 =>ToneIndex <=3;
WHEN 38 =>ToneIndex <=0;
WHEN 39 =>ToneIndex <=2;
WHEN 40 =>ToneIndex <=2;
WHEN 41 =>ToneIndex <=0;
WHEN 42 =>ToneIndex <=1;
WHEN 43 =>ToneIndex <=1;
WHEN 44 =>ToneIndex <=0;
WHEN 45 =>ToneIndex <=0;
WHEN 46 =>ToneIndex <=0;
WHEN 47 =>ToneIndex <=0;

WHEN 48 =>ToneIndex <=10; --第二首歌《雪融花》
WHEN 49 =>ToneIndex <=10;
WHEN 50 =>ToneIndex <=10;
WHEN 51 =>ToneIndex <=10;
WHEN 52 =>ToneIndex <=12;
WHEN 53 =>ToneIndex <=12;
WHEN 54 =>ToneIndex <=15;
WHEN 55 =>ToneIndex <=15;
WHEN 56 =>ToneIndex <=15;
WHEN 57 =>ToneIndex <=15;
WHEN 58 =>ToneIndex <=15;
WHEN 59 =>ToneIndex <=15;
WHEN 60 =>ToneIndex <=15;
WHEN 61 =>ToneIndex <=15;
WHEN 62 =>ToneIndex <=15;
WHEN 63 =>ToneIndex <=15;
WHEN 64 =>ToneIndex <=12;
WHEN 65 =>ToneIndex <=12;
WHEN 66 =>ToneIndex <=11;
WHEN 67 =>ToneIndex <=11;
WHEN 68 =>ToneIndex <=11;
WHEN 69 =>ToneIndex <=11;
WHEN 70 =>ToneIndex <=11;
WHEN 71 =>ToneIndex <=11;
WHEN 72 =>ToneIndex <=10;
WHEN 73 =>ToneIndex <=10;
WHEN 74 =>ToneIndex <=10;
WHEN 75 =>ToneIndex <=10;
WHEN 76 =>ToneIndex <=10;
WHEN 77 =>ToneIndex <=10;
WHEN 78 =>ToneIndex <=10;
WHEN 79 =>ToneIndex <=10;
WHEN 80 =>ToneIndex <=11;
WHEN 81 =>ToneIndex <=11;
WHEN 82 =>ToneIndex <=12;
WHEN 83 =>ToneIndex <=12;
WHEN 84 =>ToneIndex <=13;
WHEN 85 =>ToneIndex <=13;
WHEN 86 =>ToneIndex <=13;
WHEN 87 =>ToneIndex <=13;
WHEN 88 =>ToneIndex <=13;
WHEN 89 =>ToneIndex <=13;
WHEN 90 =>ToneIndex <=12;
WHEN 91 =>ToneIndex <=12;
WHEN 92 =>ToneIndex <=12;
WHEN 93 =>ToneIndex <=12;
WHEN 94 =>ToneIndex <=12;
WHEN 95 =>ToneIndex <=12;
WHEN 96 =>ToneIndex <=10;


WHEN 97 =>ToneIndex <=5; --第三首歌《童话》
WHEN 98 =>ToneIndex <=12;
WHEN 99 =>ToneIndex <=11;
WHEN 100 =>ToneIndex <=10;
WHEN 101 =>ToneIndex <=10;
WHEN 102 =>ToneIndex <=10;
WHEN 103 =>ToneIndex <=11;
WHEN 104 =>ToneIndex <=10;
WHEN 105 =>ToneIndex <=10;
WHEN 106 =>ToneIndex <=10;
WHEN 107 =>ToneIndex <=11;
WHEN 108 =>ToneIndex <=10;
WHEN 109 =>ToneIndex <=11;
WHEN 110 =>ToneIndex <=10;
WHEN 111 =>ToneIndex <=9;
WHEN 112 =>ToneIndex <=0;
WHEN 113 =>ToneIndex <=8;
WHEN 114 =>ToneIndex <=10;
WHEN 115 =>ToneIndex <=12;
WHEN 116 =>ToneIndex <=13;
WHEN 117 =>ToneIndex <=13;
WHEN 118 =>ToneIndex <=13;
WHEN 119 =>ToneIndex <=12;
WHEN 120 =>ToneIndex <=12;
WHEN 121 =>ToneIndex <=9;
WHEN 122 =>ToneIndex <=9;
WHEN 123 =>ToneIndex <=11;
WHEN 124 =>ToneIndex <=10;
WHEN 125 =>ToneIndex <=10;
WHEN 126 =>ToneIndex <=10;
WHEN 127 =>ToneIndex <=10;
WHEN 128 =>ToneIndex <=0;
WHEN 129 =>ToneIndex <=8;
WHEN 130 =>ToneIndex <=10;
WHEN 131 =>ToneIndex <=12;
WHEN 132 =>ToneIndex <=13;
WHEN 133 =>ToneIndex <=13;
WHEN 134 =>ToneIndex <=13;
WHEN 135 =>ToneIndex <=12;
WHEN 136 =>ToneIndex <=12;
WHEN 137 =>ToneIndex <=9;
WHEN 138 =>ToneIndex <=9;
WHEN 139 =>ToneIndex <=11;
WHEN 140 =>ToneIndex <=10;
WHEN 141 =>ToneIndex <=11;
WHEN 142 =>ToneIndex <=10;
WHEN 143 =>ToneIndex <=9;
WHEN 144 =>ToneIndex <=8;
WHEN 145 =>ToneIndex <=8;
WHEN 146 =>ToneIndex <=9;
WHEN 147 =>ToneIndex <=10;
WHEN 148 =>ToneIndex <=6;
WHEN 149 =>ToneIndex <=6;
WHEN 150 =>ToneIndex <=6;
WHEN 151 =>ToneIndex <=8;
WHEN 152 =>ToneIndex <=8;
WHEN OTHERS =>NULL;
    END CASE;
END PROCESS;
END;
C.音调发声ToneT
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_signed.all;
ENTITY ToneT IS
PORT ( Index: IN INTEGER RANGE 0 TO 15;
         
         LED: OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
         Tone:OUTINTEGER RANGE 0 TO 16#7FF#);
END;


ARCHITECTURE one OF ToneT IS

BEGIN
    Search : PROCESS(Index)
    BEGIN
       CASE Index IS                                 --音调分频比
      WHEN 0=>Tone<= 0;      
      WHEN 1=>Tone<= 1318;   LED<="1000000";--1
      WHEN 2=>Tone<= 1174;   LED<="0100000";--7
      WHEN 4=>Tone<= 1045;   LED<="0001000";--6
      WHEN 3=>Tone<= 987;    LED<="0010000";--5
      WHEN 5=>Tone<= 880;    LED<="0000100";--4
      WHEN 6=>Tone<= 783;    LED<="0000010";--3
      WHEN 7=>Tone<= 698;    LED<="0000001";--2
      WHEN 8=>Tone<= 659;    LED<="1000000";--1
      WHEN 9=>Tone<= 587;    LED<="0100000";--7
      WHEN 10=>Tone<=523;    LED<="0010000";--6
      WHEN 11=>Tone<=493;    LED<="0001000";--5
      WHEN 12=>Tone<=440;    LED<="0000100";--4
      WHEN 13=>Tone<=391;    LED<="0000010";--3
      WHEN 14=>Tone<=349;    LED<="0000001";--2
      WHEN 15=>Tone<=329;    LED<="1000000";--1
      WHEN OTHERS =>NULL;
END CASE;
END PROCESS;
END;
D,数控分频Speakera
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_signed.all;
ENTITY Speakera IS
    PORT ( clk :IN STD_LOGIC;         --1MHz
         Tone : IN INTEGER RANGE 0 TO 16#7FF#;   --音调分频比率
         Spks :OUT STD_LOGIC);      --频率输出给蜂鸣器
END;

ARCHITECTURE one OF Speakera IS
SIGNAL PreCLK : STD_LOGIC;
SIGNAL FullSpks : STD_LOGIC;
BEGIN
DivideCLK : PROCESS(clk)               
    VARIABLE COUNT4: INTEGER RANGE 0 TO 8;
BEGIN
    IF(CLK'EVENT AND CLK='1')THEN
      COUNT4:=COUNT4+1;
      IF COUNT4=2 THEN
         PRECLK<='1';
         ELSIF COUNT4=4 THEN
         PRECLK<='0';COUNT4:=0;
         END IF;
   END IF;
   END PROCESS;
GenSpks : PROCESS (PreCLK,Tone)
       VARIABLE Count11 : INTEGER RANGE 0 TO 16#7FF#;
BEGIN
      IF PreCLK'EVENT AND PreCLK='1'THEN             --按分频比分频
         IF Count11 = Tone THEN
             Count11 :=0;
            FullSpks <='1';
         ELSECount11 := Count11 +1;
               FullSpks <='0';   END IF;
       END IF;
END PROCESS;
DelaySpks : PROCESS (FullSpks)      
      VARIABLE Count2 : STD_LOGIC;
BEGIN                                       
      IF FullSpks'EVENT AND FullSpks='1'THEN         --D触发器2分频,保证蜂鸣器发声稳定
         Count2:= NOT Count2 ;
         IF Count2 ='1'   THEN Spks <='1';
          ELSE    Spks <='0';END IF;
      END IF;
    END PROCESS;
END;
E.点阵显示模块
library ieee;                                       
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;         
entity dianzhenxianshixs is       
        port( clk3,reset3:in std_logic;       
            hang3:out std_logic_vector(7 downto 0);
            hangnew3:out std_logic_vector(7 downto 0);
            lie3:out std_logic_vector(7 downto 0));       
        end dianzhenxianshixs;
architecture jg of dianzhenxianshixs is
        signal chushi:std_logic_vector(14 downto 0):="000000000000000";       
        signal gaowei:std_logic_vector(1 downto 0);           
        signal diwei:std_logic_vector(2 downto 0);   
begin
process(clk3,diwei,chushi,gaowei,reset3)
    begin
        if(reset3='1')then
chushi<="000000000000000";
elsif(reset3='0')then
if(clk3'event and clk3='1')then
chushi<=chushi+1;
end if;   
end if;

    gaowei(1 downto 0)<=chushi(14 downto 13);       
diwei(2 downto 0)<=chushi(2 downto 0);       
case diwei is                           --xianshihang
                    when"000"=>lie3<="01111111";
                    when"001"=>lie3<="10111111";
                    when"010"=>lie3<="11011111";
                    when"011"=>lie3<="11101111";
                    when"100"=>lie3<="11110111";
                    when"101"=>lie3<="11111011";
                    when"110"=>lie3<="11111101";
                    when"111"=>lie3<="11111110";
                end case;   
            if gaowei="00"then                             --waiquanhongxin
                hangnew3<="00000000";
                case diwei is                           
                    when"000"=>hang3<="01100110";
                    when"001"=>hang3<="10011001";
                    when"010"=>hang3<="10000001";
                    when"011"=>hang3<="10000001";
                    when"100"=>hang3<="10000001";
                    when"101"=>hang3<="01000010";
                    when"110"=>hang3<="00100100";
                    when"111"=>hang3<="00011000";
                end case;
            elsif gaowei="01"then                       --xianshi0
                case diwei is                              
                    when"000"=>hang3<="00000000";hangnew3<="00000000";
                    when"001"=>hang3<="00100100";hangnew3<="00100100";
                    when"010"=>hang3<="01011010";hangnew3<="01011010";
                    when"011"=>hang3<="01000010";hangnew3<="01000010";
                    when"100"=>hang3<="01000010";hangnew3<="01000010";
                    when"101"=>hang3<="00100100";hangnew3<="00100100";
                    when"110"=>hang3<="00011000";hangnew3<="00011000";
                    when"111"=>hang3<="00000000";hangnew3<="00000000";
                end case;
            elsif gaowei="10"then                          --xianshi1
               
                case diwei is               
                    when"000"=>hangnew3<="00000000";hang3<="00000000";
                    when"001"=>hangnew3<="00000000";hang3<="00000000";
                    when"010"=>hangnew3<="00100100";hang3<="00000000";
                    when"011"=>hangnew3<="00111100";hang3<="00000000";
                    when"100"=>hangnew3<="00111100";hang3<="00000000";
                    when"101"=>hangnew3<="00011000";hang3<="00000000";
                    when"110"=>hangnew3<="00000000";hang3<="00000000";
                    when"111"=>hangnew3<="00000000";hang3<="00000000";
                end case;
            elsif gaowei="11"then                          --xian shi1
                case diwei is            
                    when"000"=>hang3<="01100110";hangnew3<="00000000";
                    when"001"=>hang3<="10111101";hangnew3<="00100100";
                    when"010"=>hang3<="11011011";hangnew3<="01111110";
                    when"011"=>hang3<="11000011";hangnew3<="01111110";
                    when"100"=>hang3<="11000011";hangnew3<="01111110";
                    when"101"=>hang3<="01100110";hangnew3<="00111100";
                    when"110"=>hang3<="00111100";hangnew3<="00011000";
                    when"111"=>hang3<="00011000";hangnew3<="00000000";
                end case;
            end if;
end process;
end ;第4部分实验结果
4.1 实验操作过程
下载完成后自动播放音乐,sw0置于0,顺序播放,使用btn7重听本首音乐,btn6下一首,btn5上一首,sw0置于1,则进入随机播放功能。Sw1置于1,自动播放歌曲1,sw2置于1,播放歌曲2,sw3置于1,播放歌曲3.sw4置于1,进入自动弹奏模式,btn0~btn4控制自动发音1,2,3,4,5. Sw7控制停止和继续,并且同时控制点阵图形的出现和消失。
4.2 实验结果截图
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps10.png
播放时点阵显示跳动的心脏,数码管显示播放曲目
4.3 仿真原理图(未仿真点阵)
播放模式
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps11.jpg
由仿真图可以看出来
在顺序播放模式下按下next切换到下一首, 按下lastone切换到上一首,按下previous播放本首
在随机模式下,按下3个键都会随机播放一首歌曲
弹奏模式
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps12.jpg
按下1,2,3,4,5 这几个不同的音符,数码管显示不同的数字
按下停止,音乐播放器停止播放

4.4 资源利用率
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps13.jpg
4.5实验总结
4.5.1实验遇到的故障及问题
本次实验遇到的问题还是很多的,主要原因是把EDA, VHDL看得太过简单了,但其实本质上对它还是不太熟悉的。
软件上遇到的问题主要涉及编程方面。比如开始的时候对自顶向下的模式不是很理解,后来才明白这是便于分块处理,在使用portmap时经常发生变量对应错误的情况,我发现,这是因为我把名字都取得太容易混淆了,导致参量一多,连自己都分不清楚了。
硬件上遇到的问题有,对于老式实验板,许多蜂鸣器的开关都没有了,导致蜂鸣器不能使用。于是从不用蜂鸣器的同学那要了个黑色小开关来。后来发现点阵也不能用,用别的板子试验发现程序没有问题,所以直接换了块实验板,问题解决。

4.5.2实验感想总结

这四周进行了VHDL状态机和自顶向下设计方法的学习,通过本次实验更加了解了EDA,更加熟悉了VHDL的基本编程方法,特别是在实验过程中,锻炼了自己的动手能力,独立思考能力,从而增强了自主学习能力。
正如实验遇到的问题中所描述的那样,我在实验过程中其实是不断摸索的。记得最清楚的就是当音乐怎么也不响时郁闷的心情,我们在一再确认程序无误的情况下只能说是素手无策,实验一度度陷入僵局。在各处搜索结果无望的情况下,我们和身边同学进行了讨论,最后找到了问题原来是板子上有个小开关不见了。这让我明白自身能力的有限,能及时求助他人是十分有效的做法。
我的作品仍有瑕疵,由于时间等多方面原因没有进行进一步修改,比如停止时会一直叫高音而不是停下来不唱了。而且有许多想要增加实现的功能最后都没有实现,但是在这样不断的思考,不断的实践的过程中,我觉得获得的远多于一个小小的音乐播放器,希望自己能学会反思,以后能更有条理,这样才能更加高效的学习的更多。

第5部分附录
5.1.材料清单
EMP1270-144c5实验板一块
file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml7864\wps14.png
5.2.参考书目
《EDA技术与实践》.机械工业出版社, 2004年7月李国洪.沈明山.
《EDA技术及可编程器件应用实例》.科学出版社,2004年10月沈明山
《VHDL实例教程》
《数字逻辑设计实验与EDA技术》
《EDA应用实例》
感谢百度百科提供的解答

litiantao 发表于 2019-3-14 15:01:42

小顺430 发表于 2019-3-14 15:13:11

qiangzicong123 发表于 2019-3-14 17:39:23

点赞点赞
页: [1]
查看完整版本: FPGA音乐播放器