FPGA project : beep

文章描述了一个使用Verilog语言编写的音频信号发生器模块,包括定时器和音符频率控制逻辑,用于生成不同频率和占空比的音频信号。

module beep 
#(
    parameter MAX_500MS = 25'd25_000_000 ,
              MAX_NOTE_7=  3'd7           ,
              FRE_262   = 23'd190839     ,
              FRE_294   = 23'd170068     ,
              FRE_330   = 23'd151515     ,
              FRE_349   = 23'd143266     ,
              FRE_392   = 23'd127551     ,
              FRE_440   = 23'd113636     ,
              FRE_494   = 23'd101214     ,
              DUT_262   = 22'd95419      ,
              DUT_294   = 22'd85034      ,
              DUT_330   = 22'd75757      ,
              DUT_349   = 22'd71633      ,
              DUT_392   = 22'd63775      ,
              DUT_440   = 22'd56818      ,
              DUT_494   = 22'd50607     
)(
    input               wire    sys_clk     ,
    input               wire    sys_rst_n   ,

    output              reg     beep    
);

    // reg signal define
    reg     [24:00]     cnt_500ms ;
    reg     [02:00]     cnt_7     ;     
    reg     [22:00]     fre_num   ; // 音符频率 计数最大值 锁存器 组合逻辑赋值
    reg     [22:00]     cnt_f     ; // 音符频率 计数器 不同音符 所计满次数不同。随着音符而变换。
    reg     [21:00]     duty_cycle; // 占空比锁存器 ; 组合逻辑

    // cnt_500ms
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_500ms <= 0 ;
        end else begin
            if(cnt_500ms == (MAX_500MS - 1'b1)) begin
                cnt_500ms <= 0 ;
            end else begin
                cnt_500ms <= cnt_500ms + 1'b1 ;
            end
        end
    end
    // cnt_7 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_7 <= 0 ;
        end else begin
            if(cnt_500ms == (MAX_500MS - 1'b1)) begin
                if(cnt_7 == MAX_NOTE_7 - 1'b1) begin
                    cnt_7 <= 0 ;
                end else begin
                    cnt_7 <= cnt_7 + 1'b1 ;
                end
            end else begin
                cnt_7 <= cnt_7 ;
            end
        end
    end
    // fre_num
    always @(*) begin
        case (cnt_7)
            0 : begin
                fre_num <= FRE_262 ;
            end
            1 : begin
                fre_num <= FRE_294 ;
            end
            2 : begin
                fre_num <= FRE_330 ;
            end
            3 : begin
                fre_num <= FRE_349 ;
            end
            4 : begin
                fre_num <= FRE_392 ;
            end
            5 : begin
                fre_num <= FRE_440 ;
            end
            6 : begin
                fre_num <= FRE_494 ;
            end
            default: fre_num <= FRE_494 ;
        endcase
    end
    // cnt_f
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_f <= 0 ;
        end else begin
            if(cnt_f == (fre_num - 1'b1) || (cnt_500ms == MAX_500MS - 1'b1)) begin
                cnt_f <= 0 ; 
            end else begin
                cnt_f <= cnt_f + 1'b1 ;
            end
        end
    end
    // duty_cycle
    always @(*) begin
        case (cnt_7)
            0 : begin
                duty_cycle <= DUT_262 ;
            end
            1 : begin
                duty_cycle <= DUT_294 ;
            end
            2 : begin
                duty_cycle <= DUT_330 ;
            end
            3 : begin
                duty_cycle <= DUT_349 ;
            end
            4 : begin
                duty_cycle <= DUT_392 ;
            end
            5 : begin
                duty_cycle <= DUT_440 ;
            end
            6 : begin
                duty_cycle <= DUT_494 ;
            end
            default: duty_cycle <= DUT_494 ;
        endcase
    end

    // beep 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            beep <= 1'b1 ;
        end else begin
            if(cnt_f >= duty_cycle) begin
                beep <= 1'b0 ;
            end else begin
                beep <= 1'b1 ;
            end
        end
    end
endmodule
`timescale 1ns/1ns
module test();
    reg                      sys_clk    ;
    reg                      sys_rst_n  ;
    wire                     beep       ;

// Instantiation
beep 
#(
    .MAX_500MS      ( 1000 ),
    .MAX_NOTE_7     ( 7 ),
    .FRE_262        ( 70 ),
    .FRE_294        ( 60 ),
    .FRE_330        ( 50 ),
    .FRE_349        ( 40 ),
    .FRE_392        ( 30 ),
    .FRE_440        ( 20 ),
    .FRE_494        ( 10 ),
    .DUT_262        ( 35 ),
    .DUT_294        ( 30 ),
    .DUT_330        ( 25 ),
    .DUT_349        ( 20 ),
    .DUT_392        ( 15 ),
    .DUT_440        ( 10 ),
    .DUT_494        ( 5  )    
)
beep_insert(
    .sys_clk        ( sys_clk   ),
    .sys_rst_n      ( sys_rst_n ),

    .beep           ( beep      )    
);
    parameter CYCLE = 20 ;

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( CYCLE * 1000 ) ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值