基于FPGA实现电子琴
基于FPGA实现电子琴,按键消抖,DDS,PWM,MID,自动播放音乐,和弦
标签
FPGA
数字逻辑
DDS
tttao
更新2022-09-07
654

任务要求:

存储一段音乐,并可以进行音乐播放,

可以自己通过板上的按键进行弹奏,支持两个按键同时按下(和弦)并且声音不能失真,板上的按键只有13个,可以通过有上方的“上“、”下”两个按键对音程进行扩展

使用扬声器进行播放时,输出的音调信号除了对应于该音调的单频正弦波外,还必须包含至少一个谐波分量

音乐的播放支持两种方式,这两种方式可以通过开关进行切换: 

当开关切换到蜂鸣器端,可以通过蜂鸣器来进行音乐播放

当开关切换到扬声器端,可以通过模拟扬声器来进行音乐播放,每个音符都必须包含基频 + 至少一个谐波分量。  

 

Ft1FzGfFfAWNJz7WR8qdbiAQyrzM

功能框图:

主要实现两个功能,1是手动演奏,2是自动播放音乐

Fu6X83ZHiNnAtM5mpv4qF6cSzPpK

 

电子琴原理:当物体振动时,能够发出声音。振动的频率不同,声音的音调就不同。在电子琴里,虽然没有振动的弦、簧、管等物体,却有许多特殊的电装置,每个电装置一工作,就会使喇叭发出一定频率的声音。当按动某个琴键时,就会使与它对应的电装置工作,从而使喇叭发出某种音调的声音。
电子琴的音量控制器,实质上是一个可调电阻器。当转动音量控制器旋扭时,可调电阻器的电阻就随着变化。电阻大小的变化,又会引起喇叭声音强弱的变化。所以转动音量控制旋扭时,电子琴发声的响度就随之变化。

喇叭和蜂鸣器的区别:

从两者的结构和原理上比较与分析,喇叭输入的信号为音频信号,是不断变化的交流电,所以在结构上无振荡器;蜂鸣器输入的为直流电,为使其发出声音,在结构上必须配有振荡器(振荡器是一种产生交流信号的电路),将直流电转换为交流电,从而发出声音。

用蜂鸣器和模拟喇叭的实现方法差别以及音效差别分析:

蜂鸣器发出的声音比较简单,主要用于提示或报警,根据设计和用途的不同,能发出音乐声、汽笛声、蜂鸣声、警报声、电铃声等各种不同的声音。

与蜂鸣器不同的是, 扬声器音色丰富;能够发出多种音调,可以播放各种声音,例如音乐。

模拟放大电路的仿真及分析:

8002B是专为大功率、高保真的应用场合所设计的音频功放IC。所需外围元件少且在2.0V~5.5V的输入电压下即可工作。当在输出端VO1和VO2之间接上不同的负载时,运放就建立了“桥式模式”。桥式模式工作方式与通常应用时负载一端接地的单端模式不同。桥式运放在设计上也与单端模式有所差异,例如在对负载提供驱动能力上,其输出幅度是输入电压的两倍。从而,在相同条件下与单端模式相比可提供四倍的输出功率。这就在不限制电流和发音清晰的情况下提高了输出功率。对于任何功放,恰当的电源旁路选择是低噪声性能和过高电源过滤至关重要的。BYPASS和电源管脚电容的位置应尽量接近芯片。大的电源旁路电容的增加可以提升低频时的THD+N,这也应归咎于电容的增加提高了电源的稳定性。典型应用10uF和0.1uF的旁路电容于5V电源,来提高电源的稳定性,但不仅仅局限于8002B的电源旁路。旁路电容尤其是
C的选择,依赖于低频THD+N,系统成本和尺寸的折中考虑。

资源占用率由于设计的缺陷,占用的资源比较高。FttPtzfEpvuBtmYFPbmcGZaEcYTg

 

主要代码片段及说明:

自动播放:

我实现自动播放的方法比较粗暴,在case中填入所需要播放的音乐的音符所对应的按键值,通过时钟,按顺序出即可。我这里实现0.5s播放一个音。12MHz的时钟计数到600000即可。

localparam state_top=24'd6000000-1;

reg [23:0] state_cnt;
always@(posedge clk or negedge rst)begin
	if(!rst)
		state_cnt<=0;
	else if(auto_en) begin
		if(state_cnt<state_top)
		state_cnt<=state_cnt+1;
		else
		state_cnt<=0;
		end
	else
	state_cnt<=0;
end

wire state_cnt_done=(state_cnt==state_top)?1:0;
reg [4:0]state;
always@(posedge clk or negedge rst)begin
	if(!rst)
		state<=0;
	else if(state_cnt_done)begin
		if(state<41)
			state<=state+1;
		else
			state<=0;
	end
	else
		state<=state;
end

always@(*)begin
		case(state)
			0	:key_out1<=13'b111_111_111_111_0;//1
			1	:key_out1<=13'b111_111_111_111_0;//1
			2	:key_out1<=13'b111_110_111_111_1;//5
			3	:key_out1<=13'b111_110_111_111_1;//5
			4	:key_out1<=13'b111_011_111_111_1;//6
			5	:key_out1<=13'b111_011_111_111_1;//6
			6	:key_out1<=13'b111_110_111_111_1;//5
			7	:key_out1<=13'b111_111_101_111_1;//4
			8	:key_out1<=13'b111_111_101_111_1;//4
			9	:key_out1<=13'b111_111_110_111_1;//3
			10	:key_out1<=13'b111_111_110_111_1;//3
			11	:key_out1<=13'b111_111_111_101_1;//2
			12	:key_out1<=13'b111_111_111_101_1;//2
			13	:key_out1<=13'b111_111_111_111_0;//1
			14	:key_out1<=13'b111_110_111_111_1;//5
			15	:key_out1<=13'b111_110_111_111_1;//5
			16	:key_out1<=13'b111_111_101_111_1;//4
			17	:key_out1<=13'b111_111_101_111_1;//4
			18	:key_out1<=13'b111_111_110_111_1;//3
			19	:key_out1<=13'b111_111_110_111_1;//3
			20	:key_out1<=13'b111_111_111_101_1;//2
			21	:key_out1<=13'b111_110_111_111_1;//5
			22	:key_out1<=13'b111_110_111_111_1;//5
			23	:key_out1<=13'b111_111_101_111_1;//4
			24	:key_out1<=13'b111_111_101_111_1;//4
			25	:key_out1<=13'b111_111_110_111_1;//3
			26	:key_out1<=13'b111_111_110_111_1;//3
			27	:key_out1<=13'b111_111_111_101_1;//2
			28	:key_out1<=13'b111_111_111_111_0;	//1
			29	:key_out1<=13'b111_111_111_111_0;//1
			30	:key_out1<=13'b111_110_111_111_1;//5
			31	:key_out1<=13'b111_110_111_111_1;//5
			32	:key_out1<=13'b111_011_111_111_1;//6
			33	:key_out1<=13'b111_011_111_111_1;//6
			34	:key_out1<=13'b111_110_111_111_1;//5
			35	:key_out1<=13'b111_111_101_111_1;//4
			36	:key_out1<=13'b111_111_101_111_1;//4
			37	:key_out1<=13'b111_111_110_111_1;//3
			38	:key_out1<=13'b101_111_110_111_1;//3
			39	:key_out1<=13'b111_111_111_101_1;//2
			40	:key_out1<=13'b111_111_111_101_1;//2
			41	:key_out1<=13'b111_111_111_111_0;//1
		endcase
	
	end

查表器:

电子琴发出不同声音时,只需要改变查表的速率即可。直播和其他教学视频提到这个改变查表速度的名词叫做相位控制字。改变参量FREQ的大小,来实现查表速度的不同。从而输出不同频率的正弦波。

module wave(
input clk,
input rst,
input enable,
output reg [9:0] waveout
);
parameter FREQ=24'd366;//C1 261.63Hz 时钟12MHZ  FOUT=FCLK*M/2**N,M就是FREQ 频率控制字。
reg [23:0]phase_acc;
wire [9:0]sinout;
always @(posedge clk or negedge rst)
if(!rst)
phase_acc <=0;
else
phase_acc <=phase_acc+FREQ;
always@(posedge clk or negedge rst)
if(!rst)
waveout <=0;
else if(!enable)
waveout <=sinout;
else
waveout <=0;
lookup_tables ue_table(
.phase(phase_acc[23:16]),
.sin_out(sinout)
); 
endmodule

 PWM 模块:DAC芯片,但扩展版上有个低通滤波器,可以使用PWM实现一个DAC。通过一个计数器实现PWM可能会增加额外的频率噪音,来影响正常的声音,解决方法1是提升频率,把额外的频率加到人耳听不到的地方,2就是如下的方法。

module pwm
(
input clk,
input rst,
input [11:0] duty,
output pwm_out
);
reg [12:0]PWM_accumulatore;

always @(posedge clk or negedge rst)
if(!rst)
PWM_accumulatore <=0;
else
PWM_accumulatore <=PWM_accumulatore[11:0]+duty;
assign pwm_out=PWM_accumulatore[12];




endmodule

遇到的主要难题及解决方法:

由于很长时间没有学习,所以还得需要重新看一下数电,verilog等等。多去网上查找相关资料。

一开始,DDS是一个难点,直播课的讲解,外加去网上搜索相关资料,结合起来看,对其有了比较深刻的理解。

改进的地方:

1.无法完全实现钢琴的音色包括音量的随时间按下的长短,音量也会随之变化,网上也没有找到相关的资料可以提供参考,如果这能够添加上,就能够比较完全还原钢琴的感觉。

2.市面上的电子琴大多能够实现,多种乐器的不同的音色,比如鼓,吉他等,这里还没有能够实现这样的功能

3.蜂鸣器的声音不够响亮。

 

附件下载
pianolast.7z
团队介绍
团队成员
tttao
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号