??? 10/16/07 19:54 Read: times |
#145820 - re: Simulator Question: ANSWER Responding to: ???'s previous message |
Russ,
Here's what's actually going on. You really need to understand the concept of "delta delays." In your example, you have a handful of non-blocking assignments, including an assignment to the signal sysClock. All of the non-blocking assignments are completed at the same time. That's the whole point of a non-blocking assignment. THEN the scheduler notices that the @(posedge clock) sensitivity list for the always block in Client evaluates to true. This means at the instant that the rising edge condition is met, the signals strobe and data are already stable at their new values, even though on the screen it looks as if they are asserted coincident with the clock edge. Of course the assignment to dataStore takes place immediately after the rising edge of the clock, using the new value of dataIn (data) on the right hand side, because in a functional simulation, clock-to-out time is zero. The assignment dataOut = dataStore + 1;is then evaluated immediately after dataStore gets its new value. Again, in a functional simulation, the prop delay through this combinatorial function is zero. So, the simulation is correct, according to the language rules. But what if you want to make the simulation look like you expect? Don't forget that the signals data and strobe are asynchronous to the signal sysClock. So you need to make sure that everything is synchronous. Do that in your server by changing data and strobe only after the rising edge of the clock: initial begin data <= 0; // note: do NOT assign sysClk here! strobe <= 0; @(posedge sysClock); @(posedge sysClock); @(posedge sysClock); @(posedge sysClock); data <= 1; strobe <= 1; @(posedge sysClock); strobe <= 0; @(posedge sysClock); @(posedge sysClock); @(posedge sysClock); data <= 2; strobe <= 1; @(posedge sysClock); strobe <= 0; #10 $finish; end // initial beginSimulate this, and you'll see the results you expect. What's the difference? strobe and data now change a delta delay after the rising edge of the clock, not coincident with it. So at that edge of the clock, the always @(posedge clock) statement sees inputStrobe false (it hasn't changed yet). Then strobe is deasserted one clock tick later, but again that deassertion takes place a delta delay after the rising edge of the clock. So, at that clock rising edge, strobe is true and the value of dataIn immediately before the rising edge is then assigned to dataStore, and that assignment is completed a delta delay after the rising edge. Does this make sense? This is vitally important. If you don't grok how the Verilog scheduler works, you'll always get bitten by it. Now, some people like to put a delay in an assignment's right-hand side: always @(posedge clk) q <= #1 d;This delay makes clear that there's a clock-to-out delay. This isn't necessary as it's really just a crutch to remind you that the clock-to-out delay exists. OK, some of you will say, "well, you're the guy who says to use parentheses because you don't want to remember the order-of-operations, but now you say, 'don't use the obvious delay for clock-to-out.' What gives?" Here's what gives: as long as all of your code has such a delay, you're probably OK. But mix in code that does not have these delays and you open up an ugly can of worms. All Verilog gurus advise against adding these sorts of visual delays. Good luck, -a |