Mở đầu: Khi lập trình viên lần đầu mở file Verilog

Bạn vừa hoàn thành Series 10 — hiểu rõ cổng logic, D Flip-Flop, và cách ghép chúng thành mạch tuần tự trên breadboard hoặc mô phỏng. Giờ bạn mở file .v đầu tiên, thấy cú pháp gần giống C, và theo phản xạ tự nhiên bắt đầu đọc nó từ trên xuống dưới, tưởng tượng dòng lệnh này chạy xong mới đến dòng kế tiếp. Vài dòng sau bạn bối rối: tại sao thứ tự viết assign không ảnh hưởng tới kết quả? Tại sao 2 khối always "không hề gọi lẫn nhau" mà vẫn đồng bộ tăm tắp? Đây chính xác là điểm rẽ nhánh giữa tư duy phần mềmtư duy phần cứng — và là lý do hầu hết lập trình viên viết đúng cú pháp Verilog nhưng tạo ra mạch hoạt động sai hoàn toàn trong tuần đầu tiên học HDL.

Bài này giải quyết đúng điểm rẽ nhánh đó trước khi bạn viết một dòng SystemVerilog thực chiến nào. Bạn sẽ thấy 4 mức trừu tượng mà một con chip được xây từ đó, vì sao HDL mô tả phần cứng song song chứ không thực thi tuần tự, toàn cảnh quy trình biến 1 file text thành 1 con chip thật (RTL → GDSII), và bức tranh các ngôn ngữ HDL đang được dùng trong công nghiệp. Cuối bài, một sân chơi tương tác sẽ để chính bạn chứng minh điều quan trọng nhất: cùng một mạch, viết 3 kiểu code hoàn toàn khác nhau, vẫn ra đúng 1 phần cứng giống hệt.


1. Bốn mức trừu tượng thiết kế vi mạch

Khi thiết kế một vi mạch, kỹ sư không viết code từng transistor. Thay vào đó, họ làm việc ở các mức trừu tượng khác nhau, từ cơ bản nhất (transistor cứng) đến cao nhất (mô tả hành vi toán học):

Mức Tên gọi Mô tả Ví dụ
1 Transistor Viết điều kiện dẫn (conductivity) từng transistor NMOS/PMOS. Tính toán độ rộng/dài (W/L ratio) để điều chỉnh dòng. NMOS with W=2µm, L=100nm
2 Gate / Cổng Logic Ghép nối các cổng logic (AND, OR, XOR, FF). Bao gồm thông số dây nối và transistor tuning từ mức trước. Mux 2-1: y = (s) ? a : b = 1 XOR + 2 AND + 1 OR
3 RTL Mô tả sự chuyển tiếp dữ liệu giữa các thanh ghi (registers) qua logic tổ hợp (combinational). Code HDL (Verilog, SystemVerilog, VHDL). always_ff @(posedge clk) result <= data_in;
4 Behavioral / Hệ thống Mô tả hành vi toàn chuỗi (pipeline, state machine, protocol). Tương đương với mô hình toán học cao cấp (SystemC, Chisel). output = FFT(input) (mô tả chiều cao, không chi tiết)

Các mức này được gọi là "hierarchical design" — mỗi mức phục vụ một mục đích:

  • Transistor: Tối ưu hóa tiêu thụ điện, tốc độ, diện tích ở mức chi tiết nhất (công việc của layout designer).
  • Gate: Kiến trúc cơ bản của các module (công việc của digital designer).
  • RTL: Thiết kế chính (công việc của RTL designer) — phần bạn sẽ học ở series này.
  • Behavioral: Kiểm chứng (verification) và mô hình hoá hệ thống (system modeling).
📚 Điều kiện tiên quyết
Bắt buộc: Series 10 Bài 12 (Cổng Logic) + Bài 13 (Mạch tuần tự, Flip-Flop, Timing setup/hold).
Nên có: Series C (biểu diễn số, con trỏ & bộ nhớ) — nền tảng đọc hiểu cú pháp gần C của SystemVerilog.
Tài nguyên ngoài: HDLBits, ChipVerify, EDA Playground.

2. HDL khác lập trình thế nào?

Đây là hiểu nhầm số 1 của lập trình viên khi chuyển sang HDL: "Ồ, Verilog là ngôn ngữ lập trình, tôi viết code như C, chạy từ trên xuống dưới". Sai!

🕳️ Cạm bẫy: HDL là mô tả phần cứng song song, không tuần tự
Lập trình (C/Python):
int x = 5;
x = x + 10;  // Thực thi từng dòng, x lúc này = 15
printf("%d", x);
HDL (Verilog):
assign y = a + b;  // Đây KHÔNG phải "câu lệnh" tuần tự
always_comb z = x & y;  // Cả hai lệnh chạy ĐỒNG THỜI, không theo thứ tự
Cả assignalways_comb chạy cùng lúc, y và z cập nhật tức thời khi a, b, hoặc x thay đổi. Nếu bạn viết code như Python, trình tổng hợp (synthesis tool) sẽ tạo ra phần cứng sai hoàn toàn.

Sự khác biệt cốt lõi:

  • Lập trình: "Làm cái này rồi làm cái kia" (tuần tự, serial)
  • HDL: "Tất cả cái này chạy cùng lúc, kết nối với nhau" (song song, parallel)

Hãy nghĩ về nó theo cách vật lý hơn là cú pháp: mỗi cổng logic trong 1 con chip là 1 miếng silicon thật, luôn ở trạng thái "sẵn sàng" — chỉ cần điện áp đầu vào đổi, đầu ra của nó đổi theo gần như tức thời (vài phần nghìn tỷ giây), bất kể bạn viết dòng assign đó ở trên hay dưới file. Không hề có "con trỏ chương trình" nào chạy qua từng dòng như CPU thực thi lệnh — toàn bộ mạch tồn tại và hoạt động cùng một lúc, giống hàng nghìn công tắc đèn được nối dây sẵn, tất cả cùng phản ứng ngay khi bạn bật nguồn. Đây cũng là lý do một lỗi tư duy tuần tự (vd viết vòng lặp for mong đợi nó "chạy qua nhiều chu kỳ" bên trong 1 khối tổ hợp) không chỉ cho ra kết quả sai — nó có thể khiến trình tổng hợp từ chối tổng hợp hoặc tạo ra hàng nghìn cổng logic lặp lại một cách vô nghĩa.

3. Design Flow: RTL → GDSII

Khi bạn viết code RTL, nó không phải là "chương trình chạy trên máy tính". Nó là bản thiết kế mà công cụ EDA (Electronic Design Automation) sẽ chuyển đổi thành sơ đồ mạch thực tế (bản vẽ chip).

Toàn bộ quy trình được gọi là Design Flow:

  1. RTL Code: Viết Verilog/SystemVerilog/VHDL mô tả phần cứng ở mức RTL.
  2. Simulation: Dùng simulator (Modelsim, VCS) kiểm chứng logic hoạt động đúng (testbench).
  3. Synthesis: Tool (Yosys, Design Compiler) chuyển RTL → netlist cổng logic (gate-level netlist).
  4. Place & Route: Tool (Cadence Innovus, nextpnr) đặt cổng trên die và dây nối tối ưu → layout.
  5. DRC/LVS: Kiểm tra thiết kế vật lý tuân thủ quy tắc (Design Rule Check, Layout vs Schematic).
  6. GDS II Generation: Tạo file bản vẽ cuối cùng (GDSII) gửi tới nhà máy (fab) để in chip.
💡 Lưu ý
Ở series này, chúng ta tập trung vào bước 1–3 (RTL → Synthesis). Các bước 4–6 (Physical Design, GDS) sẽ được giới thiệu nhưng không đi sâu (vì đó là công việc của Physical Design Engineer, không phải RTL Designer).

4. Verilog vs SystemVerilog vs VHDL vs Chisel vs HLS

Có nhiều ngôn ngữ HDL khác nhau. Series này chọn SystemVerilog vì sao?

Ngôn ngữ Xuất xứ Đặc điểm Phổ biến ở
Verilog (1984) Gateway Design Automation (Cadence mua lại năm 1989) Đơn giản, giống C, cũ. Ít tính năng verification. Dự án cũ, FPGA hobbist
SystemVerilog (2005) Accellera, chuẩn hoá IEEE 1800-2017. Superset của Verilog. Thêm assertion (SVA), testbench hướng đối tượng (OOP), constrained-random. Chuẩn công nghiệp. ASIC design, verification
VHDL (1987) VHSIC (Quốc phòng Mỹ) Dài dòng, ada-like syntax, mạnh verification. Ít phổ biến ở công nghiệp hiện đại. Aerospace, quốc phòng
Chisel (2012) UC Berkeley HDL sinh ra từ Scala (JVM). Giảm bớt boilerplate code. Startup, RISC-V design
HLS (High-Level Synthesis) Catapult, Vivado HLS (Xilinx) Viết C/C++ → tự sinh Verilog. Nhanh prototype nhưng kết quả tối ưu kém. Mẫu nhanh, xử lý tín hiệu

Series này dạy SystemVerilog vì:

  • ✅ Chuẩn công nghiệp ASIC/FPGA hiện tại
  • ✅ Cú pháp gần C → dễ tiếp cận lập trình viên
  • ✅ Mạnh verification (SVA, constrained-random)
  • ✅ Mỗi bài sẽ note cú pháp Verilog cũ tương đương → đọc được code legacy
📚 Sẽ học sâu ở Bài 5
Bảng trên vừa nhắc tới SVA, testbench hướng đối tượng (OOP) và constrained-random — đây là 3 tính năng verification mạnh nhất của SystemVerilog, sẽ được giải thích chi tiết ở Bài 5: Testbench & Verification cơ bản. Ở bài này bạn chỉ cần biết chúng tồn tại và là lý do SystemVerilog được chọn thay vì Verilog thuần.

5. Sân chơi tương tác: Mux 2-1 viết 3 kiểu — Tour RTL Playground

Cùng một mạch logic đơn giản (Mux 2-1: chọn a hoặc b tùy theo tín hiệu chọn s) có thể viết bằng 3 kiểu RTL khác nhau. Đây chính là bằng chứng trực tiếp cho luận điểm ở Mục 2: code RTL là bản thiết kế phần cứng, không phải chương trình — dù bạn diễn đạt logic theo cách nào, sau khi synthesis nó luôn ra đúng cùng một netlist cổng logic. Bấm nút bên dưới để tự kiểm chứng, đây chính là bản thu gọn của RTL Playground mà các bài sau sẽ dùng lại.

🎛️ Tour RTL Playground: Mux 2-1 trong 3 kiểu
Đang mô phỏng kiểu:
y = 0

Bấm nút a/b/s để đổi tín hiệu đầu vào — dây dẫn "mang giá trị 1" sẽ tô sáng màu lime. Đổi kiểu code phía trên (Structural/Dataflow/Behavioral): netlist và kết quả y luôn giống hệt nhau, dù mã nguồn trông rất khác nhau.

mux2_1_structural.sv
module mux2_1_structural (
  input a, b, s,
  output y
);
  wire not_s, and_a, and_b;

  not NOT_GATE (not_s, s);
  and AND_A (and_a, a, not_s);
  and AND_B (and_b, b, s);
  or OR_GATE (y, and_a, and_b);
endmodule

Style: Liệt kê từng cổng AND, OR, NOT như bản thiết kế vật lý — instantiate cổng nguyên thủy (gate primitive) bằng tên chuẩn Verilog (not, and, or). Bạn thấy đúng những cổng nào được dùng, nhưng khó bảo trì (đổi logic = viết lại toàn bộ dây nối).

mux2_1_dataflow.sv
module mux2_1_dataflow (
  input a, b, s,
  output y
);
  assign y = (a & ~s) | (b & s);
endmodule

Style: Ghi công thức Boolean trực tiếp bằng toán tử bitwise (& AND, | OR, ~ NOT). Trình synthesis tự phân tích công thức và tạo cổng — cân bằng giữa rõ ràng và linh hoạt, thường dùng ở phần tổ hợp (combinational).

mux2_1_behavioral.sv
module mux2_1_behavioral (
  input a, b, s,
  output reg y
);
  always @(a, b, s) begin
    if (s == 0)
      y = a;
    else
      y = b;
  end
endmodule

Style: Viết như lập trình với if/else, trình synthesis sẽ "suy ra" đây là multiplexer. Dễ viết, dễ đọc, dễ bảo trì nhất — thường dùng ở phần tuần tự (sequential), sẽ học kỹ ở Bài 3.

🔬 Đào sâu: Vì sao chọn kiểu này thay vì kiểu kia?
  • Structural: Dùng khi bạn biết chính xác cổng nào cần (tối ưu điện năng, diện tích thủ công). Khó bảo trì — thay đổi logic nghĩa là viết lại toàn bộ danh sách cổng.
  • Dataflow: Cân bằng giữa rõ ràng và linh hoạt. Thường được dùng ở phần tổ hợp (combinational logic).
  • Behavioral: Dễ viết, dễ hiểu, dễ bảo trì. Trình synthesis phải "suy ra" từng cổng — đôi khi sinh dư 1-2 cổng thừa (vd 2 cổng NOT lồng nhau) mà công cụ tối ưu hoá logic (logic optimization) sẽ tự loại bỏ để về đúng netlist tối giản, y hệt 2 kiểu kia. Thường dùng ở phần tuần tự (sequential).

Trong công nghiệp thực tế, phần lớn code RTL hiện đại viết theo dataflow + behavioral — structural chỉ dùng khi cần ghép nối thủ công các module con (instantiate submodule) hoặc chèn trực tiếp một cell thư viện cụ thể (technology cell) cho mục đích tối ưu đặc biệt.

Trắc nghiệm ôn tập

Câu 1

Mức trừu tượng nào mô tả phần cứng bằng cách chuyển tiếp dữ liệu giữa các thanh ghi (registers) qua logic tổ hợp?

Câu 2

Sự khác biệt cốt lõi giữa HDL và ngôn ngữ lập trình tuần tự (như C/Python) là gì?

Câu 3

Mux 2-1 viết bằng 3 kiểu (structural, dataflow, behavioral) — sau khi synthesis, kết quả netlist sẽ như thế nào?

Câu 4

Trong Design Flow RTL → GDSII, bước nào diễn ra NGAY SAU Synthesis?

Tóm lược

Bài này giới thiệu tư duy chuyển đổi từ cổng logic sang RTL:

  • ✅ HDL là mô tả phần cứng song song, không phải lập trình tuần tự.
  • ✅ Design flow: RTL → Simulation → Synthesis → P&R → GDSII (chúng ta tập trung RTL đến Synthesis).
  • ✅ SystemVerilog là chuẩn công nghiệp hiện tại.
  • ✅ Cùng một mạch có thể viết 3 kiểu (structural, dataflow, behavioral), synthesis ra netlist giống nhau.

Bài tiếp theo sẽ bắt đầu viết code SystemVerilog tổ hợp (combinational) thực tế trên RTL Playground — một trình mô phỏng tương tác giúp bạn thấy code → netlist → waveform theo thời gian thực.

Tải file code thực hành minh họa bài học

File SystemVerilog tổng hợp cả 3 kiểu Mux 2-1 (structural/dataflow/behavioral) kèm testbench tự kiểm tra cả 3 module cho cùng kết quả trên toàn bộ 8 tổ hợp đầu vào. Chạy được trên Verilator hoặc dán trực tiếp vào EDA Playground (xem hướng dẫn trong comment đầu file):

Tải về mux2_1.sv

📖 Tài liệu tham khảo

Bài viết liên quan trong series

Bài 2: SystemVerilog tổ hợp (Combinational Logic) Quay lại Lộ trình Series Thiết Kế Vi Mạch Số & FPGA

Bình luận