1.电子琴工作原理与框图
电子琴上有两个发声装置,一个为蜂鸣器,一个为扬声器,其中蜂鸣器发声靠的是引脚产生一个方波信号驱动,改变方波的频率,就能实现蜂鸣器发对应频率的音符。 而扬声器的驱动是由DDS产生的模拟信号,经PWM调制,再经过rc滤波,最后通过运放电路输出到扬声器上。同理改变DDS产生的模拟信号频率,来实现不同的音符播放。可以通过FPGA上按键来实现电子琴的演奏和音乐播放模式。 音乐播放模式工作原理,通过对乐曲简谱进行转化,存储相应的代码,输出乐曲对应的音符,音符输入到例化好的模块。同时可以通过上下音程按键进行上下曲切换。在演奏模式,可以通过电子琴地板上的两个上下音程调节按键实现对音程的调节,其中在数码管上会显示对应的音程挡位,其中“0”为不发声,“1”档对应的频率范围为130.81~261.63即C3到C4这13个音符,“2”档对应C4到C5这13个音符,“4”档对应C5到C6这13个音符。目前就添加了扬声器演奏模式下,这3档音程。同时通过板子上的拨钮开关可以在任何时刻改变声音的输出方式(扬声器与蜂鸣器)。
test为顶层文件,输入小脚丫开发板的系统时钟C1(12MHz),系统复位引脚定义为L14,加电子琴的13个按键,以及切换拨钮N4,加上两个“上下”按键以及演奏模式与音乐播放模式切换按键。
输出有电子琴蜂鸣器buzzer:P8,电子琴扬声器speaker:N8,以及小脚丫fpga板上8个led与两个rgbLED,两个数码管
以下是部分子模块:
Buzzer为蜂鸣器发声文件,输入小脚丫开发板的系统时钟C1,系统复位引脚定义为L14,通过电子琴的按键产生对应的pwm波驱动蜂鸣器发声。
输出有电子琴蜂鸣器buzzer:P8,以及通过按键状态输出buzzer。
dds为扬声器发声文件,输入小脚丫开发板的系统时钟C1,系统复位引脚定义为L14,以及输入对应音符的参数,则通过电子琴的按键产生对应的正弦波驱动扬声器发声。
输出有电子琴蜂鸣器speaker:N8,输出是通过pwm调制输出,
从图可以看出,改变占空比就可以改变电压值,一个占空比对应为一个模拟电压值,用PWM的方式实现数字到模拟变换的功能。
这个为DDS的仿真图,频率在130HZ,根据输出的PWM占空比不同,如两个图,
播放音乐模式存放了如下歌曲,通过对应的简谱,然后编码存放在rom中。
test为顶层文件,输入小脚丫开发板的系统时钟C1(12MHz),系统复位引脚定义为L14,加电子琴的13个按键,以及切换拨钮N4,加上两个“上下”按键以及演奏模式与音乐播放模式切换按键。
输出有电子琴蜂鸣器buzzer:P8,电子琴扬声器speaker:N8,以及小脚丫fpga板上8个led与两个rgbLED,两个数码管
以下是部分子模块:
Buzzer为蜂鸣器发声文件,输入小脚丫开发板的系统时钟C1,系统复位引脚定义为L14,通过电子琴的按键产生对应的pwm波驱动蜂鸣器发声。
输出有电子琴蜂鸣器buzzer:P8,以及通过按键状态输出buzzer。
dds为扬声器发声文件,输入小脚丫开发板的系统时钟C1,系统复位引脚定义为L14,以及输入对应音符的参数,则通过电子琴的按键产生对应的正弦波驱动扬声器发声。
输出有电子琴蜂鸣器speaker:N8,输出是通过pwm调制输出,
从图可以看出,改变占空比就可以改变电压值,一个占空比对应为一个模拟电压值,用PWM的方式实现数字到模拟变换的功能。
这个为DDS的仿真图,频率在130HZ,根据输出的PWM占空比不同,如下图,
播放音乐模式存放了如下歌曲,通过对应的简谱,然后编码存放在rom中。
2.蜂鸣器和模拟喇叭的差别
模拟喇叭又称为扬声器,是电声转换器件,它可以把模拟的电信号转换为声音信号,它属于宽频率发声器件。蜂鸣器是一体化的电子讯响器,可以在不同驱动波形下发出单调的声音,属于窄频率发声器件。所以只要有合适的模拟信号,喇叭就可以播放对应的音乐。
用蜂鸣器和模拟喇叭的实现方法差别以及音效差别分析
本项目蜂鸣器发声靠的方波提供外部震荡激励,当震荡频率不同时发出不同的音调,对于FPGA来说,方波信号产生方便可靠,成为外部震荡激励的首选,方波信号输入谐振装置转换为声音信号输出。而模拟喇叭靠的是DDS产生的模拟信号,将模拟信号经PWM调制,在经RC滤波,最后接专门的音频放大器最后输出给喇叭。两个发声实现的方法都用到PWM,蜂鸣器是用PWM作为方波信号输入,而模拟喇叭则是把PWM做dac,将数字量转模拟量,最后通过放大器输出给喇叭。在音效方面,蜂鸣器听起来有点滴答滴的音效,而喇叭听起来或许和网上一样,嘈杂而又喧闹的喇叭声。我自己是真的听不出来是什么效果, 喇叭的声音是非常强大的,可以播放许多音效。
关于电路仿真部分,由于自己对电路方面有待提高,以及对RC滤波电路和放大器工作原理的理解,暂时还没有做出来。
3.主要代码片段及说明
reg pwm_out;
reg [31:0] cnt;
always @(posedge clk or negedge rst )
begin
if(!rst) cnt<=0;
else if (cnt>=T/2) cnt<=0;
else cnt<=cnt+1;
end
always @(posedge clk or negedge rst)begin
if (rst==0) pwm_out<=0;
else if (cnt==T/2) pwm_out<=~pwm_out;
else pwm_out<=pwm_out;
end
以上代码为根据一个传入的参数T,再利用计数器来产生一个对应的频率的方波,其对应的公式为f=12000000/T,如440hz时,对应的T为27272。
wire [31:0] T;
reg [23:0] phase_acc;
always @(posedge clk_in) phase_acc <= phase_acc + T; //主时钟为12MHz,寻找波表产生模拟信号
sin_table u_sin_table(.address(phase_acc[23:16]),.sin(date_out));
利用计数器phase_acc 和T来作为地址寻址,继而产生对应的模拟信号,使用24位phase_acc 计数器和12MHz时钟,输出的频率分辨率可以达到0.7Hz,然后根据想要的频率,即可计算出对应的T,如果是从phase_acc[23:16]开始寻址,则当T=2^16=65536时,正好输出phase_acc[7:0]+1时对应的频率46.875KHz,故我们需要的频率与T的关系为f=46875*T/65536,如输出440Hz时,对应的T为615。
还有一些代码则在工程中说明。
4.遇到的主要难题及解决方法
在刚开始,和往常一样通过电子琴的按键去点灯,可是遇到引脚映射的时候,发现点灯失败,后面去分析了小脚丫的原理图,以及电子琴的原理图,还有电子森林提供的小脚丫引脚图,综合分析下,最终确定了电子琴每个按键对应的引脚。这对后续的引脚映射节省的许多时间。
第二个难点是对DDS存的波表数据处理,因为例程给的是正弦波的波表数据,而项目要求需要基波和至少一次谐波,当时群友和网上都提到了许多工具有matlab,mif工具等等,最后为了处理简单,我选择了一次谐波,然后通过比较简单的excel工具去生成波表数据。
第三个难点是对DDS代码的理解,本次项目DDS代码是在电子森林例程上改动的,因为例程上只存了四分之一个波表数据,其他的都是基于对称性实现,而为了代码好理解,而本次项目则是存储了整个波表的数据。在存为波表数据后,下载程序,发现电子琴没有声音。然后就是各种找资料,问群友,最后的解决方法就是做仿真,最后通过仿真观察,发现波形不对,最后仔细查看了代码和仿真,发现问题出现在位数上面,以及寻地址的参数,通过合适的位数,防止溢出,以及寻完地址和频率范围调节参数设置好后,仿真的波形终于对了。
第四个难点,对音乐播放的设计,起初我对这一块是毫无头绪的,最后在网上查找资料,花了两三天去理解和设计自己的音乐播放,一开始音乐播放是正常的,后面发现有的音符播放和节奏不对,在问群友和请教别人,发现空拍子和四分音符持续时间,如最短的音符为四分音符,如果将全音符的持续时间设为1s,则需要提供一个4Hz的时钟频率信号即可产生四分音符的时长。最后用状态机实现两首音乐的播放和切换。
当然项目还存在许多需要改进的地方,由于自己调试的时间太短,只能按要求的去实现比较简单的功能。
5.FPGA使用资源情况
通过lattice Diamond编译出Design Summary结果如下,
共使用了1031个寄存器,其中Lattice的底层逻辑单元叫PFU(Programmable Function Unin,可编程功能单元),它是由8个LUT和8~9个寄存器构成。片(slices)资源使用率,其中作为逻辑和存储的片使用率为79%。当中最关注的LUT4s利用率为79%,作为逻辑的4输入查找表使用1564个。可以在工程文件夹下在impl1文件夹下,打开arearep文件,可以查看每个子模块用的寄存器资源。
6.改进建议
虽然项目基本完成了,但是还是有许多不足之处,因为自己对音乐这东西一窍不通,听不出来好的音效,所以在喇叭做发声装置的时候,只是简单的加了一个谐波,没有去考虑其他的参数,如幅度与相位组合。模拟喇叭的声音听起来怪怪的,第二个问题就是蜂鸣器没有做到音程调节,而扬声器可以做到音程调节,第三个问题就是没有做到好的和弦,两个按键按下,声音是噪的。由于学校有实习,调试的时间比较少,可能还有其他的bug,暂时可能没有发现,后续则会对以上问题进行优化,争取能做的完美,同时能够实现好的音效。最后感谢硬禾学堂和电子森林平台能够给我这一次学习机会,在这一次的学习中,收获了许多!