Verilog 디스플레이 태스크 마스터하기: 효율적인 디버깅 및 로깅
디스플레이 시스템 태스크는 주로 시뮬레이션 흐름을 로그 파일로 추적하고 디버깅을 빠르게 돕기 위해 정보 및 디버그 메시지를 표시하는 데 사용됩니다. 다양한 디스플레이 태스크 그룹과 값 출력 형식이 있습니다.
Display/Write 태스크
문법
$display와 $write 모두 인자 리스트에 나타나는 순서대로 인자들을 표시합니다.
$display(<list_of_arguments>);
$write(<list_of_arguments>);
$write는 문자열 끝에 줄바꿈 문자 \n을 추가하지 않지만, $display는 추가합니다. 아래 예제에서 확인할 수 있습니다.
예제
module tb;
initial begin
$display ("이 줄은 새 줄로 끝남 ");
$write ("이 줄은 새 줄 없이,");
$write ("이렇게 이어짐. 새 줄로 시작하려면 줄바꿈 문자 사용 ");
$display ("이 줄은 항상 새 줄에서 시작!");
end
endmodule
시뮬레이션 로그
ncsim> run
이 줄은 새 줄로 끝남
이 줄은 새 줄 없이,이렇게 이어짐. 새 줄로 시작하려면 줄바꿈 문자 사용
이 줄은 항상 새 줄에서 시작!
ncsim: *W,RNQUIE: Simulation is complete.
Verilog 스트로브 (Strobes)
$strobe는 현재 델타 타임스텝이 끝날 때 변수들의 최종 값을 출력하며, $display와 비슷한 형식을 가집니다.
module tb;
initial begin
reg [7:0] a;
reg [7:0] b;
a = 8'h2D;
b = 8'h2D;
#10; // 시뮬레이션이 10ns에 도달할 때까지 대기
b <= a + 1; // a+1 값을 b에 할당
$display ("[$display] time=%0t a=0x%0h b=0x%0h", $time, a, b);
$strobe ("[$strobe] time=%0t a=0x%0h b=0x%0h", $time, a, b);
#1;
$display ("[$display] time=%0t a=0x%0h b=0x%0h", $time, a, b);
$strobe ("[$strobe] time=%0t a=0x%0h b=0x%0h", $time, a, b);
end
endmodule
$strobe가 10ns에서 변수 b의 최종 업데이트된 값 0x2E를 보여주는 반면, $display는 다음 시뮬레이션 델타인 11ns에서야 이를 포착함을 알 수 있습니다.
시뮬레이션 로그
ncsim> run
[$display] time=10 a=0x2d b=0x2d
[$strobe] time=10 a=0x2d b=0x2e
[$display] time=11 a=0x2d b=0x2e
[$strobe] time=11 a=0x2d b=0x2e
ncsim: *W,RNQUIE: Simulation is complete.
Verilog 연속 모니터 (Continuous Monitors)
$monitor은 인자 리스트의 변수나 표현식이 변경될 때마다 자동으로 값을 출력합니다. 인자 변수들이 업데이트될 때마다 $display를 호출하는 것과 비슷한 효과를 냅니다.
module tb;
initial begin
reg [7:0] a;
reg [7:0] b;
a = 8'h2D;
b = 8'h2D;
#10; // 시뮬레이션이 10ns에 도달할 때까지 대기
b <= a + 1; // a+1 값을 b에 할당
$monitor ("[$monitor] time=%0t a=0x%0h b=0x%0h", $time, a, b);
#1 b <= 8'hA4;
#5 b <= a - 8'h33;
#10 b <= 8'h1;
end
endmodule
$monitor은 메인 스레드 배경에서 실행되는 태스크처럼 생겨나서 인자 변수들의 값 변경을 모니터링하고 표시합니다. 시뮬레이션 중 언제든 새로운 $monitor 태스크를 발행할 수 있습니다.
시뮬레이션 로그
ncsim> run
[$monitor] time=10 a=0x2d b=0x2e
[$monitor] time=11 a=0x2d b=0xa4
[$monitor] time=16 a=0x2d b=0xfa
[$monitor] time=26 a=0x2d b=0x1
ncsim: *W,RNQUIE: Simulation is complete.
Verilog 포맷 지정자 (Format Specifiers)
디스플레이 함수 내부에서 변수를 출력하려면 각 변수에 적절한 포맷 지정자를 주어야 합니다.
| 인자 |
설명 |
| %h, %H |
16진수 형식으로 표시 |
| %d, %D |
10진수 형식으로 표시 |
| %b, %B |
2진수 형식으로 표시 |
| %m, %M |
계층적 이름 표시 |
| %s, %S |
문자열로 표시 |
| %t, %T |
시간 형식으로 표시 |
| %f, %F |
'real'을 10진수 형식으로 표시 |
| %e, %E |
'real'을 지수 형식으로 표시 |
module tb;
initial begin
reg [7:0] a;
reg [39:0] str = "Hello";
time cur_time;
real float_pt;
a = 8'h0E;
float_pt = 3.142;
$display ("a = %h", a);
$display ("a = %d", a);
$display ("a = %b", a);
$display ("str = %s", str);
#200 cur_time = $time;
$display ("time = %t", cur_time);
$display ("float_pt = %f", float_pt);
$display ("float_pt = %e", float_pt);
end
endmodule
시뮬레이션 로그
ncsim> run
a = 0e
a = 14
a = 00001110
str = Hello
time = 200
float_pt = 3.142000
float_pt = 3.142000e+00
ncsim: *W,RNQUIE: Simulation is complete.
Verilog 이스케이프 시퀀스 (Escape Sequences)
일부 문자는 줄바꿈, 탭, 폼 피드 등 다른 표시 목적을 나타내므로 특수 문자로 간주됩니다. 이러한 특수 문자를 출력하려면 각 특수 문자를 이스케이프해야 합니다.
| 인자 |
설명 |
| \n |
줄바꿈 문자 |
| \t |
탭 문자 |
| \\ |
\ 문자 |
| \" |
" 문자 |
| %% |
% 문자 |
module tb;
initial begin
$write ("줄바꿈 문자 \n");
$display ("탭 문자 \t stop");
$display ("이스케이프 \" %%");
/* // 컴파일 에러
$display ("이스케이프 없이 \n"); // 에러: 종료되지 않은 문자열
$display ("이스케이프 없이 \""); // 에러: 종료되지 않은 문자열
*/
end
endmodule
시뮬레이션 로그
ncsim> run
줄바꿈 문자
탭 문자 stop
이스케이프 " %
ncsim: *W,RNQUIE: Simulation is complete.