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

From: Stuart Sutherland <stuart_at_.....>
Date: Mon Dec 05 2005 - 22:26:32 PST
Nasim,

There is another important difference between always_comb, and always @*.
The always_comb triggers once at simulation time zero, to ensure that at
time zero the combinational logic outputs correspond to the combinational
logic inputs.  An always procedural block will not trigger until something
in its sensitivity list changes, which might not occur until long past time
zero.  Until that first input change occurs, the combinational output values
of an always @* block will not reflect the input values of the block.  This
problem becomes a real issue when using SystemVerilog 2-state types.

The following example from my training course illustrates the problem.  I
use this example to teach both the importance of always_comb, and the
importance of using 4-state enumerated types.

I'll let you run the simulations to see the problem.

------------------------
module controller (output logic  read, write,
                   input  wire   clock, resetN);

  enum {WAIT, LOAD, STORE} State, NextState;

  always @(posedge clock, negedge resetN)
    if (!resetN) State <= WAIT;
    else State <= NextState;

//  always @(State)   // SYNTACTICALLY CORRECT, BUT WON'T WORK IN SIMULATION
  always @*         // SYNTACTICALLY CORRECT, BUT WON'T WORK IN SIMULATION
//  always_comb       // SYNTACTICALLY CORRECT, AND WORKS IN SIMULATION
    case (State)
      WAIT:   NextState = LOAD;
      LOAD:   NextState = STORE;
      STORE:  NextState = WAIT;
    endcase

  assign read  = (State == LOAD);
  assign write = (State == STORE);

endmodule: controller

module test;
  wire  read, write;
  bit clock=1, resetN=1;

  controller dut (.*);

  initial begin
    forever #5 clock = ~clock;
  end

  initial begin
    @(negedge clock) resetN = 0;
    @(negedge clock) resetN = 1;
    repeat (10) @(negedge clock) ;  // run 10 clock cycles
    $finish;
  end

  initial begin
    $monitor("At %0d: dut.State = %s (%0b)", $time, dut.State.name,
dut.State);
  end
endmodule: test
-------------------------

Stu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Stuart Sutherland                      Sutherland HDL, Inc.
stuart@sutherland-hdl.com              22805 SW 92nd Place
+1-503-692-0898                        Tualatin, OR 97062

Training engineers to be Verilog and SystemVerilog wizards!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  

> -----Original Message-----
> From: owner-sv-bc@eda.org [mailto:owner-sv-bc@eda.org] On 
> Behalf Of Nasim Hussain
> Sent: Monday, December 05, 2005 3:03 PM
> To: sv-bc@eda.org
> Subject: Re: [sv-bc] @* vs. always_comb
> 
> ummm... sorry for making this reply too long...
> 
> it's just a personal opinion, but if i were to choose from these 7 :
> 
> 	(1) initial
> 	(2) always
> 	(3) always_comb
> 	(4) always_ff
> 	(5) always_latch
> 	(6) always @*
> 	(7) final
> 
> 
> i am *ONLY* going to advise users to use 1, 2 & 3, and that is it.
> i have no need for 4, 5, 6 & 7.
> 
> 
> to model an asynch. resettable FF (for behavioral code) -
> 
> 	always @(posedge clk or posedge reset) begin
> 		if (reset) q[(SIZE - 1):0] <= {SIZE {1'b0}};
> 		else q[(SIZE - 1):0] <= d[(SIZE - 1):0];
> 	end
> 
> is as good as it can get. it's simple, concise and reflects the actual
> intent of what i need for the tool to do. no need for it to 
> do any kind
> of checking, it needs to know all that it needs to know from 
> what i have
> given or specified.
> 
> 
> i find
> 	always_ff @(posedge clock iff reset==0 or posedge reset) begin
> 		...
> 		...
> 		...
> 	end
> 
> 
> confusing and serves me no real purpose. again, a personal opinion.
> just don't make assignments to the same variable from *different*
> procedural blocks. i am sure you all know that.
> 
> 
> same deal with latches. for example, all i need for an asynch.
> resettable LATCH is -
> 
> 	always @(d or posedge clk or posedge reset) begin
> 		if (reset) q[(SIZE - 1):0] <= {SIZE {1'b0}};
> 		else if (clk) q[(SIZE - 1):0] <= d[(SIZE - 1):0];
> 	end
> 
> 
> i have absolutely no need for always_latch. yes, it might save me from
> typing in a few extra words, but i think that is it. as a 
> rule: we never
> use blocking timing controls inside sequential elements.
> 
> 
> also, i am not sure when and where always_ff and always_latch 
> fires, but
> i am speculating it must be within the *active* slot, along with it's
> gazillion other friends. my understanding (hopefully not 
> flawed) is that
> all of
> 
> 
> 	(3) always_comb
> 	(4) always_ff
> 	(5) always_latch
> 
> 
> will happen AFTER the "initial" (w/ blocking timing control) and
> "always" blocks... meaning somewhat at the end of the active slot, but
> before the beginning of the inactive slot ?
> 
> 
> till today, i don't fully comprehend all of the intricacies associated
> with using "always @*" and consequently, i have maintained my distance
> from it. "inferred" sensitivity lists aren't big on my plate. 
> telling a
> tool to be automatically sensitive to ALL the signals that it believes
> it read within a procedural block - to me, that is a risky 
> game. most of
> the time, you want ALL signals on the RHS of assignments + signal
> enables within the conditional if-else-if statements, but ...
> 
> 
> ... that said, i believe using SV's always_comb might be of some
> benefit, despite it being somewhat of an older, but wiser brother to
> "always @*". always_comb (if it fires AFTER initial and always blocks)
> can be useful to catch changing signals at time 0 (kind of similar to
> C/C++'s do-while loop where it is guaranteed to execute at 
> least once).
> 
> 
> 
> finally, i have absolutely no need for the "final" block.
> 
> 
> my conclusion - for me (can't speak for other people) -
> 
> 	(1) initial			YES, of-course!
> 	(2) always			YES, of-course!
> 	(3) always_comb			USE, but judiciously!
> 	(4) always_ff			NOT necessary!
> 	(5) always_latch		NOT necessary!
> 	(6) always @*			NO!
> 	(7) final			NEVER!
> 
> 
> thanks.
> -nasim
> 
> 
> -- 
> ----------------------------------------------------------------------
> Nasim Hussain           | Life is short,   ---     _ o     _~o     _ o
> UltraSPARC Verification |   go wherever  ----    _`\<,   _`\<,   _`\<,
> SUN Microsystems, Inc.  |     you want...  ---  ( )/( ) ( )/( 
> ) ( )/( )
> work - (408) 720-4927   |
> home - (650) 967-7730   |
> 
> 
> 
Received on Mon Dec 5 22:26:46 2005

This archive was generated by hypermail 2.1.8 : Mon Dec 05 2005 - 22:27:03 PST