«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
관리 메뉴

printf("ho_tari\n");

9일차 본문

2025.07.10

 

buzzer

 

buzzer_top.v

`timescale 1ns / 1ps

module top(
    input clk,
    input reset,
    input btnL,
    input btnR,
    output buzzer
);

    wire clean_btnL, clean_btnR;
    wire buzzer_L, buzzer_R;

    // 버튼 디바운스
    button_debounce dbL (
        .i_clk(clk),
        .i_reset(reset),
        .i_btn(btnL),
        .o_btn_clean(clean_btnL)
    );

    button_debounce dbR (
        .i_clk(clk),
        .i_reset(reset),
        .i_btn(btnR),
        .o_btn_clean(clean_btnR)
    );

    // 파워 온 시퀀스 (btnL)
    power_on_buzzer u_power (
        .clk(clk),
        .reset(reset),
        .btnL(clean_btnL),
        .buzzer_L(buzzer_L)
    );

    // 오픈 시퀀스 (btnR)
    open_buzzer u_open (
        .clk(clk),
        .reset(reset),
        .btnR(clean_btnR),
        .buzzer_R(buzzer_R)
    );

    assign buzzer = buzzer_L | buzzer_R;

endmodule

power_on_buzzer.v

`timescale 1ns / 1ps

module power_on_buzzer(
    input clk,
    input reset,
    input btnL,
    output reg buzzer_L
);

    parameter CNT_70MS = 23'd7000000;
    parameter CNT_3S   = 29'd300000000;

    parameter HALF_1K = 17'd50000;
    parameter HALF_2K = 17'd25000;
    parameter HALF_3K = 17'd16667;
    parameter HALF_4K = 17'd12500;

    reg btnL_d1, btnL_d2;
    wire btnL_edge = btnL_d1 & ~btnL_d2;

    always @(posedge clk) begin
        btnL_d1 <= btnL;
        btnL_d2 <= btnL_d1;
    end

    reg run = 0;
    reg [2:0] step = 0;
    reg [28:0] dur_cnt = 0;
    reg [17:0] wave_cnt = 0;
    reg [17:0] half_cycle = 0;

    always @(*) begin
        case (step)
            0: half_cycle = HALF_1K;
            1: half_cycle = HALF_2K;
            2: half_cycle = HALF_3K;
            3: half_cycle = HALF_4K;
            default: half_cycle = 0;
        endcase
    end

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            run <= 0; step <= 0; dur_cnt <= 0; wave_cnt <= 0; buzzer_L <= 0;
        end else begin
            if (btnL_edge) run <= ~run;
            if (!run) begin
                step <= 0; dur_cnt <= 0; wave_cnt <= 0; buzzer_L <= 0;
            end else begin
                if ((step < 4 && dur_cnt >= CNT_70MS) || (step == 4 && dur_cnt >= CNT_3S)) begin
                    dur_cnt <= 0;
                    step <= (step == 4) ? 0 : step + 1;
                end else begin
                    dur_cnt <= dur_cnt + 1;
                end

                if (half_cycle != 0) begin
                    if (wave_cnt >= half_cycle) begin
                        wave_cnt <= 0;
                        buzzer_L <= ~buzzer_L;
                    end else wave_cnt <= wave_cnt + 1;
                end else begin
                    buzzer_L <= 0;
                    wave_cnt <= 0;
                end
            end
        end
    end

endmodule

open_buzzer.v

`timescale 1ns / 1ps

module open_buzzer(
    input clk,
    input reset,
    input btnR,
    output reg buzzer_R
);

    parameter CNT_70MS = 23'd7000000;
    parameter CNT_3S   = 29'd300000000;

    parameter HALF_261 = 18'd192000;
    parameter HALF_329 = 18'd152000;
    parameter HALF_392 = 18'd128000;
    parameter HALF_554 = 18'd90000;

    reg btnR_d1, btnR_d2;
    wire btnR_edge = btnR_d1 & ~btnR_d2;

    always @(posedge clk) begin
        btnR_d1 <= btnR;
        btnR_d2 <= btnR_d1;
    end

    reg run = 0;
    reg [2:0] step = 0;
    reg [28:0] dur_cnt = 0;
    reg [17:0] wave_cnt = 0;
    reg [17:0] half_cycle = 0;

    always @(*) begin
        case (step)
            0: half_cycle = HALF_261;
            1: half_cycle = HALF_329;
            2: half_cycle = HALF_392;
            3: half_cycle = HALF_554;
            default: half_cycle = 0;
        endcase
    end

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            run <= 0; step <= 0; dur_cnt <= 0; wave_cnt <= 0; buzzer_R <= 0;
        end else begin
            if (btnR_edge) run <= ~run;
            if (!run) begin
                step <= 0; dur_cnt <= 0; wave_cnt <= 0; buzzer_R <= 0;
            end else begin
                if ((step < 4 && dur_cnt >= CNT_70MS) || (step == 4 && dur_cnt >= CNT_3S)) begin
                    dur_cnt <= 0;
                    step <= (step == 4) ? 0 : step + 1;
                end else begin
                    dur_cnt <= dur_cnt + 1;
                end

                if (half_cycle != 0) begin
                    if (wave_cnt >= half_cycle) begin
                        wave_cnt <= 0;
                        buzzer_R <= ~buzzer_R;
                    end else wave_cnt <= wave_cnt + 1;
                end else begin
                    buzzer_R <= 0;
                    wave_cnt <= 0;
                end
            end
        end
    end

endmodule

button_debounce.v

`timescale 1ns / 1ps

module button_debounce #(parameter DEBOUNCE_LIMIT = 20'd999_999) (
    input      i_clk,
    input      i_reset,
    input      i_btn,
    output    reg  o_btn_clean  
);
    reg [19:0] count;
    reg btn_state;
    reg btn_clean;

    always @(posedge i_clk, posedge i_reset) begin
        if (i_reset) begin
            count <= 0;
            btn_state <= 0;
            o_btn_clean <= 0;
        end else if (i_btn == btn_state) begin
            count <= 0;
        end else begin
            if (count < DEBOUNCE_LIMIT)
                count <= count + 1;
            else begin
                btn_state <= i_btn;
                o_btn_clean <= i_btn;
                count <= 0;  // 리셋하면 다음 변경을 다시 감지할 수 있음
            end
        end
    end
    
endmodule

'(Telechips) AI 시스템 반도체 SW 개발자 교육 > Verilog HDL' 카테고리의 다른 글

12일차  (0) 2025.07.16
10일차  (0) 2025.07.14
8일차  (0) 2025.07.09
6일차  (0) 2025.07.07
4일차  (0) 2025.07.04