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

[Harman 세미콘 아카데미] 52일차 - Verilog(Cook Timer - Button controller, Time setting, Down counter, Timeout, Alarm)

by Graffitio 2023. 9. 7.
[Harman 세미콘 아카데미] 52일차 - Verilog(Cook Timer - Button controller, Time setting, Down counter, Timeout, Alarm)
728x90
반응형
Full Code는 맨 아래에~

 


 

[Button controller]

 

📌 Button controller module

 

        자주 사용하는 기능이니까 모듈로 만들어 버리자.

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

 

tip) 오류가 있는지 간단하게 체크하는 법

       해당 모듈을 Top으로 놓고 시뮬레이션돌려보면 된다.

       문법에 오류가 있다면, 시뮬레이션 안 열림.

       구문오류는 이걸로 검증 안 됨.

 


 

[Time Setting]

 

📌 Time Setting

 

       버튼의 입력에 따라 시간을 셋팅할 수 있도록 구현해볼 것이다.

 


 

📌 Time Setting Code

 

module cook_timer(
    input clk, reset_p,
    input [2:0] btn,
    output [3:0] com,
    output [7:0] seg_7
    );
    
    // button 
    wire start, incsec, incmin;
    button_cntr btn_start_stop(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(start)); // start/stop
    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+
    // 풀다운 저항을 사용하여 버튼 회로를 구성하였으므로 pose_edge 사용
    // 풀다운이므로 0(Low)이 계속 입력되고 있다가 버튼누르면 1(High)이 걸리게 된다. 따라서 Pose_edge 사용
    // pose_edge : 버튼 누른 순간 동작 - 풀다운과 연결
    // neg_edge : 버튼 눌렀다 떼는 순간 동작 - 풀업과 연결
    
    // Time set
    wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .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(incmin), .dec1(min1_set), .dec10(min10_set)); // min up_counter
    
    reg [15:0] set_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) set_time = 0;
        else set_time = {min10_set, min1_set, sec10_set, sec1_set};
    end
    
    wire [15:0] value;
    assign value = set_time;
    
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.

endmodule

min. sec 각각 Setting 가능

 

 Edge_Detector에 대해 궁금하다면?

아래 링크 참조

 

[Harman 세미콘 아카데미] 9일차 - Counter 활용(parameter, bin_to_dec, TFF, edge_detector, debouncing)

[Schematic] [parameter] 이전에 4bit, 12bit counter를 만들었는데, parameter를 활용하면 굳이 bit마다 모듈을 만들어줄 필요가 없다. [Bin_to_Dec] 아무래도 알파벳으로 카운팅되면, 가독성이 떨어질 수 밖에 없

rangvest.tistory.com

 


 

[Down Counter]

 

📌 Down Counter

       Time Setting에서 입력된 값을 받아 Down Count하는 기능을 구현해보자.

 

// Loadable_60bit_Down_Counter
module loadable_down_counter_dec_60(
    input clk, reset_p,
    input clk_time,
    input load_enable, // user가 입력한 값을 받아오는 기능 추가 
    input [3:0] set_value1, set_value10, // 입력한 값
    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;
            dec_clk <= 0;
        end
        // load_enable = 1이면, 입력된 값을 받아온다.
        else if(load_enable == 1) begin
            dec1 <= set_value1;
            dec10 <= set_value10;
        end
        else if(clk_time) begin // 카운팅에 적용한 clk_time = high가 되면 카운팅 시작
            if(dec1 == 0) begin
                dec1 <= 9;
                if(dec10 == 0) begin // 우리는 min과 sec 둘 다 구현하는 것이므로, min down counter에 신호를 넣어줘야 된다. 
                    dec10 <= 5;
                    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

 


 

📌 Simulation

 

Setting

 

    ① clk, clk_time : 100ns

    ② reset_p : 1주고 load_enable : 0주고 100ns 돌림 // 수동으로 리셋해줘야됨

    ③ reset_p : 0주고 load_enable : 1주고 100ns 돌림 // load_enable 활성화해서 setting된 값을 받아옴.

    ④ load_enable : 0주고 5000ns 돌림

 

dec1(1의 자리)은 9~0까지 Down count

dec10(10의 자리)은 5~0까지 Down count

sec10, sec1 둘 다 0이 되면, dec_clk 펄스 발생(부분)

 


 

📌 Simulation(by Testbench) 

 

Test_bench Code

 

module tb_loadable_down_counter_dec_60(); // tb는 입출력이 없다.

	// 입력은 다 reg
	// 출력은 다 wire
    reg clk, reset_p;
    reg clk_time;
    reg load_enable; // user가 입력한 값을 받아오는 기능 추가 
    reg [3:0] set_value1, set_value10; // 입력한 값
    wire [3:0] dec1, dec10;
    wire dec_clk; // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수

    loadable_down_counter_dec_60 DUT(.clk(clk), .reset_p(reset_p), .clk_time(clk_time), .load_enable(load_enable),
                                     .set_value1(set_value1), .set_value10(set_value10), .dec1(dec1), .dec10(dec10), .dec_clk(dec_clk));
                               
     // 입력값 초기화
    initial begin
        clk = 0;
        reset_p = 1;
        clk_time = 0;
        load_enable = 1;
        set_value1 = 5; set_value10 = 3;
    end
    
    // clock 생성
    always #5 clk = ~clk; // 10ns짜리 clock, always문은 Sensitivity list 없으면 무한 반복
    
    // clock에 따라 테스트값 입력
    initial begin
        #10; reset_p = 0; #10;
        load_enable = 0; #10;
        #980;
        clk_time = 1; #10
        clk_time = 0; #990; // 1000ns동안 1클락의 펄스가 들어온다.
        clk_time = 1; #10
        clk_time = 0; #990; // 즉, 1ms마다 down count된다.
        clk_time = 1; #10
        clk_time = 0; #990;
        clk_time = 1; #10
        clk_time = 0; #990;
        clk_time = 1; #10
        clk_time = 0; #990;
        $stop;
    end
    
endmodule

 

✅ for문을 활용하여 좀 더 간단하게 작성할 수도 있다.

// 1000ns동안 1클락의 펄스가 들어온다.
for(integer i = 0 ; i < 40 ; i = i+1) begin  // 즉, 1ms마다 down count된다.
	if(i < 40) begin
		clk_time = 1; #10;
		clk_time = 0; #990;
	end
end

 

✅ $display 함수를 사용하면,

      console창에서 출력되도록 설정할 수도 있다.

for(integer i = 0 ; i < 40 ; i = i+1) begin  // 즉, 1ms마다 down count된다.
	if(i < 40) begin
		clk_time = 1; #10;
		clk_time = 0; #990;
		$display("%d%d", dec10, dec1);
	end
end

Console Display

 

Testbench work flow

      ① DUT Instsnce

      ② 변수선언

      ③ 입력값 초기화

      ④ clock 생성

      ⑤ clock에 따라 테스트 값 입력

      ⑥ 시뮬레이션

 

cf) RTL Workflow(작업 순서)

      ① Circuit Design(회로설계)

      ② Simulation(시뮬레이션)

      ③ Circuit Synthesis(회로 합성)

      ④ Implementation (Circuit Realization, 회로 구현)

      Bitstream Generation(비트스트림생성)

      Deployment on Board(보드에 올려서)

      ⑦ Testing on Board(보드에서 테스트)

 

✅ TestBench에 대해 더 궁금하다면?

 

        아래 링크 참조

 

[Harman 세미콘 아카데미] 2일차 - 보수체계, Testbench, Delay

[개요] 1. 논리 회로 - Combinational Logic (조합 논리 회로) : input이 주어지면, output이 고정된다. output이 다음 output에 영향을 주지 못 함. - Sequential Logic (순차 논리 회로) : 이전 output이 다음 output에 영

rangvest.tistory.com

 

Result

 

Run all

Simulation하고 Run을 눌러줘야 전부 다 출력된다.

 

clk_time 펄스마다 down count되는 것을 확인할 수 있다.

 

for문 적용(40 clk 반복)

 


 

[Down Counter 적용]

 

module cook_timer(
    input clk, reset_p,
    input [2:0] btn,
    output [3:0] com,
    output [7:0] seg_7
    );
    
    // button 
    wire start, incsec, incmin;
    button_cntr btn_start_stop(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(start)); // start/stop
    t_flip_flop_p tff_start_stop(.clk(clk), .rst(reset_p), .t(start), .q(start_stop));
    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 Prescaler(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));
    
    // Time set
    wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .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(incmin), .dec1(min1_set), .dec10(min10_set)); // min up_counter
       
    // load_enable을 start_stop에 연결하면, start 시(start_stop = 1)계속해서 값을 불러와버린다.
    // 따라서 start_stop = 0일때만 1이 들어가도록 설계(start 변수의 참거짓에 따라 load_enable 변화하도록)
    wire clk_start, load_enable;
    wire dec_clk; // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
    wire [3:0] sec1, sec10, min1, min10;
    assign clk_start = start_stop ? clk_sec : 0; // 대표적인 MUX 생성 방법
    assign load_enable = ~start_stop ? start : 0; // start_stop = 0 이면, start 변수 사용
    // load_enable에는 edge 한 번만 주어야 하므로 start 사용
    
    // Down Counter 적용
    loadable_down_counter_dec_60 dc_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_start), .load_enable(load_enable), 
                                        .set_value1(sec1_set), .set_value10(sec10_set),
                                        .dec1(sec1), .dec10(sec10), .dec_clk(dec_clk));
    loadable_down_counter_dec_60 dc_min(.clk(clk), .reset_p(reset_p), .clk_time(dec_clk), .load_enable(load_enable), 
                                        .set_value1(min1_set), .set_value10(min10_set), // dc_sec의 dec_clk를 받아서 min 카운트에 사용
                                        .dec1(min1), .dec10(min10));                                    
    
    // Setting Time for FND
    reg [15:0] set_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) set_time = 0;
        else set_time = {min10_set, min1_set, sec10_set, sec1_set};
    end

    // Count Time for FND
    reg [15:0] count_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) count_time = 0;
        else count_time = {min10, min1, sec10, sec1};
    end
    
    wire [15:0] value;
    assign value = start_stop ? count_time : set_time; // start_stop의 참거짓에 따라 FND에 출력하는 값 달라짐.
    
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
    
    
endmodule

 


 

[Timeout]

 

📌 Timeout 기능 구현

 

 

위 그림과 같이 Count time의 모든 bit를 묶어서 OR 연산하게 되면,

모든 bit가 0일 때만 timeout 변수가 0이 된다.

이 논리를 활용하여 Finish와 Alarm 기능을 구현해보자.

 

// time = 0 도달 시, Finish & Alarm 발생
wire timeout, alarm_start;
assign timeout = |count_time; // 뒤의 모든 비트를 OR 연산한 결과(베릴로그에서만 사용할 수 있는 문법)
edge_detector_n edg_timeout(.clk(clk), .cp_in(timeout), .rst(reset_p), .n_edge(alarm_start)); // timeout 발생 시, alarm edge 발생

 

✅ Verilog Code snippet 

      위 코드에서처럼 Verilog에서만 사용할 수 있는 연산법이 존재하며, 그 예시는 아래와 같다.

wire A;
reg [15:0] B;
assign A = | B;

      ○ A = | B

          : B의 bit 중 하나라도 1인 bit가 있다면, A가 1로 설정되도록 하는 연산.

            즉, | 뒤에 있는 변수의 모든 bit를 OR연산한 뒤, A에 대입하라는 의미이다.

 


 

📌 Timeout Code

        Counting이 끝나면, Timer가 Stop되고 설정했던 시간이 다시 출력되도록 구현

        (reset 기능이 따로 있으므로, 좀 더 UX를 고려하여 구현해보았다.)

 

module cook_timer(
    input clk, reset_p,
    input [2:0] btn,
    output [3:0] com,
    output [7:0] seg_7
    );
    
    // button 
    wire start, incsec, incmin;
    wire timeout, alarm_start;
    wire t_start_stop;
//    or (t_start_stop, start, alarm_start); // Verilog에서 구조적 모델링 하지 마!!!!
    assign t_start_stop = start ? 1 : (alarm_start ? 1 : 0); // alarm이 발생하거나 start가 1일 때, t_start_stop = 1
    button_cntr btn_start_stop(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(start)); // start/stop
    t_flip_flop_p tff_start_stop(.clk(clk), .rst(reset_p), .t(t_start_stop), .q(start_stop)); // 버튼눌렀을 때, alarm 발생 시, start_stop 변수 토글
    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 Prescaler(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));
    
    // Time set
    wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .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(incmin), .dec1(min1_set), .dec10(min10_set)); // min up_counter
       
    // load_enable을 start_stop에 연결하면, start 시(start_stop = 1)계속해서 값을 불러와버린다.
    // 따라서 start_stop = 0일때만 1이 들어가도록 설계(start 변수의 참거짓에 따라 load_enable 변화하도록)
    wire clk_start, load_enable;
    wire dec_clk; // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
    wire [3:0] sec1, sec10, min1, min10;
    assign clk_start = start_stop ? clk_sec : 0; // 대표적인 MUX 생성 방법
    assign load_enable = ~start_stop ? start : 0; // start_stop = 0 이면, start 변수 사용
    // load_enable에는 edge 한 번만 주어야 하므로 start 사용
    
    loadable_down_counter_dec_60 dc_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_start), .load_enable(load_enable), 
                                        .set_value1(sec1_set), .set_value10(sec10_set),
                                        .dec1(sec1), .dec10(sec10), .dec_clk(dec_clk));
                                        
    loadable_down_counter_dec_60 dc_min(.clk(clk), .reset_p(reset_p), .clk_time(dec_clk), .load_enable(load_enable), 
                                        .set_value1(min1_set), .set_value10(min10_set),
                                        .dec1(min1), .dec10(min10));                                    
    
    // Setting Time for FND
    reg [15:0] set_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) set_time = 0;
        else set_time = {min10_set, min1_set, sec10_set, sec1_set};
    end

    // Count Time for FND
    reg [15:0] count_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) count_time = 0;
        else count_time = {min10, min1, sec10, sec1};
    end
    
    // time = 0 도달 시,
//    wire timeout, alarm_start; // 여기에 써도 오류는 안 난다.(Verilog의 코드는 병렬구조이기 때문에) 하지만 위에서 해당 변수를 사용하므로 위로 올리도록 하자.
    assign timeout = |count_time; // 뒤의 모든 비트를 OR 연산한 결과(베릴로그에서만 사용할 수 있는 문법)
    edge_detector_n edg_timeout(.clk(clk), .cp_in(timeout), .rst(reset_p), .n_edge(alarm_start)); // timeout 발생 시, alarm edge 발생
    
    wire [15:0] value;
    assign value = start_stop ? count_time : set_time;
    
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
    
endmodule

 


 

[Alarm]

 

📌 Alarm 기능 구현

       Timeout이 발생하면 alarm이 발생하고,

       alarm_off 버튼을 누르면, 알람이 꺼지도록 설계

       (부저를 사용해도 되지만, 시끄러우므로 LED로 대체)

 


 

📌 Alarm 기능 Code I

 

    wire alarm;
    t_flip_flop_p tff_alarm_on_off(.clk(clk), .rst(btn[3]), .t(alarm_start), .q(alarm));
    assign LED_bar[0] = alarm;

 

Timeout 시, Alarm이 발생하고

Alarm_off 버튼 누르면, Alarm이 Off된다.

 


 

📌 Alarm 기능 Code II

       보통 알람 시계는 어떤 버튼을 눌러도 Alarm이 Off된다.

       UX를 좀 더 고려하여, 아무 버튼이나 눌러도 Alarm이 꺼지게끔 구현해보자. 

 

    // Alarm On/Off를 위한 기능
    wire alarm, alarm_off;
    assign alarm_off = |{btn, reset_p}; // 모든 버튼을 다 묶어버려서 넣어주면, 어떤 버튼을 눌러도 alarm이 다 리셋된다.
    t_flip_flop_p tff_alarm_on_off(.clk(clk), .rst(alarm_off), .t(alarm_start), .q(alarm));
    assign LED_bar[0] = alarm;

어떤 버튼을 눌러도 Alarm이 Off된다.

 


 

[Full code]

 

Pin Configuration

 

Block Diagram

 

※ xdc file

더보기
## This file is a general .xdc for the Cora Z7-07S Rev. B
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project

## PL System Clock
set_property -dict { PACKAGE_PIN H16   IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L13P_T2_MRCC_35 Sch=sysclk
create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports { clk }];#set

## RGB LEDs
#set_property -dict { PACKAGE_PIN L15   IOSTANDARD LVCMOS33 } [get_ports { Y[0] }]; #IO_L22N_T3_AD7N_35 Sch=led0_b
#set_property -dict { PACKAGE_PIN G17   IOSTANDARD LVCMOS33 } [get_ports { Y[1] }]; #IO_L16P_T2_35 Sch=led0_g
##set_property -dict { PACKAGE_PIN N15   IOSTANDARD LVCMOS33 } [get_ports { led0_r }]; #IO_L21P_T3_DQS_AD14P_35 Sch=led0_r
#set_property -dict { PACKAGE_PIN G14   IOSTANDARD LVCMOS33 } [get_ports { Y[2] }]; #IO_0_35 Sch=led1_b
#set_property -dict { PACKAGE_PIN L14   IOSTANDARD LVCMOS33 } [get_ports { Y[3] }]; #IO_L22P_T3_AD7P_35 Sch=led1_g
##set_property -dict { PACKAGE_PIN M15   IOSTANDARD LVCMOS33 } [get_ports { led1_r }]; #IO_L23N_T3_35 Sch=led1_r

## Buttons
set_property -dict { PACKAGE_PIN D20   IOSTANDARD LVCMOS33 } [get_ports { reset_p }]; #IO_L4N_T0_35 Sch=btn[0]
#set_property -dict { PACKAGE_PIN D19   IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L4P_T0_35 Sch=btn[1]
#set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets up_down_IBUF]

## Pmod Header JA
#set_property -dict { PACKAGE_PIN Y18   IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L17P_T2_34 Sch=ja_p[1]
#set_property -dict { PACKAGE_PIN Y19   IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L17N_T2_34 Sch=ja_n[1]
#set_property -dict { PACKAGE_PIN Y16   IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L7P_T1_34 Sch=ja_p[2]
#set_property -dict { PACKAGE_PIN Y17   IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L7N_T1_34 Sch=ja_n[2]
#set_property -dict { PACKAGE_PIN U18   IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L12P_T1_MRCC_34 Sch=ja_p[3]
#set_property -dict { PACKAGE_PIN U19   IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L12N_T1_MRCC_34 Sch=ja_n[3]
#set_property -dict { PACKAGE_PIN W18   IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L22P_T3_34 Sch=ja_p[4]
#set_property -dict { PACKAGE_PIN W19   IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L22N_T3_34 Sch=ja_n[4]

## Pmod Header JB
#set_property -dict { PACKAGE_PIN W14   IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L8P_T1_34 Sch=jb_p[1]
#set_property -dict { PACKAGE_PIN Y14   IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L8N_T1_34 Sch=jb_n[1]
#set_property -dict { PACKAGE_PIN T11   IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L1P_T0_34 Sch=jb_p[2]
#set_property -dict { PACKAGE_PIN T10   IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L1N_T0_34 Sch=jb_n[2]
#set_property -dict { PACKAGE_PIN V16   IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L18P_T2_34 Sch=jb_p[3]
#set_property -dict { PACKAGE_PIN W16   IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L18N_T2_34 Sch=jb_n[3]
#set_property -dict { PACKAGE_PIN V12   IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L4P_T0_34 Sch=jb_p[4]
#set_property -dict { PACKAGE_PIN W13   IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L4N_T0_34 Sch=jb_n[4]

## Crypto SDA 
#set_property -dict { PACKAGE_PIN J15   IOSTANDARD LVCMOS33 } [get_ports { crypto_sda }];

## Dedicated Analog Inputs
#set_property -dict { PACKAGE_PIN K9    IOSTANDARD LVCMOS33 } [get_ports { v_p }]; #VP_0 Sch=xadc_v_p
#set_property -dict { PACKAGE_PIN L10   IOSTANDARD LVCMOS33 } [get_ports { v_n }]; #VN_0 Sch=xadc_v_n

## ChipKit Outer Analog Header - as Single-Ended Analog Inputs
## NOTE: These ports can be used as single-ended analog inputs with voltages from 0-3.3V (ChipKit analog pins A0-A5) or as digital I/O.
## WARNING: Do not use both sets of constraints at the same time!
#set_property -dict { PACKAGE_PIN E17   IOSTANDARD LVCMOS33 } [get_ports { vaux1_p }]; #IO_L3P_T0_DQS_AD1P_35 Sch=ck_an_p[0]
#set_property -dict { PACKAGE_PIN D18   IOSTANDARD LVCMOS33 } [get_ports { vaux1_n }]; #IO_L3N_T0_DQS_AD1N_35 Sch=ck_an_n[0]
#set_property -dict { PACKAGE_PIN E18   IOSTANDARD LVCMOS33 } [get_ports { vaux9_p }]; #IO_L5P_T0_AD9P_35 Sch=ck_an_p[1]
#set_property -dict { PACKAGE_PIN E19   IOSTANDARD LVCMOS33 } [get_ports { vaux9_n }]; #IO_L5N_T0_AD9N_35 Sch=ck_an_n[1]
#set_property -dict { PACKAGE_PIN K14   IOSTANDARD LVCMOS33 } [get_ports { vaux6_p }]; #IO_L20P_T3_AD6P_35 Sch=ck_an_p[2]
#set_property -dict { PACKAGE_PIN J14   IOSTANDARD LVCMOS33 } [get_ports { vaux6_n }]; #IO_L20N_T3_AD6N_35 Sch=ck_an_n[2]
#set_property -dict { PACKAGE_PIN K16   IOSTANDARD LVCMOS33 } [get_ports { vaux15_p }]; #IO_L24P_T3_AD15P_35 Sch=ck_an_p[3]
#set_property -dict { PACKAGE_PIN J16   IOSTANDARD LVCMOS33 } [get_ports { vaux15_n }]; #IO_L24N_T3_AD15N_35 Sch=ck_an_n[3]
#set_property -dict { PACKAGE_PIN J20   IOSTANDARD LVCMOS33 } [get_ports { vaux5_p }]; #IO_L17P_T2_AD5P_35 Sch=ck_an_p[4]
#set_property -dict { PACKAGE_PIN H20   IOSTANDARD LVCMOS33 } [get_ports { vaux5_n }]; #IO_L17N_T2_AD5N_35 Sch=ck_an_n[4]
#set_property -dict { PACKAGE_PIN G19   IOSTANDARD LVCMOS33 } [get_ports { vaux13_p }]; #IO_L18P_T2_AD13P_35 Sch=ck_an_p[5]
#set_property -dict { PACKAGE_PIN G20   IOSTANDARD LVCMOS33 } [get_ports { vaux13_n }]; #IO_L18N_T2_AD13N_35 Sch=ck_an_n[5]
## ChipKit Outer Analog Header - as Digital I/O
## NOTE: The following constraints should be used when using these ports as digital I/O.
set_property -dict { PACKAGE_PIN F17   IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L6N_T0_VREF_35 Sch=ck_a[0]
set_property -dict { PACKAGE_PIN J19   IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L10N_T1_AD11N_35 Sch=ck_a[1]
set_property -dict { PACKAGE_PIN K17   IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L12P_T1_MRCC_35 Sch=ck_a[2]
#set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS33 } [get_ports { ck_a3 }]; #IO_L11P_T1_SRCC_35 Sch=ck_a[3]
#set_property -dict { PACKAGE_PIN N16   IOSTANDARD LVCMOS33 } [get_ports { ck_a4 }]; #IO_L21N_T3_DQS_AD14N_35 Sch=ck_a[4]
#set_property -dict { PACKAGE_PIN P14   IOSTANDARD LVCMOS33 } [get_ports { ck_a5 }]; #IO_L6P_T0_34 Sch=ck_a[5]

## ChipKit Inner Analog Header - as Differential Analog Inputs
## NOTE: These ports can be used as differential analog inputs with voltages from 0-1.0V (ChipKit analog pins A6-A11) or as digital I/O.
## WARNING: Do not use both sets of constraints at the same time!
#set_property -dict { PACKAGE_PIN C20   IOSTANDARD LVCMOS33 } [get_ports { vaux0_p }]; #IO_L1P_T0_AD0P_35 Sch=ad_p[0]
#set_property -dict { PACKAGE_PIN B20   IOSTANDARD LVCMOS33 } [get_ports { vaux0_n }]; #IO_L1N_T0_AD0N_35 Sch=ad_n[0]
#set_property -dict { PACKAGE_PIN F19   IOSTANDARD LVCMOS33 } [get_ports { vaux12_p }]; #IO_L15P_T2_DQS_AD12P_35 Sch=ad_p[12]
#set_property -dict { PACKAGE_PIN F20   IOSTANDARD LVCMOS33 } [get_ports { vaux12_n }]; #IO_L15N_T2_DQS_AD12N_35 Sch=ad_n[12]
#set_property -dict { PACKAGE_PIN B19   IOSTANDARD LVCMOS33 } [get_ports { vaux8_p }]; #IO_L2P_T0_AD8P_35 Sch=ad_p[8]
#set_property -dict { PACKAGE_PIN A20   IOSTANDARD LVCMOS33 } [get_ports { vaux8_n }]; #IO_L2N_T0_AD8N_35 Sch=ad_n[8]
## ChipKit Inner Analog Header - as Digital I/O
## NOTE: The following constraints should be used when using the inner analog header ports as digital I/O.
#set_property -dict { PACKAGE_PIN C20   IOSTANDARD LVCMOS33 } [get_ports { ck_a6 }]; #IO_L1P_T0_AD0P_35 Sch=ad_p[0]
#set_property -dict { PACKAGE_PIN B20   IOSTANDARD LVCMOS33 } [get_ports { ck_a7 }]; #IO_L1N_T0_AD0N_35 Sch=ad_n[0]
#set_property -dict { PACKAGE_PIN F19   IOSTANDARD LVCMOS33 } [get_ports { ck_a8 }]; #IO_L15P_T2_DQS_AD12P_35 Sch=ad_p[12]
#set_property -dict { PACKAGE_PIN F20   IOSTANDARD LVCMOS33 } [get_ports { ck_a9 }]; #IO_L15N_T2_DQS_AD12N_35 Sch=ad_n[12]
#set_property -dict { PACKAGE_PIN B19   IOSTANDARD LVCMOS33 } [get_ports { ck_a10 }]; #IO_L2P_T0_AD8P_35 Sch=ad_p[8]
#set_property -dict { PACKAGE_PIN A20   IOSTANDARD LVCMOS33 } [get_ports { ck_a11 }]; #IO_L2N_T0_AD8N_35 Sch=ad_n[8]

## ChipKit Outer Digital Header
set_property -dict { PACKAGE_PIN U14   IOSTANDARD LVCMOS33 } [get_ports { seg_7[1] }]; #IO_L11P_T1_SRCC_34 Sch=ck_io[0]
set_property -dict { PACKAGE_PIN V13   IOSTANDARD LVCMOS33 } [get_ports { seg_7[5] }]; #IO_L3N_T0_DQS_34 Sch=ck_io[1]
set_property -dict { PACKAGE_PIN T14   IOSTANDARD LVCMOS33 } [get_ports { seg_7[0] }]; #IO_L5P_T0_34 Sch=ck_io[2]
set_property -dict { PACKAGE_PIN T15   IOSTANDARD LVCMOS33 } [get_ports { seg_7[4] }]; #IO_L5N_T0_34 Sch=ck_io[3]
set_property -dict { PACKAGE_PIN V17   IOSTANDARD LVCMOS33 } [get_ports { seg_7[3] }]; #IO_L21P_T3_DQS_34 Sch=ck_io[4]
set_property -dict { PACKAGE_PIN V18   IOSTANDARD LVCMOS33 } [get_ports { seg_7[2] }]; #IO_L21N_T3_DQS_34 Sch=ck_io[5]
set_property -dict { PACKAGE_PIN R17   IOSTANDARD LVCMOS33 } [get_ports { seg_7[7] }]; #IO_L19N_T3_VREF_34 Sch=ck_io[6]
set_property -dict { PACKAGE_PIN R14   IOSTANDARD LVCMOS33 } [get_ports { seg_7[6] }]; #IO_L6N_T0_VREF_34 Sch=ck_io[7]
set_property -dict { PACKAGE_PIN N18   IOSTANDARD LVCMOS33 } [get_ports { com[0] }]; #IO_L13P_T2_MRCC_34 Sch=ck_io[8]
set_property -dict { PACKAGE_PIN M18   IOSTANDARD LVCMOS33 } [get_ports { com[1] }]; #IO_L8N_T1_AD10N_35 Sch=ck_io[9]
set_property -dict { PACKAGE_PIN U15   IOSTANDARD LVCMOS33 } [get_ports { com[2] }]; #IO_L11N_T1_SRCC_34 Sch=ck_io[10]
set_property -dict { PACKAGE_PIN K18   IOSTANDARD LVCMOS33 } [get_ports { com[3] }]; #IO_L12N_T1_MRCC_35 Sch=ck_io[11]
#set_property -dict { PACKAGE_PIN J18   IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L14P_T2_AD4P_SRCC_35 Sch=ck_io[12]
#set_property -dict { PACKAGE_PIN G15   IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L19N_T3_VREF_35 Sch=ck_io[13]

## ChipKit Inner Digital Header
set_property -dict { PACKAGE_PIN R16   IOSTANDARD LVCMOS33 } [get_ports { LED_bar[0] }]; #IO_L19P_T3_34 Sch=ck_io[26]
set_property -dict { PACKAGE_PIN U12   IOSTANDARD LVCMOS33 } [get_ports { LED_bar[1] }]; #IO_L2N_T0_34 Sch=ck_io[27]
set_property -dict { PACKAGE_PIN U13   IOSTANDARD LVCMOS33 } [get_ports { LED_bar[2] }]; #IO_L3P_T0_DQS_PUDC_B_34 Sch=ck_io[28]
set_property -dict { PACKAGE_PIN V15   IOSTANDARD LVCMOS33 } [get_ports { LED_bar[3] }]; #IO_L10P_T1_34 Sch=ck_io[29]
set_property -dict { PACKAGE_PIN T16   IOSTANDARD LVCMOS33 } [get_ports { LED_bar[4] }]; #IO_L9P_T1_DQS_34 Sch=ck_io[30]
set_property -dict { PACKAGE_PIN U17   IOSTANDARD LVCMOS33 } [get_ports { LED_bar[5] }]; #IO_L9N_T1_DQS_34 Sch=ck_io[31]
set_property -dict { PACKAGE_PIN T17   IOSTANDARD LVCMOS33 } [get_ports { LED_bar[6] }]; #IO_L20P_T3_34 Sch=ck_io[32]
set_property -dict { PACKAGE_PIN R18   IOSTANDARD LVCMOS33 } [get_ports { LED_bar[7] }]; #IO_L20N_T3_34 Sch=ck_io[33]
set_property -dict { PACKAGE_PIN P18   IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L23N_T3_34 Sch=ck_io[34]
#set_property -dict { PACKAGE_PIN N17   IOSTANDARD LVCMOS33 } [get_ports { ck_io35 }]; #IO_L23P_T3_34 Sch=ck_io[35]
#set_property -dict { PACKAGE_PIN M17   IOSTANDARD LVCMOS33 } [get_ports { ck_io36 }]; #IO_L8P_T1_AD10P_35 Sch=ck_io[36]
#set_property -dict { PACKAGE_PIN L17   IOSTANDARD LVCMOS33 } [get_ports { ck_io37 }]; #IO_L11N_T1_SRCC_35 Sch=ck_io[37]
#set_property -dict { PACKAGE_PIN H17   IOSTANDARD LVCMOS33 } [get_ports { ck_io38 }]; #IO_L13N_T2_MRCC_35 Sch=ck_io[38]
#set_property -dict { PACKAGE_PIN H18   IOSTANDARD LVCMOS33 } [get_ports { ck_io39 }]; #IO_L14N_T2_AD4N_SRCC_35 Sch=ck_io[39]
#set_property -dict { PACKAGE_PIN G18   IOSTANDARD LVCMOS33 } [get_ports { ck_io40 }]; #IO_L16N_T2_35 Sch=ck_io[40]
#set_property -dict { PACKAGE_PIN L20   IOSTANDARD LVCMOS33 } [get_ports { ck_io41 }]; #IO_L9N_T1_DQS_AD3N_35 Sch=ck_io[41]

## ChipKit SPI
#set_property -dict { PACKAGE_PIN W15   IOSTANDARD LVCMOS33 } [get_ports { ck_miso }]; #IO_L10N_T1_34 Sch=ck_miso
#set_property -dict { PACKAGE_PIN T12   IOSTANDARD LVCMOS33 } [get_ports { ck_mosi }]; #IO_L2P_T0_34 Sch=ck_mosi
#set_property -dict { PACKAGE_PIN H15   IOSTANDARD LVCMOS33 } [get_ports { ck_sck }]; #IO_L19P_T3_35 Sch=ck_sck
#set_property -dict { PACKAGE_PIN F16   IOSTANDARD LVCMOS33 } [get_ports { ck_ss }]; #IO_L6P_T0_35 Sch=ck_ss

## ChipKit I2C
#set_property -dict { PACKAGE_PIN P16   IOSTANDARD LVCMOS33 } [get_ports { ck_scl }]; #IO_L24N_T3_34 Sch=ck_scl
#set_property -dict { PACKAGE_PIN P15   IOSTANDARD LVCMOS33 } [get_ports { ck_sda }]; #IO_L24P_T3_34 Sch=ck_sda

##Misc. ChipKit signals
#set_property -dict { PACKAGE_PIN M20   IOSTANDARD LVCMOS33 } [get_ports { ck_ioa }]; #IO_L7N_T1_AD2N_35 Sch=ck_ioa

## User Digital I/O Header J1
#set_property -dict { PACKAGE_PIN L19   IOSTANDARD LVCMOS33 } [get_ports { user_dio[1] }]; #IO_L9P_T1_DQS_AD3P_35 Sch=user_dio[1]
#set_property -dict { PACKAGE_PIN M19   IOSTANDARD LVCMOS33 } [get_ports { user_dio[2] }]; #IO_L7P_T1_AD2P_35 Sch=user_dio[2]
#set_property -dict { PACKAGE_PIN N20   IOSTANDARD LVCMOS33 } [get_ports { user_dio[3] }]; #IO_L14P_T2_SRCC_34 Sch=user_dio[3]
#set_property -dict { PACKAGE_PIN P20   IOSTANDARD LVCMOS33 } [get_ports { user_dio[4] }]; #IO_L14N_T2_SRCC_34 Sch=user_dio[4]
#set_property -dict { PACKAGE_PIN P19   IOSTANDARD LVCMOS33 } [get_ports { user_dio[5] }]; #IO_L13N_T2_MRCC_34 Sch=user_dio[5]
#set_property -dict { PACKAGE_PIN R19   IOSTANDARD LVCMOS33 } [get_ports { user_dio[6] }]; #IO_0_34 Sch=user_dio[6]
#set_property -dict { PACKAGE_PIN T20   IOSTANDARD LVCMOS33 } [get_ports { user_dio[7] }]; #IO_L15P_T2_DQS_34 Sch=user_dio[7]
#set_property -dict { PACKAGE_PIN T19   IOSTANDARD LVCMOS33 } [get_ports { user_dio[8] }]; #IO_25_34 Sch=user_dio[8]
#set_property -dict { PACKAGE_PIN U20   IOSTANDARD LVCMOS33 } [get_ports { user_dio[9] }]; #IO_L15N_T2_DQS_34 Sch=user_dio[9]
#set_property -dict { PACKAGE_PIN V20   IOSTANDARD LVCMOS33 } [get_ports { user_dio[10] }]; #IO_L16P_T2_34 Sch=user_dio[10]
#set_property -dict { PACKAGE_PIN W20   IOSTANDARD LVCMOS33 } [get_ports { user_dio[11] }]; #IO_L16N_T2_34 Sch=user_dio[11]
#set_property -dict { PACKAGE_PIN K19   IOSTANDARD LVCMOS33 } [get_ports { user_dio[12] }]; #IO_L10P_T1_AD11P_35 Sch=user_dio[12]

 

※ Clock Library & Counter

// Cora board sys clock : 125MHz
// 1 clock 당, 8ns

// Micro sec 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



// 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


// Loadable_60bit_Down_Counter
module loadable_down_counter_dec_60(
    input clk, reset_p,
    input clk_time,
    input load_enable, // user가 입력한 값을 받아오는 기능 추가 
    input [3:0] set_value1, set_value10, // 입력한 값
    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;
            dec_clk <= 0;
        end
        else if(load_enable == 1) begin
            dec1 <= set_value1;
            dec10 <= set_value10;
        end
        else if(clk_time) begin
            if(dec1 == 0) begin
                dec1 <= 9;
                if(dec10 == 0) begin // 우리는 min과 sec 둘 다 구현하는 것이므로, min down counter에 신호를 넣어줘야 된다. 
                    dec10 <= 5;
                    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

 

※ main code

module cook_timer(
    input clk, reset_p,
    input [3:0] btn,
    output [3:0] com,
    output [7:0] seg_7,
    output [7:0] LED_bar
    );
    
    // button 
    wire start, incsec, incmin;
    wire timeout, alarm_start;
    wire t_start_stop;
//    or (t_start_stop, start, alarm_start); // Verilog에서 구조적 모델링 하지 마!!!!
    assign t_start_stop = start ? 1 : (alarm_start ? 1 : 0); // alarm이 발생하거나 start가 1일 때, t_start_stop = 1
    button_cntr btn_start_stop(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(start)); // start/stop
    t_flip_flop_p tff_start_stop(.clk(clk), .rst(reset_p), .t(t_start_stop), .q(start_stop)); // 버튼눌렀을 때, alarm 발생 시, start_stop 변수 토글
    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 Prescaler(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));
    
    // Time set
    wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
    counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .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(incmin), .dec1(min1_set), .dec10(min10_set)); // min up_counter
       
    // load_enable을 start_stop에 연결하면, start 시(start_stop = 1)계속해서 값을 불러와버린다.
    // 따라서 start_stop = 0일때만 1이 들어가도록 설계(start 변수의 참거짓에 따라 load_enable 변화하도록)
    wire clk_start, load_enable;
    wire dec_clk; // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
    wire [3:0] sec1, sec10, min1, min10;
    assign clk_start = start_stop ? clk_sec : 0; // 대표적인 MUX 생성 방법
    assign load_enable = ~start_stop ? start : 0; // start_stop = 0 이면, start 변수 사용
    // load_enable에는 edge 한 번만 주어야 하므로 start 사용
    
    loadable_down_counter_dec_60 dc_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_start), .load_enable(load_enable), 
                                        .set_value1(sec1_set), .set_value10(sec10_set),
                                        .dec1(sec1), .dec10(sec10), .dec_clk(dec_clk));
    loadable_down_counter_dec_60 dc_min(.clk(clk), .reset_p(reset_p), .clk_time(dec_clk), .load_enable(load_enable), 
                                        .set_value1(min1_set), .set_value10(min10_set),
                                        .dec1(min1), .dec10(min10));                                    
    
    // Setting Time for FND
    reg [15:0] set_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) set_time = 0;
        else set_time = {min10_set, min1_set, sec10_set, sec1_set};
    end
    
    // Count Time for FND
    reg [15:0] count_time;
    always @(posedge clk, posedge reset_p) begin
        if(reset_p) count_time = 0;
        else count_time = {min10, min1, sec10, sec1};
    end
    
    // time = 0 도달 시,
//    wire timeout, alarm_start;  // 여기에 써도 오류는 안 난다.(Verilog의 코드는 병렬구조이기 때문에) 하지만 위에서 해당 변수를 사용하므로 위로 올리도록 하자.
    assign timeout = |count_time; // 뒤의 모든 비트를 OR 연산한 결과(베릴로그에서만 사용할 수 있는 문법)
    edge_detector_n edg_timeout(.clk(clk), .cp_in(timeout), .rst(reset_p), .n_edge(alarm_start)); // timeout 발생 시, alarm edge 발생
    
    // Alarm On/Off를 위한 기능
    wire alarm, alarm_off;
    assign alarm_off = |{btn, reset_p}; // 모든 버튼을 다 묶어버려서 넣어주면, 어떤 버튼을 눌러도 alarm이 다 리셋된다.
    t_flip_flop_p tff_alarm_on_off(.clk(clk), .rst(alarm_off), .t(alarm_start), .q(alarm));
    assign LED_bar[0] = alarm;
    
    wire [15:0] value;
    assign value = start_stop ? count_time : set_time;
    
    FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7));  /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
    
endmodule

 


 

 

728x90
반응형