7/26 다기능 시계 만들기

정유석·2024년 7월 25일

교육 - 베릴로그

목록 보기
17/28


처음 만들다 실패한 코드

module multi_watch(
    input clk, reset_p,
    input [2:0] btn,
    output [3:0] com,
    output [7:0] seg_7);
    
    parameter WATCH = 3'b001;
    parameter STOP = 3'b010;
    parameter TIMER = 3'b100;
    
    reg [2:0] mode, next_mode;
    
    wire btn_mode_nedge;
    edge_detector_p(.clk(clk), .reset_p(reset_p),
     .cp(btn[0]), .n_edge(btn_mode_nedge));
    
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)begin
            mode = WATCH;
        end
        else begin
            if(btn_mode_nedge)begin
                mode = next_mode;
            end
        end
    end
    
    reg [2:0] btn_watch, btn_stop, btn_timer;
    reg [3:0] com_watch, com_stop, com_timer;
    reg [7:0] seg_7_watch, seg_7_stop, seg_7_timer;
    
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)begin
            mode = WATCH;
        end
            else begin
            case(mode)
                WATCH:begin
                    btn_watch = btn;
                    btn_stop = 0;
                    btn_timer = 0;
                    com_watch = com;
                    com_stop = 0;
                    com_timer = 0;
                    seg_7_watch = seg_7;
                    seg_7_stop = 0;
                    seg_7_timer = 0;
                    next_mode = STOP;
                end
                STOP:begin
                    btn_watch = 0;
                    btn_stop = btn;
                    btn_timer = 0;
                    com_watch = 0;
                    com_stop = com;
                    com_timer = 0;
                    seg_7_watch = 0;
                    seg_7_stop = seg_7;
                    seg_7_timer = 0;
                    next_mode = TIMER;
                end
                TIMER:begin
                    btn_watch = 0;
                    btn_stop = 0;
                    btn_timer = btn;
                    com_watch = 0;
                    com_stop = 0;
                    com_timer = com;
                    seg_7_watch = 0;
                    seg_7_stop = 0;
                    seg_7_timer = seg_7;
                    next_mode = WATCH;
                end
            endcase
        end
    end
    
    loadable_watch_top_prj prj_watch(.clk(clk), .reset_p(reset_p),
        .btn(btn_watch), .com(com_watch), .seg_7(seg_7_watch));
        
    stop_watch_ms_top_prj prj_stop(.clk(clk), .reset_p(reset_p),
        .btn(btn_stop), .com(com_stop), .seg_7(seg_7_stop));
        
    cook_timer_top prj_timer(.clk(clk), .reset_p(reset_p),
        .btn(btn_timer), .com(com_timer), .seg_7(seg_7_timer));
    
    wire [15:0] value;
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), .value(value), .com(com), .seg_7(seg_7));

endmodule

다기능 시계

module multi_watch(
    input clk, reset_p,
    input [3:0] btn,
    input btn_out,
    output [3:0] com,
    output [7:0] seg_7,
    output reg [2:0]led_debug,
    output led_start_stop, led_lap,
    output led_alarm, led_start_timer, buzz);
    
    wire btn_mode_nedge;
//    edge_detector_p(.clk(clk), .reset_p(reset_p),
//     .cp(btn[3]), .n_edge(btn_mode_nedge));
    button_cntr time_btn(.clk(clk), .reset_p(reset_p), .btn(btn[3]), .btn_nedge(btn_mode_nedge));
    
    reg [1:0] cnt_mode;
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)begin
            cnt_mode = 1;
        end
        else begin
            if(btn_mode_nedge)begin
                cnt_mode = cnt_mode + 1;
                if(cnt_mode > 3 || cnt_mode == 0)begin
                    cnt_mode = 1;
                end
            end
        end
    end
    
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)begin
            led_debug = 3'b001;
        end
        else if(cnt_mode == 1)begin
            led_debug = 3'b001;
        end
        else if(cnt_mode == 2)begin
            led_debug = 3'b010;
        end
        else if(cnt_mode == 3)begin
            led_debug = 3'b100;
        end
        else if(cnt_mode == 4)begin
            led_debug = 3'b001;
        end
    end
    
    reg [3:0] btn_watch, btn_stop, btn_timer;
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)begin
            btn_watch = btn;
        end
        else begin
            if(cnt_mode == 1)begin
                btn_watch = btn;
            end
            else if(cnt_mode == 2)begin
                btn_stop = btn;
            end
            else if(cnt_mode == 3)begin
                btn_timer = btn;
            end
        end
    end    

    wire [15:0] value, value_watch, value_stop, value_timer;
    wire [3:0] com_watch, com_stop, com_timer;
    wire [7:0] seg_7_watch, seg_7_stop, seg_7_timer;
    
    assign com = (cnt_mode == 1) ? com_watch : ((cnt_mode == 2) ? com_stop : ((cnt_mode == 3) ? com_timer : 0));
    assign seg_7 = (cnt_mode == 1) ? seg_7_watch : ((cnt_mode == 2) ? seg_7_stop : ((cnt_mode == 3) ? seg_7_timer : 0));
    
    loadable_watch_top_prj watch(.clk(clk), .reset_p(reset_p), .btn(btn_watch[2:0]), .com(com_watch), .seg_7(seg_7_watch));
    
    stop_watch_ms_top_prj stop(.clk(clk), .reset_p(reset_p), .btn(btn_stop[2:0]), .com(com_stop), .seg_7(seg_7_stop),
        .led_start(led_start_stop), .led_lap(led_lap));
    
    cook_timer_top_prj timer(.clk(clk), .reset_p(reset_p), .btn(btn_timer[2:0]), .btn_out(btn_out), .com(com_timer), .seg_7(seg_7_timer),
        .led_alarm(led_alarm), .led_start(led_start_timer), .buzz(buzz));
     
endmodule

module loadable_watch_top_prj(
    input clk, reset_p,
    input [2:0] btn,
    output [3:0] com,
    output [7:0] seg_7);
    
    wire btn_mode;    //버튼 입력 펄스를 알기위함
    wire btn_sec;    //버튼 입력 펄스를 알기위함
    wire btn_min;    //버튼 입력 펄스를 알기위함
    wire set_watch; //모드 변경 토글
    wire inc_sec, inc_min;
    wire clk_usec, clk_msec, clk_sec, clk_min; //분주기 인스턴스 사용
    
    
    button_cntr btn0(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pedge(btn_mode));
    button_cntr btn1(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pedge(btn_sec));
    button_cntr btn2(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pedge(btn_min));
         
     /*
     edge_detector_n ed_btn0(
        .clk(clk), .reset_p(reset_p), .cp(btn[0]),
        .p_edge(btn_mode));
  
     edge_detector_n ed_btn1(
        .clk(clk), .reset_p(reset_p), .cp(btn[1]),
        .p_edge(btn_sec));
   
     edge_detector_n ed_btn2(
        .clk(clk), .reset_p(reset_p), .cp(btn[2]),
        .p_edge(btn_min));
      */
        
      
    T_flip_flop_p t_mode(.clk(clk), .reset_p(reset_p), .t(btn_mode), .q(set_watch)); //T플립플롭의 파워 리셋으로 q=0  
    
    wire watch_load_en, set_load_en;
    edge_detector_n ed_source(
        .clk(clk), .reset_p(reset_p), .cp(set_watch),
        .n_edge(watch_load_en), .p_edge(set_load_en));
   
    assign inc_sec = set_watch ? btn_sec : clk_sec; //mux사용
    assign inc_min = set_watch ? btn_min : clk_min;
    
    
    clock_div_100 usec_clk(.clk(clk), .reset_p(reset_p), .clk_div_100(clk_usec)); //100분주기 1us로 만듬
    clock_div_1000 msec_clk(.clk(clk), .reset_p(reset_p), .clk_source(clk_usec), .clk_div_1000(clk_msec)); //1000분주기 1ms로 만듬
    clock_div_1000 sec_clk(.clk(clk), .reset_p(reset_p), .clk_source(clk_msec), ./*clk_div_1000*/clk_div_1000_nedge(clk_sec)); //1000분주기 1s로 만듬
    clock_div_60 min_clk(.clk(clk), .reset_p(reset_p), .clk_source(inc_sec), ./*clk_div_60*/clk_div_60_nedge(clk_min)); //60분주기 1분 만듬
                                                                            //30초 이후, 0.5초이후 에 모드버튼을 눌러도 분, 초가 올라가는 현상 해결
                                                                            
    loadable_counter_bcd_60 sec_watch(
        .clk(clk), .reset_p(reset_p),
        .clk_time(clk_sec),
        .load_enable(watch_load_en),
        .load_bcd1(set_sec1), .load_bcd10(set_sec10),  //덮어쓰기 로드를 받기위한 입력
        .bcd1(watch_sec1), .bcd10(watch_sec10));
         
    loadable_counter_bcd_60 min_watch(
        .clk(clk), .reset_p(reset_p),
        .clk_time(clk_min),
        .load_enable(watch_load_en),
        .load_bcd1(set_min1), .load_bcd10(set_min10),  //덮어쓰기 로드를 받기위한 입력
        .bcd1(watch_min1), .bcd10(watch_min10));
    
    loadable_counter_bcd_60 sec_set(
        .clk(clk), .reset_p(reset_p),
        .clk_time(btn_sec),
        .load_enable(set_load_en),
        .load_bcd1(watch_sec1), .load_bcd10(watch_sec10),  //덮어쓰기 로드를 받기위한 입력
        .bcd1(set_sec1), .bcd10(set_sec10));
         
    loadable_counter_bcd_60 min_set(
        .clk(clk), .reset_p(reset_p),
        .clk_time(btn_min),
        .load_enable(set_load_en),
        .load_bcd1(watch_min1), .load_bcd10(watch_min10),  //덮어쓰기 로드를 받기위한 입력
        .bcd1(set_min1), .bcd10(set_min10));
        
    wire [15:0] value, watch_value, set_value;
    wire [3:0] watch_sec1, watch_sec10, watch_min1, watch_min10; //BCD 60진 카운터 인스턴스 사용
    wire [3:0] set_sec1, set_sec10, set_min1, set_min10;
    
    assign watch_value = {watch_min10, watch_min1, watch_sec10, watch_sec1}; //결합연산자 사용하여 FND에 표시
    assign set_value = {set_min10, set_min1, set_sec10, set_sec1};
    assign value = set_watch ? set_value : watch_value;
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), .value(value), .com(com), .seg_7(seg_7));

endmodule    
    
module stop_watch_ms_top_prj(
    input clk, reset_p,
    input [2:0] btn,
    output [3:0] com,
    output [7:0] seg_7,
    output led_start, led_lap);
    //output [15:0] led_start);
    
    wire reset_start;
    wire start_stop;   
    wire clk_usec, clk_msec, clk_10msec, clk_sec, clk_min;
    
    reg lap;
    
    wire btn_start, btn_lap, btn_clear;
    
    wire clk_start;    
    assign clk_start = start_stop ? clk : 0;
    
    
    clock_div_100 usec_clk(.clk(clk_start), .reset_p(reset_start), .clk_div_100(clk_usec));
    clock_div_1000 msec_clk(.clk(clk_start), .reset_p(reset_start), .clk_source(clk_usec), .clk_div_1000(clk_msec));
    clock_div_10 csec_clk(.clk(clk_start), .reset_p(reset_start), .clk_source(clk_msec), .clk_div_10(clk_10msec));
    clock_div_1000 sec_clk(.clk(clk_start), .reset_p(reset_start), .clk_source(clk_msec), .clk_div_1000_nedge(clk_sec)); 
    clock_div_60 min_clk(.clk(clk_start), .reset_p(reset_start), .clk_source(clk_sec), .clk_div_60_nedge(clk_min));
    
    button_cntr btn0(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pedge(btn_start));
    button_cntr btn1(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pedge(btn_lap));
    button_cntr btn2(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pedge(btn_clear));
    
    
    assign reset_start = reset_p | btn_clear;
          
    T_flip_flop_p t_start(.clk(clk), .reset_p(reset_start), .t(btn_start), .q(start_stop));
    assign led_start = start_stop;
    
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)lap=0;
        else begin
            if(btn_lap)lap=~lap;
            else if(btn_clear) lap = 0;
        end
    end 
    
    assign led_lap = lap;
       
    wire [3:0] min10, min1, sec1, sec10;
    counter_bcd_100_clear counter_msec(.clk(clk), .reset_p(reset_p), .clk_time(clk_10msec), .clear(btn_clear), .bcd1(sec1), .bcd10(sec10));     
    counter_bcd_60_clear counter_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_sec), .clear(btn_clear), .bcd1(min1), .bcd10(min10));
//    counter_bcd_60_clear counter_min(.clk(clk), .reset_p(reset_p), .clk_time(clk_min), .clear(btn_clear), .bcd1(min1), .bcd10(min10));
    
    reg [15:0] lap_time;
    wire [15:0] cur_time;
    assign cur_time = {min10, min1, sec10, sec1};
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)lap_time = 0;
        else if(btn_lap)lap_time = cur_time;
        else if(btn_clear) lap_time = 0;
    end
    
    wire [15:0] value;
    assign value = lap ? lap_time : cur_time;
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), .value(value), .com(com), .seg_7(seg_7));
    
endmodule    
    
module cook_timer_top_prj(
    input clk, reset_p,
    input [2:0] btn,
    input btn_out,
    output [3:0] com,
    output [7:0] seg_7,
    output led_alarm, led_start, buzz);
    
    wire clk_usec, clk_msec, clk_sec, clk_min;
    clock_div_100 usec_clk(.clk(clk), .reset_p(reset_p), .clk_div_100(clk_usec));
    
    clock_div_1000 msec_clk(.clk(clk), .reset_p(reset_p), 
        .clk_source(clk_usec), .clk_div_1000(clk_msec));
        
    clock_div_1000 sec_clk(.clk(clk), .reset_p(reset_p), 
        .clk_source(clk_msec), .clk_div_1000_nedge(clk_sec)); 
        
//    clock_div_60 min_clk(.clk(clk), .reset_p(reset_p), 
//        .clk_source(clk_sec), .clk_div_60_nedge(clk_min));
    
    wire btn_start, btn_sec, btn_min, btn_alarm_off;
    button_cntr btn0(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pedge(btn_start));
    button_cntr btn1(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pedge(btn_sec));
    button_cntr btn2(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pedge(btn_min));
    button_cntr btn3(.clk(clk), .reset_p(reset_p), .btn(btn_out), .btn_pedge(btn_alarm_off));
    
    wire [3:0] set_min10, set_min1, set_sec10, set_sec1;
    wire [3:0] cur_min10, cur_min1, cur_sec10, cur_sec1;
    counter_bcd_60 counter_sec(.clk(clk), .reset_p(reset_p), 
        .clk_time(btn_sec), .bcd1(set_sec1), .bcd10(set_sec10));

    counter_bcd_60 counter_min(.clk(clk), .reset_p(reset_p), 
        .clk_time(btn_min), .bcd1(set_min1), .bcd10(set_min10));

    wire dec_clk;
    loadable_down_counter_bcd_60 cur_sec(
        .clk(clk), .reset_p(reset_p), .clk_time(clk_sec),
        .load_enable(btn_start),
        .load_bcd1(set_sec1), .load_bcd10(set_sec10), 
        .bcd1(cur_sec1), .bcd10(cur_sec10), .dec_clk(dec_clk));
        
    loadable_down_counter_bcd_60 cur_min(
        .clk(clk), .reset_p(reset_p), .clk_time(dec_clk),
        .load_enable(btn_start),
        .load_bcd1(set_min1), .load_bcd10(set_min10), 
        .bcd1(cur_min1), .bcd10(cur_min10));
        
    wire [15:0] value, set_time, cur_time;
    assign set_time = {set_min10, set_min1, set_sec10, set_sec1};
    assign cur_time = {cur_min10, cur_min1, cur_sec10, cur_sec1};
    
    
    reg start_set, alarm; //기본 T플립플롭의 틀에다가 코드 추가 always문 사용 wire->reg로 변경
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)begin
            start_set = 0;
            alarm = 0;
        end
        else begin
            if(btn_start)start_set = ~start_set;
            else if(cur_time == 0 && start_set)begin
                start_set = 0;
                alarm = 1;
            end
            else if(btn_alarm_off) alarm = 0;
        end  
    end
    
    assign led_alarm = alarm;
    assign buzz = alarm;    //부저 사용
    assign led_start = start_set;
    
    assign value = start_set ? cur_time : set_time;        
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), .value(value), .com(com), .seg_7(seg_7));
    
endmodule 

기존에 만들어둔 시계, 스탑워치, 타이머 모듈을 인스턴스로 넣어 버튼을 누를때마다 모드를 바꿔서 FND에 출력할 수 있도록 만들었다, 타이머의 alarm_off기능은 보드에 있는 버튼의 갯수가 모자르기 때문에 외부 버튼을을 풀다운 저항을 이용해 연결하였다

profile
개인 기록공간

0개의 댓글