I spent a couple of days examining different ways to handle the incoming ReadClock and ReadData signals, to deal with the imperfect timing of the real disk drive. That is time between clock pulses is not a constant 600 ns. Further, if the signal changes just at the clock edge, we might have an unstable state for a short time which could confuse my state machines.
Dealing with asynchronous incoming signals is challenging, once you go down the rat holes imagining all the conditions you might face with your logic. The key is to develop logic that results in the correct state or answer in spite of the various conditions you imagine.
My clock state recognition machine is now driven by finding three of a given value in a row to swing the state of the clock to one of the binary states. That is, each on or off signal value moves us 'rightward' or 'leftward' between four conditions - clock value 0, intermediate 1, intermediate 2, and clock value 1.
As long as a condition has three states the same sequentially, we reach the side that reflects that incoming signal. One or two conflicting states in a sea of the contrary states will dither slightly off the end points but never reach the alternate end point.
Our clock signals are on for a minimum of 100 ns coming from the Diablo, which is approximately five cycles of the FPGA. We should read the on state of the clock during that intervale. The off condition is a bit less than 500 ns or 25 cycles of the fpga.
Since this state machine has two indeterminate, intermediate states between the valid off and on states, I have to be mindful that any other FSM which depends on the clock state be written with this reality in mind.
The next FSM is the one that recognizes whether we got a ReadData value of 1 during a particular bit cell (interval between clock pulses). It can use a similar strategy where it takes three or more of the same value to drive the FSM to the on or off endpoints.
However, what I truly care about is whether the machine ever reached the on endpoint during the bitcell time, regardless of its current value. It can swing to on for a short time, then swing all the way to off, but we have to remember that we saw a '1' in order to insert the appropriate bit value into the deserializer.
The third piece of this machinery that is critical is the FSM which decides when to recognize that we had a 0 or 1 bit cell. This must reliably detect when the bit cell has ended and also must keep an eye on the ReadData machine to see if we ever reached the on state during the cell.
This third machine was the most critical of all. After many false starts and alternate approaches, I settled on one that I believed would give the most reliable results. It was all done and time to start testing, although the extensive redesign made it unlikely it would all work properly first time around.
The fourth machine must detect the first 1 bit that turns on sync when we begin to read a record, going through the preamble of many zeros until the 1 bit flags the start of data words. I will retain the existing machine for now, as it appears sound to me.
When doing major changes, one has to wait to see how the tool appears to be misbehaving and then develop all the instrumentation needed to attack the problem. I was iterating to set up logic analyzer signals and test the new logic through the evening.