Today I set up and validated the basic engine producing the ReadClock and ReadData signals that are emitted by the drive whenever the ReadGate is active - the disk continually rotates under the head and the bit patterns from each sector sequentially stream out through those signals.
Following that, I modified the logic to become the generator process that will build up a sector image. This begins at each sector mark and
- counts off words of zero as preamble padding
- emits a sync word for each of the three records
- fetches data from memory to load the serializer for each word of the record
- calculates a running checksum of the words for each record
- loads the serializer with the checksum value at the end of the record
- emits words of zero as a postamble padding
- cycles bad to do preamble, sync, data words, checksum and postamble for the next record
Since a sector is comprised of three records - header, label and data - there is an 'inner' process to actualy emit the preamble words, sync, data words, build the checksum, send out the checksum and produce the postamble. It is called from the master generator process, given a count of words, memory starting address, and preamble count.
The key to everything is the serializer, which is loaded with words by the generate record logic at the appropriate time. It gets a request for the new word from the serializer after that process has shifted out each bit of the word to become ReadData pulses. The generate record logic just passes the appropriate new word to the serializer - zeros for padding, a sync word pattern, memory contents for data words and the checksum result - as the requests for new words arrive.
I worked out from the serializer, making sure it was shifting out bits when the ReadClock pulse occured and had it ready for the ReadData pulse. Too, it had to issue the request to load a new word when it output the final data bit.
With the serializer proven out, I then debugged the record generator, ensuring it fed the right values into the serializer. The scope shows a plausible stream of bits for the sectors but just to be sure, I will set up triggering for one specific sector number and carefully inspect the bit patterns to be sure they match what should be read.
These match the patterns I should see, including proper checksums. I varied the cylinder using seeks and altered the head between upper and lower surface, further validating that the data patterns being emitted are correct.
With the bits streaming out of the emulator properly, available for the Alto to do a read, it was time to build up the logic that supports writing or updates. When the Alto turns on the WriteGate signal, it will be producing clock and data pulses on the WriteDataClock signal line.
FSMs must do a sync to the incoming stream to establish the clock vs data boundaries, since the input from the Alto is a combined signal that always pulses for clock bits but the span between clock bits will pulse only for a 1 value bit. This will occur when the GenerateRecord process is beginning its sync word phase, if WriteGate is on.
Sync allows me to deserialize the incoming data bits, producing words. It will be slightly tricky to spot the edges of the incoming signal and determine the time of the start of a bit call, 600ns long.
The required actions are:
- Pick off edges and match bit cell train when we are looking for a sync
- Turn on sync state when the first '1' data bit is seen
- Start deserializer
- Feed deserializer with bit stream
- switch off memory reading logic and begin UpdateRecord machine
- As the deserializer fills, write that word into memory
- Keep a running checksum of the data words
- At the right time, compare the deserializer output to the calculated checksum
- Flag errors in writing the records
- Loop in higher level UpdateSector logic to track postambles and preambles
- Higher level UpdateSector fires off UpdateRecord to regain sync and repeat
One possible error situation is an overrun, where my GenerateSector machine is ready for data words while the Alto has not yet issued the sync word. I may have to put in hold-off logic to force synchronization. The Alto is juggling various tasks in addition to the disk sector and disk word microcode tasks, thus the actual start of an activity has some jitter from sector to sector.
I have a completely populated and wired board for the emulator role, consisting of the circuitry to shift levels between the FPGA's 3.3V needs and the TTL relatively high current signals between the Alto and a real Diablo drive. What is still to accomplish is to build the female socket into which the Alto's cable will plug.
As expected, aligning to an async incoming stream of WriteDataClock, determine which pulses are the clock pulses and attaining synchronization is difficult. First is entrainment, where I determine the start of the 600ns bit cell. This begins when WriteGate goes active and depends on the fact that the preamble is many words of all zero data bits.
After entrainment is achieved, the logic has to accommodate jitter, based on the real edges, to stay entrained. That means we can pick off data bits reliably. Sync occurs when the first '1' data bit arrives. The next bit cell is the start of the data words of a record. When the checksum has been read and compared, we drop sync but keep entrained unless WriteGate drops.
With the entrainment and deserializing logic built, the challenge was testing without a real async and jittery input stream. I turned to the Xilinx simulator and attempted to create a pulse pattern with plenty of jitter and edge cases, to see if my logic will properly entrain and extract data bit values as well as detect a sync state.
I am now working through the logic and the simulator results, fine tuning to yield reliable entrainment and then sync detect. It is now early evening and nearly time to shut down for the day. Since I have a session with the Alto tomorrow, the weekend is when the next burst of progress can take place.