0.目录
-
项目要求
-
实现功能
-
项目分析
-
硬件结构
-
蜂鸣器
-
扬声器
-
和弦
-
音乐盒
- 资源占用
-
实物演示
-
心得体会
- 附件
1.项目要求
自己组装,并通过编程驱动模拟扬声器实现电子琴的功能。
2.实现功能
-
基于套件和工具,自己组装电子琴。
-
编程基于FPGA实现:
-
存储一段音乐,并可以进行音乐播放。
-
可以自己通过板上的按键进行弹奏,支持两个按键同时按下(和弦)并且声音不能失真,板上的按键只有13个,可以通过有上方的“上“、”下”两个按键对音程进行扩展。
-
使用扬声器进行播放时,输出的音调信号除了对应于该音调的单频正弦波外,还必须包含至少一个谐波分量。
-
音乐的播放支持两种方式,这两种方式可以通过开关进行切换:
-
当开关切换到蜂鸣器端,可以通过蜂鸣器来进行音乐播放。
-
当开关切换到扬声器端,可以通过模拟扬声器来进行音乐播放,每个音符都必须包含基频 + 至少一个谐波分量。
-
-
3.项目分析
该项目需要使用小脚丫FPGA与电子琴扩展板,电子琴拓展板与所有小脚丫核心板兼容,本次使用基于Lattice XO2-4000HC的小脚丫FPGA核心模块,通过Diamond进行开发(lattice_diamond_安装配置)。
本项目共需要有两种声音输出方式——蜂鸣器与扬声器。蜂鸣器通过PWM进行驱动,产生的声音效果较差。扬声器则通过PWM和一位DAC后加运放进行驱动,以达到更好的声音效果。
-
2个RGB灯指示扬声器输出或蜂鸣器输出。
-
LED显示当前音程。
-
数码管显示按下琴键。
-
Key1为系统复位按键。
-
SW1为切换音乐盒模式。
4.硬件结构
-
核心器件:Lattice LCMXO2-4000HC-4MG132
-
板载资源:
-
两位7段数码管;
-
两个RGB三色LED;
-
8路用户LED;
-
4路拨码开关;
-
4路按键;
-
-
36个用户可扩展I/O(其中包括一路SPI硬核接口和一路I2C硬核接口)
-
支持Lattice的开发工具Diamond
-
支持MICO32/8软核处理器
-
板上集成FPGA编程器
-
一路Micro USB接口
-
板卡尺寸52mm x 18mm
5.蜂鸣器
蜂鸣器可以直接参考例程,按下不同按键时调整PWM的频率即可。按键按下时输出,抬起后声音停止。
//当蜂鸣器使能时,计数器按照计数终值(分频系数)计数
always@(posedge clk_in or negedge rst_n_in) begin
if (!rst_n_in) begin
time_cnt <= 1'b0;
end else if (!tone_en) begin
time_cnt <= 1'b0;
end else if (time_cnt>= time_end) begin
time_cnt <= 1'b0;
end else begin
time_cnt <= time_cnt + 1'b1;
end
end
//根据计数器的周期,翻转蜂鸣器控制信号
always@(posedge clk_in or negedge rst_n_in) begin
if (!rst_n_in) begin
piano_out <= 1'b0;
end else if (time_cnt == time_end) begin
piano_out <= ~piano_out; //蜂鸣器控制输出翻转,两次翻转1Hz
end else begin
piano_out <= piano_out;
end
end
6.扬声器
扬声器为达到更好的效果,先使用PLL倍频,输入晶振为12MHz,通过PLL倍频至120MHz。
通过调整PWM波的占空比,以实现不同电压,可以参考简易电子琴设计。
PWM的代码如下:
module PWM(input clk,
input rst_n,
input [9:0]duty,
input pwm_en,
output pwm_output);
reg [10:0] pwm_acc;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)begin
pwm_acc <= 0;
end
else begin
pwm_acc <= pwm_acc[9:0]+duty;
end
end
assign pwm_output = pwm_acc[10]&pwm_en;
endmodule
正弦波表预先存储在ROM中,采用EXCEL制作,加入谐波分量(最高至五次谐波),各次比例如下:
谐波 | 比例 |
基波谐波 | 0.63 |
二次谐波 | 0.21 |
三次谐波 | 0.06 |
四次谐波 | 0.05 |
五次谐波 | 0.05 |
按该比例加和后进行归一化处理,再进行整形与十六进制转换,最终的得到256位10bit的正弦波形。
将该数据以mem格式存储后生成ROM,配置如下:
对于不同的音节正弦信号频率不同,修改ROM的时钟频率即可以不同速度输出正弦波,以达到输出不同频率正弦波的作用。
ReadSinData ReadSinData1(
.clk(clk),
.rst_n(rst_n),
.tone_en(tone_en),
.tone(tone1),
.sin_out(sin_out1)
);
PWM PWM(
.clk(clk),
.rst_n(rst_n),
.duty(pwm_duty),
.pwm_en(tone_en),
.pwm_output(piano_out)
);
7.和弦
和弦时例化3个读取ROM的模块,输入不同音节频率,将输出结果合成即可。
ReadSinData ReadSinData1(
.clk(clk),
.rst_n(rst_n),
.tone_en(tone_en),
.tone(tone1),
.sin_out(sin_out1)
);
ReadSinData ReadSinData2(
.clk(clk),
.rst_n(rst_n),
.tone_en(chord_en),
.tone(tone2),
.sin_out(sin_out2)
);
ReadSinData ReadSinData3(
.clk(clk),
.rst_n(rst_n),
.tone_en(chord_en),
.tone(tone3),
.sin_out(sin_out3)
);
assign chord_out = (sin_out1 + sin_out2 + sin_out3)/3;
8.音乐盒
预先存储一段乐谱在ROM中,控制音符以0.5s的速度播放,演示中播放的是小星星。
9.资源占用
10.实物演示
演示视频见b站链接。
11.心得体会
-
Diamond与Quartus使用上界面相似,但IP核的使用体验比Quartus差。
-
和弦的种类较多,只设置了1 3 5的和弦,其他和弦种类未进行设置。
12.附件
链接:https://pan.baidu.com/s/1kk9RoY3Ls0tt1VMOvek-hA?pwd=64ir 提取码:64ir