verilog-EGO1简易音乐播放器
1.设计思路
EGO1 上的单声道音频输出接口(J12)由下图所示的低通滤波器电路驱动。
滤波器的输入信号(AUDIO_PWM)是由FPGA产生的脉冲宽度调制信号(PWM)或脉冲密度调制信号(PDM)。低通滤波器将输入的数字信号转化为模拟电压信号输出到音频插孔上。通过控制内置蜂鸣器来输出音乐。
设计了四个寄存器,功能分别是:state:乐谱状态机,用于状态计数;count:计数器,用于累加计数;count_end:存储对应不同音阶的乐谱参数;count1:计数器。
首先查表,得到基本音阶-频率对应表(C大调):
C和G对照表:
由于芯片的时钟频率为100Mhz,要输出不同音阶,需要计算参数:D=F/2K
(D:参数,F:时钟频率,K:音阶频率),让count累加,每次累加到D,就将输出beep取反,这样,单位时间内beep输出处于高电位的次数就是音阶频率K,实现了特定音阶的输出。
管脚设置:
样本简谱:
2.主要代码
module project1(
input clk,
output beep, //蜂鸣器输出
output sd);
reg beep_r;
reg[7:0] state; //乐谱状态机
reg[16:0]count,count1;
reg[25:0]count2;
assign sd=1'b1;
parameter //(G大调乐谱参数)
L_1 = 18'd127552, //低音1
L_2 = 18'd113636, //低音2
L_3 = 18'd101236, //低音3
L_4 = 18'd95548, //低音4
L_5 = 18'd85136, //低音5
L_6 = 18'd75838, //低音6
L_7 = 18'd67567, //低音7
M_1 = 18'd63776, //中音1
M_2 = 18'd56818, //中音2
M_3 = 18'd50607, //中音3
M_4 = 18'd47778, //中音4
M_5 = 18'd42553, //中音5
M_6 = 18'd37936, //中音6
M_7 = 18'd33783; //中音7
parameter TIME = 50000000; //每种音阶持续时长为500ms
assign beep = beep_r;
always@(posedge clk) begin
count <= count + 1'b1;
if(count == count1) begin
count <= 17'h0;
beep_r <= !beep_r; //实际上每个周期分别包括等时长的高电位和低电位,一高一低反复循环,形成不同频率的声音
end
end
always @(posedge clk) begin
if(count2 < TIME)
count2 = count2 + 1'b1;
else begin
count2 = 26'd0;
if(state == 8'd32)
state = 8'd0;
else
state = state + 1'b1;
case(state)//晴天前奏曲谱
8'D0:count1 = L_6;
8'D1:count1=M_1;
8'D2:count1=M_5;
8'D3:count1=M_1;
8'D4:count1=L_4;
8'D5:count1=L_5;
8'D6:count1=M_5;
8'D7:count1=M_1;
8'D8:count1=L_1;
8'D9:count1=L_5;
8'D10:count1=M_5;
8'D11:count1=M_1;
8'D12:count1=L_1;
8'D13:count1=M_5;
8'D14:count1=L_1;
8'D15:count1=M_5;
8'D16:count1=L_6;
8'D17:count1=M_1;
8'D18:count1=M_5;
8'D19:count1=L_6;
8'D20:count1=L_4;
8'D21:count1=L_5;
8'D22:count1=M_5;
8'D23:count1=M_1;
8'D24:count1=L_1;
8'D25:count1=L_5;
8'D26:count1=M_5;
8'D27:count1=M_1;
8'D28:count1=L_1;
8'D29:count1=M_5;
8'D30:count1=L_7;
8'D31:count1=M_1;
8'D32:count1=M_5;
default: count1 = 16'h0;
endcase
end
end
endmodule