Friday, December 9, 2016

Contemplating replacing Diablo data separator circuit with fpga based phase locked loop


I developed a watchdog timer in the fpga that will emit a signal if the time between clock pulses is 700ns or longer - this will help me flag spots where the Diablo drive is misidentifying a 0 bit with late clock as a 1 bit and missing clock. I can then reliably trigger both logic analyzer and oscilloscope to see the behavior of interest.

Data is recorded on the disk with a non-return-to-zero encoding (also called frequency modulation which evolved to MFM for the first PC disks), where bit cells of 600 ns are written by reversing the magnetic flux once or twice. At the beginning of each bit cell, the flux is always flipped, which is the clock. In the middle of the cell, if the bit in question is to be a 1, another flux transition occurs, whereas a 0 bit value does not cause a reversal.

This is why disk records start with a long string of zero bits, to help the reading circuitry to synchronize on the clock bit as the start of a bit cell. The clock bits are the only transitions when the data values are all zero.

The start of meaningful data is signalled by a special non-zero pattern, which for the Diablo is a single bit cell with a data value of 1. The reading circuits pass through the flux reversal as a clock pulse and then flip the logic for less than 500 ns so that any reversal in that interval will be passed as a data bit value. This window of time where a flux reversal is a data bit is how the circuit separates clock from data pulses.

I have found spots on the disk where a record gets a checksum error, at least on some read attempts, because the clock pulse is misreported as a data pulse. Specifically, the bit cell is meant to contain a value of 0, so that the flux reversals are the clock at the start and end. In this case, the next reversal which is intended to be the clock is passed along as a data value of 1, because the timer window is still open. The clock pulse arrived a bit early.

Now, when the clock pulse following a 0 value bit cell is misrouted as a 1 data value, and the next bit cell is also a data value of 0, then we will have a longer than usual gap until the next flux reversal. The two 0 bit cells are collapsed together as a single 1 bit.

Out of the data separator circuit, we see the clock pulses skip a beat, with 1200 ns between pulses at this point. The data pulse is also wrong and more sinisterly, the serial train of data bits is compressed with two lost 0 bits reported as only a single 1 bit. This misaligns all the remaining data bits and checksum for the remainder of the record.

It is possible that I could detect and correct for this error, but it would be complex. I would need to establish the bit rate, adjust to stay synchronized with the clock transitions and then look for malformations. One such would be a skipped clock pulse coupled with a 1 data value. I could morph that into a pair of clock pulses representing the two data bits of 0.

I would need to look carefully at all the possible cases - 0 bit cell where this happens followed by a 1 bit cell, as well as other cases where clock and data are misrouted by the data separator circuitry. In essence, I will combine these to produce the flux transitions and separate them myself using more sophistication than a simple timing window.

I can also imagine errors where the pulse is split between data and clock, when the timing window elapses somewhere in the middle of a flux reversal pulse. If I combine the ReadClock and ReadData signals myself to form the original pulse train before the separator does its task, I can bypass the source of these errors and accomplish the detection of bit values correctly.

I need a second order digital phase locked loop to recover the clock properly, then use that to indicate bit cell boundaries and watch for the data 1 pulses. The incoming signal is messy, having timing jitter due to rotational variations on both write and read passes plus bit peak shifting. It may also suffer from minor variations in the media surface and from oscillations of the head heighth.

Beginning with single density floppy disks and PC era hard drives, the written signal was 'pre-compensated' to minimize the shifting of pulses upon reading, but no such technique was used with the Diablo drives.

Floppy disk data separator chips were available but are intended to support the much lower bit rates of the original SD and DD floppy drives, 250Kbps to 500Kbps whereas the Diablo is streaming data bits are 1.67 Mbps. The phase locked loops available on the Spartan 3E fpga chips won't operate at so low a frequency, requiring minimum frequencies in the range of 10Mhz.

Thus, I have to work out a different method. Opencores has a DPLL although I am not certain how good it will be at handling disk signals.The goal is to generate a train of clock outputs that is synchronized to the time averaged clock pulses observed from the head, then use that to cleanly separate transitions that are far enough from the clock to be considered a data bit value of 1.

I will implement this in the fpga, digitally mix the ReadData and ReadClock as an input, create the scaffolding for the data separator based on this, then compare the results of this versus the Diablo separator circuit. This is going to be complex design work. 

Thursday, December 8, 2016

Emulator board designed and fabbed out


Today I completed the emulator role board design and shipped it off to a different foundery,, as they would do a quantity one order. I need to be more confident in the correctness of the board before I order more.

Multilayer view of PCB design for emulator board

The above board is 6" wide by 4" high and has an 2x20 IDC type male shrouded connector on each side. The left one is mounted on the bottom of the board and plugs downward into the female connector on the Digilent FPGA extension board seen below. The right side connector is mounted on the top and accepts the 40 signal ribbon cable that runs to the Alto computer or other system that makes use of a Diablo 31 disk drive.
Extension board, fpga plugs to left and driver/emulator board sits on top
Below is the multilayer view of the driver board, the same size as the emulator board but with different numbers of input and output circuits and connections as befits its role. It also mounts atop a Digilent extension board that will in turn plug into a Nexys3 fpga board.

Multilayer view of PCB design for driver boar

Finally, to round out the pictures, here is the Nexys3 board onto which the extension board is connected. A USB connection on the left lower side communicates with a PC in order to load and store disk images.
Nexys3 fpga board hooks to extension board

Wednesday, December 7, 2016

Driver board released to foundry, beginning on emulator board.

Wednesdays as always I spent most of the day at CHM, meeting with the 1401 restoration team members. 


I spent another day iterating with the online free design verification tool associated with the 4PCB foundry and with my design on DesignSpark PCB. I really cleaned up the design substantially, ensured a good silkscreen layer, but had to accept some spurious errors that reflect limitations of the checking software.

Specifically, a metal plated hole through a board is called a 'via' and links a copper trace on one layer to another trace on a different layer. Mostly, these are linking the top and bottom layers of the board, where traces run left to right on the top layer and top to bottom for the bottom layer. Thus, a signal can pass over another using the 'other' layer.

I designed this for a four-layer board, which has two internal layers in addition to the top and bottom. One of the internal layers is ground and the other is the +5V power. If a component is connected to ground or +5V, it has a larger via which is electrically connected to one of the inner layers.

The design review software spots vias when they have signals connected to them on both top and bottom, the typical usage, but if the via is connected internally, the software confuses the plated hole with a hole that a component lead will fill. If a component is attached to the hole, it has to be soldered on.

Any spot where soldering occurs must have an opening on the solder mask layer, all other parts of the circuit board to and bottom are insulated with a thick green coating. Since the software falsely thinks the power or ground via is a solder pad for a through-hole component, it is flagging to me that the solder mask is covering this pad. That would render the pad or component hole un-solderable but in this case, no solder is needed.

I placed the order for four boards, to arrive in a bit more than a week, at a net cost of just under $300 or $75 per board. I should have all the components to attach by the time the boards arrive, thus I can assemble them at that time.

It is time to begin designing the complementary board, for the disk emulator role, which will use the tried and true components and circuit elements, only connecting them in a different order to suit the disk signals going in and out of the Alto computer. 

Driver board PCB designed, prepping for manufacturing and components ordered


I did battle most of the day with the DesignSpark PCB tool attempting to get a good quality board designed. A reasonably large board, 4 x 6", less than 40 components, and building it as a four layer board, which shouldn't be challenging. However, I may have to hand route everything.

I finally spotted a problem, that the ground and power planes in the four layer board weren't being used for ground and +5V. That cut down on routing and had the added advantage of handling the fairly beefy current requirements of the peripheral driver chips, which can sink 150ma per signal line when it has a logical 1 value. The worst case is during a seek command, with multiple track lines active plus the strobe.

The next step was some intelligent placement of the components, knowing how they need to be routed, to minimize crossing paths and conflicts. The pull up and pull down resistors that form the terminator for the input signals were the major factor in congestion, thus they were the major focus of my work.

I also moved the filtering capacitors and the peripheral driver chips to make more room for signal paths on the board. The result was a good clean routing with no manufacturing check conditions. With that complete, I produced the outputs needed for board manufacturing - gerber and excelon format files for the various layers and drill holes.

I will order two boards and enough components to build 4 or more boards- connectors, chips, resistors, and capacitors, which will let me complete the boards once everything gets here.

The foundry I chose,, has a free service to analyze the files for manufacturability issues. I made use of it and found quite a few niggling errors and one significant one that slipped past the design checks of the DesignSpark PCB software. Time to iterate until I get satisfactory results from the foundry's free check software.

Monday, December 5, 2016

Write sector confirmed to work with new driver board, time to convert it to a PCB


I set up the contents of cyl 0 head 0 sector 7 from the archived disk image, loading it into RAM, and then issued a WriteSector transaction. The sector read back in without checksum errors. I ran the tool to ReadEntireCartridge into RAM and dumped both the RAM and validity check vectors out.

Unfortunately, there is a complication with the Digilent utility that does the upload and download of RAM. It advances the RAM address registers Reg1001, Reg1010 and Reg1011 while it loaded RAM, but does not reset them. Thus, when I thought I had dumped RAM out, I was beginning in RAM at the wrong point, producing garbage. The validity bit vector contents use their own address registers, Reg10001, Reg10010 and Reg10011 so that they worked properly.

I had to fire up the testbed again, ReadEntireCartridge again and then dump this with the RAM address registers at 0. That would allow me to post-process the file and compare the archived disk to the bitsavers image.

I found that the file read from disk was about like the last time and that the sector I had written was retrieved with zero errors, as an exact match. This completes the checkout of the new board, which I can now use in all further activities.

It is time to turn the driver board into a PCB, eliminating any point to point wiring. I will fire up a PCB design tool, draw it out and submit it to a foundry to produce several copies.

Tomorrow it will be time to resume studying the exact conditions under which sectors get a temporary or permanent checksum error - looking for anything that can be mitigated, corrected or anticipated in the pursuit of an even lower error rate. 

Sunday, December 4, 2016

New driver board seems to be working properly; built logic to write an entire cartridge in one transaction


Today I switched back to testing the new driver role board, since the logic analyzer connections and setup are mostly intact. The goal is to verify that the unit with the new board still seeks, reads and writes correctly.

I verified that the SelectUnit1 signal works, in that the drive won't turn on FileReady or ReadyToSRW unless I am selecting it, nor will it respond to commands. I also stepped it through the binary powers of cylinder address to verify that each Trackxx signal is correctly wired. I watched the heads move to the commanded values 1, 2, 4 . . . 128

Next up, I did a read of Cylinder 0, Head 0, Sector 0 which completed reporting no detected checksum errors. I also did a ReadEntireCartridge transaction and watched it walk through all the sectors, retrying on those that have problematic signals with intermittent or permanent checksum errors.

All the above looked good and I monitored the WriteGate to be sure we weren't turning this on inadvertently. It is time to capture the cartridge image as a test of the recovered data images, comparing it to the bitsavers archive version and to previous recorded images. If that passes muster, the final test is to write a sector from RAM and verify that it is read back properly; the board will be fully tested.

The captured disk image and checksum information was captured and then compared to the archived versions to see whether we seemed to be more or less reading properly. The results were quite good, similar to what I experienced with the original board.

The final test, therefore, will be to load a specific sector's contents into RAM, write it to the disk, and then read it back to verify that this works. I will undertake this tomorrow.

I did want to create a WriteEntireCartridge function, analogous to the ReadEntireCartridge but that writes an archived pack image downloaded into RAM onto a blank or scratch cartridge. We have various images from archives that it would be great to have on a disk, such as the Smalltalk system.

In most cases, we will just use the disk emulator role and not need a physical cartridge, but there is something satisfying about running the Alto from a real disk. This cartridge writing function will be a tool used only a few times, invoked as transaction code 5.  Testing will be difficult, as I need a known blank or sacrificial cartridge.

The logic was completed and synthesized, using the ReadEntireCartridge logic as a template, so that it has decent chances of working correctly on the first try, but can't try it until I have a sacrificial cartridge installed. 

Saturday, December 3, 2016

Making progress on emulator role of disk tool


I worked my way through debugging the hangup of the state machines that should be continually 'reading' the contents of the current cylinder and head, making bits available to emit whenever ReadGate is on. I went through several rounds instrumenting the fpga until I found where it was hanging.

Looking at the code, my mistake glared out at me. In one step of the state machine, I wait for the SectorMark to go on, indicating we are at the beginning of a sector to be emitted. It was here I was stalling.

Since this logic supports two roles, a driver of a real disk drive and an emulator that substitutes for a disk drive, it has an incoming and an outgoing version of SectorMark. The emulator version is SectorMarkOut, while the inbound driver version is simply SectorMark. As you may suspect by now, I was waiting on the inbound SectorMark that will never arrive while in emulator mode.

After the usual lengthy run to create a new bitstream, I ran with the state machines hung in a different place, trying to generate the preamble. I needed to reload the serializer for each word, even though the contents didn't change, but I wasn't doing that during the countdowns.

My linkages to the serializer weren't working properly, which held up the state machine that emits ReadClockOut and ReadDataOut signals. Another round of synthesis and I was back to watching the behavior of the emulator. 

I am now seeing clock and data pulses emitted, but they don't seem to be in the proper relationship to the SectorMark pulse. Time to work out how to hook up the logic analyzer in order to debug this further. 

However, I want to go back to the driver mode, test out the new version of that board I built and make sure the tool is fully ready to read and archive all the cartridges we have on hand, including the personal cartridge of David Boggs which he has loaned us for this purpose. 

Getting all the data read and uploaded is a priority of the project, after which we can play around with some packs to install different software images such as Smalltalk.