任务要求:
存储一段音乐,并可以进行音乐播放,
可以自己通过板上的按键进行弹奏,支持两个按键同时按下(和弦)并且声音不能失真,板上的按键只有13个,可以通过有上方的“上“、”下”两个按键对音程进行扩展
使用扬声器进行播放时,输出的音调信号除了对应于该音调的单频正弦波外,还必须包含至少一个谐波分量
音乐的播放支持两种方式,这两种方式可以通过开关进行切换:
当开关切换到蜂鸣器端,可以通过蜂鸣器来进行音乐播放
当开关切换到扬声器端,可以通过模拟扬声器来进行音乐播放,每个音符都必须包含基频 + 至少一个谐波分量。
功能框图:
主要实现两个功能,1是手动演奏,2是自动播放音乐
电子琴原理:当物体振动时,能够发出声音。振动的频率不同,声音的音调就不同。在电子琴里,虽然没有振动的弦、簧、管等物体,却有许多特殊的电装置,每个电装置一工作,就会使喇叭发出一定频率的声音。当按动某个琴键时,就会使与它对应的电装置工作,从而使喇叭发出某种音调的声音。
电子琴的音量控制器,实质上是一个可调电阻器。当转动音量控制器旋扭时,可调电阻器的电阻就随着变化。电阻大小的变化,又会引起喇叭声音强弱的变化。所以转动音量控制旋扭时,电子琴发声的响度就随之变化。
喇叭和蜂鸣器的区别:
从两者的结构和原理上比较与分析,喇叭输入的信号为音频信号,是不断变化的交流电,所以在结构上无振荡器;蜂鸣器输入的为直流电,为使其发出声音,在结构上必须配有振荡器(振荡器是一种产生交流信号的电路),将直流电转换为交流电,从而发出声音。
用蜂鸣器和模拟喇叭的实现方法差别以及音效差别分析:
蜂鸣器发出的声音比较简单,主要用于提示或报警,根据设计和用途的不同,能发出音乐声、汽笛声、蜂鸣声、警报声、电铃声等各种不同的声音。
与蜂鸣器不同的是, 扬声器音色丰富;能够发出多种音调,可以播放各种声音,例如音乐。
模拟放大电路的仿真及分析:
8002B是专为大功率、高保真的应用场合所设计的音频功放IC。所需外围元件少且在2.0V~5.5V的输入电压下即可工作。当在输出端VO1和VO2之间接上不同的负载时,运放就建立了“桥式模式”。桥式模式工作方式与通常应用时负载一端接地的单端模式不同。桥式运放在设计上也与单端模式有所差异,例如在对负载提供驱动能力上,其输出幅度是输入电压的两倍。从而,在相同条件下与单端模式相比可提供四倍的输出功率。这就在不限制电流和发音清晰的情况下提高了输出功率。对于任何功放,恰当的电源旁路选择是低噪声性能和过高电源过滤至关重要的。BYPASS和电源管脚电容的位置应尽量接近芯片。大的电源旁路电容的增加可以提升低频时的THD+N,这也应归咎于电容的增加提高了电源的稳定性。典型应用10uF和0.1uF的旁路电容于5V电源,来提高电源的稳定性,但不仅仅局限于8002B的电源旁路。旁路电容尤其是
C的选择,依赖于低频THD+N,系统成本和尺寸的折中考虑。
资源占用率由于设计的缺陷,占用的资源比较高。
主要代码片段及说明:
自动播放:
我实现自动播放的方法比较粗暴,在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.蜂鸣器的声音不够响亮。