RE: [sv-bc] @* vs. always_comb

From: Clifford E. Cummings <cliffc_at_.....>
Date: Tue Dec 06 2005 - 11:32:11 PST
Hi, All -

Arturo replied to my recent post with some good points and I know there is 
a lot of caution at some companies regarding X-optimism and X-pessimism.

See Arturos great reply below, and then I have added more notes below 
Arturo's, just because I am not crazy about the ?: usage inside of always 
blocks.

At 07:25 PM 12/5/2005, Arturo Salz wrote:
>Cliff,
>
>I agree with everything you wrote. Your coding examples that may are
>still prone to simulation/synthesis mismatches. BTW I'm not blasting
>this reply to the reflector; I'll let you decide whether to share this
>or not.
>
>The resettable FF should be:
>      always_ff @(posedge clk or posedge reset)    q <= reset ? '0 : d
>
>The problem with your (i.e. the typical) code:
>
>      always_ff @(posedge clk or posedge reset)
>        if (reset) q <= '0;
>        else       q <= d;
>
>is that when reset is X or Z, the above functions correctly as a latch
>(q <= d) when in fact it should not --- I saw this problem in a design
>that simulated correctly and was found to have a bug that was discovered
>after manufacture. Since the problem was in the reset circuitry, the
>entire design was rendered useless and had to be re-spun.
>
>Ditto, for the level-sensitive latch:
>
>      always_latch
>        if (reset)    q <= '0;
>        else if (clk) q <= d;
>
>Should be done as:
>
>      always_latch  q <= reset ? '0 : (clk ? d : q);
>
>It may be a little know detail, but the "?" operator preserves X whereas
>if (or case) will cause simulation to make a deterministic decision
>based on a non-deterministic value, and synthesis cannot generate such
>hardware. These details largely go unnoticed until someone has a
>catastrophic failure. BTW, some formal tools will catch these types of
>problems but usually very late in the design cycle.
>
>         Arturo

Arturo's point are all well taken and perhaps the safest coding style would 
employ the style shown by Arturo.

I have personally never been bitten by clk-X or reset-X problems. They tend 
to cause more catastrophic failures that are easily traced back to the 
offend clk or reset problems; however, other if-else tests are more 
susceptible to X-optimism/pessimism and are not as easily identified.

I have two objections to the ?: notation:

(1) I don't think it is very clear unless one is used to the coding style. 
This of course is a personal preference.
(2) ?: only works with single-statement assignments unless one is prepared 
to use lots of concatenation. Since I frequently group together multiple 
similar register assignments in the same always_ff block, the ?: fails 
synthesis unless I am prepared to break up the assignments into multiple 
separate always_ff blocks.

That having been said, Arturo's comments are all valid.

Suggested SV enhancement?? Add "ifx" and "elsex" keywords that basically do 
$isunknown (^reduction) on the tested expression and if the resultant 
expression is X, make X-assignments to all variables enclosed within the 
ifx or elsex block. A similar capability would be useful on a case 
statement - BTW I don't care what the keywords are ultimately called. These 
would basically be if-else test with built-in assertions.

For now, perhaps the problem is better handled using assertions with my 
preferred coding style?

See the following testbench-register example with reset going to X and Z. 
You can run the example as is and see the effects that Arturo has 
described. You can recompile with +define+X_CATCH to see Arturo's solution 
in action, which does indeed show the problems more clearly. You can also 
recompile with +define+FATAL to see the $fatal action block stop the 
simulation on the first problem.

BTW - I know I have an interesting assertion problem in this example. It is 
hard to catch X's on the clk if the clk is the sample signal for the 
property. Perhaps Arturo has a suggested improvement.

`timescale 1ns/1ns
`define CYCLE 10
module tb;
   parameter SIZE=16;
   wire  [SIZE-1:0] q;
   logic [SIZE-1:0] d;
   logic            clk, rst_n;

   initial begin
     clk <= '0;
     forever #(`CYCLE/2) clk = ~clk;
   end

   register #(.SIZE(SIZE)) r1 (.q(q), .d(d), .clk(clk), .rst_n(rst_n));

   initial begin
     $timeformat(-9,0,"ns",10);
     $monitor("%t: q=%h  d=%h  clk=%b  rst_n=%b", $stime, q, d, clk, rst_n);
   end

   initial begin
                    rst_n <= '0;
                    d     <= '1;
     @(posedge clk);
     @(negedge clk) rst_n <= '1;
     @(negedge clk) rst_n <= 'x; // Make reset go to X
                    d     <= {SIZE/2{2'b10}};
     @(negedge clk) d     <= ~d;
     @(negedge clk) rst_n <= '1;
     @(negedge clk) rst_n <= 'z; // Make reset go to Z
                    d     <= {SIZE/4{4'b1001}};
     @(negedge clk) d     <= ~d;
     @(negedge clk) $finish;
   end
endmodule

module register #(parameter SIZE=8) (
   output logic [SIZE-1:0] q,
   input        [SIZE-1:0] d,
   input                   clk, rst_n);

   property check_clk_rst_Xs;
     @(posedge clk) !($isunknown({clk,rst_n}));
   endproperty

   ILLEGAL_CLK_RST_VALUES: assert property (check_clk_rst_Xs);
   `ifdef FATAL
                           else $fatal;
   `endif

   `ifdef X_CATCH
   always_ff @(posedge clk or negedge rst_n)
     q <= (!rst_n) ? '0 : d;
   `else
   always_ff @(posedge clk or negedge rst_n)
     if (!rst_n) q <= '0;
     else        q <= d;
   `endif
endmodule

Regards - Cliff

----------------------------------------------------
Cliff Cummings - Sunburst Design, Inc.
14314 SW Allen Blvd., PMB 501, Beaverton, OR 97005
Phone: 503-641-8446 / FAX: 503-641-8486
cliffc@sunburst-design.com / www.sunburst-design.com
Expert Verilog, SystemVerilog, Synthesis and Verification Training
Received on Tue Dec 6 11:33:38 2005

This archive was generated by hypermail 2.1.8 : Tue Dec 06 2005 - 11:34:31 PST