"Muốn hiểu Verilog – hãy code nó." Không giống các ngôn ngữ lập trình thông thường, Verilog mô tả phần cứng, không phải thuật toán. Vì vậy, cách học hiệu quả nhất là học thông qua ví dụ trực quan và phân tích tư duy phần cứng đằng sau từng dòng code.
I. Verilog là gì? Khác gì với C, Python?
So sánh | Verilog | C/Python |
---|---|---|
Mục tiêu | Mô tả phần cứng | Mô tả thuật toán |
Kiểu hoạt động | Song song (concurrent) | Tuần tự (sequential) |
Output là gì? | Mạch điện (logic gate) | Mã máy chạy trên CPU |
Debug thế nào? | Mô phỏng/tín hiệu | Print log, IDE |
Khi bạn viết if trong Verilog, bạn đang mô tả mạch so sánh và bộ chọn – chứ không phải lệnh điều kiện tuần tự.
II. Cấu trúc một module Verilog cơ bản
module my_module ( input clk, input rst, input [7:0] a, output wire [7:0] b
); // logic here
endmodule
Giải thích:
- module: giống như class hoặc hàm – đơn vị thiết kế cơ bản.
- input, output: chân kết nối (port) với các khối khác.
- wire, reg: kiểu dữ liệu – có vai trò quan trọng (xem phần dưới).
III. Wire vs Reg – Lỗi kinh điển của người mới
Đặc điểm | wire | reg |
---|---|---|
Gán giá trị | qua assign (liên tục) | trong always block |
Dùng cho | kết nối combinational | lưu trạng thái (flip-flop) |
Ví dụ:
assign y = a + b; // wire always @(posedge clk) begin y <= a + b; // reg
end
Nếu bạn gán giá trị trong always, thì biến đó phải là kiểu reg.
IV. Các khối cơ bản: combinational và sequential
1. Combinational logic (không có clock):
always @(*) begin if (sel == 0) y = a; else y = b;
end
2. Sequential logic (có clock):
always @(posedge clk) begin if (rst) y <= 0; else y <= y + 1;
end
Ghi nhớ:
- @(*) → mọi tín hiệu thay đổi sẽ kích hoạt lại block.
- @(posedge clk) → chỉ khi cạnh lên của clock xảy ra.
V. Viết testbench đơn giản để mô phỏng
module tb_my_module; reg clk, rst; reg [7:0] a; wire [7:0] y; my_module uut ( .clk(clk), .rst(rst), .a(a), .y(y) ); initial begin clk = 0; forever #5 clk = ~clk; // Tạo clock 10ns end initial begin rst = 1; a = 0; #12 rst = 0; #10 a = 5; #10 a = 10; #50 $finish; end
endmodule
Chạy bằng Vivado hoặc ModelSim để kiểm tra dạng sóng.
Đừng bao giờ nạp code chưa mô phỏng lên FPGA!
VI. Một số ví dụ nhỏ để luyện tập
1. Mạch dồn kênh 2:1 (Multiplexer)
assign y = sel ? b : a;
2. Bộ đếm tăng
always @(posedge clk or posedge rst) begin if (rst) count <= 0; else count <= count + 1;
end
VII. Mẹo học Verilog hiệu quả
- Luôn viết module nhỏ, dễ test.
- Tách rõ combinational và sequential.
- Mô phỏng nhiều – xem waveform thường xuyên.
- So sánh đầu ra mô phỏng với kỳ vọng.
- Viết code rõ ràng – đừng tối ưu sớm.
VIII. Tổng kết
Verilog là một ngôn ngữ tuyệt vời – nhưng cần tư duy phần cứng để dùng đúng. Thay vì học lý thuyết khô khan, hãy:
- Học qua ví dụ cụ thể.
- Viết testbench để hiểu luồng tín hiệu.
- Tư duy "mạch điện", không phải "code tuần tự".
Chúc các bạn sớm làm quen với ngôn ngữ này