logo资料库

Verilog的乐曲演奏电路设计.doc

第1页 / 共28页
第2页 / 共28页
第3页 / 共28页
第4页 / 共28页
第5页 / 共28页
第6页 / 共28页
第7页 / 共28页
第8页 / 共28页
资料共28页,剩余部分请下载后查看
《基于 Verilog HDL 的乐曲演奏电路设计》 一.设计目的与要求 1.课程设计目的: 1)加深对 EDA 技术的理解,掌握乐曲演奏电路的工作原理 2)了解怎样控制音调的高低变化和音长,从而完成乐曲的自动循环演奏。 3)培养自主学习、正确分析和解决问题的能力 2.课程设计要求: 1)使用 Verilog HDL 设计乐曲演奏电路,系统实现是用硬件描述语言 Verilog HDL 按分频控制的方 式进行设计,然后进行编程、时序仿真、电路功能验证,奏出美妙的乐曲。 2) 通过控制输出到扬声器的激励信号频率的高低和持续的时间,从而使扬声器发出连续的乐曲声, 且当乐曲演奏完成时,保证能自动从头开始演奏。 3.该方案可以实现的功能: 1)通过蜂鸣器播放音乐; 2)通过三位动态数码管输出相应的高中低音符; 3)通过一个开关实现两首乐曲的切换; 4)在音乐播放的同时,会有 led 流水灯的闪烁. 二、应用工具介绍 作为当今最流行的计算机软件系统,EDA 技术是以计算机为工作平台,融合了应用电子 技术、计算机技术、信息处理及智能化技术的最新成果,进行电子产品的自动设计。EDA 可 提供文本输入以及图形编辑的方法将设计者的意图用程序或者图形方式表达出来,而我们经 常用到的 VHDL 语言便是用于编写源程序所需的最常见的硬件描述语言(HDL)之一。 2.1 EDA 技术介绍 EDA 是电子设计自动化(Electronic Design Automation)的缩写,在 20 世纪 90 年代初从 计算机辅助设计(CAD)、计算机辅助制造(CAM)、计算机辅助测试(CAT)和计算机辅助工程(CAE) 的概念发展而来。EDA 技术是在电子 CAD 技术基础上发展起来的计算机软件系统,是指以计 算机为工作平台,融合了应用电子技术、计算机技术、信息处理及智能化技术的最新成果, 进行电子产品的自动设计[1]。 EDA 技术就是以计算机为工具,设计者在 EDA 软件平台上,用硬件描述语言 HDL 完成设
计文件,然后由计算机自动地完成逻辑编译、化简、分割、综合、优化、布局、布线和仿真, 直至对于特定目标芯片的适配编译、逻辑映射和编程下载等工作。典型的 EDA 工具中必须包 含两个特殊的软件包,即综合器和适配器。综合器的功能就是将设计者在 EDA 平台上完成的 针对某个系统项目的 HDL、原理图或状态图形描述,针对给定的硬件系统组件,进行编译、 优化、转换和综合,最终获得我们欲实现功能的描述文件。综合器在工作前,必须给定所要 实现的硬件结构参数,它的功能就是将软件描述与给定的硬件结构用一定的方式联系起来。 也就是说,综合器是软件描述与硬件实现的一座桥梁。综合过程就是将电路的高级语言描述 转换低级的、可与目标器件 FPGA/CPLD 相映射的网表文件。 在今天,EDA 技术已经成为电子设计的普遍工具,无论设计芯片还是设计系统,没有 EDA 工具的支持,都是难以完成的。EDA 工具已经成为设计师必不可少的武器,起着越来越重要 的作用。从目前的 EDA 技术来看,其发展趋势是政府重视、使用普及、应用广泛、工具多样、 软件功能强大。EDA 技术发展迅猛,完全可以用日新月异来描述。EDA 技术的应用广泛,现 在已涉及到各行各业。EDA 水平不断提高,设计工具趋于完美的地步。 2.2 Verilog HDL 语言介绍 Verilog HDL 是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次 的数字系统建模。被建模的数字系统对象的复杂性可以介于简单的门和完整的电子数字系统 之间。数字系统能够按层次描述,并可在相同描述中显式地进行时序建模[2]。 作为一种通用化的硬件描述语言,Verilog HDL 语言具有下述描述能力:设计的行为特性、 设计的数据流特性、设计的结构组成以及包含响应监控和设计验证方面的时延和波形产生机 制。所有这些都使用同一种建模语言。此外,Verilog HDL 语言提供了编程语言接口,通过 该接口可以在模拟、验证期间从设计外部访问设计,包括模拟的具体控制和运行[3]。 Verilog HDL 语言不仅定义了语法,而且对每个语法结构都定义了清晰的模拟、仿真语 义。因此,用这种语言编写的模型能够使用 Verilog 仿真器进行验证。语言从 C 编程语言中 继承了多种操作符和结构。Verilog HDL 提供了扩展的建模能力,其中许多扩展最初很难理 解。但是,Verilog HDL 语言的核心子集非常易于学习和使用,这对大多数建模应用来说已 经足够。当然,完整的硬件描述语句足以对从最复杂的芯片到完整的电子系统进行描述。 Verilog HDL 语言已经成为一种标准的硬件描述语言。它具有以下特点: (1)作为一种多用途的硬件描述语言,它具有很好的易学性和易用性。 (2)Verilog HDL 语言允许在同一个模块中进行不同抽象层次的描述。 2
(3)大多数逻辑综合工具都支持 Verilog HDL,使得它成为设计人员的一个很好的选择。 (4)所有的制造厂商都提供了 Verilog HDL 的工艺库,用以支持仿真。 (5)Verilog HDL 的程序语言接口拥有强大的功能,允许用户用 C 语言对内部数据结构进行 描述[3]。 正是以上优点,使得 Verilog HDL 语言广泛流行。 下面是 verilog 的设计流程 Verilog 的设计流程图 三.基本原理 乐曲演奏的原理是这样的:组成乐曲的每个音符的频率值(音调)及其持续的时间(音 长)是乐曲能连续演奏所需的两个基本数据,因此只要控制输出到扬声器的激励信号频率的 高低和持续的时间,就可以使扬声器发出连续的乐曲声[4]。 1、音调的控制 频率的高低决定了音调的高低。音乐的十二平均率规定:每两个 8 度音(如简谱中的中 音 1 与高音 1)之间的频率相差一倍。在两个 8 度音之间,又可分为 12 个半音,每两个半音 的频率比为 12√2。 另外,音名 A(简谱中的低音 6)的频率为 440Hz,音名 B 到 C 之间、E 到 F 之间为半音,其余为全音[4]。由此可以计算出简谱中从低音 1 至高音 1 之间每个音名对应 3
的频率,如表 3.11 所示: 表 3.11 简谱中的音名与频率的关系 音名 低音 1 低音 2 低音 3 低音 4 低音 5 低音 6 低音 7 频率/Hz 261.6 293.7 329.6 349.2 392 440 493.9 音名 中音 1 中音 2 中音 3 中音 4 中音 5 中音 6 中音 7 频率/Hz 523.3 587.3 659.3 698.5 784 880 987.8 音名 高音 1 高音 2 高音 3 高音 4 高音 5 高音 6 高音 7 频率/Hz 1046.5 1174.7 1318.5 1396.9 1568 1760 1975.5 所有不同频率的信号都是从同一个基准频率分频得到的。由于音阶频率多为非整数,而 分频系数又不能为小数,故必须将计算得到的分频数四舍五入取整。若基准频率过低,则由 于分频比太小,四舍五入取整后的误差较大;若基准频率过高,虽然误差变小,但分频数将 变大。实际的设计综合考虑这两方面的因素,在尽量减小频率误差的前提下取合适的基准频 率[4]。本例中选取 6MHz 为基准频率。若无 6MHz 的基准频率,则可以先分频得到 6MHz, 或换一个新的基准频率。实际上,只要各个音名间的相对频率关系不变,演奏出的乐曲听起 来都不会"走调"。 本例需要演奏的是梁祝乐曲,该乐曲各音阶频率及相应的分频比如表 2 所示。为了减小 输出的偶次谐波分量,最后输出到扬声器的波形应为对称方波,因此在到达扬声器之前,有 一个二分频的分频器。表 2 中的分频比就是从 6MHz 频率二分频得到的 3MHz 频率基础上计 算得出的。由于最大的分频系数为 9102,故采用 14 位二进制计数器分频可满足需要。在表 2 中,除给出了分频比以外,还给出了对应于各个音阶频率时计数器不同的预置数。对于不 同的分频系数,只要加载不同的预置数即可。采用加载预置数实现分频的方法比采用反馈复 零法节省资源,实现起来也容易一些,如表 3.12 所示: 表 3.12 各音阶频率对应的分频比及预置数 音名 低音 3 低音 5 分频比 预置数 9102 7653 7281 8730 音名 中音 2 中音 3 分频比 预置数 5111 4552 11272 11831 4
低音 6 低音 7 中音 1 此外,对于乐曲中的休止符,只要将分频系数设为 0,即初始值为 2141=16383 即可, 中音 5 中音 6 高音 1 12556 12974 13516 6818 6073 5736 9565 10310 10647 3827 3409 2867 此时扬声器将不会发声。 2、音长的控制 音符的持续时间必须根据乐曲的速度及每个音符的节拍数来确定。本例演奏的梁祝片 段,最短的音符为 4 分音符,如果将全音符的持续时间设为 1s 的话,则只需要再提供一个 4Hz 的时钟频率即可产生 4 分音符的时长[4]。 如图 3.2 所示是乐曲演奏电路的原理框图,其中,乐谱产生电路用来控制音乐的音调和 音长。控制音调通过设置计数器的预置数来实现,预置不同的数值可以使计数器产生不同频 率的信号,从而产生不同的音调。控制音长是通过控制计数器预置数的停留时间来实现的, 预置数停留的时间越长,则该音符演奏的时间越长。每个音符的演奏时间都是 0.25s 的整数 倍,对于节拍较长的音符,如 2 分音符,在记谱时将该音名连续记录两次即可。 乐曲演奏电路的系统框图 音名显示电路用来显示乐曲演奏时对应的音符。可以用 3 个数码管,分别显示高、中、 低音的音名,实现演奏的动态显示,十分直观。在本例中,high[3:0]、med[3:0]、low[3:0]等 信号分别用于显示高音、中音、低音音符。为了使演奏能循环进行,需另外设置一个时长计 数器,当乐曲演奏完成时,保证能自动从头开始演奏。 5
四. 方案实现 由系统框图可以看到本方案分成 8 个模块。 1)48MHz 分频成 12MHz 波形分频器,源代码和顶层模块如下 //48mhz 分成 12mhz 的分频模块 module div_clk12mhz(clk_48mhz,clk_12mhz); input clk_48mhz; output clk_12mhz; reg clk_12mhz; reg [21:0] cnt; always @(posedge clk_48mhz) if(cnt<1) cnt=cnt+1; // (48mhz/12mhz=4,cnt<[4/2-1=1]) else begin endmodule clk_12mhz =!clk_12mhz; cnt=0; end 2)12MHz 分频成 6MHz 波形分频器,源代码和顶层模块如下: //12mhz 分成 6mhz 的分频模块,提供给 song 模块 module div_clk6mhz(clk_12mhz,clk_6mhz); input clk_12mhz; output clk_6mhz; reg clk_6mhz; reg cnt; always @(posedge clk_12mhz) clk_6mhz=!clk_6mhz; endmodule 3)12MHz 分频成 4Hz 波形分频器,源代码和顶层模块如下: //12mhz 分成 4hz 的分频模块,提供给 song 模块 module div_clk4hz(clk_12mhz,clk_4hz); input clk_12mhz; output clk_4hz; reg clk_4hz; reg [21:0] cnt; 6
always @(posedge clk_12mhz) if(cnt<1499999) cnt=cnt+1; // (12mhz/4hz=3000000,cnt<[3000000/2-1=1499999]) else begin endmodule clk_4hz =! clk_4hz; cnt=0; end 4)12MHz 分频成 1mhz 波形分频器,源代码和顶层模块如下: //12mhz 分成 1mhz 的分频模块,提供给 quma 模块 module div_clk1mhz(clk_12mhz,clk_1mhz); input clk_12mhz; output clk_1mhz; reg clk_1mhz; reg [21:0] cnt; always @(posedge clk_12mhz) if(cnt<5) cnt=cnt+1; // (12mhz/1mhz=12,cnt<[12/2-1=5]) begin else endmodule clk_1mhz =! clk_1mhz; cnt=0; end 5)12MHz 分频成 1khz 波形分频器,源代码和顶层模块如下: //12mhz 分成 1khz 的分频模块,提供给 quma 模块 module div_clk1khz(clk_12mhz,clk_1khz); input clk_12mhz; output clk_1khz; reg clk_1khz; reg [21:0] cnt; always @(posedge clk_12mhz) if(cnt<5999) cnt=cnt+1; // (12mhz/1khz=12000,cnt<[12000/2-1=5999]) else begin endmodule clk_1khz =! clk_1khz; cnt=0; end 7
//定义两个输入端口 6) song 模块源代码和顶层模块如下: //音乐产生模块 module song(clk_6mhz,clk_4hz,speaker,high,med,low,k); input clk_6mhz,clk_4hz; input k; output speaker; output[3:0] high,med,low; reg[3:0] high,med,low; reg[13:0] divider,origin; reg[9:0] counter; reg speaker; wire carry; assign carry=(divider==16383); always @(posedge clk_6mhz) if(carry) divider<=origin; else divider<=divider+1; begin end always @(posedge carry) begin speaker<=~speaker;end always @(posedge clk_4hz) begin case({high,med,low}) 'b000000000011:origin<=7281; 'b000000000101:origin<=8730; 'b000000000110:origin<=9565; 'b000000000111:origin<=10310; 'b000000010000:origin<=10647; 'b000000100000:origin<=11272; 'b000000110000:origin<=11831; 'b000001010000:origin<=12556; 'b000001100000:origin<=12974; 'b000001110000:origin<=13347; 'b000100000000:origin<=13516; 'b000000000000:origin<=16383; endcase end always @(posedge clk_4hz) //模块名为 song(端口列表) //定义一个输出端口 //定义了 3 个 4 位寄存器 //定义了 2 个 14 位寄存器 //定义了 1 个 10 位寄存器 //连续赋值语句 //二分频产生方波信号 //分频比预置 //低音 3 //低音 5 //低音 6 //低音 7 //中音 1 //中音 2 //中音 3 //中音 5 //中音 6 //中音 7 //高音 1 //休止符 8
分享到:
收藏