Hướng dẫn bắt đầu với Verilog
Hãy bắt đầu hành trình khám phá logic số của bạn với hướng dẫn Verilog dành cho người mới bắt đầu này.
Từ lâu, các ngôn ngữ lập trình máy tính như FORTRAN, Pascal và C đã được sử dụng để mô tả các chương trình máy tính và việc thực thi mã của chúng diễn ra tuần tự. Nhưng không có ngôn ngữ nào để mô tả các mạch kỹ thuật số. Đây là lúc Ngôn ngữ Mô tả Phần cứng (HDL) ra đời. HDL thậm chí còn phổ biến cho mục đích xác minh. Về cơ bản có hai loại HDL:
- Verilog HDL
- VHDL ( Ngôn ngữ mô tả phần cứng mạch tích hợp tốc độ rất cao (VHSIC) )
Lưu ý: Verilog HDL và VHDL không giống nhau. VHDL được sử dụng trước khi Verilog ra đời.
Verilog là gì?
Verilog là ngôn ngữ mô tả phần cứng được sử dụng để hiện thực hóa các mạch kỹ thuật số thông qua mã lệnh. Verilog HDL thường được sử dụng cho mục đích thiết kế ( RTL ) và kiểm chứng (phát triển mạch kiểm thử) cho cả các mạch tích hợp lập trình được ( FPGA ) và các mạch tích hợp chuyên dụng ( ASIC) .
Về cơ bản, có ba cấp độ trừu tượng (các góc nhìn hoặc quan điểm khác nhau để xem xét hoặc phân tích một thiết kế) khi viết mã bằng Verilog:
- Mô hình hóa ở cấp độ cổng
- Mô hình hóa luồng dữ liệu
- Mô hình hành vi
Lưu ý: Trước khi đi sâu vào các cấp độ trừu tượng, trước tiên chúng ta hãy tìm hiểu RTL là gì.
Mức truyền tải thanh ghi (RTL) : Mức truyền tải thanh ghi là một mức độ trừu tượng thấp được sử dụng trong thiết kế số để mô tả hành vi và chức năng của một mạch hoặc hệ thống số. RTL là một phương pháp tổng quát mô tả các mạch số theo luồng dữ liệu ở cấp độ thanh ghi .
Mô hình hóa ở cấp độ cổng
Nếu một mạch điện được biểu diễn hoàn toàn bằng các cổng logic cơ bản, nó được gọi là mô hình hóa ở cấp độ cổng. Ví dụ, hãy xem mạch bán cộng bên dưới, nơi ta có thể biểu diễn nó một cách đơn giản bằng các cổng AND và XOR .

Bộ cộng một nửa
Mức độ trừu tượng này bao gồm việc mô tả mạch bằng cách sử dụng các cổng logic cơ bản như AND, OR, XOR, v.v. Mức độ này cung cấp một biểu diễn chi tiết về cấu trúc và logic của mạch. Mã RTL cho mạch cộng bán phần được cung cấp bên dưới .
module half_adder(input a,b, output sum,carry);
xor x1(sum, a, b);
and a1(carry, a, b);
endmodule
Mô hình hóa luồng dữ liệu
Ở mức độ trừu tượng này, chúng ta sử dụng các hàm xác định hoạt động của mạch thay vì cấu trúc cổng của nó. Mức độ trừu tượng này chủ yếu tập trung vào luồng dữ liệu thông qua các cổng logic hoặc biểu thức chức năng của mạch.
module half_adder(input a,b, output sum,carry);
assign sum = a ^ b;
assign carry = a & b;
endmodule
Mô hình hành vi
Đây là mức độ trừu tượng cao nhất trong Verilog. Ở mức độ này, các nhà thiết kế mô tả chức năng của mạch mà không cần chỉ rõ chức năng và cấu trúc của mạch kỹ thuật số. Mô hình này sẽ hữu ích vì nó tập trung vào những gì mạch nên làm hơn là cách thức triển khai nó.
module half_adder(input a,b, output reg sum,carry);
always@(*)
begin
sum = a ^ b;
carry = a & b;
endmodule
Các từ vựng
Các token từ vựng là những khối xây dựng cơ bản của mã Verilog, chúng là các từ khóa, định danh và toán tử. Chúng giống như một cách để giao tiếp với ngôn ngữ và hữu ích cho việc xây dựng các câu lệnh và biểu thức Verilog. Một số token từ vựng là:
- Khoảng trắng
- Bình luận
- Số
- Người vận hành
- Mã định danh và từ khóa
- Kiểu dữ liệu
- Lưới
- Sổ đăng ký
- Khai báo mô-đun
Khoảng trắng
Trong Verilog, chúng ta sử dụng các khoảng trắng này trong các lệnh xuất như `$display`, `$monitor`, `$strobe`, v.v. Trong đó, "\t" đại diện cho khoảng trắng tab, "\n" đại diện cho xuống dòng.
Bình luận
Có 2 cách để viết chú thích trong Verilog. Một cách là đặt chú thích trong "/*........*/". Cách này hữu ích khi có các chú thích nhiều dòng. Cách khác là thêm "//" vào đầu câu. Cách này hữu ích khi viết các chú thích một dòng hoặc có ngữ cảnh ngắn.
/*
Đây là ví dụ về chú thích nhiều dòng.
Xin chào,
chào mừng bạn đến với hướng dẫn Verilog */
//Đây là ví dụ về chú thích một dòng.
//Xin chào.
Số
Trong Verilog, chủ yếu có 4 hệ thống số được sử dụng. Đó là:
- Nhị phân: b hoặc B
- Hệ bát phân: o hoặc O
- Số thập phân: d hoặc D
- Mã thập lục phân: h hoặc H
Vì vậy, các số được biểu diễn trong Verilog bằng định dạng sau: <kích thước><cơ số><số>. Trong Verilog, nó sử dụng kích thước mặc định là 32 bit. Nếu cả cơ số và kích thước đều không được chỉ định, nó sẽ sử dụng mặc định là 32 bit và ký hiệu hệ thập phân.
Ví dụ: 4'b1100 tương đương với 4'd12 trong hệ thập phân.
'b0111 giống với 00000000000000000000000000000111
Theo mặc định, 123 là một số thập phân 32 bit.
Nếu biểu diễn bất kỳ số âm nào, theo mặc định nó sẽ được chuyển đổi sang dạng bù 2.
Người vận hành
Về cơ bản có 3 loại người vận hành, đó là:
- Tốc độ cao
Toán tử một ngôi
Trong trường hợp này, các toán tử như (+, -, ^, %, ~) xuất hiện ở bên trái của toán hạng. Ví dụ:
x = ~y;
Trong ví dụ này, bạn có thể thấy đối với biến cố định y, toán tử nằm bên trái của y.
Toán tử nhị phân
Trong trường hợp này, các toán tử xuất hiện giữa các toán hạng. Ví dụ:
X = Y ^ Z;
Trong trường hợp này, ta có thể thấy toán tử (^) nằm giữa các toán hạng Y và Z.
Toán tử ba ngôi/điều kiện
Các toán tử ba ngôi này giống như các câu lệnh if-else đơn giản nhưng được viết trên một dòng duy nhất. Chúng được biểu diễn theo định dạng:
Biểu thức có điều kiện ? Biểu thức đúng : Biểu thức sai
Ví dụ,
X = (A && B && C): 1'b1 : 1'b0;
Ở đây, nếu biểu thức (A && B && C) được đánh giá là 1 thì biểu thức đúng, tức là 1'b1, sẽ được đưa ra làm kết quả, ngược lại thì 1'b0 sẽ được đưa ra làm kết quả.
Mã định danh và từ khóa
Identifier là tên được đặt cho một hàm, tác vụ hoặc mô-đun trong Verilog. Các Identifier này phải viết thường và phân biệt chữ hoa chữ thường. Các ký tự như số, dấu gạch dưới, ký tự đặc biệt như $ có thể được sử dụng để đặt tên cho Identifier nhưng chúng không thể được sử dụng làm ký tự đầu tiên của Identifier vì chúng được dành riêng cho một số hàm tích hợp sẵn trong Verilog.
Ví dụ, các tên định danh như: my_identifier, my_identifier1, my_identifier$ có thể được sử dụng, nhưng các định danh như 1my_identifier, $my_identifier là không hợp lệ.
Kiểu dữ liệu
Trong Verilog có 4 giá trị cơ bản:

Mục đích chính của việc sử dụng kiểu dữ liệu trong Verilog là để biểu diễn các phần tử lưu trữ dữ liệu như các bit trong flip-flop và các phần tử truyền dẫn như dây dẫn kết nối giữa các cổng logic, mạch tuần tự và mạch tổ hợp . Có hai loại kiểu dữ liệu chính trong Verilog. Đó là
1. Lưới
Các đường dẫn tín hiệu (net) được điều khiển liên tục bởi các mạch logic tổ hợp. Điều này có nghĩa là chúng không thể lưu trữ bất kỳ giá trị nào. Chúng được biểu thị bằng từ khóa "wire" ở phía bên trái. Giá trị mặc định của một đường dẫn tín hiệu là 'Z', tức là trạng thái trở kháng cao.
Nối dây a, b, y;
gán y = a & b;
Ở đây, các biến được khai báo bằng kiểu dữ liệu wire và đối với biến ya, từ khóa "assign" được sử dụng để gán giá trị của vế phải (a & b) cho y.
2. Bên phải
Cần lưu ý rằng, Reg khác với thanh ghi phần cứng . Khai báo một Reg không có nghĩa là khai báo một flip-flop hay một latch , mà nó đại diện cho một phần tử lưu trữ, khác với mạng. Reg là một kiểu dữ liệu mà chúng ta chỉ có thể sử dụng thông qua các câu lệnh thủ tục.
reg a, b, y;
always@(posedge clock)
begin
y = a & b;
end
Khai báo mô-đun
Đoạn mã khai báo mô-đun được hiển thị bên dưới.
module helper(a, b, y, z);
input a, b; output y, z;
y = a & b;
z = a | b;
endmodule
- Trong đoạn mã trên, `module` biểu thị sự khai báo một mô-đun và `helper` biểu thị tên được gán cho mô-đun đó.
- Các toán hạng được viết trong ngoặc đơn (a, b, y, z) là các cổng đầu vào và đầu ra trong mạch kỹ thuật số. Khai báo cổng này cũng có thể để trống.
- Trong đoạn mã, các cổng a, b được khai báo là cổng đầu vào và y, z được khai báo là cổng đầu ra.
- Dấu chấm phẩy (";") trong mã lệnh biểu thị sự kết thúc của một câu lệnh mô-đun.
- Trong mã nguồn, khai báo y và z đại diện cho các câu lệnh riêng lẻ trong mô-đun.
- Từ khóa "endmodule" biểu thị sự kết thúc của một mô-đun.
Luôn chặn trong Verilog
Khối `always` là một khối thủ tục. Nó mô tả các mạch tuần tự (chốt, flip-flop ) hoặc mạch tổ hợp. Tất cả các khối `always` được thực thi song song, nhưng trên thực tế, chúng được thực thi theo một thứ tự được xác định bởi công cụ mô phỏng. Các tín hiệu được gán bên trong khối `always` phải thuộc loại `reg`.
Danh sách độ nhạy
- Nó chứa các tín hiệu ảnh hưởng đến đầu ra.
- Trong trường hợp có bất kỳ thay đổi nào về giá trị của các tín hiệu trong danh sách độ nhạy, các đầu ra phải được đánh giá lại.
- Điều này được thể hiện bằng cách thêm ký hiệu @ trước dấu ngoặc tròn.
- Ký hiệu * có nghĩa là thêm tất cả các đầu vào vào danh sách độ nhạy. Nếu danh sách độ nhạy không được chỉ định, điều đó có nghĩa là khối always sẽ tiếp tục được thực thi.
Phép gán chặn so với phép gán không chặn

Không nên sử dụng cả hai trong cùng một khối always.
Phân loại Verilog khác nhau
- Verilog-1995 : Verilog-1995, còn được gọi là Chuẩn IEEE 1364-1995, là phiên bản đầu tiên của Verilog giới thiệu cú pháp và các tính năng cơ bản của ngôn ngữ này. Nó cung cấp các cấu trúc cơ bản để mô tả mạch kỹ thuật số, bao gồm các module, cổng, kiểu dữ liệu (wire, reg), và các kỹ thuật mô hình hóa cấu trúc và hành vi cơ bản.
- Verilog-2001 : Verilog-2001, một phiên bản mở rộng của Verilog-1995, đã giới thiệu một số tính năng và cải tiến mới cho ngôn ngữ nhằm nâng cao khả năng đọc hiểu mã, khả năng tái sử dụng và sự dễ dàng trong thiết kế. Nó đã khắc phục một số hạn chế của phiên bản trước và giới thiệu các cấu trúc mới để mô hình hóa và kiểm chứng tốt hơn.
- System Verilog : System Verilog là một phần mở rộng quan trọng của Verilog, bổ sung thêm các tính năng và khả năng mới cho cả thiết kế và kiểm chứng. Nó kết hợp các tính năng từ ngôn ngữ Vera và Specman, cung cấp một giải pháp toàn diện cho thiết kế, kiểm chứng và mô hình hóa ở cấp độ hệ thống.
- Verilog-AMS (Analog và Tín hiệu hỗn hợp) : Verilog-AMS là một phần mở rộng của Verilog cho phép mô hình hóa các hệ thống tương tự và tín hiệu hỗn hợp cùng với logic số. Nó cung cấp các cấu trúc để mô tả hành vi tương tự liên tục theo thời gian, chẳng hạn như điện áp và dòng điện, ngoài các tín hiệu và logic số.
Sự khác biệt giữa Verilog HDL và VHDL
Bảng dưới đây thể hiện sự khác biệt giữa Verilog HDL và VHDL.

Ưu điểm của Verilog
- Cú pháp ngắn gọn: Verilog có cú pháp đơn giản, cho phép lập trình mạch kỹ thuật số nhanh chóng và hiệu quả.
- Tiêu chuẩn ngành: Nó được sử dụng và chấp nhận rộng rãi trong ngành công nghiệp bán dẫn, giúp việc hợp tác với người khác và tiếp cận tài nguyên trở nên dễ dàng hơn.
- Mô phỏng và tổng hợp: Verilog hỗ trợ cả mô phỏng và tổng hợp, cho phép các nhà thiết kế kiểm chứng thiết kế của họ và chuyển đổi chúng thành phần cứng thực tế.
- Thiết kế theo cấu trúc phân cấp: Verilog cho phép thiết kế theo cấu trúc phân cấp, cho phép tạo ra các hệ thống phức tạp bằng cách chia nhỏ chúng thành các mô-đun nhỏ hơn, dễ quản lý hơn.
Nhược điểm của Verilog
- Đường cong học tập dốc: Verilog có thể hơi khó hiểu đối với người mới bắt đầu do cú pháp và các khái niệm, và cần thời gian để thành thạo.
- Sự phụ thuộc vào công cụ: Thiết kế Verilog yêu cầu các công cụ chuyên dụng cho quá trình tổng hợp, mô phỏng và kiểm chứng, điều này có thể dẫn đến chi phí phát sinh và các vấn đề về khả năng tương thích.
- Khả năng tương thích phiên bản: Các vấn đề về khả năng tương thích có thể phát sinh khi sử dụng các phiên bản Verilog khác nhau hoặc khi tương tác với các công cụ và thư viện của bên thứ ba.
- Thách thức trong việc xác minh: Mặc dù Verilog hỗ trợ xác minh dựa trên mô phỏng, việc thiết lập các môi trường kiểm thử toàn diện và đảm bảo độ bao phủ đầy đủ có thể phức tạp và tốn nhiều thời gian.
Ứng dụng của Verilog
- Hệ thống nhúng: Verilog được sử dụng để thiết kế các thành phần phần cứng trong hệ thống nhúng như vi điều khiển và FPGA.
- Xử lý tín hiệu số: Verilog cho phép triển khai các thuật toán xử lý tín hiệu số (DSP) trên phần cứng cho các ứng dụng như xử lý âm thanh và video.
- Mạng máy tính : Verilog được sử dụng trong thiết kế phần cứng mạng như bộ định tuyến, bộ chuyển mạch và card giao diện mạng.
- Thiết kế ASIC: Verilog thường được sử dụng trong thiết kế mạch tích hợp chuyên dụng (ASIC) cho các triển khai phần cứng tùy chỉnh.
- Xe tự hành: Verilog được ứng dụng trong lĩnh vực điện tử ô tô cho các hệ thống như bộ điều khiển động cơ và hệ thống hỗ trợ lái xe nâng cao (ADAS).
