Wednesday, July 15, 2020

Fixing combinational loops

As part of the conversion from edge-clocked flip-flops to transparent data latches I re-coded my i4004 counter module. This resulted in several warnings about combinational loops, but those warnings were buried in a sea of warnings about my use of data latches. It seemed to work well enough when implemented for the Spartan-3E, and I assumed it would work well enough on the Spartan-6.

I was wrong.

The first indication was the trouble I had with the synchronized Power-on Clear (POC) signal. In the real i4004 chip, this is implemented as a simple RS flip-flop constructed from four transistors and two resistors forming two NOR gates. The external POC_PAD signal sets the flip-flop and the A12 signal resets it, with the POC_PAD input having priority. I coded this behaviorally, using assign statements for the two NOR gates. This worked in behavioral simulation and in the Spartan-3E, but not the Spartan-6.

When working with an FPGA, you're wiring together a set of primitive hardware elements. These elements are documented in the Libraries Guides, and these are specific to the model FPGA. While the Spartan-3E Libraries Guide (UG617) documents the existence of a flip-flop primitive with both asynchronous preset and clear, the equivalent guide for the Spartan-6 (UG615) does not. The Spartan-6 flip-flop can have either an asynchronous preset or an asynchronous clear, but not both.

To fix the POC problem I re-coded the POC synchronizer to infer a clocked flip-flop, with the D input grounded, the clock input driven by the A12 signal, and the asynchronous preset driven by the external POC_PAD input. As long as the POC_PAD input is asserted the internal POC output is also asserted. When POC_PAD is deasserted the POC output remains asserted until the next rising edge of A12. This eliminated the warning about incompatible primitives, but left seven other warnings about combinational loops.

Running a post-place and route simulation indicated that the counters in the instruction pointer had indeterminate ("X") output values. This seemed a good place to start. After a few failed attempts at quick fixes, I re-coded the counter using two edge-clocked flip-flops to represent the master-slave behavior of the original circuit. I considered using latches, but I believe this would result in a race condition. In the i4004 use, the inputs to the first stage of a multi-stage counter are non-overlapping. However, the inputs to the second (and third, in the case of the refresh counter for the scratchpad array) counter are merely the true and inverted forms of the same signal. If there is any overlap in these signals, there could be oscillation. The characteristics of the i4004 hardware prevent this, but I can't make that guarantee in an FPGA. Using edge-clocked flip-flops avoids this.

This change has resolved the combinational loop warnings, and the post-P&R simulation now shows sane counter outputs. However, that has not enabled the i4004 CPU to run.

One step at a time...

No comments:

Post a Comment