Implementing FizzBuzz on an FPGA

I recently started FPGA programming and figured it would be fun to use an FPGA to implement the FizzBuzz algorithm. An FPGA (Field-Programmable Gate Array) is an interesting chip that you can program to implement arbitrary digital logic. This lets you build a complex digital circuit without wiring up individual gates and flip flops. It's like having a custom chip that can be anything from a logic analyzer to a microprocessor to a video generator.

The "FizzBuzz test" is to write a program that prints the numbers from 1 to 100, except multiples of 3 are replaced with the word "Fizz", multiples of 5 with "Buzz" and multiples of both with "FizzBuzz". Since FizzBuzz can be implemented in a few lines of code, it is used as a programming interview question to weed out people who can't program at all.

The Mojo FPGA board, connected to a serial-to-USB interface. The big chip on the Mojo is the Spartan 6 FPGA.

The Mojo FPGA board, connected to a serial-to-USB interface. The big chip on the Mojo is the Spartan 6 FPGA.

Implementing FizzBuzz in digital logic (as opposed to code) is rather pointless, but I figured it would be a good way to learn FPGAs.1 For this project, I used the Mojo V3 FPGA development board (shown above), which was designed to be an easy-to-use starter board. It uses an FPGA chip from Xilinx's Spartan 6 family. Although the Mojo's FPGA is one of the smallest Spartan 6 chips, it still contains over 9000 logic cells and 11,000 flip flops, so it can do a lot.

Implementing serial output on the FPGA

What does it mean to implement FizzBuzz on an FPGA? The general-purpose I/O pins of an FPGA could be connected to anything, so the FizzBuzz output could be displayed in many different ways such as LEDs, seven-segment displays, an LCD panel, or a VGA monitor. I decided that outputting the text over a serial line to a terminal was the closest in spirit to a "standard" FizzBuzz program. So the first step was to implement serial output on the FPGA.

The basic idea of serial communication is to send bits over a wire, one at a time. The RS-232 serial protocol is a simple protocol for serial data, invented in 1960 for connecting things like teletypes and modems. The diagram below shows how the character "F" (binary 01000110) would be sent serially over the wire. First, a start bit (low) is sent to indicate the start of a character.2 Next, the 8 bits of the character are sent in reverse order. Finally, a stop bit (high) is sent to indicate the end of the character. The line sits idle (high) between characters until another character is ready to send. For a baud rate of 9600, each bit is sent for 1/9600 of a second. With 8 data bits, no parity bit, and 1 stop bit, the protocol is known as 8N1. Many different serial protocols are in use, but 9600 8N1 is a very common one.

Serial line output of the character "F" sent at 9600 baud / 8N1.

Serial line output of the character "F" sent at 9600 baud / 8N1.

The first step in implementing this serial output was to produce the 1/9600 second intervals for each bit. This interval can be measured by counting 5208 clock pulses on the Mojo.3 I implemented this by using a 13-bit counter to repeatedly count from 0 to 5207. To keep track of which bit is being output in each interval, I used a simple state machine that advanced through the start bit, the 8 data bits, and the stop bit. The state is held in a 4-bit register. (With FPGAs, you end up dealing a lot with clock pulses, counters, and state machines.)

To create the interval and state registers in the FPGA chip, I wrote code in the Verilog hardware description language. I won't explain Verilog thoroughly, but hopefully you can get a feel for how it works. In the code below, the first lines define a 13-bit register called counter and a 4-bit register called state. The counter is incremented until it reaches 5207, at which time the counter is reset to 0 and state is incremented to process the next output bit. (Note that <= is an assignment operator, not a comparison.4) The line always @(posedge clk) indicates that the code is executed on the positive edge of each clock.

reg [12:0] counter;
reg [3:0] state;

always @(posedge clk) begin
  if (counter < 5207) begin
     counter <= counter + 1;
  end else begin
    counter <= 0;
    state <= state + 1;
  end
end

While this may look like code in a normal programming language, it operates entirely differently. In a normal language, operations usually take place sequentially as the program is executed line by line. For instance, the processor would check the value of counter. It would then add 1 to counter. But in Verilog, there's no processor and no program being executed. Instead, the code generates hardware to perform the operations. For example, an adder circuit is created to increment counter, and a separate adder to increment state, and additional logic for the comparison with 5207. Unlike the sequential processor, the FPGA does everything in parallel. For instance, the FPGA does the 5207 comparison, the increment or reset of counter and the increment of state all in parallel on each clock pulse. Because of this parallelism, FPGAs can be much faster than processors for highly parallel tasks.

The next part of the serial code (below) outputs the appropriate bit for each state. As before, while this looks like a normal programming language, it is generating hardware circuits, not operations that are executed sequentially. In this case, the code creates gate logic (essentially a multiplexer) to select the right value for out.

case (state)
  IDLE: out = MARK; // high
  START: out = SPACE; // low
  BIT0: out = char1[0];
  BIT1: out = char1[1];
  ...
  BIT6: out = char1[6];
  STOP: out = MARK;
  default: out = MARK;
endcase

There's a bit more code for the serial module to define constants, initialize the counters, and start and stop each character, but the above code should give you an idea of how Verilog works. The full serial code is here.

The FizzBuzz Algorithm

The next step is figuring out what to send over the serial line. How do we convert the numbers from 1 to 100 into ASCII characters? This is trivial when programming a microprocessor, but hard with digital logic. The problem is that converting a binary number to decimal digits requires division by 10 and 100, and division is very inconvenient to implement with gates. My solution was to use a binary-coded decimal (BCD) counter, storing each of the three digits separately. This made the counter slightly more complicated, since each digit needs to wrap at 9, but it made printing the digits easy.

I wrote a BCD counter module (source) to implement the 3-digit counter. It has three 4-bit counters digit2, digit1, and digit0. The flag increment indicates that the counter should be incremented. Usually just digit0 is incremented. But if digit0 is 9, then it wraps to 0 and digit1 is incremented. Except if digit1 is also 9, then it wraps to 0 and digit2 is incremented. Thus, the digits will count from 000 to 999.

if (increment) begin
  if (digit0 != 9) begin
    // Regular increment digit 0
    digit0 <= digit0 + 1;
  end else begin
    // Carry from digit 0
    digit0 <= 0;
    if (digit1 != 9) begin
      // Regular increment digit 1
      digit1 <= digit1 + 1;
    end else begin
      // Carry from digit 1
      digit1 <= 0;
      digit2 <= digit2 + 1;
    end
  end
end

As before, keep in mind that while this looks like normal program code, it turns into a bunch of logic gates, generating the new values for digit2, digit1 and digit0 on each clock cycle. The system isn't executing instructions in sequence, so performance isn't limited by the number of instructions but just by the delay for signals to propagate through the gates.

The next challenge was testing if the number was divisible by 3 or 5. Like division, the modulo operation is easy on a microprocessor, but hard with digital logic. There's no built-in divide operation, so modulo needs to be computed with a big pile of gates. Although the IDE can synthesize the gates for a modulo operation, it seemed inelegant. Instead, I simply kept counters for the value modulo 3 and the value modulo 5. The value modulo 3, for instance, would simply count 0, 1, 2, 0, 1, 2, ...5

The final piece of FizzBuzz was the code to output each line, character by character. In a program, we could simply call the serial output routine for each character. But in an FPGA, we need to keep track of which character is being sent, with yet another state machine. Note that to convert each digit to an ASCII character, binary 11 is concatenated, using the slightly strange syntax 2'b11. The code excerpt below is slightly simplified; the full code includes leading zero checks so "001" will print as "1".

state <= state + 1; // Different state from serial
if (mod3 == 0 && mod5 != 0) begin
  // Fizz
  case (state)
   1: char <= "F";
   2: char <= "i";
   3: char <= "z";
   4: char <= "z";
   5: char <= "\r";
   6: begin
     char <= "\n";
     state <= NEXT; // Done with output line
     end
  endcase
end else if (mod3 != 0 && mod5 == 0) begin
  ... Buzz case omitted ...
end else if (mod3 == 0 && mod5 == 0) begin      
 ... Fizzbuzz case omitted ...
end else begin 
  // No divisors; output the digits of the number.
  case (state)
    1: char <= {2'b11, digit2[3:0]};
    2: char <= {2'b11, digit1[3:0]};
    3: char <= {2'b11, digit0[3:0]};
    4: char <= "\r";
    5: begin
     char <= "\n";
     state <= NEXT;
    end
  endcase
end

Putting it all together, there are multiple state machines and counters controlling the final FizzBuzz circuit. The main state machine controls the code above, moving through the characters of the line. For each character, this state machine triggers the serial output module, and waits until the character has been output. Inside the serial module, a state machine moves through each bit of the character. This state machine waits until the baud rate counter has measured out the width of the bit. When the serial output of the character is done, the serial module signals the main state machine. The main state machine then moves to the next character in the line. When the line is done, the main state machine increments the BCD counter (counting from 1 to 100) and then starts outputting the next line.

Programming languages make it easy to do operations in sequence, perform loops, make subroutine calls and so forth. But with an FPGA, you need to explicitly control when things happen, using state machines and counters to keep track of what's happening. In exchange for this, FPGAs give you a huge degree of parallelism and control.

Running FizzBuzz on the FPGA board

To compile the Verilog code, I used Xilinx's ISE tool (below), which is a development environment that lets you write code, simulate it, and synthesize it into gate-level circuitry that can be loaded onto the FPGA. Using the ISE tool is fairly straightforward, and explained in the Mojo tutorials. The synthesis process was slow compared to a compile, taking about 45 seconds for my FizzBuzz program.

By writing Verilog code in Xilinx's ISE tool, you can program functionality into an FPGA.

By writing Verilog code in Xilinx's ISE tool, you can program functionality into an FPGA.

Once I had the code working in the simulator,7, I downloaded it to the FPGA board over a USB cable. I connected the FPGA output pin to a USB-to-serial adapter6 and used a terminal emulator (screen) to display the serial output on my computer. I hit the reset button on the Mojo board and (after just a bit more debugging) the FizzBuzz output appeared (below).

First page of output from the FizzBuzz FPGA, as displayed by the screen terminal emulator.

First page of output from the FizzBuzz FPGA, as displayed by the screen terminal emulator.

The image below shows the raw serial data from the FPGA (yellow). This is the end result of the FizzBuzz circuitry running on the FPGA board—a sequence of pulses. The oscilloscope also shows the decoded ASCII characters (green). This data is near the beginning of the FizzBuzz output, showing the lines for 2, 3 and 4. (CR and LF are carriage return and line feed.)

The serial data signal (yellow) near the beginning of the FizzBuzz output. The ASCII decoding is in green.

The serial data signal (yellow) near the beginning of the FizzBuzz output. The ASCII decoding is in green.

What happens inside the FPGA?

You might wonder how a Verilog description of a circuit gets turned into digital logic, and how the FPGA implements this logic. The ISE synthesis tool turns the Verilog design into circuitry suitable for implementation inside the FPGA. It first synthesizes the Verilog code into a "netlist", specifying the logic and connections. Next it translates the netlists into FPGA primitives, which are mapped onto the capabilities of the particular chip (the Spartan 6 in my case). Finally, the place and route process optimizes the layout of the chip, minimizing the distance signals need to travel.

Schematic of the FizzBuzz circuit.

Schematic of the FizzBuzz circuit.

The image above shows the schematic of the FizzBuzz circuit, as generated by the synthesis tools. As you can see, the Verilog code turns into a large tangle of circuitry. Each block is a flip flop, logic element, multiplexer or other unit. These blocks make up the counters, state registers and logic for the FizzBuzz circuit. While this looks like a lot of logic, it used less than 2% of the chip's capability. A closeup (below) of the schematic shows a flip flop (labeled "fdre")8 and a lookup table (labeled "lut5") from the BCD counter. The nice thing about Verilog is that you can design the circuit at a high level, and it gets turned into the low-level circuitry. This is called RTL (Register-transfer level) and lets you design using registers and high-level operations on them, without worrying about the low-level hardware implementation. For instance, you can simply say count + 1 and this will generate the necessary binary adder circuitry.

Detail of the schematic showing a flip flop and lookup table.

Detail of the schematic showing a flip flop and lookup table.

The FPGA chip uses an interesting technique to implement logic equations. Instead of wiring together individual gates, the logic is implemented with a lookup table (LUT), which is a flexible way of implementing arbitrary logic. Each lookup table has 6 input lines, so it can implement any combinatorial logic with 6 inputs. With 6 inputs, there are 64 different input combinations, yielding a 64-line truth table. By storing this table as a 64-bit bitmap, the LUT can implement any desired logic function.

For example, part of the logic for the output pin is equivalent to the logic circuit below. This is implemented by storing the 64-bit value FFFFA8FFFFA8A8A8 into the lookup table. In the Spartan 6 chip, the LUT is implemented with 64 bits of static RAM, loaded when the FPGA is initialized. Since the chip has 5720 separate lookup tables, it can be programmed to implement a lot of arbitrary logic.

The gate logic implemented by one lookup table in the FPGA.

The gate logic implemented by one lookup table in the FPGA.

The final piece of the FPGA puzzle is the switch matrix that connects the circuitry together in arbitrary ways. In the Spartan 6 a handful of LUTs, flip flops and multiplexers are grouped into a configurable logic blocks (CLB).9 The CLBs are connected together by a switch matrix, as shown below. Each switch matrix block is programmed to connect different wires together, allowing the FPGA to be wired as desired. An important part of the FPGA synthesis process is positioning blocks to minimize the wiring distance, both to minimize signal propagation delay and to avoid running out of interconnect paths.

The switching matrix in the Spartan 6 FPGA allows arbitrary interconnections between CLBs. From the User Guide.

The switching matrix in the Spartan 6 FPGA allows arbitrary interconnections between CLBs. From the User Guide.

Should you try an FPGA?

Personally, I was very reluctant to try out an FPGA because they seemed scary and weird. While there is a learning curve, FPGAs aren't as difficult as I expected. If you're interested in new programming paradigms, FPGAs will definitely give you a different perspective. Things that you take for granted, such as performing operations in sequence, will move to the foreground with an FPGA. You can experiment with high degrees of parallelism. And FPGAs will give you a better idea of how digital circuits work.

However, I wouldn't recommend trying FPGAs unless you have some familiarity with wiring up LEDs and switches and understand basic digital logic: gates, flip flops, and state machines. If you're comfortable with an Arduino, though, an FPGA is a reasonable next step.

For most applications, a microcontroller can probably do the job as well as an FPGA and is easier to program. Unless you have high data rates or require parallelism, an FPGA is probably overkill. In my case, I found a microcontroller was barely powerful enough for my 3Mb/s Ethernet gateway project, so I'm looking into FPGAs for my next project.

Is the Mojo a good board to start with?

The Mojo FPGA development board is sold by Adafruit and Sparkfun, so I figured it would be a good hacker choice. The Mojo was designed for people getting started with FPGAs, and I found it worked well in this role. The makers of the Mojo wrote a solid collection of tutorials using Verilog.10 It was very helpful to use tutorials written for the specific board, since it minimized that amount of time I spent fighting with the board and tools. The Mojo is programmed over a standard USB cable, which is more convenient than boards that need special JTAG adapters.

The Mojo FPGA board. The Spartan-6 FPGA chip dominates the board.

The Mojo FPGA board. The Spartan-6 FPGA chip dominates the board.

Although the Mojo has plenty of I/O pins, it doesn't have any I/O devices included except 8 LEDs. It would be nicer to experiment with a board that includes buttons, 7-segment displays, VGA output, sensors and so forth. (It's not hard to wire up stuff to the Mojo, but it would be convenient to have them included.) Also, some development boards include external RAM but the Mojo doesn't, a problem for applications such as a logic analyzer that require a lot of storage.11 (You can extend the Mojo with an IO shield or RAM shield.)

A good introductory book to get started with the Mojo is Programming FPGAs; it also covers the considerably cheaper Papilo One and Elbert 2 boards. A list of FPGA development boards is here if you want to look at other options.

Conclusion

An FPGA is an impractical way to implement FizzBuzz, but it was a fun project and I learned a lot about FPGA programming. I certainly wouldn't get the FPGA job if FizzBuzz was used as an interview question, though! My code is on github, but keep in mind I'm a beginner to FPGAs.

Follow me on Twitter or RSS to find out about my latest blog posts.

Notes and references

  1. It's trivial to implement a microprocessor on an FPGA. For instance, with the Spartan 6 chip you can click a couple buttons in an IDE wizard and it will generate the circuitry for a MicroBlaze processor. Thus, the sensible way to run FizzBuzz on an FPGA would be to write the FizzBuzz code in a few lines of C, and then run it on a processor inside the FPGA. But that's too easy for me. 

  2. The start bit is necessary because otherwise the receiver couldn't tell when the character started, if the first bit sent was a 1. 

  3. Since the Mojo uses a 50 MHz clock, for 9600 baud each output bit is 50,000,000 / 9600 or approximately 5208 clocks wide. 9600 baud isn't a very fast rate so to challenge my circuit, I also tested it at 10M baud (by counting to 5 for each bit) and the circuit worked fine. (The USB-to-serial interface only worked up to 230400 baud, so I used oscilloscope decoding to check the higher speeds.) 

  4. In Verilog, <= is the nonblocking assignment operator, while = is the blocking assignment operator. Nonblocking assignments happen in parallel, and are generally used for sequential (clocked flip flop) logic. Blocking assignment is used for combinational (nonclocked) logic. This is a bit confusing but details are here

  5. I used BCD and not binary to store the number, so computing the value modulo 5 would have been almost trivial by looking at the last digit. But modulo 3 would still be difficult, so I stuck with the counter approach. 

  6. I couldn't connect the serial input directly to my computer, since it doesn't have a serial port. Instead, I used a USB-to-serial adapter, Adafruit's FTDI Friend. This adapter also had the advantage of accepting the FPGA's 3.3V signals, rather than the inconvenient +/- 15V used by genuine RS-232. 

  7. Debugging an FPGA is a very different process from software debugging. Since the FPGA is mostly a black box while running, you should test everything out in the simulator first, or else you end up in "FPGA Hell", blinking LEDs to figure out what's happening. To debug code, you simulate it by writing a "testbench", Verilog code that specifies various inputs at various times (example). You then run the simulator (below) and examine the output to make sure it is correct.

    The ISim simulator from Xilinx allows an FPGA design to be simulated.

    The ISim simulator from Xilinx allows an FPGA design to be simulated.

    If things go wrong, the simulator lets you step through the internal signals to find the problem. After testing everything in the simulator, my code only had trivial problems when I tried it on the real FPGA. My main problem was I assigned the serial output to the wrong pin on the board, so there was no output. 

  8. The Spartan 6 FPGA supports multiple types of flip flop. The FDRE is a D-Flip flop with synchronous Reset and clock Enable. 

  9. The Spartan 6 FPGA's configurable logic blocks (CLBs) are moderately complex, combining LUTs, 8 flip flops, wide multiplexers, carry logic, distributed RAM and shift registers. Hard-wiring components into the these blocks reduces flexibility slightly, but makes the switch matrix much simpler. The CLBs are described in detail in the CLB User Guide. The Spartan 6 FPGA also contains other types of blocks such as clock generation blocks and DSP blocks that can do fast 18-bit multiplication. 

  10. An alternative to the Verilog language is VHDL, which is also supported by the development environment. The Mojo also supports Lucid, a simpler FPGA language developed by the Mojo team. The Mojo Lucid tutorials explain the language, and there is a book available on Lucid. I decided I'd rather learn a standard language rather than Lucid though. 

  11. Although the Mojo doesn't have external RAM, its FPGA has 576 kilobits of internal RAM. This is tiny compared to boards with megabytes of external DRAM, though. 

Repairing the card reader for a 1960s mainframe: cams, relays and a clutch

I recently helped repair the card reader for the Computer History Museum's vintage IBM 1401 mainframe. In the process, I learned a lot about the archaic but interesting electromechanical systems used in the card reader. Most of the card reader is mechanical, with belts, gears, and clutches controlling the movement of cards through the mechanism. The reader has a small amount of logic, but instead of transistorized circuits, the logic is implemented with electromechanical relays.1 Timing signals are generated by spinning electromechanical cams that generate pulses at the proper rotation angles. This post explains how these different pieces work together, and how a subtle timing problem caused the card reader to fail.

The IBM 1402 card reader/punch. The 1401 computer is in the background (left) and a tape drive is at the right.

The IBM 1402 card reader/punch. The 1401 computer is in the background (left) and a tape drive is at the right.

The IBM 1401 was a popular business computer of the early 1960s, used for applications such as payroll or inventory. Data records were stored on 80-column punch cards, which were read into the computer by the card reader and printed on the high-speed line printer. The IBM 1401's card reader (above) could read 800 cards per minute—over 13 cards per second—which is a remarkable speed for a mechanical device. Cards whizzed through the card reader, 80 metal brushes read the holes in each column, and then the cards were stacked in the hoppers in the middle of the reader.3 If anything went wrong, from a misread card to a card jam, the card reader would slam to a halt (hopefully before bent cards started piling up) and an error light would illuminate on the card reader's control panel. At this point, the operator would fix the problem and processing could continue.2

80-column punch cards. Each column of the card holds a character, represented by the holes punched in the column. THE text at the top of the card shows what is in each column. Black paper behind the first card makes the holes more visible.

80-column punch cards. Each column of the card holds a character, represented by the holes punched in the column. THE text at the top of the card shows what is in each column. Black paper behind the first card makes the holes more visible.

The photo below shows the IBM card reader/punch with the front doors opened up. The right half is the reader and the left half is the punch. (The punch records data on cards; I will ignore it in this article.) The blue panel has the operator controls and indicators. Cards enter through the feeder in the upper right, travel right-to-left through the brushes (behind the blue panel) and fall into the stacker slots (center). To the right of the stacker is the service panel with the dynamic timer (circle with knob); this will be relevant later. The relays, resistors, capacitors and diodes that make up the reader's circuitry are below the service panel. Converting the hole pattern to characters was done by the 1401 computer, not the reader, so this circuitry is fairly basic.3 The garbage can on the lower left collects "chips", the bits punched out of cards by the punch, and triggers a warning light when it is full.

With the front doors of the card reader/punch removed, the circuitry is visible. The left half is the punch and the right half is the reader. The *Reader Stop* light is illuminated on the panel, indicating a malfunction.

With the front doors of the card reader/punch removed, the circuitry is visible. The left half is the punch and the right half is the reader. The *Reader Stop* light is illuminated on the panel, indicating a malfunction.

A few months ago a problem with the card reader kept showing up under certain circumstances: the card reader would halt with a "Reader Stop" error, indicating a problem with card feeding and travel.2 Given the age of the card reader at the Computer History Museum, it's not surprising that Reader Stop problems arise. However, in this case, cards were feeding fine and there was nothing visibly wrong. Eventually the 1401 maintenance team determined that the problem occurred if you do multiple cycles of reading a card, printing a line on the printer, reading a card, printing a line, and so on. The first three cards read fine, but the fourth card read always failed with a Reader Stop. But during normal processing, hundreds of cards could be read without a problem. What was different about repeatedly reading and printing?

The card reader can read 800 cards per minute, but the line printer can only print 600 lines per minute. Thus, if you continuously read and print, the printer will eventually fall behind. The consequence is that the card reader will occasionally be blocked while the printer finishes a line. In particular, the system can read and print three cards in a row, but there is a delay before reading the fourth card.4 This is normal behavior for the system, but for some reason, this delay was triggering the Reader Stop error.

The question at this point of the investigation was why the delayed read triggered a Reader Stop. The logic diagram below shows the many different things can cause a Reader Stop.5 (This logic was implemented in the reader by relay circuits of Byzantine complexity.) Usually a card jam or card feed problem is responsible for a stop, but there weren't any card movement problem. And the card levers (microswitches) that detect card movement were operating correctly. Eventually, the team discovered that removing relay R-10 (Read Clutch Impulse near the bottom of the diagram) stopped the Reader Check from happening. Removing this relay prevented the clutch status from being checked8 so it prevented the error from being reported but didn't fix the underlying problems. It did, however, indicate that the problem was with the clutch.

Diagram showing the logic conditions that yield a Reader Stop error in the card reader. From the manual.

Diagram showing the logic conditions that yield a Reader Stop error in the card reader. From the manual.

At this point, I'll explain how the clutch works in the card reader. The card reader is powered by a 1/4 horsepower electric motor. This motor powers a variety of shafts, belts, rollers and cams inside the card reader. However, the reader needs a mechanism to rapidly start and stop card reading under computer control. This is accomplished by a clutch that powers the card feed rollers. With the clutch engaged, cards will be fed through the card reader. With the clutch disengaged, cards will not move (although other parts of the reader will keep running). The GIF below shows the clutch in action: it is disengaged for one cycle and engaged for one cycle. Although the silver pulley (driven by the motor) turns continuously, the black gear is started and stopped by the clutch, which is just behind the black gear.

The clutch in the 1402 card reader. The clutch is disengaged for one cycle and engaged for one cycle.

The clutch in the 1402 card reader. The clutch is disengaged for one cycle and engaged for one cycle.

The diagram below shows the main parts of the clutch. The ratchet (green) continuously rotates, powered by the motor. When the coil (orange) pulls the latch (purple), the dog (blue) will fall into the ratchet (green), engaging the clutch. This will cause the outer wheel to rotate in sync with the ratchet, feeding a card. After one cycle, the clutch can be disengaged by the latch, or can remain clutched for another cycle. Above, you can see the latch move just before the clutch engages. The dogs and ratchet are hidden behind the black gear. For more details, see the footnotes.67

The card reader's clutch mechanism. From the 1402 manual.

The card reader's clutch mechanism. From the 1402 manual.

The clutch requires careful timing. If the coil pulls the latch too late, the dog won't engage with the ratchet until the next cycle and no card will be fed. And if the latch is released too late, the clutch won't disengage until the next cycle, feeding an extra card. Either way, this would cause a serious problem if you are, for instance, printing payroll checks. To catch this, the card reader includes a clutch check circuit that ensures that a clutch happens only when requested.8 This circuit is what triggered the Reader Stop issue.

Timing in the card reader is controlled by the angular position of the main drive shaft; there isn't a clock signal. A 360° rotation of the drive shaft corresponds to one card read cycle.9 The mechanical and electrical components must be precisely adjusted so they activate at the correct rotational angles. For instance, a card's first row of holes reaches the brushes at 8° and card lever #1 is triggered at 227°. And the clutch is engaged or disengaged at exactly 315°. Electrical signals are generated by rotating cams that open and close microswitches at the appropriate degree angles. For example the read clutch is controlled by cam RC6 that closes at 272° and opens at 342°. The photo below shows a cam on a drive shaft, with the microswitch above it; when the cam rotates to a high point, the switch closes.

One of the cams and microswitches in the card reader.

One of the cams and microswitches in the card reader.

To examine timings, the card reader has an interesting maintenance feature called the Dynamic Timer, which is sort of a mechanical oscilloscope that visually shows the angle timing of signals. The dynamic timer consists of a neon bulb that spins behind a plastic disk labeled with the angles from 0° to 359°. If a signal is selected with a control panel switch, the bulb lights up when the signal is active.1 Because the neon bulb is spun by the main driveshaft, its position is synchronized to the rotation angle of the card reader's mechanisms. Thus, the neon bulb traces out sectors of a circle, indicating when the signal is active. For example, the image below shows the read brush signal, which is activated as each card row passes under the brushes. Since there are 12 rows on a punch card, the signal is activated 12 times in a card cycle. By reading the angle labels on the clear plastic dial, the signal timings can be checked for correctness. In addition, the knob in the middle of the dynamic timer can be rotated manually to move the card reader's cycle to any desired angle.

The dynamic timer of the 1402 card reader. The 12 signals correspond to the 12 rows on the card, indicating when the row passes through the brushes.

The dynamic timer of the 1402 card reader. The 12 signals correspond to the 12 rows on the card, indicating when the row passes through the brushes.

We measured the timing of read clutch control cam RC6 and found it was off by about 5 degrees. The manual called the timing of this cam "critical" saying it needed to be within 2° earlier or 0° later from the correct angle.10 Since the cam was well outside the allowed range, we tried to adjust it. The first problem was that the cam was frozen to the shaft; apparently after decades of storage in a a damp garage it had rusted to the shaft. Carl eventually hit the cam hard enough (yet carefully!) with a hammer to loosen it from the shaft so it could be adjusted.

The photo below shows how we manually adjusted cam timings. The dynamic timing wheel (left) can be turned by hand until the cam closes, and then the angle can be read from the dial. The adjustment process is rather tedious, requiring trial and error. First, the duration that contact is closed is corrected by moving the contact closer or farther from the cam. After each adjustment, the duration must be manually checked by slowly rotating the dynamic timing wheel 360°. Once the duration is correct, the next step is to rotate the cam a few degrees at a time until it closes and opens at the right angle. Again, the timing must be carefully checked after each adjustment until trial-and-error yields the right cam setting.

By manually rotating the dynamic timer wheel, the cam timing (center) can be checked. The light (upper right) shows when the cam has closed. This photo shows cam RL10 being adjusted.

By manually rotating the dynamic timer wheel, the cam timing (center) can be checked. The light (upper right) shows when the cam has closed. This photo shows cam RL10 being adjusted.

Once cam RC6 had the proper timing, we tested the card reader. Surprisingly, it failed just as before. We checked the timing of RC6 with the dynamic timer, and strangely, the timer still showed that it closed 5° too late, even though we had measured it as closing correctly. After puzzling over the schematics, I found that cam RC6 was powered through cam RL10, so a bad timing on cam RL10 would cause the dynamic timer to show the wrong time for RC6.

We continued the next week and measurement of RL10 showed it was closing 5° too late. So we repeated the cam adjustment process with RL10. Carl loosened RL10's setscrews, whacked it with a hammer, and was surprised when it spun around on the shaft—apparently it hadn't rusted onto the shaft the way RC6 had. Since the timing of RL10 was now thoroughly off, it took some extra effort to find the right position for it. One complication is that RL cams only rotate while the clutch is tripped, so we had to manually trip the clutch for each test. (This video shows how the clutch can be tripped manually.) After a couple hours of adjustment, the cam had the right duration and then the right start angle.

We powered up the card reader and this time it ran all the tests successfully! We had found the elusive problem. Apparently cam RL10 was open a bit too much, so the signal to read a card after a pause in reading wasn't quite able to engage the clutch. Then the clutch check circuitry would detect that the clutch had failed to engage, triggering the Read Stop.

Conclusion

Tracking down and fixing the mysterious Reader Stop errors on the card reader was tricky and more time-consuming than most problems. But it provided an interesting look back in time at the obsolete technology used inside the card reader: relay logic, spinning cams and a mechanical clutch. Debugging the card reader is a different experience from tracking down software problems or even normal hardware problems. Just understanding the schematics with their obsolete symbols can be a challenge. Hopefully what we learned in this repair will help us the next time the card reader malfunctions.

Many members of the 1401 restoration team were involved in fixing this problem, including Carl, Frank, Alexy, Ron, George, Glenn, Jim and Grant. The Computer History Museum in Mountain View runs demonstrations of the IBM 1401 on Wednesdays and Saturdays so check it out if you're in the area; the demo schedule is here.

Follow me on Twitter or RSS to find out about my latest blog posts.

Notes and references

  1. While IBM's computers were supposed to be transistorized by the time of the 1401, two vacuum tubes are hidden deep inside the card reader. These tubes power the neon bulbs for the dynamic timer used for diagnostics. The photo below shows the tubes and the transformer that powers them.

    The 1402 card reader contains two vacuum tubes to drive the neon bulbs in the dynamic timer.

    The 1402 card reader contains two vacuum tubes to drive the neon bulbs in the dynamic timer.

  2. The 1402 card reader reports three types of errors. A Reader Stop indicates a jam or card feed problem. (This is the error we encountered.) A Validity error indicates an invalid character caused by a bad hole pattern. A Reader Check indicates that the card was read incorrectly. An interesting technique was used to detect a bad read. The first set of brushes was used to count the number of holes in each column. The second set of brushes performed the actual read of the characters. If the number of holes in a column was different between the first and second reads, the system knew that the card had been read incorrectly. (This was typically caused by a brush that was slightly out of alignment or making bad contact.) You might wonder why the holes were counted, instead of just checking the characters. Counting holes required fewer bits of expensive core memory. 

  3. The card reader itself didn't convert the hole pattern into characters. Instead, there were 80 parallel wires directly from the 80 hole-sensing brushes to the computer, which did the hole-to-character conversion. The reader had one set of brushes to count holes (for the error check) and a second set to actually read the characters. The punch had a set of brushes to check the punched holes and optionally a set of brushes to read before punching. Thus, there could be up to four sets of brushes in the reader/punch. In addition, the punch had 80 wires from the computer to the 80 hole punch coils. As a result, two massive 200-wire cables connected the card reader and the computer. 

  4. The 1401 computer has a core-memory print buffer that allows computation to continue while printing a line. However, a complex interlock circuit will block the computer if it tries to print a line while the buffer is still in use. (This buffering and locking is all done in hardware; there is no operating system.) The print buffer was an optional feature for the computer, renting for an extra $386 per month. 

  5. The Reader Stop diagram shown earlier is somewhat confusing, but I'll give an overview. As cards pass through the card reader, they trip microswitches (called Card Levers or CLC). The logic tests if a microswitch isn't triggered, indicating if a card got jammed before reaching the microswitch. For example, the second triangle triggers an error if there are cards in the hopper, but no card reached card lever 1 after a feed signal. (Note that the logic symbols are backwards compared to modern usage; IBM used a semicircle for OR, and a triangle for AND. Thus, each set of inputs into a triangle shows a set of conditions that will trigger a reader stop.)

    A label like R-6 indicates that the signal comes from relay 6. Relay R-13 is the Reader Stop Control relay; it gets triggered if there was a card at microswitch 1 or 2 during angle 158°-188°. During this time, the card should have already passed the microswitch, so if it is still closed, there must be a jam. "CLC 1 DELAY" indicates that there was a card at CLC 1 in the previous cycle. If there is no card at CLC 2 this cycle, the card must have been jammed along the way. 

  6. Several documents on the 1402 card reader/punch are available on bitsavers. The IBM 1402 Card Read-Punch Manual is an operator's manual for the card reader. The Customer Engineering Manual of Instruction explains the implementation of the card reader for the service engineer, and is probably the best guide to how it operates. The Customer Engineering Instruction Reference Manual explains the internals of the card reader, with a focus on maintenance. The Wiring Diagram provides schematics of the card reader. The Service Index provides a summary of information for servicing. 

  7. The operation of the clutch mechanism is a bit tricky. In the diagram below, the ratchet (green) is constantly spinning. The remaining parts of the clutch are connected together and rotate only when the clutch is engaged. The key idea is that when the intermediate arm (middle) is latched, the control studs push the dogs up and out of the ratchet disengaging the clutch. (This happens because the intermediate arm can pivot slightly relative to the drive arm (left), so the dog pivot and control stud will move relative to each other, swinging the dogs upwards.) When the intermediate arm is unlatched, the dogs are no longer raised and they will engage with one of the ratchet's teeth. At this point, the mechanism is clutched and everything rotates in synchronization, until the intermediate arm hits the latch again, disengaging the dogs from the ratchet. The video of a simpler ratchet clutch may clarify the dog and ratchet mechanism.

    Diagram of the card reader's ratchet clutch, from the service manual.

    Diagram of the card reader's ratchet clutch, from the service manual.

  8. In case anyone (most likely me, in the future) needs to understand the clutch check circuit, I'll give an explanation. The reader sends a "Proc Feed" signal to the computer each time a card could be fed. If the computer wants to read a card, it sends a "Read Clutch" signal back. This signal is gated by cams RL10 and RC6 and cam RC5 and does two things. It triggers the read clutch magnet, the coil that pulls the clutch latch. It also energizes the clutch check relay R10. (See the schematic for details.) A bit later in the cycle, the clutch status is checked using the circuit below. If the clutch check relay is activated but the clutch did not latch, cam RL10 (not shown) will not be rotating and will remain closed. RL10 will trigger the Read Stop relay R4 through RC7 and R10's normally-open contacts. On the other hand, if the clutch check relay is not activated, but the clutch is latched, cam RL2 will be rotating and will trigger the Read Stop relay through the Read Stop relay R4's normally-closed contacts.

    The clutch check circuit in the card reader uses cams and relays to trigger a Read Stop if the clutch fails to latch. From the 1402 schematic.

    The clutch check circuit in the card reader uses cams and relays to trigger a Read Stop if the clutch fails to latch. From the 1402 schematic.

  9. Although one card can be read every 360° cycle of the reader, it takes three cycles to process a particular card. During the first cycle, the card is moved out of the hopper into the reader and triggers card lever 1. During the second cycle, the card passes through the first set of brushes (which counts the holes in each column), and triggers card lever 2. During the third cycle, the card passes through the second set of brushes (which actually reads the card), and is ejected into a hopper. Thus, there are typically three cards in flight in the reader at any time. (This is one reason the reader has so much circuitry to detect jams quickly, to prevent multiple cards from piling up in a crumpled heap.) 

  10. Many cams (including RC6) actually have three lobes, so they open and close three times every 360°, spaced 120° apart. This is due to an optional feature called Early Read (which cost an extra $10 per month). On the basic card reader, if the computer requests a card too late in the cycle, it has to wait for up to an entire revolution (75ms) until the clutch can latch, slowing down the system. With Early Read, there are three clutch points per revolution, cutting down the wasted time to at most 25ms. (One complication: the clutch is geared to half the speed of the regular shaft and turns 180° per cycle. This is why there are 6 teeth on the clutch ratchet.) 

IBM mainframe tube module part II: Powering up and using a 1950s key debouncer

In the 1950s, before integrated circuits or even transistors, mainframe computers were built from thousands of power-hungry vacuum tubes filling massive cabinets. To simplify construction and maintenance of these computers, IBM invented a pluggable module with eight tubes;1 failed modules could be quickly pulled out of the computer and replaced. I came across one of these tube modules and wondered if it would still work decades later. Could I power it up and demonstrate it in a circuit, or would the components have failed with time?

The glowing orange filaments are visible in the tubes of this IBM tube module. This 8-tube module is a key debouncer from the IBM 705 business computer.

The glowing orange filaments are visible in the tubes of this IBM tube module. This 8-tube module is a key debouncer from the IBM 705 business computer.

Part I of my post discussed tube modules and described the IBM 705 that used this module. To recap, the IBM 705 was a large business computer introduced in 1954. It weighed 16 tons, used 70 kilowatts of power and cost $15 million (in 2018 dollars). A few dozen 705 systems were built, mostly used by large companies and the US government. For example, Texaco2 used the 705 for accounting applications such as payroll, marketing, and distribution. Even though the 705 was intended as a business computer, Texaco also used it for technical applications such as refinery simulation and pipe stress analysis. Below you can see the large CPU of an IBM 705 computer. Each of the four panels in the front held up to 80 tube modules.

The CPU of an IBM 705. From IBM 705 Electronic Data Processing Machine brochure.

The debouncer

By tracing out the circuitry of the tube module and studying old IBM documents, I determined that the module consisted of five key debouncing circuits. When you press a key or button, the metal contacts inside the switch tend to bounce against each other a few times before closing, so you end up with multiple open/closed signals, rather than a nice, clean signal. To use a key signal in a computer, it needs to be "debounced", with the multiple rapid transitions replaced by a single, clean transition. (Perhaps you have used a cheap keyboard that occasionally gives you double letters; this happens when the keyboard bounces more than the debounce circuit can handle.) In modern systems, debouncing is usually done in software, but back in the 1950s tubes were used for debouncing.

This tube module from an IBM 705 mainframe computer, implemented five key debouncing circuits.

This tube module from an IBM 705 mainframe computer, implemented five key debouncing circuits.

The IBM 705 was controlled from a complex console with control keys and neon status lights (below). The console was used for manual control of the computer, monitoring status, detecting and correcting errors, and debugging. (While memory could be modified from the console keyboard, programs were normally read from punch cards.) Tube-based debouncing circuits were used on many of the console keys to ensure proper operation, so that's probably the role of the module I examined.3

Console of an IBM 705 computer. That console was used to control the computer and for debugging it. Photo from IBM.

Console of an IBM 705 computer. That console was used to control the computer and for debugging it. Photo from IBM.

Vacuum tubes

IBM 6211 vacuum tube: a dual triode. The pins plug into a socket on the top of the tube module. The plates are visible inside the tube. The number 6211 is faintly visible near the top of the tube.

IBM 6211 vacuum tube: a dual triode. The pins plug into a socket on the top of the tube module. The plates are visible inside the tube. The number 6211 is faintly visible near the top of the tube.

Since most readers probably haven't used vacuum tubes, I'll give a bit of background. This module was built from a common type of vacuum tube known as a triode. In a triode, electrons flow from the cathode to the plate (or anode), under the control of the grid. The heater, similar to a light bulb filament, heats the cathode to around 1000°F, causing electrons to "boil" off the cathode. The anode has a large positive voltage (+140V in this module), which attracts the negatively-charged electrons. The grid is placed between the cathode and the anode to control the electron flow. If the grid is negative, it repels the electrons, blocking the flow to the plate. Thus, the triode can act as a switch, with the grid turning on and off the flow of electrons. The module I examined used dual triode tubes, combining two triodes into one tube for compactness.

Schematic symbol for a triode tube

Schematic symbol for a triode tube

Two vacuum tube circuits form the building blocks of this tube module: the inverting amplifier and the cathode follower. The schematic below shows a vacuum tube inverting amplifier (slightly simplified). If the input to the grid is negative, the flow of electrons through the tube is blocked, and the output is pulled up to +140 volts by the resistor. If the input to the grid is positive, electrons flow through the tube, pulling the plate output close to ground. Thus, the circuit both amplifies the input (since a small input change causes a large output change) and inverts the input.

An inverting amplifier built from a vacuum tube triode.

An inverting amplifier built from a vacuum tube triode.

The second circuit used in the module is the cathode follower, which is essentially a buffer; its low-impedance output let it drive other circuits. While the schematic (below) looks similar to the inverter, it has the opposite effect since the output is from the cathode, not the plate. If a positive input voltage is fed into the grid, the tube will conduct. The voltage drop across the cathode resistor will cause the cathode voltage (and thus the output voltage) to rise. On the other hand, if the input voltage is negative, electron flow will be reduced, shrinking the voltage drop across the resistor and reducing the cathode voltage. Either way, the cathode voltage (and output) will adjust to be approximately equal to the input voltage. The trick is that it's not a negative grid per se that blocks electron flow, but a negative grid with respect to the cathode.4 Thus the cathode follower essentially copies its input voltage to the output, but providing higher current.

A cathode follower buffer built from a vacuum tube triode.

A cathode follower buffer built from a vacuum tube triode.

Powering the filaments

The first step in making the module operational was to power up the vacuum tube filaments. Filaments usually operate at 6.3V AC for historical reasons (a 6V lead-acid battery contained three 2.1V cells, yielding 6.3V). Each tube's filament uses almost 3 watts, so a large filament transformer is necessary. The filament energy consumption is part of the reason tube-based computers used so much power.

The filament transformer converts AC line input to 6.3V to power the filaments. The transformer weighs 3.5 pounds.

The filament transformer converts AC line input to 6.3V to power the filaments. The transformer weighs 3.5 pounds.

We connected the transformer and inserted tubes one at a time to power up their filaments. Everything went smoothly—the tubes all lit up with a nice orange glow and none were burnt out. Each tube has two filaments (since they are dual triodes), so we could see two orange spots in each.

The tubes give off an orange glow when the filaments are powered with 6.3V AC.

The tubes give off an orange glow when the filaments are powered with 6.3V AC.

Powering the circuitry

Powering the tube module is inconvenient because of the multiple large voltages required. This tube module uses +140V, -60V and -130V, with input signals of probably 48V.10 The power supplies we had available only went up to +/- 120V, but I did some simulations with LTspice that showed the module should work with the lower voltages. We used a stack of power supplies to power the module, mostly vintage HP supplies from Marc's collection.5

To run the tube module, we used a stack of power supplies and test equipment. Two more power supplies are under the table.

To run the tube module, we used a stack of power supplies and test equipment. Two more power supplies are under the table.

The connector for the tube module probably hasn't been manufactured in 50 years, so I needed to find a way to connect wires to the module. I could have soldered wires directly to the module, but I didn't want to modify the module since it's a historical artifact. Instead I found that .110 quick-disconnect terminals fit (more or less) on the module's pins. To manage all the connections to the tube module, I built a small junction box to connect banana plugs from the power supplies to the tube module. This box also had a button to trigger the input.6

To keep the wiring under control, I built a junction box between the power supplies and the tube module. It also includes a pushbutton to control the input.

To keep the wiring under control, I built a junction box between the power supplies and the tube module. It also includes a pushbutton to control the input.

The trigger circuit

The schematic78 below shows one of the debounce circuits, which IBM called a "contact-operated trigger". (A trigger is the old term for a flip-flop, or a similar circuit that can be in two states.) The input goes through the resistor-capacitor low-pass filter on the left, smoothing out the input so the circuit won't respond to bounces. This goes to the grid (2) of a triode inverter amplifier as discussed earlier. The output from the first inverter (plate, 1) is connected to a second inverter (grid, 7) via the 91K resistor. The output from the second inverter (plate, 6) is shifted to the desired +30/-10 voltage range by a voltage divider (the 390K and 430K resistors). Shifting the voltage down is the reason a -130V supply is needed. 6 (The two inverters form a Schmitt trigger9 due to the connected cathodes and 3K resistor.) The output from this circuit is connected to a cathode follower (described earlier but not shown in the schematic below), which buffers the signal for use by other modules.

Schematic of one "trigger" circuit of the tube module.

Schematic of one "trigger" circuit of the tube module.

The diagram below illustrates how the debouncer functions. The red line shows the input, say from a button press. Notice that the switch opens and closes twice before closing for good. If the computer used this input as a control, it might perform the operation three times. The blue line shows the debounced signal, which turns on once cleanly. To perform the debouncing, the debouncer uses a resistor-capacitor filter to smooth out (i.e. integrate) the input signal into a slowly-changing signal; this is the green line. When the green signal gets high enough; the output turns on. Note that the output stays on even though the green signal drops in the last bounce. This is due to the Schmitt trigger; it turns off at a much lower level than where it turns on.

Signals in the debouncer: red is the input (with bounce). Blue is the debounced output. Green is the internal signal after R-C filtering. This image is from an LTspice simulation of the module.

Signals in the debouncer: red is the input (with bounce). Blue is the debounced output. Green is the internal signal after R-C filtering. This image is from an LTspice simulation of the module.

Using the tube module

The tube module showing how the five debounce triggers are divided among the tubes.

The tube module showing how the five debounce triggers are divided among the tubes.

The tube module contains five debounce circuits, each made up of a trigger and a cathode follower. The diagram above shows how these circuits map onto the eight tubes. Each cathode follower (CF) uses one triode (half a tube) so there are two cathode followers per tube.11 Since there's one triode left over, the last debouncer (5) has a double cathode follower for a higher current output. The photo below shows that someone marked the top of the module with red and greed dots indicating the two tube types and functions, probably to simplify maintenance.

Top of an IBM tube module type 330567. The red dots indicate 6211 tubes and the green dots indicate 5965 tubes.

Top of an IBM tube module type 330567. The red dots indicate 6211 tubes and the green dots indicate 5965 tubes.

We tested one of the five debounce circuits in the module. Although the tube module contains five debouncers, some resistors were knocked off the module over the years, so debounce circuit 4 was the only one we could use without repairs. Below, you can see the power and signal wires hooked up to the tube module, along with an oscilloscope probe to view the output. At the left, we have wired a neon bulb to the debouncer's status output. In the computer, these status outputs were connected to neon bulbs on the console or on maintenance panels.

The tube module in operation. The filaments illuminate the tubes. At the left, a neon bulb is connected to the module's neon output.

The tube module in operation. The filaments illuminate the tubes. At the left, a neon bulb is connected to the module's neon output.

The oscilloscope trace below shows the debounce circuit in operation. The input (yellow) is a pulse with contact bounce. You can see a bunch of large spikes due to bounce, as well as couple bounces of longer duration. There is also some bouncing at the end of the pulse. In contrast, the output (green) is a clean signal with a sharp transition. The bounce and noise in input signal could cause erroneous operation if used in a computer, for instance causing multiple operations. On the other hand, the output signal provides a single clean pulse to the computer, ensuring proper operation. Note that the output signal turns on and off about 1.3 ms after the input signal; this delay is due to slow charging and discharging of the R-C filter.

The lower trace shows the input with contact bounce as it turns on. In the output from the tube module, contact bounce has been eliminated.

The lower trace shows the input with contact bounce as it turns on. In the output from the tube module, contact bounce has been eliminated.

Once we had the tube module operational, we hooked it up to a vintage HP pulse counter. Without the debouncer, pressing a button would result in multiple counts; each bounce incremented the count. But with the tube debouncer in the circuit, each button press resulted in a single count, showing the module was functioning. Marc's video below shows the pulse counter in operation. Because the pulse counter could only handle 5 volt inputs, we used a resistor divider to reduce the voltage from the tube module. The resistor divider was implemented with large resistor decade boxes; they are on top of the stack of power supplies in the earlier photo.

Conclusion

Despite its age, the tube module still worked. (At least the one of the five debouncers we tested.) I was a little concerned about putting high voltages through such old electronics, but there were no sparks or smoke. Fortunately Marc had enough power supplies to power the module, and even though we fell a few volts short on the -130V and +140V the module still functioned. The module was bulky and consumed a lot of power—I could feel the warmth from it—so it's easy to understand why transistors rapidly made vacuum tube computers obsolete. Even so, its amazing to think that the principles of modern computers were developed using vacuum tubes so long ago.

Thanks to Carl Claunch for providing the module. Thanks to Paul Pierce, bitsavers and the Computer History Museum for making IBM 700 documentation available.

Follow me on Twitter or RSS to find out about my latest blog posts.

Notes and references

  1. Although each module contained eight tubes, this does not correspond to a byte. The eight tubes generally don't map onto eight of anything since circuits can use more or less than one tube. Also, the byte wasn't a thing back then; IBM's vacuum tube computers used 36-bit words (scientific models), or 6-bit characters (business models). 

  2. For a detailed list of companies using the IBM 705 and their applications, see the 1961 BRL report. This report has extensive information on early computers and how they were used. 

  3. By studying the IBM 705 schematics, I found that the debouncing circuit was used with many keys on the IBM 705 console, such as reset, clear memory, initial reset, machine stop, display, test start and test stop. The debouncer was also used for relay-controlled console signals such as machine stop, manual stop, manual store, memory test, half/multiple step and display step. I didn't see this specific tube module in the schematics, so the module could have been part of an IBM 705 peripheral or the earlier IBM 702 computer. 

  4. The cathode follower might seem like it should oscillate: when the cathode is low, current will flow, pulling the cathode high, which will block current flow, making the cathode low again. Yes, it could oscillate if the wires are too long, for instance. But it's designed so it will reach a stable intermediate point where everything balances out. 

  5. To supply the module with power, we used two vintage HP3068A power supplies (60V each) for the -60V and -120V. An HP6645A DC power supply provided 120V. A modern Protek 3003B power supply provided 30V for the input. We counted pulses using an HP 5334B universal counter. 

  6. There's a second output from the inverter's plate. This high-voltage output is used to drive a neon indicator bulb, showing the status of the circuit. The 1MΩ resistor limits current through the neon bulb. 

  7. The schematic says the input is "from key, relay or CB." A "CB" is a circuit breaker, but not in the modern current-protection sense. In old IBM machines, a circuit breaker was a microswitch triggered by a rotating cam, providing a timing signal. That is, it breaks the circuit as it opens and closes. Circuit breakers were common in electromechanical systems such as tabulating machines and card readers. 

  8. The schematic is from 700 Series Component Circuits, an IBM document that describes the wide variety of circuits used in IBM tube modules. If you want to understand tube modules in detail, this is the document to read. The contact-operated trigger is described on page C-35 and the schematic is on page C-36. The cathode follower is discussed on page A-43. 

  9. The tube module uses Schmitt triggers, which were invented in 1937. A Schmitt trigger provides hysteresis; when it turns on, it stays on until the input drops significantly. The Schmitt trigger is implemented by connecting the cathodes together, along with a series resistor. When one triode turns on, the cathode voltage will rise due to the resistor, similar to the cathode follower circuit. But since both triodes have the same cathode voltage, the rising cathode voltage will tend to shut the other triode off. Since it's harder for the other triode to turn on, the Schmitt trigger will stay in its current state until there is a large voltage swing on the input. 

  10. Vacuum tube systems used many different inconveniently-large voltages. The table below (from 700 Series Component Circuits) lists the voltages used by the IBM 704 (scientific) and IBM 705 (business) computers. I was surprised that the scientific computers and business computers used totally different voltages, but historically they were entirely different systems. IBM's 701 scientific computer started as the "Defense Calculator" project, while the 702 business computer came from IBM's TPM II (Tape Processing Machine) project. Thus, the two branches of the 700 series ended up with completely different architectures. (Among other differences, the 701 used binary while the 702 used binary-coded decimal characters.) They also ended up with different hardware components.

    IBM's vacuum tube computers use a large variety of voltages. Based on 700 Series Component Circuits, page E27.

    IBM's vacuum tube computers use a large variety of voltages. Based on 700 Series Component Circuits, page E27.

    The power supply manual explains some of the voltages and their uses. A +500V supply was used by the IBM 701 to power its electrostatic memory system, which stored bits on the surface of Williams tubes. Later machines used core memory instead, with the voltages listed above. The +15V and -30V were used as diode clamps to keep output voltages in the proper range. The +220V supply was typically used by AND gates, while OR gates used -250V. Tubes typically used the +150V supply for plates and -100V for cathodes. In the business computers (702/705), most logic used +270, +140V, -12V, -60V, -130V and -270V. 

  11. The triggers are implemented with type 6211 tubes, while the cathode followers are implemented with the more powerful 5965 tubes. From the photo, it may appear that the tubes don't match the locations since there are four tubes with metallized tops and four tubes with metallized sides. However, the tube markings indicate that all tubes were in the right locations. The location of the shiny getter is independent of the tube type.