Verilog_RTL 설계/Basys_3

[Baysys_3] Stop_Watch

juniha 2025. 7. 9. 19:42

목표

  • 시작 / 정지 토글
  • lap time 표시
  • clear
  • 1/100초 단위 시간 측정
  • 4자리 7세먼트 출력

사용 코드

module stop_watch(
    input clk, reset_p,         // 시스템 클록, 비동기 리셋 (active high)
    input [2:0] btn,            // 버튼 입력: [0] 시작/정지, [1] 랩, [2] 초기화
    output [7:0] seg_7,         // 7세그먼트 출력 제어 신호 (a~g, dp)
    output [3:0] com            // 7세그먼트 공통 단자 제어
);

    // 버튼의 네거티브 엣지(떼는 순간)를 감지하는 신호
    wire btn_start, btn_lap, btn_clear;

    // 각 버튼에 대해 디바운서 및 음엣지 감지 모듈 인스턴스
    button_cntr btn0(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_nedge(btn_start)); // 시작/정지
    button_cntr btn1(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_nedge(btn_lap));   // 랩
    button_cntr btn2(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_nedge(btn_clear)); // 초기화

    // 제어 상태 및 랩 시간 저장용 레지스터
    reg start_stop, lap;               // start_stop: 1이면 작동 중, lap: 1이면 랩 모드
    reg [7:0] lap_sec, lap_csec;       // 랩 시간 저장 (초, 센티초)
    reg [19:0] cnt_sysclk;             // 클록 분주기 (0.01초 타이머용)
    reg [7:0] cnt_csec, cnt_sec;       // 센티초 및 초 카운터

    // 상태 제어: 시작/정지, 랩 저장, 초기화
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) begin
            start_stop = 0; lap = 0;
            lap_sec = 0; lap_csec = 0;
        end
        else if(btn_start)         // 시작/정지 버튼
            start_stop = ~start_stop;
        else if(btn_lap) begin     // 랩 버튼 → 현재 시간 저장 및 lap 모드 토글
            lap_sec = cnt_sec;
            lap_csec = cnt_csec;
            lap = ~lap;
        end
        else if(btn_clear) begin   // 초기화 버튼 → 모든 값 리셋
            start_stop = 0; lap = 0;
            lap_sec = 0; lap_csec = 0;
        end
    end

    // lap 상태를 토글하는 중복 블록 (❗비효율적 - 삭제 권장)
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) lap = 0;
        else if(btn_lap) lap = ~lap;
    end

    // 시간 카운터: 1초를 100등분하여 센티초 단위로 측정
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) begin
            cnt_sysclk = 0;
            cnt_csec = 0;
            cnt_sec = 0;
        end
        else begin
            if(start_stop) begin
                if(cnt_sysclk >= 999_999) begin  // 약 0.01초 경과 (100MHz 기준)
                    cnt_sysclk = 0;

                    if(cnt_csec >= 99) begin     // 센티초 100개 = 1초
                        cnt_csec = 0;
                        if(cnt_sec >= 59)        // 59초까지 측정 후 0으로 초기화
                            cnt_sec = 0;
                        else
                            cnt_sec = cnt_sec + 1;
                    end
                    else begin
                        cnt_csec = cnt_csec + 1;
                    end
                end
                else begin
                    cnt_sysclk = cnt_sysclk + 1;
                end
            end
        end
    end

    // BCD 변환 및 출력 처리
    wire [7:0] csec, sec;            // BCD 변환 결과
    wire [7:0] fnd_sec, fnd_csec;    // FND에 표시할 초/센티초

    assign fnd_sec = lap ? fnd_sec : cnt_sec;
    assign fnd_csec = lap ? lap_csec : cnt_csec;

    // BCD 변환기: 2자리씩 7세그먼트에 표시하기 위한 BCD 변환
    bin_to_dec bcd_sec(.bin(cnt_csec), .bcd(csec)); // 센티초
    bin_to_dec bcd_min(.bin(cnt_sec), .bcd(sec));   // 초

    // 4자리 7세그먼트 디스플레이 출력
    fnd_4digit_cntr fnd(
        .clk(clk),
        .reset_p(reset_p),
        .value({sec, csec}),   // sec: 상위 2자리, csec: 하위 2자리
        .seg_7(seg_7),
        .com(com)
    );
    
endmodule

사용 코드_Segment_display

##7 Segment Display
set_property -dict { PACKAGE_PIN W7   IOSTANDARD LVCMOS33 } [get_ports {seg_7[7]}]
set_property -dict { PACKAGE_PIN W6   IOSTANDARD LVCMOS33 } [get_ports {seg_7[6]}]
set_property -dict { PACKAGE_PIN U8   IOSTANDARD LVCMOS33 } [get_ports {seg_7[5]}]
set_property -dict { PACKAGE_PIN V8   IOSTANDARD LVCMOS33 } [get_ports {seg_7[4]}]
set_property -dict { PACKAGE_PIN U5   IOSTANDARD LVCMOS33 } [get_ports {seg_7[3]}]
set_property -dict { PACKAGE_PIN V5   IOSTANDARD LVCMOS33 } [get_ports {seg_7[2]}]
set_property -dict { PACKAGE_PIN U7   IOSTANDARD LVCMOS33 } [get_ports {seg_7[1]}]

set_property -dict { PACKAGE_PIN V7   IOSTANDARD LVCMOS33 } [get_ports seg_7[0]]

set_property -dict { PACKAGE_PIN U2   IOSTANDARD LVCMOS33 } [get_ports {com[0]}]
set_property -dict { PACKAGE_PIN U4   IOSTANDARD LVCMOS33 } [get_ports {com[1]}]
set_property -dict { PACKAGE_PIN V4   IOSTANDARD LVCMOS33 } [get_ports {com[2]}]
set_property -dict { PACKAGE_PIN W4   IOSTANDARD LVCMOS33 } [get_ports {com[3]}]

사용 코드_Button

##Buttons
set_property -dict { PACKAGE_PIN U18   IOSTANDARD LVCMOS33 } [get_ports reset_p]
set_property -dict { PACKAGE_PIN T18   IOSTANDARD LVCMOS33 } [get_ports btn[0]]
set_property -dict { PACKAGE_PIN W19   IOSTANDARD LVCMOS33 } [get_ports btn[1]]
set_property -dict { PACKAGE_PIN T17   IOSTANDARD LVCMOS33 } [get_ports btn[2]]

 

동작 영상