资源描述
沈阳工程学院课程设计(论文)
目 录
摘 要 I
Abstract II
第1章 引 言 1
1.1 EDA技术及发展历史 1
第2章 VHDL语言及其应用 2
2.1 VHDL的应用 2
第3章 乐曲硬件演奏电路 4
3.1 基本要求 4
3.2 原理描述 4
3.3 乐曲硬件演奏电路的层次化设计方案 5
3.3.1 音乐节拍发生器 notetabs 5
3.3.2 音符译码电路 tonetaba模块 11
3.3.3 数控分频模块(speakera)设计 13
3.4 乐曲硬件演奏电路的顶层设计和仿真 16
结 论 19
参考文献 20
致 谢 21
附录 22
千万不要删除行尾的分节符,此行不会被打印。在目录上点右键“更新域”,然后“更新整个目录”。打印前,不要忘记把上面“Abstract”这一行后加一空行
20
沈阳工程学院课程设计(论文)
第1章 引 言
1.1 EDA技术及发展历史
随着计算机业的发展,从80年代中期计算机应用进入各个领域。在这种背景下,87、88年由美国ACCEL Technologies Inc推出了第一个应用于电子线路设计软件包——TANGO,这个软件包开创了电子设计自动化(EDA)的先河。这个软件包现在看来比较简陋,但在当时给电子线路设计带来了设计方法和方式的革命,人们纷纷开始用计计算机来设计电子线路,直到今天在国内许多科研单位还在使用这个软件包。
随着电子业的飞速发展,TANGO日益显示出其不适应时代发展需要的弱点。为了适应科学技术的发展,Protel Technology公司以其强大的研发能力推出了Protel For Dos作为TANGO的升级版本,从此Protel这个名字在业内日益响亮。
中国科学院EDA中心是中国科学院根据其“面向国家战略需求、面向世界科技前沿”的新时期办院方针,面对中国IC设计产业发展对技术和人才的迫切需求,于2001年11月经中国科学院批准设立的非法人事业机构。是中国科学院全院集成电路设计领域科研与教育的网络化公共平台,是中国科学院该领域对外战略合作的代表机构,面向全国开展技术服务。
第2章 VHDL语言及其应用
20世纪80年代美国国防部开发Very High Speed Integrated Circuit—VHSIC,用于描述集成电路的结构和功能。此后,硬件描述语言向标准化方向发展,1987年成为IEEE Standard 1076,称为VHDL语言。它也是美国国防部标准(MIL-STD-454L)。1993年该标准增修为IEEE1164标准。1996年,再次加入电路合成的标准程序和规格,成为IEEE1076.3标准。VHDL的英文全名是Very-High-Speed Integrated Circuit HardwareDescription Language,诞生于1982年。1987年底,VHDL被IEEE和美国国防部确认为标准硬件描述语言 。自IEEE公布了VHDL的标准版本,IEEE-1076(简称87版)之后,各EDA公司相继推出了自己的VHDL设计环境,或宣布自己的设计工具可以和VHDL接口。此后VHDL在电子设计领域得到了广泛的接受,并逐步取代了原有的非标准的硬件描述语言。1993年,IEEE对VHDL进行了修订,从更高的抽象层次和系统描述能力上扩展VHDL的内容,公布了新版本的VHDL,即IEEE标准的1076-1993版本,(简称93版)。现在,VHDL和Verilog作为IEEE的工业标准硬件描述语言,又得到众多EDA公司的支持,在电子工程领域,已成为事实上的通用硬件描述语言。有专家认为,在新的世纪中,VHDL于Verilog语言将承担起大部分的数字系统设计任务。
从宏观的角度看,VHDL的语法构成了程序的各组成部分;微观上看VHDL的语法是各种语句的运用细节。本章在VHDL的特性之后,从这两个角度简要介绍VHDL的语法基础。
硬件描述语言HDL(Hardware Description Language)诞生于1962年。HDL是用形式化的方法描述数字电路和设计数字逻辑系统的语言。主要用于描述离散电子系统的结构和行为。与SDL(Software Description Language)相似,经历了从机器码(晶体管和焊接)、汇编(网表)、到高级语言(HDL)的过程。
2.1 VHDL的应用
VHDL主要用于描述数字系统的结构,行为,功能和接口。除了含有许多具有硬件特征的语句外,VHDL的语言形式和描述风格与句法是十分类似于一般的计算机高级语言。VHDL的程序结构特点是将一项工程设计,或称设计实体(可以是一个元件,一个电路模块或一个系统)分成外部(或称可是部分,及端口)和内部(或称不可视部分),既涉及实体的内部功能和算法完成部分。在对一个设计实体定义了外部界面后,一旦其内部开发完成后,其他的设计就可以直接调用这个实体。这种将设计实体分成内外部分的概念是VHDL系统设计的基本点。
VHDL是一种标准的硬件电路设计语言,目前已成为广大电路设计人员设计数字系统首选的开发工具。基于VHDL硬件电路语言的编程与实际应用技巧,VHDL硬件电路语言在微机、通信、编码、存储器以及电子电路等方面的具体设计应用,具有实际的指导意义。
关于用VHDL和原理图输入进行CPLD/FPGA设计的粗略比较:在设计中,如果采用原理图输入的设计方式是比较直观的。你要设计的是什么,你就直接从库中调出来用就行了。这样比较符合人们的习惯。但是这样做需要设计人员要在两方面有较高的素质:
但是当你采用VHDL等高级语言来设计时这些问题都会得到较好的解决。由于在使用VHDL等高级语言时,有专用的工具来实现将语言描述的电路功能转换为实际的电路所以你就用不着对底层的电路很熟悉,也用不着对CPLD/FPGA的结构很熟悉(因为有专用的工具针对你的描述采用相应的器件哦)。当你要换器件时,你只需要将原来设计好的VDHL文件在新器件的设计工具中再次实现就行了。
第3章 乐曲硬件演奏电路
3.1 基本要求
利用FPGA,设计一个乐曲硬件演奏电路。乐曲的12平均率规定:每2个八度(如简谱中的中音1与高音1)之间的频率相差1倍。在2个八度音之间,又可分为12个半音,每2个半音的频率比为12√2。另外,音符A的频率为440HZ,音符B到C之间,E到F之间为半音,其余为全音。由此可以计算出简谱中从低音l至高音1之间每个音符的频率。设计音符查找表电路模块,时钟模块,数控分频器模块,音乐节拍产生模块电路。
3.2 原理描述
产生音乐的两个因素是音乐频率和音乐的持续时间,以纯硬件完成演奏电路比利用微处理器来实现乐曲演奏要复杂的多,如果不凭借EDA工具和硬件描述语言,凭借传统的数字逻辑技术,即使最简单的演奏电路也难以实现。乐曲硬件演奏电路系统主要有数控分频器和乐曲存储模块组成。数控分频器对FPGA的基准频率进行分频,得到与各个音阶对应的频率输出。乐曲存储模块产生节拍控制和音阶选择信号,即在此模块中可存放一个乐曲曲谱真值表,由一个计数器来控制此真值表的输出,而由计数器的计数时钟信号作为乐曲节拍控制信号。乐曲演奏电路的结构框图如下:
时钟电路
查符查表电路
音乐节拍
产生电路
数控分频器
基准时钟
模式选择
图3.1 乐曲演奏电路结构框图
3.3 乐曲硬件演奏电路的层次化设计方案
乐曲硬件演奏电路的设计主要就是由三个部分组成的,首先为了实现音乐的演奏必须得得到音阶的频率和节拍,这主要就是由音乐节拍发生器和数控分频模块完成的,完了就是译码查表电路是由音符译码电路模块产生的,乐曲硬件演奏电路可分为三个模块,音乐节拍发生器模块,音符译码电路模块,数控分频模块。
3.3.1 音乐节拍发生器 notetabs
该模块将利用FPGA的片内POM存放乐曲简谱真值表,该计数器的计数频率为4HZ,即每一个数值的停留时间为0.25S,也就是每个节拍是0.25S,每个节拍的频率也是4HZ,随着NoteTabs中计数器按4HZ的时钟频率做加法计数时,乐符数据叫输向音符译码电路ToneTaba,所以所存的乐曲就自然的演奏起来。
其VHDL源程序如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY NoteTabs IS
PORT ( clk : IN STD_LOGIC;
ToneIndex : OUT INTEGER RANGE 0 TO 15 );
END;
ARCHITECTURE one OF NoteTabs IS
SIGNAL Counter : INTEGER RANGE 0 TO 138;
BEGIN
CNT8 : PROCESS(clk)
BEGIN
IF Counter = 138 THEN Counter <= 0;
ELSIF (clk'EVENT AND clk = '1') THEN
Counter <= Counter + 1;
END IF;
END PROCESS;
Search : PROCESS(Counter)
BEGIN
CASE Counter IS -- 译码器,查歌曲的乐谱表,查表结果为音调表的索引值
WHEN 00 => ToneIndex <= 3; -- 简谱"3"音
WHEN 01 => ToneIndex <= 3; -- 发4个时钟节拍
WHEN 02 => ToneIndex <= 3;
WHEN 03 => ToneIndex <= 3;
WHEN 04 => ToneIndex <= 5; -- 简谱"5"音
WHEN 05 => ToneIndex <= 5; -- 发3个时钟节拍
WHEN 06 => ToneIndex <= 5;
WHEN 07 => ToneIndex <= 6; -- 简谱"6"音
WHEN 08 => ToneIndex <= 8;
WHEN 09 => ToneIndex <= 8;
WHEN 10 => ToneIndex <= 8;
WHEN 11 => ToneIndex <= 9;
WHEN 12 => ToneIndex <= 6;
WHEN 13 => ToneIndex <= 8;
WHEN 14 => ToneIndex <= 5;
WHEN 15 => ToneIndex <= 5;
WHEN 16 => ToneIndex <= 12;
WHEN 17 => ToneIndex <= 12;
WHEN 18 => ToneIndex <= 12;
WHEN 19 => ToneIndex <= 15;
WHEN 20 => ToneIndex <= 13;
WHEN 21 => ToneIndex <= 12;
WHEN 22 => ToneIndex <= 10;
WHEN 23 => ToneIndex <= 12;
WHEN 24 => ToneIndex <= 9;
WHEN 25 => ToneIndex <= 9;
WHEN 26 => ToneIndex <= 9;
WHEN 27 => ToneIndex <= 9;
WHEN 28 => ToneIndex <= 9;
WHEN 29 => ToneIndex <= 9;
WHEN 30 => ToneIndex <= 9;
WHEN 31 => ToneIndex <= 0;
WHEN 32 => ToneIndex <= 9;
WHEN 33 => ToneIndex <= 9;
WHEN 34 => ToneIndex <= 9;
WHEN 35 => ToneIndex <= 10;
WHEN 36 => ToneIndex <= 7;
WHEN 37 => ToneIndex <= 7;
WHEN 38 => ToneIndex <= 6;
WHEN 39 => ToneIndex <= 6;
WHEN 40 => ToneIndex <= 5;
WHEN 41 => ToneIndex <= 5;
WHEN 42 => ToneIndex <= 5;
WHEN 43 => ToneIndex <= 6;
WHEN 44 => ToneIndex <= 8;
WHEN 45 => ToneIndex <= 8;
WHEN 46 => ToneIndex <= 9;
WHEN 47 => ToneIndex <= 9;
WHEN 48 => ToneIndex <= 3;
WHEN 49 => ToneIndex <= 3;
WHEN 50 => ToneIndex <= 8;
WHEN 51 => ToneIndex <= 8;
WHEN 52 => ToneIndex <= 6;
WHEN 53 => ToneIndex <= 5;
WHEN 54 => ToneIndex <= 6;
WHEN 55 => ToneIndex <= 8;
WHEN 56 => ToneIndex <= 5;
WHEN 57 => ToneIndex <= 5;
WHEN 58 => ToneIndex <= 5;
WHEN 59 => ToneIndex <= 5;
WHEN 60 => ToneIndex <= 5;
WHEN 61 => ToneIndex <= 5;
WHEN 62 => ToneIndex <= 5;
WHEN 63 => ToneIndex <= 5;
WHEN 64 => ToneIndex <= 10;
WHEN 65 => ToneIndex <= 10;
WHEN 66 => ToneIndex <= 10;
WHEN 67 => ToneIndex <= 12;
WHEN 68 => ToneIndex <= 7;
WHEN 69 => ToneIndex <= 7;
WHEN 70 => ToneIndex <= 9;
WHEN 71 => ToneIndex <= 9;
WHEN 72 => ToneIndex <= 6;
WHEN 73 => ToneIndex <= 8;
WHEN 74 => ToneIndex <= 5;
WHEN 75 => ToneIndex <= 5;
WHEN 76 => ToneIndex <= 5;
WHEN 77=> ToneIndex <= 5;
WHEN 78 => ToneIndex <= 5;
WHEN 79 => ToneIndex <= 5;
WHEN 80 => ToneIndex <= 3;
WHEN 81 => ToneIndex <= 5;
WHEN 82 => ToneIndex <= 3;
WHEN 83 => ToneIndex <= 3;
WHEN 84 => ToneIndex <= 5;
WHEN 85=> ToneIndex <= 6;
WHEN 86 => ToneIndex <= 7;
WHEN 87 => ToneIndex <= 9;
WHEN 88 => ToneIndex <= 6;
WHEN 89 => ToneIndex <= 6;
WHEN 90 => ToneIndex <= 6;
WHEN 91 => ToneIndex <= 6;
WHEN 92 => ToneIndex <= 6;
WHEN 93 => ToneIndex <= 6;
WHEN 94 => ToneIndex <= 5;
WHEN 95 => ToneIndex <= 6;
WHEN 96 => ToneIndex <= 8;
WHEN 97 => ToneIndex <= 8;
WHEN 98 => ToneIndex <= 8;
WHEN 99 => ToneIndex <= 9;
WHEN 100 => ToneIndex <= 12;
WHEN 101 => ToneIndex <= 12;
WHEN 102 => ToneIndex <= 12;
WHEN 103 => ToneIndex <= 10;
WHEN 104 => ToneIndex <= 9;
WHEN 105 => ToneIndex <= 9;
WHEN 106 => ToneIndex <= 10;
WHEN 107 => ToneIndex <= 9;
WHEN 108 => ToneIndex <= 8;
WHEN 109 => ToneIndex <= 8;
WHEN 110 => ToneIndex <= 6;
WHEN 111 => ToneIndex <= 5;
WHEN 112 => ToneIndex <= 3;
WHEN 113 => ToneIndex <= 3;
WHEN 114 => ToneIndex <= 3;
WHEN 115 => ToneIndex <= 3;
WHEN 116 => ToneIndex <= 8;
WHEN 117 => ToneIndex <= 8;
WHEN 118 => ToneIndex <= 8;
WHEN 119 => ToneIndex <= 8;
WHEN 120 => ToneIndex <= 6;
WHEN 121 => ToneIndex <= 8;
WHEN 122 => ToneIndex <= 6;
WHEN 123 => ToneIndex <= 5;
WHEN 124 => ToneIndex <= 3;
WHEN 125 => ToneIndex <= 5;
WHEN 126 => ToneIndex <= 6;
WHEN 127 => ToneIndex <= 8;
WHEN 128 => ToneIndex <= 5;
WHEN 129 => ToneIndex <= 5;
WHEN 130 => ToneIndex <= 5;
WHEN 131 => ToneIndex <= 5;
WHEN 132 => ToneIndex <= 5;
WHEN 133 => ToneIndex <= 5;
WHEN 134 => ToneIndex <= 5;
WHEN 135 => ToneIndex <= 5;
-- 程序过长,部分省
WHEN 136 => ToneIndex <= 0; -- 简谱休止符à输出
WHEN 137 => ToneIndex <= 0; -- 频率为零
WHEN 138 => ToneIndex <= 0;
WHEN OTHERS => NULL;
END CASE;
END PROCESS;
END;
随着频率记数器预置数记数法开始记数,得到了音节的输出频率和节拍,每0.25S为一个周期,频率为4HZ,音阶随着基准频率分频得到的频率从低音依次到高音。
仿真波形如下:
图3.2音乐节拍发生器防真波形
原器件符号:
图3.3 音乐发生器元件符号
3.3.2 音符译码电路 tonetaba模块
音符译码电路即音调发生器实际上是一个翻译电路,根据输入为数控分频模块提供所发音符频率的初始值,而此数控分频模块入口的停留时间即为此音符的节拍数,以VHDL程序中仅设置了“梁祝”乐曲全部音符所对应的音符频率的初始值。
//CLK_4HZ: 用于控制音长(节拍)的时钟频率;
//CLK_6MHZ: 用于产生各种音阶频率的基准频率;
//SPEAKER: 用于激励扬声器的输出信号,本例中为方波信号;
//HIGH, MED, LOW:分别用于显示高音、中音和低音音符,各驱动一个数码管来显示。
其VHDL源程序如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY ToneTaba IS
PORT ( Index : IN INTEGER RANGE 0 TO 15;
CODE : OUT INTEGER RANGE 0 TO 15;
HIGH : OUT STD_LOGIC;
Tone : OUT INTEGER RANGE 0 TO 16#7FF# );
END;
ARCHITECTURE one OF ToneTaba IS
BEGIN
Search : PROCESS(Index)
BEGIN
CASE Index IS -- 译码电路,查表方式,控制音调的预置数
WHEN 0 => Tone <= 2047; CODE <= 0; HIGH <= '0';
WHEN 1 => Tone <= 773; CODE <= 1; HIGH <= '0';
WHEN 2 => Tone <= 912; CODE <= 2; HIGH <= '0';
WHEN 3 => Tone <= 1036; CODE <= 3; HIGH <= '0';
WHEN 5 => Tone <= 1197; CODE <= 5; HIGH <= '0';
WHEN 6 => Tone <= 1290; CODE <= 6; HIGH <= '0';
WHEN 7 => Tone <= 1372; CODE <= 7; HIGH <= '0';
WHEN 8 => Tone <= 1410; CODE <= 1; HIGH <= '1';
WHEN 9 => Tone <= 1480; CODE <= 2; HIGH <= '1';
WHEN 10 => Tone <= 1542; CODE <= 3; HIGH <= '1';
WHEN 12 => Tone <= 1622; CODE <= 5; HIGH <= '1';
WHEN 13 => Tone <= 1668; CODE <= 6; HIGH <= '1';
WHEN 15 => Tone <= 1728; CODE <= 1; HIGH <= '1';
WHEN OTHERS => NULL;
END CASE;
END PROCESS;
END;
在源程序中Index是音乐节拍发生器输出的音符数据;TONE是为数控分频模块提供的音符频率的初始值,为方便测试,特设置了一个音名代码显示输出CODE和音高指示信号HUGH可以通过数码管或LED来显示乐曲演奏时对应的音符和高音名。CODE输出对应该音阶简谱的显示数码1,HIGH输出为高电平,指示音阶为高,HIGH输出为低电平时,则指示音阶为中音。低音时,Tone值小,分频比大,进位信号SPKS的周期长。
图3.4 音符译码电路仿真波形
图3.5 音乐译码器元件符号
3.3.3 数控分频模块(speakera)设计
数控分频模块设计采用了预置数记数法分频,从而得到各个音阶所产生的频率输出。所谓预置数记数就是先预置个数,然后用休止符数减去预置数就是分频数,然后用基准频率除以分频数就是该音阶的频率。
数控分频器对FPGA的基准频率进行分频,得到与各个音阶对应的频率输出。数控分频模块是11位的加法计数器构成。当计数器计满是,产生一个进位信号FULLSPKS,该信号就是用作发音的频率信号。在即使器的预置端给定不同的初始值,其输出将产生不同的频率信号,频率信号初值Tone就是前级音符译码电路的输出。低音时,Tone值小,分频比大,进位信号SPKS的周期长,扬声器发出的声音低,Tone随音乐的乐谱而变化,自动控制分频比,从而实现数控分频,发生信号的频率与Tone成正比,这就是利用数控分频器演奏音乐的原理。
通过分频后其进位信号FULLSPJKS是一周期脉冲信号,为有利于驱动扬声器,在音调输出时再进行2分频,将脉冲展宽,使之占空比为50%,扬声器这样就有足够的发声功率。
其VHDL源程序如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY Speakera IS
PORT ( clk : IN STD_LOGIC;
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 15;
BEGIN
PreCLK <= '0';
-- 将CLK进行16分频,PreCLK为CLK的16分频
IF Count4 > 11 THEN
PreCLK <= '1';
Count4 := 0;
ELSIF clk'EVENT AND clk = '1' THEN
Count4 := Count4 + 1;
END IF;
END PROCESS;
GenSpkS : PROCESS(PreCLK, Tone)
VARIABLE Count11 : INTEGER RANGE 0 TO 16#7FF#;
BEGIN
-- 11位可预置计数器
IF PreCLK'EVENT AND PreCLK = '1' THEN
IF Count11 = 16#7FF# THEN
Count11 := Tone;
FullSpkS <= '1';
ELSE
Count11 := Count11 + 1;
FullSpkS <= '0';
END IF;
END IF;
END PROCESS;
DelaySpkS : PROCESS(FullSpkS)
VARIABLE Count2 : STD_LOGIC;
BEGIN
-- 将输出再进行2分频,将脉冲展宽,以使扬声器有足够功率发音
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;
VHDL程序的第1个进程首先对FPGA的时基脉冲Tone输入的分频系数进行分频,得到所需要的音符频率;第2个进程的作用是在音调输出时再进行2分频,将脉冲展宽,使扬声器有足够发生功率。数控分频器仿真波形如下:
图3.6 数控分频器仿真波形
图3.7 分频器元件符号
3.4 乐曲硬件演奏电路的顶层设计和仿真
乐曲硬件演奏电路顶层电路分为3个模块,音乐节拍发生器NoteTabs 模块,音符译码电路Tonetabs模块,数控分频模块( speaker)。其顶层设计的VHDL程序如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY Songer IS -- 顶层设计
PORT ( CLK12MHZ : IN STD_LOGIC; --音调频率信号
CLK8HZ : IN STD_LOGIC; --节拍频率信号
CODE1 : OUT INTEGER RANGE 0 TO 15;
HIGH1 : OUT STD_LOGIC;
SPKOUT : OUT STD_LOGIC );
END;
ARCHITECTURE one OF Songer IS
COMPONENT NoteTabs
PORT ( clk : IN STD_LOGIC;
ToneIndex : OUT INTEGER RANGE 0 TO 15 );
END COMPONENT;
COMPONENT ToneTaba
PORT ( Index : IN INTEGER RANGE 0 TO 15;
CODE : OUT INTEGER RANGE 0 TO 15;
HIGH : OUT STD_LOGIC;
Tone : OUT INTEGER RANGE 0 TO 16#7FF# ); --11位2进制数
END COMPONENT;
COMPONENT Speakera
PORT ( clk : IN STD_LOGIC;
Tone : IN INTEGER RANGE 0 TO 16#7FF#; --11位2进制数
SpkS : OUT STD_LOG
展开阅读全文