Bài này sẽ phân tích chi tiết mô hình mô phỏng sự kiện của System Verilog trên một ví dụ cụ thể. THam khảo lại các bài trước bài 1, bài 2 và bài 3.
Như đã trình bày trong các bài trước về mô hình mô phỏng sự kiện. System Verilog thêm nhiều cấu trúc mới để hỗ trợ xây dựng các mô hình mô phỏng và kiểm tra nên mô hình mô phỏng sự kiện cũng được cải tiến để tránh sự chạy đua giữa thiết kế RTL và các cấu trúc mới này.
Bỏ qua các vùng sự kiện PLI Pre-Active, Pre-NBA, Post-NBA, Pre-Observed, Post-Observed, Pre-Re-NBA, Post-Re-NBA và Pre-Postponed, chúng ta có sơ đồ đơn giản về các vùng sự kiện như hình 1.
Hình 1: Mô hình mô phỏng sự kiện của System Verilog trong mối liên quan đến các phát biểu của System Verilog (bỏ qua một số vùng PLI) |
program chk (clk, rst, ctrl, syn0, ctrl_out);
input clk, rst, ctrl, syn0, ctrl_out;
initial begin
$monitor ("[%d] ctrl_out = %b", $time, ctrl_out);
#8 $display ("[%d] END", $time);
end
chk_syn0: assert property (@ (posedge clk) (~rst & ~syn0 & ctrl) |-> ##1 syn0)
$display("[%d] Assertion PASS", $time);
else
$display("[%d] Assertion FAIL", $time);
endprogram
module event_sim;
reg clk;
reg rst;
reg ctrl;
wire ctrl_out;
reg syn0, syn1;
always @ (posedge clk) begin
if (rst) begin
syn0 <= 1'b0;
syn1 <= 1'b0;
end else begin
syn0 <= ctrl;
syn1 <= syn0;
end
end
assign ctrl_out = ~syn1 & syn0;
initial begin
clk = 0;
rst = 1;
ctrl = 0;
#2
rst = 0;
#2
ctrl = 1;
end
always #1 clk = ~clk;
chk chk (clk, rst, ctrl, syn0, ctrl_out);
endmodule
Code trên đây gồm một module và một program, trong đó module event_sim gọi program chk bên trong.
Code này gồm 1 khối always lấy mẫu tín hiệu ctrl theo clock clk qua 2 FF là syn0 và syn1. Phát biểu ctrl_out sẽ tích cực mức “1” trong 1 chu kỳ nếu xuất hiện cạnh lên ở ctrl thông qua phát biểu assign.
Khối initial trong module sẽ khởi tạo giá trị đầu cho các tín hiệu clk, rst và ctrl. Ban đầu, rst được gán bằng 1 để reset syn0 và syn1. Sau 2ns, rst = 0 và sau 2ns kế tiếp ctrl được lái bằng 1 để tạo cạnh lên trên ctrl.
Một khối always khác trong module dùng để tạo clock có chu kỳ là 2ns bằng cách lấy bù clk sau mỗi 1ns.
program chk được gọi, các tín hiệu trong module sẽ được kết nối đến các tín hiệu của program vì trùng tên (như cách gọi module). Program có hai nhiệm vụ chính là:
- Giám sát trạng thái tín hiệu ctrl_out bằng lệnh $monitor. Cứ mỗi lần ctrl_out chuyển trạng thái, một thông điệp sẽ được in ra báo thời điểm chuyển trạng thái và giá trị mới của ctrl_out. Sau 8ns, thông điệp END được in ra và quá trình mô phỏng kết thúc. Chú ý, block initial trong program sẽ tự động gọi task $finish đểkết thúc quá trình mô phỏng khi nó hoàn thành tất cả các phát biểu bên trong nó.
- Sử dụng một phát biểu assert để kiểm tra “syn0 phải bằng 1 tại cạnh lên của clock sau khi ctrl chuyển trạng thái từ 0 sang 1”. Nếu đúng, thông điệp “Asertion PASS” được in ra, nếu sai, thông điệp “Assertion FAIL” được in ra.
Các thành phần trong program và module sẽ có vùng thực thi khác nhau như sau:
- Các thành phần trong module thực thi trong tập vùng Active
- Các thành phần trong program thực thi trong tập vùng Reactive
Hình 2: Vùng thực thi của các phát biểu trong module và vùng thực thi program |
Hình 3: Vùng thực thi của các phát biểu trong program |
Khi chạy mô phỏng với module top là event_sim các process sau được sinh ra:
- Process initial 1 (sinh ra do program chk được gọi trong module event_sim)
- Process always 1
- Process assign
- Process initial 2
- Process always 2
và một assertion đồng thời (sinh ra do program chk được gọi trong module event_sim).
Quá trình mô phỏng của đoạn code minh họa được thể hiện trong các hình sau đây theo từng khe thời gian.
Hình 4: Các process và assertion sinh ra khi chạy mô phỏng |
Hình 5: Khe thời gian T=0 và T=1 |
Hình 7: Khe thời gian T=4 và T=5 |
Hình 8: Khe thời gian T=6 và T=7 |
Hình 9: Khe thời gian T=8 |
Kết quả chạy mô phỏng được thể hiện trên terminal và waveform với phần mềm QuestaSim như sau:
# [0] ctrl_out = x
# [1] ctrl_out = 0
# [5] ctrl_out = 1
# [7] Assertion PASS
# [7] ctrl_out = 0
# [ 8] END
# 1
# Simulation stop requested.
Hình 10: Waveform của ví dụ trên QuestaSim |
Qua ví dụ này, chúng ta có thể thấy sự khác nhau giữa việc dùng module và program. Tuy việc sử dụng module vừa có thể mô hình một thiết kế (RTL code) và vừa mô hình các thành phần mô phỏng (verification code) nhưng nếu bạn viết các testbench mới hoặc xây dựng môi trường mới thì nên dùng program để mô tả các thành phần mô phỏng. Điều này sẽ giúp tránh sự chạy đua giữa code thiết kế và code mô phỏng vì các thành phần trong module được thực thi ở tập vùng Active, còn program được thực thi ở tập vùng Reactive.
0 bình luận:
Đăng nhận xét