Language/Verilog

Vivado : 동기식 카운터

짱도르딘 2024. 7. 12. 17:38
728x90

 

Positive 업 카운터

module up_counter_p(
    input clk, reset_p, enable,
    output reg [3:0] count);
    
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)count=0;
        else if(enable)count=count + 1;
    end       
endmodule

 


Vivado에서는 C언어와 같이 증감 연산자를 사용할 수 없기 때문에 count = count + 1과 같이 코딩한다.

 

시뮬레이션을 진행할 때, Reset 값에 1을 인가한 뒤 0으로 인가해주어야만 정상적인 동작을 수행한다.

Reset을 하지 않으면, 그전에 어떤 값이 들어있는지 모르기 때문에 초기화를 한번 진행해 주는 것이다.

 

Positive Up counter 출력 결과

 

Rising Edge일 때마다 출력값이 1씩 증가하는 것을 확인할 수 있다.

 

Positive 다운 카운터

module down_counter_p(
    input clk, reset_p, enable,
    output reg [3:0] count);
    
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)count=0;
        else if(enable)count=count - 1;
    end       
endmodule

 

Positive Down counter 출력 결과

 

다운카운터 할 때에는 count = count - 1로 변경하여 진행한다.

 

Rising Edge 때마다 출력값이 1씩 감소하는 것을 확인할 수 있다.

 

Negative 업 카운터

module up_counter_n(
    input clk, reset_p, enable,
    output reg [3:0] count);
    
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)count=0;
        else if(enable)count = count + 1;
    end       
endmodule

 

Negative Up counter 출력 결과

 

Positive 때와는 달리, Falling Edge일 때마다 출력값이 1씩 증가하는 것을 확인할 수 있다.

 

Negative 다운 카운터

module down_counter_n(
    input clk, reset_p, enable,
    output reg [3:0] count);
    
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)count=0;
        else if(enable)count=count - 1;
    end       
endmodule

 

Negative Down counter 출력 결과

 

 

Falling Edge일 때마다 값이 1씩 감소하는 것을 확인할 수 있다.


 

동기식 BCD 업 카운터

 

BCD 카운터 상태도

 

module bcd_upcounter_p(
    input clk, reset_p,
    output reg [3:0] count);
    
    always @(posedge clk or posedge reset_p)begin
        if(reset_p) count = 0;
        else begin
            if(count >= 9) count = 0;
            else count = count + 1;
        end
    end        
endmodule

 

출력값이 0부터 1씩 증가하다가, 9를 넘어가서는 10으로 되지 않고 0으로 다시 초기화되는 것을 확인할 수 있다.

 

동기식 BCD 다운 카운터

 

module bcd_downcounter_p(
    input clk, reset_p,
    output reg [3:0] count);
    
    always @(posedge clk or posedge reset_p)begin
        if(reset_p) count = 9;
        else begin
            if(count >= 10 | count == 0) count = 9;
            else count = count - 1;
        end
    end        
endmodule

 

BCD 업 카운터와는 달리, 9부터 1씩 작아지는 모습을 띤다. 0이 되었을 시 다시 9로 초기화되는 모습을 볼 수 있다.

 


 

3비트 동기식 카운터

 

 

구현할 카운터는 업 다운 카운터로, up_down이 1일 시에는 0부터 9까지 증가, 0일 시에는 9부터 1까지 감소하는 동작을 수행한다.

 

module up_downcount_p1(
    input clk, reset_p,
    input up_down,
    output reg [3:0] count);
    
    // 1 = up counter, 0 = down counter
    
    always @(posedge clk or posedge reset_p)begin
    if(reset_p) count = 0;
    else begin
        if(up_down)begin
            if(count >= 9) count = 0;
            else count = count + 1;
            end
        else begin
            if(count == 0) count = 9;
            else count = count - 1;
            end
        end
    end   
endmodule

 

 

출력 결과를 확인해 보면 up_down이 0일 시에는 1씩 감소하는 모양을 보이며, up_down이 1일 시에는 1씩 증가하는 모습을 볼 수 있다.


 

링카운터

링카운터 상태도

 

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'b0000;
        else begin
            case(q)
                4'b0001: q = 4'b0010;
                4'b0010: q = 4'b0100;
                4'b0100: q = 4'b1000;
                4'b1000: q = 4'b0001;
                default: q = 4'b0001;
            endcase
        end
    end         
endmodule

 

결과는 2진수로 1, 2, 4, 8씩 반복되는 것을 확인할 수 있다.

 

 

시프트 연산자를 사용하여 링카운터 코드를 작성하면 아래와 같다.

 

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 << 1; 
        end
    end    
endmodule

 

배선을 따로 연결하여 결합 연산자를 사용해 (시프트 연산자를 사용하지 않고) 시프트 연산을 구현하면 아래의 코드와 같다.

 

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

 

링카운터 도면

 

 

 

728x90

'Language > Verilog' 카테고리의 다른 글

Vivado : Basys3 7segment  (0) 2024.07.16
Vivado : Edge Detector, Shift Register(SISO, SIPO, PISO, PIPO)  (2) 2024.07.16
Vivado : Decoder, Encoder  (2) 2024.06.25
Vivado : 4bit 가산기  (0) 2024.06.16
Vivado : 전가산기(Full-adder) 구현  (0) 2024.06.13