Saturday, January 18, 2020

Emulating old tech in an FPGA

When I started this project I had a couple of goals. The first was to learn about CPLDs and FPGAs, and how they were programmed using HDLs like Verilog and VHDL. My second was to understand how the i4004 CPU functioned internally, and recreate one in an FPGA. Somehow this second goal morphed into a third goal, which was to build an i4004 CPU from discrete components.

But my prime focus has always been on the learning, not on producing a result.

NOR gate
Inverter
To emulate an i4004 CPU in an FPGA I had to map the 1971 design into 2012 technology. Some bits were easy, as I was already familiar with RTL -- Resistor-Transistor Logic -- and this is basically RTL using MOSFETs instead of bipolar transistors. For example, one of these pictures shows the basic logical building block: an inverter constructed from one resistor and one transistor. If the transistor's gate is low the resistor pulls the output high, and if the gate is high the transistor turns on and pulls the output low. Pretty quickly I identified other basic logic functions such as NOR gates (pictured) and NAND gates.

Dynamic Latch
Initially, though, this little bit of circuitry from the state generator confused me. The transistor and resistor in the middle obviously form an inverter, but the other two transistors weren't connected in the familiar common-source configuration. Eventually I realized these were transmission gates: when the gate is high the circuits on the two sides of the transistor are electrically connected, but when the gate is low they are disconnected. But what was the purpose of disconnecting the gate on the inverter transistor?

Eventually it occurred to me that a MOSFET's gate is basically a capacitor, and capacitors hold a charge when they're disconnected. By turning on the transmission gate the inverter would respond to the signal on the other side of the transmission gate, but once the transmission gate was turned off the inverter would hold that state regardless of what happens to the signal on the other side of the transmission gate. This combination becomes a latch, so-called because it latches the state of its input. In the real world the charge on a capacitor leaks down over time, so this isn't like a flip-flop that will hold its state as long as there is power, but it will hold long enough for the purposes at hand. Thus this is a dynamic latch because you have to keep things moving at some minimum speed.

Logic in a modern FPGA is all static. That is, it will hold its state as long as power is applied. So how would I map this dynamic latch onto an FPGA? Verilog defines primitives for this purpose: the transmission gate is a tranif1 and the net it drives is a trireg. Unfortunately none of the Verilog simulators I have access to support these primitives, nor do FPGAs. So I considered using a transparent data latch, an FPGA component which would work in place of most of the i4004's transmission gates.

When I tried using latches, though, the tools spit warnings at me. I learned that the use of latches is strongly frowned upon, as they usually result from coding errors and apparently can make it hard for the tools to reach timing closure. So the version of the i4004 CPU I published on OpenCores uses edge-clocked flip-flops instead.

The problem with using edge-clocked flops is that the design of the i4004 expects signals to flow through several groups of logic while the clock signal holds the transmission gates open, and an edge-clocked flop only allows the signal to pass one group per rising clock edge. The Digilent Spartan-3E Starter board has a 50 MHz external clock oscillator, so I used that to clock my flops and used the MCS-4 CLK1 and CLK2 signals as clock enables. Thus for every 400ns clock enable period there were 20 rising clock edges. As long as no signal needed to propagate through more than 20 transmission gates in a single MCS-4 clock period, this scheme would work.

Higher-speed clocks result in higher power consumption, so I used a 20 MHz clock on my P170-DH replacement board. However, this results in only 8 rising clock edges during a 400ns MCS-4 clock period and I don't know if that's enough.

One option is to raise the clock frequency from 20 MHz to 50 MHz, either by replacing the oscillator or using one of the digital clock managers (DCM) in the Spartan-6. Instead I'm thinking strongly about replacing the clocked flops with transparent latches and filtering the warnings. That's what I've been doing with my i4002 RAM emulation. I'll have to see how well this works in the i4004 CPU.

2 comments:

  1. RTL means « Register Transfer Level » ^^

    ReplyDelete
    Replies
    1. That's one meaning for RTL. It also means "Resistor-Transistor Logic", as I stated.

      Delete