IBM 1410 FPGA: Off to the Races??

Once the 1415 console emulation was up and running, I was able to run diagnostics. The first set of diagnostic failures arose in the Assembly Channel because the Automated Logic Diagrams I had for parts of the Assembly Channel were not for the 1410 Accelerator feature, unlike the vast majority of ALD pages I had.

Once I fixed that, diagnostic CU01 ran OK in non-overlapped non-priority (interrupt) mode. However, once I enabled overlapped I/O with the priority feature in the diagnostic settings, the diagnostic errored out with an Instruction Check. The overlapped I/O is that of the 1415 console. The diagnostic then monitors that (along with a priority interrupt) to make sure that the channel status information and the interrupt operate as expected.

The Assembly Channel issue had been reproducible using a single instruction, and I could set that instruction in the initialization of the first 10K memory module, so I was able to troubleshoot it using simulation. But not this one – it happens after 10s of thousands of instructions. I had been less than confident about using the built-in logic analyzer capability that Vivado affords for Xilinx chips, but this problem left me no choice. Fortunately, after just one false start, I was able to figure out how to make a change in the signals the logic analyzer had available, set triggers, and so on – so, not so bad.

Here is what the problem looked like that caused the Instruction Check. Note that the signal +S E CYCLE REQUIRED is going active (high) just after signal -S LOGIC GATE A. Now, that should not be a problem, except that +S ERROR SAMPLE is also high at this point, and since Logic Gate A is active, as well as E Cycle Required, the logic in the CPU sees that as a possible problem – knowing that if E Cycle Required is active, it ought to be activating Logic Gate R rather than Logic Gate A. (Note: At this point I had not included +S E CYCLE REQUIRED A (one of four different ways that +S E CYCLE REQUIRED can be asserted – and which turned out to be the “villan” in this case. Anyway, here is what the output of the logic analyzer looked like:

E Cycle Required Request with a Race Condition
E Cycle Required Request with a Race Condition

Now, this was not occurring on all or even anywhere near a majority of overlapped I/O operations. Below is an example (using the very same FPGA configuration) of a successful overlap. Note that in this example, +S E CYCLE REQUIRED is asserted much earlier – along with -S LOGIC GATE E so there is no race – E Cycle Required is ready and present long before the time of+S LOGIC GATE Z when the CPU makes the decision between Logic Gate A and Logic Gate R is made.

IBM 1410 FPGA Overlapped I/O Cycle With No Race Condition
IBM 1410 FPGA Overlapped I/O Cycle With No Race Condition

So, I went looking for possibilities:

  • Had I made a mistake when I entered the data for the associated ALDs?
  • Was this a race condition caused by the fact that I insert “D” flip flops to disconnect any timing loop identified by my generation code (within a single ALD) or by Vivado during synthesis (involving multiple ALDs)?
  • Was this a race condition caused because the FPGA gates are much faster than the original RTL logic SMS cards, and/or the fact that LUTs are used to collapse combinatorial logic into a decision table that may eliminate multiple levels of original gates?
  • Was this a very tight timing window in the original CPU?

During my investigation I came upon this tidbit in manual 226-2692, IBM Customer Engineering Instruction-Reference 1411 Input-Output Operations on page 46:

Service Note
Because close timing conditions occur in the areas listed below, excessive delay, or accumulated delays in the logic circuits may cause machine failures:
CHANNEL REGISTERS AND CONTROLS
E-cycle required
F-cycle required
E-cycle control
F-cycle control
Address channel

Well, do any of those look familiar? Like maybe the italicized one? While I have resolved the issue, I do not know, for sure, the exact nature of why I ran into it. The original CPU had the +S E CYCLE REQUIRED signal originating in (physical) Frame “D”, whereas the logic gate signals are created in Frame “C”, a couple of feet apart. As a guess I think it is most likely the the FPGA logic is faster than the original hardware in this area, such that +S E CYCLE REQUIRED could be being asserted earlier than the original engineers thought probable.

Regardless, I faced the issue of what to do about it. I had several choices:

  • I could try and tweak my generated logic in terms of speed, by adding delays, to see if I could resolve it that way.
  • I could inhibit +S E CYCLE REQUIRED A (the one that seemed problematic) in the presence of -S LOGIC GATE A so that in such a case, the E Cycle Required signal would not be asserted until near the end of the memory cycle of this enar miss.
  • I could inhibit +S E CYCLE REQUIRED (so, all four possibilities) in the presence of -S LOGIC GATE A

The first two choices might work, but would leave me in a situation where this problem could recur later on, in some other setting, whereas the third option would prevent it from happening a priori. The only downside that I could see would be that it might prevent a device from transferring data to memory quite as fast as the original.

So I investigated transfer speeds of various devices to see what they might be like:

  • Unit record devices have a core buffer in the IBM 1414 I/O Synchronizer, and are slow enough anyway, that it would not likely make any observable difference.
  • IBM 729 tape drives. The 729 IV transfers at 112.5 IPS at 556 CPI, the 729 VI at 112.6 IPS at 800 CPI. So, roughly, 112.6*800 = 90,080 cps, or a bit over 11 micro-seconds per character. So, every other cycle would be fine on a an 1410 with the Accelerator feature with 4.0 microsecond cycles – allowing it to “steal” every other core cycle.
  • IBM 7340 Hypertape Drives. Some models are 112.5 IPS / 170,000 cps tape drives (so, roughly 1500 CPI), or 5.9 microseconds/character. That would require making transfers in non-overlapped mode (see the 1302 disk drive, below). However, ones attached to a 1410 more likely operated at 34,000 cps – plenty slow enough.
  • A 1405 Disk Drive spins at 1200 RPM (so only 20 rps) and has a 1000 character track size (so, say 1200 to be conservative). That gives us about (1/20)/1200, or 50ms/1200, or 41 microseconds per character – lots of time.
  • A 1301 transfers characters at 90,100 cps, or 11 microseconds per character – so plenty of time using every other core storage cycle.
  • A 1302 transfers characters at 184,000 cps, or 5.4 microseconds per character. But on a 1410, these devices transfer data only in non-overlapped mode (even if the I/O instruction specifies overlapped mode) – because they must use consecutive storage cycles for their data.
  • A 1311 (the 2311 is not supported) has 2980 characters/track, and rotates at 40ms/revolution. this gives us roughly 13 microseconds per character.

These point to things being OK so long as the peripheral can “steal” every other core cycle. On top of that, the 1410 Channels are double buffered, so even if sometimes it takes 5 cycles to get two characters in or out, operation should not be affected. It would not seem the peripheral speed would prevent using the last option listed.

So, I made the changes, labeling them with a fictitious ECO “JRJ001” in the database and tested – diagnostic CU01 now passes without problems. Below is what the signals look like, timing wise. I believe (but cannot prove) that what happened is that +S E CYCLE REQUIRED ended up delaying until the next possible “last logic gate” (in a given memory cycle), which is typically logic gate E, as is the case in this capture.

E Cycle Required after Installing "ECO" JRJ001
E Cycle Required after Installing “ECO” JRJ001

So, what is next on the block?

  • Several enhancements to the console program, including merging what is now the main root window with the 1415 console form – no need to have them separate.
  • Run more diagnostics, by saving core images under my software simulator and transferring them to the FPGA memory to read them, as I did with CU01.
  • Experiments with speeds: how fast can I run the 1411 CPU before it fails its diagnostics?
  • Research into channel signals. I don’t have ALDs for the relevant IBM 1414 I/O Synchronizers, though I do have ILDs, which pretty well define the logic. But rather than parroting exactly what the 1414s would have done, I will likely just use VHDL using some of that ILD logic as a wrapper around communication to and from the PC support program, at least at first.

IBM1410 FPGA: Core Memory Upload – Dual Ported CORE??

After a year messing with other stuff, I finally got back to working on the FPGA implementation of the IBM 1410. With the CPU work essentially done, yet no peripherals, the issue to tackle was how to test the CPU – with no way to load diagnostics.

The solution I came up with was to take memory images I had generated (and could continue to generate) of diagnostics loaded into core (which are generally restartable at location 1) and load them into the FPGA.

Since I didn’t want to integrate this additional “feature” into the existing 1410 memory logic, I chose instead to implement dual port VHDL RAM memory that is underlying what the CPU things of as core, so I could load stuff into it. I then wrote a simple state machine using the existing multi-facet UART interface hardware (which also handles things like console I/O, lights and switches between the FPGA and the PC running the console program) so that it could load memory images from my existing 1410 Simulator. In so doing, I had to swap the top two bits – the simulator has the WM has the high order bit and the C bit as the next lower bit, whereas the FPGA has the C bit as the high order bit.

This turned to be a bit easier than I expected to pull of, and after a week or so of effort, it is now in place.

Loading up the main CPU diagnostic, CU01, it did not get all that far. The Subtract instruction has an issue where it isn’t placing the sign bit over the B field (result) units position – at least it is not doing so when the result sign is different from the original sign. Presumably an error in entering the information from an ALD or a signal misconnection. I suppose it could be the kind of thing that might have happened in the factory during the construction of a real IBM1410 where something was amiss.

Fortunately I can easily reproduce this problem under the Vivado simulator, which provides what amounts to a mult-hundred probe logic analyzer, and am using that to track down the problem.

Sun 4/60 SPARCStation 1

Over the past couple of weeks I have worked to reconstitute a Sun Sparcstation 1 (aka Sun 4/60) that I procured from UW Surplus way back in 1999, and which had been sitting on a shelf since then. The label on the front says it was priced at $0.00, however I think that was just the label the originating department slapped on it – I actually paid $18.99, tax included.

The disk drives had both died, but a SCSI2SD board (both V 5.2 and V6 / 2021) worked as substitutes, with little difference in performance. I set up both SunOS 4.1.4 (aka Solaris 1.4) and Solaris 2.7 (aka Solaris 7) – but the performance of the later Solaris was nearly intolerable. The video card that came with it was has a very odd Sun specific monochrome output, but I was able to acquire a color card at low cost off of eBay this year, and swap them out.

The machine has two Ethernet ports – one on the mainboard (le0) and the other on an SBus expansion board (le1) – the latter has a coax “thin net” connector. I don’t have that, but fortunately I have a couple of AUI cable to 10BaseT adapters so I was able to hook it up to my network.

These systems used a Mouse Systems optical mouse – and I got a mouse with the system, but not the mouse pad – and the pads are now essentially made of “unobtanium”. I found a site on the web where someone had printed their own – dark red horizontal stripes and vertical blue ones. It does not work very well, but at least it does work.

Somewhere along the line I also got a Sun SCSI cartridge tape drive shown in this photo. I have used that with PCs to recover cartridge data, but in this photo it is just for show.

For more info, including links to the PDFs I used to create the mouse pad, visit my UNIX® workstations page.

IBM 1410 FPGA: Console Output

Getting console output was going to require writing some VHDL of my own – I don’t have an actual IBM I/O Selectric available! I started out by reading through the material in the IBM 1415 Console CE Instruction manual (S223-2648) to design some finite state machines (FSM) to stand in for the console cams and feedback contacts.

The I/O Selectric uses cam contacts to control the timing of things like when the type ball tilt and rotate has completed, when shifts have completed, when spaces and backspaces have completed and when a carriage return has completed. It uses additional feedback contacts to indicate the parity of the received character, whether the keyboard is locked and the current shift state (upper or lower case).

To save time, particularly during simulation, I sped those timings up by a factor of 100. Mostly this just involved the console implementation module itself, via a VHDL generic parameter, but I also had to adjust the single shot on ALD 45.50.01.1 as well.

The Selectric also uses a set of solenoids to initiate actions such as printing a character, locking/unlocking the keyboard, spacing and backspacing, carriage return and shifting from/to upper and lower case.

After writing some simple state machines for the cam timing, I enabled the normal stop print-out in the CPU via a test bench signal, and then used simple VHDL with “wait” statements to check for the outputs and provide the input signals required by the CPU in order to test my understanding under simulation.

The first thing I came across was a latch on page 45.50.15.1 that did not have a reset. In real world hardware this can work because (unless it enters a meta-stable state on power up) it will be in one state or the other. However, under simulation that does not work – it ends up as an undefined signal – so I added a Program Reset signal to the latch at location 4A on that page to compensate.

The next thing I saw in the traces – which I hadn’t expected, but probably should have – was activation of the carriage return solenoid so I had to add the FSM for that. (Note: The I/O Selectric implements a carriage return by returning the type ball to the home position and initiating a paper (line) feed operation).

This was then followed by an “S” character – and the fun began. The interface feedback signals from the Selectric are full of names that end NC or NO (normally closed, normally open). Now one might expect that these refer to the state of those signals at idle, but the cam contacts aside, that quickly got pretty confusing – more so because most of these signals (except those that drive the solenoids) are active low. In addition, the keyboard lock signal is -W on the CPU diagrams, but +W on the 1415 Console Printer contact diagram page 40.30.01.0, and a couple of the feedback signals from the Selectric to the CPU are marked as -B level on the ALD page — but are actually -V level, as can be determined from page 40.30.01.1 as well.

Eventually I came to the realization that the best way of handling the NC vs. NO +/- confusion was to more or less ignore it, and instead use the signal name and level to determine what state a given signal ought to be in at a given time. That helped a lot. Once I got ordinary characters working right, I proceeded to code the state machines for space/backspace, and shifts.

Shifts were a little problematic at first, because the CPU drops the solenoid drive the instant it sees the feedback signal from the Selectric – which didn’t give me a clock cycle to save the new shift state.

Once I got that working under simulation, I turned my attention to getting that I/O from the Selectric to a PC for display. A few months back I had looked into using a MicroBlaze soft CPU to do that, but looking at how my Digilent Nexys 4 USB to PC connection works, I discovered I can run successfully at speeds of at least 115,200 bits/second, which should be plenty enough to run a simple flag bit/type protocol for not only console output, but also switch inputs, printer output, card input, tape I/O and disk I/O – perhaps adding a silo or two for lower priority devices. This is a huge simplification over what I had been thinking would be necessary.

But at this point there was also a little bit of extra work required. initially I had written the VHDL to use character output for the UART, but I subsequently discovered that VHDL doesn’t have a consistently synthesizable way to convert from character to std_logic_vector, so now that type-ball characters are specified as std_logic_vector bit strings, instead of ASCII characters – which is probably better in the long run, anyway. Mostly I am using the same encoding I used from the IBM 1410 simulator software, which in turn was derived from Joseph Newcomers IBM 1401 emulation software.

Once I had tested the UART VHDL, found at Nandland, I put together a test to combine that with the CPU and generate a bitstream for the FPGA. I had two small problems in the process – trivial ones, really. The first was that I keep forgetting to wire signal “+P SPECIAL +12V POWER FOR OSC” (which then feeds “+P SPECIAL +12V FOR REL DRIVERS”) to logic ONE. The second issue was that while most of the buttons on the Digilent Nexys4 are active high, the Soft CPU reset button – which I feed to the 1410 CPU Computer Reset signal is active LOW – wasted an entire day on that one. 8(.

One I did that, I obtained the following result: A printout of:

S 00009 00007 00007 .c … _ _

This is exactly the expected result (one which I had already observed in simulation). The “c” is a 1410 blank (different from the console space operation), and will print as a “b” using a PC-side application. Also, the three periods after that, which are the contents of the A Data Register, B Channel and Assembly Channel, have wordmarks – which you cannot see in the PuTTY output because they get backspaced over. Finally, the last two characters, the channel unit select and unit number registers for Channel 1 are wiped out by the backspace/underscore combination that occurs because they seem to be uninitialized, and therefore have bad parity.


Next on the list will be cleaning up the latches in the VHDL code which are currently tracking upper/lower case, tilt, rotate, space/backspace, and the character to be sent to the UART, and maybe a couple of more, as well as working on the PC side console application – starting with designing the protocol I will use for PC / IBM 1410 communication.

IBM 1410 FPGA Testing, and Memory

“There you go again”

What with the Thanksgiving holiday and all (even though it was spent at home, ’cause 2020), it took several days to ferret out the issue where simulation of a power on reset followed by START worked, but on the FPGA that failed. Of course it was bound to be an issue with triggers. However, I used the Integrated Logic Analyzer (ILA) to confirm that issue before I changed anything. Sure enough, card type DEZ needed the same adjustments as DEY: I changed it so that the transition of the AC SET input was required to occur after the transition of GATE ON / GATE OFF. At the same time, I moved all of that logic inside the FPGA clock transition section, to make it synchronous with the FPGA clock. That fixed the issue, which occurred on page 12.12.31.1

So now, after I load the FPGA, all I need do is press START and I see the correct waveform. (Also note that the transition of the output to ON (NEXT TO LAST LOGIC GATE) immediate turns off GATE ON – because that is exactly how it is wired. So first we see -S (active low) STOP AT F . LOGIC GATE D at about 320 into the trace. Note that GATE ON is already present, however, the trigger is held off by the “DCRFORCE” input coming from block 3B until STOP AT F . LOGIC GATE D goes true. Next, we see CLOCK PULSE 2 appear (but it gets inverted before it us used for ACSET, so it essentially matches CLOCK PULSE 1) at 389 on the diagram. Then at 392, the trigger sets, NEXT TO LAST LOGIC GATE goes true, and GATE ON is removed.

Corrected timing for power on reset followed by START

Decoding Memory Addresses

The IBM 1410 storage address register (STAR) is a five position two-out-of-five code register. However, it is not used altogether to select an address. On a read, all of the 10,000 position core memory segments are read, in parallel, each to its own B data register position. So, for a 40K machine, it has 4 B data registers, for 0-9999, 10000-19999, 20000-29999 and 30000-39999. On a read, the ten thousands position of the memory address is used to select one of the B data registers to gate onto the B Channel. During the write portion of a memory cycle (to change memory, or to regenerate memory if only a read is required), the ten thousands position is used to decide which B data register to update, if any, before the write portion of the memory cycle. The other B data registers retain their original contents from the read cycle.

At present, rather than simulating the full core plane of the IBM 1410, I chose to implement memory, for now, using a binary address and (probably) an array of 10K FPGA Block RAM segments. This means that the binary addressed RAM for the FPGA IBM 1410 uses a 14 bit address (to cover 0-9999), with memory arranged in the same 10K sections.

The inputs into this decoder are the -Y MEM AR UP/TP/HP/THP signals, which are in two-out-of-five code. The output from the decoder is a 14 bit binary address, 0 – 9999. This was implemented “brute force” by decoding each of the positions to the appropriate binary number, so the UP decodes to 0 – 9 in a 14 bit binary number, the TP decode to 00 – 90 (by tens) in a 14 bit binary number, and so on. Then the four binary numbers are simply added together in the VHDL – leaving the implementation of the adder for the tool chain to figure out.

Memory – and a Startup Issue

Next I created a simple set of Block RAM modules (BRAM) along with a VHDL wrapper for the 40K main core unit, accepting the aforementioned addresses in 2 out of 5 code, the Ten Thousands position (so that eventually it can tell if it is the 40K main core or the 60K Z Frame core), inhibit signals, and output sense signals. In order to more easily generate the necessary BRAM enable and write enable signals, I also brought out the MY_X_RD_1 and MY_X_WR_1 signals.

After some fussing I got my BRAM module working under simulation, but ran into an odd problem where during startup the system would overwrite location 00001 with garbage (and presumably 10001, 20001 and 30001 as well) because the system was left in Logic Gate B (LGB) state during the power on reset that then proceeding through a memory cycle once the power on reset was complete triggering the computer reset- thereby writing those locations with uninitialized garbage. (Computer reset will finish a cycle if it is encountered mid cycle to avoid corrupting core.)

I temporarily disabled memory writes, and then found I could successfully execute my halt instruction (WM/. WM/. in locations 1 and 2) under simulation AND on the FPGA.

The startup issue was interesting. I had supposed that the power on reset signal issued on ALD page 12.65.01.1 would start OFF, come ON during the power on reset, and then turn OFF again. However, that was having the undesirable effect of letting the system progress from LGA to LGB during the power on reset as mentioned above. Some study of the aforementioned ALD, along with the IBM 1415 console manual (the power on switch is located there) made me realize I had misunderstood.

That power on reset signal is asserted during power on to keep the system in a reset state (and thus in LGA) for an RC constant of about 500ms. Then, after that, the signal goes to logic 0, triggering the one-shot at block 2D to do a computer reset. At that point, the machine is in LGA, and the computer reset will leave it there.

Since I already have a system initialization VHDL process in the FPGA VHDL logic, it was easy to manage the power on reset signal there – indeed, the two may eventually become one, as they both have the same purpose of getting some stuff set up before letting the IBM 1410 CPU start.

This tested OK under both simulation and on the FPGA, though I have not yet verified that the FPGA is actually writing the contents back into the BRAM.

Next up: testing write by setting a wordmark somewhere (to verify read/write), and then halting, and a simple loop – both of which should be possible with my current VHDL by just changing the RAM initial values.

Update: The instructions sequence, starting at location 1, of setting a word mark at location 8 (which takes locations 1 through 6), a NOP instruction (reading out the set word mark instruction needs a wordmark on the character after) and then a period (halt without the word mark) behaves correctly. Wohoo! I have something of a CPU.

Next up: starting work on the console.

Volume IX is Now a Memory

Testing of the ALDs in volume IX is now complete. With that all ALD pages for the main CPU and the channels (including the I/O channels E and F) have been tested, some more thoroughly than others. Memory spans volumes IX and X, so memory isn’t done yet.

After that comes the last volume I plan on working on for now, volume X. The main piece is the I/O Selectric console support.

Adventures in Error Land

One of the things that is interesting about the IBM is the extent of error checking. The Core has parity (check bit), but all of the major data paths (called “channels” on the IBM 1410) as well (A, B and Assembly channels, for example). Unfortunately, some of this is not covered in the ILD diagrams. While it is covered in the System Fundamentals manual, the logic actually used on some of the ALD’s is a bit different from channel to channel, even though the end result is essentially the same. In particular, while all of the pages use card type DHL (And-Or-Invert, or And/Nor, if you like), some of the pages use plain old NOR gates in places in combination with NAND gates – resulting in differences in positive +S inputs vs. negative -S inputs, so that I was not able to just copy the test bench code from one channel to the next.

Also, page 18.13.03.1 had an error – combining two outputs with and AND on the ILD when the circuit is actually OR. When the test failed, the reason was apparent, comparing it with others on the same ILD, figure 59.

Page 18.14.06.1 had a different kind of error. The polarity of the signal shown as “+S LOG GT E.2ND+3RD CHK TEST” is incorrect. It is correctly depicted as -S on the destination sheet, 18.14.07.1. The ILD also shows this as Logic Gate F rather than E, even though the ILD for the destination page (on the same ILD sheet) correctly shows Logic Gate E. So, yet another vote of confidence for the testing process. 😉

Set… No, Reset…, No Set…. I’m all Confused

Page 18.14.03.1 presented an interesting challenge. This is the Address Channel Validity check trigger. It is reset via collector pullover of the OFF output when a valid character is present and sets when an invalid character show sup (except during Logic Gate A of a 1401 cycle). It then also has a latch, along with a feedback path besides, to keep it set. That feedback path prevents a valid character from resetting the trigger once set.

But it also has a DC Set via the check test switch. The two are connected to their respective inputs by 4.7K ohm resistors. The interesting situation happens when you think about there being a valid character present (thus the off input is pulled high) when one presses the check test switch (which wants to pull the on input high). If this were ordinary logic levels fed from different gates, this would leave one input being logic 1 (0v) and the other being logic 0 (-12V) and would leave the base on the “on” side in no-man’s land. HOWEVER, the check test switch supplies -V voltage – more than enough to force the “on” side on and the on output to ground (logic 0).

In VHDL, one or the other necessarily takes precedence. When I developed the circuit for the DEZ trigger card type, I set it up with the Off output pullover taking precedence. That has worked fine – until this page.

But that does not mean one ought to reverse it. That might break some other page. For my test bench, I worked around the issue by putting an invalid character up long enough for the trigger to set. It would be interesting to scope this situation on a real machine, though that will never ever happen.

(Oh, and did I forget to mention that Triggers are a Pain? 8D).

Oh, and have I mentioned…

Page 18.14.08.1 presented a challenge. It has a trigger (naturally) with the ubiquitous pull on and pull off connections. Unlike the previous ones, however, this pull off DOT function is driven by two gates instead of just one. The program logic recognizes the case where a single gate pulls on or pulls of a trigger, but not one where more than one gate is involved.

Rather than futzing with the program logic for what appears to be a single case (we’ll see about that), instead I inserted a gate “FXOR” (for faux OR) befoer the DOT function to fix it.

(Oh, and did I forget to mention … never mind. 😉 ).

We Interrupt this program…

Near the end of Volume IX were the ILD pages for interrupt processing. Most of that was straightforward: if interrupts are enabled, and an I/O operation completes (presumably in overlap mode), an interrupt is generated.\

But while there is a section on interrupts in the CPU instructional materials, including some ILD-type diagrams, their coverage is not as thorough as a regular ILD.

There is also a special case for interrupts for unit record equipment, perhaps intended for SPOOL (simultaneous peripheral operation online) support. There is a toggle switch for turning on interrupts for overlapped I/O operations (including 1301 seek), console inquiry, console output, non-overlapped seek and disk device “attention” signals.

Unit record interrupts are special, however: the operator must select one (card reader, punch, printer or paper tape) using a rotary switch, and then push a special priority interrupt button. This generates an initial interrupt – completed I/O turns on subsequent interrupts.

This last one was tricky to test, because it is implemented using a set of three latches – the first one being a “one and only one” latch to handle the button press. (We didn’t ever actually use that on the School of Business IBM 1410).

Chains of latches, especially where the signals are not brought out to the sheet edge are almost as much “fun” to work with as triggers. 😉

Mutually exclusive logic blocks

Memory testing also brought up the first case where I could not test an ALD without disabling one or more logic blocks. In particular a couple of sheets had gates for both feature S10 (10K of memory) and S2 (20K or more of memory), and the logic design was such that they cannot coexist, so I used the application to disable generation of the logic blocks related to feature S10 on those pages. (Other pages may still have both – but in those cases coexistence seemed possible.)

Load Sharing Matrix Switches

While I am testing or at least sort of testing most of the memory related circuits, including the sense amplifiers from a digital point of view, and the drivers for the LSMS units, I am not testing/generating/simulating the LSMS units themselves. This is mostly because each LSMS takes up four logic blocks on an ALD, and I don’t currently have a way to merge more than two logic blocks or merge two that are not vertically adjacent to each other. Finally it would just add complexity to the memory unit when I generate an FPGA to actually simulate the core. Instead I will just simulate Read/Write/Inhibit on 8 bits at a time directly from the storage / memory address register (variously referred to as STAR and MAR – the former in the documentation, the latter in the ALD signal names.

A Sense of Forcing my h-AND

Finally, the ALDs related to sense amplifiers required special treatment. For each bit of each of the possible four memory readout characters on a system with 40K, there are two sense amplifiers, one supporting 5K bits of a core plane – either the 0-4999 or 5000-5999 portions. These gates’ outputs are then connected together, but not using just load resistors. Instead, each sense amplifier card has a diode on the output such that when they are connected together driving a -Y signal level, they comprise an AND gate.

The HDL generation currently supposes that B level DOT functions are AND and that the others are OR (with a per signal level setting). Most cases for Y signal level DOT functions are indeed OR, but not in this case, because of the diodes that are present (anode facing out from the gate). Fortunately, a while back I added the ability to force a given DOT function’s generated logic, so this was easy to deal with.