Thứ Sáu, 11 tháng 5, 2018

[System Verilog] Mô hình mô phỏng sự kiện – phần 4: Ví dụ cho System Verilog

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 2bà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)
Chúng ta sẽ phân tích sự thực thi mô phỏng thông qua code ví dụ sau đây:
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 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).
Hình 4: Các process và assertion sinh ra khi chạy mô phỏng
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 5: Khe thời gian T=0 và T=1

Hình 6: Khe thời gian T=2 và T=3
Hình 7: Khe thời gian T=4 và T=5
Chú ý, kết thúc khe thời gian T=4, process initial 2 sẽ được loại bỏ vì tất cả các phát biểu của nó đã được thực thi.
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 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