Notice
Recent Posts
Recent Comments
Link
관리 메뉴

거북이처럼 천천히

Advanced Clock 본문

RTL Design/Verilog 연습

Advanced Clock

유로 청년 2024. 8. 6. 02:29

1. Advanced Clock

 

Verilog RTL 설계(7월 18일 - 1, Advanced Clock Mode - 4)

1. 초 값이 30초 이상일 때, btn_set 버튼을 누를 때마다 분 값이 1씩 증가한다. (또 다른 해결책)해당 문제에 대해서 이미 이전 게시글을 통해서 다루어 보았다.Verilog RTL 설계(7월 17일 - 5, Advanced Clock

jbhdeve.tistory.com

 

 

 

< Source, Edge detector >

// Edge detector.
module edge_detector (
    input clk, reset_p,
    input cp,
    output n_edge, p_edge );
    
    reg flip_flop_current, flip_flop_old;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin flip_flop_current <= 0; flip_flop_old <=0; end
        else begin
            flip_flop_current <= cp;
            flip_flop_old <= flip_flop_current;
        end
    end
    
    assign p_edge = ({flip_flop_current, flip_flop_old} == 2'b10)? 1 : 0;
    assign n_edge = ({flip_flop_current, flip_flop_old} == 2'b01)? 1 : 0;
    
endmodule

 

 

 

< Source, Decoder of 7-segment >

// Decoder of 7-segment.
module decoder_of_seg_7 (
    input [3:0] hex_value,
    output reg [7:0] seg_7);
    
    always @(hex_value) begin
        case (hex_value)
            0  : seg_7 = 8'b0000_0011; //common anode, 0이 켜지는거임 
            1  : seg_7 = 8'b1001_1111;  // 1
            2  : seg_7 = 8'b0010_0101;  // 2
            3  : seg_7 = 8'b0000_1101;  // 3
            4  : seg_7 = 8'b1001_1001;  // 4
            5  : seg_7 = 8'b0100_1001;  // 5
            6  : seg_7 = 8'b0100_0001;  // 6
            7  : seg_7 = 8'b0001_1111;  // 7
            8  : seg_7 = 8'b0000_0001;  // 8
            9  : seg_7 = 8'b0000_1001;  // 9
            10 : seg_7 = 8'b0001_0001;  // A
            11 : seg_7 = 8'b1100_0001;  // b
            12 : seg_7 = 8'b0110_0011;  // C
            13 : seg_7 = 8'b1000_0101;  // d
            14 : seg_7 = 8'b0110_0001;  // E
            15 : seg_7 = 8'b0111_0001;  // F
        endcase
    end
    
endmodule

 

 

 

< Source, Clock divider 60 >

// Clock divider 60.
module clk_div_60 (
    input clk, reset_p,
    input clk_source,
    output clk_div_60,
    output clk_div_60_nedge, clk_div_60_pedge );
    
    wire clk_source_nedge;
    edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
    
    reg [5:0] clk_div_60_count;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) clk_div_60_count = 0;
        else if(clk_source_nedge) begin
            if(clk_div_60_count >= 59) clk_div_60_count = 0;
            else clk_div_60_count = clk_div_60_count + 1;
        end
    end
    
    assign clk_div_60 = (clk_div_60_count < 30)? 0 : 1;
    edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_60), .n_edge(clk_div_60_nedge), .p_edge(clk_div_60_pedge));
endmodule

 

 

 

< Source, Clock divider 100 >

// Clock divider 100.
module clk_div_100 (
    input clk, reset_p,
    output clk_div_100,
    output clk_div_100_nedge, clk_div_100_pedge );
    
    reg [6:0] clk_div_100_count;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) clk_div_100_count = 0;
        else begin
            if(clk_div_100_count >= 99) clk_div_100_count = 0;
            else clk_div_100_count = clk_div_100_count + 1;
        end
    end
    
    assign clk_div_100 = (clk_div_100_count < 50)? 0 : 1;
    edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100), .n_edge(clk_div_100_nedge), .p_edge(clk_div_100_pedge));
endmodule

 

 

 

< Source, Clock divider 1000 >

// Clock divider 1000.
module clk_div_1000 (
    input clk, reset_p,
    input clk_source,
    output clk_div_1000,
    output clk_div_1000_nedge, clk_div_1000_pedge );
    
    wire clk_source_nedge;
    edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
    
    reg [9:0] clk_div_1000_count;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) clk_div_1000_count = 0;
        else if(clk_source_nedge) begin
            if(clk_div_1000_count >= 999) clk_div_1000_count = 0;
            else clk_div_1000_count = clk_div_1000_count + 1;
        end
    end
    
    assign clk_div_1000 = (clk_div_1000_count < 500)? 0 : 1;
    edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_1000), .n_edge(clk_div_1000_nedge), .p_edge(clk_div_1000_pedge));
endmodule

 

 

 

< Source, Ring Counter of 7-Segment's com >

// Ring Counter
module ring_counter (
    input clk, reset_p,
    output reg [3:0] com );
    
    wire clk_1usec, clk_1msec;
    clk_div_100 clk_usec (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_1usec));
    clk_div_1000 clk_msec(.clk(clk), .reset_p(reset_p), .clk_source(clk_1usec), .clk_div_1000_nedge(clk_1msec));
    
    always @(posedge clk or posedge reset_p) begin
    if(reset_p) com = 4'b1110;
    else if(clk_1msec) begin
        if(com == 4'b0111) com = 4'b1110;
        else com = {com[2:0], 1'b1};
    end
end
    
endmodule

 

 

 

< Source, Control FND >

// Control FND.
module fnd_cntr ( 
    input clk, reset_p,
    input [15:0] hex_value,
    output [3:0] com,
    output [7:0] seg_7 );
    
    // Ring counter of com value
    ring_counter ring_counter_0 (.clk(clk), .reset_p(reset_p), .com(com));
    
    // Selecting  seg_7 value
    reg [3:0] value;
    always @(*) begin
           case (com)
                4'b1110 : value = hex_value[3:0];
                4'b1101 : value = hex_value[7:4];
                4'b1011 : value = hex_value[11:8];
                4'b0111 : value = hex_value[15:12];
                default : value = value;
           endcase
    end
    
    decoder_of_seg_7 decoder_7_segment (.hex_value(value), .seg_7(seg_7));
endmodule

 

 

 

< Source, Button Control module for chattering >

// Button control for chattering
module button_cntr (
    input clk, reset_p,
    input button,
    output reg button_pulse, 
    output button_p_edge);
    
    reg [16:0] counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else begin
            if(counter >= 99999) counter = 0;
            else counter = counter + 1;
        end
    end
    
    wire clk_1msec;
    assign clk_1msec = (counter < 50000)? 0 : 1;
    
    wire clk_1msec_nedge;
    edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_1msec), .n_edge(clk_1msec_nedge));
    
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) button_pulse = 0;
        else if(clk_1msec_nedge) button_pulse = button;
    end
    
    edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(button_pulse), .p_edge(button_p_edge));
endmodule

 

 

 

< Source, T Flip-Flop >

// T Flip - Flop
module t_flip_flop (
    input clk, reset_p,
    input btn_set,
    output reg set_watch );
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) set_watch = 0;
        else if(btn_set) set_watch = ~ set_watch;
        else set_watch = set_watch;
    end
    
endmodule

 

 

 

< Source, Loadable BCD 60진 Counter >

// BCD 60진 Counter 
module loadable_bcd_60_counter (
    input clk, reset_p,
    input clk_source,
    input loadable_enable,
    input [3:0] loadable_bcd10, loadable_bcd1,
    output reg [3:0] bcd10, bcd1 );
    
    wire clk_source_nedge;
    edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin bcd10 = 0; bcd1 = 0; end
        else if(loadable_enable) begin
            bcd10 = loadable_bcd10;
            bcd1 = loadable_bcd1;
        end 
        else if(clk_source_nedge) begin
            if(bcd1 >= 9) begin
                bcd1 = 0;
                if(bcd10 >= 5) bcd10 = 0;
                else bcd10 = bcd10 + 1;
            end
            else bcd1 = bcd1 + 1;
        end
    end
endmodule

 

 

 

< Source, Top module of Advanced clock >

module Advanced_Watch(
    input clk, reset_p,
    input [2:0] btn,
    output [3:0] com,
    output [7:0] seg_7 );
    
    // Get One Cycle Pulse of buttons.
    wire btn_set, btn_min, btn_sec;
    button_cntr button_control_set (.clk(clk), .reset_p(reset_p), .button(btn[0]), .button_p_edge(btn_set));
    button_cntr button_control_min (.clk(clk), .reset_p(reset_p), .button(btn[1]), .button_p_edge(btn_min));
    button_cntr button_control_sec (.clk(clk), .reset_p(reset_p), .button(btn[2]), .button_p_edge(btn_sec));
    
    // Get Pulse of second, minute.
    wire clk_1usec, clk_1mesec, clk_1sec, clk_1min;
    clk_div_100 clk_usec (.clk(clk), .reset_p(new_reset_p), .clk_div_100(clk_1usec));
    clk_div_1000 clk_msec(.clk(clk), .reset_p(reset_p), .clk_source(clk_1usec), .clk_div_1000(clk_1msec));
    clk_div_1000 clk_sec(.clk(clk), .reset_p(reset_p), .clk_source(clk_1msec), .clk_div_1000(clk_1sec));
    clk_div_60 clk_min(.clk(clk), .reset_p(reset_p), .clk_source(inc_sec), .clk_div_60(clk_1min));
    
    // Declare mode & Control set_watch mode
    wire set_watch;
    t_flip_flop t_ff_set_watch (.clk(clk), .reset_p(reset_p), .btn_set(btn_set), .set_watch(set_watch));
    
    // Declare mode & Control set_watch mode
    wire inc_sec, inc_min;
    assign inc_sec = (set_watch) ? btn_sec : clk_1sec;
    assign inc_min = (set_watch) ? btn_min : clk_1min;
    
    // Get one cycle pulse of changing mode.
    wire watch_mode_nedge, set_mode_pedge;
    edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(set_watch), .n_edge(watch_mode_nedge));
    edge_detector edge_detector_2 (.clk(clk), .reset_p(reset_p), .cp(set_watch), .p_edge(set_mode_pedge));
    
    // Loadable BCD 60진 Counter.
    wire [3:0] watch_bcd10_min, watch_bcd1_min, watch_bcd10_sec, watch_bcd1_sec;
    wire [3:0] set_bcd10_min, set_bcd1_min, set_bcd10_sec, set_bcd1_sec;
   
    // Loadable BCD 60진 Counter of Watch mode
    loadable_bcd_60_counter watch_min_loadable_counter (.clk(clk), .reset_p(reset_p), .clk_source(inc_min),
                        .loadable_enable(watch_mode_nedge), .loadable_bcd10(set_bcd10_min), .loadable_bcd1(set_bcd1_min),
                        .bcd10(watch_bcd10_min), .bcd1(watch_bcd1_min));
                        
    loadable_bcd_60_counter watch_sec_loadable_counter (.clk(clk), .reset_p(reset_p), .clk_source(inc_sec),
                        .loadable_enable(watch_mode_pedge), .loadable_bcd10(set_bcd10_sec), .loadable_bcd1(set_bcd1_sec),
                        .bcd10(watch_bcd10_sec), .bcd1(watch_bcd1_sec));
                        
                        
     // Loadable BCD 60진 Counter of Set mode
     loadable_bcd_60_counter set_min_loadable_counter (.clk(clk), .reset_p(reset_p), .clk_source(inc_min),
                        .loadable_enable(set_mode_nedge), .loadable_bcd10(watch_bcd10_min), .loadable_bcd1(watch_bcd1_min),
                        .bcd10(set_bcd10_min), .bcd1(set_bcd1_min));
                        
    loadable_bcd_60_counter set_sec_loadable_counter (.clk(clk), .reset_p(reset_p), .clk_source(inc_sec),
                        .loadable_enable(set_mode_pedge), .loadable_bcd10(watch_bcd10_sec), .loadable_bcd1(watch_bcd1_sec),
                        .bcd10(set_bcd10_sec), .bcd1(set_bcd1_sec));
                        
                        
     // Combine data of clock.
     wire [15:0] hex_value_watch, hex_value_set;
     assign hex_value_watch = {watch_bcd10_min, watch_bcd1_min, watch_bcd10_sec, watch_bcd1_sec};
     assign hex_value_set = {set_bcd10_min, set_bcd1_min, set_bcd10_sec, set_bcd1_sec};
     
     // Select data & Show data
     wire [15:0] hex_value;
     assign hex_value = (set_watch)? hex_value_set : hex_value_watch;
     
    fnd_cntr fnd(.clk(clk), .reset_p(reset_p), .hex_value(hex_value), .com(com), .seg_7(seg_7));
endmodule

 

 

 

 

 

 

 

2. 구동 영상

 

'RTL Design > Verilog 연습' 카테고리의 다른 글

4X4 Matrix KeyPad - 1  (0) 2024.08.09
Stop Watch - 1  (0) 2024.08.07
Normal Clock  (0) 2024.08.04
비동기식 카운터 (Asynchronous counter)  (0) 2024.07.11
T Flip Flop  (0) 2024.07.11