VHdl乐曲演奏实验
乐器演奏电路设计-vhdl

重庆交通大学计算机与信息学院设计性实验报告班级:通信工程专业 07 级 2 班姓名(学号):实验项目名称:乐器演奏电路设计实验项目性质:设计性实验所属课程: VHDL 实验室(中心):指导教师:徐雯娟实验完成时间: 2009 年 12 月 13 日一、实验目的1,了解普通扬声器的工作原理;2,了解QuartusII4.1中提供了宏功能元件库mega_lpm。
3,使用LPM_ROM参数化存储模块。
二、实验内容及要求要求能够演奏出《友谊地久天长》的曲调或可另选一段较完整的曲调。
(扩展要求:能够从数码管上显示出当前曲调的简谱和频率)三、实验原理1,音符的频率:可以由上图中的U3获得,这是一个数控分频器。
由其clk 端输入一具有较高频率(这里是12MHz)的信号,通过U3分频后由SPKOUT输出,U3对clk 输入信号的分频比由11位预置数Tone[10..0]决定。
SPKOUT的输出频率将决定每一音符的音调,这样,分频计数器的预置值Tone[10..0]与SPKOUT 的输出频率,就有了对应关系。
2,音符的持续时间:须根据乐曲的速度及每个音符的节拍数来确定,图中模块U2的功能首先是为U3提供决定所发音符的分频预置数,而此数在U3输入口停留的时间即为此音符的节拍值。
模块U2是乐曲简谱码对应的分频预置数查表电路,其中设置了乐曲全部音符所对应的分频预置数(一共8个),每一音符的停留时间由音乐节拍和音调发生器模块U1的clk的输入频率决定(如为4Hz),这8个值的输出由对应于U2的3位输入值Index[2..0]确定。
3,乐谱的存储:在U1中设置了一个7位二进制计数器(计数最大值为65),作为音符数据ROM 的地址发生器。
这个计数器的计数频率若选为4Hz,即每一计数值的停留时间为0.25秒,恰为当全音符设为1秒时,四四拍的4分音符持续时间。
随着U1中的计数器按4Hz的时钟速率作加法计数时,即随地址值递增时,音符数据ROM 中的音符数据将从ROM中通过ToneIndex[2..0]端口输向U2模块,乐曲就开始连续自然地演奏起来了。
用VHDL实现乐曲播放与音乐键盘功能

用VHDL实现乐曲播放与音乐键盘功能附有VHDL程序摘要本设计目的是用VHDL实现乐曲播放与音乐键盘两用的系统。
该系统有两种工作模式:一个是作为音乐按键使用;一个是播放乐曲。
作为音乐键盘,首先系统要能播放每个音符的声音,我们知道声音的高低由声音的频率来决定,实现每个音符不同的发音频率值,主要是通过一个可预置数的分频器,将时钟信号进行分频,分频后得到不同的发音频率。
音乐播放是该系统的附加功能。
作为音乐键盘,系统已经实现每个音符不同的发音频率值,要使系统能够实现演奏音乐的功能还需要确定每个音符的发声持续时间,通过将时钟信号适当分频,即每个节拍的持续时间,还需要按顺序存储乐曲的每个音符,每个节拍向蜂鸣器输出一个音符的声音。
正文2.1. 系统设计设计要求:本设计目的是用VHDL实现乐曲播放与音乐键盘两用的系统。
该系统有两种工作模式:一个是作为音乐键盘使用;一个是播放乐曲。
设计方案:本设计由三个模块构成:(1)模块NOTETABS模块NOTETABS有两种工作模式。
其中设置了全部音符对应的分频预置数,当系统作为音乐键盘时当有键盘按下时,模块TONETABA向当Tone输出一个与键盘对应的分频预置数;当系统作为音乐播放使用时模块,该模块是置了一个8位二进制计数器,这个计数器的计数频率为4HZ,即每一个计数值的停留时间为0.25秒,恰为当全音符设为1秒时,四四拍的4分音符持续时间,每个音符的停留时间由音乐节拍和音调发生器模块NOTETABS的clk的出入频率决定。
这个分频预置数的输出由对应于TONETABA中的Index[3..0]确定。
输向TONETABA中Index[3..0]的值ToneIndex[3..0]的输出值与持续时间由模块NOTETABS决定。
(2)模块TONETABA模块TONETABA是乐曲简谱码对应的分频预置数查表电路,模块TONETABA接收模块NOTETABS发出的所要发生的音符的信息,然后查表,找出该音符所对应的分频预置数,并通过Tone端口向模块SREAKERA输出该预置数。
EDA课程设计---乐曲硬件演奏电路的VHDL设计

EDA课程设计题目:乐曲硬件演奏电路的VHDL设计一、 设计题目:乐曲硬件演奏电路的VHDL 设计二、 设计目标:1)能够播放“梁祝”乐曲。
2)能够通过LED 显示音阶。
3)具有“播放/停止”功能,并在此基础上实现“按键演奏”的电子琴功能。
三、 设计原理:1. 音乐基础知识一段简单乐谱由音调和节拍组成,音调表示一个音符唱多高的频率,节拍表示一个音符唱多长的时间。
音符的节拍我们可以举例来说明。
在一张乐谱中,我们经常会看到这样的表达式,如1=C 44、1=G 43……等等。
以43为例加以说明,它表示乐谱中以四分音符为节拍,每一小结有三拍。
比如:图1其中1 、2 为一拍,3、4、5为一拍,6为一拍共三拍。
1 、2的时长为四分音符的一半,即为八分音符长,3、4的时长为八分音符的一半,即为十六分音符长,5的时长为四分音符的一半,即为八分音符长,6的时长为四分音符长。
那么一拍到底该唱多长呢?一般说来,如果乐曲没有特殊说明,一拍的时长大约为400—500ms 。
我们以一拍的时长为400ms为例,则当以四分音符为节拍时,四分音符的时长就为400ms,八分音符的时长就为200ms,十六分音符的时长就为100ms。
2.原理图框图:图2.框图3.原理图说明音乐播放原理说明音符的频率由数控分频器模块Speakera产生。
ToneTaba模块从NoteTabs模块中输入的音符数据,将对应的分频预置数据传送给Speakera模块,并将音符数据送到LED模块显示音阶。
NoteTabs模块中包含有一个音符数据ROM,里面存有歌曲“梁祝”的全部音调,在此模块中设置了一个8位二进制计数器,作为音符数据ROM的地址发生器。
这个计数器的计数频率为4Hz,即每一个数值的停留时间为0.25秒。
例如:“梁祝”乐曲的第一个音符为“3”,此音在逻辑中停留了4个时钟节拍,即1秒钟时间,所对应的“3”音符分频预置数为1036,在Speakera的输入端停留了1秒。
乐曲硬件演奏电路设计

目录目录 0前言: (1)1.题目分析 (1)1.1 功能要求 (1)1.2 性能指标 (1)2.设计方案 (2)2.1顶层实体描述 (2)2.2模块划分 (3)2.3模块描述 (3)2.3.1 Speakera模块 (3)2.3.2 ToneTaba模块 (3)2.3.3 NoteTabs模块 (4)2.4顶层电路图 (5)3.方案实现 (5)3.1 NoteTabs模块仿真及描述 (5)3.2 ToneTaba模块仿真及描述 (5)3.3 Speakera模块仿真及描述 (6)3.4顶层电路仿真及描述 (6)4.硬件测试及说明 (6)5.结论 (7)6.课程总结 (7)7.附录 (8)前言:这次设计实验我做的是乐曲硬件演奏电路设计,通过在系统编程技术课程的学习,我已经学会了用VHDL语言来实现系统要求的电路设计。
VHDL语言具有良好的电路行为描述和系统描述的能力,用VHDL语言进行电子系统的设计非常方便和实用,而基于VHDL的自顶向下的设计方法是其很大的一个优点。
1.题目分析1.1 功能要求(1)播放歌曲(2)简谱码输出显示在数码管显示(3)通过LED灯显示音阶1.2 性能指标(1)乐曲硬件演奏电路的基本原理乐曲都是由一连串的音符组成,每一音符对应着一个确定的频率,按照乐曲的乐谱依次输出这些音符所对应的频率,就可以在扬声器上连续地发出各个音符的音调。
我们知道,组成乐曲的每个音符的发音频率值及其持续的时间是乐曲能连续演奏所需的两个基本要素,所以,掌握好一首歌曲的节奏,就能完整地演奏出来。
(2)音符频率和乐曲节奏多个不同频率的信号可通过对某个基准频率进行分频器获得,本设计中选取750KHz的基准频率,由于clk端输入的是较高频率12MHz信号,可以对其进行16分频。
计数时钟信号作为输出音符快慢的控制信号,时钟快时输出节拍速度就快,演奏的速度也就快,时钟慢时输出节拍的速度就慢,演奏的速度自然降低。
基于VHDL的乐曲演奏设计与实现

硬件述语 言 , 括系统 行为级 、 包 寄存 器传输 级 和逻
辑 门级多个设计层次。它具有 强大 的行 为描述 能力 ,
可 以用 简 洁 明确 的源代码 来 描述 复 杂 的逻 辑 控制 。 设计者可 以利 用 V D H L程序 , 用 “ 采 自顶 而下 ” 的方
图 1 设 计 流 程 图
事 检 测 与 自动 化 装 置研 究 。
音 阶产生 部分 由分 频器和选 择器组 成 。分频 器
产 生音 阶信 号 , 由于音 阶信 号频 率 只有 几百 赫 兹 至 上 千赫兹 , 而系 统 的主 频选 用 1 H , 么 分频 器 2M z那
21 0 1午第 2期
工 业 仪 表 与 自动化 装 置
4器件进行验证 , 果表 明该设 计能很好 地 实现 乐 曲的 自动演奏 、 结 暂停及 恢复功 能。
关 键 词 : 曲 演 奏 ; H L M x lsI 乐 V D ; aPu 1
中图分 类号 :P 0 T 32
文献标志码 : A
文章编号 :0 0— 6 2 2 1 )2— 0 2— 3 10 0 8 ( 0 1 0 0 3 0
择模块 控制音 阶发 生部 分 , 连续 地 演奏 出一段 乐 能 曲; 数器采 用可预置 计数器 , 计 主要实 现 的是连 续演 奏和暂 停功能 。
2 1 音阶模块 .
收 稿 日期 :0 0— 9—2 21 0 5
基 金项 目 : 省 级 自然科 学 重 点 项 目资 助 ( J0 8 1 1 安徽 K20 A 0 ) 作者 简 介 : 崔袜 ( 95) 女 , 南 个 旧 人 , 验 师 , 16 , 云 实 本科 , 要 从 主
t e s se .smu ain.a d d wno d d t EX1 h y tm i lto n o la e o FL OK e is EPF1 s re OLC8 — 4 d vc s t e f . e 0KI 4 e ie o v r y Th i r s t h w h tt i e in c n b o d f ra t mai sc p a e ul s o ta h sd sg a e g o o u o tc mu i ly,p u e a d r s m e fncin. s a s n e u u to
课程设计(论文)基于vhdl的简易乐曲演奏器的设计

1 引言VHDL是一种硬件描述语言,它可以对电子电路和系统的行为进行描述,基于这种描述,结合相关的软件工具,可以得到所期望的实际电路与系统。
使用VHDL语言描述的电路,可以进行综合和仿真。
然而,值得注意的是,尽管所有VHDL代码都是可仿真的,但并不是所有代码都能综合。
VHDL被广泛使用的基本原因在于它是一种标准语言,是与工具和工艺无关的,从而可以方便地进行移植和重用。
VHDL两个最直接的应用领域是可编程逻辑器件(PLD)和专用集成电路(ASIC),其中可编程逻辑器件包括复杂可编程逻辑器件(CPLD)和现场可编程门阵列(FPGA)。
关于VHDL最后要说明的是:与常规的顺序执行的计算机程序不同,VHDL 从根本上讲是并发执行的。
在VHDL中,只有在进程(PROCESS)、函数(FUNCTION)和过程(PROCEDURE)内部的语句才是顺序执行的。
本课程设计主要是基于VHDL文本输入法设计乐曲演奏电路,该系统基于计算机中时钟分频器的原理,采用自顶向下的设计方法来实现,通过按键输入来控制音响或者自动演奏已存入的歌曲。
系统实现是用硬件描述语言VHDL按模块化方式进行设计,然后进行编程、时序仿真、电路功能验证,奏出美妙的乐曲(当然由于条件限制,暂不进行功能验证,只进行编程和时序仿真)。
该设计最重要的一点就是通过按键控制不同的音调发生,每一个音调对应不同的频率,从而输出对应频率的声音。
我们知道,与利用单片机来实现乐曲演奏相比,以纯硬件完成乐曲演奏电路的逻辑要复杂得多,如果不借助于功能强大的EDA工具与硬件描述语言,仅凭传统的数字逻辑技术,即使最简单的演奏电路也难以实现。
2 整体功能介绍2.1准备知识在本次设计中采用了铃声《北京欢迎你》作为要播放的乐曲,它的旋律如下:3 5 3 2 3 2 3 3 2 6 1 3 2 22 1 6 1 23 5 2 3 6 5 6 2 1 12 1 6 1 23 5 2 3 6 5 5 3 -2 3 2 1 5 6 2 5 3 3 2 3 (加粗表示低音,其他为中音)根据声乐知识,组成乐曲的每个音符的发音频率值及其持续的时间是乐曲能连续演奏所需的两个基本要素,获取这两个要素所对应的数值以及通过纯硬件的手段来利用这些数值实现所希望乐曲的演奏效果是本实验的关键。
VHDL实验:乐曲演奏

LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY song IS PORT( clk_4MHz, clk_4Hz: IN STD_LOGIC; --预置计数器和乐谱产生器的时钟 digit: BUFFER STD_LOGIC_VECTOR(6 DOWNTO 0); --低三位表示低音,中间三位表示中音,最高位表示高音;本 曲仅仅有高音1,故此用1位表示。 speaker: out STD_LOGIC --扬声器 ); END song; ARCHITECTURE song_arch OF song IS
WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN
44=>digit<="0001000"; 46=>digit<="0010000"; 48=>digit<="0000011"; 50=>digit<="0001000"; 52=>digit<="0000110"; 54=>digit<="0000110"; 56=>digit<="0000101"; 58=>digit<="0000101"; 60=>digit<="0000101"; 62=>digit<="0000101"; 64=>digit<="0011000"; 66=>digit<="0011000"; 68=>digit<="0000111"; 70=>digit<="0010000"; 72=>digit<="0000110";
乐曲硬件演奏电路的VHDL设计

乐曲硬件演奏电路的VHDL设计1.Songer顶层文件模块:LIBRARY IEEE; -- 硬件演奏电路顶层设计 USE IEEE.STD_LOGIC_1164.ALL; ENTITY Songer ISPORT ( CLK4MHZ : IN STD_LOGIC; --音调频率信号 CLK8HZ : IN STD_LOGIC; --节拍频率信号 pause: IN STD_LOGIC;CODE1 : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);-- 简谱码输出显示 HIGH1 : OUT STD_LOGIC; --高8度指示 SPKOUT : OUT STD_LOGIC );--声音输出 END; ARCHITECTURE one OF Songer IS COMPONENT NoteTabsPORT ( clk : IN STD_LOGIC;SWITCH: IN STD_LOGIC;ToneIndex : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) ); END COMPONENT; COMPONENT ToneTabaPORT ( Index : IN STD_LOGIC_VECTOR (3 DOWNTO 0) ; CODE : OUTSTD_LOGIC_VECTOR (3 DOWNTO 0) ; HIGH : OUT STD_LOGIC;Tone : OUT STD_LOGIC_VECTOR (10 DOWNTO 0) ); END COMPONENT;COMPONENT SpeakeraPORT ( clk : IN STD_LOGIC;Tone : IN STD_LOGIC_VECTOR (10 DOWNTO 0); SpkS : OUT STD_LOGIC ); END COMPONENT;SIGNAL Tone : STD_LOGIC_VECTOR (10 DOWNTO 0);SIGNAL ToneIndex : STD_LOGIC_VECTOR (3 DOWNTO 0);BEGINu1 : NoteTabs PORT MAP (clk=>CLK8HZ,SWITCH=>pause,ToneIndex=>ToneIndex); u2 : ToneTaba PORT MAP(Index=>ToneIndex,Tone=>Tone,CODE=>CODE1,HIGH=>HIGH1); u3 : Speakera PORT MAP(clk=>CLK4MHZ,Tone=>Tone, SpkS=>SPKOUT ); END;2.音乐节拍和音调发生器(NoteTabs.VHD)LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY NoteTabs ISPORT ( clk : IN STD_LOGIC; switch: IN STD_LOGIC;ToneIndex : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) ); END;ARCHITECTURE one OF NoteTabs ISCOMPONENT MUSIC --音符数据ROM PORT(address : IN STD_LOGIC_VECTOR (7 DOWNTO 0);inclock : IN STD_LOGIC ;q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0));END COMPONENT;SIGNAL Counter : STD_LOGIC_VECTOR (7 DOWNTO 0); BEGINCNT8 : PROCESS(clk,Counter)BEGINIF Counter=138 THEN Counter Counter , q=>ToneIndex, inclock=>clk); END;3.简谱码对应的分频预置数查表电路(ToneTaba.VHD)LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;ENTITY ToneTaba ISPORT ( Index : IN STD_LOGIC_VECTOR (3 DOWNTO 0) ; CODE : OUTSTD_LOGIC_VECTOR (6 DOWNTO 0) ; HIGH : OUT STD_LOGIC;Tone : OUT STD_LOGIC_VECTOR (10 DOWNTO 0) ); END;ARCHITECTURE one OF ToneTaba IS BEGINSearch : PROCESS(Index)BEGINCASE Index IS -- 译码电路,查表方式,控制音调的预置数 WHEN \WHEN \ WHEN \ WHEN \ WHEN \ WHEN \ WHEN \ WHEN \ WHEN \ WHEN \ WHEN \ WHEN \ WHEN \ WHEN OTHERS => NULL; END CASE; END PROCESS; END;4.数控分频与演奏发生器(Speakera.VHD)LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY Speakera ISPORT ( clk : IN STD_LOGIC;Tone : IN STD_LOGIC_VECTOR (10 DOWNTO 0); SpkS : OUT STD_LOGIC ); END; ARCHITECTURE one OF Speakera ISSIGNAL PreCLK, FullSpkS : STD_LOGIC; BEGINDivideCLK : PROCESS(clk)VARIABLE Count4 : STD_LOGIC_VECTOR (3 DOWNTO 0) ; BEGINPreCLK 11 THEN PreCLK。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
EDA课程设计实验报告专业:班级:姓名:LSC学号:指导教员:一、试验名称:乐曲自动演奏器二、试验目的:1. 使用FPGA 控制蜂鸣器演奏乐曲梁祝中的一段;2. 初步学会利用结构建模方法设计程序。
三、试验内容:1. 利用时钟分频进行音调和音长的设定;2. 利用整个程序,播放梁祝乐曲;3. 让LED 灯随着音乐的节拍显示,分高、中、低三种频率显示。
四、试验要求:1. 将时钟频率分别分成6MHz 和4Hz 两种;2. 利用功能框图建立整个程序,清晰的播放出梁祝乐曲。
五、试验背景及基本原理:5.1乐曲演奏基本原理:乐曲演奏的原理是这样的:组成乐曲的每个音符的频率值(音调)及其持续的时间(音长)是乐曲能连续演奏所需的两个基本数据,因此只要控制输出到扬声器的激励信号频率的高低和持续的时间,就可以使扬声器发出连续的乐曲声。
5.2音调的控制频率的高低决定了音调的高低。
音乐的十二平均率规定:每两个8度音(如简谱中的中音1与高音1)之间的频率相差一倍。
在两个8度音之间,又可分为12个半音,每两个半音的频率比为12√2。
另外,音名A(简谱中的低音6)的频率为440Hz,音名B到C之间、E到F之间为半音,其余为全音[4]。
由此可以计算出简谱中从低音1至高音1之间每个音名对应的频率,如表所示:5.3音名与频率的关系所有不同频率的信号都是从同一个基准频率分频得到的。
由于音阶频率多为非整数,而分频系数又不能为小数,故必须将计算得到的分频数四舍五入取整。
若基准频率过低,则由于分频比太小,四舍五入取整后的误差较大;若基准频率过高,虽然误差变小,但分频数将变大。
实际的设计综合考虑这两方面的因素,在尽量减小频率误差的前提下取合适的基准频率。
本试验中选取6MHz为基准频率。
若无6MHz的基准频率,则可以先分频得到6MHz,或换一个新的基准频率。
实际上,只要各个音名间的相对频率关系不变,演奏出的乐曲听起来都不会"走调"。
本试验需要演奏的是梁祝乐曲,该乐曲各音阶频率及相应的分频比如表2所示。
为了减小输出的偶次谐波分量,最后输出到扬声器的波形应为对称方波,因此在到达扬声器之前,有一个二分频的分频器。
表2中的分频比就是从6MHz频率二分频得到的3MHz频率基础上计算得出的。
由于最大的分频系数为9102,故采用14位二进制计数器分频可满足需要。
在表中,除给出了分频比以外,还给出了对应于各个音阶频率时计数器不同的预置数。
对于不同的分频系数,只要加载不同的预置数即可。
各音节频率对应的分频比及预置数表此外,对于乐曲中的休止符,只要将分频系数设为0,即初始值为2141=16383即可,此时扬声器将不会发声。
5.4音长的控制音符的持续时间必须根据乐曲的速度及每个音符的节拍数来确定。
本例演奏的梁祝片段,最短的音符为4分音符,如果将全音符的持续时间设为1s的话,则只需要再提供一个4Hz的时钟频率即可产生4分音符的时长。
由乐谱产生电路控制音乐的音调和音长。
控制音调通过设置计数器的预置数来实现,预置不同的数值可以使计数器产生不同频率的信号,从而产生不同的音调。
控制音长是通过控制计数器预置数的停留时间来实现的,预置数停留的时间越长,则该音符演奏的时间越长。
每个音符的演奏时间都是0.25s的整数倍,对于节拍较长的音符,如2分音符,在记谱时将该音名连续记录两次即可。
5.4音名显示音名显示电路用来显示乐曲演奏时对应的音符。
可以用3个数码管,分别显示高、中、低音的音名,实现演奏的动态显示,十分直观。
在本试验中,high[3:0]、med[3:0]、low[3:0]等信号分别用于显示高音、中音、低音音符。
为了使演奏能循环进行,需另外设置一个时长计数器,当乐曲演奏完成时,保证能自动从头开始演奏。
六、程序基本流程及实现6.1程序基本流程:6.2程序实现由系统框图(见附录)可以看到本方案分成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 begincnt=0; clk_12mhz =!clk_12mhz; endEndmodule2)12MHz分频成6MHz波形分频器,源代码和顶层模块如下://12mhz分成6mhz的分频模块,提供给song模块module div_clk6mhz(clk_12mhz,clk_6mhz);input clk_12mhz;output clk_6mhz;reg clk_6mhz;regcnt;always @(posedge clk_12mhz)clk_6mhz=!clk_6mhz;Endmodule3)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;always @(posedge clk_12mhz)if(cnt<1499999) cnt=cnt+1; // (12mhz/4hz=3000000,cnt<[3000000/2-1=1499999])else begincnt=0; clk_4hz =! clk_4hz; endEndmodule4)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])else begincnt=0; clk_1mhz =! clk_1mhz; endEndmodule5)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 begincnt=0; clk_1khz =! clk_1khz; endEndmodule6) song模块源代码和顶层模块如下://音乐产生模块song(clk_6mhz,clk_4h module z,speaker,high,med,low); //模块名为song(端口列表)input clk_6mhz,clk_4hz; //定义两个输入端口output speaker; //定义一个输出端口output[3:0] high,med,low;reg[3:0] high,med,low; //定义了3个4位寄存器reg[13:0] divider,origin; //定义了2个14位寄存器reg[9:0] counter; //定义了1个10位寄存器reg speaker;wire carry;assign carry=(divider==16383); //连续赋值语句always @(posedge clk_6mhz)begin if(carry) divider<=origin;else divider<=divider+1;endalways @(posedge carry)begin speaker<=~speaker;end //二分频产生方波信号always @(posedge clk_4hz)begincase({high,med,low}) //分频比预置'b000000000011:origin<=7281; //低音3'b000000000101:origin<=8730; //低音5'b000000000110:origin<=9565; //低音6'b000000000111:origin<=10310; //低音7'b000000010000:origin<=10647; //中音1'b000000100000:origin<=11272; //中音2'b000000110000:origin<=11831; //中音3'b000001010000:origin<=12556; //中音5'b000001100000:origin<=12974; //中音6'b000100000000:origin<=13516; //高音1'b000000000000:origin<=16383; //休止符endcaseendalways @(posedge clk_4hz)beginif(counter==151) counter<=0; //计时,以实现循环演奏else counter<=counter+1;case(counter) //记谱0: {high,med,low}<='b000000000011; //低音"3"1: {high,med,low}<='b000000000011; //持续4个时钟节拍2: {high,med,low}<='b000000000011;3: {high,med,low}<='b000000000011;4: {high,med,low}<='b000000000101; //低音"5"5: {high,med,low}<='b000000000101; //发3个时钟节拍6: {high,med,low}<='b000000000101;7: {high,med,low}<='b000000000110; //低音"6"8: {high,med,low}<='b000000010000; //中音"1"9: {high,med,low}<='b000000010000; //发3个时钟节拍10: {high,med,low}<='b000000010000;11: {high,med,low}<='b000000100000; //中音"2"12: {high,med,low}<='b000000000110; //低音"6"13: {high,med,low}<='b000000010000; //中音"1"14: {high,med,low}<='b000000000101; //低音"5"15: {high,med,low}<='b000000000101;16: {high,med,low}<='b000001010000; //中音"5"17: {high,med,low}<='b000001010000; //发3个时钟节拍18: {high,med,low}<='b000001010000;19: {high,med,low}<='b000100000000; //高音"1"20: {high,med,low}<='b000001100000; //中音"6"case(counter) //记谱0: {high,med,low}<='b000000000011; //低音"3"1: {high,med,low}<='b000000000011; //持续4个时钟节拍2: {high,med,low}<='b000000000011;3: {high,med,low}<='b000000000011;4: {high,med,low}<='b000000000101; //低音"5"5: {high,med,low}<='b000000000101; //发3个时钟节拍6: {high,med,low}<='b000000000101;7: {high,med,low}<='b000000000110; //低音"6"8: {high,med,low}<='b000000010000; //中音"1"9: {high,med,low}<='b000000010000; //发3个时钟节拍10: {high,med,low}<='b000000010000;11: {high,med,low}<='b000000100000; //中音"2"12: {high,med,low}<='b000000000110; //低音"6"13: {high,med,low}<='b000000010000; //中音"1"14: {high,med,low}<='b000000000101; //低音"5"15: {high,med,low}<='b000000000101;16: {high,med,low}<='b000001010000; //中音"5"17: {high,med,low}<='b000001010000; //发3个时钟节拍18: {high,med,low}<='b000001010000;19: {high,med,low}<='b000100000000; //高音"1"20: {high,med,low}<='b000001100000; //中音"6“endcaseendendmodule7)取码模块源代码和顶层模块如下://取码模块,从song模块取得数码管显示部分的位码和段码modulequma(high,med,low,clk_1mhz,dig,duan);input [3:0] high,med,low;input clk_1mhz;reg[7:0] dig;output [7:0]dig;//定义输出八位位码reg [7:0] duan;output [7:0] duan; //定义用于输出的段码的代码always @(posedge clk_1mhz)//扫描high,med,low三个寄存器的值,取出位码和段码的代码beginif (high!=0) //如果high的值不为0,则只输出high的值begin dig<=8'b11111011;case (high)1:duan<=8'b00000001;2:duan<=8'b00000010;3:duan<=8'b00000011;4:duan<=8'b00000100;5:duan<=8'b00000101;6:duan<=8'b00000110;7:duan<=8'b00000111;endcaseendcase (low )1:duan<=8'b00000001;2:duan<=8'b00000010;3:duan<=8'b00000011;4:duan<=8'b00000100;5:duan<=8'b00000101;6:duan<=8'b00000110;7:duan<=8'b00000111;endcaseendendendmodule8)disp:显示模块,每位输出转换为七段数码管显示。