FPGA—蜂鸣器播放《两只老虎》

一、蜂鸣器

1.蜂鸣器按照工作原理可分为:压电式蜂鸣器和电磁式蜂鸣器。

2.按照音源可分为:有源蜂鸣器和无源蜂鸣器。

有源蜂鸣器:内部有振荡源,直接通以直流电即可发出声音。

无源蜂鸣器:内部无振荡源,需要通以方波、PWM信号才能发出声音。

二、乐谱知识

这个实验我主要是用一首儿歌《两只老虎》的乐谱来做实验

FPGA—蜂鸣器播放《两只老虎》_第1张图片  图一:音频表 FPGA—蜂鸣器播放《两只老虎》_第2张图片 图二:两只老虎乐谱

 三、波形图

FPGA—蜂鸣器播放《两只老虎》_第3张图片 图三:波形图

 四、核心代码

4.1Verilog代码

module buzzer(
    input        clk,
    input        rst_n,

    output       beep
);
    parameter   L1 = 190800,
                L2 = 170050,
                L3 = 151500,
                L4 = 143250,
                L5 = 127550,
                L6 = 113600,
                L7 = 101200;
    parameter   DELAY = 180;

    reg [17:0]  num;

    reg [7:0]   cnt_d;
    wire        add_cntd;
    wire        end_cntd;

    reg [17:0]  cnt_p;
    wire        add_cntp;
    wire        end_cntp;

    reg  [5:0]  cnt_b;
    wire        add_cntb;
    wire        end_cntb;

//cnt_p
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt_p <= 'd0;
    end
    else if(add_cntp) begin
        if(end_cntp)begin 
            cnt_p <= 'd0;
        end
        else begin
            cnt_p <= cnt_p +1'b1;
        end 
    end
end
assign add_cntp = 1'b1;
assign end_cntp = add_cntp && cnt_p == num - 1;


//cnt_d
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt_d <= 'd0;
    end 
    else if(add_cntd) begin
        if(end_cntd)begin 
            cnt_d <= 'd0;
        end
        else begin
            cnt_d <= cnt_d +1'b1;
        end 
    end
end
assign add_cntd = end_cntp;
assign end_cntd = add_cntd && cnt_d == DELAY - 1;


//cnt_b
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt_b <= 'd0;
    end 
    else if(add_cntb) begin
        if(end_cntb)begin 
            cnt_b <= 'd0;
        end
        else begin
            cnt_b <= cnt_b + 1'b1;
        end 
    end
end

assign add_cntb = end_cntd;
assign end_cntb = add_cntb && cnt_b == 32 - 1;

always@(*)begin
    case(cnt_b)
        0:num = L1;
        1:num = L2;
        2:num = L3;
        3:num = L1;
        4:num = L1;
        5:num = L2;
        6:num = L3;
        7:num = L1;
        8:num = L3;
        9:num = L4;
        10:num = L5;
        11:num = L3;
        12:num = L4;
        13:num = L5;
        14:num = L5;
        15:num = L6;
        16:num = L5;
        17:num = L4;
        18:num = L3;
        19:num = L1;
        20:num = L5;
        21:num = L6;
        22:num = L5;
        23:num = L4;
        24:num = L3;
        25:num = L1;
        26:num = L2;
        27:num = L5;
        28:num = L1;
        29:num = L2;
        30:num = L5;
        31:num = L1;
        default:num = L1;
    endcase
end 
assign beep = (cnt_p < (num>>1))?  1'b1 : 1'b0;
endmodule

 4.2tb仿真代码

`timescale 1ns/1ps
module buzzer_tb();
    reg   clk;
    reg   rst_n;
    wire  beep;
    parameter   L1 = 50,
                L2 = 100,
                L3 = 150,
                L4 = 200,
                L5 = 250,
                L6 = 300,
                L7 = 350;

    parameter 	CYCLE   = 20;

 buzzer  u_buzzer(
    .clk    (tb_clk),
    .rst_n  (tb_rst_n),
    .beep   (tb_beep)
);
initial begin
        clk = 1'b1;
        rst_n = 1'b1;
        #(CYCLE);
        rst_n = 1'b0;
        #(CYCLE*2);
        rst_n = 1'b1;
end
        always #10 clk = ~clk;

endmodule

你可能感兴趣的:(fpga开发)