Notice
Recent Posts
Recent Comments
Link
관리 메뉴

거북이처럼 천천히

Verilog RTL 설계(7월 17일 - 7, Advanced Clock Mode) 본문

RTL Design/Verilog RTL 설계

Verilog RTL 설계(7월 17일 - 7, Advanced Clock Mode)

유로 청년 2024. 7. 21. 12:39

1. 지금까지 설계한 Advanced Clock 소스 코드

// Root of module
module Set_Clock_Mode(
    input clk, reset_p,
    input [3:0] btn,
    output [3:0] com,
    output [7:0] seg_7 );
    
    // Get pulse wave of sec, min
    wire clk_usec, clk_sec, clk_min;
    clk_div_100 clk_div_usec (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_usec));
    clk_div_n clk_div_sec(.clk(clk), .reset_p(reset_p), .clk_source(clk_usec), .prescale(1000000), .clk_div_n(clk_sec));
    clk_div_n clk_div_min(.clk(clk), .reset_p(reset_p), .clk_source(inc_sec), .prescale(60), .clk_div_n_nedge(clk_min));
    
    // Get One Cycle Pulse of button.
    wire btn_set, btn_sec, btn_min;
    button_cntr edge_btn_set (.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_nedge(btn_set));
    button_cntr edge_btn_sec (.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_nedge(btn_sec));
    button_cntr edge_btn_min (.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_nedge(btn_min));
    
    // select mode.
    wire set_watch;
    t_flip_flop t_ff (.clk(clk), .reset_p(reset_p), .t(btn_set), .q(set_watch));
    
    // Select standard pulse of bcd 60 counter.
    // when current state is watch mode, standard pulse is clk_sec, clk_min
    // when current state is set mode, standard pulse is btn_sec, btn_min
    wire inc_sec, inc_min;
    assign inc_sec = (set_watch)? btn_sec : clk_sec;
    assign inc_min = (set_watch)? btn_min : clk_min;
    
    // BCD 60 counter.
     wire [3:0] min_10, min_1, sec_10, sec_1;
    bcd_60_counter counter_clk(.clk(clk), .reset_p(reset_p), .clk_source(inc_sec), .bcd1(sec_1), .bcd10(sec_10));
    bcd_60_counter counter_min(.clk(clk), .reset_p(reset_p), .clk_source(inc_min), .bcd1(min_1), .bcd10(min_10));
    
    // Combine data of second, minute. 
    wire [15:0] value;
    assign value = {min_10, min_1, sec_10, sec_1};
    
    // Print the FND
    fnd_cntr fnd(.clk(clk), .reset_p(reset_p), .value(value), .com(com), .seg_7(seg_7));
endmodule

// Control Button.
module button_cntr (
    input clk, reset_p,
    input btn,
    output btn_pedge, btn_nedge);
    
    // Get 1ms Pulse wave, One Cycle Pulse
    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_1ms, clk_1ms_nedge;
    assign clk_1ms = (counter < 50000)? 0 : 1;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_1ms), .n_edge(clk_1ms_nedge));
    
    // Get positive edge of button, Negative edge of button.
    reg debounced_btn;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) debounced_btn = 0;
        else if(clk_1ms_nedge) debounced_btn = btn;
    end
    
    edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(debounced_btn), .p_edge(btn_pedge), .n_edge(btn_nedge)); 
endmodule

// T Flo Flop
module t_flip_flop (
    input clk, reset_p,
    input t,
    output reg q );
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) q = 0;
        else if(t) q = ~q;
        else q = q;
    end
endmodule

// BCD 60 Counter
module bcd_60_counter (
    input clk, reset_p,
    input clk_source,
    output reg [3:0] bcd1, bcd10 );

    wire clk_sourc_nedge;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_sourc_nedge));
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin
            bcd1 = 0;
            bcd10 = 0;
        end else if(clk_sourc_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
 
// Prescaler N
module clk_div_n (
    input clk, reset_p,
    input clk_source,
    input [31:0] prescale,
    output clk_div_n, clk_div_n_nedge );
    
    // Get one cycle pulse of clk_source
    wire clk_source_nedge;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
    
    // Counting
    integer counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else if(clk_source_nedge) begin
            if(counter >= prescale-1) counter = 0;
            else counter = counter + 1;
        end 
    end
    
    // Get clk_div_n wave, One cycle pulse of clk_div_n.
    assign clk_div_n = (counter < prescale / 2)? 0 : 1;
    edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_n), .n_edge(clk_div_n_nedge));
    
endmodule

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

// Control FND
module fnd_cntr (
    input clk, reset_p,
    input [15:0] value,
    output reg [3:0] com,
    output [7:0] seg_7);
    
    // Shifting the com value every 1ms.
    // prescale 100000
    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
    
    // period 1ms Pulse wave
    wire clk_div_100000, clk_div_100000_nedge;
    assign clk_div_100000 = (counter < 50000) ? 0 : 1;
    
    // period 1ms One Cycle Pulse
    edge_detector_n edge_detector_0(.clk(clk), .reset_p(reset_p), .cp(clk_div_100000), .n_edge(clk_div_100000_nedge));
    
    // Shifting com value
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) com = 4'b1110;
        else if(clk_div_100000_nedge) begin
            if(com == 4'b0111) com = 4'b1110;
            else com = {com[2:0], 1'b1}; 
        end
    end
    
    reg[3:0] hex_value;
    
    always @(com) begin
        case(com) 
            4'b1110 : hex_value = value[3:0];
            4'b1101 : hex_value = value[7:4];
            4'b1011 : hex_value = value[11:8];
            4'b0111 : hex_value = value[15:12];
            default : hex_value = hex_value;
        endcase
    end
    
    // Get fnd data
    decoder_seg_7 fnd (.hex_value(hex_value), .seg_7(seg_7));
endmodule

// Decoder of 7-seg
module decoder_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;  // 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'b0000_0101;  // 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

// Edge detector 
module edge_detector_n (
    input clk, reset_p,
    input cp,
    output p_edge, n_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 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