이번 포스팅에서는 Verilog HDL을 활용해 0부터 9999까지 숫자를 세는 카운터 시스템을 설계하고,

그 결과를 7세그먼트 디스플레이(FND)에 실시간으로 출력하는 회로를 구현해보려고 합니다.

카운터는 100Hz의 일정한 속도로 증가하며, 스위치 입력을 통해 동작 시작/정지 및 초기화 기능을 손쉽게 제어할 수 있도록 구성되어 있습니다.

ℹ️ Verilog Code

clk_div_100hz 모듈은 시스템 클럭(00MHz)을 사람이 인식할 수 있는 저속 신호인 100Hz로 분주하는 기능을 담당합니다. 파라미터는 F_COUNT = 1_000_000으로 지정되어 있으며, 이를 기준으로 내부 카운터가 0부터 999,999까지 세면서 펄스 신호를 생성합니다.

module clk_div_100hz #(
    parameter F_COUNT = 1_000_000
) (
    input  clk,
    input  reset,
    output o_clk_100hz
);

    //parameter F_COUNT = 1_000_000;

    reg [$clog2(F_COUNT)-1:0] r_counter;
    reg r_clk;
    assign o_clk_100hz = r_clk;

    always @(posedge clk, posedge reset) begin
        if (reset) begin
            r_counter <= 0;
            r_clk <= 0;
        end else begin
            if (r_counter == F_COUNT - 1) begin
                r_counter <= 0;
                r_clk <= 1'b1;
            end else if (r_counter >= F_COUNT / 2) begin  //duty ratio 50%
                r_counter <= r_counter + 1;
                r_clk <= 1'b0;
            end else begin
                r_counter <= r_counter + 1;
                r_clk <= 1'b0;
            end
        end
    end

endmodule

출력 신호 o_clk_100hz는 10ms 주기의 신호로, 정확한 50% 듀티비를 유지하도록 조건을 분기하여 설계했습니다. 이 신호는 counter_10000 모듈에 전달되어 카운터가 일정한 속도로 증가할 수 있도록 합니다.

counter_10000 모듈은 100Hz의 입력 클럭을 받아 0부터 9999까지 증가하는 10000진 카운터입니다.출력값은 14비트 count_data이고, 카운트가 9999에 도달하면 자동으로 0으로 초기화되어 순환합니다. 외부 reset 또는 sw[1] 신호가 들어오면 즉시 0으로 초기화되도록 설계되어, 사용자가 직접 값을 리셋할 수 있습니다.

module counter_10000 (
    input         clk,
    input         reset,
    output [13:0] count_data
);

    reg [13:0] r_counter;
    assign count_data = r_counter;

    always @(posedge clk, posedge reset) begin
        if (reset) begin
            r_counter <= 0;
        end else begin
            if (r_counter == 10000 - 1) begin
                r_counter <= 0;
            end else begin
                r_counter <= r_counter + 1;
            end
        end
    end

endmodule

fnd_controller는 숫자 값을 FND에 출력하는 모듈로 이전 포스팅에서 다뤘으므로 넘어가겠습니다.

FND Controller 포스팅

top_10000_counter 모듈은 전체 시스템의 동작을 통합 제어하는 최상위(top) 모듈입니다.

module top_10000_counter (
    input        clk,
    input        reset,
    input  [1:0] sw,
    output [7:0] fnd_data,
    output [3:0] fnd_com
);

    wire [13:0] w_count_data;
    wire w_clk_100hz;

    wire w_run_stop_clk;
    wire w_clear;

    assign w_run_stop_clk = clk & sw[0];
    assign w_clear = reset | sw[1];

    clk_div_100hz U_CLK_DIV_100 (
        .clk(w_run_stop_clk),
        .reset(w_clear),
        .o_clk_100hz(w_clk_100hz)
    );

    counter_10000 U_COUNTER_10000 (
        .clk(w_clk_100hz),
        .reset(w_clear),
        .count_data(w_count_data)
    );

    fnd_controller U_FND_CTRL (
        .clk(clk),
        .reset(reset),
        .count_data(w_count_data),
        .fnd_data(fnd_data),
        .fnd_com(fnd_com)
    );

endmodule

입력으로는 클럭(clk), 리셋(reset), 그리고 2비트 스위치(sw[1:0])를 받아 각각 시스템 동작 시작/정지와 초기화를 제어합니다.

내부에는 세 가지 주요 모듈이 연결되어 있습니다. 클럭을 100Hz로 분주해주는 clk_div_100hz, 0부터 9999까지 숫자를 세는 counter_10000, 그리고 숫자 값을 FND에 출력하는 fnd_controller입니다.

스위치 신호는 논리 연산을 통해 처리되며, sw[0]이 1일 때만 카운터가 동작하고, sw[1] 또는 외부 reset 신호가 들어오면 즉시 카운터가 초기화되도록 설계되어 있습니다.