Thursday, September 29, 2016

Diablo tool now reading and writing RAM across USB, almost ready for testing and cartridge archiving


I chased down a hot bit in my design that was spuriously triggering memory cycles over and over. With the cause discovered and corrected, I could move on to debugging the USB read/write mechanism.

I brought out signals to the PMOD connectors and watched them on the logic analyzer to verify how my transactional FSM was dealing with the autoread/autowrite activity from the USB link. It was both good and bad news.

The good news is that I saw a reasonable sequence beginning with the Start signal, with or without the Read status line depending on the direction of transfer, and then the state machine wrapped up exchanging Done and Start.

The bad news was a flaw I spotted in the byte mode machine, which I corrected and then began to see that RAM was indeed storing and retrieving data. What I wrote came back properly.

I fired up the 'read sector' command and then read memory using the Adept utility. I was seeing the data although I think I have something backwards in how I am fetching RAM contents in word mode. I altered instrumentation as well as pored over my logic and the documentation. I am close, at least with the word mode retrieval.

Went to byte mode and did more testing. I am getting the data words out of memory, but the bottom half of the word comes before the top half. I have to look over all my signal assignments and verify whether this is the usual PC phenomenon of reversed bytes or if it is a flaw somewhere in my logic.

This turns out to be the expected order - it reads the low byte first (even address) then the high byte (next higher odd address). I tried the file transfer function of the Adept utility and got the same data that comes back in the autoread/autowrite mode.

The one issue is an off by one kind of error, in that the uploaded file is missing the first byte and everything else is shifted over by one. This is similar to the odd results I am getting reading via the autoread registers.

Since the actual storage of the deserialized words during a sector read is done as a word, it is not possible to drop half the word and shift things over. This tells me that my problem is in the USB autoread/write logic and addressing.

Each round of diagnostics takes 20+ minutes to synthesize and produce the bitstream, so that progress is steady but not speedy. Soon I will be out of energy for the evening.

Tuesday, September 27, 2016

Replaced logic to read/write RAM over USB link


Today I rolled out all the logic that should manage the RAM input/output from a USB connected computer to the onboard RAM which is the disk cartridge buffer on my fpga board. I had to accommodate the 'autoRAM' behavior of the digilent reference code, since the Adept utility depends on this.
Logic from Digilent I replaced with my own code
That behavior was a bit complex, given an 8 bit wide extended parallel port (EPP) is the USB transport but the RAM is configured to be 16 bits wide to match the Alto. The digilent behavior operates in either byte or word mode.

Word mode is where pairs of reads or writes are used to deal with a single RAM word.That meant an internal register to hold one half of a word and a state machine that alternates between actual RAM access and dummy cycles manipulating the internal register.

Byte mode writes a single byte and expects the fpga to determine based on the low order address bit whether this goes in the upper or lower byte of a given RAM word. I don't have insight into the Adept utility and can't guarantee that it only uses one of these modes, so I had to implement both.

A further twist is that the RAM itself is 16 bits wide, but has two control signals, UB and LB, which determine whether the write updates the top byte, the bottom byte or both. Similarly for reads, it only makes the output bus active for the selected byte unless both are requested.
Digilent provided state diagram for memory controller module

My lowest level RAM access FSM always deals with 16 bit words, reading and writing both upper and lower halves. I didn't want to modify this to support the digilent byte mode, where a user may write only one of the halves of a given word address.

The performance critical behavior is dealing with the disk drive and the host computer, which always occurs as full words. I left my inner FSM as it is, so I had to deal with the half byte problem up in the new logic. Essentially, I handle a byte write by first reading the entire existing word, replacing only the half being 'written' and then writing back the entire word.

I am actively debugging all this tonight.

Sunday, September 25, 2016

Testing on the Alto and Diablo successful, booted up today


Finally feeling halfway human again, so spent the morning working on a complete redesign of the memory link logic, as the reference code from Digilent is untenable and too convoluted to attempt to modify.

As a utility function with many uses and options, it is fairly complicated. It has options to read and write to onboard flash, which I don't need. It can address memory at a low level, directly toggling control lines, which I don't need. It can read the RAM in either byte wide or full 16 bit word mode.

Since this is accessed from the Digilent Adept utility program on the PC, I am not certain that it always uses the word mode, so I must implement both byte and word mode functionality. This will take a bit of time to get working properly, but at least I have my memory access working to write those data words into RAM.

The utility works fine to read and write all registers except for the 'autoread/autowrite' register 14 which I need to move data between RAM and PC. I will continue finishing the design while working on the Alto this afternoon.

I saw signs of unreliability between the Xilinx toolchain and the Digilent Nexys2 board, something I have experienced in the past too. Some days back, switch 6 was not recognized at all, but it began to work after a few days. This morning, my memory request signal output on a PMOD pin was not working, but when I made changes to deliver this signal on a few extra pins as well, suddenly the original pin was functional

It seems that the bitstream going to program the fpga is corrupted, or some paths inside the FPGA don't work, which the vagaries of placement and routing choices will mean that one bitstream will expose defects while wholly unrelated changes produce a new bitstream where the defect is avoided.

In the afternoon, the restoration members met to test a few things with the Alto. I want to use the logic analyzer to capture the data words being read from the Diablo. Ken likely wants to test some Ethernet tool functions. We have a boot disk given to us by the LCM which we will attempt to boot up too.

We hadn't gotten a good trace from the logic analyzer, mostly due to attempts to create overly clever triggers for the capture of data, but decided to move on to testing the disk cartridge that LCM made for us.

We attempted the boot but it didn't complete. As we looked at the data words coming in, Ken noticed that the header showed us at cylinder 8, sector 0, not the boot location. Removing the disk drive cover allowed us to look at the rotary indicator dial. Indeed, as soon as we tried to boot we saw it seek out to cylinder 8.

Examining the cable carefully showed no problems, so we decided to put the scope on the disk signal that must be active (at ground level) to cause a seek. We didn't see it. The problem, whatever it was, went away from all the cable manipulation.

Of course, no boot because we had the erased cartridge in the drive. Next up, we put our new boot cartridge in place, hit the reset button and had a successful boot! The system consistently boots but we judge that we have a few relatively minor issues to fix before everything is 100%

The mouse does not appear to work, possibly due to a burned out incandescent bulb inside. When we run the microcode validation diagnostic (MADTEST), it suffers a failure and exits to the debugger (SWAT).

Some other applications fail in exactly the same way, such as Bravo, the editor, and Draw, the graphics program. Others, such a the CRT test or the KB test, work just fine. The SWAT screen and reported address is always the same, regardless of which application fails.

As we devoted only an afternoon to this session, we ran out of time to do much more than collect plenty of data which will be poured over in the coming days.

Saturday, September 24, 2016

Working during lucid moments, in some cases cleaning up fever distorted logic

I finally had enough energy to sit at the PC to rework the RAM access state machine. Still far too exhausted to join the team working on the Alto. I managed about 30 minutes work on Friday and a couple of hours on Saturday.


Here is the signal timing chart that my state machine should be producing.

RAM protocol for pseudo-static read/write
With my state machine appearing to work perfectly in simulations, I built up simple FSMs to write the slide switches into RAM when one button is pushed, then read the content out into the LEDs when another button is depressed.

Once I know that I can read and write RAM properly, I will move on to replacing the Digilent utility code used to move files between PC and RAM. Tested the FSMs until I got this right. All was good thus begin reintegrating the utility access logic.

The main discovery I made today is that coding VHDL while feverish is not a good idea. I wrote "if signalx <= '1' then" several times, when it should have been "if signalx = '1' then". No error from the toolchain, but results in an assignment of '1' to the signal and an always-true condition for the if statement, not what I wanted at all.

Using the eight LEDs on the board, I displayed the top half of the word last read from memory, which matched the last data word of the disk sector emitted by my internal pattern generator. The problem is that I should not be doing any read of memory when reading the sector, everything should be a write.

This is a clue of a potential flaw somewhere, essentially a weakness in my logic for choosing when to write versus read. I made some improvements and tested more. The spurious output of data was resolved, but still not seeing data through the Adept utility.

At this point, going to recode the logic myself, leveraging my working memory access FSM. Setting up the FSMs for reading and writing the registers, particularly registers 9, 10 and 11, being the RAM address, was easy. More work was implementing the transactional "handshake" for the read or write to the automatic register 14.

I was still working on it by the end of Saturday, still going through bouts of fever but gradually getting better. Tomorrow I will finish up the utility access to my RAM read/write machine, test it and hopefully be ready to read disk contents in the afternoon.

Thursday, September 22, 2016

Flat on back with flu

I fell ill with a very strong influenza last night and the extreme fatigue has kept me almost immobile all day. I got nothing done on the tool or any other project.

Wednesday, September 21, 2016

RAM problems due to Xilinx handling of tristates (again)

Wednesdays are when I meet with the 1401 Restoration team at CHM. We had problems with one tape drive, which a team member traced back to a bad SMS card; swapped the card and tape drive now working just fine. Overall, the systems are in fairly good shape - exceptional shape given their age.


I know that RAM itself works because I can write data via the Adept utility and retrieve it successfully the same way, but my logic to write each extracted word from the disk into RAM is failing.

As I set up instrumentation, I think I discovered the source of the problem. It is the incompetent handling of tristate signals by the Xilinx toolchain. There are quite a few places where the Digilent provided code treats output signals as tristates - emits Z unless the module is active. I also followed that practice.

HOWEVER, the signals as defined in the top level module are type OUT, not INOUT, which means they are not tristate pins. I suspect that nothing good comes from having two separate sources that are treating the signal as a tristate - only emitting values when active - but the actual signal is not tristate hardware.

After I changed everything to INOUT, the Adept function to read and write to disk no longer worked. Grrrrrrrr. All because I leveraged some reference code which insisted on this stupid tristate behavior and won't play nice if integrated.

It is time to write my own logic to replace at least some of the Digilent reference code. I will be successful when I can read or write RAM. Before I coded it all from scratch, I realized that I could take all the control signal assignments out of the Digilent provided code section, where they used tristate Z as the default, and reimplement them in my memory access FSM.

Any time my memory FSM was in the idle state, it would connect the signals the same way as in the Digilent code, yet not use Z for inactive. In other words, these assignments in the idle state were replaced in toto by my assignments in all the other memory FSM states.

My first stab at this didn't work correctly - reading and writing via the Adept utility is funky, which is the only way I can verify things right now. Don't know if my routine is writing correctly but can't retrieve it or if everything hosed up. Still trying to avoid writing a lot of logic from scratch.

I came up with an improved scheme and will implement it tomorrow.

Tuesday, September 20, 2016

Problem with driver board seems to be with RAM write and read

More woodwork today with Diablo tool work in the afternoon in between tasks. Once the last pieces are painted, I can nail them down and this facade is ready to be assembled on site this weekend.

Roof behind columns
Sign to install near roofline

I discovered that slide switch 6 is not working on the Digilent board I am using - just a random defect of some sort. Everything else appears to work, most likely this is a failure in the switch itself.

I am directly watching the pattern generator output and the bits being emitted don't match what should be delivered. I was not sure if the pattern itself is malfunctioning or that the problem is in the way the driver logic is recognizing sync words and other data.

I programmed the analyzer to give me symbolic names for the state machines I am tracking - much easier to interpret than the binary digits emitted from the board. It will help me see if the logic is going awry somewhere.

I am seeing the state machine correctly collect the words as it should see them based on the pattern generator, therefore I have to turn my attention to whether I am writing properly to the on board RAM. I looked over examples of how this is addressed by Digilent reference code and adjusted my logic accordingly.

Logic simulator results look correct, so time to run this transactionally from the PC. The advantage of the built in test pattern generator is that I can trigger a read sector, it should write the results to memory, and then I can read out the words using the Adept utility. I should quickly see whether I wrote the proper data or not

The results were disappointing. The logic analyzer showed me triggering the writes with the proper extracted word, but when I read the RAM back afterwards nothing had been written there. I ran out of time tonight, but the resolution to this will require me to significantly reinstrument the signals going out to the logic analyzer, so that I can watch the RAM signals myself.

The big open question is whether the signal quality from the real Diablo drive through my level shifters will give me a good clean read of the sector. I need to hook up to the drive at our next session on Friday.

Monday, September 19, 2016

Testing with built in pattern generator and logic analyzer

Once again my time is divided, in this case I am helping build a Bavarian building facade with my wife, to be used for guest photos at a Oktoberfest themed fundraiser for the organization where she is involved.

Fortunately for my electronic hobbies, the building involves cutting batches of wood which must be painted by my wife and dry out before I can install them and repeat the cycle. This gives me an hour or two of free time in each go-around.


I put in some final instrumentation for use with the logic analyzer, then continued the wiring of all the signals into the unit. After the analyzer was wired, I had to jumper the outputs of the pattern generator to some of the input lines.

Once the physical wiring was done, I began to set up the logic analyzer to properly group and report the signals it is watching. This will take a bit of time but makes debugging much easier when looking through traces.

With the analyzer configured and everything wired, I began to capture some traces to see what was happening. My first problem was that the logic analyzer complained about slow or missing clocks, which is probably an issue with the connection I used to get the 50ns clock out of the board. I will try to use a different route that might have better signal characteristics.

Debugging fpga with built in pattern generator
Now I am reading the clock and seeing data, but it doesn't line up with what I expect. I will do more runs with various trigger and search patterns until I get an idea what is happening. Next were some runs where I triggered on the first 1 bit coming in on Read Data and contrasted that with what was being clocked in by my logic.

I had to smarten up the trigger criteria - Sector Mark followed by read sector FSM going to setup to read field 1, then look for '1' data bits. I found this occurred about 9 word times into the sector, which is far too early.

Back to the simulator to look over my test generator code, then more logic analyzer work until the test generator itself is doing the right thing. I can't debug the behavior of my disk driver logic if the input it sees is scrambled.

Sunday, September 18, 2016

Built in test generator to produce signals 'as if' real disk were being read


Having created a generator for test input, to loop back into my board instead of needing a real Diablo drive spinning, I have to sort out how to produce the essential bit stream of data as it would come in off the disk surface.

I figured out a technique that should allow me to produce a two dimensional array (an array of bit strings essentially), one array element per word in the sector and each entry is the 16 bits that will serially be produced for the word. That requires 327 16 bit words initialized in the testgenerator module.

The trick will be to adjust the timing to emit this just when the ReadData pulse should occur, but I can do that in the process which is currently producing the ReadClock pulses. For simplicity, I will emit the same sector pattern for every sector, for this incarnation of the test generator.

Luckily there is a single cycle state in the clock generator FSM which I can watch for, which resets the indices for word and bit so that I can cycle through them at the ReadData bit emission time. When the bit in question is 1, I emit a pulse, otherwise no pulse is produced.

I spent quite a bit of time creating realistic data patterns and ensuring the checksums would match. A very manual process, although I did set up an Excel spreadsheet to process the checksum calculations.

Getting the test generator to emit the right sequence of pulses to match my intended disk sector contents took more time than I expected, tripping over subtleties in two dimensional indexing in VHDL, something I do only rarely. Finally it was producing the bitstream I think we would see from the read head, at the times it should appear.

I used the Xilinx simulator to check the output and timing of everything, but the proof is the actual pulses being created.To finish testing this out, I will hook up the FPGA to my logic analyzer, then capture and record the patterns produced.

When the generated signals are right, I can jumper them to the appropriate 'inputs' of the tool and monitor the outputs and the diagnostic pins. I was still wiring the analyzer when the day ran out but I did have good looking results from the simulator.

As a side note, much of the logic I am working out here to produce the test signals will also be used for the emulator role. Therefore I am making progress on the rest of the tool while I work on the debugging of the driver role.

Saturday, September 17, 2016

Developing better testing and debugging functions


To make debugging easier, I embarked on two directions at the same time. One was to build in a test pattern generator, using spare I/O pins and some of the sizeable unused gates on the fpga. The other was to route key internal state out through 32 external I/O pins on the PMOD connectors of the board, in addition to whatever I can display via the eight LEDs and four 7-segment displays.

My test pattern generator now emits index and sector marks at the timing of a real disk drive. It produces the read data clock pulses at 600ns separation. Now, I have to work out a way to emit a realistic sector worth of read data pulses spaced directly in between the clock pulses at the appropriate timing.

The PMOD connectors now have the word that is extracted by the deserializer from the string of disk bits, along with the memory strobe pulse that triggers the writing of the value into RAM. I also plan to output the state of the key state machines involved in reading.

Friday, September 16, 2016

Testing of disk tool with real Diablo drive

Today we met to work on the Xerox Alto. Since we believe the one pack we had does not contain a boot sector or software, we need to wait to run with a different cartridge. We expect a diagnostics cartridge to arrive Monday, being shipped to us by the Living Computer Museum. We also have two packs picked up from Xerox PARC.

We don't want to risk booting from a cartridge until we have retrieved its contents and archived it, which puts my disk tool in the critical path. We will test out my tool today, using the one cartridge that we think is already wiped (actually overwritten with a pseudo random sequence), since we are not risking precious contents.

I set up the tool so it won't attempt to write, only seek or read, which is what we need to retrieve the contents. The current state of the process is a bit clunky - using the Adept tool to set the cylinder, head and sector, then asking for seek or read sector operations.

These operations write into the RAM buffer on the card, which we retrieve with a File Upload operation of the utility to produce a file on the PC containing any data we have read.  The file has to be read and transformed to collect the data in a meaningful format.

Ken brought his ethernet emulator, partially built but ready for some live testing to prove out part of the design. His packet was seen by the Alto and it began to try to boot from Ethernet, but he needs to fine tune the tool until its output is completely correctly received by the Alto.


I am properly setting the cylinder, and seek operations work exactly as expected. The read sector transaction completed, but when I checked RAM the contents don't match the disk. I manually wrote zeroes to the beginning of RAM, read the sector again, and still had zeroes in memory.

We had the scope on the signal lines and could see the disk data streaming in from the drive. The fpga can see it too, or it would have hung waiting for the sync word. However it may not have extracted the words properly or it may not have stored them correctly.

I am going to have to instrument signals on the 'PMOD' connectors to let us use the logic analyzer on the words that my logic believes are on the disk. I will also use the unused connectors NA16 to NA25 on the extension board as drivers of various inputs, so that I can generate my own test signals from within the fpga.

In addition, I want to complete the recording of checksum errors and other status information so that we can interrogate those after each read operation. That will have to wait until after I finish the built in stimulus generator to let me test without a real Diablo drive on hand.

Some of the logic I develop will be the core of the emulator role as well, where this tool will hook to a computer and pretend to be a Diablo disk drive.

Thursday, September 15, 2016

Tool ready for first test with Diablo 31 drive


My first task in the morning was to walk through the results in simulation of the read sector and write sector commands to make everything was correct.  Seek to cylinder had a flaw, it was not putting up the cylinder address so that every seek would be to cylinder 0.

With the seek logic updated, I had good operation of seeks and could 'sign off' on that function. Next up was to work on the read sector function. I went back to fundamentals, carefully studying the Diablo manual and Alto documentation to be certain I was handling the read and write precisely as would be done on the Alto.

Some timing recommendations from Diablo are ignored in the Alto implementation. The most significant is the recommendation by Diablo that the write gate for a new sector is not turned on until 25us after the sector and that writing of zeroes at the end of the data record continues through the next sector marker for 25us.

I continued to pore over the situation when doing an update - where we finish reading one record of a sector and switch over to write the subsequent record(s). The precise way this is done is essential to producing a readable sector for future read commands.

My detailed examination of the read sector command showed it to perform apparently perfectly,

  • finding the correct sector
  • waiting for the right delay
  • scanning preambles to find the sync word
  • extracting data words
  • calculating checksums
  • verifying the check word against the calculated sum. 
It did this for all three records in sequence, in a way that should work properly with a real disk. I hope to test tomorrow with the Diablo drive on the Alto, at least to examine the first sector and compare it to what we think is being read.

When I began to examine the write sector command in detail, I quickly found a flaw. It was not writing out the sync bit to start each field. That was corrected, but the next problem is a defect in my design approach for writing a sector.

I switch off the write gate and stop writing zeroes as soon as I am through with the checksum of the data record, but I should continue up until the sector mark, I think, or at least for a reasonable postamble duration.

Since I am not going to do any writing tomorrow, I will put this change on the back burner and work on readying the tool for reading from the disk.

Another task today was to use my Analog Discovery to inject signals into each input wire on the Diablo cable and verify the expected results on the fpga input pin. Too, I would inject signals on the fpga output pins and verify the results were correct on the disk cable. This was essential before hooking up to the fpga.

I was able to confirm all the signals, assignments and quality except for two signals whose outputs seem to be bridged or shorted together somewhere on the board. Once I found that and corrected it, this was ready to hook up.

I also found a problem with the substitution I made of the CD4050 chip, but this is delivering +5V signals not 3.3V signals. I did some rewiring and it now produces +3.3 output on the signals into the fpga.

With a working connection board and presumed good logic in the fpga, it was time to trigger some functions and watch them on the logic analyzer. I tried to use of the Analog Discovery to drive index marker, sector marker, address acknowledge, file ready and ready to seek/read/write signals, which I hoped would work in spite of being generated at 3.3V to an input expecting 5V TTL.

The documentation on the Analog Discovery is paltry, to say the least, so it took some time to figure out how I might produce the bare minimum to drive my tool. I need to emit Index and Sector markers, with steady levels on File Ready and Read to Seek/Read/Write. Too, it would be necessary to emit Read Clock and a button to intermittently emit a Read Data pulse.

At the end of the day, I decided that I didn't have the means to adequately drive it with this tool. It might be possible to loop some signals from the fpga back to the cable, but that is a lot of logic coding to try to do in one night.

Wednesday, September 14, 2016

1401 work, Alto Diablo tool work and a discovery about our Alto cartridge

Today I spent some time during the day with the rest of the 1401 Restoration Team at CHM. The systems are in pretty solid shape right now, but we did have a few defects to work on. We fixed a problem in a 729 tape drive, repaired the 083 card sorter, and improved the opening and closing of a cover on a 1403 printer.

 One of the seven model 729 tape drives had been sporadically unloading the tape when it was made ready, something that could be triggered by shaking the drive or walking heavily alongside it. Today, it became a solid problem, one we could trace down.

I found a logic input to a gate sitting at ground, but it was an IBM type N signal which is ECL with a typical 0 value of -0.3 to -0.4V and a typical 1 value of 0.4 to 0.6V. Ground is in the forbidden zone, between -.4 and +.4V. No properly working source would drive a line to 0V.

We identified the cards in the signal path that were the source for this signal, reseated the card and resolved the problem. The drive now works properly with no spontaneous unloading.

The card sorter has a single read brush that is moved on a threaded rod to place it in one of the 80 column positions as cards move under it at right angles. The brush was bent up and due for replacement. With a new brush in place and adjusted, the sorter sorted again.


Ken Shirriff, computer archeologist and cryptanalyst, continues to tease information out of our logic analyzer traces collected last friday.

He determined that the drive read sector 0 of cylinder 0 correctly, with proper checksums on all three records of the sector. The data being written into memory matched the instructions that the Alto then fetched and tried to execute as the boot code.

The instructions being executed were not the boot sequence, and seemed a bit nonsensical. We were preparing to check for problems with memory, instruction decode or other aspects of the execution when Ken noticed something about the data that was being fetched.

The values matched the pseudo-random sequence produced by the Diablo Exerciser utility program - it begins with the same seed value and outputs the same sequence every time. It is used to 'wipe' a disk, putting gibberish on the cartridge to overwrite any prior contents.

Therefore, we conclude that our failure to boot from this cartridge is indeed due to lack of boot code in sector 0, because it had been wiped using DiEX. This presents some opportunities and challenges.

The obvious challenge is that we currently have nothing to boot onto the Alto, at least not this cartridge. The opportunity is that this is now a good pack to use as I debug my disk tool, since I won't be jeopardizing any good data.

Ken has gotten a couple of additional cartridges from Xerox PARC, which may contain bootable software, but we are also receiving a cartridge with diagnostics from Josh at the Living Computer Museum, which is what we will use to boot from initially.

It is critical that we retrieve the existing content of each disk cartridge and archive it before we do anything that might write on or corrupt it in any way. I am working to have my tool ready to read the cartridges this Friday, starting with the 'wiped' cartridge we have, then when we are comfortable with its readiness, pulling data from the cartridges we got from PARC.

With assured data on hand, I can then test the ability to read, write and update the primary cartridge. The ultimate goal is to take an archived cartridge image and write it to the primary cartridge, converting it back into a bootable disk.

I picked up 100 pairs of resistors to use as terminators for incoming signals to my fpga extension boards - the best choice for cable compensation turned out to be 120 ohms to +5V and 300 ohms to ground. I installed pairs on all nine input signals on the board, a somewhat tedious process on the prototype board which has seen quite a few modifications already.

I built up FSMs to drive the transactions from the PC, where the user can command the fpga to read a sector, write a sector, update only the data record of a sector, update both label and data records of a sector, seek to a target cylinder, plus later to read or write an entire cylinder at a time.

This included FSMs to produce status back to the PC, in support of the transactional protocol and to reflect various error conditions if they occurred. Not all the error conditions are reflected at this time, but eventually will be.

I hope to be able to begin simulating the proper operation of this logic, triggered the new way, which will be the critical path to Friday's test session. I was able to fire off transactions one at a time using some temp code linked to the simulated buttons.

Write sector works just as expected, but read sector is a bit off in my first tests. I need this to work properly before I can test the mode switching 'update data' and 'update label and data' transactions. It may be a misalignment of the bit stream from the testbench, but I have to pour over this very carefully tomorrow.

One last test before I went to sleep - trying some seek operations. The state machine worked fine, the logic dropped the 'strobe' signal once the 'disk drive' responded with 'address ack'. The 'drive' had dropped the 'ready for seek/read/write' until the end of the simulated head movement, when it went back on, releasing the machine and signaling completion.

The transactional mechanism, using the registers written and read from the PC, was also tested for the seek operation. It looked solid as well, at least as simulated on the testbench. Tomorrow, when I finalize testing of the modified extender board, I can hook things up and see if I can command the appropriate actions from the PC.

Tuesday, September 13, 2016

Testing new circuits to level shift signals for Diablo disk tool


I rewired the disk tool driver board to use one bidirectional level shifter chip, containing four independent circuits, for the three timing critical signals, plus swapping in CD4050 chips which operate at higher frequencies than the original CD4504 choices.

Ken is picking up a couple of extra disk cartridges from Xerox PARC, one of which I will use to test out the disk driver role. I am working toward using it on the next Alto restoration team meeting, probably on Friday.

With my new components in place, I did some stress testing of signals through the extender board. I still have to tweak the terminator resistors on my side to clean up the incoming signals a bit more. That done, I had good enough results at 3.2MHz to move forward with the board.

I don't have enough resistors to terminate all the incoming lines, requiring a trip to Anchor Electronics tomorrow before I finish off the board.

Monday, September 12, 2016

High frequency testing of the disk drive level shifting circuits


I have some Sparkfun bidirectional level shifters that claim to support high frequency signals, which I decided to check before I tested the simpler resistor voltage divider network. I drove them with a 2MHz signal from the Digilent Analog Discovery module, using +5 and +3.3 power supplies.

Using the AD to generate the square wave signals for testing
The Digilent is not ideal as it provides only a 4V swing but that should still show me the effect on waveforms as it is shifted through these devices. To produce a similarly proportioned level change, I set the lower voltage to 3V. I don't care about propagation delay, but significant malformation of the pulse form will produce problems in reading and writing on the disk head.

The output waveshape followed the input very closely up to 2MHz, but did round off unacceptably up at 5Mhz which is far beyond the 1.6MHz operating rate of the disk drive interface. The artifacts I saw were ringing at the upper and lower flats of the signal, but very sharp rise and fall times with essentially no change in pulse width.

Just to be certain they work properly as uplevelers, I swapped the input and output, set up the Analog Discovery to produce a lower voltage swing and looked at the high level output. My first attempt, providing a 2V input swing with 3V low power produced just a 2V high side swing, with 5V supply, which is wrong.
Four channel up/down level shifting board from Sparkfun
This might be due to the limitations of the Analog Discovery, producing a 0 to 2V swing instead of 0 to 3.3V as it should be. The high side should still have pulled up to +5V, not lingered down at 2V. I will check over my wiring and retest later today.

I discovered that the +5V reference voltage was not connected properly. Retesting, I found that the signal did not get higher than the input value when running at 2MHz, but at substantially slower speeds, for example 100KHz, the signal pulled all the way up to 5V. The capacitance in the leads, MOSFET and the relatively high 10K pullup resistance results in this frequency limiting behavior.

I wired in a 1K resistor in parallel with the onboard 10K, thus increasing the draw on the power supplies but also hopefully hastening the pullup effect. I turned it all on and tested again. At 1MHz, this gave me very nice 5V signals with full pulse width. Still, at 2MHz, the rise from 4 to 5V was slower and the effect was a shorter on pulse.

I learned a bit more about the Analog Discovery, including the fact that I could set up the waveform much more granularly, so I then did my final testing with 5V or 3.3V swings on the signal and a frequency of just over 1.6MHz.

I believe I can drop the resistance further to get acceptable operation at 1.6MHz, with the circuit pulling 10ma from the rails. If this is in spec for the devices on the board, and safe for connected disk drive circuits, then I can ensure good high speed pull-up by adding parallel 500 ohm resistors.

Using a 500 ohm parallel resistor does produce exactly what I want - essentially identical input and output waveforms, if you ignore a bit of ringing caused by the rough breadboard testbed I set up. I tried it for both up and down shifting of levels with excellent results both ways.

Uplevel - yellow is 3.3V input at 1.6MHz, blue is 5V output
downlevel - yellow is 5V input at 1.6MHz, blue is 3.3V output

I did more work on the new FSMs - 'update data record of sector' and 'update label and data records of sector' - including better integration of these multiple FSMs sharing the Read Field and Write Field FSMs that do the work on the individual records of a sector.

Once all the coding work is complete, it will be time to test it all out including regression testing of the read sector and write sector machines. Since the update machines involve a mix of reading and writing, depending on the record in the sector,

I will make use of the data I set up in the testbench where I originally tested by read field and read sector logic. This way, I can see that it is properly reading the records before the write gate switches on and I begin 'writing' transitions to the disk.

I would need to build only two more major FSMs - 'read a cylinder' and 'write a cylinder' that will step through all 12 sectors of the current cylinder for each of the two heads. These will take at least 80 ms to complete, two disk rotations, plus the need to wait for sector 0 to arrive at the start.

Since on average we wait 20ms for our intended sector to come under the head, for a randomly issued read or write, it would take an average of 566 ms to read a cylinder in 24 separate IO commands, versus just 103 ms average to do this with the full cylinder FSM.

That comes to just 21 seconds for all 204 cylinders, ignoring the seek time to step 203 times. A seek of one track takes 15ms, so about 25 seconds would capture or write an entire cartridge. Reading an entire cartridge using individual read sector commands (4,896 invocations) would take about two minutes.

I am not convinced that this is a priority, since an entire cartridge can be read in 2 minutes without this work, only a 5.7x speedup on an already acceptable time. Thus, I will instead work on the final linkage of the read, write, seek and update machines to the transactional registers coming from the PC, so that this will be ready for use on the Diablo drive.


I picked up two components that fit together to allow me to hook my 136 channel logic analyzer onto a SCSI bus and capture the signals during use. I have a couple of SCSI based 9 track tape drives that I would like to interface to my fpga based unit that adds peripherals to my IBM 1130 system.

However, I don't have any logic to drive a SCSI interface and I couldn't find any open source, no cost logic that I could leverage. This tooling will help me design my own SCSI driver for the tape drives.

Sunday, September 11, 2016

Continuing work on disk driver tool

I am helping my wife with a fundraiser for Villa Siena, by building a mock Bavarian building front to be used as a backdrop for guest photos at the Oktoberfest fundraiser. Lots of sawing, measuring and so forth, but it is coming together well.

The sides of the building are eight feet tall the roof adds another four feet - hard to lift it up that high! Will be doing some of the assembly flat on the ground, then rotate the completed unit upright ninety degrees. It has to come apart for transportation, which complicates things a bit.


I wrote and tested the two new state machines, Update Data Record of Sector (UDS) and Update Label and Data Record of Sector (ULDS), which will leverage the existing Read Field and Write Field logic. The alter the preamble and postamble timing to handle the switchover from reading to writing.

These both begin by reading the first record of the sector, the header field. UDS will also read the second (label) field while ULDS will write new contents for that record. Both of these will write new content for the third record (Data).

I am seeking blank or sacrificial cartridges for the Alto that I can use to test out the write and update functionality in the real world. We have a couple of potential sources, but at worst case I will just have to use one of my spare fpga boards and connect my driver role board to my emulator role board. This way, I could mount cartridge contents on a PC, access it from my driver as if it were a physical Diablo, and see what happens as I read, wrote and updated portions of the virtual cartridge.

Building up the two new FSMs, both of which drive the Read Field and Write Field FSMs, means more muxing of fields since an address, preamble, count or trigger for those two machines can be produced by three or four of this higher level FSMs. It may be that the emulation role could involve adding more of such driving FSMs, thus this has to be generalized neatly.

I also set up a testbench to verify the ability of my level shifting circuitry to handle the incoming and outgoing disk head signals, which operate at over 1.6MHz. I set up my Digilent Analog Discovery to generate a square wave at that frequency, 0 to 5V swing, passed it through the circuitry to shift it down with 0 to 3.3V then display it on my oscilloscope.

As I feared, this circuit will NOT pass the high frequency signals I need. My second experiment will be with a simple voltage divider, which should definitely work right as long as I choose resistor values wisely.

Saturday, September 10, 2016

Fine tuning of plan for sector updates on the disk tool


I had to do some deep thinking about exactly how to handle the case where I am updating an existing sector, which means that the header and optionally the label records are read, then the controller has to switch over to writing to write out the data (and optionally the label) record on the remainder of the sector.

This has two complications. First, the timing of the clock transitions when we begin writing are extraordinarily unlikely to match seamlessly with the clock transitions that were previously written on the disk. Second, the write pole is forward of the erase pole on the disk head, thus when we begin writing the space where we first write transitions has not been erased.

If the new clock transitions begin right after the previously recorded transitions of the postamble of the prior record, then will appear to be a 1 bit value and not a clock transition. Thus, if this happens at any time while the controller is trying to read, incoming data is corrupt. If it happens when the controller should be seeing a preamble of zeroes before the sync word, we get a false start to the record.

It takes about 2 microseconds for the erase pole to get to the point on the disk where the write pole had been when switched on. There will be remnants of the transitions written prior to this pass, until the erase pole reaches them. For that 2 us interval we may get false transitions.

There is no way to smoothly switch from reading old transitions at the end of one record and start writing the preamble of zeroes for a new record. If one were to look at a sector at the gap between one record and the next, when the latter record was written as an update, we would see:

  • an interval of transitions every 600 ns, representing the postamble words of zeroes for the first sector
  • an interval of 2000 ns when the erase and write gates are turned on
  • the new clock transitions every 600 ns but not on the same schedule as the old transitions
  • a few words of zero 
  • a sync word of 0000000000000001 to start the next record

One could just start new clock transitions right when the write and erase gates are switched on. If so, there is a 2 us interval where there may be confusing overlap of transitions. Alternatively, one could wait the 2us before issuing any transitions, so there is a gap with no clock transitions.

The Alto always works on word boundaries, so the way it handles this cutover is the first case, producing some overlapping but not synchronous clock transitions. When the sector is first written, there are five words of zeros after a record, called the postamble, then three words of zeroes as a preamble before the sync word that starts the next record.

To handle a switch from reading to writing between records, the alto switches off reading but counts three word times (still in the postamble) before turning on the write and erase gates. The next word, word four of the postamble, has its first 4 bits corrupted by the distance between the poles on the head, but is more or less where the original postamble word was placed.

The controller continues writing the last postamble word and the three preamble words, then the content words of the record. When reading the sector in the future, the read gate is turned off after reading each sector, then delayed 4 word times to make sure the head is well past the corrupted section before it begins reading preamble words looking for the sync word.

I will change my write logic to begin with clock transitions immediately after turning on the write and erase gates, since this is how the Alto handles the disk. The remnant transitions only occur during the first word of switch on, but all the reading logic ignores data for quite a bit of time past that point.

When writing the first record of a sector, the write and erase turns on and 34 words of zeroes are emitted before the sync word. When reading the first record, the controller waits for the equivalent of 21 word times before it starts reading the transitions - far far past the corrupted first preamble word.

Similarly, when writing a new record after reading a prior record, there are three postamble words from the original version of the record, one corrupted word and a final good postamble word. The preamble of three words is written too.

Thus, when reading a record that was 'updated', the delay of four word times puts the head past the corruption point and lets it see about four words of newly recorded clock transitions before the sync word.

I will make the change to how I start up writing a field, to create clock transitions immediately after turning on the write and erase gates. That will let me build the Update Sector FSM properly, according to the scheme described above.

Friday, September 9, 2016

Found and fixed a bad chip in Xerox Alto II, writing sectors working in disk tool


Today we dug through our logic analyzer traces to look for clues, while also changing our connection method to pick up the microcode address field. Previously, we had the ROM board on an extender so it was hanging outside the card cage. We put a clip around one of the ROM chips and picked off the ten bits of microcode address.

The new method used a specially made cable, replacing a short bridge cable that linked the ROM card with a control card in the next slot. Our special cable provided a set of pins onto which we could attach logic analyzer probes. This let us keep the card in its normal position and use the extender card for other purposes.

We noticed that the disk sector task is only called once, never again. There should be a wakeup every 3.333 microseconds as a new sector mark is delivered from the disk drive. No wakeup signals, so we put the disk controller card on the extender and began to debug with oscilloscope and analyzer.

We didn't see the sector mark pulses in the logic on the board, but it was passed through the board to a backplane pin. Tracing further, we saw the pulse entering the logic at the input to an schmitt trigger inverter, but no sign of it on the output pin.

We pulled the chip and tested it on the bench. It was a hex inverter chip and the one gate for the sector pulse was dead as a doornail. I looked through the schematics and noticed that one gate was unused. We didn't have a spare 7414 chip on hand, but could snip off the leads to the bad gate, bend up and solder to the leads for the spare gate and connect it into the circuit.

With that frankenchip in place, the sector mark pulses were passed into the logic, the disk sector task awoke every sector, and we were able to trace the boot logic reading the first sector from disk. The disk command block in memory was fetched and checked, then the disk word task woke up four times but nothing occurred past that point.

There are many possibilities at this point. We could have invalid contents on the disk. The read signals may be corrupted. We may have other hardware issues to address, but this will depend on a very detailed study of what is occurring.

We had run out of time at this point and had to make copies of all the logic analyzer data and go off to study it on our own, before we meet again for the next session.


My write sector FSM is now working perfectly on the simulator. Next up is creation of the two update FSMs, to update just the data record or both the label and data records of a sector, after reading the existing header or header + label records

Then there needs to be logic to cycle through all 12 sectors, reading or writing them in sequence. This will make disk copies faster to perform.

Beyond that, I need to couple these read/write/update sector machines to the USB transaction registers so that everything can be controlled by a PC remotely. That will set me up to test with a real disk drive, once we have a blank or sacrificial cartridge to use for the testing.

I can also use the mechanism with a good cartridge to read all the data from it and evaluate or save it on a PC, as long as I ensure that the write mechanism is tied off and can't be activated.

Thursday, September 8, 2016

write field working and write sector function seemingly works as well

Final day of my holiday at the Del Coronado hotel, flying home this afternoon. Tomorrow will be spent restoring the Alto itself.


I am working on a better representation of the state machines I will code. The usual diagrams for Moore and Mealy machines don't fully express what I do in my compact FSM style.

The issue is that the normal diagrams show outputs as either a fixed value for a given state, or a value that blends the given state with some input signals. However, I have some values which are emitted only during the transition from one state to the next, in other words they persist only for the first cycle of that new state but if it remains in that state for subsequent cycles, other values are emitted instead.

The values in question are not a steady output of the old state nor a steady output of the new state. While they are a combination of input signals and the old state, they aren't emitted until the clock edge when the FSM enters the new state. These don't fit the usual Moore and Mealy notions and the existing diagramming methods

I decided to show the one-time values being emitted on the arc that shows the transition. Normally these arcs just show the conditions that cause the transition, but I will add some emission notation from the arc, similar to the emission notation that is used from the state nodes.

This new notation helped me firm up my logic for the write field FSM, which as I said yesterday is a bit complex since it coordinates with several other FSMs. I did waste some time with bogus error messages from the Xilinx tool, wherein the error is claimed against some signal quite different from the real source of the error.

I had my new FSM controlling the 'load word' signal, but hadn't removed the connection of that signal from the input button 1 since I was 'toggling' the button in the simulator. The error should have said multiple drivers for signal load word. However, it instead complained about multiple drivers for the tristate mem_OE signal, wasting my time hunting for the real problem.

I ran the simulation on my write field logic, which helped me spot some weaknesses in the serializer and how it interacts with this new FSM. With that cleaned up, I appeared to write the preamble of 34 words of zero correctly and then move on to read memory and write those words. This trace will take quite a bit of time to check over, as I have to count all the transitions to be sure that I am not dropping or adding any bit cell times during the transitions through this state machine.

I looked through this more carefully and it still looks solid, so I moved on to build the higher level write sector FSM which will call the write field machine three times. That too looks good, but I didn't have time to check as carefully because my flight home was landing.

Building out and testing the write sector logic

Relatives joined us today at poolside, requiring my presence and shortchanging the disk tool effort. I still managed to achieve solid progress in the time before and after their visit.


I set up a quick simulation of the writing FSM, which should be producing transitions for the right mix of clock and data values, which took a little bit of fussing with simulator stimuli but eventually gave me a good insight into how this was working.

I did some tweaking and got the timing just right - transitions exactly as they should occur. Next up is to write and test the serializer FSM, which will take a word given to it and feed the 16 bits to the write FSM one at a time as the 'getbit' signal comes from that write task.

The simulator helped me get the serializer working properly with the write FSM, so that I could then pop up a level and build the write field FSM that uses them. Soon they were working together well, once I stuck in a bit of glue logic to control when the new word is loaded into the serializer.

The write field logic has to step through several phases as it writes a record:
  1. write a selected count of words of zero (the preamble)
  2. write a sync word "0000000000000001"
  3. write a selected count of data words, XORing the contents to form a checksum
  4. write the checksum word
  5. write four words of zero (the postamble)
For the first (header) record, the preamble is 34 words long and the data field is 2 words long. The label record has a preamble of 5 words and a data count of 8 words. The final record, data, has a preamble of 5 words and a data count of 256 words.

When writing records, I will have to seamlessly transition from one call of the write field to the next, ensuring that the postamble words of one field and the preamble words of the next record are contiguous. This will be a constraint on the next higher level FSM, write sector, which will invoke the write record FSM three times.

The write field FSM was written in a compact style I have developed, minimizing cycles but making the logic harder to write and understand.

Tuesday, September 6, 2016

Diablo driver logic ready to read target sectors from live disk, working on write logic


I zoomed in on the simulation signals for my RAM access FSM in order that I ensure all of them meet requirements. Some must be active and held steady for a bit before the activation clock edge (setup times). Some must maintain their state for a bit after the edge when the activation is dropped (hold time). I also checked that every signal is in its proper state.

I had a bit of tweaking of ancilliary signals but eventually I had a good solid write of the word that was assembled from the bitstream off the disk drive. Time to finish and test out the entire Read Sector FSM.

I had to set up the actual numbers for the preamble wait time before reading each of the three sector records, which I got from my notes. Then, I set the target to read sector 5 and aligned the timing of the testbench to that point.

I was able to read the header record and then sit syncing but never found the 1 bit because it wasn't in my testbench yet. I first did some tweaking of the preamble timing and verified it was right, before sticking in the sync word at the right point to continue reading my sector.

By the midafternoon, I had the read sector routine up to checking the checksum of the second record (label field) against the calculated checksum, after which it would wait for a preamble and then read the data field (record 3).

I realized that my testbench was delivering a single 1 bit to sync up, but the actual timing would be 15 zero  bits and then the 1 bit. Because of this, I am shortening the sector duration and need to expand to exactly match what should be read or written on the disk cartridge.

The outcome is that a full sector takes 3.120 milliseconds out of the 3.333 available between sector marks. That is quite reasonable.

I had a fully successful read of the entire sector 5, using accurate timing of the Read Data and Read Clock signals relative to the sector mark pulses I was generating. Proper timing, checksums match, everything seemed good.

The next verification to make was that the RAM addresses were generated properly - 00000100010101000000000 to 00000100010101100001001, which would mean that my entire read sector logic was now read to test with live data from a Diablo drive. It passed with flying colors.

Early evening, before dinner, I began building up the logic to write to the disk drive. This involves generating transitions for mixed clock and data pulses, a transition each time there is a pulse. Transition means that the bit value reverses, so a pulse could produce either a 1 or 0 depending on the immediately preceding bit value.

The timing critical routine is a state machine which turns on the write gate, waits 2 microseconds for the erase head to catch up with the position of the write head, and then begins writing a transition for a clock pulse every 600ns, with transitions halfway in between for any data bit that is 1. This routine emits a single pulse to request the next bit value when it emits the clock transition.

The higher level state machine, to write a field, will have to start the write FSM and feed it the preamble, a set number of words of all zero bits, then the data fields, write the checksum after the data and then emit three words of zero as a postamble. This state machine will call a serializer FSM for each word, after reading from RAM or generating the word value.

The serializer FSM loads the word it receives in a shift register, then waits for the 'get bit' signal from the write FSM. On the get bit request this FSM shifts out the bit from the shift register so it is available to the write FSM. If the last bit was shifted it, it signals that the word is emptied which triggers the higher level write field FSM to advance to its next word.

My first try at a write FSM was incorrect because I wrote it as if it were producing clock and data pulses, meaning go to 1 for 100 ns, then off for 200 to 500 ns. Wrong! A transition is just a knife edge change or toggle, so I had to rewrite it. Also, the write FSM must sit at 0 as its idle state value.

I built a good FSM to handle the write signals but ran out of time before testing today, as I have to get ready for dinner now. Tomorrow, I will test this, build the serializer and the overall write field FSMs.

progress on RAM access logic for disk tool

I flew to San Diego to vacation for a few days at the Del Coronado. Sitting in a poolside cabana with power, wifi and other amenities, I could concentrate on logic development and debugging through simulation.


I began working ou the scheme for the FSMs that would produce the write head signal, serializing words and encoding the bits in the non-return-to-zero methodology used on the disk. This is a scheme where reversing the state of a bit will end up creating a pulse when the sector is read. It is the timing of the reversals that produces both clock and data bits.

The driver will toggle the state of the 'write clock and data' line once each 600ns, to generate the data clock pulse on reading. Right in the middle between those clock pulses, if there is another pulse, then the bit value is 1, while the absence of a pulse means a bit value of 0.

The driver toggles the state of the line once at each 600ns point, but switches again 300 ns after that to encode 1 bits. If each bit of the line is a constant 300 ns, then the pattern of all zero data bits would be represented by 11001100110011001100 etc. The reversal of the signal line produces the clock bit, but the next time interval has no reversal so no pulse is produce. If I wanted a pattern of all one bits, the pattern might be 1010101010101010101010 etc, switching state to produce pulses each 300ns.

Synchronization is the process by which one determines which are the clock pulses and which are the data pulses. The logic sees a long stream of words with all data bits 0, which means a long string of pulses every 600ns,nothing in between them. The circuitry or logic locks timing to that pattern and recognizes the pulses as the clock bits.

Finally, after the long string of zero bits (patterns like 100110011001100110011) a data bit of 1 occurs in the 300ns position halfway between clock bits. That single bit of 1 indicates that the very next data bit will be the first bit of a word. In our pattern just above, the 10011001100110010, in its last transition, caused a toggle in the data bit position and now we are synchronized to know where to ind clock bits, data bits and the start of a word.

Writing this from my logic is easy - I have a write signal FSM that will cycle forever between four states - clock pulse activation for 100ns, quiet space for 200ns, optional data pulse or quiet time of 100ns, and quiet time of 200ns. This FSM must get the data bit value, 0 or 1, from the serializer FSM which is grabbing words from my buffer in RAM then shifting them out, one bit per cycle of the write signal FSM.

Writing involves turning on the 'write gate' signal which causes the erase head and write head to begin magnetizing the disk surface. Due to the construction of the head, the first 25 us after the write gate produces write signals but the erase head has not cleared the track yet - the erased section is 'behind' the written section by that time. The signal produced in that duration cannot be reliably read.

The solution is to ignore certain parts of the recorded signal. When writing a sector, a bunch of zeroes followed by a 1 bit is produced for some duration, but on reading, the read signal is ignored for part of that time. When the logic begins looking at read clock and data pulses, we are in the middle of the long stream of zero bits and safely past the point where the erase head hadn't worked.

Thus, we write sections of all zero bits to allow the read process to wait and reliably be in the midst of the zeroes before it starts reading. The zero bits before synchronization are called a preamble. At the end of a field, following the last (checksum) word, there are a few words of all zero bits, called a postamble.

This is important in the space between the three fields or records of a sector. For illustration, we will talk about the end of the header record and the start of the label record. The checksum word of the header record is followed by four postamble words of zero, then five preamble words of zero before the sync 1 and word 1 of the label record.

When reading the header and then the label field, this permits the logic to turn off the read gate or stop looking at the read clock and data bits right after the checksum word of the header record. The logic waits long enough to be about halfway through the four postamble plus five preamble words of zeros, then switches on reading and waits to resynchronize.

If the operation read the header record but then rewrote the label record, which is possible with Alto disks, then we are going to wait for the time of one word, to move into the postamble of zeroes that was previously written, then turn on the write gate and start toggling in zeroes to produce the 4 postamble plus 5 preamble duration of zeroes.

That way, when reading the originally written header record, then turning off the read head for part of the gap, it will find a good preamble and sync written in the update for the label record.

I found that my memory driving FSM double fired, because the read field FSM kept the trigger field active too long. Changing Read Field to drop the trigger after one cycle ensures that I will get just one memory cycle.

Sunday, September 4, 2016

Debugging Diablo disk driver logic using Xilinx simulator, building out core functionality


I worked on the testbench this morning, building up the processes to model the index and sector marker pulses during rotation. I hard coded a preamble, header field, checksum and postamble to let me watch how the read field, deserializer, synchronizer and RAM write would work. This will let me debug much of the code I already have written and establish a sound foundation for building up the rest of the tool.

I cleaned up a couple of issues right away with the testbench, before I even had a full field composed and ready to read. I set up the getfield logic to be triggered by a virtual button push, which I can trigger from the simulator testbench, to watch how the logic performs in its job of syncing, deserializing and for forth.

I began with watching it attempt to serialize, although I was emitting nothing but 0 bits which will keep it from finding sync. The great thing about the simulator is that I can drill down and display any signals at all, no matter at what level or in what module.

Next up, I worked through my mechanism detecting the sync word but I had some issues with how my bit timer process is working - this routine watches the Read Clock and Read Data signals to capture the 0 and 1 bits, feeding them to my deserializer.

I worked on that during the early afternoon, tweaking the logic until it worked correctly. Once it is feeding correct words out of the serial stream from the 'disk drive', I can check the logic to wait for preambles, read a target number of words, and then read the checksum word.

During my vacation in San Diego, from tomorrow until Thursday, I can sit in my poolside cabana at the Del Coronado, enjoy the weather, breezes, poolside activity, drinks, while building logic and simulating it until it works properly. I hope to make substantial progress by the end of the week.

Sync and deserialize reliably delivers words; time to move on to debug the read field FSM fully including checksum calculation and comparison. Unfortunately, I have hit a brick wall, thanks to the Xilinx toolchain. I synthesize the design itself, everything is good.

I do a check on the simulation, all is good. But when I try to run the simulator, it aborts instantly and with nary a message to suggest a cause. I have tried restarting and even rebooting the PC. Until I can bypass this, I can't test a thing. Grrrrr.

Here is how it starting working again: I added one space at the end of a line, then backspaced, then saved the file. In other words, it was EXACTLY the same as before. When I clicked to start the simulator, everything is back in operation. What a rickety product. Imagine if I paid over $10,000 for a license!

By dinner time, I was working on the RAM putaway of the word that came in from the disk head, tuning up the RAM control FSM. I haven't peered into the RAM simulation itself to verify the writing, but the control FSM and upper FSMs are behaving properly.

I set up a preamble delay of 2 microseconds and a memory location to put a two word field (modeling the first record, the header field). The FSM waited, streamed through the remaining preamble of zeroes until it found a sync bit. It then deserialized and extracted the two words, computing the checksum as it did this, passing each to the memory FSM to put it away.

Addresses bumped, the word count decremented, and after the second word was read, the state machine read the checksum word (word 3), tested it and triggered an error because I hadn't set up a correct checksum in the testbench file yet. As soon as it finished with the checksum word, it dropped out of synchronization and we stopped extracting and deserializing bits.

In other words, at this level it worked perfectly. I have to peer inside the memory to confirm that it will write the buffer as I expect, with proper timing for all those signals, but it looks very good right now. I will figure out the right checksum and place it in the testbench so I can confirm that it will recognize a proper match.

I am running out of time tonight, having just about enough left to finish the deep checkout of memory and a good checksum match. Next up once it is working, I have to build a higher level FSM to read a sector - this will call the read field FSM three times with the proper preamble, location and word counts, after matching the desired sector to the sector counter running in the fpga.

Addressing worked right, when the checksum on disk matches the computed value from the data words, the FSM emits the right signal. However, my memory FSM is not doing the right things yet with the RAM chip signals. That will be the first problem I tackle tomorrow.

Saturday, September 3, 2016

Working on the core of the driver role logic

My morning was spent at a nearby fire station as a volunteer examiner for people taking FCC ham radio licensing tests - good turnout so we were busy grading and signing paperwork.


I received the shell for the new connector, which allows me to start wiring up the cable for the drive emulation role board, which will allow the tool to act as a disk drive when attached to a Xerox Alto. I will work on that later, first priority is building up the logic for the driver role.

I am still massaging the 'read field' state machine that will be used three times by the read sector FSM, but also used once or twice by the update sector FSMs. It has to drive the memory interface module that writes and reads from the RAM, plus it must interact with the synchronizer and deserializer when grabbing words from the disk head.

I decided that it makes more sense to refactor this, as there are four situations where I need to process a field. For the driver role, I need to deserialize from the head and write to buffer on a read, but read from the buffer, serialize and clock to the head on a write. Then, for the emulator role, I have to read from the buffer, serialize, generate separate clock and data signals when the host is reading, and when the host writes, I have to separate data from clock, deserialize and write to the buffer.

Each function - serialize, deserialize, memory access and field processing - should exist for all combinations of role and IO direction. Whether they should be combined or discrete is an engineering choice I have to make.

I currently have one memory access FSM which looks at a signal to determine whether it is reading or writing to RAM, but it could be split into pure read and write FSMs. It doesn't seem to be too complex as a combined function.

While I experiment with separated and combined versions, I will begin to build a testbench where I can produce realistic pulses and timings as from a real disk, to see if my logic will correctly detect, deserialize, extract fields and store in the buffer properly. Equally I can test later to see if my generated stream for writing produces signals at the right times.

Friday, September 2, 2016

Debugging work on Xerox Alto II with logic analyzer, bit of work on Diablo driver/emulator

I spent most of the day away, working on the Alto restoration, but did cobble together a bit on my Diablo driver.


Today the team met to work on the Alto. We wired it up to a logic analyzer and began our debugging of the inability to boot up from disk at startup. This took quite a bit of time and involved a few complexities.

In order to capture the current address of each microinstruction being executed, we had to put a chip clamp around one of the ROM chips. That in turn required us to use a board extender to gain access, and a cable extender since the far end of the board had an active connector attached.

After cabling the ROM chip to the analyzer, we hooked to almost 70 other signals from the backplane. When we had it all set properly, we could begin capturing execution of the various microcode tasks and try to work out why the boot sequence is not working.

We found that the parity error task is invoked on the very first memory access. Further, we see that the Error latch is on when the machine starts and stays set perpetually. This should be resetting both at startup and when the parity error task ends.

What we don't know yet is whether this is a problem with the RAM boards, thus a real parity/hamming code error, or if the flaw is in the error detection logic itself. To do this, we will have to cable another 40 pins at least, to see what is going to and coming from memory. We are also trying to map out a debugging sequence where we might just scope some internal signals to check out the error detection logic.

One big unknown before we started was whether the ROM contents matched the versions for which we had listings. Debugging would have been quite hard if not, since each microinstruction branches to the next one, rather than executing sequentially in the usual fashion, so they are interleaved fairly randomly throughout the 1K words of ROM.

Ken Shirriff used a partial disassembler and some inductive logic to work out most of the ROM contents given the listings we found online. We were delighted to find that the addresses we saw matched exactly.


My male plug (MRAC 42 pin connector) arrived, which I can begin soldering up with twisted pairs for connection to the other FPGA extension board which will be used for the disk emulator role. I can't solder in both ends until I get the connector shell which has left Israel and could be in transit, in customs, or traveling across the US.

I also received by 74HTC125 chips and zener diodes to speed up the timing critical circuits, those that deal with data streaming to or from the disk heads.I still have to modify my driver extension board to put these on for the Read Data, Read Clock, and Write Data plus Clock signals.

Thursday, September 1, 2016

Got to bottom of most of the USB to memory issues, adding disk driver logic


I triple checked all the UCF file pin assignments and all the hookups from the memory controller and USB logic, but it all looks right. I did another experiment, where I loaded the RAM using my logic then forced the standalone ADEPT memory to retrieve what was in the chips. That would tell me if I was writing the contents but not able to read properly, or if I am not even writing.

The testing was illuminating. First, I used my logic and the Adept File IO utility to load RAM with a known pattern, then used the Adept Memory (standalone) logic to extract that RAM to a file. The data was random characters, not what I wrote at all.

Next, I used the Memory (standalone) function to load RAM with my known pattern, reset the FPGA to invoke my logic, and tried a read operation using the Register mode. The data matched!. That means that I am correctly reading the RAM, but my logic doesn't write it correctly.

Writing to RAM involves an area where I made changes to overcome the Xilinx inability to correctly hook tristate from an internal module out to external pins. I am using a MUX to drop the high impedance (Z) state and pass through the intended data to write. I know that data is correctly formed because I see it on my LEDs. However, if the mux doesn't give proper setup and hold times for the bus, I could get random crap being written.

Turns out the problems are simpler and more localized. Two issues. First, crap documentation for the reference code led me seriously astray. It defines a bit in the config register, bit 0x10, as unimplemented and to indicate that the memory is in programming mode, not to be used by custom applications. Second, the File I/O to load memory consistently gives the same wrong data in RAM.

When I set the config register with bit 0x10 on, manually reading and writing, whether in single byte or word at a time mode, worked perfectly. Whatever I wrote to RAM will come back out when I read it. When I write it to RAM, I can then use File I/O to dump RAM to a file which comes out properly.

What does not work right is File I/O to load a PC file into RAM using this logic. It claims to have completed properly but I get the same gibberish in memory every time, regardless of what is in the file. I tried loading a different file entirely but got the exact same gibberish in memory.

This may be a flaw in the utility, not in my logic. The only consequence of this is that I can't just fire up the Adept utility and load RAM from a file - it will get the garbage loaded. I can use the utility to suck a copy of RAM up to a file, and can manually store location by location using the Register IO tab, but if I want to take a known cartridge image and load it into RAM, it will need to involve a program I write on a PC.

I moved back to coding, starting to code the next higher layer in functionality, an FSM that will turn off the incoming word stream (stop sync), wait a requested amount of time to skip over some preamble, then turn on the deserializer to sync up and deliver a target number of words into the buffer beginning at the indicated starting point.

I realized I had to build the logic to write to a buffer word before I would know what my read field FSM needs to do, so that became the highest priority task. I have two ways to go with this, leveraging the memory controller from Digilent I was using for USB access, or drive the memory myself.

Given the flawed behavior of the File I/O attempts to write, it was possible that the Digilent reference logic was defective and that would compromise my code, so I instead build a memory read/write FSM from scratch. The memory is a Micron Async/Page/Burst CellularRAM 1.5, part MT45W8MW16BGX. It is a DRAM that auto-refreshes and acts like an static ram chip.

I worked out a very conservative state machine that is sure to give me clean data in and out of RAM, operating at 200ns although the chip itself does its one access in 50ns - four states in the machine are what swell the time. This way I don't have to worry about this aspect of the design.

Then, when I looked more closely at how to have the Digilent logic and my FSM share the chip control lines, I saw that many of the control lines were set up as tristate buses to allow sharing.

However, that meant that the internal module with the digilent code was setting signals to Z when not active, which triggered the abysmal conversion to muxes by the Xilinx toolchain. These may be the reason for the bad behavior with File IO I had discovered. It is positively riddled with code that treats its inputs and outputs as tristate.

I should have realized when it was the only reference project that used a schematic view for the top level, rather than a top level module. I bet this avoids the mangling of the logic that occurs when a regular VHDL module is used as the top.

I decided that I would yank the whole memory controller logic from digilent up into the top level module, instead of trying to manage all those muxes. It was messy but it should resolve the problems and allow me to share the chip lines properly.

It will let me share lines for the RAM and it works as before, but exactly as before, meaning it still does not write properly using File I/O but does just great otherwise. I built my read/write memory FSM to use tristates on the same chip pins, meaning everyone treats it like a bus.

I am starting to build up enough logic here to warrant driving some of it with a testbench and validating function well before I hook this up to a real drive. That will definitely add time to the project but the up front time will be compensated by less debugging time later.

My read/write of memory is nicely integrated, although not yet tested. Time to get back to the read field function, which will pick up one of the three records or fields in an Alto sector. I reached the end of the evening while working on this state machine.