Thursday, September 12, 2019

[Design] Thảo luận 1 vấn đề trong thiết kế Verilog có thể gây sai function trong gate netlist


Tác giả: TrongTran
Ngày: 12/09/2019.
Cập nhật: 14/10/2019.


Trong đợt cập nhật trước thì mình đề cập đây là một lỗi syntax. Tuy nhiên, Có một anh đã góp ý cho mình rằng đây không phải là một lỗi syntax. Việc design như thế này là không gây ra lỗi. Tuy nhiên, chúng ta không khuyến khích design theo cách này. Vì logic out ra ngoài có thể không đúng với function. Mình đổi lại từ "lỗi" thành từ "vấn đề" để tránh nhầm lẫn (thật ra mình cũng không biết nên gọi bằng từ gì cho đúng).

Đây là một phương thức design mà một anh trong nhóm mình vô tình phát hiện khi tổng hợp gate từ verilog code.

Mình đã tiến hành kiểm nghiệm và thật ngạc nhiên là hầu hết các tool verify hiện nay đều không thể phát hiện được. Thậm chí là cả VCS (Synopsys), NCSIM (Cadence) và DC compiler (Tool tổng hợp gate từ RTL). Nếu DC compiler không thể phát hiện đã đành đằng này ngay cả tool check equivalent giữa gate và RTL cũng không thể phát hiện được (Formality).

Sau khi tiến hành kiểm tra thì mình phát hiện ra chỉ có 1 tool Spyglass của synopsys là có thể phát hiện được cách thiết kế này. Tuy nhiên, chúng ta thường bỏ qua những lỗi được report bởi tool này. Lí do là vì một design lớn thường xuất hiện cả trăm ngàn lỗi (Report bởi spyglass) và người confirm hầu như không thể phát hiện được lỗi nào là thật, lỗi nào có thể bỏ qua.


Đầu tiên mình nói đây là vấn đề liên quan đến việc chặp 2 output với nhau. Bạn sẽ nghĩ ngay đến một module như thế này:

module test (in_0, in_1, in_2, in_3, out);

   input in_0;
   input in_1;
   input in_2;
   input in_3;

   output out;

   wire out;

   assign out = in_0&in_1;
   assign out = in_2&in_3;

endmodule

Trường hợp trên ta có biến out được assign 2 lần.
Đây là một trường hợp phổ biến và chắc chắn là mọi tool đều có thể phát hiện được.

Tuy nhiên, có một trường hợp khác, Ta xét ví dụ như bên dưới:

module test_spyglass (clk, rst_n, in_0, in_1, in_2, in_3, out);

   input clk;
   input rst_n;

   input   in_0;
   input   in_1;
   input   in_2;
   input   in_3;
   output  out;

   reg     tmp_0;
   reg     tmp_1;
   wire    out;

   always @(posedge clk or negedge rst_n) begin
      if (!rst_n) begin
         tmp_0 = 1'b0;
      end else begin
         tmp_0 <= in_0;
      end
   end

   always @(posedge clk or negedge rst_n) begin
      if (!rst_n) begin
         tmp_1 = 1'b0;
      end else begin
         tmp_1 <= in_1;
      end
   end

   module_and_logic module_and_logic_00 (.in_0(in_2), .in_1(tmp_0), .out(out));
   module_or_logic module_or_logic_00 (.in_0(in_3), .in_1(tmp_1), .out(out));



endmodule

module module_and_logic (in_0, in_1, out);

   input   in_0;
   input   in_1;
   output  out;

   assign out = in_0&in_1;

endmodule

module module_or_logic (in_0, in_1, out);

   input  in_0;
   input  in_1;
   output out;

   assign out = in_0|in_1;

endmodule





Cấu trúc của code này như sau:






Hai submodule được gọi và 2 submodule này đều out ra cùng 1 tín hiệu đó là “out”.
Chỉ khác nhau 1 điểm đó là với module bên trên tín hiệu output là từ 2 submodule, còn như ví dụ ban đầu output từ một combinational logic trong module top.

Khi tổng hợp code verilog này thành gate nestlist, Ta sẽ có được 1 gate như sau:

module test_spyglass (clk, rst_n, in_0, in_1, in_2, in_3, out);

   input clk;
   input rst_n;

   input   in_0;
   input   in_1;
   input   in_2;
   input   in_3;
   output  out;

   reg     tmp_0;
   reg     tmp_1;
   wire    out;
   wire HINET_0, HINET_0;


DFF D0 ( .D(in_0), .CP(clk), .CDN(rst_n), .Q(tmp_0) );
DFF D1 ( .D(in_1), .CP(clk), .CDN(rst_n), .Q(tmp_1) );

   
 module_and_logic module_and_logic_00 (.in_0(in_2), .in_1(tmp_0), .out(HINET_1));


   module_or_logic module_or_logic_00 (.in_0(in_3), .in_1(tmp_1), .out(HINET_0));

AND (.A1(HINET_0), .A2(HINET_1), .Z(out) );

endmodule


module module_and_logic (in_0, in_1, out);

   input   in_0;
   input   in_1;
   output  out;

   AND (.A1(in_0), .A2(in_1), .Z(out) );

endmodule


module module_or_logic (in_0, in_1, out);

   input  in_0;
   input  in_1;
   output out;

   OR (.A1(in_0), .A2(in_1), .Z(out) );


endmodule

Như vậy là ta có thêm 1 cổng logic AND (Phần màu đỏ) để “and” 2 tín hiệu đó lại. Đây là lí do mà việc chạy để kiểm tra equivalence giữa RTL và gate lại không phát hiện được. Đây cũng là lí do mình nói function của bạn có thể bị sai. Tại sao ư ? Nếu bạn chỉ verify cho RTL và bạn dùng tool Formality để check equivalence giữa gate và RTL. Bạn tin tưởng rằng RTL của bạn đúng và FM pass. Không có bất kì hành động nào nhằm verify function cho gate. Tuy nhiên, Vấn đề sẽ trở nên nghiêm trọng hơn với việc sai fucntion trên gate.
Mình ví dụ, Đây là 2 tín hiệu out error cho fusa từ 1 IP đến module interrupt. 
Khi có error xảy ra nó sẽ toggle lên 1. Trong trường hợp chèn cổng AND. Tín hiệu chỉ toggle khi cả hai logic đều bằng 1. Điều này không đúng với mục đích function của chúng ta đó là interupt khi 1 trong 2 tín hiệu error toggle.

Tuy nhiên, Tool Spyglass của synopsys hoàn toàn có thể phát hiện ra lỗi này và báo như sau “Non-tristate signal 'test_spyglass.out' has multiple drivers”.

Như vậy, bạn cố gắn lưu ý cách design này để tránh nhé. Đặc biệt là với các bạn thích dùng tool VCS để mô phỏng.


Mọi người để lại comment để góp ý với mình hen. Cảm ơn ạ.

No comments:

Post a Comment

Cách tính BW và latency trong 1 hệ thống SoC sử dụng chuẩn giao tiếp AXI protocol

Tác giả:  TrongTran Ngày:  31/12/2019 Nếu bạn nào đang làm về verification cho system performance (ST) thì bài này sẽ bổ ích cho bạn. Ngày ...