Thursday, December 5, 2019

Thảo luận 1 lỗi mismatch bit width trong thiết kế verilog rất khó được phát hiện

Tác giả: TrongTran
Ngày: 05/12/2019


Trước đây mình có trình bày về 1 issue liên quan đến lỗi 2 output được connect vào 1 port.
Trong bài này, Đây là 1 bug mới mà một anh trong công ty mình tạo ra. Với hầu hết các lỗi liên quan đến mismatch bit width thì các tool sẽ phát hiện được. Nhưng lỗi này, Mình đã tiến hành kiểm tra bằng nhiều loại tool và kết quả là không phát hiện được.

Mình xét ví dụ nhỏ:





Trong ví dụ trên mình muốn các bạn đặt sự tập trung vào dòng nằm trong hình chữ nhật đỏ bên trên.
Function của module này cơ bản chỉ là:
  • 2 input XOR với nhau sau đó đi qua mạch 2 flip flop. 


Tuy nhiên, ở đây mình cố tình khai báo biến reg async_ff có 1 bit width. Điều này sẽ dẫn đến mismatch bit width vì biến result là 1 signal có 2 bit data. Như vậy mismatch bit width sẽ diễn ra tại dòng 31 và 32 trong hình trên.

Điều gì sẽ xảy ra?

Mình đã chạy hàng loạt các tool để kiểm chứng kết quả là:
  • VCS không warning cũng không error.
  • Cadence incisive không warning cũng không error.
  • Cadence xcelium không warining cũng không error.
  • Synthesis  không warning không error và formality vẫn pass.

Mọi thứ quá hoàn hảo để không phát hiện được issue này.
Bây giờ hãy thử kiểm tra function nhé:

Mình có 1 test bench như bên dưới:

module tb();
  
  reg [1:0] in_0;
  reg [1:0] in_1;
  wire [1:0] out;
  reg clk;
  
  
  initial begin
     clk = 1;
     forever #10 clk = ~clk;
  end
  
  top top_0 (.clk(clk), .in_0(in_0), .in_1(in_1), .out(out));
  
  initial begin
    #20;
    in_0 = 2'b00;
    in_1 = 2'b11;
    #20;
    in_0 = 2'b00;
    in_1 = 2'b00;
    #20;
    in_0 = 2'b11;
    in_1 = 2'b11;
    #20;
    in_0 = 2'b10;
    in_1 = 2'b11;
    #20;
    in_0 = 2'b10;
    in_1 = 2'b01;
    #20;
    $finish();
  end
    initial begin
         $dumpfile("dump.vcd");
          $dumpvars(0, tb);
     end  
endmodule

Và đây là waveform:


Vì kết quả bị delay 2 chu kì nên vòng xanh thứ nhất là input
in_0 = 2'b00;
in_1 = 2'b11;

Nếu in_0 ^ in_1 = 2'b11;
Thực tế kết quả là 2'b01.
Biến mismatch đã được fix giá trị 0.
Các bạn có thấy lạ không. Vì rõ ràng là biến result tại dòng 13 đã được gán 
result = in_0 ^ in_1;

nên giá trị phải là 1 chứ nhỉ ? và giá trị out[1] không bị delay 2 chu kì như out[0] vì out[1] không qua 2 flip flop do mismatch bit width ?

Không phải nhé, Thực ra giá trị out[1] = 0 là chính xác đấy. Lí do chỉ có out[0] được gán tại dòng 32, còn out[1] không được gán giá trị nên sẽm ang giá trị 0. Biến result khác out nhé.

Như vậy check function sẽ phát hiện được lỗi này.
Thế nhưng bạn có chắc bạn check đủ case cho nó. Mình vừa đối mặt issue này bởi signal sai là signal STROBE trong kênh W channel.
Thường thì chúng ta không verify đủ case của tín hiệu này. Ví dụ: 

WDATA có 64 bit bạn phải check đủ các case cho tín hiệu 0f, ff.....
Hãy thận trọng.

Gate netlist cũng sẽ fix 0 cho tín hiệu gán thiếu như bên dưới:

module top (clk, in_0, in_1, out) ;
    input  clk ;
    input  [1:0] in_0 ;
    input  [1:0] in_1 ;
    output [1:0] out ;

    wire net_2 ;
    wire net_1 ;
    wire result ;
    wire FLT_1 ;
    wire FLT_2 ;

    sub_top_0 sub_0 (.clk(clk), .result({FLT, result}), .out({FLT, net_1}));


    XOR2 xor_0 (.A1(in_0[0]), .A2(in_1[0]), .Z(result));
    BUFF buf_1 (.I(1'b0), .Z(net_2));
    BUFF buf_2 (.I(net_2), .Z(out[1]));
    BUFF buf_3 (.I(net_1), .Z(out[0]));

endmodule


module sub_top_0 (clk, result, out);
    input  clk;
    input  [1:0] result;
    output [1:0] out;

    wire [0:0] async_ff;

    DFF dff_1 (.D(async_ff[0]), .CP(clk), .Q(out[0]));
    DFF dff_2 (.D(result[0]), .CP(clk), .Q(async_ff[0]));
endmodule


Thế thì spyglass có phát hiện lỗi này. Câu trả lời là có mà là WARNING ???????
Bạn sẽ nhận được mã sau:

RP_UnmatchWidth    4.4.1(3)       Warning     top.v    31      10    Bit width of LHS does not match with RHS on the assignment
RP_UnmatchWidth    4.4.1(3)       Warning     top.v    32      10    Bit width of LHS does not match with RHS on the assignment

Nhưng với một design lớn. Có hàng ngàn mã lỗi như vậy. Vì sao? Một số case như sau:

wire [3:0] b;
assign b = 0;

Vâng, Cái này nó cũng warning y như cái trên đấy. Còn một vài case nữa nhưng mình ko tiện nêu ra. Do đó không phải dễ để tìm ra lỗi này. Hãy thận trọng confirm tất cả error dạng này nhé.
Qua 2 issue mình nêu bạn sẽ thấy sức mạnh của tool spyglass từ synopsys mạnh như thế nào. Hãy tận dụng nó một cách có hiệu quả, bạn sẽ tránh được các issue không đáng có.

Mọi góp ý về issue này hãy call cho mình nhé: 0339339692.

Code ví dụ cho bạn nào muốn trial lại:

module top (clk, in_0, in_1, out);
    input [1:0] in_0;
    input [1:0] in_1;
    output [1:0] out;
    input clk;

    wire [1:0] out;
    wire [1:0] result;

    sub sub_0 (.clk(clk), .result(result), .out(out));
    assign result = in_1 ^ in_0;
endmodule

module sub (clk, result, out);

   input clk;
   input [1:0] result;
   output[1:0] out;
   reg [0:0] async_ff;
   reg [1:0] out;


   always @(posedge clk) begin
         async_ff <= result;
         out <= async_ff;
   end
endmodule







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 ...