Notice
Recent Posts
Recent Comments
Link
관리 메뉴

거북이처럼 천천히

Verilog RTL 설계(7월 12일 - 6, Edge detector) 본문

RTL Design/Verilog RTL 설계

Verilog RTL 설계(7월 12일 - 6, Edge detector)

유로 청년 2024. 7. 15. 11:15
flip_flop_current = cp;
flip_flop_old = flip_flop_current;

1. Verilog에서 동기순차회로를 설계할 때에는 Clock Pulse와 Reset만 Sensitive variable로 사용하고, 나머지 변수에 대해서는 Sensitive variable로 사용하지 않는다.

  • PDT (Propagation delay time)은 신호 및 데이터가 회로를 통과하는데, 소요되는 시간을 의미한다.
  • PDT 를 정확히 계산하는 것이 회로의 Timing과 성능을 결정 짓는 데, 중요한 요소가 된다.
  • Clock Pulse와 Reset 신호는 동기화하고, 초기화하는데, 사용되는 특별한 신호이다. 
    따라서 이들 신호의 Timing은 예측이 가능하고, 제어도 가능하다. 
  • 하지만, 이를 제외한 나머지 변수의 edge detect 같은 경우에는 언제 사용할지 여부와 변화 시점을 예측하는 것은 불가능하다. 이러한 예측 불가능한 동작은 회로의 동작을 비결정적으로 만들 수 있다.
  • 즉, Clock Pulse와 Clock 이외에 다른 변수를 Sensitive list에 포함시키면, 그 변수의 값이 변화하는 시점과 그와 관련된 지연 시간을 정확하게 계산하기 어렵기 때문에 전체적으로 회로의 PDT (Propagation delay time)의 계산이 어려워 진다.
  • 따라서 동기 순차 회로 설계시, Sensitive list에 Clock Pulse, reset 변수만 포함시키므로서 회로의 정확한 동작 및 지연 시간, 안정성을 보장할 수 있다.

 

 

 

 

2. CP와 Reset 변수 이외에 다른 변수들의 edge detect는 어떻게 감지할 것이냐?

  • Edge detector를 설계함으로서 특정 변수의 edge를 감지하여 그에 맞는 작업을 수행하도록 하는 것이다.
  • 다시 한 번 말하지만, Sensitive list에는 CP와 Reset 변수만 사용해야 회로의 동작, 지연시간, 안정성이 보장되며, 다른 변수들은 언제 값이 변화할 지 여부를 예측할 수 없기 때문에 그에 대한 Edge detector가 필요하다.

 

 

 

 

3. Edge detector 회로 (One cycle Pulse)

  • One cycle Pulse는 일반적으로 한 번의 edge을 감지하고, 그에 대응하여 한 클럭 주기 동안만큼만 활성화되는 신호를 생성하는 edge detector의 한 형태이다.
  • 즉, 다시 말해 edge를 감지하면 딱 한 클럭동안만 활성화된 펄스 신호를 출력으로 내보내는 edge detector라고 할 수 있다.
  • One cycle Pulse는 D Flip Flop 2개를 직렬로 연결하여 구현할 수 있다. 

One cycle pulse (edge detector) implemented with D Flip Flop

 

  • 만약, Button 이라는 단자로부터 어떻게 Edge detect를 하는지 아래 Timing diagram을 통해 살펴보자.

Timing diagram of One Cycle Pulse

  • Button 단자의 상태 값이 Low → High로 변화하게 되면 다음 Positive edge에서 Current 값이 Low → High로 변화하고, 다음 Positive edge에서 Old 값이 Low → High으로 변화하게 된다.
  • ★★★★★★
    Q) 왜 Button 값의 상태 값이 변화한 것에 대해서 current와 old 값이 왜 동시 변화하지 않고, 순차적으로 변화하는가?
    A) 신호, 데이터 값이 D Flip Flop을 통과할 때마다 PDT가 발생하기 때문에 첫 번째 플립플롭을 통과하면서 PDT가 발생하고, 다음 old 값이 변화하고자 할때, 이미 Positive edge가 끝났기 때문에 old 값은 current 값과 동시 변화하지 않고, 다음 positive edge에서 변화하게 된다.
  • ★★★★★★
    Q) 그럼, 어떻게 Edge를 감지할 것인가?
    A) 한 클럭 동안 이지만, current 값이 1, old 값이 0인 순간이 존재한다.
    이때 다음과 같은 Gate를 연결하면 해당 입력값이 들어왔을 때, 출력 값으로 1을 출력함으로서 한 클럭 동안 활성환된 펄스파형을 출력으로 내보낸다. (One Cycle Pulse)

Edge detect를 하기 위한 AND Gate

 

  • 즉, 2개의 직렬로 연결된 D Flip Flop에 대해서 위와 같은 Gate를 연결해줌으로서  한 클럭 동안 활성환된 펄스파형을 출력으로 내보낸다. (One Cycle Pulse)

 

 

 

 

 

 

 

4. Vivado로 구현한 One Cycle Pulse (잘못된 경우)

< Source >

//  One cycle pulse (wrong case)
module One_cycle_pulse_positive_wrong_case(
    input cp, enable, reset_p,
    output p_edge  );

    reg flip_flop_current, flip_flop_old;
    
    always @(posedge cp or posedge reset_p) begin
        if(reset_p) begin
            flip_flop_current = 0;
            flip_flop_old = 0;
        end else if(enable) begin
            flip_flop_current = cp;
            flip_flop_old = flip_flop_current;
        end
    end
    
    // Special AND Gate.
    assign p_edge = ({flip_flop_current, flip_flop_old} == 2'b10) ? 1 : 0;
    
endmodule

 

< RTL analysis >

 

  • 위 코드에 대해서 RTL analysis 하면 D Flip Flop이 직렬이 아닌 병렬로 연결 되었음을 확인할 수 있다.
  • Q) 왜 D Flip Flop이 직렬이 아닌 병렬로 연결되었는가?
    A) 
    왜냐하면 always문내에 명령문을 병렬적이 아닌 순차적으로 실행되기 때문이다. 
flip_flop_current = cp;
flip_flop_old = flip_flop_current;
  • 따라서 위 코드들에 대해서 위에부터 순차적으로 실행되기 때문에 flip_flop_current값과 flip_flop_old 값과 cp 값 모두 같은 값을 갖는다.
  • 따라서 Vivado는 같은 값을 갖기 때문에 그에 대해서 논리회로를 구성한 것이다.
  • Q) 그럼, 어떻게 하면 논리적 오류 없이 D Flip-Flop을 직렬로 구성할 수 있는가?

 

 

 

 

 

 

4. Behavioral modeling of One Cycle Pulse  (Blocking)

  • always 문내에서는 명령문을 순차적으로 진행한다는 점을 이용하여 아래와 같이 코드를 수정한다.
  • C언어나 always문 내에서 명령어를 처리하는 것처럼 순차적으로 진행하며, 현재 문장이 완전히 실행된 후에 다음 문장으로 넘어가는 것Blocking이라 한다.
  • 따라서 현재 문장이 실행하는 동안 다음 명령어는 실행시킬 수 없다.

< Source >

// Behavioral modeling of one cycle pulse
module Behavioral_modeling_of_one_cycle_pulse(
    input clk, cp, enable, reset_p,
    output one_cycle_pulse );
    
    reg flip_flop_current, flip_flop_old;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin
            flip_flop_current = 0;
            flip_flop_old = 0;
        end else if(enable) begin
            flip_flop_old = flip_flop_current;
            flip_flop_current = cp;
        end 
    end
    
    // Special AND Gate.
    assign one_cycle_pulse = ({flip_flop_current, flip_flop_old} == 2'b10)? 1 : 0; 
    
endmodule

 

< Simulation >

 

< RTL analysis >

 

  • 첫 번째 D Flip Flop의 출력 값, Q이 다시 두 번째 D Flip Flop의 입력 값, D로 들어가는 것을 확인함으로서 두 개의 D Flip Flop이 직렬로 연결되어 있음을 확인할 수 있다.

 

< Synthesis >

 

 

 

 

 

 

 

5. Behavioral modeling of One Cycle Pulse  (Non-Blocking)

  • 다음과 같이 코드를 수정해서 사용할 수 있다.
  • Non-Blocking은 병렬적으로 수행하지만, 먼저 r-value의 값을 평가한 후, 정해진 r-value에 대해서 l-value에게 할당하는 방법을 의미한다.
  • 따라서 Non-blocking 방법을 사용하면 첫 번째 잘못된 경우에 대해서 해결할 수 있다.

 

< Source >

module Edge_Detector_Positive_Non_Blocking(
    input clk, cp, enable, reset_p,
    output p_edge   );
    
    reg flip_flop_current, flip_flop_old;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin
            flip_flop_current <=0;
            flip_flop_old <= 0;
        end else if(enable) begin
            flip_flop_current <= cp;
            flip_flop_old <= flip_flop_current;
        end
    end
    
    // Special AND gate for positive edge detect.
    assign p_edge = ({flip_flop_current, flip_flop_old } == 2'b10) ? 1 : 0;
    
endmodule
  • Non-blcoking 값에 의해서 r-value 값이 먼저 정의되고, 그 다음으로 병렬적으로 r-value 값을 l-value로 할당한다.
  • <= 연산자는 Non-blocking 연산자로서 r-value를 먼저 정의한 뒤, 그다음 병렬적으로 l-value에 할당한다.

 

< Simulation >

  • clk의 low level에서 cp의 상태값이 Positive edge로 변화하였다.
  • 따라서 clk의 다음 positive edge에서 flip_flop_current 값이 0 → 1로 변화하며, flip_flop_old 값은 첫 번째 플립플롭의 PDT에 의해서 아직 0으로 상태값이 유지된다.
  • 그리고, 다음 clk의 positive edge에서 flip_flop_old  값이 0 → 1로  값이 변화한다.

 

< RTL Analysis >

 

  • 첫 번째 플립플롭의 출력 값, Q가 두 번째 플립플롭의 입력 값, D에 들어가는 것을 확인함으로서 위 두 개의 플립플롭은 직렬로 연결되었음을 확인할 수 있다.

 

 

< Synthesis >