Writing an integrated digital simulator including schematic capture, automatic netlist extraction and all associated facilities is probably an arduous task. On the other hand, once a netlist is available, a digital simulator core is a more manageable project. In the first instance, only the functional level will be implemented, not the behavioural (or even mixed) mode. A simple simulator is built upon the premise that ' circuits shall not be tested very close to their maximum operational frequency'.
This section contains the following parts:
Here are some imperative features of the netlist input preprocessor: Here are some sound input netlist checks:
Delays would be of little concern, were circuits purely combinatorial: They would simply imply a maximum operational speed for the circuit. However, as soon as some of the results have to be stored, the register latching them must wait for the data from the previous stage to become valid, before doing so. Data may be lost if the register delays too long, on the other hand, (and the design will not function as fast as it could, anyway.) When dynamic registers are involved, a minimum operational frequency is enforced upon the circuit, even if the remaining part of the design does not need such a high speed.
The simulator needs a data structure to hold the input netlist, that is, the node numbers to which each gate or module is connected: Thus each gate knows where to look for its input data, and where to place the results. (It may seem that this is just a copy of the netlist file, but macros must be collapsed to gatelists, and additional preprocessing may be needed. More importantly, the items in the file can only be examined sequentially, so the speed of access will be poor.)
There are about three ways to define input signals:
Here are the main simulation steps: Three levels of tolerance can be applied to nodes, if they have multiple outputs connected to them: Excessive data shall either be filtered, or ignored. Here are some reasonable output options:
Certain building blocks form the bulk of any digital design. Most of the time, it makes sense to simulate those at the behavioural level, not the gate level, (even if the former is not accessible to the user.) Here are some predefined modules:
Since the netlist is not automatically extracted, the program is incomplete . It is much faster to type in a netlist, if a labeled (paper) schematic is already available, than transfer the design to a computer using a CAD package. On the other hand, typing is boring and error- prone. It is ill- suited to people who have been justifiably used to the nice graphical interfaces of the last decade, or so. Any amount of time can be expended on the input interface.
Verifying, rather than hoping, that software components operate as expected, is surely a crucial factor to writing a successful suite. Yet, once the program has been tested, the simulator may not have to be blamed when the results occasionally appear 'weird'.
It may well be that the circuit is not operating as initially expected. It looks like this section has grown too long as it is. An example is clearly missing: A test- case circuit, together with input netlist and output waveforms will be presented in a future section.
Sensible options for the input preprocessor.
Essential input netlist checks.
These checks will prevent an input being substituted for an output, or vice versa.
They will not, however, stop an input being supplied for a different input (or an output for a different output.)
Delay models.
The duration of the widest pulse which will be suppressed by a gate defines its inertia delay. On the other hand, transport delay is the time difference between a change in an input signal and the corresponding transition taking effect on the output. Strictly speaking, the time for an output to rise, can be different from the time it needs to fall. It is important to calculate exact delay values when designs are operating near their maximum frequency.
On- chip, transport delay is basically proportional to the sum of inputs and outputs connected to the gate. For really fast chips, some wires become slower than gates. Then, the exact delay is not known until the subunits of the integrated circuit have been placed, and connections implemented by the autorouter. (You will be using a more sophisticated simulator long before that.)
Turning to sequential circuits, the input data must be sustained for a short time after the active edge of the clock signal, if it is to be stored reliably. This is known as the hold time. Some simulators even insist that data be stable for a small time interval prior to the active transition of the clock- that's the setup time. (A similar constraint is imposed upon the 'program enable' input.) Additionally, control inputs such as clock, clear, preset, program load, count and so on must persist for a minimum amount of time, or the state of the flip flops becomes undefined. There may be technology- dependent priority rules if several control inputs are excited at the same time.
Inertia delays, hold times and minimum control pulse widths are verified by performing timing checks. If a timing check fails, some of the logic values scheduled have to be deleted, as well as some of the future timing checks: Since a leading edge does not occur, there is no need to verify the timing of the trailing edge.
Many are the advantages of synchronous design, not least, that it results in circuits which are easy to understand and simulate. Unless the circuit is near its maximum speed, restrictions on sequential elements should be likely to be observed.
Data structures for digital simulator.
Here are some options:
This last option makes the program easily portable to any language- it looks like the preferred choice.
A similar data structure is used for the affected component list -ACL- (sometimes known as the fan- out list- FOL.) For each node, a list of the serial numbers of each gate or module, which has at least one of its inputs connected to the node, is compiled. When the logic level on the node changes, it is thus easily possible to find out which gates may be affected. Their output(s) will have to be evaluated again.
From the subsection on delays, it should be clear that node values are scheduled, rather than being applied to nodes immediately. A data structure is needed to hold that information in the meantime. In the first array of records, each record has the following fields:
The second array of records has the following fields:
(These data structures shall be collectively termed 'the event buffer' from now on. 'Event' here has the usual programming meaning, not the one in hardware description languages (HDL.)
The third array can be used as a stack to reserve and (later on, after records have been processed) to free slots for records. Slots (indices) are allocated from the top of the stack, and restored there, after the corresponding records have been read. The reason for needing this array, is that generally record slots will not be recovered in the same order they have been reserved (especially if modules, rather than just gates, are used.) This may look like a waste of space and time, since memory is plentiful nowadays. However, circuits have grown very large, too. This array can be omitted if only small circuits are going to be simulated: Addresses for records already processed are simply discarded, rather than retrieved for new use. The entire workspace can be reclaimed by the operating system at the end of the simulation. Sample code for asserting and relinquishing slots for records is in the fast fill routine section, which, by the way, now includes the improved version.
Records for timing checks are similar to records for values scheduled to be applied to nodes: Of course, the logic levels indicated are to be verified until the time mentioned, rather than being impressed upon the instant specified.
Additional data structures are needed for tristate nodes; these are discussed in the tristate section.
Describing input waveforms.
Boolean expressions take the following form :
Simulation process.
There are some clear timesaving steps here:
It looks as though half the processing can be evaded (much more for multi- bit counters and decoders) if events are only generated when the (future) logic level to be scheduled is different from the present value on the node . However, this is also like rushing out on thin ice. Simulation errors will escalate as soon as any module is provided with input data any faster than it can produce the results. (Why you would want to do this, I don't know. It can happen, though. For example, the gates driving the module inputs may need different times to switch to the low, or high, state.) Therefore, it is better to be safe than sorry. An event is generated even if the present and scheduled (future) state of the node are the same. If, at the time the new value is to be impressed, it is no different from the old value, the event is propagated no further.
Handling tristate or ambiguous nodes.
Being technology- dependent, this last option is probably best avoided.
Tristate modules conveniently arbitrate bus use without need for multiplexers. How to cope with unknown values on nodes? There may be some scope for claiming that, for example, once any input to an And gate is zero, the output will be zero- whatever the state of all the remaining inputs. This, however, is probably not what the designer intended (after the device has been reset), so it seems better to give a warning.
Slim are the chances for resolving the state of sequential circuits in the presence of uninitialised or vague inputs: (there is one exception to which the text will refer later under this subheading.) As soon as the clock, clear, set, program, count and so on input becomes undefined, so does the sequential element. Generally, the states of internal flip- flops in sequential blocks will be unknown at power- on; this implies that, for example, counters will not count until they have been reset or programmed. Shift registers, on the other hand, gradually shift out the ambiguous state as fresh data is clocked into them.
The only time, really, that unknown values are acceptable (after the device has been reset), is on data inputs when the clock is not active (while respecting hold times, and, possibly, set- up times.)
If at most one driver will assert a tristate node at any time, it is possible to get away just with storing the serial number of the driver last enforcing a logic level upon the node. It is then checked that this driver has switched- off before another device can drive the node.
If multiple outputs may drive a node at the same time, it probably easier to define a dummy node for each output. The logic levels on dummy nodes are combined, according to the rules at the beginning of this section, to resolve the eventual state of the node (or, maybe, to give an error message.) Whenever any dummy node is updated, the aggregate value must be recomputed.
Plausible output options.
The coarse mode is useful to detect logic faults, and some timing faults. Additional timing faults may appear near the maximum operational frequency. In that condition, the coarse mode becomes more of a liability, than an asset. The normal, fine mode, will be selected (but, at low frequencies, it is the detailed mode which will look more confusing.)
Basic library.
A library can become very detailed and extensive. Then its length is a considerable proportion of the simulator package size.
Drawbacks.
Not providing the behavioural mode to the user implies (among other things) that use cannot be made of several excellent automatic synthesis tools: These (on their own) generate a gatelist for the controller of a finite state machine, that is, the circuitry for present state outputs, and next state logic. However, finite state machines are arguably better implemented on a microcontroller board. Very high speed may not be needed. Ease of design, flexibility, and lower risk associated with design faults which must be rectified before the project is committed to production, seem to point towards the software implementation. This is also the cheaper option if the volume is not large.
Afterword.
For example, when both inputs to a symmetric Set- Reset bistable are asserted, then released at the same time, the simulation will show that the outputs are oscillating. This may not be obvious from an inspection of the truth table: Readers may concentrate on different input combinations, rather than sequences of those combinations, (which are far more numerous.)
Related future sections.
Some material had to be left out, though equally important: That includes testability analysis, submodule placement, autorouting, possibly by using Lee's algorithm, or heuristics, and fault simulation. (Part of the latter, admittedly, only applies to circuits of limited, and non- reconvergent, fanouts.)