CHIP KIDD

[FPGA] T Flip Flop 을 이용한 up/down Counter 모듈 설계 본문

반도체/FPGA - Verilog

[FPGA] T Flip Flop 을 이용한 up/down Counter 모듈 설계

쑨야미 2021. 3. 12. 15:47

용어정리

순차논리회로 : 플립플롭, 래치 --> 메모리를 이용하여 데이터 저장 가능

조합논리회로 : 논리 게이트, mux/demux, decoder/encoder

동기식 비동기식 회로 차이 : 동일 CLk을 이용한 회로 → 동기식, 각각의 다른 clk을 이용한 회로 →비동기식

 

카운터는 무수히 많은 곳에 사용된다. 시계뿐만 아니라, 수를 계산하고, 순서를 계산하고, 인터럽터, 번호표 등 매우 많은 곳에 사용된다. 따라서 이번시간에 카운터 모듈을 만들어 보고자 한다. 재활용이 가능한 카운터를 구조적 모델링을 통해 만들어 보고, 더나아가 뒤에있을 구조적 모델링을 통한 시계를 만들어보자. 

T Flip Flop

: T에 신호가 들어올때 출력 toggle( 초기값 필요 → Q = 0)

 

  • 시뮬레이션 결과를 보면 CLK주기를 2배 늘려주는 것을 확인할 수 있다. 

Counter 카운터

TPP가 clk주기를 줄이고 늘릴 수 있는 특성 이용하여,  TPP를 4개를 아래와 같이 연결하면 Q0~Q3 의 4bit의 output을 도출 한다. 시뮬레이션 결과를 보면  숫자가 카운터 됨을 알 수 있다.  

TFF로 이루어진 카운터 회로
up카운터 시뮬레이션 결과
up 카운터 진리표

Down Counter

3개의 TFF를이용하여 만든 8bit downcounter

TFF의 특성(clk주기의 2배의 출력 생성)하여연결 시켜 다운카운터를 만들어 본다. 첫번째TFF의 출력인 Q0를 두번째 TFF의 clk에 입력하면 , 두번째 출력 Q1은 clk주기의 4배크기인 출력파형을 생성한다.  저는 4개의 TFF를 이용하여 16비트 down counter를 생성해 보았다.

시뮬레이션 결과를 보면 , f e dc b a 9 → 8 7 6 5 4 3 2 1 0 순서로 출력값을 내어놓게된다.

Down Counter를 구현하는데 핵심은 clk 파형이 Rising Edge 일때 데이터가 Toggle 되게 하는게 핵심이다. 

우선

<Code> Positive Edge에서 동작하는 TPP

module T_flip_flop(
    input T,
    input clk,
    input reset,
    output reg Q
    );
    //wire reset;  //회로로 만들땐 input 으로 바꿔줘랑
    //assign reset = 1; 
    
    initial begin 
        Q = 0;
    end
    
    always @(posedge clk or negedge reset) begin
    
        if(!reset) Q = 0;
        else begin
            if(T) Q = ~Q;     
        end 
              
    end
endmodule

<Code> TFF를 이용한 구조적 모델링 

module down_counter(
    input T,
    input clk,
    output [3:0]Q
    );
    
    T_flip_flop T0 (.T(T), .clk(clk), .reset(1'b1), .Q(Q[0]));
    T_flip_flop T1 (.T(T), .clk(Q[0]), .reset(1'b1), .Q(Q[1]));
    T_flip_flop T2 (.T(T), .clk(Q[1]), .reset(1'b1), .Q(Q[2]));
    T_flip_flop T3 (.T(T), .clk(Q[2]), .reset(1'b1), .Q(Q[3]));
    
endmodule

UP COUNTER / 비동기식

 

다운카운터는 TPP 가 clk 의 Rising Edge 에서 Toggle 되었지만, 반대로 업카운터는 Clk의 Falling Edge 에서 Toggle이 작동하면 된다. 따라서 회로는 그대로 둔 상태에서 코드변경만 해주면된다.

<code>  negative edge 에서 동작하는 TPP 구현이다. 

module T_flip_flop_negedge(
    input T,
    input clk,
    input reset,
    output reg Q
    );
    //wire reset;  //회로로 만들땐 input 으로 바꿔줘랑
    //assign reset = 1; 
    
    initial begin 
        Q = 0;
    end
    
    always @(negedge clk) begin
        if(reset) if(T) Q = ~Q;        
    end
    
    always @(reset) begin
        if(!reset) Q = 0;    
    end

endmodule

 TPP_neg 를 구현했다면 이것을 가지고 up counter를 구현해보자(구조적모델링)

module up_counter(
    input T,
    input clk,
    output [3:0]Q
    );
    
    T_flip_flop_negedge T0 (.T(T), .clk(clk), .reset(1'b1), .Q(Q[0]));
    T_flip_flop_negedge T1 (.T(T), .clk(Q[0]), .reset(1'b1), .Q(Q[1]));
    T_flip_flop_negedge T2 (.T(T), .clk(Q[1]), .reset(1'b1), .Q(Q[2]));
    T_flip_flop_negedge T3 (.T(T), .clk(Q[2]), .reset(1'b1), .Q(Q[3]));
    
endmodule

UP COUNTER 동기식

동기식 up counter는 같은 clock를 가지고 동작하는 회로이다.  

동기식 UP 카운터 회로도

회로도를 바탕으로 TFF-neg를 이용하여 코드를 짜보자

<Code>

module up_counter_synchronous(
    input T,
    input clk,
    output [3:0]Q
    );
    
    wire q2,q3;
    
    and (q2, Q[1], Q[0]);
    and (q3, Q[2], q2); 
    
    T_flip_flop_negedge T0 (.T(T), .clk(clk), .reset(1'b1), .Q(Q[0]));
    T_flip_flop_negedge T1 (.T(Q[0]), .clk(clk), .reset(1'b1), .Q(Q[1]));
    T_flip_flop_negedge T2 (.T(q2), .clk(clk), .reset(1'b1), .Q(Q[2]));
    T_flip_flop_negedge T3 (.T(q3), .clk(clk), .reset(1'b1), .Q(Q[3]));
    
endmodule

 

BCD Up Counter

UP/Down 카운터를 만들줄 안다면, 이를 이용하여 BCD(10진수)카운터를 만들 수있다. 

 output이 1010일때 초기화 시켜주는 회로를 만든다면 가능하다.  (Q3,Q1 = High Q2,Q0 = Low → 카르노맵 Q1, Q3 nand)  즉 아래와같이 회로를 만들어주면 된다. 이 회로는 동기 회로이기 때문에 문제가 일어나지 않지만, 비동기식 카운터의 경우에는 지연회로 동작인 clk에 의해 Q2, Q3부분에서 toggle이 한번더 일어나기 때문에 제대로 작동되지 않을 수있다. 따라서 Q2, Q3에는 Clr단자가 아닌 Preset 단자에 high 신호를 넣어주면 된다.  

BCD up counter ( 9→0 )

<Code>

module bcd_counter(
    input T,
    input clk,
    output [3:0]Q
    );
    
    wire q2,q3;
    wire rst,q2bar,q0bar;
    
    not(q2bar, Q[2]);
    not(q0bar, Q[0]);
    
    and (q2, Q[1], Q[0]);
    and (q3, Q[2], q2); 
    
    nand(rst, Q[1], Q[3],q2bar, q0bar);
    
    T_flip_flop_negedge T0 (.T(T), .clk(clk), .reset(rst), .Q(Q[0]));
    T_flip_flop_negedge T1 (.T(Q[0]), .clk(clk), .reset(rst), .Q(Q[1]));
    T_flip_flop_negedge T2 (.T(q2), .clk(clk), .reset(rst), .Q(Q[2]));
    T_flip_flop_negedge T3 (.T(q3), .clk(clk), .reset(rst), .Q(Q[3]));
    
endmodule

 

이번 시간에는, TFF를 이용하여 up/down 카운터와 BCD 카운터 까지 만들어 보았다. 이를 이용하여 

시계를 만들어 보자 .