본문 바로가기
# Semiconductor/- Semicon Academy

[Harman 세미콘 아카데미] 54일차 - Verilog(Digital Watch : time setting, set fix, set mode)

by Graffitio 2023. 9. 11.
[Harman 세미콘 아카데미] 54일차 - Verilog(Digital Watch : time setting, set fix, set mode)
728x90
반응형
[Digital Watch 만들기]

 

이제까지 만들어놓은 모듈 라이브러리를 활용하여 디지털 시계를 구현해보도록 하자.

 


 

[Time Setting]

 

📌 Block Diagram

block diagram

디지털 시계의 기능 중 하나인, 시간 설정 기능을 구현해보도록 하자.

시작은 00min : 00sec이며, 시간은 back ground에서 계속 흘러가고, 

설정은 흘러가는 시간 위에 적용시킬 수 있도록 설계하였다.

 


 

📌 Code & Operation

 

Clock Library

 

// usec clock
module clock_usec(
    input clk, reset_p,
    input enable,
    output clk_usec
    );
    
    // 125개 카운트하면 1us
    reg [6:0] cnt_8nsec;
    wire cp_usec; // cp : clock pulse
    
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) cnt_8nsec = 0; // reset이 들어오면 cnt = 0
            else if(cnt_8nsec >= 124) cnt_8nsec = 0; // 0부터 124번까지 카운트하면 다시 0으로
            else cnt_8nsec = cnt_8nsec + 1;
     end
    
    assign cp_usec = cnt_8nsec < 63 ? 0 : 1; // 0~62 : 0, 63~124 : 1 
    
    // 비정규 clock이므로 동기화가 필요하다.
    edge_detector_n edg(.clk(clk), .cp_in(cp_usec), .rst(reset_p), .n_edge(clk_usec)); /// 안 쓰는 출력은 빼버리면 된다.
    
endmodule


// min clock
module clock_min(
    input clk, clk_sec, reset_p,
    output clk_min
    );

    // 60개 카운트하면 1s
    reg [5:0] cnt_sec;
    reg cp_min; // cp : clock pulse
    
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) cnt_sec = 0; // reset이 들어오면 cnt = 0
        else if(clk_sec) begin
            if (cnt_sec >= 29) begin
                cnt_sec = 0; // 0부터 번까지 카운트하면 다시 0으로
                cp_min = ~cp_min;
            end
            else cnt_sec = cnt_sec + 1;
        end
    end // 이렇게 카운트가 짝수일 경우, 위와 같이 코딩하여 1bit 줄일 수 있다.
    
    // 비정규 clock이므로 동기화가 필요하다.
    edge_detector_n edg_min(.clk(clk), .cp_in(cp_min), .rst(reset_p), .n_edge(clk_min)); /// 안 쓰는 출력은 빼버리면 된다.
    
endmodule


// 1000분주 clock
module clock_div_1000(
    input clk, clk_source, reset_p,
    output clk_div_1000
    );

    reg [8:0] cnt_clk_source;
    reg cp_div_1000; // cp : clock pulse
    
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) cnt_clk_source = 0; // reset이 들어오면 cnt = 0
        else if(clk_source) begin
            if (cnt_clk_source >= 499) begin
//            if (cnt_clk_source >= 999) begin
                cnt_clk_source = 0; // 0부터 499번까지 카운트하면 다시 0으로
                cp_div_1000 = ~cp_div_1000;
            end
            else cnt_clk_source = cnt_clk_source + 1;
        end
    end // 이렇게 카운트가 짝수일 경우, 위와 같이 코딩하여 1bit 줄일 수 있다.
    
    // 비정규 clock이므로 동기화가 필요하다.
    edge_detector_n edg_div_1000(.clk(clk), .cp_in(cp_div_1000), .rst(reset_p), .n_edge(clk_div_1000)); /// 안 쓰는 출력은 빼버리면 된다.
endmodule

 

 

Counter

 

// 60bit_Counter
module counter_dec_60(
    input clk, reset_p,
    input clk_time,
    output reg [3:0] dec1, dec10
    );
    
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) begin
            dec1 = 0;
            dec10 = 0;
        end
        else if(clk_time) begin
            if(dec1 >= 9) begin 
                dec1 <= 0;
                if(dec10 >= 5) dec10 = 0;
                else dec10 <= dec10 + 1;
            end
            else dec1 <= dec1 + 1;
        end
    end
endmodule

 

 

Btn Controller

 

module button_cntr(
    input clk, reset_p,
    input btn,
    output btn_pe, btn_ne
    );
    
    // DFF를 위한 분주기
    reg [16:0] clk_div = 0; // 이렇게 = 0 해놓으면 시뮬레이션에서 자동으로 0으로 초기화된다.
                            // 보드에서 쓸 때는 시스템적으로 0으로 초기화
    always @(posedge clk) clk_div = clk_div + 1;
    
    // Debounce
    wire debounced_btn;
    D_flip_flop_n debnc(.d(btn), .clk(clk_div[16]), .rst(reset_p), .q(debounced_btn)); // 바운싱 제거용 DFF
    
    // synchronization(Edge Detecting)
    edge_detector_n edg(.clk(clk), .cp_in(debounced_btn), .rst(reset_p), .p_edge(btn_pe), .n_edge(btn_ne)); // Edge Detector
    // p_edge(btn_pe) : 버튼을 눌렀을 때 동작
    // n_edge(btn_ne) : 버튼을 눌렀다 뗄 때 동작
    // 둘 중에 필요한 것만 골라서 쓰면 된다.

endmodule

 

 

Watch Top

 

module Watch_Top(
    input clk, reset_p,
    input [3:0] btn,
    output [3:0] com,
    output [7:0] seg_7
    );
    
    // Clock Library
    wire clk_usec, clk_msec, clk_sec;
    clock_usec usec_clk(.clk(clk), .reset_p(reset_p), .clk_usec(clk_usec));
    clock_div_1000 msec_clk(.clk(clk), .clk_source(clk_usec), .reset_p(reset_p), .clk_div_1000(clk_msec));
    clock_div_1000 sec_clk(.clk(clk), .clk_source(clk_msec), .reset_p(reset_p), .clk_div_1000(clk_sec));
    clock_min min_clk(.clk(clk), .clk_sec(clk_sec), .reset_p(reset_p), .clk_min(clk_min)); 
    
    // btn
    button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pe(incsec)); // sec+
    button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pe(incmin)); // min+
    
    // Time set
    wire incsec, incmin;
    wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    assign comp_sec = |{incsec, clk_sec}; // 시간과 up_sec 버튼 입력을 OR 연산(동시에 받음)하여 넣어주면,
    assign comp_min = |{incmin, clk_min}; // 시간은 시간대로 버튼입력은 버튼입력대로 각각 따로 받을 수 있다.
    counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(comp_sec), .dec1(sec1_set), .dec10(sec10_set)); // sec up_counter
    wire [3:0] min1_set, min10_set;
    counter_dec_60 up_min(.clk(clk), .reset_p(reset_p), .clk_time(comp_min), .dec1(min1_set), .dec10(min10_set)); // min up_counter
    
    // Setting Time for FND
    reg [15:0] watch_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) watch_time = 0;
        else watch_time = {min10_set, min1_set, sec10_set, sec1_set};
    end
    
    // 출력을 위한 FND Controller
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(watch_time), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
    
endmodule

 

 

 

 

 

 

module Watch_Top(
    input clk, reset_p,
    input [3:0] btn,
    output [3:0] com,
    output [7:0] seg_7
    );
    
    // Clock Library
    wire clk_usec, clk_msec, clk_sec;
    clock_usec usec_clk(.clk(clk), .reset_p(reset_p), .clk_usec(clk_usec));
    clock_div_1000 msec_clk(.clk(clk), .clk_source(clk_usec), .reset_p(reset_p), .clk_div_1000(clk_msec));
    clock_div_1000 sec_clk(.clk(clk), .clk_source(clk_msec), .reset_p(reset_p), .clk_div_1000(clk_sec));
    clock_min min_clk(.clk(clk), .clk_sec(clk_sec), .reset_p(reset_p), .clk_min(clk_min)); 
    
    // btn
    wire fix_sec, fix_min;
    assign fix_sec = btn_fix ? btn[1] : 0 ;
    assign fix_min = btn_fix ? btn[2] : 0 ;
    button_cntr btn_cntr_fix(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(debounced_fix)); // 버튼눌러도 시간 안 바뀌게 고정
    t_flip_flop_p tff_fix(.clk(clk), .rst(reset_p), .t(debounced_fix), .q(btn_fix)); 
    button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(fix_sec), .btn_pe(incsec)); // sec+
    button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(fix_min), .btn_pe(incmin)); // min+
    
    // Time set
    wire incsec, incmin;
    wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    assign comp_sec = |{incsec, clk_sec}; // 시간과 up_sec 버튼 입력을 OR 연산(동시에 받음)하여 넣어주면,
    assign comp_min = |{incmin, clk_min}; // 시간은 시간대로 버튼입력은 버튼입력대로 각각 따로 받을 수 있다.
    counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(comp_sec), .dec1(sec1_set), .dec10(sec10_set)); // sec up_counter
    wire [3:0] min1_set, min10_set;
    counter_dec_60 up_min(.clk(clk), .reset_p(reset_p), .clk_time(comp_min), .dec1(min1_set), .dec10(min10_set)); // min up_counter
    
    // Setting Time for FND
    reg [15:0] watch_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) watch_time = 0;
        else watch_time = {min10_set, min1_set, sec10_set, sec1_set};
    end
    
    // 출력을 위한 FND Controller
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(watch_time), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
    
endmodule

 


 

[Time Fix 기능]

 

📌 Block Diagram

 

기껏 시간을 맞춰놨는데, 실수로 버튼을 눌러서 다시 셋팅해야하는 불상사가 일어나지 않도록

Time Fix 기능을 추가하여 fix 버튼을 누르면 setting 버튼이 동작하지 않도록 설계하였다.

 


 

📌 Code & Operation

 

module Watch_Top(
    input clk, reset_p,
    input [3:0] btn,
    output [3:0] com,
    output [7:0] seg_7
    );
    
    // Clock Library
    wire clk_usec, clk_msec, clk_sec;
    clock_usec usec_clk(.clk(clk), .reset_p(reset_p), .clk_usec(clk_usec));
    clock_div_1000 msec_clk(.clk(clk), .clk_source(clk_usec), .reset_p(reset_p), .clk_div_1000(clk_msec));
    clock_div_1000 sec_clk(.clk(clk), .clk_source(clk_msec), .reset_p(reset_p), .clk_div_1000(clk_sec));
    clock_min min_clk(.clk(clk), .clk_sec(clk_sec), .reset_p(reset_p), .clk_min(clk_min)); 
    
    // btn
    wire fix_sec, fix_min;
    assign fix_sec = btn_fix ? btn[1] : 0 ; // btn_fix 누르면 btn[]가 동작하고 다시 누르면 0이 입력되도록 Muxing 
    assign fix_min = btn_fix ? btn[2] : 0 ; // 즉, btn_fix 입력에 따라 Setting mode, Fix mode 선택 가능
    button_cntr btn_cntr_fix(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(debounced_fix)); // 버튼눌러도 시간 안 바뀌게 고정
    t_flip_flop_p tff_fix(.clk(clk), .rst(reset_p), .t(debounced_fix), .q(btn_fix)); 
    button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(fix_sec), .btn_pe(incsec)); // sec+
    button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(fix_min), .btn_pe(incmin)); // min+
    
    // Time set
    wire incsec, incmin;
    wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    assign comp_sec = |{incsec, clk_sec}; // 시간과 up_sec 버튼 입력을 OR 연산(동시에 받음)하여 넣어주면,
    assign comp_min = |{incmin, clk_min}; // 시간은 시간대로 버튼입력은 버튼입력대로 각각 따로 받을 수 있다.
    counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(comp_sec), .dec1(sec1_set), .dec10(sec10_set)); // sec up_counter
    wire [3:0] min1_set, min10_set;
    counter_dec_60 up_min(.clk(clk), .reset_p(reset_p), .clk_time(comp_min), .dec1(min1_set), .dec10(min10_set)); // min up_counter
    
    // Setting Time for FND
    reg [15:0] watch_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) watch_time = 0;
        else watch_time = {min10_set, min1_set, sec10_set, sec1_set};
    end
    
    // 출력을 위한 FND Controller
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(watch_time), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
    
endmodule

 


 

[min과 sec가 따로 노는 오류 수정]

 

📌 Error

min/sec async Error

      이전과 같이 코딩하면, sec가 60초가 되어도 min은 clk_min에 맞춰서 따로 동작한다.

      즉, up_sec btn을 5번 눌러서 셋팅하면 65초에 min이 1 증가하는 오류가 발생한다.

 

      위와 같은 오류가 발생한 이유는 sec와 min을 동기화시켜주지 않았기 때문이다. 

      따라서 sec counter에서 60까지 count하면, min_pulse를 발생시켜 min counter에 전달해 줘야 한다.

      또한 min_pulse와 min set button 입력을 OR연산하여(동시에 적용되도록) min counter에 넣어주면

      sec와 min이 연동되고 up_min도 같이 구현할 수 있다.

 


 

📌 Fixed Code & Result

      

sec clock으로 sec, min 둘 다 counting

 

Counter 수정

 

// 60bit_Counter_puler
module counter_dec_60_pul(
    input clk, reset_p,
    input clk_time,
    output reg [3:0] dec1, dec10,
    output reg dec_clk // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
    );
    
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) begin
            dec1 = 0;
            dec10 = 0;
        end
        else if(clk_time) begin
            if(dec1 >= 9) begin 
                dec1 <= 0;
                if(dec10 >= 5) begin
                    dec10 = 0;
                    dec_clk <= 1; // dec10, dec1 = 0, 0 이 되고 이후에 5, 9가 되면서 dec_clk 상승 펄스 발생
                end
                else dec10 <= dec10 + 1;
            end
            else dec1 <= dec1 + 1;
        end
        else dec_clk <= 0;
    end
endmodule

 

 

clk_sec으로 min clock까지 count

 

module Watch_Top(
    input clk, reset_p,
    input [3:0] btn,
    output [3:0] com,
    output [7:0] seg_7
    );
    // 분주기 인스턴스
    wire clk_usec, clk_msec, clk_sec;
    clock_usec usec_clk(.clk(clk), .reset_p(reset_p), .clk_usec(clk_usec));
    clock_div_1000 msec_clk(.clk(clk), .clk_source(clk_usec), .reset_p(reset_p), .clk_div_1000(clk_msec));
    clock_div_1000 sec_clk(.clk(clk), .clk_source(clk_msec), .reset_p(reset_p), .clk_div_1000(clk_sec));
    
    // btn
    wire fix_sec, fix_min;
    assign fix_sec = btn_fix ? btn[1] : 0 ; // btn_fix 누르면 btn[]가 동작하고 다시 누르면 0이 입력되도록 Muxing
    assign fix_min = btn_fix ? btn[2] : 0 ; // 즉, btn_fix 입력에 따라 Setting mode, Fix mode 선택 가능
    button_cntr btn_cntr_fix(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(debounced_fix)); // 버튼눌러도 시간 안 바뀌게 고정
    t_flip_flop_p tff_fix(.clk(clk), .rst(reset_p), .t(debounced_fix), .q(btn_fix)); 
    button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(fix_sec), .btn_pe(incsec)); // sec+
    button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(fix_min), .btn_pe(incmin)); // min+
    
    // Time set
    wire incsec, incmin, min_pulse;
    wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    assign comp_sec = |{incsec, clk_sec}; // 시간과 up_sec 버튼 입력을 OR 연산(동시에 받음)하여 넣어주면,
    assign comp_min = |{incmin, min_pulse};  // 시간은 시간대로 버튼입력은 버튼입력대로 각각 따로 받을 수 있다.
    counter_dec_60_pul up_sec(.clk(clk), .reset_p(reset_p), .clk_time(comp_sec), .dec1(sec1_set), .dec10(sec10_set), .dec_clk(min_pulse)); // sec up_counter
    wire [3:0] min1_set, min10_set;
    counter_dec_60 up_min(.clk(clk), .reset_p(reset_p), .clk_time(comp_min), .dec1(min1_set), .dec10(min10_set)); // min up_counter
    
    // Setting Time for FND
    reg [15:0] watch_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) watch_time = 0;
        else watch_time = {min10_set, min1_set, sec10_set, sec1_set};
    end
    
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(watch_time), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
    
endmodule

up_sec btn을 눌러서 조절해도 잘 동작한다.

 


 

[구조적 모델링은 지양하자.]

 

Verilog에서는 정확성, 유연성, 확장성, 고수준 추상화, 그리고 복잡성 관리 등의 이유와

Gate를 사용하여 만들어도어짜피  MUX밖에 없어서 MUX로 구현하기 때문에

구조적 모델링은 지양하고, 동작적 모델링을 지향한다.

 

📌 Structural Level Modeling Code

 

// 구조적 모델링
// OR 연산 사용
assign comp_sec = |{incsec, clk_sec};
assign comp_min = |{incmin, min_pulse};

 


 

📌 Behavioral Level Modeling Code

 

// 동작적 모델링
assign comp_sec = clk_sec ? 1 : incsec ? 1 : 0 ;
assign comp_min = min_pulse ? 1 : incmin ? 1 : 0 ;

 


 

[Time Setting Mode]

 

📌 Block Diagram

 

Block Diagram

위에서 Fix button을 구현해서 멋대로 셋팅되는 것을 방지했는데,

실제로 우리가 사용하는 디지털 시계는 Setting mode가 존재하고 해당 mode로 들어가서 시간을 setting한다.

그러므로 loadable counter를 활용하여 Setting mode를 구현해보도록 하자.

 


 

📌 Code

 

Counter

 

// 60bit_loadable_up_Counter
module loadable_up_counter_dec_60(
    input clk, reset_p,
    input clk_time, load_enable,
    input [3:0] set_value1, set_value10,
    output reg [3:0] dec1, dec10,
    );
    
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) begin
            dec1 = 0;
            dec10 = 0;
        end
        else if (load_enable) begin
            dec1 = set_value1;
            dec10 = set_value10;
        end
        else if(clk_time) begin
            if(dec1 >= 9) begin 
                dec1 <= 0;
                if(dec10 >= 5) dec10 = 0;
                else dec10 <= dec10 + 1;
            end
            else dec1 <= dec1 + 1;
        end
    end
endmodule

 

 

Wach_top

 

module Watch_Top(
    input clk, reset_p,
    input [3:0] btn,
    output [3:0] com,
    output [7:0] seg_7
    );
    // 분주기 인스턴스
    wire clk_usec, clk_msec, clk_sec;
    wire upcount_sec;
    clock_usec usec_clk(.clk(clk), .reset_p(reset_p), .clk_usec(clk_usec));
    clock_div_1000 msec_clk(.clk(clk), .clk_source(clk_usec), .reset_p(reset_p), .clk_div_1000(clk_msec));
    clock_div_1000 sec_clk(.clk(clk), .clk_source(clk_msec), .reset_p(reset_p), .clk_div_1000(clk_sec));
    clock_min min_clk(.clk(clk), .clk_sec(upcount_sec), .reset_p(reset_p), .clk_min(clk_min)); 
    
    // set mode select
    wire set_mode;
    assign upcount_sec = set_mode ? incsec : clk_sec;
    
    // btn
    button_cntr btn_cntr_setmode(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(btn_set_pe)); // 버튼눌러도 시간 안 바뀌게 고정
    t_flip_flop_p tff_setmode(.clk(clk), .rst(reset_p), .t(btn_set_pe), .q(set_mode)); 
    button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pe(incsec)); // sec+
    button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pe(incmin)); // min+

    // Time set
    wire [3:0] sec1, sec10, min1, min10;
    wire [3:0] sec1_set, sec10_set, min1_set, min10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    
    // time count 
    loadable_up_counter_dec_60 cnter_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_sec), .load_enable(btn_set_pe), 
                                           .set_value1(sec1_set), .set_value10(sec10_set), .dec1(sec1), .dec10(sec10)); // sec up_counter
    loadable_up_counter_dec_60 cnter_min(.clk(clk), .reset_p(reset_p), .clk_time(clk_min), .load_enable(btn_set_pe), 
                                           .set_value1(min1_set), .set_value10(min10_set), .dec1(min1), .dec10(min10)); // min up_counter
	
    // time set
    loadable_up_counter_dec_60 set_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .load_enable(btn_set_pe),
                                       .set_value1(sec1), .set_value10(sec10), .dec1(sec1_set), .dec10(sec10_set)); // sec up_set
    loadable_up_counter_dec_60 set_min(.clk(clk), .reset_p(reset_p), .clk_time(incmin), .load_enable(btn_set_pe),
                                       .set_value1(min1), .set_value10(min10), .dec1(min1_set), .dec10(min10_set)); // min up_set

	// cur_time / set_time 
    wire [15:0] cur_time, set_time;
    assign cur_time = {min10, min1, sec10, sec1};
    assign set_time = {min10_set, min1_set, sec10_set, sec1_set};
    
    wire [15:0] value;
    assign value = set_mode ? set_time : cur_time;
    
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
    
endmodule

set mode로 전환하면 counter값을 불러와 그 것을 기준으로 time setting되고,

setting된 time을 기준으로 count를 시작하게 된다.

 


 

 

 

728x90
반응형