- 1 1. Giới thiệu: Tầm quan trọng và mục đích của “display” trong Verilog
- 2 2. Cơ bản về $display: Cú pháp, mục đích và lưu ý
- 3 3. So sánh các system task log: $display・$write・$strobe・$monitor
- 4 4. Định dạng và kỹ thuật hiển thị nâng cao
- 5 5. Ví dụ thực tiễn: Sử dụng $display trong testbench và module
- 6 6. Ứng dụng điều khiển hiển thị (pixel / text / hình ảnh)
- 7 7. Mẹo và phân chia theo tình huống
- 8 8. FAQ (Câu hỏi thường gặp)
- 9 9. Kết luận & Bước tiếp theo
1. Giới thiệu: Tầm quan trọng và mục đích của “display” trong Verilog
“display” trong Verilog là gì?
$display
trong Verilog là một trong những system task, được sử dụng để “hiển thị” trạng thái nội bộ của chương trình trong quá trình mô phỏng. Tương tự như printf
trong ngôn ngữ C, nó cho phép in ra giá trị của tín hiệu, biến, hoặc chuỗi lên terminal/console. Đây là một công cụ quan trọng để debug và kiểm tra hoạt động.
Tại sao $display
không thể thiếu trong phát triển Verilog
- Nâng cao hiệu quả debug: Trong thiết kế mạch phức tạp, việc quan sát tín hiệu bên trong rất quan trọng. Với
$display
, bạn có thể kiểm tra ngay lập tức giá trị tín hiệu khi mô phỏng. - Trực quan hóa mô phỏng: Khi cần theo dõi sự thay đổi giá trị tại thời điểm cụ thể, chỉ xem waveform có thể chưa đủ. Log hiển thị mang lại độ tin cậy cao.
- Hữu ích cho tài liệu: Khi truyền đạt ý tưởng thiết kế hoặc quy tắc hoạt động cho kỹ sư khác, log hiển thị kèm chú thích sẽ giúp dễ hiểu hơn.
Mục tiêu và cấu trúc của bài viết
Bài viết này sẽ lần lượt giải thích:
- Cách viết và sử dụng cơ bản: Giới thiệu cú pháp và cách dùng
$display
. - So sánh với các system task khác: Như
$write
,$strobe
,$monitor
. - Định dạng và kỹ thuật nâng cao: Sử dụng các định dạng như
%d
,%b
,%h
,%s
. - Ví dụ thực tiễn: Sử dụng trong testbench với mã minh họa.
- Ứng dụng điều khiển hiển thị: Bao gồm ví dụ LCD và monitor.
Qua cấu trúc này, người học từ cơ bản đến trung cấp có thể nắm chắc $display
trong Verilog và áp dụng ngay vào thực tế. Các phần tiếp theo sẽ đi kèm ví dụ minh họa dễ hiểu.
2. Cơ bản về $display
: Cú pháp, mục đích và lưu ý
Cú pháp cơ bản của $display
Cú pháp cơ bản khi sử dụng $display
trong Verilog:
$display("chuỗi hoặc định dạng", tín_hiệu1, tín_hiệu2, ...);
- Chuỗi: Chứa text hoặc định dạng (ví dụ:
%d
,%b
,%h
). - Tham số: Gồm các tín hiệu/biến tương ứng để in ra.
Ví dụ: Hiển thị clock và reset
$display("Time=%0t : clk=%b, reset=%b", $time, clk, reset);
Kết quả: thời gian mô phỏng cùng giá trị tín hiệu clk và reset được in ra.
Mục đích sử dụng của $display
- Kiểm tra tiến trình mô phỏng
Chèn$display
tại vị trí cần theo dõi để biết chương trình chạy đến đâu. - Xem giá trị tín hiệu
Giúp dễ hiểu hơn so với chỉ xem waveform. - Thông báo có điều kiện
Kết hợp vớiif
để in log khi điều kiện thỏa mãn. Ví dụ:if (reset) $display("Reset asserted at %0t", $time);
So sánh $display
và $write
$display
tự động xuống dòng sau khi in, còn $write
thì không.
Ví dụ:
$display("Hello");
$display("World");
Kết quả:
Hello
World
$write("Hello");
$write("World");
Kết quả:
HelloWorld
→ Khi cần log có cấu trúc từng dòng: dùng $display
. Khi cần in nối tiếp: dùng $write
.
Lưu ý khi sử dụng
- Tránh in quá nhiều: Nếu in mỗi chu kỳ clock, log sẽ quá lớn → nên dùng điều kiện lọc.
- Tận dụng thời gian mô phỏng: In
$time
hoặc$realtime
để theo dõi thời điểm chính xác. - Chỉ dùng cho mô phỏng:
$display
không được tổng hợp khi thiết kế FPGA/ASIC.
3. So sánh các system task log: $display・$write・$strobe・$monitor
Ngoài $display
, Verilog còn có các system task khác để xuất log. Mỗi task có thời điểm và mục đích khác nhau, vì vậy cần hiểu rõ để debug hiệu quả.
$display
: Task hiển thị tiêu chuẩn
- Đặc điểm
Tự động xuống dòng sau khi in, log rõ ràng từng dòng. - Mục đích
Dùng phổ biến nhất, in một lần tại thời điểm gọi.
$write
: Hiển thị không xuống dòng
- Đặc điểm
Không thêm ký tự xuống dòng. - Mục đích
Khi muốn in nhiều giá trị trên cùng một dòng. - Ví dụ
$write("A=%d, ", a); $write("B=%d", b);
→ Kết quả:A=5, B=10
$strobe
: In giá trị sau khi chu kỳ mô phỏng kết thúc
- Đặc điểm
In giá trị cuối cùng đã ổn định sau khi tất cả tín hiệu được cập nhật. - Mục đích
Tránh in giá trị tạm thời trong điều kiện race. - Ví dụ
$strobe("Time=%0t, signal=%b", $time, sig);
$monitor
: Theo dõi tự động
- Đặc điểm
Tự động in log mỗi khi tín hiệu thay đổi. - Mục đích
Thích hợp để giám sát liên tục. - Ví dụ
$monitor("At %0t: a=%b, b=%b", $time, a, b);
Bảng so sánh
Task | Xuống dòng | Thời điểm xuất | Mục đích chính |
---|---|---|---|
$display | Có | Khi được gọi | Log cơ bản |
$write | Không | Khi được gọi | Hiển thị cùng dòng |
$strobe | Có | Sau chu kỳ mô phỏng | Xem giá trị ổn định |
$monitor | Có | Khi tín hiệu thay đổi | Theo dõi liên tục |
Mẹo sử dụng
- Dùng
$display
cho trường hợp cơ bản - Dùng
$write
khi muốn in cùng dòng - Dùng
$strobe
để đảm bảo giá trị ổn định - Dùng
$monitor
để theo dõi dài hạn
4. Định dạng và kỹ thuật hiển thị nâng cao
$display
và $write
hỗ trợ định dạng giống như printf
trong C. Điều này giúp hiển thị tín hiệu/biến dưới nhiều dạng khác nhau, hỗ trợ debug hiệu quả.
Các định dạng cơ bản
Ký hiệu | Nội dung | Kết quả |
---|---|---|
%b | Nhị phân (binary) | 1010 |
%d | Thập phân (decimal) | 10 |
%h | Thập lục phân (hexadecimal) | A |
%o | Bát phân (octal) | 12 |
%c | Ký tự ASCII | A |
%s | Chuỗi | Hello |
%t | Thời gian mô phỏng | #100 |
%m | Tên module (hierarchy) | top.u1.u2 |
Ví dụ thực tế
- In cùng lúc nhiều dạng
$display("data = %b (bin), %d (dec), %h (hex)", data, data, data);
- Xem hierarchy
$display("Module hiện tại: %m");
- In thời gian
$display("Time=%0t: clk=%b", $time, clk);
Kỹ thuật nâng cao
- Bổ sung số 0 / định dạng số chữ số
$display("Count=%04d", count);
→Count=0012
- Phân biệt có dấu/không dấu:
%d
là có dấu,%u
là không dấu. - In nhiều dòng: Dùng
\n
để xuống dòng trong chuỗi.
Lưu ý
- Chú ý độ rộng bit: Có thể gây tràn hoặc sai số khi dùng
%d
. - Xử lý giá trị chưa xác định (X, Z):
%b
sẽ in trực tiếpx
hoặcz
.
5. Ví dụ thực tiễn: Sử dụng $display
trong testbench và module
Bây giờ, chúng ta sẽ xem các ví dụ thực tế để thấy rõ cách sử dụng $display
. Từ testbench cơ bản đến debug có điều kiện.
Ví dụ cơ bản: In trong testbench
Chèn $display
trong testbench để quan sát tiến trình mô phỏng:
module tb_counter;
reg clk;
reg reset;
wire [3:0] count;
// DUT (Device Under Test)
counter uut (
.clk(clk),
.reset(reset),
.count(count)
);
// Tạo clock
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// Kịch bản test
initial begin
reset = 1;
#10 reset = 0;
#50 $finish;
end
// Hiển thị trạng thái
always @(posedge clk) begin
$display("Time=%0t | reset=%b | count=%d", $time, reset, count);
end
endmodule
→ Mỗi lần clock lên cạnh, log sẽ in giá trị của reset
và count
.
Ví dụ có điều kiện
always @(posedge clk) begin
if (count == 4'd10) begin
$display("Đã đạt count=10 (Time=%0t)", $time);
end
end
→ Tránh log dư thừa, chỉ in khi cần.
Thông báo debug
always @(posedge clk) begin
if (count > 4'd12) begin
$display("WARNING: tràn count! Time=%0t, value=%d", $time, count);
end
end
→ Giúp phát hiện nhanh bug.
Giám sát nhiều tín hiệu
$display("Time=%0t | clk=%b | reset=%b | A=%h | B=%h | SUM=%h",
$time, clk, reset, A, B, SUM);

Tóm tắt điểm chính
- Hiển thị tiến trình trong testbench
- Dùng điều kiện để lọc log
- Thêm cảnh báo để phát hiện lỗi
- Sắp xếp nhiều tín hiệu trên 1 dòng
6. Ứng dụng điều khiển hiển thị (pixel / text / hình ảnh)
$display
dùng để in text trong mô phỏng, nhưng Verilog cũng có thể điều khiển hiển thị thực tế trên LCD, VGA, HDMI.
Khái niệm cơ bản
- HSYNC: tín hiệu đồng bộ ngang
- VSYNC: tín hiệu đồng bộ dọc
- RGB: dữ liệu màu pixel
Ví dụ 1: Hiển thị thanh màu
always @(posedge clk) begin
if (h_counter < 100) rgb <= 24'hFF0000; // Đỏ
else if (h_counter < 200) rgb <= 24'h00FF00; // Xanh lá
else if (h_counter < 300) rgb <= 24'h0000FF; // Xanh dương
else rgb <= 24'h000000; // Đen
end
Ví dụ 2: Hiển thị ký tự
// Hiển thị 'A'
if (font_rom[char_code][y][x] == 1'b1)
rgb <= 24'hFFFFFF; // Trắng
else
rgb <= 24'h000000; // Nền đen
Ví dụ 3: Hiển thị hình ảnh
rgb <= image_rom[addr]; // Đọc dữ liệu màu từ ROM
Sự khác biệt
$display
: chỉ mô phỏng (text)- Điều khiển hiển thị: tạo tín hiệu video (phần cứng thực)
7. Mẹo và phân chia theo tình huống
Trong mô phỏng
- Dùng
$display
để log debug - Tránh in quá nhiều bằng cách lọc điều kiện
- Kết hợp nhiều task:
$monitor
: theo dõi liên tục$strobe
: giá trị ổn định$write
: hiển thị cùng dòng
Trong hiển thị thực tế
- 7-seg: hiển thị số đếm
- LCD/VGA: hiển thị ký tự và hình ảnh
- Overlay debug: chèn giá trị debug lên màn hình
Kinh nghiệm thực tế
- Bắt đầu debug bằng mô phỏng (
$display
), sau đó chuyển sang phần cứng - Kết hợp log text và waveform để dễ phân tích
- Thống nhất format log trong nhóm phát triển
8. FAQ (Câu hỏi thường gặp)
Q1. Khác nhau giữa $display
và $monitor
?
A. $display
: in 1 lần khi gọi. $monitor
: tự động in mỗi khi tín hiệu thay đổi.
Q2. Khi nào dùng $strobe
?
A. Khi nhiều tín hiệu thay đổi cùng lúc, $strobe
in giá trị cuối cùng đã ổn định.
Q3. Dùng %m
để làm gì?
A. In tên module hiện tại (hierarchy). Hữu ích trong thiết kế lớn.
Q4. Log quá nhiều, xử lý thế nào?
- Dùng
if
để lọc - Chỉ in sự kiện quan trọng
- Dùng
$monitor
cho ít tín hiệu - Xuất ra file để lọc
Q5. $display
có dùng được trong phần cứng không?
A. Không. Đây là task chỉ dành cho mô phỏng. Trong FPGA/ASIC, nó bị bỏ qua.
Q6. Hiển thị chữ/hình trên thực tế thì sao?
A. Phải dùng mạch tạo tín hiệu video:
- 7-seg: hiển thị số cơ bản
- LCD/VGA: điều khiển HSYNC, VSYNC, RGB
- Ký tự: dùng font ROM
- Hình ảnh: đọc bitmap từ ROM
9. Kết luận & Bước tiếp theo
Tóm tắt nội dung
$display
: in tín hiệu/biến trong mô phỏng, giốngprintf
.- Các task liên quan:
$write
,$strobe
,$monitor
. - Sử dụng định dạng:
%b
,%d
,%h
,%m
,%t
. - Ví dụ thực tiễn: testbench, debug điều kiện.
- Ứng dụng mở rộng: điều khiển LCD/VGA, hiển thị text/hình ảnh.
Bước tiếp theo
- SystemVerilog: hỗ trợ debug nâng cao.
- Kết hợp waveform: vừa log text vừa xem tín hiệu.
- Thực hành phần cứng: hiển thị trên FPGA.
- Phát triển nhóm: thống nhất format log.
Kết lời
$display
không chỉ là công cụ in text, mà là vũ khí debug mạnh mẽ trong Verilog. Khi kết hợp với điều khiển hiển thị thực tế, bạn có thể vừa mô phỏng vừa tạo tín hiệu video trên FPGA. Hy vọng bài viết này giúp bạn hiểu và ứng dụng hiệu quả $display
.