Menu

Chú thích trong Verilog: một dòng, nhiều dòng và quy ước

Cách viết chú thích một dòng và nhiều dòng trong Verilog, cùng các mẫu viết tài liệu mà kỹ sư thiết kế số dùng để giữ module dễ đọc khi chúng lớn dần.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

Hai dạng chú thích

Verilog hỗ trợ đúng hai cú pháp chú thích (comment), đều lấy từ C:

Toàn bộ cú pháp chỉ có vậy. Không có # như Python, không có -- như VHDL, không có kiểu Lisp. Chỉ có // và /* ... */.

Khi nào dùng kiểu nào

Gần như lúc nào bạn cũng sẽ dùng //. Nó ngắn hơn, không thể vô tình quên đóng, và hợp tự nhiên với cách viết Verilog (mỗi dòng một khai báo, chú thích nằm cùng dòng hoặc ngay dòng bên cạnh):

output reg [7:0] data,  // byte we shift out on tx_serial
output reg       valid, // high while data is being transmitted
input  wire      ready  // downstream consumer is ready to accept

/* ... */ chủ yếu dùng cho hai việc: các khối tiêu đề lớn ở đầu tệp, và tạm thời vô hiệu hóa một đoạn code khi gỡ lỗi. Trường hợp vô hiệu hóa khá nguy hiểm, đọc tiếp để biết vì sao.

Cái bẫy "không lồng nhau"

Chú thích khối không lồng nhau được. Nếu bạn cố chú thích hóa một vùng đã chứa sẵn chú thích khối, dấu */ đầu tiên sẽ đóng khối bên ngoài chứ không phải khối bên trong:

/* outer
   /* inner */    // <-- this */ closes the outer comment
   still active in the source as far as the parser is concerned
*/

Kết quả: một lỗi cú pháp ở chỗ không ngờ tới, trên một dòng trông có vẻ đúng.

Khi cần vô hiệu hóa một vùng, hãy chọn một trong hai cách:

  1. Thêm // vào đầu mỗi dòng. Phần lớn trình soạn thảo làm việc này chỉ với một phím tắt.

  2. Dùng một khối bảo vệ của bộ tiền xử lý:

    `ifdef DISABLED
        // code that should not compile
    `endif
    

Mẫu thứ hai cũng là cách giữ nhiều cấu hình build trong cùng một tệp.

Pragma tổng hợp: chú thích không chỉ là chú thích

Công cụ của các hãng dùng những chú thích có định dạng đặc biệt làm chỉ dẫn riêng. Trình mô phỏng vẫn bỏ qua chúng, nhưng công cụ tổng hợp thì đọc:

// synthesis translate_off
initial begin
    $display("simulator-only setup");
end
// synthesis translate_on

Hai pragma này bảo công cụ tổng hợp "bỏ qua mọi thứ giữa hai dấu này." Cách viết cụ thể khác nhau tùy hãng (synthesis, synopsys, pragma, xilinx, v.v.), hãy xem tài liệu của công cụ bạn dùng. Điều cần biết: chú thích trong Verilog đôi khi mang vai trò thực sự.

Quy ước khối tiêu đề

Các tệp Verilog dùng lâu dài gần như luôn bắt đầu bằng một khối tiêu đề. Định dạng cụ thể là quy định của từng nhóm, nhưng một ví dụ điển hình:

// -----------------------------------------------------------------------------
// Module      : uart_tx
// Description : 8-N-1 UART transmitter. Accepts a byte on `data` when `valid`
//               is asserted and shifts it out on `serial_out`. `baud_tick`
//               must pulse once per baud period.
// Ports       : clk        - system clock
//               reset_n    - active-low synchronous reset
//               baud_tick  - 1-cycle pulse at each baud interval
//               data       - byte to transmit
//               valid      - asserted to start a transmission
//               serial_out - the wire that leaves the FPGA
//               busy       - high while a frame is in flight
// Author      : example@team
// Revision    : 2026-05-26 - initial version
// -----------------------------------------------------------------------------

module uart_tx (
    input  wire       clk,
    input  wire       reset_n,
    input  wire       baud_tick,
    input  wire [7:0] data,
    input  wire       valid,
    output reg        serial_out,
    output reg        busy
);
    // ... body ...
endmodule

Mục đích không phải là trang trí. Mục đích là ai đó mở tệp này một năm sau (rất có thể là chính bạn) chỉ cần đọc bốn dòng là biết nó làm gì, nó cần gì và nó tạo ra gì. Lợi ích đó càng lớn khi dự án càng lớn.

Chú thích trong dòng thật sự có ích

Một lỗi phổ biến là chú thích cái gì một dòng làm trong khi code đã thể hiện rõ điều đó:

// bad - the comment restates the code
count <= count + 1;   // increment count

// better - the comment explains why this line is here
count <= count + 1;   // free-running cycle counter for timestamping

Thứ chú thích làm tốt nhất là giải thích vì sao, điều mà code tự nó không thể hiện được: một cách mã hóa kỳ lạ tuân theo mục nào của đặc tả, vì sao một thanh ghi rộng hơn một bit so với vẻ ngoài, vì sao nhánh default được đặt là 'x thay vì '0. Hãy dùng chú thích cho những điều đó. Để code nói những điều hiển nhiên.

Thử ngay

Khối bên dưới chứa mọi dạng chú thích. Chạy thử: đầu ra sẽ không làm bạn bất ngờ, nhưng cấu trúc tệp thì đáng để xem:

Giờ bạn đã thấy mọi dạng chú thích Verilog hỗ trợ. Các bài còn lại dùng chúng đúng như bạn mong đợi: khối tiêu đề ở đầu các module dài, // một dòng cạnh các port, và chú thích khối chỉ khi có cả một đoạn lập luận cần ghi lại.

Câu hỏi thường gặp

Viết chú thích trong Verilog như thế nào?

Verilog hỗ trợ hai kiểu chú thích, đều kế thừa từ C. // bắt đầu một chú thích kéo dài đến hết dòng. /* ... */ bao quanh một khối nhiều dòng. Trình biên dịch bỏ qua mọi thứ nằm giữa các dấu này; cả hai kiểu đều hợp lệ như nhau trong mọi tệp, dù là tệp tổng hợp được hay chỉ dùng để mô phỏng.

Chú thích Verilog có tổng hợp được không?

Chú thích không còn tồn tại sau khi phân tích cú pháp: công cụ tổng hợp bỏ chúng đi giống hệt trình mô phỏng. Ngoại lệ duy nhất là pragma tổng hợp: các chú thích có định dạng đặc biệt như // synthesis translate_off mà công cụ của các hãng nhận diện là chỉ thị. Cú pháp pragma phụ thuộc vào từng công cụ và không thuộc Verilog chuẩn.

Chú thích Verilog có lồng nhau được không?

Không, và đây là cái bẫy với người mới khi cố chú thích hóa một khối đã chứa sẵn /* ... */. Dấu */ đầu tiên bên trong sẽ đóng chú thích bên ngoài, khiến phần còn lại của khối trở thành code đang hoạt động. Hãy dùng // ở mỗi dòng, hoặc bọc cả vùng đó trong `ifdef SOMETHING_FALSE / `endif nếu bạn thật sự cần vô hiệu hóa một đoạn.

Chú thích tiêu đề trong Verilog nên có những gì?

Phần lớn các nhóm đặt một phần tiêu đề nhỏ ở đầu mỗi tệp: tên module, mục đích trong một câu, tóm tắt các port, tác giả/ngày và lịch sử sửa đổi. Định dạng cụ thể khác nhau; điều quan trọng là ai mở tệp cũng biết nó làm gì mà không cần đọc phần thân. Các thiết kế lớn còn thêm chú thích cho từng tín hiệu ngay cạnh mỗi khai báo port.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu