Testbench tự kiểm: clock, oracle và đường thất bại
Tiên quyết
Sau bài này bạn sẽ
- Tách DUT, stimulus, clock, checker và điều kiện kết thúc
- Tính expected độc lập cho reset, hold, increment và wrap
- Kiểm sau NBA bằng hợp đồng thời điểm rõ và bắt X bằng case inequality
- Dùng watchdog và mutation probe để kiểm cả đường thất bại
Một waveform đẹp chưa trả lời thiết kế đúng chưa
Một counter đếm vài lần rồi finish chưa đủ để gọi là đã kiểm đúng. Nếu enable bị bỏ qua, reset mất ưu tiên hoặc wrap sai, hình sóng vẫn có thể trông hợp lý ở stimulus đơn giản.
Bài bắt đầu bằng yêu cầu nhỏ có thể tính tay: counter 2 bit, reset đồng bộ active-low ưu tiên hơn enable; enable 0 giữ state, enable 1 tăng modulo 4. TB kiểm từng output theo lịch cố định và dừng với lỗi nếu một bước không đúng.
Mỗi phần của TB có một trách nhiệm
DUT chỉ chứa hành vi counter. TB tạo clock, drive reset/enable, lưu expected và so sánh output. Checker không được dùng chính output DUT để tự tạo expected cùng cạnh, vì như vậy có thể lặp lại lỗi hoặc chấp nhận state sai.
Nguồn đào tạo phân chia DUT, connections, stimulus và checker. Trong ví dụ này, top TB không cần port; không coi tên top hay cách đặt file là điều tạo nên một test tốt. Sự độc lập của oracle và độ phủ các yêu cầu mới là điều cần đánh giá. [1]
Half-period và thời điểm lấy mẫu
Clock khởi tạo 0 và đảo mỗi 5 ns, nên period 10 ns, posedge tại 5,15,...75. Không khởi tạo clock sẽ khiến phép đảo X không tạo clock nhị phân như dự định.
Stimulus đổi tại 10,20,30,60,70 ns; checker đọc 1 ns sau mỗi posedge. Cách bố trí này hợp với đúng DUT posedge và clock đang xét; nó tránh đọc output trước NBA và tránh stimulus cạnh tranh ở cùng cạnh. Không suy nó thành công thức #1 hoặc negedge an toàn cho mọi DUT.
Checker còn kiểm timestamp 6+10×index, nên thay nhầm half-period không chỉ làm bài chạy “nhanh hơn” mà bị phát hiện sai hợp đồng.
Expected phải đến từ yêu cầu
Trước chạy, viết chuỗi state sau 8 cạnh là 0,1,1,2,3,0,0,0. Oracle là bảng theo index được tính từ kế hoạch stimulus, không phải một counter thứ hai sao lại đúng biểu thức RTL.
Chuỗi bắt đầu reset, tăng, hold, tăng hai lần, wrap, reset khi enable vẫn 1 rồi hold sau nhả reset. Giá trị thay đổi đủ để lỗi bỏ enable hoặc mất wrap khó bị giấu bởi toàn số 0.
Một bảng cố định không thay thế mọi reference model khi bài toán lớn hơn. Nó phù hợp ở đây vì số bước nhỏ và người học có thể đối chiếu từng mốc bằng tay. [2]
Reset, hold và wrap là ba câu hỏi khác
Reset đồng bộ được kiểm sau cạnh, không đòi output đổi tức thì khi rst_n vừa đổi giữa hai cạnh. Tại cạnh 65 ns, reset 0 và enable 1 cùng tồn tại; expected 0 kiểm reset có ưu tiên.
Hold được kiểm ở hai thời điểm, gồm một lần state 1 để bắt lỗi vô tình xóa state. Wrap từ 3 về 0 được kiểm tại 55 ns. Các bộ đếm action cuối phải có 2 reset,2 hold và 4 increment; thiếu một nhóm không được gọi là đã phủ kế hoạch này.
Đây là kiểm kế hoạch 8 cạnh, không phải functional coverage đầy đủ hoặc vét cạn mọi chuỗi reset/enable.
Đừng để X làm điều kiện lỗi bị bỏ qua
Với unknown_bit=X, biểu thức unknown_bit != 0 cho unknown; if không đi vào nhánh báo lỗi. Còn unknown_bit !== 0 trả giá trị xác định 1. TB tự kiểm hai cờ weak_caught0/strict_caught1 để làm lộ khác biệt.
Checker DUT dùng case inequality với expected đã biết, nên X/Z bất ngờ không được coi là “không thấy mismatch”. Điều này không có nghĩa mọi test đều phải so case equality: nếu yêu cầu cho phép unknown hoặc don't-care, cần định nghĩa checker thích hợp thay vì tự bỏ qua nó.
Các quy tắc chuẩn vẫn [3]; kết quả ở đây có TB 4-state thực chạy.
Kiểm 8 cạnh và đủ ba nhóm hành động
Kỳ vọng trước chạy: check tại 6/16/26/36/46/56/66/76 ns, state 0/1/1/2/3/0/0/0; action count 2/2/4. Tất cả đúng thì finish 76 ns, trước watchdog 100 ns.
Output từng cạnh và assertion đều có trong bằng chứng; chúng không thay kiểm toàn không gian state hoặc synthesis của DUT. [4]
Testbench cũng phải có đường thất bại đã kiểm
Hãy thử suy luận ba thay đổi sai trước khi chạy trên bản sao: bỏ điều kiện enable làm hold state 1 đổi; bỏ reset làm cạnh đầu chưa biết; dừng clock làm checker không tới cạnh tiếp theo. Với lỗi cuối, watchdog phải kết thúc bằng fatal thay vì treo vô hạn.
Một TB chỉ kiểm kết quả cuối có thể bỏ sót lỗi trung gian nếu counter quay lại đúng giá trị cuối. Vì vậy ví dụ kiểm cả 8 cạnh và action count. Mutation probe là cách kiểm sức bắt lỗi của TB trong phạm vi các lỗi đã thử, không phải chứng minh không còn bug nào.
Tự kiểm tra
Mô tả cách pass và cách fail trước khi chạy
Một test tự kiểm cần expected độc lập, thời điểm đọc xác định, cách bắt unknown, điều kiện đủ bước và deadline. Xem waveform khi debug, nhưng để assertion và exit status quyết định kết quả regression.
Bài giữ draft/LRM needs-spec-check; không gọi 8 cạnh là đã hoàn tất verification mọi tình huống của counter.
Nguồn và mức độ đối chiếu
- Verilog Testbench — bản chụp trong resources.zip, Testbench Components. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản ex.a7.testbench, Oracle và expected của ví dụ. Trích dẫn; nguồn đã đọc toàn văn.
- 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 nguyên bản ex.a7.testbench, Thực nghiệm nguyên bản. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, testbench language and system task semantics. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Thí nghiệm nguyên bản ex.a7.testbench, Source, assertions và verification.json của TB nguyên bản. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Procedural timing; assignments; equality; simulation control tasks. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Verilog Testbench — bản chụp trong resources.zip, What is a Verilog testbench?; Verilog Testbench Components. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản ex.a7.testbench, counter.sv, tb_counter.sv và verification.json. Trích dẫn; nguồn đã đọc toàn văn.