[SystemVerilog 실무] 4. 절차적 블록과 제어 구조 이해하기
본문 바로가기
지식 공유/SystemVerilog

[SystemVerilog 실무] 4. 절차적 블록과 제어 구조 이해하기

by 긍수저 2025. 5. 10.
반응형

SystemVerilog는 여러 프로세스 모델을 지원하여, 다양한 시나리오의 동시성(Concurrency) 및 동기화(Synchronization)을 표현할 수 있습니다. 본 포스트에서는 정적 프로세스와 동적 프로세스, 그리고 race condition을 방지하기 위한 시뮬레이션 시간 모델에 대해 설명합니다.


정적 프로세스 (Static Processes)

SystemVerilog에서 가장 기본적인 프로세스는 always와 initial입니다.

  • always block
    특정 이벤트에 반응하여 반복적으로 실행됩니다.
always @(posedge clk)
  ... // clock edge에 반응
always @(a or b)
  ... // a, b 중 하나라도 바뀌면 실행
  • initial block
    시뮬레이션 시작 시 단 한 번만 실행됩니다.
initial begin
  ...
end

동적 프로세스 (Dynamic Processes)

동적 프로세스는 fork ... join 문장을 통해 병렬 실행을 표현합니다. 다양한 종료 조건에 따라 다음과 같이 세분화됩니다.

  • fork ... join
    모든 병렬 Thread가 종료될 때까지 대기합니다.
fork
  task1();
  task2();
join

  • fork ... join_any
    하나의 Thread라도 종료되면 전체 종료로 간주합니다.
fork
  task1();
  task2();
join_any

  • fork ... join_none
    Thread들을 병렬로 실행하되, 부모 프로세스는 즉시 다음 코드 실행을 시작합니다.
fork
  task1();
  task2();
join_none

  • join 스타일의 선택은 testbench의 구조와 병렬 task의 동기화 수준에 따라 결정됩니다.


Process 종료 제어: wait fork vs disable fork

  • wait fork
    fork ... join_none 같은 구조에서, 모든 Thread가 종료될 때까지 기다립니다.
fork
  a = #10 1;
  b = #20 2;
join_none
wait fork; // 여기서 대기
  • disable fork
    병렬 실행 중인 Thread들을 즉시 강제로 종료시킵니다.
fork
  repeat (100) @(posedge clk);
join_none
disable fork; // Thread 중단

 


Deep Talk: 시뮬레이션 Race Condition

Race Condition이란?

출력 값이 이벤트 순서나 타이밍에 의존하여 예기치 않게 결정되는 상황입니다.

  • 하드웨어 레이스
    조합 회로에서 전파 지연으로 인해 발생
    → 클록 도메인 간 리셋에서 문제 가능성 큼

  • 시뮬레이션 유도 레이스
    시뮬레이터가 실제 병렬 동작을 순차적으로 처리하기 때문에 발생
    → 예: 두 assign 구문이 동시에 같은 변수에 접근할 경우

Verilog의 4단계 Time Slot 큐 모델

Verilog 시뮬레이터는 한 시점에서 발생한 이벤트를 다음 네 단계로 구분해 처리합니다.

  1. Active Events
    즉시 실행되는 이벤트 (예: a = 10;)
  2. Inactive Events
    #0 지연으로 예약된 이벤트 (예: #0 a = 20;)
  3. Non-Blocking Assignments (NBA)
    <= 연산자로 예약된 이벤트
  4. Postponed
    $monitor처럼 모든 연산 이후에 실행되는 이벤트

이러한 단계적 처리 덕분에 <= 연산을 활용하면 race condition을 줄일 수 있습니다.

 


SystemVerilog의 Time Slot 큐 모델

이벤트 종류 특징 예시
Active Event 즉시 실행: 현재 타임 슬롯에서 실행. a = 5;
Inactive Event 타임 슬롯 끝난 후 실행: #0 지연을 사용. #0 a = 5;
Non-Blocking Assignment (NBA) 다음 타임 슬롯에서 반영: <= 사용하여 실행 예약. a <= 5;
Observed Event 값 변화 추적: 값이 변경될 때마다 자동으로 실행되어 출력. $monitor("a = %0d", a);
Reactive Event 조건 변화에 반응: 조건이 변화하면 즉시 실행. always @(a) $display("a changed");
Re-Inactive Reactive + Inactive: 조건 변화 후 다음 타임 슬롯에서 실행. always @(a) #1 b = a + 1;
Re-NBA Reactive + Non-Blocking Assignment: 조건 변화 후 다음 타임 슬롯에서 NBA 실행. always @(a) a <= a + 1;

 

반응형

댓글