본문 바로가기

VERILOG

[프로젝트]BASYS3를 이용한 VERILOG 다기능 시계 만들기(3)

BASYS3를 이용한 VERILOG 다기능 시계 만들기(3)

 

 

목차

  • 구상도와 필요한 내부를 설계를 하였다.
  • VERIOG를 이용하여 COOKTIMER 코드를 짠다.

COOKTIMER TOP 구상도

COOKTIMER 구상도

 

COOKTIMER의 TOPMODULE

 

module cook_timer_top(
    input clk,
    input [3:0] btn,
    output [3:0] com_an,
    output [6:0] seg_7,
    output [3:0] led
    );
    
    wire reset_n;
    wire dec_clk;
    wire btn_start, btn_down, btn_incsec, btn_incmin , btn_reset;
    wire clk_up_down_sec;
    wire down;
    
    wire [3:0] sec [1:0];
    wire [3:0] min [1:0];
    
    reg time_out = 0; // 
    wire led_on;
    wire reset_edge;
     

//    assign time_out = |{sec[0], sec[1], min[0], min[1]};
    assign reset_n = ~reset_edge; // btn 누르면 1이므로  반전시키기
    
    edge_detect    ed_clk_reset (.clk(clk), .cp_in(btn_reset), .reset_n(1), .n_edge(reset_edge));
 
    D_flip_flop_posedge dff_down (.D(btn[1]), .E(clk_msec), .Q(btn_down));
    D_flip_flop_posedge dff_incsec (.D(btn[3]), .E(clk_msec), .Q(btn_incsec));
    D_flip_flop_posedge dff_incmin (.D(btn[0]), .E(clk_msec), .Q(btn_incmin));
    D_flip_flop_posedge dff_reset ( .D(btn[2]),  .E(clk_msec), .Q(btn_reset));
        
    clock_usec uCLK(.clk(clk), .reset_n(reset_n), .clk_usec(clk_usec));
    clock_msec mCLK(.clk(clk), .clk_usec(clk_usec), .reset_n(reset_n), .clk_msec(clk_msec));
    clock_sec sCLK(.clk(clk), .clk_msec(clk_msec), .reset_n(reset_n), .clk_sec(clk_sec));
    clock_min MCLK(.clk(clk), .clk_sec(clk_sec), .reset_n(reset_n), .clk_min(clk_min));
    
    always @(posedge clk) 
    begin
        time_out = |{sec[0], sec[1], min[0], min[1]};
    end
    
    FND_4digit_switcher FND_4digit (
    .value_1(sec[0]),
    .value_10(sec[1]),
    .value_100(min[0]), 
    .value_1000(min[1]), // FND에 1234 출력되도록 설정
    .clk(clk),
    .com_an(com_an),
    .seg_7(seg_7)
    );
    
    T_flip_flop_posedge tff_down( .T(1), .clk(btn_down), .reset_n(time_out), .preset_n(1), .Q(down) );
    
    not (btn_down_n, btn_down);
    not (btn_incsec_n, btn_incsec);
    not (btn_incmin_n, btn_incmin);   
    and (any_btn, btn_down_n, btn_incsec_n, btn_incmin_n, reset_n);
    
    T_flip_flop tff_led( .T(1), .clk(time_out), .reset_n(any_btn), .preset_n(1), .Q(led_on) );
    //아무버튼이나 눌러도 reset되게 하며 0분0초될때 토글되게 한다.
    
    assign led[0] = led_on;
    

/* 아래의  mux와 같은 형태이다. 둘중 택 1   
    and ( clk_down_sec, down, clk_sec );
    and ( clk_up_sec, ~down, btn_incsec );
    or (clk_up_down_sec, clk_down_sec, clk_down_sec);
*/    
//instance 이름 지정이 필요하다
    mux_2_1 mux_sec (.D({clk_sec, btn_incsec}), .S(down), .F(clk_up_down_sec));
    
    counter_up_down counter_sec (.clk(clk_up_down_sec), .down(down), .reset_n(reset_n), .count_1(sec[0]), .count_10(sec[1]), .dec_clk(dec_clk));
    
    wire dec_clk_negedge;
    
    edge_detect ED_clk_min( .clk(clk), .cp_in(dec_clk), .reset_n(reset_n),  .n_edge(dec_clk_negedge));
    
    mux_2_1 mux_min ( .D({dec_clk_negedge, btn_incmin}), .S(down), .F(clk_up_down_min));
    
    counter_up_down counter_min (.clk(clk_up_down_min), .down(down), .reset_n(reset_n), .count_1(min[0]), .count_10(min[1]));
    
    
endmodule


module counter_up_down(
    input clk,
    input down,
    input reset_n,
    output reg [3:0] count_1 = 0,
    output reg [3:0] count_10 = 0,
    output reg dec_clk = 0
    );
    
    always @(negedge clk or negedge reset_n)begin
        if(!reset_n)begin
            count_1 = 0;
            count_10 = 0;
            dec_clk =1 ;
        end
        else begin
            if(down)begin //down mode
                if(count_1 == 0)begin
                    count_1 = 9;
                    if(count_10 ==0)begin
                        count_10 = 5;
                        dec_clk = 0;            //1들어오면 1분을 깍음 
                    end
                    else begin
                        count_10 = count_10 -1;     //10의자리 1씩 깍아 내림 
                    end
                end
                else begin
                    count_1 = count_1 -1;            //1의 자리 1씩 깍아내림 
                    if(~|{count_1, count_10}) dec_clk = 1;
                end
            end
            
            else begin //up mode
                dec_clk = 0;
                if(count_1 >=9)begin
                    count_1 = 0;
                    if(count_10 >= 5) begin
                        count_10 = 0;
                        dec_clk = 1;
                    end
                    else  count_10 = count_10 +1;
                end
                else begin
                 count_1 = count_1 +1;
                 //dec_clk =1;
                end    
            end
        end
    end
endmodule
  • 입출력 선언.
  • wire 선언 및 출력 변수 reg 선언.
  • 리셋 버튼이 눌러지는 하강엣지의 순간에 리셋.
  • btn_reset을 clk입력으로 받고 하강엣지일때 reset_edge 출력.
  • 버튼 별 D 플립플롭 입력 받음
  • clk의 상승엣지일때 time_out에 초와 분의 각 bit자리 or 처리한 값 삽입.
  • btn_down이 눌릴때 출력 Q의 down은 토글.
  • down,incsec, incmin을 반전시키고 reset버튼과 and게이트로 묶어 anybtn 출력.
  • time_out 들어올때 시간이 다되었다는 의미로 led 출력
  • down에 따라 내부클럭시간인 clk_sec가 출력 or 초증가 버튼 값 출력
  • down에 따라 출력된 down_sec이 들어올때 count에 sec값 저장. down_min이 들어올때 count에 min값 저장