Scope và hierarchy: cùng tên value, khác instance
Tiên quyết
- Module A2: Logic tổ hợp: Đang tải
- Module A4: Tuần tự & timing: Đang tải
- Module và instance: nối hai bộ cộng mà không nhầm cổng: Đang tải
- Parameter và generate: cấu hình phần cứng trước khi chạy: Đang tải
Sau bài này bạn sẽ
- Phân biệt tên module, instance, generate block và tín hiệu cục bộ
- Đọc đường dẫn tương đối và đường dẫn từ root của ví dụ
- Phân biệt index generate ở elaboration với chọn dữ liệu lúc runtime
- Dùng hierarchy để quan sát debug mà vẫn giữ hợp đồng RTL qua port
Hai ngăn có cùng nhãn không phải cùng một ngăn
Một module có tín hiệu nội bộ tên value. Khi module được instantiate hai lần, không có một value dùng chung cho mọi bản sao. Mỗi instance có scope và kết nối riêng. Để debug đúng nơi, cần đọc đường dẫn chứ không chỉ tìm một tên bằng văn bản.
Ví dụ tạo hai lane bằng generate, mỗi lane chứa một scoped_cell. Cùng input byte a5, lane thấp nhìn nibble 5, lane cao nhìn nibble a. TB còn có biến value riêng bằng 99 để cho thấy một tên ngắn không đủ xác định đối tượng.
Các đường dẫn đã viết được parser/simulator kiểm thật; toàn bộ name lookup, package scope, upward reference và những trường hợp khác còn [1].
Module type khác tên instance
scoped_cell là tên module type. u_cell là tên instance bên trong mỗi generate block. hierarchy_pair là module bao hai lane và dut là instance của nó ở testbench.
Viết một đường dẫn bắt đầu từ dut là chọn instance có thật trong TB. Không dùng tên module type thay cho instance rồi mong nó trỏ tới mọi bản sao cùng lúc. Tên module trong source và tên instance trong cây elaboration trả lời hai câu hỏi khác nhau.
Generate block được đặt tên g_lane. Hai nhánh có tên g_lane[0] và g_lane[1]; tên u_cell lặp lại hợp lệ vì nằm ở hai scope khác nhau. Named block giúp đường dẫn dễ đọc hơn tên tự sinh vốn có thể đổi khi chỉnh source.
Ba biến value độc lập
TB khai báo int value=99. Mỗi scoped_cell khai báo một wire 4 bit tên value, nối với input data của instance đó. Trong scope TB, tên ngắn value ở phép kiểm là biến 99; trong leaf, tên ngắn value ở biểu thức cộng là wire của leaf.
Tại data a5, hai wire leaf lần lượt bằng 5 và 10, còn value của TB vẫn 99. Không có việc “lần gán sau thắng” giữa ba tên này: đó là ba đối tượng thuộc ba scope khác nhau.
Parameter STEP cũng thuộc mỗi instance. Lane 0 override STEP=1, lane 1 override STEP=2 tại elaboration. Hai instance cùng type nhưng không bắt buộc có cùng parameter.
Đọc từng đoạn của đường dẫn
dut.g_lane[1].u_cell.value đi từ TB tới instance dut, chọn generate block lane 1, vào instance u_cell rồi đọc wire value. Mỗi đoạn chọn một đối tượng trong scope trước đó.
Đường dẫn $root.tb_hierarchy.dut.g_lane[0].u_cell.result trong TB bắt đầu từ root và chỉ rõ top tb_hierarchy trước khi đi xuống leaf. TB đã kiểm đường dẫn này bằng kết quả qua port. Đây là đường dẫn của đúng ví dụ; không suy ra mọi simulator đều hỗ trợ mọi dạng hierarchical name.
Một tên phân cấp phụ thuộc cấu trúc elaborated design. Đổi tên u_cell hoặc chèn một wrapper có thể làm đường dẫn TB cũ không còn đúng dù hành vi port giữ nguyên. Parser/elaborator phải bắt lỗi tên; không thay giá trị expected để che lỗi kết nối hoặc lookup.
Kiểm 256 input và hai STEP khác nhau
Tính trước: byte a5 cho nibble thấp 5 cộng STEP 1 thành 6; nibble cao 10 cộng STEP 2 thành 12. Byte ff cho kết quả 16 và 17, nên output mỗi lane cần 5 bit.
TB chạy đủ 256 byte. Oracle dùng chia/lấy dư số nguyên cho high/low nibble, kiểm cả port và wire nội bộ, parameter của hai instance và đường dẫn root. Sau vòng lặp mới in HIER CASES checked=256 low=16 high=17.
Parse/lint/sim/synth đều đạt. Simulation ở ví dụ này dùng Verilator với input 0/1; synthesis generic kiểm 0 FF. Không lấy tên mô phỏng làm lời hứa hierarchy sẽ còn nguyên sau flatten/optimization. [2]
Chọn phần tử dữ liệu khác chọn instance
g_lane[0] trong đường dẫn là chọn một scope generate bằng index hằng. Generate tạo cấu trúc tại elaboration; nó không phải một mảng các object có thể truy cập tùy ý bằng mọi biến runtime.
Nếu yêu cầu là chọn output lane trong lúc chạy, hãy đưa kết quả qua port/bus rồi chọn dữ liệu trên bus theo hợp đồng thiết kế. Thay số 0 trong đường dẫn bằng một biến không tự tạo phần cứng mux giữa các instance.
Bài không đưa một đoạn đường dẫn runtime không hợp lệ vào file rồi gọi nó đã mô phỏng. Phần đã kiểm chỉ dùng hai constant index. Quy tắc đầy đủ về index/hierarchical names phải tiếp tục đọc LRM và diagnostic của tool đang dùng.
Quan sát nội bộ khác nối thiết kế
RTL của ví dụ nối toàn bộ dữ liệu qua named ports. Hierarchical references chỉ được đọc trong TB để đối chiếu và debug, không dùng để ghi đè logic bên trong hoặc force output.
Với interface ổn định, test kiểm ở port ít phụ thuộc tên nội bộ hơn. Probe hierarchy hữu ích để định vị lỗi, nhưng cần biết chi phí bảo trì khi refactor. Trong flow lớn, bind/interface/probe được thiết kế riêng có thể phù hợp hơn; bài này chưa kiểm các cơ chế đó.
Cũng không suy ra mọi cross-module reference đều synthesizable vì TB đọc được tín hiệu. Yosys ở đây chỉ tổng hợp RTL nối bằng port, không tổng hợp TB có $root.
Tên đúng nhưng scope sai
- Nhầm scoped_cell là instance name thay vì module type.
- Đọc lane 0 trong khi lỗi đang ở lane 1; cả hai có wire tên value nên nhìn lướt khó thấy.
- Quên parameter override riêng và đoán cả hai cộng 1.
- Dùng variable runtime ở nơi cần constant generate index.
- Dựa vào tên nội bộ sau synthesis mà không kiểm báo cáo/netlist tương ứng.
- Biến probe debug thành đường nối chức năng, làm kết nối ẩn khó review.
Tự kiểm tra
Debug bằng cây hierarchy
Bắt đầu từ top/instance đúng, đi qua từng named scope, xác nhận parameter của instance và so tín hiệu nội bộ với hợp đồng port. Sau khi tìm được nguyên nhân, sửa kết nối hoặc RTL đúng chỗ thay vì sửa expected để hợp thức hóa kết quả sai.
Bằng chứng phủ 256 byte và những đường dẫn đã nêu; chưa phủ toàn bộ namespace/package rules, force, bind, visibility sau tối ưu hoặc dữ liệu X/Z. Bài vẫn draft với LRM needs-spec-check.
Nguồn và mức độ đối chiếu
- IEEE 1800-2023 SystemVerilog LRM, cần đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Thử nghiệm A6.hier-ref: source và verification.json, Bằng chứng hierarchy. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Scopes, hierarchical names, generate blocks, root scope. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Thử nghiệm A6.hier-ref: source và verification.json, Ví dụ đã chạy: source và verification.json. Trích dẫn; nguồn đã đọc toàn văn.
- Thử nghiệm A6.hier-ref: source và verification.json, hierarchy_pair.sv, tb_hierarchy.sv và verification.json. Trích dẫn; nguồn đã đọc toàn văn.