Clocking block và skew: đọc mẫu nào, lái tín hiệu lúc nào?

Khoảng 45 phútMức 3/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 sampled clockvar và tín hiệu raw sau NBA
  • Tính thời điểm drive từ output skew có đơn vị rõ
  • Đọc bằng chứng #1step và #0 theo đúng phạm vi đã chạy

Cùng một cạnh, hai câu hỏi về giá trị

Một register lấy req ở posedge và cập nhật q bằng nonblocking assignment. Checker hỏi “q trước cạnh là bao nhiêu?” khác với “q sau NBA của cạnh này là bao nhiêu?”. Cả hai câu hỏi đều hữu ích, nhưng trộn câu trả lời sẽ làm một DUT đúng trông như chậm một chu kỳ hoặc làm scoreboard đi trước thiết kế.

Clocking block đặt tên cho một hợp đồng drive/sample quanh một clock event. Nó không đổi latency của DUT. Trước khi chọn skew, hãy viết checker muốn quan sát đầu vào của cạnh, đầu ra sau cập nhật, hay transaction của chu kỳ trước. Chọn mốc theo ý nghĩa kiểm thử, không theo giá trị tình cờ thấy trong một log.

Input của clocking block là phía testbench đọc

Trong interface timed_link, cb khai báo input q và output req. DUT phát q nên testbench đọc q; testbench phát req nên DUT đọc req. Hướng này nhìn từ người dùng clocking block, không sao chép tên input/output từ cổng DUT.

link.cb.q là clocking input đã lấy mẫu theo skew. link.q là tín hiệu raw tại thời điểm process đang đọc. Hai expression có thể khác nhau mà cả hai đều đúng. Main cố ý quan sát cả hai ở các mốc khác nhau để người học nhìn được sự khác biệt thay vì xem cb chỉ là tên dài hơn của interface.

[1]

Input #1step giữ giá trị ngay trước clock event

Main viết tường minh default input #1step output #2ns. Input #1step lấy mẫu ngay trước time slot của clock event, tương ứng giá trị vào Preponed; step gắn với độ chính xác thời gian mô phỏng, không phải một chu kỳ clock hoặc mặc định một nanosecond.

Ở cạnh 15 ns, q trước cạnh vẫn bằng 0, trong khi req đã bằng 1 từ 7 ns. Do đó cb.q đọc 0 còn q raw sau NBA bằng 1. Trong ví dụ register này, sampled q trông như kết quả của chu kỳ trước; không khái quát rằng mọi input #1step đều tạo thêm một register hoặc luôn trễ đúng một clock so với mọi tín hiệu khác.

[2]

Output #2ns đổi req sau cạnh hai nanosecond

Testbench đợi @(link.cb) rồi gán link.cb.req <= next_req. Với output skew 2 ns, req mới xuất hiện ở 7,17,27,37 ns sau các cạnh 5,15,25,35 ns. DUT tại cạnh 5 ns vẫn lấy req cũ bằng 0; req được drive ở 7 ns có thể được lấy ở 15 ns.

Skew không phải delay vật lý do simulator đo được. Chọn 2 ns chỉ làm hợp đồng của ví dụ rõ ràng khi period 10 ns; nó không chứng minh setup/hold hoặc thay constraints của STA. Ghi #2ns thay vì số trần giúp không vô tình đổi ý nghĩa khi timeunit của scope thay đổi.

Theo bốn cạnh bằng hai state của mô hình

Hai biến model_req và model_q ghi state trước cạnh. Sau mỗi lượt, model_q nhận req cũ và model_req nhận giá trị vừa drive. Oracle không đọc output DUT để cập nhật state dự kiến.

Cạnh ns req trước cạnh cb.q với #1step q sau NBA req ở cạnh+2 ns
5 0 0 0 1
15 1 0 1 0
25 0 1 0 1
35 1 0 1 0

Main kiểm cb.q tại event; ở cạnh+1 ns kiểm q đã cập nhật và req vẫn cũ; ở cạnh+3 ns kiểm req đã mới. Bốn check mỗi cạnh cho 16 check, kết thúc 38 ns. Bảng là dự đoán của mô hình, được self-check trong source, không phải waveform VCD được dựng lại.

Đổi input skew phải đổi ý nghĩa oracle

Probe riêng đổi input thành #0 và đối chiếu cb.q với q của cạnh hiện tại sau NBA: các mẫu dự kiến 0,1,0,1. Probe này đã chạy đạt trên tool hiện tại. Nếu chỉ đổi declaration thành #0 nhưng vẫn giữ oracle đòi mẫu #1step, checker phải báo sai; đó là kiểm hợp đồng, không phải yêu cầu hai skew cho cùng giá trị.

Default khi không ghi skew là input#1step/output#0 theo nguồn đào tạo, vẫn cần đối chiếu LRM chính thức. Main dùng explicit skews; PASS của main không tự chứng minh mọi default, inout, cycle delay hay clocking qua virtual handle. Đọc trực tiếp raw signal cũng không tự áp dụng skew của cb.

Clocking block không tự sửa mọi race

Nếu một process khác vẫn ghi trực tiếp req, clocking block không tự thu hồi quyền ghi của process ấy. Nếu scoreboard so sai chu kỳ, lấy mẫu có trật tự vẫn cho một kết luận sai. Cần giữ một writer theo hợp đồng, dùng đúng sampled value và đặt expected ở đúng transaction.

Nguồn training có lời hứa quá rộng “không bao giờ race”; ở đây chỉ claim bốn cạnh và các mốc được oracle kiểm. Một tài liệu khác trong ZIP ghi default input 0 và chỉ một block cho mỗi clock, mâu thuẫn với mô tả training còn lại; không dùng các khái quát đó để thay LRM. Bài vẫn draft/needs-spec-check.

16 check quanh bốn clock event

Expected trước chạy: CLOCKING CHECK edges=4 checks=16 input_skew=1step output_skew_ns=2 time_ns=38. Parse/simulate main đã đạt với Verilator; probe input#0 đúng oracle là bằng chứng riêng. Mutant đổi skew nhưng giữ hợp đồng cũ và mutant output#0 phải bị bắt, không nới checker để chúng xanh.

Clocking block và skew: đọc mẫu nào, lái tín hiệu lúc nào?

Expected tính trước chạy: CLOCKING CHECK edges=4 checks=16 input_skew=1step output_skew_ns=2 time_ns=38

tb.sv testbench
`timescale 1ns/1ps// Expected4edges,16checks,last at38ns. #1step samples old q; output #2ns changes req at edge+2.interface timed_link(input bit clk);  bit req=0,q=0;  clocking cb @(posedge clk);    default input #1step output #2ns;    input q;    output req;  endclockingendinterfacemodule capture(timed_link link);  always @(posedge link.clk)link.q<=link.req;endmodulemodule tb_clocking;  bit clk=0;  always #5 clk=~clk;  timed_link link(clk);  capture dut(link);  bit model_req=0,model_q=0,next_req;  int checks=0;  initial begin    for(int edge_no=0;edge_no<4;edge_no++)begin      @(link.cb);      if(link.cb.q!==model_q)$fatal(1,"clocking sampled old-q oracle");checks++;      next_req=(edge_no%2)==0;      link.cb.req<=next_req;      #1;      if(link.q!==model_req)$fatal(1,"clocking post-NBA q oracle");checks++;      if(link.req!==model_req)$fatal(1,"clocking before-skew req oracle");checks++;      #2;      if(link.req!==next_req)$fatal(1,"clocking after-skew req oracle");checks++;      model_q=model_req;model_req=next_req;    end    if(checks!=16||$time!=38)$fatal(1,"clocking accounting");    $display("CLOCKING CHECK edges=4 checks=16 input_skew=1step output_skew_ns=2 time_ns=38");$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: CLOCKING CHECK edges=4 checks=16 input_skew=1step output_skew_ns=2 time_ns=38

Chỉ 4 cạnh, explicit input#1step/output#2ns. Probe input#0 với oracle khác được kiểm riêng; không claim mọi default/clockvar/UVM hoặc timing vật lý.

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.

[3]

Tự kiểm tra

Tự kiểm tra: clocking

  1. Tại cạnh 15 ns trong main, cb.q với input#1step bằng bao nhiêu?
  2. Gán cb.req tại event 5 ns với output#2ns làm req đổi dự kiến lúc nào?
  3. Trong bài, #1step có nghĩa gì?
  4. Bốn check mỗi cạnh trên bốn cạnh cho bao nhiêu check?
  5. Probe input#0 đúng oracle đã chạy lấy dãy mẫu q nào?

Ghi rõ event, sample, drive và chu kỳ expected

Hãy review một clocking block bằng bốn mốc: event nào, input lấy từ trước hay sau cập nhật nào, output đổi khi nào và DUT sẽ nhận ở cạnh nào. Tách sampled clockvar khỏi raw signal. Khi đổi skew, cập nhật mô hình có chủ đích rồi chạy cả main và phản ví dụ; không sửa expected chỉ vì log mới nhìn thuận mắt.

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

  1. SystemVerilog Clocking Blocks Part 1 — bản chụp resources.zip, What Is a Clocking Block?; Direction Convention: A Common Source of Confusion; Basic Syntax; Declaring a Clocking Block Inside an Interface. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. SystemVerilog Clocking Blocks Part 2 — bản chụp resources.zip, Skew Syntax; The Special Case: #1step. Trích dẫn; nguồn đã đọc các mục liên quan.
  3. Thí nghiệm nguyên bản ex.b4.clocking, Source, self-checks, verification.json và timing/argument probes. Trích dẫn; nguồn đã đọc toàn văn.
  4. IEEE 1800-2023 SystemVerilog LRM, Clocking, program, stratified scheduling and simulation I/O — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
  5. SystemVerilog Clocking Block — bản chụp resources.zip, SystemVerilog Clocking Block; Clocking Skew — ghi nhận khái quát không dùng làm rule. Trích dẫn; nguồn đã đọc các mục liên quan.