David Brown said:
Fair enough - I was not thinking of such situations. But thinking about
these as parallel assignments would make it clear that this
is not a simple case.
Fair comment.
I'm a relative newbie at VHDL myself (I've done a bit more Verilog), so I am
happy to be corrected. Do you have any other suggestings for models that
are simple enough to start with and are not too inaccurate ?
Let's start by limiting the problem to processes that have a
sensitivity list (and therefore no wait statements in the body),
and assignments that don't have an associated "after" delay.
(Note that these are some of the restrictions that you
must obey for synthesisable logic.)
Given these restrictions, I think it's easiest to say:
* Assignments to any given signal are executed in sequence,
so that only the last-executed of any such assignments will
take effect.
* Signals are not immediately updated by assignments to them;
instead, the signals have a steady value whilst the process
executes. When all processes have finished executing at any
given moment of simulation time, ALL signals are updated
with the values that have been newly assigned to them.
I know that's not a short description, but it's reasonably
accurate and I think it's fairly clear and unambiguous.
The critical insight is the distinction between signal
ASSIGNMENT, which is instantaneous and is executed in the
normal "software-like" flow of a process, and signal UPDATE
which doesn't happen until all processes have halted because
they're waiting for their sensitivity lists or a wait statement.
This two-stage simulation cycle guarantees that all processes
see consistent values on all signals. It implies that each
signal has not only its current value that you can read, but
also a projected value that will be used in the future to
update the signal. Assignment modifies the projected value,
not the current value. (The "projected value" is actually
quite a lot more complicated than that, because it is
really a list of time/value pairs describing the scheduled
future behaviour of the signal, but we'll let that pass!)
In the special (but very important) case of clocked processes,
you can reasonably think of it in a slightly simpler way:
* Whenever you USE the value of a signal, you see its value
as it was at the moment of the clock edge;
* Whenever you ASSIGN to a signal, you are specifying the
new value the signal will take just after the clock edge.
I guess if you had said "signals are UPDATED in parallel"
instead of "signals are ASSIGNED in parallel", then you
would not have triggered my dodgy-assumptions alarm!
If you allow delayed signal assignments such as
Q <= D after Tco;
then things are a bit more complicated and you will need to
learn the full details of inertial delay.
If you use a process with no sensitivity list, for example
in a test bench, then you run the risk that a signal's
value will change during the life of a process. However,
it can change only during the execution of "wait" statements.
Life is still sane.