3.2.2 Sequential Logic - Counters

Kiwoong Nam·2025년 6월 6일

HDLBits

목록 보기
9/11

Slow decade counter

Countslow

module top_module (
    input clk,
    input slowena,
    input reset,
    output [3:0] q);
    always @(posedge clk) if (reset || (q == 9 && slowena)) q <= 0; else if (slowena) q <= q + 1;

endmodule

enable이 있는 카운터의 경우, 오버플로우 초기화 조건에 enable을 반드시 넣어줘야 한다!!

Counter 1-12

Exams/ece241 2014 q7a

  • 성공한 코드
module top_module (
    input clk,
    input reset,
    input enable,
    output [3:0] Q,
    output c_enable,
    output c_load,
    output [3:0] c_d
); //
    // When using always @(pos clk) to set c_load, it very slow and fail
	  assign c_d = 4'b1;
    assign c_enable = enable;
    assign c_load = reset || (enable && Q == 4'd12);
    count4 the_counter (clk, c_enable, c_load, c_d, Q);

endmodule

주어진 4비트 카운터를 사용해 1부터 12까지 세는 회로다. 12일 때 load 신호를 줘 1을 로드하는 방식이다.

  • 실패한 코드
module top_module (
    input clk,
    input reset,
    input enable,
    output [3:0] Q,
    output c_enable,
    output c_load,
    output [3:0] c_d
); //
	  assign c_d = 4'b1;
    assign c_enable = enable;
    count4 the_counter (clk, c_enable, c_load, c_d, Q);
    
    always @(posedge clk) begin
        if (reset || (enable && (Q == 4'd12))) c_load <= 1'b1;
        else
            c_load <= 1'b0;
    end

endmodule

c_load가 reg가 되어버리면 다음 클럭에서 변하는 문제 때문에 안 되는 것 같다.

Counter 1000

Exams/ece241 2014 q7b

module top_module (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
); //
    wire [3:0] q0;
    wire [3:0] q1;
    wire [3:0] q2;
    assign c_enable[0] = 1'b1;
    assign c_enable[1] = q0 == 4'b1001;
    assign c_enable[2] = q1 == 4'b1001 && q0 == 4'b1001;
    bcdcount counter0 (clk, reset, c_enable[0], q0);
    bcdcount counter1 (clk, reset, c_enable[1], q1);
    bcdcount counter2 (clk, reset, c_enable[2], q2);
    always @(posedge clk) begin
        if (q0 == 8 && q1 == 9 && q2 == 9) OneHertz <= 1;
        else if (q0 == 9 && q1 == 9 && q2 == 9) OneHertz <= 0;
    end

endmodule

3개의 bcd 카운터를 이용해 1000까지 세면서 마지막 10% 듀티에 출력을 활성화하는 분주 회로이다. 899->900, 999->0에서 출력을 변화시킨다.

12-hour clock

Count clock

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss);
    
    cnt ss_lower (
        .clk, .reset, 
        .ena,
        .lowval(4'h0),
        .highval(4'h9),
        .q(ss[3:0])
    );

    cnt ss_upper (
        .clk, .reset, 
        .ena(ena && ss[3:0] == 4'h9),
        .lowval(4'h0),
        .highval(4'h5),
        .q(ss[7:4])
    );

    cnt mm_lower (
        .clk, .reset, 
        .ena(ena && ss == 8'h59),
        .lowval(4'h0),
        .highval(4'h9),
        .q(mm[3:0])
    );

    cnt mm_upper (
        .clk, .reset, 
        .ena(ena && ss == 8'h59 && mm[3:0] == 4'h9),
        .lowval(4'h0),
        .highval(4'h5),
        .q(mm[7:4])
    );

    hhm hh_module (
        .clk, .reset,
        .ena(ena && ss == 8'h59 && mm == 8'h59),
        .q(hh)
    );

    ampm pm_module (
        .clk, .reset,
        .ena(ena && ss == 8'h59 && mm == 8'h59 && hh == 8'h11),
        .q(pm)
    );

endmodule

module cnt (
    input clk, reset, ena,
    input [3:0] lowval,
    input [3:0] highval,
    output [3:0] q
);
    always @(posedge clk) begin
        if (reset || ena && q == highval) q <= lowval;
        else if (ena) q <= q + 1;
    end
endmodule

module hhm (
    input clk, reset, ena,
    output [7:0] q
);
    reg [3:0] state; // 0(12) to 11(11)
    always @(posedge clk) begin
        if (reset || ena && state == 4'd11) state <= 4'b0;
        else if (ena) state <= state + 1;
    end

    always @(*) begin
        case (state)
            4'd0: q <= 8'h12;
            4'd1: q <= 8'h1;
            4'd2: q <= 8'h2;
            4'd3: q <= 8'h3;
            4'd4: q <= 8'h4;
            4'd5: q <= 8'h5;
            4'd6: q <= 8'h6;
            4'd7: q <= 8'h7;
            4'd8: q <= 8'h8;
            4'd9: q <= 8'h9;
            4'd10: q <= 8'h10;
            4'd11: q <= 8'h11;
        endcase
    end
endmodule

module ampm (
    input clk, reset, ena,
    output q
);
    always @(posedge clk)
        if (reset) q <= 1'b0;
        else if (ena) q <= ~q;
endmodule

왜 이딴 문제에 솔루션을 안 주는지 모르겠다.
115959pm 다음이 120000am, 125959am 다음이 010000am이라는 잔혹한 현실이 괴로워 시간의 경우 FSM 형태로 구현하였다.

0개의 댓글