The Timer Module

It’s finally time for the first in-depth analysis of a module! Logic module A2, the Timer, is responsible for almost all of the timing and synchronization in the computer. It’s broken down into three pages. Here’s the unmodified scans of the originals:

a02-1a02-2a02-3

 

 

 

 

As I mentioned in the Timing Overview, R-700 has a pretty good overview of what the Timer and Scaler modules do:

r700_fig3-3

And for reference, here’s what the clock divider at the heart of the Pulse Forming Divider Logic does:

logisim_divider

I’ll use the phase names from this example for this discussion.

The 2.048MHz clock generated by the computer’s oscillator (the CLOCK signal) enters this module and runs directly into a clock divider.

timer_clockdiv1

Above I’ve circled in red almost everything covered by the Pulse Forming Divider Logic block in fig. 3-3. Immediately of note is the fact that only two of the four phase control pulses are actually created here: PHS2 at the bottom, and PHS4 at the top. PHS3 is actually created in Module A24, INOUT VII.

timer_phs3

Since PHS3/ is the inverse of CT, we can treat CT and PHS3 as effectively the same thing.

That’s great and all, but PHS1 is absolutely nowhere to be found. Mapping the phase letters to phase control pulse names, we get:

PHS2 = C (blue wire)

PHS3 = B (olive wire)

PHS4 = D (magenta wire, with some extra sauce)

(Recall that the ordering of phases is A->C->B->D, so the apparent mismatch of PHS2 and PHS3 makes sense.)

The PHS4 logic is a bit more complicated than PHS2 or PHS3; rather than taking the D phase directly, it first inverts it and then NORs it with the A phase (green and magenta). The resulting signal is very similar to D, except in that it can’t overlap with A.

timer_phase_control_pulses

The simulator confirms that this brings down PHS4 a bit earlier than it otherwise would have been. The additional propagation delays incurred by this logic also keeps PHS3 (CT) and PHS4 from overlapping, which may or may not be important.

Anyways, we can pretty safely expect that PHS1 is the A phase of the clock divider (highlighted in magenta above). However, other than inhibiting the tail end of PHS4, the only thing the A phase does is run through an inverter to create RT. This creates a signal with 75% duty cycle… whose only inactive period is during PHS1.

The Clear, Write, and Read control pulses CT (Clear Time), WT (Write Time), and RT (Read Time) produced by this clock divider are the very same as those talked about in the section of R-700 I reproduced in the post on registers. Happily, it explicitly mentions what these signals should look like:

The CLEAR 2 pulse, that always occurs during the first half of WRITE 2, would have forced the flip-flop to the 0 state…. Thus the simultaneous occurrence of READ 1, WRITE 2, and the short CLEAR 2 pulses transfers the content of REG 1 to REG 2.

Sure enough, this is exactly what the simulator shows, which is pretty cool!

timer_rwc_pulses

It does leave open the question of what happens during PHS1, however. timer_phs1_gap

At this point all I can say for certain is that PHS1 is the only time during which register transactions are not happening.

Down below all of this is a very interesting little bit of logic.

ovfstb_pulser

I talked about this briefly in my post about open-sourcing everything, since it was the primary motivator for my addition of propagation delays to Logisim. Basically, this is a rising-edge-detector that emits a pulse on the rising edge of its input, which in this case is CT/. In other words, this circuit creates a short pulse as soon as Clear Time is over. Here’s what that looks like in Logisim:

prop_delays

The two rightmost NOT gates are used to control the duration of the pulse. Here, because there’s 5 gates in the loop driving OVFSTB/, the width of the pulse is 5 gate propagation delays. In the original AGC, the average gate delay was 20ns, so OVFSTB/ was low for somewhere around 100ns. There aren’t that many places that I’ve found in the computer so far where the gate propagation delay truly matters for the logic (thankfully), but this is one of the big ones. It’s somewhat likely that I’ll have to add in another couple of NOTs to widen the pulse in my replica.

Anyways, the underflow and overflow checks of the write bus happen while OVFSTB/ is low. This logic is pretty straightforward, and lives at the top of page 3 of the Timer module:

timer_overflow_checks

The Virtual AGC Assembly Language Manual section on the A register has a good little discussion about how this check works. Basically, it’s the main ‘modified’ feature of the Modified One’s Complement number system used in the AGC. Bits 16 and 15 are both sign bits, but during an overflow or underflow, only bit 15 will change. Bit 16 then is used as the sign for the result, meaning that the answer for any addition will at the very least have the correct sign. Furthermore, overflow and underflow can easily be detected by checking to see when bits 16 and 15 are not the same, which is exactly what is happening above.

Next up in the Timer is another clock divider circuit.

timer_clockdiv2

It’s driven by the inverse of phase D from the first divider, which is interesting in that it’s got a 75% duty cycle. Up until now I’ve only talked about what happens with 50% duty cycle square waves with these clock dividers; it hadn’t occurred to me to try anything else until I started simulating this module.

timer_cdiv_duty_cycle

Phases A and B are both long, while phases C and D are both short. And interestingly, FS and FS/ still have 50% duty cycle, although that feature isn’t used here.

In this clock divider, the shorter phases C and D are used to create two pairs of signals, RINGA/ and RINGB/, and ODDSET/ and EVNSET/. Even though each one of the four signals is 512kHz, the pairs taken together constitute the two 1.024MHz lines drawn from the Pulse Forming Divider Logic and the Ring Counter in figure 3-3. The only difference between the two pairs is that ODDSET/ is inhibited when the computer is in STOP mode, while RINGA/ and RINGB/ both continue ticking away happily.

RINGA/ and RINGB/ are used to drive the Ring Counter, which occupies the top half of the second page of the Timer.

timer_ring_counter

The operation of this circuit is pretty neat. Here’s what it looks like in Logisim:

timer_ring_counter

It pulls off the division by 10 by first setting each of 5 flip flops, and then starting over from the first, resetting each. The outputs of the ring counter are used for various lower rate timing things, but I haven’t dug into the details much yet.

In the timer module, the outputs are of the ring counter are combined in Strobe Pulse Generator gates to produce strobe signals. According to R-700, these are used “for phase and pulse length control of various interface timing pulses, roughly 3 μsec duration, at different positions within the basic 9.76 μsec interval of the 102.4kHz signal”.

timer_strobe_pulse_generator

Instead of having SB0, SB1, SB2, and SB3 as indicated by figure 3-3, we’ve instead got SB0, SB1, SB2, and SB4, plus an additional signal called EDSET. Here’s the simulator output for the ring counter and these signals:

timer_ring_counter_signals

Oddly, EDSET always stays low. Looking at only the signals that contribute to it, it appears to be impossible to reach during nominal operation.

timer_edset

It’s not even anywhere close enough to blame the difference on my shorter modeled propagation delays; there is always at least one input solidly high. My best guess is that it’s there to somewhat streamline initialization of the ring counter. During powerup, each of the five flip-flops in the ring counter will randomly hold a 1 or 0. They’ll eventually get synchronized as in the above GIF, but module A5, Cross Point Generator NQI, folds EDSET back into P03:

timer_edset_p03

Presumably, this catches an undesirable startup condition in the ring counter and forces P03 low, although I haven’t spent much time analyzing this.

The final bit of timing circuitry in the Timer module is the Time Pulse Generator. It takes up the entirety of the third page, and is pretty complex. I attempted to untangle it a little bit in my KiCad copy, which make it very slightly cleaner:

timer_time_pulse_generator

It’s implemented as a 12-bit shift register, and is driven forward by ODDSET/ and EVNSET/. Each of the twelve signals T01..T12 denotes one of the twelve time pulses that make up a Memory Cycle Time (MCT). Instructions are encoded as a series of sequences, and each sequence the computer can execute takes up one MCT. So in a sense, these pulses control which phase of microinstructions the computer is on out of each larger instruction.

Here’s what the signals look like:

timer_time_pulses

Note that even stages are NORed with EVNSET/ and odd stages are NORed with ODDSET, which results in non-overlapping time pulses. This is desirable to prevent sequence steps from interfering with one another.

Interestingly, the start of each time pulse is coincident with PHS1, with PHS4 filling the gaps between time pulses.

timer_time_pulse_phs1

Of course, this means that the time spent writing to registers each time pulse is quite short compared to the read and clear times:

timer_time_pulse_rcw

The write signal lasts throughout the PHS4 downtime, though. Presumably there’s enough time for everything to be safely written, but it’s surprisingly tight.

The other signals created by the time pulse generator are the T01DC/..T12DC/ signals. These are the overlapping versions of the time pulses (T11DC/ doesn’t exist):

timer_time_pulse_dc

And that’s about it for the timer module! The only things I didn’t cover are the start/stop logic, which will get its own post, and the first stage of the Scaler, which I’ll talk about with the Scaler module.

Leave a Reply

Your email address will not be published. Required fields are marked *