Problem spotted and corrected. The deserializer emits a signal called
gotword for the duration of the bitcell, 600 ns or 30 fpga cycles. In that time, my ReadField logic will take the extracted word, store it in RAM, adjust the address of the next word to be stored and loop back.
This takes less than 30 cycles therefore I was trying to put the same word away a second time, instead of waiting for our next incoming word. It was solved with a simple interlock keeping the state machine in the address manipulation state until
gotword goes inactive before going back to look for the next word.
I now read the sector but get a checksum error on the first record (header). The data appeared to be shifted in correctly and at the correct time, but the error comes when the comparison between the incoming word and the computed checksum fails. I therefore altered the testbed to emit the running checksum value and watched that for signs of problems.
The checksum matches what was extracted from the bitstream, so the flaw is more subtle. I again changed the emitted signals to allow me to watch the state of the error flag during the test - another 30 minute pass through the toolchain - and observed the results.
What I saw at the time of the test and immediately afterwards was a good status for the checksum, yet the result when the
ReadSector transaction completed was an error marked for the header record. I took another half hour, passed out the point in time when the error is recorded as a signal, and examined what was occurring around then.
The
ReadField transaction is run three times per sector, at the request of the higher level
ReadSector transaction. Each time, the parameters such as preamble size and word count are set up while triggering the inner transaction to run.
When the inner transaction returns to its idle state, the outer transaction should advance to set up the parameters for the next record and trigger the inner transaction to handle it. What I am seeing is that the inner
ReadField transaction returns to its
rfidle state as it should, sits there for only three cycles and then appears to kick off in another transaction.
This should involve the outer
ReadSector transaction stepping from its
rsread1 state to the
rsset2 setup stage to trigger the inner machine to handle the second (label) record. The outer machine does NOT advance to
rsset2; that only occurs at the next
rfidle stage of the inner machine.
This means that the inner transaction tries to read the label record but with the long preamble and short word count that pertains to the header record. It fails to produce a good checksum and that is how I get the error status recorded.
I will confirm this with a change in instrumentation, twiddle my thumbs until the testbed is ready and see what is actually taking place. If this is the case, I have a problem with my
ReadSector transaction not stepping properly to its
rsset2 stage, even with three cycles of the triggering
rfidle state from the inner transaction.
Since I did have the problem - the step
rsread1 took just a single cycle thus really didn't read the header record - I modified the outer transaction to interlock better with the inner one. That is, kicking off each read step involves a wait step that insists that the
ReadField transaction left its
rfidle state before it starts looking for the inner to end with
rfidle later.
I need to see that the
ReadField transaction runs properly three times at the correct time in relation to the outer
ReadSector steps, Once that works, I can check to see if the checksum verifies good reading and then verify the contents of RAM to match what my dummy data driver is emitting.
Both tests worked well. I even performed the upper level ReadEntireCartridge transaction which bumps through all the sectors, issuing ReadSector for each in order. The file produced looked good, but since I used contents of all zeroes in my dummy data, it doesn't absolutely prove out the logic.
Therefore, I planned to write some unique data values in each record, first with invalid checksums. I should see all my data captured in the file properly when I 'read' the cartridge, but each sector should reflect the checksum errors. After that works, I can add in the appropriate checksum values and test to see if my logic is now reading 'without errors'.
I had previously built a spreadsheet that is designed around the three record format of an Alto sector. I enter the data words I want and the spreadsheet displays the appropriate checksum. Since it gave me the correct values, I first verified the checksum failure for the two records where I deliberately stored a bad checksum.
I then corrected the data stream, waited a half hour for the toolchain to complete and verified that all worked properly. I found the data properly stored in RAM, matching the values I used, meaning I can consider the logic to read cartridges to be working.
I took a look at the
WriteSector state machine to see if it could benefit from the improved interlocking I used on the
ReadSector peer machine. Indeed, it is amenable to the same improvement, which I introduced. Once I wrap up the reading tests, I can quickly do a
WriteEntireCartridge to validate that the logic still works.
As of dinner time, both ReadEntireCartridge and WriteEntireCartridge transactions are working properly to the extent I can test them without a live Diablo drive or a real Alto. However, I am reasonably confident and look forward to the testing.
PERMISSIVE MAKE RELAY TESTER CONSTRUCTION
I found a good way to anchor the Arduino and relay modules down inside the box. I had to make some holes for power and USB cables to attach, stick in a barrier strip and add the four LEDs to the cover. Once done, I could wire up the tester and be ready to go.
I tried some acrylic glue to anchor the relay module inside the box, further fixing it firmly. With that done and proven out, I did the same treatment for the Arduino itself. A hole was drilled and covered with a rubber grommet for the USB cable that connects to and powers the Arduino.
I need to decide how to route in the power from the two power bricks - one at 20V and the other at 5V - which drive the relay coils and contacts respectively. I could just drill holes and knot the wire inside and out to anchor it in place, or I could attempt to install sockets on the side and matching plugs to the power cables.
Four LEDs have to be installed in the cover. There is one under each of the two relay sockets, to indicate which is active for testing. The other two are in the center of the cover and light to show when the pick and the hold coils are active. I have a grommet assortment coming which will allow me to mount the LEDs cleanly in the box. The grommets will also help with the holes for power cables or sockets.
I did find a reasonable grommet for the power cables to enter - sans sockets - and drilled a first hole. It is a bit too small in diameter, so it needs to be drilled out with a slightly larger bit. I will take this on tomorrow, then install the power lines and knot them inside for strain protection. I still need the mini grommets to mount the LEDs.
Tomorrow, I will grab four LEDs and wire them up, before beginning the final wiring of the unit. I decided against the use of a barrier strip, instead using point to point wiring. All these soldered junctions need insulation, which I will apply with my 'rubber in a bottle' paint on insulation.
The copy of the sketch that drives the Arduino is out of date, not including the improvements suggested by Ron Crane that improved the accuracy of the testing by way of a known voltage drop. I will need to find that code on the laptop at CHM where the original tester sits.