问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

电子琴及乐曲演奏设计Verilog代码Quartus SOPC实验箱

创作时间:
作者:
@小白创作中心

电子琴及乐曲演奏设计Verilog代码Quartus SOPC实验箱

引用
CSDN
1.
https://blog.csdn.net/diaojiangxue/article/details/142214333

本实验利用音频功放模块演奏乐曲,或者利用按键部分弹奏乐曲。已经给出的代码中有缺少的逻辑,请补充代码,并下载到FPGA验证其功能。

实验内容

本实验利用音频功放模块演奏乐曲,或者利用按键部分弹奏乐曲。已经给出的代码中有缺少的逻辑,请补充代码,并下载到FPGA验证其功能。

将SW1 置于上,可以使用硬件电子琴,此时F1-F8 分别对应1、2、3、4、5、6、7、8、升1 八个音,由此可以演奏出简单的音乐;

将SW1 置于下,可以播放预置的音乐,本设计中预置了王菲的《传奇》,按rst 键重复

实验准备

该实验需要使用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 时钟,分频表如下所示:

音名
频率/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,初始化乐曲文件。分配好引脚后生成比特流文件下载到芯片,验证奏乐功能,根据实现程度进行打分。(30分)

部分代码展示

//输入模块
module data_input(
input clk_500KHz,//500KHZ 
input reset,
input [3:0] L_row,//行
output [3:0] H_col,//列
output key_0_rise,//切换
output key_1_rise,//琴键1
output key_2_rise,//琴键2
output key_3_rise,//琴键3
output key_4_rise,//琴键4
output key_5_rise,//琴键5
output key_6_rise,//琴键6
output key_7_rise//琴键7
);
wire [15:0] key_number;//
key_4x4 i_key_4x4 
( 
.clk_500KHz(clk_500KHz),//500KHZ 
.reset(reset), //低电平复位
.L_row(L_row), //行 
.H_col(H_col), //列 
.key_number(key_number)//按键键值
); 
reg key_0_buf1=0;
reg key_1_buf1=0;
reg key_2_buf1=0;
reg key_3_buf1=0;
reg key_4_buf1=0;
reg key_5_buf1=0;
reg key_6_buf1=0;
reg key_7_buf1=0;
reg key_8_buf1=0;
reg key_9_buf1=0;
reg key_A_buf1=0;
reg key_B_buf1=0;
reg key_C_buf1=0;
reg key_D_buf1=0;
reg key_E_buf1=0;
reg key_F_buf1=0;
reg key_0_buf2=0;
reg key_1_buf2=0;
reg key_2_buf2=0;
reg key_3_buf2=0;
reg key_4_buf2=0;
reg key_5_buf2=0;
reg key_6_buf2=0;
reg key_7_buf2=0;
reg key_8_buf2=0;
reg key_9_buf2=0;
reg key_A_buf2=0;
reg key_B_buf2=0;
reg key_C_buf2=0;
reg key_D_buf2=0;
reg key_E_buf2=0;
reg key_F_buf2=0;
always@(posedge clk_500KHz)
begin
key_0_buf1<=key_number[0];
key_1_buf1<=key_number[1];
key_2_buf1<=key_number[2];
key_3_buf1<=key_number[3];
key_4_buf1<=key_number[4];
key_5_buf1<=key_number[5];
key_6_buf1<=key_number[6];
key_7_buf1<=key_number[7];
key_8_buf1<=key_number[8];
key_9_buf1<=key_number[9];
key_A_buf1<=key_number[10];
key_B_buf1<=key_number[11];
key_C_buf1<=key_number[12];
key_D_buf1<=key_number[13];
key_E_buf1<=key_number[14];
key_F_buf1<=key_number[15];
key_0_buf2<=key_0_buf1;
key_1_buf2<=key_1_buf1;
key_2_buf2<=key_2_buf1;
key_3_buf2<=key_3_buf1;
key_4_buf2<=key_4_buf1;
key_5_buf2<=key_5_buf1;
key_6_buf2<=key_6_buf1;
key_7_buf2<=key_7_buf1;
key_8_buf2<=key_8_buf1;
key_9_buf2<=key_9_buf1;
key_A_buf2<=key_A_buf1;
key_B_buf2<=key_B_buf1;
key_C_buf2<=key_C_buf1;
key_D_buf2<=key_D_buf1;
key_E_buf2<=key_E_buf1;
key_F_buf2<=key_F_buf1;
end
assign
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号