Sequence có tham số: tái sử dụng mẫu thời gian, hiểu endpoint và đệ quy
Sau bài này bạn sẽ
- Dùng một sequence cho hai kênh tín hiệu khác nhau
- Truy biểu thức actual tới đúng tick trong sequence
- Phân biệt endpoint, lưu dữ liệu và bước đệ quy sang clock kế tiếp
Cùng một quy tắc, hai cặp tín hiệu
Kênh A yêu cầu ack sau đúng một tick. Kênh B cũng vậy. Viết hai bản sequence gần giống nhau khiến việc sửa delay dễ lệch giữa hai kênh.
Ta có thể đặt tên cho mẫu thời gian và truyền tín hiệu vào lúc dùng. Mẫu nói “req ở tick này, ack ở tick sau”; mỗi assertion quyết định nó áp dụng cho cặp tín hiệu nào.
Việc tái sử dụng chỉ có ích khi cả tín hiệu, clock và nghĩa vụ đều được nối đúng. Tên sequence giống nhau chưa bảo đảm hai assertion kiểm cùng hợp đồng.
Theo từng request tới tick cần ack
Xét hai kênh dùng cùng clock. Mỗi request trong bảng chỉ cao một tick. Ack được lấy mẫu ở tick kế tiếp.
| Kênh | Tick request | Tick cần ack | Ack tại tick đó | Kết luận |
|---|---|---|---|---|
| A | 1 | 2 | 1 | Đáp ứng |
| A | 4 | 5 | 0 | Vi phạm |
| A | 7 | 8 | 1 | Đáp ứng |
| A | 10 | 11 | 1 | Đáp ứng |
| B | 2 | 3 | 1 | Đáp ứng |
| B | 5 | 6 | 1 | Đáp ứng |
| B | 8 | 9 | 0 | Vi phạm |
Ack của B tại tick 6 không trả lời request A tại tick 4. Kênh, nội dung điều kiện và thời điểm đều thuộc hợp đồng cần kiểm.
Formal là tên trong mẫu, actual là biểu thức được nối
Đây là định nghĩa được dùng trong ví dụ:
sequence transfer(req,ack);req ##1 ack;endsequence
req và ack là formal argument: tên được dùng bên trong mẫu. Trong transfer(req_a,ack_a), actual argument là các biểu thức req_a và ack_a. Một lần dùng khác là transfer(req_b,ack_b).
Assertion A đặt mẫu sau implication:
req_a |-> transfer(req_a,ack_a) dùng clock @(posedge clk).
Khi req_a false, antecedent không tạo nghĩa vụ ack cho attempt đó. Khi req_a true, mẫu bắt đầu ngay tại tick request và yêu cầu ack_a ở tick kế tiếp. Formal req lặp lại điều kiện đầu của mẫu; nó không tự thay thế vai trò gating của implication.
Truy biểu thức tới đúng tick
Trong mẫu này, req được xét ở điểm bắt đầu; ack được xét sau ##1. Ở request A tại tick 1, ack_a đang bằng 0 nhưng tới tick 2 bằng 1, nên lần kiểm ấy vẫn được đáp ứng.
Truyền ack_a vào formal không có nghĩa chụp giá trị 0 tại tick 1 rồi giữ nó cho cả sequence. Đó là bài toán lưu dữ liệu khác; biến local và capture đã được học ở bài trước.
Clock trong ví dụ được ghi rõ tại assertion là @(posedge clk). ##1 là một tick của clock đó. Đổi chu kỳ clock không tự đổi quan hệ “tick kế tiếp” thành một delay cố định theo ns.
Nếu truyền ack_b vào assertion A, mẫu vẫn có cấu trúc hợp lệ nhưng quan sát nhầm kênh. Hãy lần đường actual → formal → tick sử dụng, thay vì chỉ kiểm tên khai báo.
Endpoint là lúc mẫu hoàn tất
Với req ##1 ack, nếu req tại tick 1 và ack tại tick 2 cùng đáp ứng, endpoint của match là tick 2. Chưa thấy ack ở tick 1 không có nghĩa mẫu đã thất bại: nó còn đang chờ tới tick cần kiểm.
Khi nối mẫu bằng implication |->, điều kiện phía sau bắt đầu tại endpoint của antecedent. Viết bảng start/endpoint trước sẽ giúp phân biệt cách nối mẫu với việc đọc một cờ “đã xong” lưu trong thanh ghi.
Sequence method như .triggered liên quan tới trạng thái match và clock context. Nguồn training cũng có tên .ended; cần đối chiếu đúng cú pháp/ngữ nghĩa của bản IEEE đang dùng trước khi thay tên method. Không coi một method là cờ done giữ nguyên tới khi reset.
Trong bộ ví dụ hiện tại, dạng .triggered mới được parser chấp nhận và chưa có mô phỏng thành công. Phạm vi này được ghi trong bằng chứng cuối bài.
Đệ quy cần một bước sang thời gian sau
Thay vì liệt kê mọi tick chờ, một property có thể tự gọi lại trên tick sau. Source minh họa dùng:
property recur(x); x or (1'b1 |=> recur(x));endproperty
Bảng minh họa nhánh dừng khi x cuối cùng true:
| Tick đang xét | x | Cách lần theo biểu thức |
|---|---|---|
| 1 | 0 | Xét tiếp bước gọi ở tick 2 |
| 2 | 0 | Xét tiếp bước gọi ở tick 3 |
| 3 | 1 | Nhánh x đã đáp ứng tại tick này |
Bước thời gian làm các lần tự gọi khác nhau. Nếu chỉ thay |=> bằng |->, lời gọi quay lại ngay ở cùng tick; không còn sự tiến triển thời gian đang mô tả.
Nếu simulation dừng khi vẫn chờ, chưa thể dùng bảng trên để kết luận pass. Quy tắc strong/weak, finite-end, polarity và reset wrapper của property đệ quy còn cần đối chiếu chuẩn. Source đệ quy ở bài mới có bằng chứng parser, chưa có bằng chứng chạy mô phỏng.
Bốn nhầm lẫn khi tái sử dụng sequence
- Nối nhầm actual từ kênh khác dù tên formal vẫn đúng.
- Coi argument là giá trị đã capture ở thời điểm bắt đầu.
- Dùng
##0hoặc##2khi yêu cầu là đúng tick kế tiếp. - Coi endpoint là trạng thái lưu vĩnh viễn, hoặc gọi đệ quy mà không tiến sang thời gian sau.
Tách ba câu hỏi khi đọc: mẫu nhận biểu thức nào, biểu thức được xét ở tick nào, và attempt nào tạo nghĩa vụ kiểm mẫu đó?
Đổi kênh, đổi delay và lần theo nghĩa vụ
- Với request A tại tick 4, có được dùng ack B tại tick 6 để gọi A đáp ứng không? Vì sao?
- Nếu đổi
##1thành##0, tại tick nào cần kiểm ack của request A tại tick 1? - Nếu cần so dữ liệu ở deadline với dữ liệu lúc request, argument đơn thuần đã đủ giữ dữ liệu chưa?
- Trong bảng đệ quy, vì sao bước từ tick 2 sang tick 3 cần tiến triển thời gian?
- Parser chấp nhận một property đã đủ chứng minh hành vi khi chạy và lúc kết thúc simulation chưa?
Kiểm tra
Bằng chứng kiểm chứng
Expected tính trước chạy từ bảng: SVA ARG CHECK samples=12 starts_a=4 starts_b=3 failures_a=1 mask_a=32 failures_b=1 mask_b=512 time_ns=120. Hai vi phạm ở tick 5 và 9 tạo mask 32 và 512. Stimulus đổi ở cạnh xuống; chạy đủ 12 sample tới 120 ns, qua deadline cuối 11.
Guard kiểm tick/start count của hai kênh, số failure, mask và thời gian thật. Hai ack thiếu là lỗi cố ý: tắt assertion làm failure trở về 0 và oracle phải từ chối. Bốn mutant giữ nguyên kỳ vọng: nối nhầm ack, đổi delay thành 0, đổi thành 2, dùng gate của A cho B. Cả bốn parse/build được rồi bị bắt ở runtime.
Pyslang chấp nhận hai source trên; Verilator 5.050 không resolve được .triggered và báo unsupported recursive property call. Dạng .ended bị parser đã ghim từ chối với InvalidMemberAccess. Các probe được giữ riêng; không nâng giới hạn một công cụ thành quy tắc của IEEE, không đổi cú pháp/kỳ vọng để gọi đã simulated PASS.
Main chỉ chạy formal không khai báo kiểu/hướng, tín hiệu bit 2-state, một clock và delay một tick. Chưa kiểm local/output formal, conversion, multiclock, phương thức endpoint hay kết thúc property đệ quy. Bảng đệ quy là minh họa lập luận, không phải trace mô phỏng. Nguồn training có bảng bị hỏng và ví dụ chưa rõ clock/reset, nên không sao chép code/diagnostic của tutorial làm bằng chứng cho bài.
Nguồn và mức độ đối chiếu
- IEEE 1800-2023 SystemVerilog LRM, Sequence arguments, endpoint methods and recursive properties — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Sequence in Assertions — formal arguments, What Is an SVA Sequence?; Where does the Clock Come From?; The sequence with a formal argument; Multiple sequences example; Common Mistakes. Trích dẫn; nguồn đã đọc các mục liên quan.
- If expression and ended sequence — tài liệu training, ended in sequence; ended in sequence example; Points to Remember. Trích dẫn; nguồn đã đọc các mục liên quan.
- Recursive property — tài liệu training, What Makes a Property Recursive?; How the Recursive Property Works; Why a Time Delay Is Required; Restrictions on Recursive Properties; Legal reset wrapper. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản B8.advanced, Two-channel sequence arguments, four runtime mutants and retained endpoint/recursion limitations. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Sequence formal arguments, actual expressions and sampling — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- IEEE 1800-2023 SystemVerilog LRM, Sequence endpoint methods and clock context — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- IEEE 1800-2023 SystemVerilog LRM, Recursive properties, time progress and restrictions — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).