Verilog로 링 카운터 설계

황윤성·2024년 9월 16일

Verilog HDL

목록 보기
9/9

이번 글에서는 베릴로그를 활용해 링 카운터를 설계하는 방법을 소개하고자 합니다. 링 카운터는 시프트 레지스터의 한 종류로 특정 비트가 회전하는 방식으로 동작하며 여러 디지털 시스템에서 사용됩니다.

1.기본 링 카운터 구현

가장 간단한 형태의 링 카운터는 4비트 시프트 레지스터를 사용하여 구현됩니다. 이 카운터는 특정 비트가 이동하며 순환하는 형태로 동작합니다.

module ring_counter(
    input clk, reset_p,
    output reg[3 : 0] q);
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p)
            q <= 4'b0001;
        else begin
            case(q)
                4'b0001: q <= 4'b0010;
                4'b0010: q <= 4'b0100;
                4'b0100: q <= 4'b1000;
                4'b1000: q <= 4'b0001;
            endcase
        end
    end
endmodule

이 코드에서는 q가 클럭 신호에 따라 이동하며 리셋 신호가 들어오면 q는 초기화 됩니다.

시뮬레이션 결과입니다. counter가 순차적으로 돌아가는 모습을 볼 수 있습니다.

2. LED제어를 위한 링 카운터

여기서는 LED제어를 위해 링 카운터를 조금 더 확장해 봅니다. 이 카운터는 16개의 LED를 순차적으로 켜고 끄는 역할을 합니다.

module ring_counter_led(
    input clk, reset_p,
    output reg [15:0] led);

    reg [20:0] clk_div;
    always @(posedge clk) clk_div <= clk_div + 1;
    
    wire clk_div_nedge;
    edge_detector_p ed(.clk(clk), .reset_p(reset_p), .cp(clk_div[20]), .n_edge(clk_div_nedge));

    always @(posedge clk or posedge reset_p)begin
        if(reset_p) 
            led <= 16'b0000_0000_0000_0001;
        else if(clk_div_nedge) begin
            if(led == 16'b1000_0000_0000_0000) 
                led <= 16'b0000_0000_0000_0001;
            else 
                led <= {led[14:0], 1'b0}; 
        end
    end
endmodule

여기서 우리는 clk_div를 사용하여 클럭 신호를 나눠줍니다. edge_detecter_p모듈은 클럭 신호의 하강 엣지를 검출하여 LED제어를 더욱 안정적으로 만듭니다.

3. 시프트 연산을 이용한 링 카운터

다음으로 시프트 연산을 활용한 링 카운터를 살펴보겠습니다. 이 방식을 비트를 왼쪽으로 이동시키며 마지막 비트를 첫 번째 위치로 순환시킵니다.

module ring_counter_shift(
    input clk, reset_p,
    output reg[3 : 0] q);
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p)
            q <= 4'b0001;
        else begin
          if(q == 4'b1000)
              q <= 4'b0001;
          else
              q <= {q[2:0], 1'b0}; 
         end
    end
endmodule

이 방법을 간단하면서도 효율적으로 링 카운터를 구현할 수 있는 방법입니다.

4. 7세그먼트 디스플레이 제어용 링 카운터

마지막으로 7세그먼트 디스플레이의 각 자리수를 제어하는 링 카운터를 살펴봅시다. 이 카운터는 디스플레이의 특정 위치를 순차적으로 활성화하는데 사용 됩니다.

module ring_counter_fnd(   
    input clk, reset_p,
    output reg[3 : 0] com);
    
    reg [20 : 0] clk_div = 0;
    always @(posedge clk) clk_div <= clk_div + 1;
    
    wire clk_div_nedge;
    edge_detector_p ed (.clk(clk), .reset_p(reset_p), .cp(clk_div[16]), .n_edge(clk_div_nedge));
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p)
            com <= 4'b1110;
        else if(clk_div_nedge) begin
            if(com == 4'b0111)
                com <= 4'b1110;
            else
                com <= {com[2:0], 1'b1};   
         end
     end
endmodule
profile
하드웨어 엔지니어 꿈나무

0개의 댓글