Interface và modport: gom tín hiệu, giữ rõ ai được ghi

Khoảng 45 phútMức 1/3Bản nháp: một số khẳng định chưa đối chiếu spec

Sau bài này bạn sẽ

  • Phân biệt interface definition, instance và modport view
  • Đọc hướng input/output từ phía thành phần dùng modport
  • Thiết kế oracle bắt cả mất carry lẫn nối nhầm bundle

Một nhóm dây có chung tên chưa chắc có chung ownership

Hai bộ cộng có cùng ba tín hiệu a, b và total. Viết từng cổng ở mọi nơi dễ dẫn tới việc lấy đầu vào bên trái nhưng đọc đầu ra bên phải. Interface giúp giữ các tín hiệu liên quan trong một instance có tên; modport mô tả vai trò của thành phần kết nối vào instance ấy.

Hãy phân biệt hai câu hỏi: “tín hiệu nào thuộc cùng một bundle?” và “thành phần này được đọc hoặc ghi tín hiệu nào?”. Bundle trả lời câu đầu; modport giúp trả lời câu sau. Cả hai đều chưa quy định lúc nào stimulus được đổi hay lúc nào checker được đọc. Bài này chỉ dùng mạch tổ hợp và chờ ổn định, chưa giải bài toán timing ở cạnh clock.

Một definition, hai instance, hai bộ tín hiệu

interface sum_link; ... endinterface định nghĩa cấu trúc. Hai khai báo sum_link left(); sum_link right(); tạo hai instance riêng trong hierarchy. Ghi left.a không tự đổi right.a, dù cả hai xuất phát từ cùng một definition.

Ngược lại, nối hai module vào cùng left khiến chúng cùng thấy bộ tín hiệu của left. Interface không tự nhân bản storage theo số module kết nối. Đây là lỗi thường gặp khi nhân bản DUT: sửa tên instance DUT nhưng quên sửa actual interface ở cổng. Bài dùng hai bộ đầu vào bổ sung nhau để việc nối nhầm không thể ẩn sau dữ liệu giống hệt.

[1]

Hướng modport nhìn từ phía người sử dụng

modport calc(input a,b, output total) nói rằng module dùng view calc đọc a/b và điều khiển total. Output total không có nghĩa testbench phải phát total vào DUT; hướng được đọc từ phía module có cổng sum_link.calc link.

View probe khai báo cả ba tín hiệu là input để mô tả một phía chỉ quan sát. Modport không tạo một bản sao của a/b/total và không phải bộ chuyển hướng tự động. Hai view cùng tham chiếu tín hiệu của một instance. Đổi tên view không sửa ownership sai trong implementation.

Probe âm ghi vào input của modport được pyslang từ chối. Đây là kiểm tra một lỗi cụ thể ở tool đang dùng, không phải lời hứa mọi simulator sẽ báo cùng câu chữ hay mọi xung đột driver đều được modport tự tìm ra.

[2]

Cổng interface nối cả bundle, không tạo mạch mới

module sum_unit(sum_link.calc link) nhận instance qua cổng có view calc. sum_unit left_unit(left) kết nối left vào formal link; bên trong truy cập link.a, link.b và link.total. Phần tử tính toán vẫn là phép cộng do module viết ra.

Nếu DUT cũ có từng cổng riêng, testbench có thể nối từng cổng ấy tới member của interface; chỉ gom phía testbench không tự đổi port list của DUT. Khi DUT dùng interface-as-port, chỗ instantiation mới rút thành một bundle. Đó là thay đổi biểu diễn kết nối, không phải tự động có thêm pipeline, handshake hoặc kiểm tra protocol.

[3]

Logic là kiểu dữ liệu, không phải quyền sở hữu

Main khai báo a/b là logic 4 bit và total là logic 5 bit. Testbench là phía ghi a/b; mỗi sum_unit có một continuous assignment ghi total của instance mình. Không dùng chữ logic để kết luận có thể thêm nhiều writer tùy ý hoặc mọi member phải do procedural block điều khiển.

Net/variable, data type và driver là những trục khác nhau cần kiểm khi review code. Với ví dụ này, ownership đơn giản là một nguồn ghi cho từng tín hiệu. Modport diễn đạt vai trò ở cổng; top-level vẫn có trách nhiệm không nối sai hoặc ghi trực tiếp lên total. Mô phỏng dùng Verilator 2-state nên không chứng minh hành vi X/Z hay resolution khi nhiều driver tranh chấp.

Kiểm từng bộ cộng trước khi kiểm tổng chung

Với x/y chạy từ 0 tới 15, bên trái nhận x/y và có kết quả toán học x+y. Bên phải nhận 15−x và 15−y nên có kết quả 30−x−y. Hai kết quả phải được kiểm riêng, sau đó mới cộng để đối chiếu tổng chung 30 ở mỗi cặp.

Chỉ kiểm left.total + right.total bằng 30 chưa đủ: hai giá trị sai bù trừ có thể vượt qua. Checker dùng biến vòng lặp làm oracle, không đọc lại a/b của DUT rồi lặp phép cộng của implementation. Mất carry được kích hoạt khi tổng vượt 15; nối nhầm right_unit vào left cũng phải bị bắt. Giữ input khác nhau giữa hai instance giúp fault này hiện rõ.

Chờ ổn định của mô hình khác với timing phần cứng

Testbench ghi đồng thời bốn input rồi chờ #1 trước khi đọc hai output. Có 16×16=256 cặp, mỗi cặp hai phép đối chiếu, tức 512 check. Tổng tích lũy bằng 30×256=7680; thời điểm cuối dự kiến 256 ns với timescale 1 ns/1 ps.

Khoảng chờ này chỉ tạo điểm quan sát ổn định trong ví dụ tổ hợp. Nó không đo propagation delay thực, không chứng minh setup/hold và không sửa mọi race của DUT tuần tự. Nếu chuyển sang always_ff tại posedge, phải thiết kế lại hợp đồng drive/sample; bài clocking sẽ xử lý riêng thay vì mang #1 ở đây sang mọi testbench.

Vét 256 cặp và đối chiếu 512 kết quả

Expected được tính trước chạy: INTERFACE CHECK pairs=256 checks=512 combined_sum=7680 time_ns=256. Main đã parse và simulate; không claim lint, synthesis hoặc four-state.

Interface và modport: gom tín hiệu, giữ rõ ai được ghi

Expected tính trước chạy: INTERFACE CHECK pairs=256 checks=512 combined_sum=7680 time_ns=256

tb.sv testbench
`timescale 1ns/1ps// Expected:256input pairs, two independent adders ->512checks, combined sum30*256=7680.interface sum_link;  logic[3:0] a,b;  logic[4:0] total;  modport calc(input a,b,output total);  modport probe(input a,b,total);endinterfacemodule sum_unit(sum_link.calc link);  assign link.total={1'b0,link.a}+{1'b0,link.b};endmodulemodule tb_interface;  sum_link left();sum_link right();  sum_unit left_unit(left);sum_unit right_unit(right);  int pairs=0,checks=0,sum_total=0;  initial begin    for(int x=0;x<16;x++)for(int y=0;y<16;y++)begin      left.a=4'(x);left.b=4'(y);right.a=4'(15-x);right.b=4'(15-y);      #1;      if(int'(left.total)!=x+y)$fatal(1,"left interface sum oracle");checks++;      if(int'(right.total)!=30-x-y)$fatal(1,"right interface sum oracle");checks++;      sum_total+=int'(left.total)+int'(right.total);pairs++;    end    if(pairs!=256||checks!=512||sum_total!=7680||$time!=256)$fatal(1,"interface accounting");    $display("INTERFACE CHECK pairs=256 checks=512 combined_sum=7680 time_ns=256");$finish;  endendmodule

Đã kiểm chứng thế nào

  • Phân tích và elaborate theo LRM (pyslang 12.1.0)
  • Mô phỏng, exit 0 và output khớp kỳ vọng tính tay (Verilator 5.050, 2-state)

Output phải khớp: INTERFACE CHECK pairs=256 checks=512 combined_sum=7680 time_ns=256

Verilator 5.050/2-state; chỉ source/cấu hình đã chạy. Không claim X/Z, timing vật lý, synthesis, UVM hay mọi parameter specialization.

Oracle nguyên bản theo input vòng lặp; fault probes giữ riêng, không làm yếu checker.

Các kiểm tra chạy lúc xây dựng nội dung (2026-11-06), không chạy trong trình duyệt. Kỳ vọng được tính tay trước khi chạy.

Hai bản sao lỗi runtime giữ nguyên oracle: thu hẹp kết quả còn 4 bit và nối nhầm instance bên phải. Probe ghi vào modport input kiểm đường từ chối ở parser. Kết quả và file tái hiện được giữ cùng repo.

[4]

Tự kiểm tra

Tự kiểm tra: interface

  1. Trong modport calc(input a,b, output total), ai điều khiển total?
  2. Hai khai báo sum_link left(); và sum_link right(); tạo gì?
  3. Giá trị lớn nhất của a+b với hai input unsigned 4 bit là bao nhiêu?
  4. 256 cặp input, hai oracle riêng mỗi cặp: bao nhiêu phép đối chiếu output?
  5. #1 trước đọc output trong main chứng minh điều gì?

Review kết nối theo instance, view và thời điểm

Trước khi thêm DUT thứ hai, vẽ instance nào có tín hiệu nào, writer nào điều khiển chúng và view nào được đưa cho từng cổng. Sau đó chọn stimulus phân biệt các instance và oracle độc lập cho từng kết quả. Interface làm kết nối gọn hơn; kiểm ownership và timing vẫn là công việc của người thiết kế testbench.

Nguồn và mức độ đối chiếu

  1. SystemVerilog Interface — bản chụp resources.zip, What Is an Interface?; A Basic Interface Example; How Do You Define Port Directions?; How Do You Connect an Interface to a DUT?. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. SystemVerilog Modport — bản chụp resources.zip, Syntax; Example of a Named Port Bundle. Trích dẫn; nguồn đã đọc các mục liên quan.
  3. SystemVerilog Interface Syntax and Connections — bản chụp resources.zip, Connecting an Interface to a SystemVerilog Design. Trích dẫn; nguồn đã đọc các mục liên quan.
  4. Thí nghiệm nguyên bản ex.b4.interface, Source, self-checks, verification.json và fault probes. Trích dẫn; nguồn đã đọc toàn văn.
  5. IEEE 1800-2023 SystemVerilog LRM, Interfaces, modports, parameterization and virtual interfaces — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).