I'm currently redesigning the signal propagation algorithm of a circuit simulator I'm developing as a hobby project (https://www.antarescircuit.io).
In the new design, I'm trying to detect when conflicting signals are asserted to wires and issue a warning if this is the case. Now I get lots of warnings when simulating the famous MIC-1 machine according to "Structured Computer Organisation" by Andrew S. Tannenbaum. They originate from bus contention when reading register values from the CPU's scratchpad (aka register file).
The scratchpad circuit looks as follows:
The tristate buffers at the right side are supposed to control which register forwards its current value onto the CPU's B data path. The register is selected by 4-bit input "FB", whose value gets decoded by an 4-16 decoder.
The problem is that the decoder (like any combinational circuit) produces intermediate results due to propagation delays of the various logic gates it consists of. In the example above, register 6 is to be addressed, but for a short moment, the decoder sets more than one output line to "high".
The contention exists for 20 ns and is determined by one single gate delay. I've chosen this value for simulation because it seems to be in the range of typical real hardware gates. The signal then remains stable for at least 9'000 ns.
The root cause the contention is illustrated by the following snapshot of the decoder. The signals that run through the inverters take longer, and the output AND gates produce invalid intermediate results.
Note: The snapshot is taken from a test with a 3-8 decoder. The 4-16 decoder used in the scratchpad consists of two of them. And don't be confused by the "zero" bubbles at the AND's outputs. These are produced by the signal flow animation feature and represent the signals that are going to flow to the outputs with the next simulation cycle, thereby establishing the expected and correct output of the decoder.
The question is how conflicting signals at the outputs of tristate buffers can be avoided. I've considered the following options.
- Fine-tune timing: Add non-inverting buffers with the same propagation delay like the inverters to the decoder to make sure that all signals arrive at the AND gates at the same time. This makes the simulation work correctly, but looks to me like cheating, and I'm not sure if this would really eliminate the problem on real hardware, where you would face varying propagation delays due to fabrication differences of the logic gates.
- Synchronization: I understand that combinational logic generally produces intermediate results, and clocked circuits are generally used to deal with that. However, neither Tannenbaum in his book mentioned this problem when he explained the scratch pad, nor could I find information on the net that discusses whether it is legitimate to directly control tristate buffers with the output of combinational decoders. Trying to synchronize the output of the decoder would require significant change in the micro architecture of the CPU, probably involving the need to introduce another sub-clock signal.
- Ignore the problem: I could easily ignore the problem, as the simulated CPU circuit works fine despite the temporary bus contention. However, I'd like to do that only if my design of the scratchpad is reasonable, and it is common to ignore such short and temporary contention situations, even when running the circuit on real hardware. But since these situation, at least in my understanding, represent temporary "short circuits" on real hardware, I doubt that these are acceptable.
I'm more a software engineer than an electrical engineer and am therefore perhaps just not aware of a possibly obvious solution to my problem, so any help is appreciated.