Tài liệu hướng dẫn thiết kế IC số từ RTL đến GDSII | OpenLane 2 + Sky130 PDK (130nm)
Phiên bản: 2026-02-28 | OpenLane v2.3.10 | Run: RUN_2026-02-28_00-26-42
Tài liệu này hướng dẫn từng bước quy trình thiết kế một chip số hoàn chỉnh — từ viết mã RTL (Register Transfer Level) đến tạo file GDSII (file layout vật lý để đưa vào sản xuất chip). Cụ thể:
| Đối tượng | Yêu cầu kiến thức |
|---|---|
| Sinh viên năm 3-4 Điện tử, Vi mạch, CNTT | Đã học Kỹ thuật số (Digital Logic), hiểu cơ bản về flip-flop, combinational/sequential logic, FSM |
| Học viên cao học Chuyên ngành VLSI/IC Design | Muốn thực hành flow RTL-to-GDSII với công cụ open-source thay vì EDA thương mại (Cadence, Synopsys) |
| Kỹ sư mới Chuyển sang lĩnh vực chip | Có nền tảng lập trình, muốn hiểu quy trình thiết kế chip từ đầu đến cuối |
| Người tự học Hobbyist, maker | Quan tâm đến thiết kế chip, sẵn sàng cài đặt Linux/WSL và học các khái niệm mới |
Để tiếp thu tài liệu này hiệu quả nhất, bạn nên có nền tảng ở các mảng kiến thức sau:
| Mảng kiến thức | Nội dung cụ thể | Mức độ |
|---|---|---|
| Kỹ thuật số (Digital Logic) |
Cổng logic (AND, OR, NOT, XOR), bảng chân trị, Karnaugh map, flip-flop (D-FF, JK-FF), thanh ghi, bộ đếm, FSM (Moore/Mealy) | Bắt buộc |
| Hệ thống số (Number Systems) |
Nhị phân, thập lục phân, chuyển đổi cơ số, số bù 2 (two's complement), phép toán bit (AND, OR, shift) | Bắt buộc |
| Lập trình cơ bản | Hiểu khái niệm biến, vòng lặp, điều kiện, module/function. Biết dùng terminal/command line (cd, ls, mkdir) | Bắt buộc |
| SystemVerilog / Verilog (Xem phần giới thiệu bên dưới) |
Cú pháp module, always_ff/always_comb, wire/logic, assign, testbench cơ bản | Nên có |
| Linux cơ bản | Cài đặt package (apt), sử dụng terminal, Docker cơ bản (pull, run), sửa file text | Nên có |
| Điện tử tương tự (Analog basics) |
Transistor MOSFET (NMOS/PMOS), điện áp ngưỡng (Vt), công suất tiêu thụ, khái niệm ký sinh (R, C) | Biết thêm càng tốt |
Lưu ý: Nếu bạn chưa biết SystemVerilog, đừng lo — tài liệu giải thích từng dòng code. Phần giới thiệu ngôn ngữ ngay bên dưới sẽ giúp bạn nắm nhanh cú pháp cơ bản.
SystemVerilog (IEEE 1800) là ngôn ngữ mô tả phần cứng (HDL) được sử dụng rộng rãi nhất trong ngành bán dẫn hiện nay. Nó kế thừa từ Verilog và bổ sung nhiều tính năng mạnh mẽ cho cả thiết kế lẫn kiểm thử.
| Tiêu chí | SystemVerilog | Verilog | VHDL |
|---|---|---|---|
| Cú pháp | Giống C/C++ | Giống C | Giống Ada/Pascal |
| Phổ biến | Toàn cầu #1 | Vẫn dùng | Châu Âu, Quốc phòng |
| Verification | Rất mạnh | Hạn chế | Trung bình |
| Học dễ | Trung bình | Dễ nhất | Khó nhất |
module counter ( input logic clk, // Xung nhịp input logic reset, // Reset đồng bộ input logic enable, // Cho phép đếm output logic [7:0] count // Giá trị đếm (0-255) ); // always_ff = mô tả logic tuần tự (flip-flop) always_ff @(posedge clk) begin if (reset) count <= 8'h00; // Reset → đếm về 0 else if (enable) count <= count + 1; // Enable → đếm lên 1 end endmodule
| Cú pháp | Ý nghĩa |
|---|---|
module ... endmodule | Đơn vị thiết kế cơ bản (tương tự class trong OOP). Mỗi module có tên, cổng vào/ra, và logic bên trong |
input / output | Khai báo cổng: tín hiệu đi vào hoặc đi ra khỏi module |
logic | Kiểu dữ liệu chính trong SystemVerilog, thay thế wire và reg của Verilog cũ |
[7:0] | Bus 8-bit: gồm 8 đường tín hiệu, bit 7 (MSB) đến bit 0 (LSB) |
always_ff @(posedge clk) | Khối logic tuần tự: thực thi tại mỗi cạnh lên của clock. Tạo ra flip-flop khi synthesis |
<= (non-blocking) | Phép gán không chặn: tất cả gán trong always_ff xảy ra đồng thời tại cạnh clock |
8'h00 | Hằng số: 8 bit, dạng hex, giá trị 00. Cũng có thể viết 8'd0 (decimal) hay 8'b0000_0000 (binary) |
| Tài nguyên | Loại | Ghi chú |
|---|---|---|
| ChipVerify — SV Tutorial | Web (miễn phí) | Tài liệu tra cứu cú pháp phổ biến nhất. Có ví dụ từng mục, quiz, phỏng vấn |
| ASIC-World — SV in One Day | Web (miễn phí) | Hướng dẫn nhanh SystemVerilog trong 1 ngày, phù hợp nắm tổng quan |
| Doulos — SV Tutorials | Web (miễn phí) | Từ công ty đào tạo EDA hàng đầu. Bài viết chất lượng cao về design & verification |
| Coursera — SV Hardware Design | Khoá học online | Khoá miễn phí trên Coursera, có bài tập thực hành, phù hợp người mới hoàn toàn |
| Verification Guide | Web (miễn phí) | Chuyên sâu về verification: UVM, assertions, constrained-random |
Gợi ý lộ trình: Đọc ChipVerify để nắm cú pháp cơ bản (2-3 ngày) → Làm theo tài liệu này → Quay lại học sâu verification khi cần.
Đường dẫn nhanh (Quick Path)
Nếu muốn chạy demo ngay, đi thẳng đến:
Đường dẫn đầy đủ (Full Path)
Nếu muốn hiểu sâu lý thuyết, đọc tuần tự:
Toàn bộ tài liệu sử dụng thiết kế mẫu 8-bit Counter (bộ đếm 8-bit) làm ví dụ xuyên suốt. Đây là module đủ đơn giản để người mới hiểu được, nhưng đủ đầy đủ để trải qua mọi bước trong quy trình thiết kế chip thực tế: synthesis, floorplan, placement, routing, timing analysis, DRC/LVS signoff.
Mục tím = nội dung Simulation & Verification (mới bổ sung)
8-bit Counter là một mạch số đếm từ 0 đến 255 (28 − 1). Mỗi xung clock, giá trị đếm tăng lên 1. Khi đạt 255 (11111111), chu kỳ tiếp sẽ quay về 0 (overflow). Đây là một trong những module cơ bản nhất trong thiết kế số.
| Thành phần | Chức năng |
|---|---|
| 8 Flip-Flop D | Mỗi flip-flop lưu 1 bit của giá trị đếm. 8 flip-flop = 8 bit = đếm được 0–255 |
| Bộ cộng +1 (Incrementer) | Tính count + 1 mỗi chu kỳ clock |
| MUX điều khiển | Chọn giữa giá trị mới (count+1) hoặc giữ nguyên, dựa vào tín hiệu EN |
| Async Reset | Khi rst_n=0, tất cả flip-flop về 0 ngay lập tức (không cần chờ clock) |
Tại mỗi cạnh lên (posedge) của clock, mạch thực hiện 1 trong 3 hành động:
| rst_n | en | Hành động | Giải thích |
|---|---|---|---|
| 0 | x (bất kỳ) | count ← 00000000 | Reset: tất cả flip-flop về 0 ngay lập tức (async, không cần chờ clock) |
| 1 | 1 | count ← count + 1 | Đếm: giá trị tăng lên 1. Nếu đang 255 sẽ quay về 0 (overflow) |
| 1 | 0 | count ← count | Giữ: giá trị không đổi, chờ enable bật lại |
8 bit = 28 = 256 giá trị (0 đến 255). Khi vượt 255, counter quay về 0:
| Cycle | Binary | Decimal | Sự kiện |
|---|---|---|---|
| 0 | 00000000 | 0 | Reset |
| 1 | 00000001 | 1 | +1 |
| 2 | 00000010 | 2 | +1 |
| 3 | 00000011 | 3 | +1 |
| ... | ... | ... | ... |
| 254 | 11111110 | 254 | +1 |
| 255 | 11111111 | 255 | Giá trị tối đa |
| 256 | 00000000 | 0 | Overflow — quay về 0 |
| 257 | 00000001 | 1 | Tiếp tục đếm |
| Bit-width | Số FF | Phạm vi | Số giá trị | Dùng cho |
|---|---|---|---|---|
| 4-bit | 4 | 0 – 15 | 16 | BCD counter, đếm đơn giản |
| 8-bit | 8 | 0 – 255 | 256 | Timer, PWM, UART baud rate |
| 16-bit | 16 | 0 – 65,535 | 65,536 | Address counter, timer dài |
| 32-bit | 32 | 0 – 4.29×109 | 4,294,967,296 | Timestamp, program counter CPU |
| Port | Hướng | Độ rộng | Mô tả |
|---|---|---|---|
clk | Input | 1 bit | Clock: xung nhịp. Mỗi cạnh lên là 1 chu kỳ đếm |
rst_n | Input | 1 bit | Reset (active low): khi = 0, counter về 0 ngay lập tức. Hậu tố _n nghĩa là "active khi = 0" |
en | Input | 1 bit | Enable: khi = 1, counter đếm. Khi = 0, giữ nguyên giá trị |
count | Output | 8 bit | Giá trị đếm: từ 00000000 (0) đến 11111111 (255) |
| Ứng dụng | Cách dùng counter |
|---|---|
| Timer/Delay | Đếm số xung clock, khi đạt giá trị mục tiêu thì trigger sự kiện |
| UART Baud Rate | Chia tần clock hệ thống xuống baud rate (VD: 50MHz → 9600 baud) |
| PWM Generator | So sánh count với ngưỡng để tạo xung độ rộng thay đổi |
| Memory Address | Tự động tăng địa chỉ khi đọc/ghi SRAM/Flash tuần tự |
| Ứng dụng | Cách dùng counter |
|---|---|
| Frequency Divider | Bit cao nhất (count[7]) có tần số = clock/256 |
| State Machine | Đếm số chu kỳ chờ trong FSM (VD: chờ 100 cycles) |
| Watchdog Timer | Nếu không được reset định kỳ, counter overflow → reset hệ thống |
| LED Blinking | Đếm chậm để tạo tần số nhấp nháy thấy được bằng mắt |
Mỗi phần của nguyên lý tương ứng với code RTL:
module counter ( input logic clk, // ← Xung nhịp (100MHz trong demo) input logic rst_n, // ← Reset active-low (async) input logic en, // ← Enable điều khiển đếm/dừng output logic [7:0] count // ← 8-bit output (0–255) ); // ┌ posedge clk = cạnh lên clock always_ff @(posedge clk or negedge rst_n) begin // └ negedge rst_n = async reset if (!rst_n) // ← rst_n=0: RESET count <= 8'b0; // tất cả 8 flip-flop → 0 else if (en) // ← en=1: ĐẾM count <= count + 1; // bộ cộng +1, kết quả vào DFF // ← en=0: GIỮ (không có else → giữ nguyên) end endmodule
Toàn bộ quy trình trong tài liệu này sử dụng công cụ mã nguồn mở (OpenLane, Yosys, OpenROAD, Magic...). Các công cụ này hoạt động tốt với các PDK mã nguồn mở hiện có:
| PDK | Process | Nhà sản xuất | Ghi chú |
|---|---|---|---|
| Sky130 | 130 nm | SkyWater / Google | Phổ biến nhất, dùng trong tài liệu này |
| GF180MCU | 180 nm | GlobalFoundries | PDK mở thứ hai, hỗ trợ tốt MCU/analog |
| IHP SG13G2 | 130 nm SiGe | IHP (Đức) | BiCMOS, phù hợp RF & mmWave |
Với các node tiên tiến (28nm, 7nm, 5nm, 3nm...) dùng trong chip thương mại (Apple, Qualcomm, NVIDIA), cần PDK thương mại từ TSMC, Samsung, Intel và công cụ EDA thương mại (Synopsys, Cadence, Siemens EDA) có giá hàng trăm nghìn đến hàng triệu USD/năm. Tuy nhiên, quy trình thiết kế (design flow) là giống nhau — kiến thức bạn học ở 130nm hoàn toàn áp dụng được khi chuyển sang node nhỏ hơn.
| # | Khâu | Công cụ | Diễn giải |
|---|---|---|---|
| FRONTEND — Thiết kế & kiểm tra logic | |||
| 1 | RTL Design | SystemVerilog | Viết mô tả phần cứng ở mức thanh ghi — “bản thiết kế” dạng code, mô tả chip sẽ hoạt động như thế nào |
| 2 | RTL Sim | Icarus Verilog | Mô phỏng logic zero-delay: kiểm tra code đúng/sai trước khi đi tiếp. Phát hiện ~80% lỗi ở bước này |
| 3 | Lint | Verilator | Kiểm tra lỗi cú pháp, coding style, cảnh báo tổng hợp — như “spell check” cho RTL |
| SYNTHESIS — Ranh giới Frontend ↔ Backend | |||
| 4 | Synthesis | Yosys | Chuyển code RTL → netlist cổng logic (NAND, NOR, FF) sử dụng standard cells từ thư viện Sky130 |
| 5 | GL Sim | Icarus + Cells | Mô phỏng lại bằng netlist cổng logic thật — kiểm tra synthesis không làm sai chức năng |
| BACKEND — Hiện thực vật lý (Physical Design) | |||
| 6 | Floorplan | OpenROAD | Xác định kích thước chip, vị trí I/O pins, vùng đặt macro — giống “quy hoạch mặt bằng” |
| 7 | PDN | OpenROAD | Xây dựng lưới nguồn VDD/VSS — “hệ thống điện” cấp năng lượng cho toàn bộ chip |
| 8 | Placement | OpenROAD | Sắp xếp hàng nghìn standard cells vào các hàng (rows) trên chip, tối ưu vị trí để giảm độ dài dây |
| 9 | CTS | OpenROAD | Tổng hợp cây clock — phân phối xung nhịp đến mọi flip-flop với skew tối thiểu |
| 10 | Routing | OpenROAD | Đi dây kim loại kết nối các cells, sử dụng 5 lớp metal (met1–met5) của Sky130 |
| 11 | Post-PnR Sim | Icarus + SDF | Mô phỏng với trễ thực tế (back-annotation từ file SDF) — kiểm tra timing violations trước signoff |
| SIGNOFF & TAPEOUT | |||
| 12 | Signoff | Magic + Netgen | Kiểm tra cuối cùng: DRC (quy tắc sản xuất), LVS (layout khớp netlist), antenna check |
| 13 | GDSII | KLayout | Xuất file layout cuối cùng — gửi cho foundry để sản xuất wafer silicon |
Mục tím = các bước mô phỏng/kiểm thử xen kẽ trong quy trình. Trong thực tế, kỹ sư thường quay lại bước trước nếu phát hiện lỗi — đây là quy trình lặp (iterative), không phải một chiều.
Hướng dẫn cài đặt từ đầu trên Ubuntu 24.04 LTS (hoặc tương đương). Toàn bộ toolchain là open-source và miễn phí.
Sơ đồ tổng quan các thành phần trên HOST và trong Docker container:
| Thành phần | Yêu cầu tối thiểu | Khuyến nghị |
|---|---|---|
| Hệ điều hành | Ubuntu 22.04 / 24.04 LTS | Ubuntu 24.04 LTS (64-bit) |
| RAM | 8 GB | 16 GB trở lên |
| Ổ cứng | 30 GB trống | 50 GB+ (SSD khuyến nghị) |
| CPU | 4 cores | 8 cores trở lên |
| Internet | Cần thiết | Tải Docker image ~2GB, PDK ~500MB |
| Quyền | sudo | Cần sudo để cài Docker và apt packages |
Nếu bạn dùng Windows 10 (build 19041+) hoặc Windows 11, bạn có thể chạy toàn bộ toolchain thông qua WSL2 (Windows Subsystem for Linux). Sau khi cài WSL2 với Ubuntu, các bước tiếp theo hoàn toàn giống trên Ubuntu native.
Mở PowerShell với quyền Administrator và chạy:
# Cài WSL2 + Ubuntu 24.04 (một lệnh duy nhất) wsl --install -d Ubuntu-24.04 # Nếu đã có WSL1, nâng cấp lên WSL2: wsl --set-default-version 2 # Khởi động lại máy tính sau khi cài xong
Tạo file C:\Users\<username>\.wslconfig để cấp đủ tài nguyên cho EDA tools:
# File: C:\Users\<username>\.wslconfig [wsl2] memory=12GB # Cấp ít nhất 8GB, khuyến nghị 12-16GB processors=6 # Số CPU cores swap=4GB # Swap space localhostForwarding=true
Sau khi tạo/sửa file, chạy wsl --shutdown rồi mở lại Ubuntu để áp dụng.
Mở Ubuntu 24.04 từ Start Menu (hoặc gõ wsl trong terminal). Lần đầu sẽ yêu cầu tạo username/password.
# Cập nhật hệ thống sudo apt update && sudo apt upgrade -y # Kiểm tra phiên bản Ubuntu lsb_release -a # → Ubuntu 24.04 LTS
Trên Windows, nên dùng Docker Desktop thay vì docker.io trong WSL:
# 1. Tải Docker Desktop từ: https://www.docker.com/products/docker-desktop/ # 2. Cài đặt → bật tùy chọn "Use WSL 2 based engine" # 3. Vào Settings → Resources → WSL Integration # → Bật "Enable integration with my default WSL distro" # → Bật Ubuntu-24.04 # Kiểm tra trong WSL: docker --version docker run hello-world
Lưu ý quan trọng cho WSL:
~/projects/), không đặt trong /mnt/c/ — hiệu suất I/O sẽ chậm hơn 5-10 lần.ms-vscode-remote.remote-wsl) để code trực tiếp trong môi trường Linux.✔ Sau khi hoàn thành các bước trên, tiếp tục từ mục 3.2 bên dưới. Tất cả lệnh giống hệt Ubuntu native.
Cập nhật hệ thống và cài các công cụ cơ bản.
# Cập nhật package list sudo apt update && sudo apt upgrade -y # Cài đặt các tools cơ bản sudo apt install -y \ git \ python3 \ python3-venv \ python3-pip \ python3-tk \ build-essential \ curl \ wget
OpenLane 2 chạy các EDA tools (Yosys, OpenROAD, Magic, Netgen, KLayout) bên trong Docker container. Đây là thành phần bắt buộc.
# Cài Docker sudo apt install -y docker.io # Thêm user hiện tại vào group docker (để chạy không cần sudo) sudo usermod -aG docker $USER # QUAN TRỌNG: Logout rồi login lại để group có hiệu lực # Hoặc chạy lệnh sau để áp dụng ngay: newgrp docker # Kiểm tra Docker hoạt động docker run hello-world
Lưu ý:
Nếu dùng VS Code Remote SSH, session cũ có thể không nhận group docker mới. Cần đóng hoàn toàn VS Code và kết nối lại. Nếu vẫn lỗi permission, chạy tạm: sudo chmod 666 /var/run/docker.sock
Các tools này chạy trực tiếp trên host (không qua Docker), dùng để viết RTL, chạy simulation, và xem waveform.
# Verilator: lint checking + fast simulation sudo apt install -y verilator # Icarus Verilog: RTL simulation, tạo file VCD waveform sudo apt install -y iverilog # GTKWave: xem waveform từ file VCD sudo apt install -y gtkwave # Yosys: synthesis (cũng có trong Docker, nhưng cài host để dùng nhanh) sudo apt install -y yosys # Graphviz: vẽ schematic từ Yosys (yosys "show" command) sudo apt install -y graphviz xdot
Kiểm tra versions:
verilator --version # Verilator 5.020+ iverilog -V # Icarus Verilog 12.0+ yosys --version # Yosys 0.33+ gtkwave --version # GTKWave 3.3+
OpenLane 2 là framework Python điều phối toàn bộ flow RTL→GDSII. Cài trong virtual environment để không ảnh hưởng hệ thống.
# Tạo virtual environment python3 -m venv ~/openlane-env # Kích hoạt venv source ~/openlane-env/bin/activate # Cài OpenLane 2 pip install --upgrade pip pip install openlane # Kiểm tra openlane --version # Output: OpenLane v2.3.10
Quan trọng:
Mỗi lần mở terminal mới, cần chạy source ~/openlane-env/bin/activate trước khi dùng OpenLane. Có thể thêm vào ~/.bashrc để tự động kích hoạt.
Sky130 là Process Design Kit miễn phí từ Google/SkyWater, công nghệ 130nm. Chứa thông tin về standard cells, timing, layout rules.
# Kích hoạt venv (nếu chưa) source ~/openlane-env/bin/activate # Tìm revision phù hợp với phiên bản OpenLane đã cài cat ~/openlane-env/lib/python3.12/site-packages/openlane/open_pdks_rev # Output: 0fe599b2afb6708d281543108caf8310912f54af # Tải và enable Sky130 PDK volare enable --pdk sky130 0fe599b2afb6708d281543108caf8310912f54af # Quá trình tải ~500MB, bao gồm: # - sky130_fd_sc_hd: High-Density standard cells # - sky130_fd_sc_hvl: High-Voltage standard cells # - sky130_fd_io: IO cells # - sky130_fd_pr: Primitive devices # - sky130_sram_macros: SRAM macros
PDK được lưu tại: ~/.volare/volare/sky130/versions/<revision>/sky130A/
Lần chạy đầu tiên, OpenLane sẽ tự động pull Docker image (~2GB). Có thể pull trước để tiết kiệm thời gian.
# Pull trước Docker image docker pull ghcr.io/efabless/openlane2:2.3.10 # Kiểm tra image đã tải docker images | grep openlane
Nếu dùng VS Code làm editor, cài các extensions sau để hỗ trợ thiết kế chip.
| Extension | Chức năng | Cài đặt |
|---|---|---|
| TerosHDL | All-in-one cho HDL: syntax highlighting, schematic viewer, documentation generation, linting | teros-technology.teroshdl |
| SystemVerilog | Language server cho SystemVerilog: go-to-definition, hover info, autocomplete | eirikpre.systemverilog |
| Verilog-HDL | Linting với Verilator/iverilog, syntax highlighting | mshr-h.veriloghdl |
| WaveTrace | Xem waveform .vcd ngay trong VS Code | wavetrace.wavetrace |
# Cài tất cả extensions bằng CLI:
code --install-extension teros-technology.teroshdl
code --install-extension eirikpre.systemverilog
code --install-extension mshr-h.veriloghdl
code --install-extension wavetrace.wavetrace
Các package để tạo report, vẽ hình, xử lý dữ liệu thiết kế.
# Kích hoạt venv source ~/openlane-env/bin/activate # Matplotlib: vẽ waveform, biểu đồ pip install matplotlib # KLayout đã được cài cùng OpenLane (klayout Python module) # Dùng để render layout GDSII thành hình ảnh python3 -c "import klayout; print('KLayout OK')"
Chạy script dưới đây để xác nhận mọi thứ đã cài đúng:
#!/bin/bash
echo "=== System Check ==="
echo -n "OS: "; lsb_release -d | cut -f2
echo -n "RAM: "; free -h | awk '/Mem/{print $2}'
echo -n "Disk free: "; df -h / | awk 'NR==2{print $4}'
echo ""
echo "=== Docker ==="
echo -n "Docker: "; docker --version 2>/dev/null || echo "NOT INSTALLED"
echo -n "Permission: "; docker ps &>/dev/null && echo "OK" || echo "FAILED (run: sudo usermod -aG docker $USER)"
echo ""
echo "=== EDA Tools ==="
echo -n "Verilator: "; verilator --version 2>/dev/null | head -1 || echo "NOT INSTALLED"
echo -n "Iverilog: "; iverilog -V 2>/dev/null | head -1 || echo "NOT INSTALLED"
echo -n "Yosys: "; yosys --version 2>/dev/null || echo "NOT INSTALLED"
echo -n "GTKWave: "; which gtkwave &>/dev/null && echo "OK" || echo "NOT INSTALLED"
echo ""
echo "=== OpenLane ==="
source ~/openlane-env/bin/activate 2>/dev/null
echo -n "OpenLane: "; python3 -c "import openlane; print(openlane.__version__)" 2>/dev/null || echo "NOT INSTALLED"
echo -n "KLayout: "; python3 -c "import klayout; print('OK')" 2>/dev/null || echo "NOT INSTALLED"
echo ""
echo "=== Sky130 PDK ==="
PDK_PATH=$(find ~/.volare -name "sky130A" -type d 2>/dev/null | head -1)
if [ -n "$PDK_PATH" ]; then
echo "PDK path: $PDK_PATH"
echo -n "HD cells: "; ls "$PDK_PATH/libs.ref/sky130_fd_sc_hd/lef/" 2>/dev/null | wc -l; echo " LEF files"
else
echo "PDK: NOT INSTALLED"
fi
echo ""
echo "=== Docker Image ==="
docker images ghcr.io/efabless/openlane2 --format "{{.Tag}} ({{.Size}})" 2>/dev/null || echo "NOT PULLED"
Hướng dẫn từng bước để chạy demo 8-bit counter từ RTL đến GDSII. Giả sử đã cài đặt xong môi trường theo Section 15.
mkdir -p ~/projects/chip_demo cd ~/projects/chip_demo
Tạo file counter.sv với nội dung:
module counter ( input logic clk, input logic rst_n, input logic en, output logic [7:0] count ); always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) count <= 8'b0; else if (en) count <= count + 1; end endmodule
Tạo file tb_counter.sv với nội dung:
module tb_counter; logic clk, rst_n, en; logic [7:0] count; counter dut (.*); // auto-connect ports cùng tên initial clk = 0; always #5 clk = ~clk; // Clock 10ns (100MHz) initial begin $dumpfile("counter.vcd"); $dumpvars(0, tb_counter); rst_n = 0; en = 0; // Reset #20; rst_n = 1; en = 1; // Bắt đầu đếm #500; en = 0; // Dừng đếm #50; en = 1; // Đếm tiếp #200; $display("Final count = %0d", count); $finish; end endmodule
Mô phỏng để kiểm tra RTL đúng logic trước khi synthesis.
# Compile iverilog -g2012 -o counter_sim counter.sv tb_counter.sv # Chạy simulation vvp counter_sim # Output: Final count = 70 # Xem waveform (nếu có GUI) gtkwave counter.vcd & # Hoặc xem trong VS Code với extension WaveTrace: # Mở file counter.vcd trong VS Code
Kết quả mong đợi:
Counter bắt đầu từ 0, đếm lên khi EN=1, dừng khi EN=0, tiếp tục khi EN=1 lại. Giá trị cuối = 70.
Dùng Yosys để tạo sơ đồ nguyên lý trước và sau synthesis.
# RTL schematic (trước synthesis) yosys -p "read_verilog -sv counter.sv; hierarchy -top counter; proc; opt; \ show -format png -prefix schematic counter" # Gate-level schematic (sau synthesis) yosys -p "read_verilog -sv counter.sv; hierarchy -top counter; proc; opt; \ flatten; synth -top counter; \ show -format png -prefix synth_schematic counter" # Kết quả: schematic.png và synth_schematic.png
File cấu hình cho OpenLane. Đây là các tham số tối thiểu.
{
"DESIGN_NAME": "counter",
"VERILOG_FILES": ["dir::counter.sv"],
"CLOCK_PORT": "clk",
"CLOCK_PERIOD": 10.0,
"FP_CORE_UTIL": 50,
"PL_TARGET_DENSITY_PCT": 60,
"DIE_AREA": "0 0 100 100",
"FP_SIZING": "absolute"
}
| Tham số | Giải thích |
|---|---|
DESIGN_NAME | Tên module top-level trong RTL |
VERILOG_FILES | Danh sách file RTL. dir:: = relative path từ thư mục chứa config.json |
CLOCK_PORT | Tên port clock |
CLOCK_PERIOD | Chu kỳ clock mục tiêu (ns). 10.0 = 100MHz |
FP_CORE_UTIL | % diện tích core dành cho cells. 50% là an toàn |
PL_TARGET_DENSITY_PCT | Mật độ placement mục tiêu. 60% phù hợp cho design nhỏ |
DIE_AREA | Kích thước die (x0 y0 x1 y1 theo um). 100x100um đủ cho counter |
FP_SIZING | absolute = dùng DIE_AREA cố định |
Đây là bước chính — chạy toàn bộ 78 bước từ RTL đến GDSII.
# Kích hoạt venv source ~/openlane-env/bin/activate # Di chuyển vào thư mục project cd ~/projects/chip_demo # Chạy OpenLane (lần đầu sẽ pull Docker image ~2GB) docker run --rm \ -v $HOME:$HOME \ -v $HOME/.volare:$HOME/.volare \ -e PDK_ROOT=$HOME/.volare \ -e PDK=sky130A \ -w $(pwd) \ ghcr.io/efabless/openlane2:2.3.10 \ openlane --pdk sky130A config.json # Thời gian: ~1-3 phút cho design nhỏ # Kết quả nằm trong: runs/RUN_<timestamp>/
Kết quả mong đợi:
Flow chạy 78/78 steps. Cuối cùng hiển thị:
* Antenna: Passed
* LVS: Passed
* DRC: Passed
Flow complete.
Xem các file output và metrics.
# Tìm thư mục kết quả (thay <timestamp> bằng giá trị thực) RUN_DIR=$(ls -td runs/RUN_* | head -1) # Xem metrics tổng hợp python3 -c " import json with open('$RUN_DIR/final/metrics.json') as f: content = f.read().replace('Infinity', '\"Inf\"') m = json.loads(content) print(f'Cells: {m[\"design__instance__count\"]}') print(f'Area: {m[\"design__instance__area\"]} um2') print(f'Setup slack: {m[\"timing__setup__ws\"]:.3f} ns') print(f'Hold slack: {m[\"timing__hold__ws\"]:.3f} ns') print(f'Power: {m[\"power__total\"]*1000:.3f} mW') print(f'Wirelength: {m[\"route__wirelength\"]} um') print(f'DRC errors: {m[\"magic__drc_error__count\"]}') print(f'LVS errors: {m[\"design__lvs_error__count\"]}') " # Liệt kê output files ls $RUN_DIR/final/ # Các thư mục quan trọng: # gds/ → file GDSII (gửi fab) # lef/ → Layout Exchange Format # nl/ → gate-level netlist # sdf/ → timing delay annotation # spef/ → parasitic data # spice/ → SPICE netlist
Render file GDSII thành hình ảnh bằng KLayout Python.
# Kích hoạt venv source ~/openlane-env/bin/activate # Render GDSII ra PNG python3 -c " import klayout.db as db from klayout.lay import LayoutView layout = db.Layout() RUN_DIR = '$(ls -td runs/RUN_* | head -1)' layout.read(f'{RUN_DIR}/final/gds/counter.gds') lv = LayoutView() lv.show_layout(layout, True) lv.max_hier() lv.zoom_fit() lv.save_image('layout.png', 1200, 1200) print('Saved layout.png') " # Mở hình: xdg-open layout.png (GUI) hoặc xem trong VS Code
| Lỗi | Nguyên nhân | Cách sửa |
|---|---|---|
docker: permission denied |
User chưa trong group docker | sudo usermod -aG docker $USER rồi logout/login lại |
No module named 'tkinter' |
Thiếu python3-tk | sudo apt install python3-tk |
the input device is not a TTY |
Dùng openlane --dockerized trong non-interactive shell |
Chạy trực tiếp qua docker run thay vì --dockerized (xem bước 7) |
Could not determine open_pdks version |
volare không tìm được revision | Chỉ định revision cụ thể: volare enable --pdk sky130 <revision> |
| Setup violation (slack âm) | Timing không đạt | Tăng CLOCK_PERIOD hoặc tối ưu RTL (xem Section 14) |
| DRC errors > 0 | Routing congestion | Tăng DIE_AREA, giảm FP_CORE_UTIL, tăng DRT_OPT_ITERS |
| Flow rất chậm | Docker image chưa pull | docker pull ghcr.io/efabless/openlane2:2.3.10 trước |
externally-managed-environment |
pip cài ngoài venv trên Ubuntu 24.04 | Luôn dùng python3 -m venv rồi activate trước khi pip install |
Sau khi chạy thành công demo counter, thử các bài tập nâng cao:
| STT | Bài tập | Mô tả |
|---|---|---|
| 1 | Counter 16-bit | Sửa [7:0] thành [15:0]. Quan sát area và timing thay đổi |
| 2 | Counter up/down | Thêm port up_down điều khiển hướng đếm. Thêm logic vào RTL |
| 3 | Push frequency | Giảm CLOCK_PERIOD xuống 2.0ns (500MHz). Quan sát setup slack |
| 4 | Viết SDC riêng | Tạo file counter.sdc với false path cho reset, thêm vào config |
| 5 | ALU đơn giản | Thiết kế ALU 8-bit (add, sub, and, or, xor). Module phức tạp hơn |
| 6 | UART TX | Thiết kế bộ truyền UART. Có FSM, baud rate generator |
| 7 | SPI Master | Module SPI master với clock divider, shift register, FSM |
| 8 | RISC-V CPU | Thử chạy flow cho một RISC-V core đơn giản (VD: PicoRV32) |
module counter ( input logic clk, input logic rst_n, input logic en, output logic [7:0] count ); always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) count <= 8'b0; else if (en) count <= count + 1; end endmodule
module tb_counter; logic clk; logic rst_n; logic en; logic [7:0] count; counter dut ( .clk(clk), .rst_n(rst_n), .en(en), .count(count) ); // Clock: 10ns period initial clk = 0; always #5 clk = ~clk; initial begin $dumpfile("counter.vcd"); $dumpvars(0, tb_counter); rst_n = 0; en = 0; #20; rst_n = 1; en = 1; #500; en = 0; #50; en = 1; #200; $display("Final count = %0d", count); $finish; end endmodule
Functional simulation using Icarus Verilog. The counter starts at 0, counts up when EN=1, pauses when EN=0, and resumes when EN=1 again. Final value: 70.
| Time (ns) | Event | Expected Behavior |
|---|---|---|
| 0 - 20 | Reset active (rst_n=0, en=0) | count = 0 |
| 20 - 520 | Counting (rst_n=1, en=1) | count increments each clock |
| 520 - 570 | Paused (en=0) | count holds value |
| 570 - 770 | Resume (en=1) | count continues from held value |
| 770 | Simulation end | Final count = 70 |
Mô phỏng RTL là bước đầu tiên và quan trọng nhất trong quy trình verification. Đây là mô phỏng zero-delay (không có trễ) — chỉ kiểm tra logic đúng/sai, chưa quan tâm timing.
Quy trình 3 bước: Compile → Run → View waveform
# -g2012: bật chuẩn SystemVerilog (IEEE 1800-2012) # -o: chỉ định file output (simulation binary) # Liệt kê tất cả source files: RTL + testbench iverilog -g2012 -o counter_sim counter.sv tb_counter.sv
# vvp = Verilog Virtual Processor (runtime engine) # Sẽ tạo file counter.vcd (Value Change Dump) vvp counter_sim
# GTKWave — công cụ xem waveform mã nguồn mở gtkwave counter.vcd & # Hoặc dùng WaveTrace extension trong VS Code # (cài từ VS Code Marketplace, mở file .vcd trực tiếp)
Thay vì xem waveform bằng mắt, hãy viết testbench tự kiểm tra. Đây là kỹ năng bắt buộc trong verification chuyên nghiệp.
module tb_counter_selfcheck; logic clk, rst_n, en; logic [7:0] count; integer errors = 0; logic [7:0] expected; // Instantiate DUT counter dut (.clk(clk), .rst_n(rst_n), .en(en), .count(count)); initial clk = 0; always #5 clk = ~clk; // Task kiểm tra giá trị task check(input [7:0] exp, input string msg); if (count !== exp) begin $error("FAIL: %s — got %0d, expected %0d at %0t", msg, count, exp, $time); errors++; end endtask initial begin // Test 1: Reset rst_n = 0; en = 0; #20; check(0, "Reset"); // Test 2: Count up rst_n = 1; en = 1; expected = 0; repeat(10) begin @(posedge clk); #1; expected++; check(expected, "Count up"); end // Test 3: Pause en = 0; repeat(5) @(posedge clk); #1; check(expected, "Pause"); // Kết quả if (errors == 0) $display("*** TEST PASSED ***"); else $display("*** TEST FAILED: %0d errors ***", errors); $finish; end endmodule
VCD (Value Change Dump) là chuẩn IEEE nhưng file rất lớn. FST là định dạng nén của GTKWave, nhỏ hơn 10-50x.
| Đặc điểm | VCD | FST |
|---|---|---|
| Chuẩn | IEEE 1364 | GTKWave proprietary |
| Kích thước | Rất lớn (text) | Nhỏ hơn 10-50x (binary nén) |
| Tốc độ ghi | Chậm | Nhanh |
| Công cụ hỗ trợ | Tất cả viewers | GTKWave |
| Dùng khi | Cần tương thích mọi tool | Dự án lớn, tiết kiệm disk |
# Convert VCD → FST (nhỏ hơn nhiều lần) vcd2fst counter.vcd counter.fst # Mở FST trong GTKWave gtkwave counter.fst &
Waveform (dạng sóng) là công cụ debug trực quan nhất trong thiết kế số. Dưới đây là hướng dẫn cách đọc và phân tích waveform với GTKWave.
| Dạng tín hiệu | Biểu diễn | Ý nghĩa |
|---|---|---|
| 1-bit (wire/reg) | Đường cao (1) / thấp (0) | clk, reset, enable — đọc mức logic tại mỗi thời điểm |
| Bus nhiều bit | Hình thang với giá trị hex/dec | [7:0] count — đọc giá trị số tại mỗi thời điểm |
| X (unknown) | Màu đỏ / gạch chéo | Giá trị chưa xác định — thường do chưa reset hoặc lỗi logic |
| Z (high-impedance) | Màu xanh / đường giữa | Không ai drive tín hiệu — floating, thường là lỗi kết nối |
Cách đọc: Ban đầu count = X (chưa reset). Khi reset = 1, count = 00. Khi enable = 1, count tăng 01, 02, 03... tại mỗi cạnh lên clock.
Kiểm tra cơ bản
Debug nâng cao
| Phím tắt | Chức năng | Khi nào dùng |
|---|---|---|
Ctrl + Scroll | Zoom in/out theo thời gian | Xem tổng quan hoặc chi tiết từng clock |
Shift + Click | Đặt marker (cursor B) | Đo khoảng cách thời gian giữa 2 điểm |
Ctrl + F | Tìm giá trị cụ thể | Tìm lúc count = FF (overflow) |
Left/Right Arrow | Di chuyển đến edge tiếp theo | Duyệt từng thay đổi của tín hiệu |
T | Toggle radix (hex/dec/bin) | Đổi giữa hiển thị hex ↔ decimal ↔ binary |
Ctrl + S | Lưu file .gtkw (save state) | Lưu layout waveform để mở lại sau |
G | Toggle grid | Bật/tắt lưới giúp canh thời gian dễ hơn |
| Hiện tượng | Nguyên nhân có thể | Cách khắc phục |
|---|---|---|
| Tất cả tín hiệu = X | Quên reset hoặc reset sai cực tính | Kiểm tra active-high vs active-low reset |
| Output không đổi | Enable chưa bật hoặc clock không toggle | Kiểm tra clock generator trong testbench |
| Count nhảy sai giá trị | Logic sai hoặc testbench drive sai | Trace ngược từ output → input tại clock edge lỗi |
| Glitch trên output | Combinational hazard (RTL sim) | Bình thường ở RTL sim; gate-level sim sẽ rõ hơn |
| Waveform file trống | Quên $dumpfile/$dumpvars | Thêm system task vào testbench initial block |
Trong ngành chip, verification (kiểm thử) chiếm hơn 60% tổng thời gian và nhân lực phát triển. Một chip lỗi sau khi tape-out có thể gây thiệt hại hàng triệu USD — nên phải kiểm tra kỹ trước khi sản xuất.
Assertions là các điều kiện phải đúng được nhúng vào design hoặc testbench. Khi vi phạm → báo lỗi ngay lập tức, giúp phát hiện bug sớm.
// Kiểm tra reset: count phải = 0 khi rst_n = 0 always @(posedge clk) begin if (!rst_n) assert (count == 8'b0) else $error("Reset failed: count=%0d", count); end
// Property: count tăng 1 khi enabled property p_count_increment; @(posedge clk) disable iff (!rst_n) (en && count < 8'hFF) |=> (count == $past(count) + 1); endproperty assert property (p_count_increment) else $error("Count did not increment"); // Property: count giữ nguyên khi disabled property p_count_stable; @(posedge clk) disable iff (!rst_n) (!en) |=> (count == $past(count)); endproperty assert property (p_count_stable) else $error("Count changed when disabled");
Lưu ý về Icarus Verilog
Icarus Verilog chỉ hỗ trợ immediate assertions. Concurrent assertions (property/sequence) cần Verilator (hỗ trợ một phần) hoặc VCS/Xcelium (hỗ trợ đầy đủ).
Coverage đo bao nhiêu % code đã được kiểm tra. Nếu coverage thấp → còn nhiều trường hợp chưa test → có thể có bug ẩn.
| Loại Coverage | Đo gì | Mục tiêu |
|---|---|---|
| Line Coverage | % dòng code đã thực thi | >95% |
| Toggle Coverage | % tín hiệu đã chuyển 0→1 và 1→0 | >90% |
| Branch Coverage | % nhánh if/else/case đã đi qua | >95% |
| FSM Coverage | % trạng thái và transitions đã thăm | 100% |
| Expression Coverage | % tổ hợp điều kiện boolean | >90% |
# Compile với coverage enabled verilator --cc --exe --build \ --coverage \ -Wno-fatal \ counter.sv tb_counter_verilator.cpp # Chạy simulation (tạo file coverage.dat) ./obj_dir/Vcounter # Xem báo cáo coverage verilator_coverage --annotate coverage_report/ coverage.dat # Mở file annotated để xem dòng nào chưa được test cat coverage_report/counter.sv
Với design phức tạp, viết test case thủ công không thể phủ hết mọi trường hợp. Constrained-random tạo input ngẫu nhiên nhưng tuân theo các ràng buộc hợp lệ.
// Simple constrained-random testbench cho counter module tb_counter_random; logic clk, rst_n, en; logic [7:0] count; integer errors = 0; logic [7:0] expected = 0; counter dut (.clk(clk), .rst_n(rst_n), .en(en), .count(count)); initial clk = 0; always #5 clk = ~clk; initial begin $dumpfile("counter_random.vcd"); $dumpvars(0, tb_counter_random); // Reset rst_n = 0; en = 0; #20; rst_n = 1; // 1000 chu kỳ ngẫu nhiên repeat(1000) begin @(posedge clk); en = $urandom_range(0, 1); // 3% xác suất reset ngẫu nhiên rst_n = ($urandom_range(0, 99) < 3) ? 0 : 1; end $display("Random test done — %0d errors", errors); $finish; end endmodule
UVM (Universal Verification Methodology)
Trong công nghiệp, constrained-random được triển khai bằng UVM — framework chuẩn ngành dựa trên SystemVerilog classes. UVM cung cấp: transaction-level modeling, scoreboard tự động, coverage-driven verification. Cần VCS hoặc Xcelium để chạy UVM đầy đủ.
Tài liệu này tập trung vào công cụ open-source, nhưng khi làm việc trong công ty bạn sẽ gặp các tool thương mại.
| Công cụ | Vendor | Điểm mạnh | License |
|---|---|---|---|
| VCS | Synopsys | Nhanh nhất, full SV/UVM, DVE debugger | Commercial |
| Xcelium | Cadence | Multi-language (VHDL+SV+e), CDC analysis | Commercial |
| QuestaSim | Siemens EDA | GUI debugger mạnh, tích hợp FPGA | Commercial |
| Icarus Verilog | Open-source | Miễn phí, hỗ trợ SV cơ bản, dễ học | GPL |
| Verilator | Open-source | Rất nhanh (C++ compiled), lint, coverage | LGPL |
DFT là các kỹ thuật thiết kế giúp kiểm tra chip sau khi sản xuất. Không có DFT, không thể biết chip silicon có lỗi sản xuất hay không.
# OpenLane hỗ trợ scan insertion tự động # Cấu hình trong config.json: { "SCAN_CHAIN_ENABLE": 1, "SCAN_CHAIN_COUNT": 1 } # Sau synthesis, Yosys thay DFF → Scan DFF # sky130_fd_sc_hd__sdfrtp (scan D flip-flop with reset) # Thêm ports: scan_in, scan_out, scan_enable
ATPG — Tự động sinh Test Patterns
Công cụ ATPG (như Synopsys TetraMAX hoặc Cadence Modus) phân tích netlist + scan chains để tự sinh bộ test patterns tối ưu. Metrics quan trọng: Fault Coverage (% lỗi phát hiện được), Test Coverage (% nodes được test), Pattern Count (ít patterns hơn → test nhanh hơn → chi phí thấp hơn).
Khi design có nhiều clock domain (ví dụ: clock CPU 500MHz + clock bus 100MHz), tín hiệu truyền qua ranh giới clock domain có thể gây metastability — flip-flop rơi vào trạng thái không xác định.
// Đồng bộ tín hiệu 1 bit từ clk_a sang clk_b module sync_2ff ( input logic clk_b, rst_n, input logic data_in, // từ clock domain A output logic data_out // đồng bộ sang clock domain B ); logic meta; // FF1: có thể metastable always_ff @(posedge clk_b or negedge rst_n) begin if (!rst_n) begin meta <= 1'b0; data_out <= 1'b0; end else begin meta <= data_in; // FF1: capture (may go metastable) data_out <= meta; // FF2: resolve metastability end end endmodule
| Công cụ | Vendor | Chức năng |
|---|---|---|
| SpyGlass CDC | Synopsys | Phân tích CDC tĩnh, phát hiện missing synchronizers |
| Conformal CDC | Cadence | CDC verification + formal proof |
| Verilator --lint-only | Open-source | Cảnh báo cơ bản về clock domain (hạn chế) |
Tại sao CDC quan trọng?
Bug CDC không thể phát hiện bằng RTL simulation thông thường vì simulator mô phỏng lý tưởng (zero-delay). Bug chỉ xảy ra trên silicon thật với timing thực tế. Đây là một trong những nguyên nhân hàng đầu gây re-spin chip.
Verification Engineer (VE) là vai trò chiếm số lượng kỹ sư nhiều nhất trong team thiết kế chip. Dưới đây là các hoạt động chính hàng ngày.
Quy trình verification điển hình
1. Đọc spec → 2. Viết verification plan → 3. Xây dựng testbench environment (UVM) → 4. Viết directed tests → 5. Thêm constrained-random tests → 6. Chạy regression + thu coverage → 7. Phân tích coverage holes → 8. Viết thêm tests → 9. Đạt coverage target → 10. Sign-off verification
Pre-synthesis behavioral schematic generated by Yosys. Shows high-level RTL constructs: $adffe (flip-flop with async reset + enable) and $add (8-bit adder).
Post-synthesis gate-level netlist after technology mapping to Sky130 standard cells. The design was mapped to 138 cells including DFFs, buffers, and combinational logic.
| Cell Type | Count | Description |
|---|---|---|
| Sequential (DFF) | 8 | D flip-flops with async reset |
| Combinational | 19 | AND, OR, XOR, MUX gates |
| Clock Buffer | 4 | Clock tree buffers |
| Timing Repair Buffer | 17 | Hold/setup repair buffers |
| Hold Buffer | 7 | Hold time fix buffers |
| Fill Cell | 607 | Filler cells for continuity |
| Tap Cell | 90 | Well tap cells |
Sau khi synthesis (Yosys), RTL code được chuyển thành netlist gồm các gate thực tế từ thư viện Sky130. Gate-level simulation kiểm tra xem quá trình synthesis có giữ đúng chức năng hay không.
Cần 3 thành phần: synthesized netlist + Sky130 cell models + testbench.
# 1. Xác định đường dẫn file netlist sau synthesis ls runs/RUN_*/results/synthesis/counter.synthesis.v # 2. Xác định đường dẫn Sky130 cell simulation models CELL_MODELS="$PDK_ROOT/sky130A/libs.ref/sky130_fd_sc_hd/verilog" # 3. Compile gate-level simulation iverilog -g2012 \ -o counter_gl_sim \ -DFUNCTIONAL \ -DUNIT_DELAY="#1" \ -I $CELL_MODELS \ $CELL_MODELS/primitives.v \ $CELL_MODELS/sky130_fd_sc_hd.v \ runs/RUN_*/results/synthesis/counter.synthesis.v \ tb_counter_gl.sv # 4. Chạy simulation vvp counter_gl_sim # 5. Xem waveform và so sánh với RTL simulation gtkwave counter_gl.vcd &
Giải thích các flag quan trọng
-DFUNCTIONAL: bỏ qua timing checks, chỉ kiểm tra logic. -DUNIT_DELAY="#1": thêm delay 1 đơn vị cho mỗi gate. -I: đường dẫn include cho cell models.
Testbench cho gate-level cần: reset lâu hơn (chờ X settle), tolerance cho timing, và xử lý tín hiệu X.
`timescale 1ns/1ps module tb_counter_gl; logic clk, rst_n, en; logic [7:0] count; // Instantiate gate-level netlist counter dut ( .clk(clk), .rst_n(rst_n), .en(en), .count(count) ); initial clk = 0; always #5 clk = ~clk; initial begin $dumpfile("counter_gl.vcd"); $dumpvars(0, tb_counter_gl); // Reset lâu hơn RTL sim (chờ X propagation settle) rst_n = 0; en = 0; #100; // 100ns thay vì 20ns rst_n = 1; en = 1; #500; en = 0; #50; en = 1; #200; $display("GL sim — Final count = %0d", count); $finish; end endmodule
| Đặc điểm | RTL Simulation | Gate-Level Simulation |
|---|---|---|
| Input | counter.sv (RTL source) | counter.synthesis.v (netlist) |
| Tốc độ | Nhanh | Chậm hơn 10-100x |
| Timing | Zero-delay | Zero-delay hoặc unit-delay |
| X-propagation | Ít gặp | Thường gặp (cần reset kỹ) |
| Phát hiện | Lỗi logic trong RTL | Lỗi synthesis, optimization sai |
| Cần thêm | Chỉ testbench | Cell models (Sky130 Verilog) |
Troubleshooting thường gặp
Tín hiệu X không settle: tăng thời gian reset. Module not found: kiểm tra đường dẫn cell models (-I flag). Kết quả khác RTL: kiểm tra define FUNCTIONAL — nếu thiếu, cell models sẽ check timing và báo violation.
| Metric | VPWR | VGND |
|---|---|---|
| Worst Voltage | 1.7997V | 0.000208V |
| Worst Drop | 0.259 mV | 0.208 mV |
| Average Drop | 0.048 mV | 0.032 mV |
| Status | PASS | PASS |
Final routed layout with all 36 mask layers. Standard cells are placed in rows with signal routing on metal layers between them.
Sau Place & Route, các parasitic (R, C) từ dây nối thực tế được trích xuất. SDF (Standard Delay Format) chứa delay chính xác của mỗi gate và interconnect. Đây là mô phỏng chính xác nhất trước khi sản xuất chip.
OpenLane/OpenROAD tự động tạo file SDF cho nhiều PVT corners sau khi hoàn thành routing.
# Các file SDF được tạo tự động sau P&R ls runs/RUN_*/results/final/sdf/ # Typical corner (25°C, 1.80V) runs/RUN_*/results/final/sdf/nom_tt_025C_1v80/counter.sdf # Slow corner (100°C, 1.60V) — worst-case setup runs/RUN_*/results/final/sdf/nom_ss_100C_1v60/counter.sdf # Fast corner (-40°C, 1.95V) — worst-case hold runs/RUN_*/results/final/sdf/nom_ff_n40C_1v95/counter.sdf # Xem nội dung SDF (ví dụ) head -30 runs/RUN_*/results/final/sdf/nom_tt_025C_1v80/counter.sdf # (IOPATH clk Q (0.215:0.215:0.215) (0.178:0.178:0.178))
# Dùng netlist sau P&R (final netlist) NETLIST="runs/RUN_*/results/final/verilog/gl/counter.v" SDF="runs/RUN_*/results/final/sdf/nom_tt_025C_1v80/counter.sdf" CELL_MODELS="$PDK_ROOT/sky130A/libs.ref/sky130_fd_sc_hd/verilog" # Compile timing simulation iverilog -g2012 \ -o counter_sdf_sim \ -I $CELL_MODELS \ $CELL_MODELS/primitives.v \ $CELL_MODELS/sky130_fd_sc_hd.v \ $NETLIST \ tb_counter_sdf.sv # Chạy simulation vvp counter_sdf_sim # Xem waveform — sẽ thấy delay thực tế gtkwave counter_sdf.vcd &
`timescale 1ns/1ps module tb_counter_sdf; logic clk, rst_n, en; logic [7:0] count; counter dut (.clk(clk), .rst_n(rst_n), .en(en), .count(count)); // SDF back-annotation initial begin $sdf_annotate("runs/RUN_*/results/final/sdf/nom_tt_025C_1v80/counter.sdf", dut); end initial clk = 0; always #5 clk = ~clk; initial begin $dumpfile("counter_sdf.vcd"); $dumpvars(0, tb_counter_sdf); rst_n = 0; en = 0; #100; rst_n = 1; en = 1; #500; en = 0; #50; en = 1; #200; $display("SDF sim — Final count = %0d", count); $finish; end endmodule
Hạn chế của Icarus Verilog với SDF
Icarus Verilog hỗ trợ $sdf_annotate nhưng không đầy đủ tất cả SDF constructs. Trong công nghiệp dùng VCS hoặc Xcelium cho timing simulation chính xác.
| Đặc điểm | STA | Timing Simulation |
|---|---|---|
| Phương pháp | Phân tích tĩnh tất cả paths | Chạy mô phỏng với delay thực |
| Tốc độ | Rất nhanh (phút) | Chậm (giờ cho design lớn) |
| Coverage | 100% timing paths | Chỉ paths được kích hoạt |
| Glitch detection | Không | Có (thấy trong waveform) |
| Dùng khi | Signoff chính (bắt buộc) | Bổ sung, debug timing |
| Cấp độ | Input | Timing | Độ chính xác | Tốc độ | Khi nào |
|---|---|---|---|---|---|
| RTL Sim | .sv files | Zero-delay | Functional only | Nhanh nhất | Sau code RTL |
| Gate-Level Sim | Netlist + cell libs | Unit-delay | Structural | Trung bình | Sau synthesis |
| Post-Layout Sim | Netlist + SDF | Real delays | Chính xác nhất | Chậm nhất | Sau P&R |
Static Timing Analysis across 9 PVT corners. All corners pass with zero violations.
| Corner | Setup Slack (ns) | Hold Slack (ns) | Setup TNS | Hold TNS | Violations |
|---|---|---|---|---|---|
| nom_tt_025C_1v80 | +6.821 | +0.362 | 0 | 0 | 0 |
| nom_ss_100C_1v60 | +5.984 | +0.872 | 0 | 0 | 0 |
| nom_ff_n40C_1v95 | +7.127 | +0.135 | 0 | 0 | 0 |
| min_tt_025C_1v80 | +6.831 | +0.356 | 0 | 0 | 0 |
| min_ss_100C_1v60 | +5.995 | +0.873 | 0 | 0 | 0 |
| min_ff_n40C_1v95 | +7.134 | +0.131 | 0 | 0 | 0 |
| max_tt_025C_1v80 | +6.812 | +0.367 | 0 | 0 | 0 |
| max_ss_100C_1v60 (worst) | +5.971 | +0.868 | 0 | 0 | 0 |
| max_ff_n40C_1v95 | +7.120 | +0.139 | 0 | 0 | 0 |
| Property | Value |
|---|---|
| Clock Name | clk |
| Period | 10.0 ns |
| Waveform | 0.0 / 5.0 ns |
| Min Period Achievable | 1.53 ns |
| Max Frequency | 652.92 MHz |
| Clock Buffers | 4 (2-level tree) |
| Max Skew | 3.14 ps |
| Max Latency | 0.294 ns |
Static Timing Analysis (STA) phân tích tất cả đường dữ liệu (timing path) trong chip mà không cần chạy mô phỏng. STA kiểm tra xem dữ liệu có đến đúng thời điểm tại mỗi flip-flop hay không, dựa trên hai ràng buộc cơ bản: Setup Time và Hold Time.
Dữ liệu phải ổn định TRƯỚC cạnh clock ít nhất Tsetup
Dữ liệu phải giữ ổn định SAU cạnh clock ít nhất Thold
| Metric | Định nghĩa | Công thức | Ví dụ (design này) | Đánh giá |
|---|---|---|---|---|
| Slack | Margin thời gian còn dư trên 1 path | Data Required Time − Data Arrival Time |
+6.821 ns | MET |
| WNS Worst Negative Slack |
Slack tệ nhất trong toàn bộ design | min(slack của tất cả path) |
0 (không có slack âm) | PASS |
| TNS Total Negative Slack |
Tổng tất cả slack âm | ∑(slack < 0) |
0 | PASS |
Slack > 0: PASS (MET) | Slack < 0: FAIL (VIOLATED) — chip không hoạt động đúng ở tần số mục tiêu.
Những kiểm tra sau BẮT BUỘC phải PASS trên TẤT CẢ PVT corners trước khi gửi fab. Nếu còn vi phạm, chip sẽ KHÔNG hoạt động đúng.
| Check | Mức nghiêm trọng | Hậu quả | Fix sau fab? |
|---|---|---|---|
| Setup Violations WNS < 0 (max path) |
CRITICAL | Chip chạy sai ở tần số mục tiêu. Data đến flip-flop muộn → latch sai giá trị. Có thể chạy đúng nếu giảm tần số. | KHÔNG — phải respin |
| Hold Violations WNS < 0 (min path) |
NGHIÊM TRỌNG NHẤT | Chip chạy sai ở MỌI tần số (kể cả 1 Hz). Race condition → data bị ghi đè trước khi được đọc. | KHÔNG — phải respin |
TẠI SAO HOLD NGHIÊM TRỌNG HƠN SETUP?
Setup violation: có thể “chữa cháy” bằng cách giảm clock frequency → tăng thời gian cho data đến.
Hold violation: KHÔNG THỂ fix bằng bất kỳ cách nào sau fabrication:
→ Trong quy trình thiết kế, hold phải được fix triệt để trước khi tapeout.
Ngoài setup/hold, OpenSTA còn kiểm tra các vi phạm signal integrity. Đây không trực tiếp gây lỗi chức năng, nhưng làm giảm độ tin cậy và có thể gây timing failure gián tiếp.
| Vi phạm | Ý nghĩa | Hậu quả | Cách fix |
|---|---|---|---|
| Max Slew Transition time |
Tín hiệu chuyển đổi (0→1 hoặc 1→0) quá chậm | Switching không tin cậy, tăng dòng ngắn mạch, có thể gây metastability | Thêm buffer, dùng cell drive lớn hơn |
| Max Capacitance Wire/pin load |
Tải capacitance trên wire/pin quá lớn | Slew degradation → tăng delay → có thể gây setup violation | Route lại, thêm buffer |
| Max Fanout Số lượng loads |
1 output phải drive quá nhiều inputs | Timing degradation, tăng slew | Thêm buffer tree (OpenLane tự động: step 31) |
Trong design counter 8-bit này, tất cả 3 kiểm tra đều PASS (0 violations) — xem bảng Signoff ở Mục 13.
Chip phải hoạt động đúng trong mọi điều kiện vận hành. Biến thiên trong quá trình sản xuất (Process), điện áp (Voltage), và nhiệt độ (Temperature) tạo ra các “corner” — trường hợp cực trị phải kiểm tra.
| ss (slow-slow) | Transistor chậm, delay lớn nhất |
| tt (typical) | Nominal — giá trị trung bình |
| ff (fast-fast) | Transistor nhanh, delay nhỏ nhất |
| 1v60 | Điện áp thấp → chậm hơn |
| 1v80 | Nominal |
| 1v95 | Điện áp cao → nhanh hơn |
| 100C | Nóng → điện trở tăng, chậm hơn |
| 025C | Nhiệt độ phòng |
| n40C | Lạnh (−40°C) → nhanh hơn |
| Check | Worst-case Corner | Tại sao? | Slack trong design này |
|---|---|---|---|
| Setup max delay path |
max_ss_100C_1v60 |
Slow process + nóng + low voltage = delay lớn nhất | +5.971 ns |
| Hold min delay path |
min_ff_n40C_1v95 |
Fast process + lạnh + high voltage = delay nhỏ nhất | +0.131 ns |
Đây là lý do chạy STA trên 9 corners (3 parasitic × 3 PVT): để đảm bảo chip hoạt động đúng trong MỌI điều kiện vận hành.
Clock là “nhịp tim” của chip. Mọi bất thường trong phân phối clock đều ảnh hưởng trực tiếp đến timing.
| Vấn đề | Định nghĩa | Ảnh hưởng Timing | Giá trị (design này) |
|---|---|---|---|
| Clock Skew | Chênh lệch thời gian clock đến giữa 2 flip-flop | Tăng hold risk (nếu launch clock đến trước), giảm setup margin (nếu capture clock đến sớm) | 3.14 ps (rất nhỏ) |
| Clock Uncertainty | Margin dự phòng cho jitter + skew chưa biết | Trừ trực tiếp khỏi data required time → giảm slack | 0.25 ns (xem critical path) |
| Clock Jitter | Biến động ngẫu nhiên của clock edge | Làm tăng uncertainty → giảm timing margin | Modeled trong uncertainty |
| CTS Clock Tree Synthesis |
Xây dựng cây buffer để phân phối clock đều | Thêm latency nhưng giảm skew. Sau CTS cần re-check hold | 4 buffers, 2-level tree (step 34) |
Clock Domain Crossing (CDC)
Design counter này chỉ có 1 clock domain. Với design nhiều clock, cần xử lý CDC bằng synchronizer (2-FF hoặc handshake protocol). CDC violations không được STA phát hiện — cần dùng tool riêng (VD: Spyglass CDC, Questa CDC).
Tìm tắt chiến lược xử lý các vấn đề timing thường gặp. Chi tiết config parameters xem ở Mục 16.
| Vấn đề | Nguyên nhân gốc | Fix (Config) | Fix (RTL) | OpenLane Step |
|---|---|---|---|---|
| Setup violation WNS < 0 (max) |
Combinational path quá dài | SYNTH_STRATEGY: "DELAY 0"Tăng CLOCK_PERIOD |
Pipeline: thêm FF giữa các tầng logic | Step 54 report |
| Hold violation WNS < 0 (min) |
Path quá ngắn giữa 2 FF | Tăng PL_RESIZER_HOLD_SLACK_MARGINTăng CTS_HOLD_SLACK_MARGIN |
Hiếm khi cần — tool tự chèn buffer | Step 36 auto-fix |
| Max Slew | Wire dài, cell drive yếu | Tăng DIE_AREA |
Giảm fanout trong RTL | Step 31 auto-fix |
| Max Cap | Load quá nhiều trên 1 net | Thêm buffer | Chia net thành nhiều nhánh | Step 31 auto-fix |
| Max Fanout | 1 output → quá nhiều inputs | SYNTH_MAX_FANOUT: 6 |
Restructure logic tree | Step 31 auto-fix |
| Clock skew cao | Clock tree không cân bằng | CTS_CLK_MAX_WIRE_LENGTH |
Giảm số FF trên 1 domain | Step 34 CTS |
Hãy quay lại xem Critical Path report ở trên và hiểu từng phần. Dưới đây là giải thích chi tiết từng dòng:
| Group | Internal (uW) | Switching (uW) | Leakage (pW) | Total (uW) | % |
|---|---|---|---|---|---|
| Sequential | 50.4 | 15.3 | 91.4 | 65.7 | 26.7% |
| Combinational | 46.0 | 64.4 | 120.0 | 110.4 | 44.8% |
| Clock Network | 55.5 | 14.9 | 569.7 | 70.4 | 28.6% |
| Total | 151.9 | 94.6 | 781.1 | 246.6 | 100% |
Tổng công suất tiêu thụ của chip gồm hai phần chính: Dynamic Power (tiêu thụ khi hoạt động) và Static Power (tiêu thụ ngay cả khi không chuyển mạch).
Dynamic power chiếm 99.97% tổng công suất trong design này. Đây là thành phần chính cần tối ưu.
Pdynamic = α · CL · VDD² · f
| Ký hiệu | Ý nghĩa | Ảnh hưởng | Cách giảm |
|---|---|---|---|
| α Activity Factor |
Tỷ lệ chuyển mạch (0→1, 1→0) trên mỗi chu kỳ clock | Tuyến tính — α ×2 → P ×2 | Clock gating, giảm toggling không cần thiết |
| CL Load Capacitance |
Tổng tụ tải: wire cap + pin cap + internal cap | Tuyến tính — C ×2 → P ×2 | Dùng cell nhỏ hơn, routing ngắn hơn |
| VDD Supply Voltage |
Điện áp nguồn (Sky130: 1.8V nominal) | Bình phương — V ×2 → P ×4 | Voltage scaling, multi-VDD domains |
| f Clock Frequency |
Tần số hoạt động | Tuyến tính — f ×2 → P ×2 | DVFS (Dynamic Voltage-Frequency Scaling) |
Nhận xét: VDD ảnh hưởng mạnh nhất (bình phương). Giảm điện áp 10% → giảm dynamic power ~19%.
Trong design Sky130 (130nm) này, leakage chỉ chiếm ~0%. Nhưng ở công nghệ tiên tiến hơn, leakage trở thành vấn đề nghiêm trọng.
| Loại Leakage | Nguyên nhân | Phụ thuộc |
|---|---|---|
| Subthreshold Leakage Isub |
Dòng rò qua kênh transistor khi VGS < Vth (transistor “OFF” nhưng vẫn có dòng nhỏ chạy qua) | Tăng theo nhiệt độ, giảm theo Vth |
| Gate Leakage Igate |
Dòng rò qua lớp oxide cổng (tunneling) — oxide mỏng hơn ở node nhỏ | Tăng khi oxide mỏng (node < 65nm) |
| Process Node | Tỷ lệ Leakage / Total | Mức độ lo ngại |
|---|---|---|
| 130nm (Sky130 — design này) | < 1% | Không đáng kể |
| 65nm | 10–20% | Cần lưu ý |
| 28nm | 20–40% | Quan trọng |
| 7nm / 5nm | 30–50%+ | Critical |
Giải pháp: Multi-Vth cells (HVT cho path không critical, LVT cho path critical), Power Gating (tắt nguồn module không dùng).
Công suất không chỉ ảnh hưởng đến pin/battery. Power quá cao gây ra hàng loạt vấn đề vật lý nghiêm trọng.
| Vấn đề | Nguyên nhân | Hậu quả | Kiểm tra bằng |
|---|---|---|---|
| IR Drop Sụt áp trên PDN |
Dòng lớn chạy qua điện trở wire của Power Distribution Network (VPWR/VGND) | VDD thực tế tại cell giảm → delay tăng → timing failure. Nếu sụt áp >10% → chip có thể không hoạt động | OpenROAD IR Drop Analysis (step 55) |
| Electromigration (EM) Dịch chuyển nguyên tử kim loại |
Mật độ dòng quá cao trên wire → nguyên tử kim loại bị “kéo đi” theo dòng electron | Wire bị đứt (open) hoặc chập (short) sau vài tháng/năm sử dụng → chip hỏng dần | EM analysis (signoff flow) |
| Thermal Nhiệt độ chip |
P = I × V → nhiệt tỏa ra. Power density cao → hotspot | Nhiệt tăng → leakage tăng → nhiệt tăng thêm (thermal runaway). Tệ nhất: chip cháy | Thermal simulation (tool riêng) |
| Ground Bounce Nhiễu trên GND |
Nhiều cell chuyển mạch đồng thời → dòng tức thời (di/dt) lớn trên inductance của bonding wire | Điện áp GND dao động → noise margin giảm → lỗi logic ngẫu nhiên | Decoupling cap, PDN analysis |
POWER BUDGET
Mỗi chip có power budget — giới hạn công suất tối đa dựa trên package thermal resistance và điều kiện tản nhiệt. Vượt quá budget → chip quá nhiệt → không đạt reliability. Trong design counter này: 246.6 μW — rất nhỏ, không cần lo về thermal.
Các kỹ thuật phổ biến để giảm công suất tiêu thụ, sắp xếp theo mức độ hiệu quả.
| Kỹ thuật | Loại Power giảm | Cách hoạt động | Hiệu quả | Hỗ trợ trong OpenLane? |
|---|---|---|---|---|
| Clock Gating | Dynamic | Tắt clock cho module không hoạt động → α = 0 cho toàn bộ logic phía sau | 20–60% dynamic | Có — Yosys tự động infer clock gate từ RTL |
| Voltage Scaling | Dynamic + Static | Giảm VDD → P giảm theo V² | Rất cao (bình phương) | Không — cần multi-VDD PDK |
| Multi-Vth | Static (leakage) | Dùng HVT cell (high threshold, ít rò) cho path không critical. LVT chỉ cho path critical | 30–50% leakage | Có — SYNTH_STRATEGY |
| Power Gating | Static (leakage) | Dùng switch transistor tắt hoàn toàn VDD cho module không dùng | ~100% leakage module đó | Không — cần UPF/CPF flow |
| Operand Isolation | Dynamic | Gate input của module khi output không được dùng → ngăn toggling vô ích | 10–20% | Cần code RTL thủ công |
Ưu tiên cho người mới: Viết RTL “clock-gating friendly” (dùng if (enable) thay vì MUX) → tool synthesis tự động chèn clock gate — đây là cách đơn giản nhất và hiệu quả nhất.
Hãy quay lại bảng Power Breakdown ở trên và hiểu ý nghĩa từng nhóm:
Giảm công suất là ưu tiên hàng đầu trong thiết kế chip hiện đại. Từ công thức Pdynamic = α · CL · V2DD · f, có nhiều kỹ thuật tác động vào từng thành phần.
| Kỹ thuật | Tác động | Mô tả | Mức độ |
|---|---|---|---|
| Clock Gating | Giảm α (activity) | Tắt clock cho module không hoạt động — tiết kiệm 20-40% | RTL / Synthesis |
| Operand Isolation | Giảm α | Giữ input ổn định khi output không cần — giảm switching | RTL |
| Multi-Vt | Giảm leakage | Dùng High-Vt cells cho paths không critical, Low-Vt cho critical paths | Synthesis |
| Voltage Scaling (DVFS) | Giảm VDD | Giảm VDD khi không cần hiệu năng cao — P ∝ V2 | Architecture |
| Power Gating | Tắt hoàn toàn | Cắt nguồn cho module không dùng — cần retention FFs | Architecture / P&R |
| Memory Shutdown | Giảm leakage SRAM | Tắt hoặc đưa SRAM vào sleep mode | Architecture |
Clock gating tắt clock cho các flip-flops khi không cần cập nhật giá trị. Synthesis tools (Yosys, Design Compiler) có thể tự động chèn clock gating cells.
// TRƯỚC clock gating — clock toggle mỗi chu kỳ dù en=0 always_ff @(posedge clk) if (en) count <= count + 1; // SAU clock gating (synthesis tool tự chèn) // Clock gating cell: gated_clk = clk AND en_latched // → khi en=0, gated_clk không toggle → không tiêu dynamic power // Trong OpenLane, clock gating được bật mặc định // Yosys sẽ thay enable-FFs bằng clock-gated FFs khi có thể
Công cụ phân tích power
OpenROAD (trong OpenLane): báo cáo power tĩnh sau P&R. Synopsys PrimeTime PX: phân tích power động với VCD activity. Cadence Voltus: phân tích IR drop, EM. Trong tài liệu này, OpenROAD đã phân tích power ở các mục trên.
| Check | Tool | Errors | Status |
|---|---|---|---|
| Design Rule Check | Magic | 0 | PASS |
| Design Rule Check | KLayout | 0 | PASS |
| Layout vs Schematic | Netgen | 0 device / 0 net / 0 pin mismatches | PASS |
| Antenna Violations | OpenROAD | 0 nets / 0 pins | PASS |
| Illegal Overlap | Magic | 0 | PASS |
| XOR Check (Magic vs KLayout) | KLayout | 0 differences | PASS |
| Max Slew Violations | OpenSTA | 0 | PASS |
| Max Cap Violations | OpenSTA | 0 | PASS |
| Max Fanout Violations | OpenSTA | 0 | PASS |
| Disconnected Pins | ODB | 0 | PASS |
Signoff là bước kiểm tra cuối cùng và bắt buộc trước khi gửi GDSII cho nhà máy (foundry) để sản xuất. Chip được sản xuất sẽ không thể sửa — một lỗi bị bỏ sót nghĩa là phải respin (thiết kế lại + fab lại), tốn hàng triệu USD và hàng tháng delay.
| Loại check | Kiểm tra gì? | Nếu FAIL? | Mức độ |
|---|---|---|---|
| Physical DRC, LVS, Antenna |
Layout có thể sản xuất được không? Layout khớp schematic không? | Foundry từ chối / chip hỏng vật lý | BLOCKER |
| Timing Setup, Hold |
Chip chạy đúng ở tần số mục tiêu trong mọi PVT corner? | Chip chạy sai hoặc không chạy được | BLOCKER |
| Signal Integrity Slew, Cap, Fanout |
Tín hiệu đủ chất lượng? Không quá tải? | Hoạt động không ổn định, reliability thấp | WARNING |
DRC kiểm tra layout tuân thủ design rules của foundry — các ràng buộc vật lý đảm bảo chip có thể được sản xuất thành công bằng quy trình lithography.
| Design Rule | Ý nghĩa | Tại sao cần? | Ví dụ (Sky130) |
|---|---|---|---|
| Minimum Width | Chiều rộng tối thiểu của metal wire / poly | Wire quá mỏng → đứt trong quá trình etch hoặc bị electromigration | Metal1: 0.14 μm |
| Minimum Spacing | Khoảng cách tối thiểu giữa 2 wire cùng layer | Quá gần → short circuit (chập mạch) do lithography không phân giải được | Metal1: 0.14 μm |
| Minimum Enclosure | Via phải nằm trong metal ít nhất một khoảng nhất định | Via lệch ra ngoài → tiếp xúc kém → điện trở cao hoặc open | Via1 enc: 0.055 μm |
| Minimum Area | Diện tích tối thiểu của 1 polygon metal | Metal quá nhỏ → bị “bay” (floating) trong quá trình CMP (đánh bóng) | Metal1: 0.083 μm² |
| Density Rules | Mật độ metal trên mỗi layer phải trong khoảng min–max | Mật độ không đều → CMP tạo bề mặt không phẳng → lỗi layer trên | Metal fill tự động bởi tool |
TẠI SAO CHẠY DRC BẰNG 2 TOOL?
OpenLane chạy DRC bằng cả Magic và KLayout, sau đó dùng XOR check so sánh kết quả. Mỗi tool có parser GDSII khác nhau — nếu kết quả khác nhau, có thể layout bị hỏng trong quá trình export. Hai tool đồng ý = độ tin cậy cao hơn.
LVS so sánh layout vật lý (GDSII) với netlist logic (gate-level) để đảm bảo chúng tương đương nhau. Nếu không khớp → chip được sản xuất sẽ khác với thiết kế.
| Device mismatch | Số transistor / cell trong layout ≠ netlist |
| Net mismatch | Kết nối wire trong layout ≠ netlist |
| Pin mismatch | Tên/vị trí pin không khớp |
| Short circuit | 2 net khác nhau bị chập trong layout |
| Open circuit | Net bị đứt (không kết nối hết) |
| Missing via | Thiếu via kết nối giữa 2 metal layer |
| Unconnected pin | Pin cell không được route đến |
| Extra device | Fill cell / decap bị tool hiểu nhầm là logic |
| Wrong power | Cell kết nối sai VPWR/VGND rail |
| Parasitic device | Layout tạo ra transistor “ký sinh” ngoài ý muốn |
Trong design này: 0 device / 0 net / 0 pin mismatches — layout hoàn toàn khớp netlist. Tool: Netgen (open-source LVS engine cho Sky130).
Antenna effect là hiện tượng đặc thù trong quy trình sản xuất chip, không liên quan đến “ăng-ten” thu sóng.
| Check | Ý nghĩa | Hậu quả nếu FAIL |
|---|---|---|
| Illegal Overlap | 2 cell đặt chồng lên nhau trong layout | Short circuit, chip không sản xuất được |
| XOR Check Magic vs KLayout |
So sánh GDSII output từ 2 tool — phải giống nhau bit-by-bit | Nếu khác → GDSII có thể bị corrupt, foundry nhận sai dữ liệu |
| Disconnected Pins | Pin cell không kết nối với wire nào | Cell không nhận tín hiệu → logic sai |
Trong OpenLane, hầu hết các vi phạm được tự động fix. Bảng dưới liệt kê các trường hợp cần can thiệp thủ công.
| Vi phạm | Nguyên nhân phổ biến | OpenLane tự fix? | Cách fix thủ công |
|---|---|---|---|
| DRC: Spacing | Routing quá chật, congestion cao | Có — detail routing tự tránh | Tăng DIE_AREA hoặc giảm FP_CORE_UTIL |
| DRC: Density | Metal density không đều | Có — fill cell tự chèn (step 51) | Hiếm khi cần — kiểm tra RUN_FILL_INSERTION |
| LVS: Net mismatch | Routing bị đứt hoặc sai kết nối | Không | Kiểm tra log routing, tăng routing resource (layers) |
| Antenna | Wire dài trên 1 metal layer | Có — chèn diode + reroute (step 41) | GRT_ANTENNA_ITERS tăng lên nếu vẫn fail |
| Overlap | Cell placement bị chồng do macro quá lớn | Không | Tăng DIE_AREA, kiểm tra macro placement |
| Disconnected Pin | Router không tìm được đường đi | Không | Kiểm tra routing congestion, tăng die area |
OpenLane flow là phiên bản đơn giản hóa. Trong industry, signoff phức tạp hơn nhiều.
| Hạng mục | OpenLane (Tutorial này) | Industry (Commercial) |
|---|---|---|
| DRC Tool | Magic + KLayout (open-source) | Calibre (Siemens), IC Validator (Synopsys) |
| LVS Tool | Netgen | Calibre LVS, IC Validator LVS |
| STA Tool | OpenSTA | PrimeTime (Synopsys) — golden standard |
| Power Analysis | OpenROAD (estimate) | PrimePower, Voltus (Cadence) |
| IR Drop | OpenROAD (static) | RedHawk (Ansys), Voltus — dynamic IR drop |
| EM Analysis | Không có | RedHawk, Voltus EM |
| Formal Verification | Không có | Formality (Synopsys), Conformal (Cadence) — chứng minh netlist tương đương RTL |
| CDC/RDC | Không có | Spyglass (Synopsys), Questa CDC (Siemens) |
| Số lượng checks | ~10 checks | 50–200+ checks (tùy foundry & node) |
Lưu ý: Foundry (TSMC, Samsung, Intel) cung cấp signoff runset — bộ rule files chỉ tương thích với tool thương mại. Dù OpenLane pass hết, khi dùng PDK thương mại bạn vẫn cần chạy lại signoff bằng tool foundry-certified.
GTKWave là công cụ xem waveform mã nguồn mở mạnh mẽ nhất. Một số tips giúp debug hiệu quả hơn.
# Lưu session để không phải thêm signals lại # (GTKWave tự lưu khi dùng File → Write Save File) gtkwave counter.vcd session.gtkw # Mở FST (nhanh hơn VCD cho file lớn) gtkwave counter.fst &
Dùng bind để gắn assertions vào DUT mà không sửa RTL code — rất hữu ích khi debug.
// File: counter_assertions.sv // Module chứa assertions — tách riêng khỏi RTL module counter_assertions ( input logic clk, rst_n, en, input logic [7:0] count ); // Overflow check: 0xFF + 1 = 0x00 property p_overflow; @(posedge clk) disable iff (!rst_n) (count == 8'hFF && en) |=> (count == 8'h00); endproperty assert property (p_overflow); // Reset check property p_reset; @(posedge clk) (!rst_n) |=> (count == 8'h00); endproperty assert property (p_reset); endmodule // Trong testbench — bind assertions vào DUT: bind counter counter_assertions chk (.*); // (.*) = tự kết nối tất cả ports cùng tên
Verilator biên dịch Verilog/SystemVerilog thành C++ code, sau đó compile bằng GCC/Clang. Nhanh hơn Icarus Verilog 10-100x, lý tưởng cho regression testing.
# Cài đặt Verilator sudo apt install verilator # Lint check (không cần testbench) verilator --lint-only -Wall counter.sv # Compile cho simulation với trace verilator --cc --exe --build --trace -Wno-fatal counter.sv tb_counter_verilator.cpp # Chạy simulation ./obj_dir/Vcounter # Xem trace gtkwave counter_trace.vcd &
Verilator dùng C++ testbench thay vì SystemVerilog testbench. Đây là testbench đầy đủ cho counter:
// File: tb_counter_verilator.cpp #include "Vcounter.h" #include "verilated.h" #include "verilated_vcd_c.h" int main(int argc, char** argv) { Verilated::commandArgs(argc, argv); Vcounter* dut = new Vcounter; // Trace setup Verilated::traceEverOn(true); VerilatedVcdC* tfp = new VerilatedVcdC; dut->trace(tfp, 99); tfp->open("counter_trace.vcd"); int time = 0; // Reset (10 cycles) dut->rst_n = 0; dut->en = 0; for (int i = 0; i < 20; i++) { dut->clk = !dut->clk; dut->eval(); tfp->dump(time++); } // Count (50 cycles) dut->rst_n = 1; dut->en = 1; for (int i = 0; i < 100; i++) { dut->clk = !dut->clk; dut->eval(); tfp->dump(time++); } printf("Final count = %d\n", dut->count); tfp->close(); delete dut; return 0; }
| Công cụ | Loại | Tốc độ (tương đối) | SV Support | Waveform | License |
|---|---|---|---|---|---|
| Icarus Verilog | Interpreted | 1x (baseline) | Cơ bản | VCD | Open-source |
| Verilator | C++ compiled | 10-100x | Synth subset | VCD/FST | Open-source |
| VCS | Compiled | 50-200x | Full SV/UVM | VPD/FSDB | Commercial |
| Xcelium | Compiled | 50-200x | Full SV/UVM/e | SHM | Commercial |
| QuestaSim | Mixed | 20-80x | Full SV/UVM | WLF | Commercial |
Khi nào dùng công cụ nào?
Icarus: học tập, design nhỏ, gate-level sim. Verilator: regression testing, CI/CD, design trung bình. VCS/Xcelium: production verification, UVM, design lớn (SoC). QuestaSim: FPGA prototyping, debug GUI.
| Parameter | Value |
|---|---|
| Design Name | counter |
| Technology Node | SkyWater Sky130 (130nm) |
| Target Clock Period | 10.0 ns (100 MHz) |
| Achievable Clock Period | 1.53 ns (653 MHz) |
| Supply Voltage | 1.8V |
| Die Area | 100 x 100 um (10,000 um2) |
| Core Area | 88.78 x 76.16 um (6,761 um2) |
| Core Utilization | 9.46% |
| Standard Cell Area | 639.4 um2 |
| IO Pins | 11 (clk, rst_n, en, count[7:0]) |
| Total Nets | 50 |
| Total Wirelength | 898 um |
| Total Vias | 270 |
Verilator kiểm tra chất lượng code trước khi synthesis. Phát hiện lỗi cú pháp, warnings, và các timing construct không synthesizable.
| Step | Tên | Mô tả |
|---|---|---|
| 01 | verilator-lint | Chạy Verilator để lint code SystemVerilog. Phát hiện lỗi cú pháp, biến chưa khai báo, bit-width mismatch, unused signals |
| 02 | checker-linttimingconstructs | Kiểm tra xem RTL có dùng các construct không synthesizable không (ví dụ: #delay, initial trong module chính) |
| 03 | checker-linterrors | Đánh giá kết quả lint — nếu có error thì dừng flow ngay |
| 04 | checker-lintwarnings | Đánh giá warnings từ lint — cảnh báo nhưng không dừng flow |
Yosys chuyển đổi RTL (behavioral) thành gate-level netlist sử dụng các standard cells của Sky130.
| Step | Tên | Mô tả |
|---|---|---|
| 05 | yosys-jsonheader | Yosys đọc RTL, xuất JSON header chứa thông tin module (ports, parameters) để các bước sau dùng |
| 06 | yosys-synthesis | Bước chính: Yosys tổng hợp RTL → gate-level netlist. Gồm: proc (xử lý always block), opt (tối ưu), techmap (map sang Sky130 cells), abc (tối ưu logic combinational) |
| 07 | checker-yosysunmappedcells | Kiểm tra xem còn cell nào chưa được map sang thư viện Sky130 không. Nếu có → lỗi |
| 08 | checker-yosyssynthchecks | Kiểm tra các cảnh báo từ Yosys: latch suy ra ngoài ý muốn, multi-driver, v.v. |
| 09 | checker-netlistassignstatements | Kiểm tra netlist có assign statement bất thường không (dấu hiệu synthesis không hoàn chỉnh) |
Kiểm tra các ràng buộc thiết kế và chạy STA lần đầu làm baseline.
| Step | Tên | Mô tả |
|---|---|---|
| 10 | openroad-checksdcfiles | Kiểm tra file SDC (Synopsys Design Constraints) — định nghĩa clock, input/output delay. Nếu không có, dùng SDC mặc định |
| 11 | openroad-checkmacroinstances | Kiểm tra nếu design có macro (SRAM, IP block) thì chúng có tồn tại trong thư viện không |
| 12 | openroad-staprepnr | Chạy STA (Static Timing Analysis) lần đầu trước khi P&R, dùng làm baseline so sánh |
Xác định kích thước die, core area, chèn tap/endcap cells, và tạo Power Distribution Network.
| Step | Tên | Mô tả |
|---|---|---|
| 13 | openroad-floorplan | Tạo floorplan: xác định die area (100×100µm), core area, row sites cho standard cells |
| 14 | odb-checkmacroantennaproperties | Kiểm tra thuộc tính antenna của macro cells (nếu có) |
| 15 | odb-setpowerconnections | Gán kết nối nguồn VPWR/VGND cho tất cả cells trong netlist |
| 16 | odb-manualmacroplacement | Đặt macro (SRAM, IP) theo vị trí người dùng chỉ định. Design này không có macro |
| 17 | openroad-cutrows | Cắt bỏ các hàng standard cell bị macro che khuất |
| 18 | openroad-tapendcapinsertion | Chèn 90 tap cells (giữ well potential) và endcap cells ở đầu/cuối mỗi hàng |
| 19 | odb-addpdnobstructions | Thêm vùng cấm (obstruction) để PDN không bị xung đột với macro/pin |
| 20 | openroad-generatepdn | Tạo Power Distribution Network: vẽ đường VPWR/VGND ngang (metal 1) và straps dọc (metal 4/5) cấp nguồn cho toàn bộ chip |
| 21 | odb-removepdnobstructions | Gỡ bỏ obstruction tạm sau khi PDN đã xong |
| 22 | odb-addroutingobstructions | Thêm obstruction cho routing — tránh signal routing đi qua vùng PDN/macro |
Global placement tìm vị trí tối ưu cho 138 cells, sau đó detailed placement snap vào lưới.
| Step | Tên | Mô tả |
|---|---|---|
| 23 | openroad-globalplacementskipio | Global placement lần 1 — đặt thô tất cả cells (bỏ qua IO pins) để ước lượng vị trí |
| 24 | openroad-ioplacement | Đặt IO pins (clk, rst_n, en, count[7:0]) lên cạnh die theo thứ tự tối ưu wirelength |
| 25 | odb-customioplacement | Áp dụng vị trí IO tùy chỉnh nếu người dùng chỉ định |
| 26 | odb-applydeftemplate | Áp dụng DEF template — dùng khi muốn giữ floorplan từ run trước |
| 27 | openroad-globalplacement | Global placement chính: thuật toán đặt 138 cells sao cho tổng wirelength ngắn nhất, mật độ đều, timing tốt |
| 28 | odb-writeverilogheader | Xuất Verilog header sau placement |
| 29 | checker-powergridviolations | Kiểm tra xem cells nào không kết nối được với PDN (VPWR/VGND) |
| 30 | openroad-stamidpnr | STA giữa chừng — kiểm tra timing sau global placement |
| 31 | openroad-repairdesignpostgpl | Repair design: thêm buffer để sửa max slew, max cap, max fanout violations. Thêm 17 timing repair buffers |
| 32 | odb-manualglobalplacement | Điều chỉnh vị trí thủ công (nếu người dùng chỉ định) |
| 33 | openroad-detailedplacement | Detailed placement: dịch chuyển cells vào vị trí hợp lệ trên row sites, loại bỏ overlap |
Xây dựng cây clock từ pin clk đến 8 flip-flops. Chèn clock buffers để cân bằng skew.
| Step | Tên | Mô tả |
|---|---|---|
| 34 | openroad-cts | Clock Tree Synthesis: xây dựng cây clock 2 tầng với 4 clock buffers (clkbuf_16). Skew: 3.14ps, latency: 0.294ns |
| 35 | openroad-stamidpnr-1 | STA sau CTS — kiểm tra timing với clock tree thực tế (propagated clock) |
| 36 | openroad-resizertimingpostcts | Timing repair sau CTS: thêm 7 hold buffers để sửa hold violations gây ra bởi clock skew |
| 37 | openroad-stamidpnr-2 | STA lần nữa — xác nhận hold đã được sửa |
Global routing tìm đường đi tổng quát, detailed routing gán vào track cụ thể. Tổng: 898µm wirelength, 270 vias.
| Step | Tên | Mô tả |
|---|---|---|
| 38 | openroad-globalrouting | Global routing: tìm đường đi tổng quát cho mỗi net qua các ô lưới (GCells). Chưa xác định track cụ thể |
| 39 | openroad-checkantennas | Kiểm tra antenna violations — dây metal quá dài có thể tích điện và phá gate oxide khi fab |
| 40 | odb-diodesonports | Chèn antenna diodes ở các port nếu cần bảo vệ |
| 41 | openroad-repairantennas | Sửa antenna violations bằng cách chèn diodes hoặc route lại qua metal layer cao hơn |
| 42 | openroad-stamidpnr-3 | STA sau global routing — timing với ước lượng RC từ routing |
| 43 | openroad-detailedrouting | Detailed routing: gán dây vào track cụ thể, xử lý via, tuân thủ DRC. Chạy 2 iterations (14 DRC → 0) |
| 44 | odb-removeroutingobstructions | Gỡ routing obstructions tạm |
| 45 | openroad-checkantennas-1 | Kiểm tra antenna lần cuối sau detailed routing |
| 46 | checker-trdrc | Kiểm tra DRC từ TritonRoute. 0 errors |
| 47 | odb-reportdisconnectedpins | Báo cáo pins bị đứt kết nối sau routing |
| 48 | checker-disconnectedpins | Đánh giá — nếu có critical pin bị đứt → lỗi |
| 49 | odb-reportwirelength | Báo cáo wirelength mỗi net. Net dài nhất: 85.78µm |
| 50 | checker-wirelength | Kiểm tra net nào vượt ngưỡng wirelength cho phép |
Chèn fill cells, trích xuất parasitic, STA cuối cùng và phân tích IR drop.
| Step | Tên | Mô tả |
|---|---|---|
| 51 | openroad-fillinsertion | Chèn 607 fill cells vào khoảng trống. Đảm bảo metal density đồng đều cho fabrication |
| 52 | odb-cellfrequencytables | Thống kê tần suất sử dụng từng loại cell |
| 53 | openroad-rcx | Parasitic Extraction (RCX): tính resistance + capacitance thực tế của mỗi dây routing. Xuất file SPEF |
| 54 | openroad-stapostpnr | STA cuối cùng: phân tích timing với parasitic thực tế, trên 9 PVT corners. Đây là kết quả timing chính thức |
| 55 | openroad-irdropreport | IR Drop analysis: tính sụt áp trên power grid. Worst drop: 0.259mV (rất nhỏ so với 1.8V) |
Xuất file GDSII để gửi nhà sản xuất (foundry). Magic và KLayout xuất độc lập để cross-verify.
| Step | Tên | Mô tả |
|---|---|---|
| 56 | magic-streamout | Magic xuất GDSII — file nhị phân chứa toàn bộ geometry của chip, gửi cho fab |
| 57 | klayout-streamout | KLayout xuất GDSII độc lập — để so sánh XOR với Magic |
| 58 | magic-writelef | Magic xuất LEF — dùng khi chip này là macro trong design lớn hơn |
Kiểm tra toàn diện: DRC, LVS, antenna, timing, overlap. Tất cả phải PASS trước khi gửi fab.
| Step | Tên | Mô tả | Kết quả |
|---|---|---|---|
| 59 | odb-checkdesignantennaproperties | Kiểm tra lại thuộc tính antenna sau routing cuối | OK |
| 60 | klayout-xor | XOR check: so sánh pixel-by-pixel giữa GDSII từ Magic và KLayout. Phải khớp 100% | 0 diff |
| 61 | checker-xor | Đánh giá kết quả XOR | PASS |
| 62 | magic-drc | DRC bằng Magic: kiểm tra toàn bộ design rule của Sky130 (spacing, width, enclosure, overlap...) | 0 err |
| 63 | klayout-drc | DRC bằng KLayout: chạy DRC độc lập, cross-verify với Magic | 0 err |
| 64 | checker-magicdrc | Đánh giá Magic DRC | PASS |
| 65 | checker-klayoutdrc | Đánh giá KLayout DRC | PASS |
| 66 | magic-spiceextraction | Magic trích xuất SPICE netlist từ layout để so sánh với schematic netlist | Done |
| 67 | checker-illegaloverlap | Kiểm tra overlap bất hợp pháp giữa cells | 0 |
| 68 | netgen-lvs | LVS: Netgen so sánh SPICE netlist (layout) với Verilog netlist (synthesis). Phải khớp 100% | PASS |
| 69 | checker-lvs | Đánh giá LVS — 0 device/net/pin mismatch | PASS |
| 70 | checker-setupviolations | Kiểm tra setup timing violations trên tất cả 9 corners | 0 vio |
| 71 | checker-holdviolations | Kiểm tra hold timing violations trên tất cả 9 corners | 0 vio |
| 72 | checker-maxslewviolations | Kiểm tra max slew (transition time) violations | 0 |
| 73 | checker-maxcapviolations | Kiểm tra max capacitance violations | 0 |
| 74 | misc-reportmanufacturability | Báo cáo tổng hợp: DRC PASS, LVS PASS, Antenna PASS → sẵn sàng gửi fab | READY |
Trong 78 bước của OpenLane, người thiết kế có thể can thiệp ở nhiều mức độ khác nhau. Dưới đây là hướng dẫn cụ thể sửa gì, ở đâu, bằng cách nào.
Mức độ: TOÀN QUYỀN — Đây là nơi người thiết kế quyết định chức năng chip. Chiếm 60–70% thời gian.
File cần sửa:
counter.sv — module chínhtb_counter.sv — testbench
| Mục tiêu | Cách làm cụ thể |
|---|---|
| Thay đổi chức năng | Sửa logic trong always_ff / always_comb. Ví dụ: đổi từ counter lên thành counter lên/xuống:if (up_down) count <= count + 1; else count <= count - 1; |
| Thêm port mới | Thêm input/output trong module declaration. Ví dụ thêm tín hiệu overflow:output logic overflow ... assign overflow = (count == 8'hFF); |
| Tăng bit-width | Sửa [7:0] thành [15:0] cho 16-bit counter. Cần sửa cả testbench và config |
| Tối ưu tốc độ | Pipeline các phép tính: chia logic tổ hợp phức tạp thành nhiều tầng flip-flop. Giảm critical path delay |
| Tối ưu diện tích | Dùng resource sharing: nhiều phép tính dùng chung 1 adder/multiplier qua MUX |
| Sửa lỗi lint | Xem log 01-verilator-lint/verilator-lint.log. Sửa warnings về: unused signals, implicit wire, width mismatch |
Mức độ: QUAN TRỌNG NHẤT — SDC quyết định mục tiêu timing của toàn bộ design.
File cần tạo/sửa:
counter.sdc — file ràng buộc timingThêm vào config.json: "PNR_SDC_FILE": "dir::counter.sdc"
| Mục tiêu | Cách làm cụ thể |
|---|---|
| Định nghĩa clock | create_clock -name clk -period 10.0 [get_ports clk] # Period 10ns = 100MHz. Giảm xuống 5.0 để target 200MHz |
| Input/output delay | set_input_delay 2.0 -clock clk [get_ports {rst_n en}] set_output_delay 2.0 -clock clk [get_ports {count[*]}] # Delay từ/đến thế giới bên ngoài. Ảnh hưởng setup/hold slack |
| False path | set_false_path -from [get_ports rst_n]
# Loại bỏ reset khỏi timing analysis — không cần meet timing |
| Multicycle path | set_multicycle_path 2 -setup -from [get_pins slow_reg/Q] # Cho phép path này 2 chu kỳ clock thay vì 1 |
| Clock uncertainty | set_clock_uncertainty 0.25 [get_clocks clk] # Margin cho jitter + skew. Tăng lên để an toàn hơn |
| Max transition/capacitance | set_max_transition 0.5 [current_design] set_max_capacitance 0.2 [current_design] # Giới hạn slew và cap để đảm bảo signal integrity |
Mức độ: CONFIG — Tuning qua tham số trong config.json hoặc viết Yosys script riêng.
File cần sửa:
config.json — thêm các tham số synthesiscustom_synth.tcl (nâng cao) — Yosys TCL script tùy chỉnh
| Tham số | Giá trị & ý nghĩa |
|---|---|
SYNTH_STRATEGY |
"AREA 0" → tối ưu diện tích (nhỏ nhất)"DELAY 0" → tối ưu tốc độ (nhanh nhất)"DELAY 3" → tối ưu tốc độ mạnh hơn (tốn area)// Trong config.json:
"SYNTH_STRATEGY": "DELAY 0" |
SYNTH_MAX_FANOUT |
Giới hạn fanout trước khi Yosys chèn buffer. Mặc định: 10"SYNTH_MAX_FANOUT": 6
// Giảm xuống để tăng tốc độ (nhiều buffer hơn) |
SYNTH_BUFFERING |
1 (bật) / 0 (tắt) buffering trong ABC. Bật để giảm delay |
SYNTH_SIZING |
1 = cho phép ABC resize cells (dùng cell lớn hơn để giảm delay) |
| Custom Yosys script | Viết file TCL riêng để kiểm soát từng bước synthesis:"SYNTH_SCRIPT": "dir::custom_synth.tcl"
# Trong custom_synth.tcl:
read_verilog -sv counter.sv
hierarchy -top counter
proc; opt; fsm; opt
techmap; opt
abc -D 10000 -liberty sky130.lib
opt_clean |
Mức độ: CONFIG + SCRIPT — Định nghĩa kích thước, vị trí macro, và power grid.
File cần sửa:
config.json — die size, utilizationmacro_placement.cfg (nếu có macro) — vị trí macropin_order.cfg (tùy chọn) — thứ tự pin trên cạnh die
| Tham số | Giá trị & ý nghĩa |
|---|---|
DIE_AREA |
Kích thước die cố định:"DIE_AREA": "0 0 200 200"
// x0 y0 x1 y1 (µm). Tăng lên nếu routing congestion |
FP_SIZING |
"absolute" = dùng DIE_AREA cố định"relative" = tự tính từ FP_CORE_UTIL |
FP_CORE_UTIL |
% diện tích core dành cho cells. Khoảng tốt: 40–60%"FP_CORE_UTIL": 50
// Cao quá → routing khó. Thấp quá → chip lớn |
FP_PIN_ORDER_CFG |
Chỉ định vị trí pin trên 4 cạnh die:# pin_order.cfg: #N ← cạnh trên count\[0\] count\[1\] count\[2\] count\[3\] #S ← cạnh dưới clk rst_n en #E ← cạnh phải count\[4\] count\[5\] count\[6\] count\[7\] "FP_PIN_ORDER_CFG": "dir::pin_order.cfg" |
FP_PDN_* |
Cấu hình Power Distribution Network:"FP_PDN_HPITCH": 153.6, // khoảng cách ngang giữa straps "FP_PDN_VPITCH": 153.18, // khoảng cách dọc "FP_PDN_HWIDTH": 1.6, // độ rộng strap ngang "FP_PDN_VWIDTH": 1.6, // độ rộng strap dọc "FP_PDN_HSPACING": 1.7, // spacing giữa strap cùng layer // Tăng density straps nếu IR drop cao |
| Macro placement | Nếu design có SRAM/IP, chỉ định vị trí:# macro_placement.cfg: sram_inst 50 50 N // tên x y hướng "MACRO_PLACEMENT_CFG": "dir::macro_placement.cfg" |
Mức độ: CONFIG — Tuning mật độ, repair strategy.
| Tham số | Giá trị & ý nghĩa |
|---|---|
PL_TARGET_DENSITY_PCT |
Mật độ mục tiêu khi placement:"PL_TARGET_DENSITY_PCT": 60
// Cao → cells xích lại gần nhau, wirelength ngắn nhưng congestion tăng
// Thấp → cells trải đều, dễ routing nhưng wirelength dài |
PL_ROUTABILITY_DRIVEN |
1 = placement có tính đến routability. Bật khi gặp congestion |
PL_TIME_DRIVEN |
1 = placement ưu tiên timing. Bật khi setup slack âm |
PL_RESIZER_HOLD_SLACK_MARGIN |
Margin cho hold repair:"PL_RESIZER_HOLD_SLACK_MARGIN": 0.1
// Tăng lên 0.2–0.3 nếu hold slack quá sát 0 |
PL_RESIZER_MAX_WIRE_LENGTH |
Chiều dài wire tối đa trước khi chèn buffer:"PL_RESIZER_MAX_WIRE_LENGTH": 500
// Giảm xuống nếu có long wire violations |
Mức độ: CONFIG — Chọn buffer, giới hạn skew.
| Tham số | Giá trị & ý nghĩa |
|---|---|
CTS_CLK_BUFFER_LIST |
Danh sách buffer cho clock tree:"CTS_CLK_BUFFER_LIST": "sky130_fd_sc_hd__clkbuf_4 sky130_fd_sc_hd__clkbuf_8 sky130_fd_sc_hd__clkbuf_16"
// Chỉ dùng buffer lớn để giảm skew |
CTS_MAX_CAP |
Max capacitance tại mỗi nút clock tree. Giảm để thêm buffer, tăng để giảm cell count |
CTS_TOLERANCE |
Dung sai cân bằng skew (%). Mặc định: 100. Giảm để skew đều hơn |
| Hold repair sau CTS | "CTS_HOLD_SLACK_MARGIN": 0.15
// Margin cho hold buffer insertion sau CTS
// Tăng nếu vẫn có hold violations ở signoff |
Mức độ: CONFIG — Điều chỉnh routing strategy và khắc phục congestion.
| Tham số | Giá trị & ý nghĩa |
|---|---|
GRT_ADJUSTMENT |
Hệ số điều chỉnh global routing congestion:"GRT_ADJUSTMENT": 0.3
// 0.0 = dùng hết capacity
// 0.5 = dự trữ 50% capacity. Tăng khi gặp DRC routing |
GRT_OVERFLOW_ITERS |
Số iterations tối đa cho global routing. Tăng nếu routing chưa hội tụ:"GRT_OVERFLOW_ITERS": 80 // mặc định 50 |
DRT_OPT_ITERS |
Số lần lặp tối ưu detailed routing. Tăng để giảm DRC errors:"DRT_OPT_ITERS": 128 // mặc định 64 |
RT_MIN_LAYER / RT_MAX_LAYER |
Giới hạn metal layer cho signal routing:"RT_MIN_LAYER": "met1"
"RT_MAX_LAYER": "met4"
// Giữ met5 riêng cho power straps |
| Antenna repair | Nếu antenna violations xuất hiện:"DIODE_ON_PORTS": "in"
"GRT_ANTENNA_ITERS": 10
// Tự động chèn diode và reroute |
Mức độ: REVIEW + FIX — Đọc report, xác định vấn đề, quay lại sửa ở bước trước.
| Vấn đề | Cách xử lý |
|---|---|
| Setup violation |
1. Giảm CLOCK_PERIOD (target chậm hơn)2. Đổi SYNTH_STRATEGY sang "DELAY 0"3. Pipeline RTL (thêm flip-flop giữa các tầng logic) 4. Tăng DIE_AREA (giảm congestion, wire ngắn hơn)// Xem critical path:
cat runs/*/54-openroad-stapostpnr/nom_tt_025C_1v80/ws.max.rpt
|
| Hold violation |
1. Tăng PL_RESIZER_HOLD_SLACK_MARGIN lên 0.2–0.42. Tăng CTS_HOLD_SLACK_MARGIN3. OpenLane tự chèn hold buffer — nếu vẫn fail, tăng margin |
| DRC errors |
1. Tăng DIE_AREA hoặc giảm FP_CORE_UTIL2. Tăng DRT_OPT_ITERS lên 1283. Tăng GRT_ADJUSTMENT lên 0.4–0.5// Xem chi tiết DRC:
cat runs/*/62-magic-drc/*.rpt
|
| LVS mismatch |
Thường do lỗi trong PDN hoặc connectivity: 1. Kiểm tra power connections 2. Xem log: runs/*/68-netgen-lvs/*.rpt3. Nếu device mismatch: kiểm tra lại LEF/GDS của macro |
| IR drop cao |
1. Tăng số lượng power straps (giảm FP_PDN_HPITCH/FP_PDN_VPITCH)2. Tăng độ rộng straps ( FP_PDN_HWIDTH/FP_PDN_VWIDTH)3. Thêm VSRC_LOC_FILES để chỉ định vị trí nguồn cấp
|
| Antenna violations |
1. Bật "DIODE_ON_PORTS": "in"2. Tăng GRT_ANTENNA_ITERS3. Nếu vẫn fail: thêm diode cell thủ công trong RTL |
Trong OpenLane, OpenROAD chạy ngầm. Tuy nhiên, bạn có thể mở OpenROAD trực tiếp để khám phá, debug, hoặc can thiệp thủ công vào design. OpenROAD sử dụng Tcl shell (giống Synopsys ICC2, Cadence Innovus).
# Cách 1: Mở OpenROAD CLI trong Docker container của OpenLane docker run -it -v $(pwd):/work -w /work \ efabless/openlane:2.3.10 openroad # Cách 2: Mở với GUI (cần X11 forwarding) docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix \ -v $(pwd):/work -w /work \ efabless/openlane:2.3.10 openroad -gui # Cách 3: Nếu đã cài OpenROAD standalone openroad # CLI mode openroad -gui # GUI mode
| Nhóm | Lệnh Tcl | Mô tả |
|---|---|---|
| Đọc design vào OpenROAD | ||
| Library | read_liberty sky130.lib | Đọc thư viện timing (.lib) của standard cells |
| LEF | read_lef sky130_fd_sc_hd.tlefread_lef sky130_fd_sc_hd.lef | Đọc tech LEF (layer rules) và cell LEF (geometry) |
| Netlist | read_verilog counter.nl.vlink_design counter | Đọc gate-level netlist từ synthesis và link top module |
| SDC | read_sdc counter.sdc | Đọc timing constraints (clock, I/O delay) |
| DEF | read_def counter.def | Đọc file DEF (đã có placement/routing) để tiếp tục xử lý |
| Floorplan & Placement | ||
| Floorplan | initialize_floorplan -die_area "0 0 200 200" \ | Tạo floorplan với kích thước die và core area |
| IO Pins | place_pins -hor_layers met3 -ver_layers met2 | Tự động đặt IO pins trên các cạnh die |
| PDN | pdngen pdn.cfg | Tạo lưới nguồn VDD/VSS từ file config |
| Placement | global_placement -density 0.6detailed_placement | Đặt cells: global (thô) → detailed (chính xác trên row sites) |
| Resize | repair_designrepair_timing -hold | Chèn buffer sửa slew/cap violations và hold violations |
| CTS & Routing | ||
| CTS | clock_tree_synthesis -buf_list "clkbuf_4 clkbuf_8 clkbuf_16" | Xây dựng cây clock với các buffer chỉ định |
| Routing | global_route -adjustment 0.3detailed_route -bottom_routing_layer met1 \ | Global route (tìm đường đi) → Detailed route (gán track cụ thể) |
| Phân tích & Xuất | ||
| STA | report_checks -path_delay maxreport_checks -path_delay min | Xem setup path tệ nhất (max) và hold path tệ nhất (min) |
| Timing | report_tns / report_wnsreport_clock_skew | Tổng slack âm, slack âm tệ nhất, skew cây clock |
| Power | report_power | Ước lượng công suất tĩnh + động |
| Design | report_design_areareport_cell_usage | Diện tích và số lượng từng loại cell |
| Xuất | write_def counter_final.defwrite_verilog counter_final.nl.v | Xuất DEF (layout) và netlist sau khi sửa |
# Mở OpenROAD và load kết quả OpenLane để khám phá openroad # Đọc thư viện read_liberty $PDK_ROOT/sky130A/libs.ref/sky130_fd_sc_hd/lib/sky130_fd_sc_hd__tt_025C_1v80.lib read_lef $PDK_ROOT/sky130A/libs.ref/sky130_fd_sc_hd/techlef/sky130_fd_sc_hd__nom.tlef read_lef $PDK_ROOT/sky130A/libs.ref/sky130_fd_sc_hd/lef/sky130_fd_sc_hd.lef # Đọc design đã hoàn thành từ OpenLane read_def runs/RUN_*/results/final/def/counter.def read_sdc runs/RUN_*/results/final/sdc/counter.sdc # Kiểm tra timing report_checks -path_delay max -format full_clock_expanded report_checks -path_delay min -format full_clock_expanded report_tns report_wns report_clock_skew # Kiểm tra design report_design_area report_power report_cell_usage
Khi OpenLane chạy tự động không đạt yêu cầu, bạn có thể dừng giữa chừng và can thiệp bằng OpenROAD trực tiếp. Đây là kỹ năng quan trọng của kỹ sư backend.
| Tình huống | Cách can thiệp | Lệnh OpenROAD |
|---|---|---|
| Setup violation trên 1 path cụ thể | Tìm path → resize cell trên critical path → chạy lại STA | # Xem path tệ nhất report_checks -through [get_nets net_name] -fields {slew cap} # Resize cell lớn hơn (drive mạnh hơn) resize -cell_name sky130_fd_sc_hd__buf_8 # Kiểm tra lại report_checks -path_delay max |
| Hold violation sau CTS | Chèn hold buffer thủ công vào path bị violation | # Xem hold paths report_checks -path_delay min # Repair hold tự động repair_timing -hold -slack_margin 0.2 # Legalize lại placement detailed_placement |
| Congestion tại 1 vùng | Dùng GUI xem heatmap → điều chỉnh density tại vùng đó | # Trong GUI: View → Heatmap → Routing # Tạo placement blockage tại vùng congested set_placement_padding -masters sky130_fd_sc_hd__mux2_1 \ -left 2 -right 2 # Chạy lại placement global_placement -density 0.5 detailed_placement |
| Di chuyển cell trong GUI | GUI mode: click chọn cell → kéo đến vị trí mới | # Mở GUI openroad -gui # Trong GUI: # 1. Edit → Find → tìm cell instance # 2. Click chọn cell, chuột phải → Move # 3. Đặt vào vị trí mới # 4. detailed_placement (legalize) # Hoặc bằng Tcl: set inst [get_cells _123_] set_property $inst ORIGIN {50.0 25.0} |
| Thay cell thủ công | Swap 1 cell sang loại khác (VT cao hơn, drive mạnh hơn) | # Xem cell hiện tại report_cell_usage # Swap cell cụ thể sang drive mạnh hơn swap_cell _098_ sky130_fd_sc_hd__buf_8 # Swap tất cả buf_1 → buf_2 (cẩn thận!) foreach inst [get_cells -filter "ref_name == sky130_fd_sc_hd__buf_1"] { swap_cell $inst sky130_fd_sc_hd__buf_2 } |
| Xuất kết quả sau khi sửa | Lưu DEF + netlist mới rồi tiếp tục flow OpenLane | # Lưu kết quả đã chỉnh sửa write_def counter_fixed.def write_verilog counter_fixed.nl.v # Trong config.json OpenLane, dùng DEF này: # "FP_DEF_TEMPLATE": "dir::counter_fixed.def" |
Sau mỗi lần chạy OpenLane, kết quả nằm trong runs/RUN_*/. Biết đọc đúng file sẽ giúp bạn nhanh chóng xác định vấn đề và biết cần sửa ở đâu.
# Xem setup timing (critical path)
cat runs/*/54-openroad-stapostpnr/nom_tt_025C_1v80/ws.max.rpt
Kết quả mẫu:
Startpoint: _109_ (rising edge-triggered flip-flop clocked by clk) Endpoint: _115_ (rising edge-triggered flip-flop clocked by clk) Path Group: clk Path Type: max ← "max" = setup check Delay Time Description --------------------------------------------------------- 0.00 0.00 clock clk (rise edge) 0.29 0.29 clock network delay (propagated) 0.29 ^ _109_/CLK (sky130_fd_sc_hd__dfxtp_1) 0.32 0.61 v _109_/Q ← Flip-flop output (clock-to-Q) 0.16 0.77 v _085_/Y ← Combinational logic cell 0.21 0.98 ^ _090_/Y ← Tiếp tục qua logic gates 0.10 1.08 v _096_/Y 0.00 1.08 v _115_/D ← Data arrives at next FF 1.08 data arrival time ← ① Thời điểm data đến 10.00 10.00 clock clk (rise edge) 0.29 10.29 clock network delay (propagated) -0.25 10.04 clock uncertainty -0.04 10.00 library setup time ← Setup requirement 10.00 data required time ← ② Thời điểm data phải đến --------------------------------------------------------- 10.00 data required time -1.08 data arrival time --------------------------------------------------------- 8.92 slack (MET) ← ② - ① = 8.92ns > 0 → OK!
| Đọc gì | Ý nghĩa | Hành động nếu lỗi |
|---|---|---|
slack (MET) |
Dương = OK. Càng lớn càng tốt. Giá trị 8.92ns nghĩa là còn dư rất nhiều | — |
slack (VIOLATED) |
Âm = LỖI TIMING. Ví dụ -0.5ns nghĩa là data đến chậm 0.5ns | Giảm clock freq, tối ưu RTL, resize cells |
Path Type: max |
Setup check — data phải đến trước cạnh clock tiếp theo | Giảm delay: dùng cell nhanh hơn, pipeline |
Path Type: min |
Hold check — data phải giữ ổn định sau cạnh clock | Tăng delay: chèn hold buffer |
clock network delay |
Trễ của cây clock từ source đến flip-flop. Cho biết CTS hoạt động thế nào | Nếu quá lớn: giảm số tầng buffer hoặc dùng buffer mạnh hơn |
# ★ Tóm tắt nhanh: pass hay fail? cat runs/*/metrics.csv | head -1 # Header cat runs/*/metrics.csv | tail -1 # Giá trị # Setup timing (tất cả corners) grep -r "slack" runs/*/54-openroad-stapostpnr/*/ws.max.rpt # Hold timing grep -r "slack" runs/*/54-openroad-stapostpnr/*/ws.min.rpt # DRC: bao nhiêu lỗi? grep -c "violation" runs/*/62-magic-drc/*.rpt # LVS: match hay không? tail -5 runs/*/68-netgen-lvs/*.rpt # IR Drop cat runs/*/55-openroad-irdropreport/*.rpt # Cell count & area sau synthesis grep "Number of cells\|Chip area" runs/*/05-yosys-synthesis/*.stat.rpt # Routing DRC errors (mục tiêu: 0) grep "Number of violations" runs/*/43-openroad-detailedrouting/*.log | tail -1
| Muốn biết | Xem file | Giá trị tốt |
|---|---|---|
| Timing pass chưa? | 54-*/ws.max.rpt & ws.min.rpt | Tất cả slack ≥ 0 |
| DRC clean chưa? | 62-magic-drc/*.rpt | 0 violations |
| LVS match chưa? | 68-netgen-lvs/*.rpt | "Circuits match uniquely" |
| Diện tích bao nhiêu? | metrics.csv (cột design__die__area) | Càng nhỏ càng tốt |
| Power bao nhiêu? | metrics.csv (cột total_power) | Tùy yêu cầu |
| IR drop có ổn? | 55-*/irdrop.rpt | < 5% VDD (tức < 90mV cho 1.8V) |
| Routing congestion? | 43-*/*.log (cuối file) | 0 DRC violations |
| Antenna violations? | 39-*/checkantennas.log | 0 violations |
Thiết kế chip là quá trình lặp. Thường cần 10–30 lần chạy để đạt PPA (Power, Performance, Area) mong muốn.
| Lần chạy | Thường làm gì |
|---|---|
| Lần 1–3 | Điều chỉnh DIE_AREA, FP_CORE_UTIL, CLOCK_PERIOD để flow chạy qua được |
| Lần 4–10 | Tối ưu timing: sửa SDC, tuning SYNTH_STRATEGY, PL_TARGET_DENSITY |
| Lần 10–20 | Sửa DRC/LVS/antenna. Tuning routing, PDN, hold margin |
| Lần 20+ | Tối ưu PPA: giảm area, giảm power, push frequency lên cao hơn |
| Tool | Version | Purpose |
|---|---|---|
| OpenLane | v2.3.10 | RTL-to-GDSII flow orchestration |
| Yosys | 0.33 | Logic synthesis |
| OpenROAD | (bundled) | Floorplan, placement, CTS, routing, STA |
| Magic | (bundled) | DRC, SPICE extraction, GDSII export |
| KLayout | 0.29.12 | DRC, GDSII export, XOR check |
| Netgen | (bundled) | LVS verification |
| Verilator | 5.020 | Lint checking, fast simulation, coverage |
| Icarus Verilog | 12.0 | RTL, gate-level, and timing simulation |
| GTKWave | 3.3.120 | Waveform viewer (VCD, FST) |
| Sky130 PDK | 0fe599b | 130nm process design kit |
FIFO (First-In First-Out) là module cơ bản trong mọi SoC — dùng để đệm dữ liệu giữa các module có tốc độ xử lý khác nhau. Đây là bài tập tốt để thực hành sau counter.
module sync_fifo #( parameter DEPTH = 8, parameter WIDTH = 8 )( input logic clk, rst_n, input logic wr_en, rd_en, input logic [WIDTH-1:0] wr_data, output logic [WIDTH-1:0] rd_data, output logic full, empty ); logic [WIDTH-1:0] mem [DEPTH]; logic [$clog2(DEPTH):0] wr_ptr, rd_ptr; // Extra bit for full/empty assign full = (wr_ptr[$clog2(DEPTH)] != rd_ptr[$clog2(DEPTH)]) && (wr_ptr[$clog2(DEPTH)-1:0] == rd_ptr[$clog2(DEPTH)-1:0]); assign empty = (wr_ptr == rd_ptr); assign rd_data = mem[rd_ptr[$clog2(DEPTH)-1:0]]; always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) begin wr_ptr <= 0; rd_ptr <= 0; end else begin if (wr_en && !full) begin mem[wr_ptr[$clog2(DEPTH)-1:0]] <= wr_data; wr_ptr <= wr_ptr + 1; end if (rd_en && !empty) rd_ptr <= rd_ptr + 1; end end endmodule
Bài tập
1. Viết testbench self-checking cho FIFO. 2. Chạy qua OpenLane để tạo GDSII. 3. Mở rộng thành Async FIFO với 2 clock domains (dùng Gray code pointers + 2-FF sync).
UART TX là module giao tiếp nối tiếp cơ bản nhất — chuyển byte thành dạng serial (start + 8 data + stop bits) ở baudrate định sẵn.
module uart_tx #( parameter CLK_FREQ = 100_000_000, // 100MHz parameter BAUD_RATE = 115_200 )( input logic clk, rst_n, input logic tx_start, input logic [7:0] tx_data, output logic tx_out, output logic tx_busy ); localparam CLKS_PER_BIT = CLK_FREQ / BAUD_RATE; typedef enum logic [1:0] {IDLE, START, DATA, STOP} state_t; state_t state; logic [15:0] clk_cnt; logic [2:0] bit_idx; logic [7:0] shift_reg; assign tx_busy = (state != IDLE); always_ff @(posedge clk or negedge rst_n) begin if (!rst_n) begin state <= IDLE; tx_out <= 1'b1; end else begin case (state) IDLE: if (tx_start) begin shift_reg <= tx_data; state <= START; clk_cnt <= 0; end START: begin tx_out <= 1'b0; // Start bit if (clk_cnt == CLKS_PER_BIT - 1) begin state <= DATA; clk_cnt <= 0; bit_idx <= 0; end else clk_cnt <= clk_cnt + 1; end DATA: begin tx_out <= shift_reg[bit_idx]; if (clk_cnt == CLKS_PER_BIT - 1) begin clk_cnt <= 0; if (bit_idx == 7) state <= STOP; else bit_idx <= bit_idx + 1; end else clk_cnt <= clk_cnt + 1; end STOP: begin tx_out <= 1'b1; // Stop bit if (clk_cnt == CLKS_PER_BIT - 1) state <= IDLE; else clk_cnt <= clk_cnt + 1; end endcase end end endmodule
Bài tập
1. Viết UART RX (nhận serial → byte). 2. Kết hợp TX+RX thành module UART hoàn chỉnh. 3. Thêm FIFO đệm cho TX và RX. 4. Chạy qua OpenLane và so sánh kết quả với counter (area, power, timing).
SPI (Serial Peripheral Interface) là giao thức 4 dây phổ biến để giao tiếp với Flash, ADC, DAC, sensor. Phức tạp hơn UART vì có nhiều chế độ (CPOL/CPHA).
| Tín hiệu | Hướng | Chức năng |
|---|---|---|
| SCLK | Master → Slave | Clock do master tạo |
| MOSI | Master → Slave | Data từ master gửi đi |
| MISO | Slave → Master | Data từ slave gửi về |
| CS_N | Master → Slave | Chip Select (active low) |
// SPI Master skeleton — CPOL=0, CPHA=0 (Mode 0) module spi_master ( input logic clk, rst_n, input logic start, input logic [7:0] tx_data, output logic [7:0] rx_data, output logic busy, // SPI signals output logic sclk, mosi, cs_n, input logic miso ); // Bài tập: implement FSM // States: IDLE → CS_LOW → TRANSFER (8 bits) → CS_HIGH → IDLE // - SCLK: toggle tạo clock cho slave // - MOSI: gửi tx_data[7:0] MSB first // - MISO: sample rx_data tại rising edge của SCLK endmodule
Lộ trình học tập đề xuất
Bước 1: Counter 8-bit (tài liệu này) → Bước 2: FIFO → Bước 3: UART TX/RX → Bước 4: SPI Master → Bước 5: Simple CPU (ALU + register file + FSM controller). Mỗi bước đều có thể chạy qua OpenLane để tạo GDSII.
Bảng tra cứu nhanh các thuật ngữ chuyên ngành sử dụng trong tài liệu này. Sắp xếp theo nhóm chủ đề.
| Tiếng Anh | Tiếng Việt | Giải thích ngắn |
|---|---|---|
| RTL (Register Transfer Level) | Mức truyền thanh ghi | Mức mô tả phần cứng bằng các phép gán thanh ghi theo xung clock |
| HDL (Hardware Description Language) | Ngôn ngữ mô tả phần cứng | Ngôn ngữ dùng để mô tả mạch số: Verilog, VHDL, SystemVerilog |
| Netlist | Danh sách kết nối | Mô tả mạch ở mức cổng logic, gồm tên cell và kết nối giữa chúng |
| Flip-flop (FF) | Mạch lật | Phần tử nhớ 1 bit, lưu giá trị tại cạnh lên/xuống clock |
| Latch | Mạch chốt | Phần tử nhớ trong suốt (transparent) khi enable = 1 |
| Combinational logic | Logic tổ hợp | Mạch mà output chỉ phụ thuộc input hiện tại, không có nhớ |
| Sequential logic | Logic tuần tự | Mạch có phần tử nhớ, output phụ thuộc cả input và trạng thái trước |
| FSM (Finite State Machine) | Máy trạng thái hữu hạn | Mô hình mạch tuần tự với số trạng thái xác định |
| Counter | Bộ đếm | Mạch tuần tự đếm xung clock, tăng/giảm giá trị |
| Multiplexer (MUX) | Bộ dồn kênh | Mạch chọn 1 trong nhiều input dựa trên tín hiệu select |
| Decoder | Bộ giải mã | Chuyển mã nhị phân sang dạng one-hot hoặc tín hiệu chọn |
| Tiếng Anh | Tiếng Việt | Giải thích ngắn |
|---|---|---|
| Synthesis | Tổng hợp | Chuyển RTL thành netlist cổng logic (dùng Yosys, Design Compiler) |
| Standard Cell | Cell chuẩn | Thư viện các cổng logic đã thiết kế sẵn (NAND, NOR, FF...) |
| Technology Library | Thư viện công nghệ | File .lib chứa thông tin timing, power, area của standard cells |
| PDK (Process Design Kit) | Bộ công cụ thiết kế theo quy trình | Tập hợp files mô tả quy trình sản xuất chip (Sky130, GF180) |
| Area | Diện tích | Diện tích chip, đo bằng µm² hoặc số cell equivalents |
| Optimization | Tối ưu hóa | Cải thiện timing/area/power bằng cách thay đổi cấu trúc mạch |
| Mapping | Ánh xạ | Gán logic gates trừu tượng vào standard cells cụ thể |
| Tiếng Anh | Tiếng Việt | Giải thích ngắn |
|---|---|---|
| Floorplan | Bản đồ sàn | Xác định kích thước chip, vị trí macro, I/O pads |
| Placement | Đặt vị trí | Sắp xếp standard cells vào các hàng (rows) trên chip |
| Routing | Đi dây | Kết nối các cells bằng dây kim loại theo các lớp metal |
| CTS (Clock Tree Synthesis) | Tổng hợp cây clock | Xây dựng mạng phân phối clock với skew tối thiểu |
| Metal layer | Lớp kim loại | Các lớp dây dẫn (met1-met5) dùng để kết nối cells |
| Via | Lỗ xuyên lớp | Kết nối giữa hai lớp kim loại liền kề |
| Die | Khuôn chip | Vùng silicon chứa toàn bộ mạch tích hợp |
| GDSII | Định dạng layout | File layout cuối cùng gửi nhà máy sản xuất (foundry) |
| DEF (Design Exchange Format) | Định dạng trao đổi thiết kế | File chứa thông tin placement, routing của design |
| LEF (Library Exchange Format) | Định dạng trao đổi thư viện | File mô tả hình học (geometry) của standard cells |
| Tiếng Anh | Tiếng Việt | Giải thích ngắn |
|---|---|---|
| STA (Static Timing Analysis) | Phân tích timing tĩnh | Kiểm tra timing không cần mô phỏng, phân tích mọi đường |
| Setup time | Thời gian thiết lập | Data phải ổn định trước cạnh clock (tối thiểu) |
| Hold time | Thời gian giữ | Data phải giữ ổn định sau cạnh clock (tối thiểu) |
| Slack | Dư timing | Chênh lệch giữa thời gian yêu cầu và thực tế. Slack < 0 = violation |
| Critical path | Đường tới hạn | Đường dài nhất quyết định tần số tối đa của mạch |
| Clock skew | Lệch clock | Chênh lệch thời gian đến của clock giữa các flip-flop |
| Clock jitter | Nhiễu clock | Biến thiên ngẫu nhiên của chu kỳ clock |
| SDF (Standard Delay Format) | Định dạng trễ chuẩn | File chứa giá trị trễ thực tế để back-annotate vào simulation |
| Corner | Góc điều kiện | Tổ hợp PVT (Process, Voltage, Temperature) để phân tích timing |
| WNS (Worst Negative Slack) | Slack âm tệ nhất | Violation timing tệ nhất trong toàn bộ design |
| TNS (Total Negative Slack) | Tổng slack âm | Tổng tất cả violations, đo mức độ vi phạm tổng thể |
| Tiếng Anh | Tiếng Việt | Giải thích ngắn |
|---|---|---|
| Dynamic power | Công suất động | Tiêu thụ khi mạch chuyển trạng thái (switching + internal) |
| Static power (Leakage) | Công suất tĩnh / Rò rỉ | Tiêu thụ khi mạch không hoạt động, do dòng rò transistor |
| Switching power | Công suất chuyển mạch | Năng lượng nạp/xả tụ ký sinh khi tín hiệu thay đổi |
| Clock gating | Chặn clock | Tắt clock cho khối không hoạt động để tiết kiệm điện |
| Power domain | Miền nguồn | Vùng chip có thể tắt/bật nguồn độc lập |
| DVFS | Điều chỉnh điện áp-tần số động | Thay đổi voltage và frequency theo workload |
| Multi-Vt | Đa ngưỡng điện áp | Dùng cell HVT (chậm, ít rò) và LVT (nhanh, rò nhiều) |
| Tiếng Anh | Tiếng Việt | Giải thích ngắn |
|---|---|---|
| Testbench | Khung kiểm thử | Module không tổng hợp được, tạo stimulus và kiểm tra DUT |
| DUT (Design Under Test) | Thiết kế cần kiểm thử | Module RTL đang được mô phỏng/kiểm tra |
| Stimulus | Kích thích / Tín hiệu đầu vào | Các tín hiệu input tạo ra để test DUT |
| Waveform | Dạng sóng | Biểu đồ tín hiệu theo thời gian, xem bằng GTKWave |
| VCD (Value Change Dump) | File ghi thay đổi giá trị | Định dạng chuẩn lưu waveform, dung lượng lớn |
| Assertion | Xác nhận / Kiểm tra ràng buộc | Điều kiện phải luôn đúng, tự động báo lỗi nếu vi phạm |
| Code coverage | Độ phủ mã | Phần trăm code RTL được thực thi trong simulation |
| Functional coverage | Độ phủ chức năng | Phần trăm scenario/feature đã được kiểm tra |
| UVM (Universal Verification Methodology) | Phương pháp kiểm thử phổ quát | Framework SystemVerilog chuẩn công nghiệp cho verification |
| Formal verification | Kiểm thử hình thức | Chứng minh toán học tính đúng đắn, không cần testbench |
| Regression | Kiểm thử hồi quy | Chạy lại toàn bộ test suite sau mỗi thay đổi code |
| CDC (Clock Domain Crossing) | Giao nhau miền clock | Tín hiệu truyền giữa 2 domain clock khác nhau, cần đồng bộ |
| Tiếng Anh | Tiếng Việt | Giải thích ngắn |
|---|---|---|
| DRC (Design Rule Check) | Kiểm tra quy tắc thiết kế | Kiểm tra layout tuân thủ quy tắc chế tạo của foundry |
| LVS (Layout vs Schematic) | So sánh layout và sơ đồ | Đảm bảo layout khớp với netlist, không sai kết nối |
| ERC (Electrical Rule Check) | Kiểm tra quy tắc điện | Phát hiện lỗi điện: floating gate, short circuit... |
| Antenna check | Kiểm tra hiệu ứng antenna | Tích tụ điện tích trên dây kim loại dài có thể hỏng gate oxide |
| Foundry | Nhà máy chế tạo chip | Nơi sản xuất chip (TSMC, Samsung, GlobalFoundries, SkyWater) |
| Tapeout | Gửi sản xuất | Bước cuối: gửi GDSII cho foundry để chế tạo wafer |
| Yield | Tỷ lệ chip tốt | Phần trăm chip hoạt động đúng trên wafer |
| SPEF (Standard Parasitic Exchange Format) | Định dạng ký sinh chuẩn | File chứa R, C ký sinh sau extraction, dùng cho STA chính xác |
| IR Drop | Sụt áp trên lưới nguồn | Điện áp giảm do điện trở dây dẫn nguồn VDD/VSS |
| EM (Electromigration) | Di chuyển điện tử | Dòng điện quá lớn làm dịch chuyển nguyên tử kim loại, đứt dây |
| Tiếng Anh | Tiếng Việt | Giải thích ngắn |
|---|---|---|
| Scan chain | Chuỗi quét | Nối FF thành chuỗi để shift-in/shift-out test patterns |
| BIST (Built-In Self Test) | Tự kiểm tra tích hợp | Logic kiểm tra được nhúng ngay trong chip |
| JTAG | Giao tiếp debug/test | Chuẩn IEEE 1149.1 cho boundary scan và debug |
| ATPG | Tạo mẫu kiểm tra tự động | Tool tự tạo test vectors để phát hiện lỗi stuck-at |
| Fault coverage | Độ phủ lỗi | Phần trăm lỗi (stuck-at-0/1) được phát hiện bởi test patterns |
| # | Tên sách | Tác giả | Ghi chú |
|---|---|---|---|
| 1 | Digital Design and Computer Architecture (2nd Ed.) | David Harris, Sarah Harris | Nền tảng thiết kế số, từ cổng logic đến CPU. Rất phù hợp cho người mới |
| 2 | CMOS VLSI Design: A Circuits and Systems Perspective (4th Ed.) | Neil Weste, David Harris | Kinh điển về thiết kế CMOS — từ transistor đến system-on-chip |
| 3 | Digital Integrated Circuits: A Design Perspective (2nd Ed.) | Jan Rabaey, Anantha Chandrakasan, Borivoje Nikolić | Thiết kế IC số từ góc nhìn mạch điện, timing, power |
| 4 | Verilog HDL: A Guide to Digital Design and Synthesis (2nd Ed.) | Samir Palnitkar | Tham khảo toàn diện về ngôn ngữ Verilog HDL |
| 5 | SystemVerilog for Design (2nd Ed.) | Stuart Sutherland, Simon Davidmann, Peter Flake | SystemVerilog cho thiết kế (RTL), phân biệt với verification |
| 6 | Static Timing Analysis for Nanometer Designs | J. Bhasker, Rakesh Chadha | Chuyên sâu về STA — setup/hold, clock domains, timing closure |
| 7 | Physical Design Essentials: An ASIC Design Implementation Perspective | Khosrow Golshan | Floorplan, placement, routing, CTS — trọng tâm của backend flow |
| 8 | VLSI Physical Design: From Graph Partitioning to Timing Closure | Andrew Kahng, Jens Lienig, Igor Markov, Jin Hu | Thuật toán trong physical design — dùng trong OpenROAD |
| 9 | SystemVerilog for Verification (3rd Ed.) | Chris Spear, Greg Tumbush | Kinh điển về verification — OOP, constraints, coverage, assertions |
| 10 | Writing Testbenches: Functional Verification of HDL Models (2nd Ed.) | Janick Bergeron | Phương pháp viết testbench chuyên nghiệp, verification planning |
| # | Tài nguyên | Mô tả |
|---|---|---|
| 1 | OpenLane 2 Documentationopenlane2.readthedocs.io |
Tài liệu chính thức của OpenLane 2 — cấu hình, API, flow steps |
| 2 | Sky130 PDK Documentationskywater-pdk.readthedocs.io |
Thông tin về standard cells, IO cells, primitive devices của Sky130 |
| 3 | OpenROAD Documentationopenroad.readthedocs.io |
Floorplan, placement, CTS, routing, STA — engine chính của OpenLane |
| 4 | Yosys Manualyosyshq.readthedocs.io |
Synthesis engine: commands, passes, scripting |
| 5 | Zero to ASIC Coursezerotoasiccourse.com |
Khóa học online từ Matt Venn — từ Verilog đến tapeout thực tế trên Sky130 |
| 6 | Efabless / Google Open MPWefabless.com |
Chương trình sản xuất chip miễn phí cho thiết kế open-source |
| 7 | VLSI System Design (VSD)vsdiat.com |
Workshop và khóa học về OpenLane, Sky130 — rất nhiều video hướng dẫn |