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