Menu

Verilog $display와 $monitor: testbench에서 출력하기

$display, $write, $monitor가 어떻게 동작하는지 - 쓰게 될 format specifier, 그 차이, 그리고 각각이 맞는 도구일 때.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

Verilog의 C printf 일족

세 시스템 태스크가 시뮬레이터의 stdout에 출력합니다.

  • $display - 한 번 출력, 줄바꿈 추가.
  • $write - 한 번 출력, 줄바꿈 없음.
  • $monitor - 관찰된 신호가 변할 때마다 자동으로 출력.

세 모두 printf처럼 format string과 인자 목록을 받습니다. format specifier는 비슷하지만 Verilog 특유입니다.

$display: 기본

$display는 일꾼입니다.

대략 이런 것을 보게 됩니다.

Hello, world.
byte_val  = ab
byte_val  = 10101011
byte_val  = 171
byte_val  = 171 (no padding)
multi: nibble=1010 count=42

메모.

  • %d는 피연산자 크기 기반 기본 너비로 패딩합니다. 8비트 reg라면 3자(255 들어갈 공간). 표 출력에서 보기 흉할 수 있어 %0d로 억제하세요.
  • %h, %b, %o도 기본 패딩이 비슷합니다. 정렬이 유용하지 않으면 testbench 코드 대부분이 %0 변형을 씁니다.
  • 줄 끝의 줄바꿈은 자동. $display의 format string 끝에 \n을 두지 마세요 - 빈 줄이 생깁니다.

Format Specifier

Verilog이 지원하는 세트.

Specifier의미
%bbinary
%ddecimal (신호가 signed면 signed)
%h 또는 %xhex
%ooctal
%c단일 ASCII 문자 (low 8비트)
%sstring
%t시뮬레이션 시간
%m현재 스코프의 계층 이름
%%literal %
%0Xleading 패딩 없음, %b, %d 등 어느 쪽이든

%b, %d, %h, %o가 95% 쓰게 될 넷입니다. %t가 그다음으로 흔합니다 - timestamp가 찍힌 로그 줄을 원할 때마다.

$write: 줄바꿈 없음

$write는 줄바꿈을 추가하지 않는 점 빼고 $display와 같습니다.

출력.

abc
done

루프 본문으로부터 한 줄을 만드는 데 유용.

$write("[");
for (integer i = 0; i < 8; i = i + 1) $write("%h ", arr[i]);
$display("]");

$monitor: 변경 시 자동 출력

$monitor는 watch list를 등록합니다. format string에 언급된 어떤 신호든 변할 때마다 시뮬레이터가 다시 평가하고 출력합니다.

입력 변경마다 한 줄씩 세 줄을 봅니다. 자극 변경 후 수동으로 $display를 호출할 필요 없음 - $monitor가 해 줍니다.

두 가지 제한.

  • 한 번에 활성인 $monitor는 하나뿐. 다시 호출하면 이전 watch list가 대체됩니다. 일시 억제와 재활성에는 $monitoroff$monitoron 사용.
  • 같은 time step 안의 변경은 출력 하나로 합쳐짐. 시간 5에 ab가 둘 다 변하면 monitor가 두 번이 아니라 한 번 발사되어 두 새 값을 함께 출력.

각각 언제 쓸까

  • $display: 대부분의 testbench 출력. 자극 후, 중요한 상태 전이 후, 또는 sampling always @(posedge clk) 블록 안에서 명시적으로 호출.
  • $write: 루프나 여러 작은 조각으로부터 한 줄을 만들 때.
  • $monitor: 작은 신호 집합을 연속적으로 추적하고 변할 때만 출력 보고 싶을 때. 초기 디버깅에 유용; 출력이 줄 수 측면에서 결정적이지 않아 regression 스크립트에는 다루기 어려움.

대부분의 워크플로에서는 $display로 충분합니다. 진짜로 연속적인 변경 기반 출력을 원할 때만 $monitor로 손이 갑니다.

시간 다루기

$time은 현재 시뮬레이션 시간을 64비트 정수로 반환합니다. %0t와 짝지으세요.

$display("at %0t: signal flipped", $time);

출력은 at 25: signal flipped처럼 보입니다(단위는 timescale에 따름).

sub-tick 정밀도가 필요하다면(드묾) 대신 $realtime을 쓰세요 - real을 반환합니다.

%t는 시뮬레이터가 고른 기본 너비로 시간을 자동 형식화합니다. %0t가 패딩을 벗깁니다.

클럭 edge에서 sampling

순차 설계를 모니터링하는 깔끔한 idiom: 사이클마다 한 번 출력하는 별도 always @(posedge clk) 블록.

이 sampling 패턴은 클럭당 로그 한 줄을 보장합니다 - 출력에 패턴 매칭하는 regression 테스트에 완벽.

파일에 로깅

$fopen으로 파일을 열고, $fdisplay(파일 핸들에 쓰는 점 빼고 $display처럼 동작)로 로깅.

integer fd;
initial begin
    fd = $fopen("results.txt", "w");
    $fdisplay(fd, "test=%s status=%s", test_name, status);
    $fclose(fd);
end

$fopen은 32비트 핸들을 반환합니다. $fdisplay, $fwrite, $fstrobe 등의 첫 인자로 전달하세요. 함수는 그 외에는 콘솔 출력 형제들과 동일합니다.

다음에 볼 내용

$display와 친구들이 텍스트 로그를 줍니다. 시각적 디버깅 - 신호를 시간에 따른 전압으로 보기 - 에는 VCD 파형이 필요합니다. 다음 문서 Dumpfile and VCD는 시뮬레이션을 스크럽 가능한 그래픽 파형으로 만드는 두 호출 $dumpfile$dumpvars를 다룹니다.

자주 묻는 질문

Verilog의 $display와 $monitor 차이는?

$display는 실행될 때 한 번 즉시 출력합니다 - C의 printf와 비슷. $monitor는 watch list를 등록합니다; list의 어떤 신호든 변할 때마다 형식 메시지가 자동으로 출력됩니다. 한 번에 활성인 $monitor는 하나뿐이며, 다시 호출하면 이전 watch list가 대체됩니다.

Verilog $display는 어떤 format specifier를 지원하나요?

흔한 것들: %b(binary), %d(decimal), %h(hex), %o(octal), %c(low 바이트의 단일 문자), %s(string), %t(시뮬레이션 시간), %m(계층 인스턴스 이름). 0 패딩을 없애려면 %0d 형태를 쓰세요 - %d는 기본 너비로 패딩하고 %0d는 패딩하지 않습니다.

Verilog의 $write란?

$write$display와 비슷하지만 줄바꿈을 추가하지 않습니다. 여러 호출로부터 한 줄의 출력을 만들고 싶을 때 유용합니다. 줄 끝의 $display(인자 없거나 줄바꿈 있는)가 줄을 종료합니다.

Verilog에서 시뮬레이션 시간은 어떻게 출력하나요?

%t format specifier와 함께 $time(또는 sub-tick 해상도가 필요하면 $realtime)을 사용합니다: $display("at time %t: ...", $time);. 기본 패딩을 없애려면 %0t. 시간 단위의 평범한 정수 카운트라면 $time%0d도 됩니다: $display("t=%0d", $time);.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기