산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> verilog

Verilog 차단 vs 비차단 할당: 핵심 차이점 완벽 이해

차단 할당 (Blocking Assignment)

차단 할당문은 = 연산자를 사용하며, 절차적 블록 내에서 순차적으로 실행됩니다. 하지만 병렬 블록에서 실행되는 문장들의 실행을 막지는 않습니다.

module tb;
  reg [7:0] a, b, c, d, e;
  initial begin
    a = 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    b = 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c = 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    d = 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    e = 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

두 개의 initial 블록이 시뮬레이션 시작 시 병렬로 실행됩니다. 각 블록 내 문장들은 순차적으로 실행되며, 두 블록 모두 0ns에 완료됩니다. 구체적으로 변수 a가 먼저 할당되고, 그 다음 display 문, 그리고 나머지 문장들이 순서대로 실행됩니다. 이는 첫 번째 $display에서 변수 b와 c가 8'hxx로 나오는 출력에서 확인할 수 있습니다. 첫 번째 $display가 호출될 때 변수 b와 c에 대한 할당이 아직 실행되지 않았기 때문입니다.

시뮬레이션 로그

ncsim> run
[0] a=0xda b=0xx c=0xx
[0] a=0xda b=0xf1 c=0xx
[0] a=0xda b=0xf1 c=0x30
[0] d=0xaa e=0xx
[0] d=0xaa e=0x55
ncsim: *W,RNQUIE: Simulation is complete.

다음 예제에서는 같은 문장 집합에 몇 가지 지연을 추가하여 동작을 살펴보겠습니다.

module tb;
  reg [7:0] a, b, c, d, e;
  initial begin
    a = 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    #10 b = 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c = 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    #5 d = 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    #5 e = 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

시뮬레이션 로그

ncsim> run
[0] a=0xda b=0xx c=0xx
[5] d=0xaa e=0xx
[10] a=0xda b=0xf1 c=0xx
[10] a=0xda b=0xf1 c=0x30
[10] d=0xaa e=0x55
ncsim: *W,RNQUIE: Simulation is complete.

비차단 할당 (Non-blocking Assignment)

비차단 할당은 후속 문장의 실행을 차단하지 않고 할당을 예약하며, <= 기호로 지정합니다. 흥미롭게도 같은 기호가 표현식에서는 관계 연산자로, 비차단 할당 문맥에서는 할당 연산자로 사용됩니다. 위 첫 번째 예제에서 모든 = 기호를 비차단 할당 연산자 <=로 바꾸면 출력에 차이가 있음을 볼 수 있습니다.

module tb;
  reg [7:0] a, b, c, d, e;
  initial begin
    a <= 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    b <= 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c <= 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    d <= 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    e <= 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

모든 $display 문이 'h'x를 출력하는 것을 볼 수 있습니다. 이 동작의 이유는 비차단 할당의 실행 방식에 있습니다. 특정 타임스텝의 모든 비차단 문장의 RHS가 캡처되고, 다음 문장으로 넘어갑니다. 캡처된 RHS 값은 타임스텝이 끝날 때 LHS 변수에 할당됩니다.

시뮬레이션 로그

ncsim> run
[0] a=0xx b=0xx c=0xx
[0] a=0xx b=0xx c=0xx
[0] a=0xx b=0xx c=0xx
[0] d=0xx e=0xx
[0] d=0xx e=0xx
ncsim: *W,RNQUIE: Simulation is complete.

위 예제의 실행 흐름을 분석하면 다음과 같습니다.

|__ 블록1 생성: initial
| |___ 시간 #0ns: a <= 8'DA, 비차단이므로 RHS 값(8'hDA) 기록 후 다음 단계 실행
| |___ 시간 #0ns: $display()는 차단이므로 실행: 하지만 a가 새 값을 받지 못해 a=8'hx
| |___ 시간 #0ns: b <= 8'F1, 비차단이므로 RHS 값(8'hF1) 기록 후 다음 단계 실행
| |___ 시간 #0ns: $display()는 차단이므로 실행. 하지만 b가 새 값을 받지 못해 b=8'hx
| |___ 시간 #0ns: c <= 8'30, 비차단이므로 RHS 값(8'h30) 기록 후 다음 단계 실행
| |___ 시간 #0ns: $display()는 차단이므로 실행. 하지만 c가 새 값을 받지 못해 c=8'hx
| |___ 타임스텝 및 initial 블록 종료, 캡처된 값을 변수 a, b, c에 할당
|__ 블록2 생성: initial
| |___ 시간 #0ns: d <= 8'AA, 비차단이므로 RHS 값(8'hAA) 기록 후 다음 단계 실행
| |___ 시간 #0ns: $display()는 차단이므로 실행: 하지만 d가 새 값을 받지 못해 d=8'hx
| |___ 시간 #0ns: e <= 8'55, 비차단이므로 RHS 값(8'h55) 기록 후 다음 단계 실행
| |___ 시간 #0ns: $display()는 차단이므로 실행. 하지만 e가 새 값을 받지 못해 e=8'hx
| |___ 타임스텝 및 initial 블록 종료, 캡처된 값을 변수 d, e에 할당
|__ 시뮬레이션 종료 #0ns

이제 두 번째 예제를 사용하여 모든 차단 문을 비차단으로 바꿔보겠습니다.

module tb;
  reg [7:0] a, b, c, d, e;
  initial begin
    a <= 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    #10 b <= 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c <= 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    #5 d <= 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    #5 e <= 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

다시 한 번 출력이 이전과 다름을 볼 수 있습니다.

시뮬레이션 로그

ncsim> run
[0] a=0xx b=0xx c=0xx
[5] d=0xx e=0xx
[10] a=0xda b=0xx c=0xx
[10] a=0xda b=0xx c=0xx
[10] d=0xaa e=0xx
ncsim: *W,RNQUIE: Simulation is complete.

실행 흐름 분석:

|__ #0ns에서 블록1 생성: initial
| |___ 시간 #0ns: a <= 8'DA, 비차단이므로 RHS 값(8'hDA) 기록 후 다음 단계 실행
| |___ 시간 #0ns: $display()는 차단이므로 실행: 하지만 a가 새 값을 받지 못해 a=8'hx
| |___ 타임스텝 종료: 캡처된 값을 변수 a에 할당, 이제 a는 8'hDA
| |___ 10 타임 유닛만큼 대기하여 #10ns로 시간 진행
| | |___ 시간 #10ns: b <= 8'F1, 비차단이므로 RHS 값(8'hF1) 기록 후 다음 단계 실행
| |___ 시간 #10ns: $display()는 차단이므로 실행. 하지만 b가 새 값을 받지 못해 b=8'hx
| |___ 시간 #10ns: c <= 8'30, 비차단이므로 RHS 값(8'h30) 기록 후 다음 단계 실행
| |___ 시간 #10ns: $display()는 차단이므로 실행. 하지만 c가 새 값을 받지 못해 c=8'hx
| |___ 타임스텝 및 initial 블록 종료, 캡처된 값을 변수 b, c에 할당
|__ #0ns에서 블록2 생성: initial
| |___ 5 타임 유닛만큼 대기하여 #5ns로 시간 진행
| | |___ 시간 #5ns: d <= 8'AA, 비차단이므로 RHS 값(8'hAA) 기록 후 다음 단계 실행
| |___ 시간 #5ns: $display()는 차단이므로 실행: 하지만 d가 새 값을 받지 못해 d=8'hx
| |___ 타임스텝 종료: 캡처된 값을 변수 d에 할당, 이제 d는 8'hAA
| |___ 5 타임 유닛만큼 대기하여 #5ns로 시간 진행
| | |___ 시간 #10ns: e <= 8'55, 비차단이므로 RHS 값(8'h55) 기록 후 다음 단계 실행
| |___ 시간 #10ns: $display()는 차단이므로 실행. 하지만 e가 새 값을 받지 못해 e=8'hx
| |___ 타임스텝 및 initial 블록 종료, 캡처된 값을 변수 e에 할당, 이제 e는 8'h55
|__ 시뮬레이션 종료 #10ns

verilog

  1. 버릴로그(Verilog) 입문: 디지털 회로 설계를 위한 하드웨어 기술 언어
  2. Verilog 결합(Concatenation) & 복제(Replication) 연산자 실전 가이드
  3. Verilog 함수 마스터하기: 효율적인 RTL 설계를 위한 활용법
  4. Verilog 태스크 이해: 함수와의 차이점, 문법, 활용법
  5. Verilog 클럭 생성기: 설계 및 구현 가이드
  6. Verilog 수학 함수 마스터하기: 효율적인 하드웨어 설계를 위한 활용
  7. Verilog $timeformat 마스터하기: 정밀도 및 표시 제어
  8. 모든 범위에서 Verilog Timescale 이해 및 출력하기
  9. Verilog 파일 I/O 마스터하기: 열기, 읽기, 쓰기, 닫기
  10. Verilog 입문: Hello World 예제