ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Verilog Simulation 이해하기 - Non-blocking과 Blocking assigment의 순서
    Tech/Verilog 2013. 10. 8. 20:10

    Verilog Simulation은 Cycle-accurate Simulation이 가능하다는 장점이 있는 반면, 같은 time step T에 해당하는 모든 event가 동시에 수행된다는 점에서 복잡하기도 하다. 특히 순차적으로 동작하는 blocking statements와 동시에 동작하는 non-blocking statement가 섞여있으면 누가 더 먼저 실행되나? 헷갈리게 된다. 이렇게 Verilog Simulation 상의 Event 처리 순서가 궁금할 때, Verilog Simulation Refernce Model을 참조해서 읽어보면 애매한 부분들이 어느정도 해결된다.

    본 포스팅에서는 바로 그 Verilog Simulation Reference Model 및 동작 순서에 대해서 간략히 정리하려고 하는데, 더 자세히 알고 싶다면 아래 Article을 참조하면 된다.

    Clifford E. Cummings, “Verilog Nonblocking Assignments With Delays, Myths & Mysteries”, SNUG 2002.


    Verilog Simulation Reference Model


    Verilog Simulation은 Cycle-accurate하게 동작하기 위해서 Simulation Time에 따라 동일한 Time에 발생하는 Event를 한꺼번에 큐에 넣은 뒤에 하나씩 처리하는 방식으로 진행된다. Simulation이 시작하면, 시간 T는 0, 모든 net은 HiZ, 모든 변수는 X (unknown)로 설정된 뒤, initial이나 always 등의 procedural block이 active되면서 이벤트를 처리하기 시작한다. Pseudo-code형태로 표현하면 아래와 같다.

    while (there are events) {              // 이벤트가 있다면
        if (there are active events) {      // Active event 가 있다면,
            E = any active event;           // Active event를 E라 하자.
            if (E is an update event) {     // E가 상태 업데이트 이벤트라면
                update the modified object; // 상태를 업데이트 하고,
                add evaluation events for sensitive processes to event queue;
                                            // 업데이트된 변수에 sensitive한 procedure를
                                            // event queue에 추가한다.
            }
            else {                          // E가 상태 업데이트 이벤트가 아니라면,
                evaluate the process;       // 수행하고, (combinational 연산의 경우에 해당)
                add update events to the event queue;
                                            // 상태 업데이트 이벤트로 추가한다.
            }
        }
    
        else if (there are nonblocking update events) { // Nonblocking 으로 상태 업데이트
                                                        // 이벤트가 있다면 (<= 대입의 경우)
            active all nonblocking update events;       // 모두 update event queue로 추가하고
        }
    
        else {
            advance T to the next event time;         // 다음 Time step T로 이동
            activate all inactive events for time T;  // T에 해당하는 event는 모두 Active시킨다.
        }
    }
    


    그림으로 그려보면 아래와 같이 나타난다.



    정리해보면 Verilog Simulation에서는

    • =를 이용해 대입한 Blocking assignments
    • 대입문에서의 Right Hand Side (A<=B+C라 하면 B+C 에 해당하는 combinational logic)
    • assign D = E 에 해당하는 Continuous assignment
    • 그리고 $display 명령어

    가 가장 먼저 실행되며, (이 때, 이들 4가지의 서로 간 실행 순서는 상관없다.) 그 뒤로

    • <=로 대입되는 Nonblocking assignment

    의 업데이트가 이루어진다. 이 때, Nonblocking으로 업데이트되는 변수에 관계있는 Event들은 추가적으로 Active Event로 등록된다. Event Queue는 이렇게 추가된 Event들까지 모두 처리한 이후에, 더이상 queue에 event가 남아있지 않을 때 종료되며, 최종적으로는 아래 2가지 명령어를 처리하고 다음 Time step으로 이동한다.

    • $monitor, $strobe

    따라서, Verilog Simulation에서 Non-blocking 등으로 대입한 변수의 변화를 확인하고자 한다면 $monitor를 써야한다. 몇가지 추가적인 예제를 보면서 이 순서를 이해해보자.



    Verilog Simulation에서 헷갈리기 쉬운 몇가지 예제들


    module display_cmds;
    reg a;
    initial $monitor(“\$monitor: a = %b”, a);
     initial begin
     $strobe (“\$strobe : a = %b”, a);
     a = 0;
     a <= 1;
     $display (“\$display: a = %b”, a);
     #1 $finish;
     end
     endmodule
    


    위 결과가 어떻게 출력될까? 아래와 같이 나타난다.


    $display: a = 0
    $monitor: a = 1
    $strobe : a = 1
    

    앞서 이야기했듯이, $display는 Nonblocking assignment에 앞서 수행되기 때문에 a 값이 미처 업데이트되지 않았다. 

    module nb_schedule1;
    reg a, b;
     initial begin
     a = 0;
     b = 1;
     a <= b;
     b <= a;
     $monitor
     $display
     $strobe
     #0 $display
     #1 $monitor
     $display
     $strobe
     $display
     #1 $finish;
     end
    endmodule
    


    이 예제는 결과가 어떻게 출력될까? #0 와 같이 다소 tricky한 문법이 사용되었는데, 위 Simulation Model 대로만 해석하면 된다. 본 예제를 통해, #0를 사용한다고해서 blocking assignment의 가장 마지막에 동작한다거나 하는 효과를 얻을 수 없음을 알 수 있다. 결과 콘솔은 아래와 같이 나타난다.


    0ns: $display: a=0  b=1
    0ns: #0      : a=0  b=1
    0ns: $monitor: a=1  b=0
    0ns: $strobe : a=1  b=0
    1ns: $display: a=1  b=0
    1ns: #0      : a=1  b=0
    1ns: $monitor: a=1  b=0
    1ns: $strobe : a=1  b=0
    


    즉, Verilog Simulation에서 non-blocking assignment는 모든 active event가 수행된 뒤에 일어나기 때문에, $display가 먼저 실행된다. 따라서 $display로는 Nonblocking assignment의 업데이트 결과를 볼 수 없으며, Nonblocking assignment를 사용해서 대입 된 변수는 $monitor 를 통해서 확인하도록 하자.


    댓글

Copyright 2022 JY