名称:电子琴及乐曲演奏设计Verilog代码Quartus B-ICE实验箱(文末获取)
软件:Quartus
语言:Verilog
代码功能:
电子琴及乐曲演奏
一、实验内容:
本实验利用音频功放模块演奏乐曲,或者利用按键部分弹奏乐曲。已经给出的代码中有缺少的逻辑,请补充代码,并下载到FPGA验证其功能。
将SW1 置于上,可以使用硬件电子琴,此时F1-F8 分别对应1、2、3、4、5、6、7、8、升1 八个音,由此可以演奏出简单的音乐;
将SW1 置于下,可以播放预置的音乐,本设计中预置了王菲的《传奇》,按rst 键重复
图1 系统框图
二、实验准备:
该实验需要使用Audio 功放模块、SW1-SW8模块、F1-F10模块。将控制拨码开关模块CPRL_SW中 SEL1拨置于上,SEL2拨置于下,逻辑电平为10使DP9数码管显示2,可以使用Audio 音频模块,如果把BZ1中的跳线器连接在1-2 的方式,那么可以使用LS_BUZ1有源蜂鸣器,如果把BZ1中的跳线器连接在2-3 的方式,那么可以使用2W 的喇叭;F1-F6已经固定连接到实验平台中的FPGA_CON1处,F7-F10是复用的I/O,当实验平台上控制拨码开关模块LCD_ALONE_CTRL_SW中KSI拨置于下,可以使用按键模块中的F7,F8,F9,F10;SW1-SW8已经固定连接到实验平台中的FPGA_CON1和FPGA_CON2处。
三、实验原理
在此,首先介绍一下硬件电路的发声原理。我们知道,声音的频谱范围约在几十到几千赫兹,如果将一定频率的方波接上扬声器就能发出相应频率的声音。而乐曲中的每一音符对应着一个确定的频率,因此,要想FPGA 发出不用音符的音调,实际上只要控制它输出相应音符的频率即可(音符和频率的关系见下表)
乐曲都是由一连串的音符组成,因此按照乐曲的乐谱依次输出这些音符所对应的频率,就可以在扬声器上连续地发出各个音符的音调。而要准确地演奏出一首乐曲,仅仅让扬声器能够发声是不够的,还必须准确地控制乐曲的节奏,即每个音符的持续时间。由此可见,乐曲中每个音符的发音频率及其持续的时间是乐曲能够连续演奏的两个关键因素。而简易电子琴,工作原理与乐曲演奏一样,只是将固定预置乐曲变成了手动按键输入,节拍时间取决于按键的停留时间,如果合适,同样能播放出完整的歌曲来。频率的高低决定了音调的高低。音乐的十二平均率规定:每两个八度音(如简谱中的中音1 和高音1)之间的频率相差一倍。在两个八度音之间又分为十二个半音。另外,音名A(简谱中的低音6)的频率为440Hz,音名B 到C 之间、E 到F 之间为半音,其余为全音。由此可以计算出简谱中从低音1 到高音1 之间每个音名对应的频率,所有不同频率的信号都是从同一个基准频率分频得到的。由于音阶频率多为非整数,而分频系数又不能为小数,因此必须将计算得到的分频数四舍五入取整。因此,要想FPGA 发出不同音符的音调,实际上只要控制它输出相应音符的频率即可。本文中选取50MHZ 作为CLK 的分频计数器的输入分频信号。乐曲都是由一连串的音符组成,因此按照乐曲的乐谱依次输出这些音符所对应的频率,就可以在扬声器上连续地发出各个音符的音调。采用50M 时钟,分频表如下所示:
表 1 频率与分频系数
音名 | 频率/Hz | 分频 系数 | 音名 | 频率/Hz | 分频 系数 | 音名 | 频率/Hz | 分频 系数 |
低音 1 | 261.6 | 191132 | 中音 1 | 523.3 | 95548 | 高音 1 | 1045.5 | 47824 |
低音 2 | 293.7 | 170242 | 中音 2 | 587.3 | 85136 | 高音 2 | 1174.7 | 42564 |
低音 3 | 329.6 | 151700 | 中音 3 | 659.3 | 75838 | 高音 3 | 1318.5 | 37922 |
低音 4 | 349.2 | 143184 | 中音 4 | 698.5 | 71582 | 高音 4 | 1396.9 | 35794 |
低音 5 | 392 | 127551 | 中音 5 | 784 | 63776 | 高音 5 | 1568 | 31888 |
低音 6 | 440 | 113636 | 中音 6 | 880 | 56818 | 高音 6 | 1760 | 28410 |
低音 7 | 493.9 | 101236 | 中音 7 | 987.8 | 50618 | 高音 7 | 1975.5 | 25310 |
音符的持续时间须根据乐曲的速度及每个音符的节拍数来确定。因此,在想控制音符的音长,就必须知道乐曲的速度和每个音符所对应的节拍数,在这个设计中所演奏的乐曲的最短的音符为四分音符,如果将全音符的持续时间设为1s 的话,那么一拍所应该持续的时间为0.25 秒,则只需要再提供一个4HZ 的时钟频率即可产生四分音符的时长。要想让系统知道现在应该演奏哪个音符,而这个音符持续的时间应该是多少,就必须编写乐曲文件,在乐曲文件中音符是按地址存放的,当系统工作时就按4Hz 的频率依次读取简谱,当系统读到某个音符的简谱时就对应发这个音符的音调,持续时间为0.25 秒,而如果在曲谱文件中这个音符为三拍音长,那又该如何控制呢?其实只要将该音符连续书写三遍,这时系统读乐曲文件的时候就会连续读到三次,也就会发三个0.25 秒的音长,这时我们听上去就会持续了三拍的时间,通过这样一个简单的操作就可以控制音乐的音长了。
本次实验采用了王菲的《传奇》,如下示:
注1:在编码过程中,由于测试中断的时间较长,所以将上图中画圈的地方去掉了(实际这
些地方的00 表示停顿两个节拍)。
若想演奏出这首曲子,首先要将曲子的节拍写出来然后再存起来供调用,本实验中将
其节拍编码后存入ROM(利用了quartus 宏模块)中,然后调用。本程序编码方式如下所示:
Mux2_1为播放方式(按键弹奏或直接播放)二选一模块;
Div模块用于分频和ram地址产生,
Sram 为音乐的存放ROM,ToneTaba模块为音符码转换成发生频率
Electronic_organ模块为按键时通过查表输出所需音符频率。
仿真波形:
在此给出用quartus 内嵌式逻辑分析仪得到的波形,通过换算在得到每个音的频率,看其是否是需要的音的频率。
输出频率计算方法;逻辑分析仪的采样频率为250KHz(在程序中的分频器中产生),所以输出时钟频率
f=250000/N,N 为波形一个周期的点数。如第一幅图,即低音1 中,N=957,则其输出频率f=250000/957=261.23Hz,考虑到这个N 是手动找的,所以和前面原理中的分析完全吻合,即产生了低音1 所需要的频率。其余几个音完全一样。
注:在电子琴实验中,并没有用到其余中音和高音;在音乐演奏电路中,很多乐曲没有用到高音,但在程序中也都给出了高音的编码,在此并没有对其测试。
低音1:N=957
低音2:N=855
任务:
Div模块内部完善对应功能的程序,并建立sram ip,初始化乐曲文件。分配好引脚后生成比特流文件下载到芯片,验证奏乐功能,根据实现程度进行打分。
本代码已在B-ICE实验箱验证,B-ICE实验箱如下,其他开发板可以修改管脚适配:
1. 工程文件
2. 程序文件
程序补充:
IP核设置
3. 程序编译
4. RTL图
5. 管脚分配
部分代码展示:
//Filename:electronic_organ //Function:input key and output clk respectively //Date:2010.9.25 //Description:Cyclone III EP3C16Q240C8 module electronic_organ(iclk_50,keyin,buzzout); input iclk_50; input [7:0] keyin; output buzzout; reg [17:0] N; reg [17:0] cnt; reg clk_buzz; initial begin clk_buzz=0; cnt=0; end always@(posedge iclk_50) begin if(!keyin[7]) //----do N<=191132; else if(!keyin[6]) //----ri N<=170242; else if(!keyin[5]) //----mi N<=151700; else if(!keyin[4]) //----fa N<=143184; else if(!keyin[3]) //----so N<=127552; else if(!keyin[2]) //----la N<=113636; else if(!keyin[1]) //----si N<=101236; else if(!keyin[0]) //----#do N<=95548; else begin clk_buzz<=0; cnt<=17'd0; end
源代码
点击下方的公众号卡片获取