FPGA学习--蜂鸣器播放音乐

简单介绍

本来是需要介绍蜂鸣器的,这里就不多做介绍了,因为我也不知道怎么解释,这里只是加入了自己的理解。
蜂鸣器在Verilog语言里面一般用beep来写,高电平表示关闭,而低电平表示触发。只是让蜂鸣器响这些就够了,但是我们今天需要播放音乐,需要播放不同的音频,所以这里有一些新的理解。

音频介绍

一般能够找到的简谱频率都是偏低音,也就是262hz开始的,但是这些低音在蜂鸣器上发音不太准,(也许占空比低点会好点,但是我没试过)这里选择了钢琴的高音区,如下图。

这里直接使用的白键的音,我们使用50MHz/音阶频率得到的结果,表示我们要在相应的位置计数并改变蜂鸣器的状态,可让蜂鸣器发出一秒内相应的音节频率。
今天我们直接写一个明日香处刑曲,也就是马来西亚民谣RASA SAYANGE(乐)。

代码内容

module beep_play(
    input   wire            clk     ,
    input   wire            rst_n   ,

    output  wire            beep     
);

    //各个音节代码,方便使用
    localparam  G1 = 5'd01 ,
                G2 = 5'd02 ,
                G3 = 5'd03 ,
                G4 = 5'd04 ,
                G5 = 5'd05 ,
                G6 = 5'd06 ,
                G7 = 5'd07 ;
    localparam  M1 = 5'd08 ,
                M2 = 5'd09 ,
                M3 = 5'd10 ,
                M4 = 5'd11 ,
                M5 = 5'd12 ,
                M6 = 5'd13 ,
                M7 = 5'd14 ;
    localparam  D1 = 5'd15 ,
                D2 = 5'd16 ,
                D3 = 5'd17 ,
                D4 = 5'd18 ,
                D5 = 5'd19 ,
                D6 = 5'd20 ,
                D7 = 5'd21 ;

    //计数器,用于计时和记录音节位置
    parameter   MAX_0_3s = 24'd15_000_000;
    parameter   MAX_FLAG = 8'd147;
    

    reg beep_r;//控制蜂鸣器
    reg [7:0] flag;//记录蜂鸣器的音节位置
    reg [4:0] music_r;//记录音节的内容
    reg [23:0] cnt;//时间计数器
    reg [17:0] MAX_music;//用于记录音节频率
    reg [17:0] cnt_music;//记录单个音节的震荡计数

    //记录单个音节的长度
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            cnt <= 24'd0;
        end
        else if (cnt == MAX_0_3s - 1'd1) begin
            cnt <= 24'd0;
        end
        else begin
            cnt <= cnt + 1'd1;
        end
    end

    //记录音节位置,用于表示音乐播放到某个位置
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            flag <= 8'd0;
        end
        else if (flag == MAX_FLAG && cnt == MAX_0_3s - 1'd1) begin
            flag <= 8'd0;
        end
        else if (flag != MAX_FLAG && cnt == MAX_0_3s - 1'd1) begin
            flag <= flag + 1'd1;
        end
        else begin
            flag <= flag;
        end
    end

    //用于记录音节的震荡位置,此数*频率=50MHz,既是上述的
    always @(*) begin
        case (music_r)
            D1      :   MAX_music = 18'd47778   ;
            D2      :   MAX_music = 18'd42565   ;
            D3      :   MAX_music = 18'd37922   ;
            D4      :   MAX_music = 18'd35793   ;
            D5      :   MAX_music = 18'd31888   ;
            D6      :   MAX_music = 18'd28409   ;
            D7      :   MAX_music = 18'd25310   ;
            M1      :   MAX_music = 18'd23889   ;
            M2      :   MAX_music = 18'd21283   ;
            M3      :   MAX_music = 18'd18961   ;
            M4      :   MAX_music = 18'd17897   ;
            M5      :   MAX_music = 18'd15944   ;
            M6      :   MAX_music = 18'd14205   ;
            M7      :   MAX_music = 18'd12655   ;
            G1      :   MAX_music = 18'd11945   ;
            G2      :   MAX_music = 18'd10641   ;
            G3      :   MAX_music = 18'd9480    ;
            G4      :   MAX_music = 18'd8948    ;
            G5      :   MAX_music = 18'd7972    ;
            G6      :   MAX_music = 18'd7102    ;
            G7      :   MAX_music = 18'd6327    ;
            default :   MAX_music = 18'd6327    ;
        endcase
    end

    //用于记录音节的位置的音频
    //次吃保存的乐谱是号称明日香处刑曲的RASA SAYANGE,简谱参考哔哩哔哩作者,有一些我的修改,毕竟机器比人要不会变通一点。
    //作者:Tiny五角星 https://www.bilibili.com/read/cv23088573/ 出处:bilibili
    always @(*) begin
        case (flag)
            8'd000  :   music_r = M6;
            8'd001  :   music_r = M6;
            8'd002  :   music_r = M5;
            8'd003  :   music_r = M4;
            8'd004  :   music_r = M3;
            8'd005  :   music_r = M3;
            8'd006  :   music_r = M1;
            8'd007  :   music_r = M3;
            8'd008  :   music_r = M2;
            8'd009  :   music_r = M2;
            8'd010  :   music_r = D7;
            8'd011  :   music_r = D7;
            8'd012  :   music_r = M1;
            8'd013  :   music_r = M1;
            8'd014  :   music_r = M1;
            8'd015  :   music_r = M1;
            8'd016  :   music_r = M5;
            8'd017  :   music_r = M5;
            8'd018  :   music_r = M5;
            8'd019  :   music_r = M5;
            8'd020  :   music_r = G1;
            8'd021  :   music_r = G1;
            8'd022  :   music_r = M7;
            8'd023  :   music_r = M6;
            8'd024  :   music_r = M5;
            8'd025  :   music_r = M5;
            8'd026  :   music_r = M3;
            8'd027  :   music_r = M4;
            8'd028  :   music_r = M5;
            8'd029  :   music_r = M5;
            8'd030  :   music_r = G1;
            8'd031  :   music_r = G1;
            8'd032  :   music_r = M6;
            8'd033  :   music_r = M6;
            8'd034  :   music_r = M5;
            8'd035  :   music_r = M4;
            8'd036  :   music_r = M3;
            8'd037  :   music_r = M3;
            8'd038  :   music_r = M1;
            8'd039  :   music_r = M3;
            8'd040  :   music_r = M2;
            8'd041  :   music_r = M2;
            8'd042  :   music_r = D7;
            8'd043  :   music_r = D7;
            8'd044  :   music_r = M1;
            8'd045  :   music_r = M1;
            8'd046  :   music_r = M1;
            8'd047  :   music_r = M1;
            8'd048  :   music_r = M3;
            8'd049  :   music_r = M4;
            8'd050  :   music_r = M5;
            8'd051  :   music_r = M5;
            8'd052  :   music_r = G1;
            8'd053  :   music_r = G1;
            8'd054  :   music_r = M7;
            8'd055  :   music_r = M6;
            8'd056  :   music_r = M5;
            8'd057  :   music_r = M5;
            8'd058  :   music_r = M3;
            8'd059  :   music_r = M4;
            8'd060  :   music_r = M5;
            8'd061  :   music_r = M5;
            8'd062  :   music_r = G1;
            8'd063  :   music_r = G1;
            8'd064  :   music_r = M6;
            8'd065  :   music_r = M6;
            8'd066  :   music_r = M5;
            8'd067  :   music_r = M4;
            8'd068  :   music_r = M3;
            8'd069  :   music_r = M3;
            8'd070  :   music_r = M1;
            8'd071  :   music_r = M3;
            8'd072  :   music_r = M2;
            8'd073  :   music_r = M2;
            8'd074  :   music_r = D7;
            8'd075  :   music_r = D7;
            8'd076  :   music_r = M1;
            8'd077  :   music_r = M1;
            8'd078  :   music_r = M1;
            8'd079  :   music_r = M1;
            8'd080  :   music_r = M3;
            8'd081  :   music_r = M4;
            8'd082  :   music_r = M5;
            8'd083  :   music_r = M5;
            8'd084  :   music_r = M5;
            8'd085  :   music_r = M5;
            8'd086  :   music_r = M3;
            8'd087  :   music_r = M3;
            8'd088  :   music_r = M3;
            8'd089  :   music_r = M4;
            8'd090  :   music_r = M5;
            8'd091  :   music_r = M5;
            8'd092  :   music_r = M5;
            8'd093  :   music_r = M5;
            8'd094  :   music_r = M3;
            8'd095  :   music_r = M3;
            8'd096  :   music_r = M3;
            8'd097  :   music_r = M4;
            8'd098  :   music_r = M6;
            8'd099  :   music_r = M6;
            8'd100  :   music_r = M5;
            8'd101  :   music_r = M4;
            8'd102  :   music_r = M3;
            8'd103  :   music_r = M3;
            8'd104  :   music_r = M1;
            8'd105  :   music_r = M3;
            8'd106  :   music_r = M2;
            8'd107  :   music_r = M2;
            8'd108  :   music_r = D7;
            8'd109  :   music_r = D7;
            8'd110  :   music_r = M1;
            8'd111  :   music_r = M1;
            8'd112  :   music_r = M1;
            8'd113  :   music_r = M1;
            8'd114  :   music_r = M3;
            8'd115  :   music_r = M4;
            8'd116  :   music_r = M5;
            8'd117  :   music_r = M5;
            8'd118  :   music_r = M5;
            8'd119  :   music_r = M5;
            8'd120  :   music_r = M3;
            8'd121  :   music_r = M3;
            8'd122  :   music_r = M3;
            8'd123  :   music_r = M4;
            8'd124  :   music_r = M5;
            8'd125  :   music_r = M5;
            8'd126  :   music_r = M5;
            8'd127  :   music_r = M5;
            8'd128  :   music_r = M3;
            8'd129  :   music_r = M3;
            8'd130  :   music_r = M3;
            8'd131  :   music_r = M4;
            8'd132  :   music_r = M6;
            8'd133  :   music_r = M6;
            8'd134  :   music_r = M5;
            8'd135  :   music_r = M4;
            8'd136  :   music_r = M3;
            8'd137  :   music_r = M3;
            8'd138  :   music_r = M1;
            8'd139  :   music_r = M3;
            8'd140  :   music_r = M2;
            8'd141  :   music_r = M2;
            8'd142  :   music_r = D7;
            8'd143  :   music_r = D7;
            8'd144  :   music_r = M1;
            8'd145  :   music_r = M1;
            8'd146  :   music_r = M1;
            8'd147  :   music_r = M1;
            default :   music_r = M1;
        endcase
    end

    //用于记录每个音节应该在那个位置进行震荡
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            cnt_music <= 18'd0;
        end
        else if (cnt == MAX_0_3s - 1'd1 || cnt_music == MAX_music - 1'd1) begin
            cnt_music <= 18'd0;
        end
        else begin
            cnt_music <= cnt_music + 1'd1;
        end
    end

    //让蜂鸣器在指定位置震荡
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            beep_r <= 1'b1;
        end
        else if (cnt_music >= (MAX_music - 1'd1) / 2) begin
            beep_r <= 1'b0;
        end
        else begin
            beep_r <= 1'b1;
        end
    end

    assign beep = beep_r;

endmodule

结束

今天还是玩得还是很开心的,拜拜了您嘞!

  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
FPGA蜂鸣器播放音乐的方法是利用计数器产生PWM波形,根据乐谱设置震荡周期,并给蜂鸣器赋值。在无源蜂鸣器中,有震荡源直接通直流电就可发声,而无震荡源则需要通震荡波才能发声。 具体实现方法如下: 1. 首先,通过FPGA的计数器模块产生PWM波形。计数器的计数频率可以根据需要调整,一般情况下,计数频率越高,音质越好。通过设置计数器的初始值和周期,可以控制PWM信号的频率和占空比。 2. 根据乐谱将音符的频率转换为对应的震荡周期。音符的周期可以通过时钟频率除以音符频率得到,或者通过音符周期除以时钟周期得到。根据乐谱的要求,设置计数器的初始值和周期,使得计数器在每个音符周期内完成一个完整的循环。 3. 将计数器的值传递给蜂鸣器,使其发出对应频率的声音。通过将计数器的值赋给蜂鸣器的输入端口,可以控制蜂鸣器的振动和声音的产生。 总结:FPGA蜂鸣器播放音乐的方法是通过计数器产生PWM波形,根据乐谱设置震荡周期,并将计数器的值赋给蜂鸣器实现对应频率的声音。这样就可以利用FPGA蜂鸣器播放音乐。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* *2* [蜂鸣器播放音乐 fpga实现](https://blog.csdn.net/xianyudewo/article/details/120525690)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值