Finally ran the tests to see what is happening when I attempt to write to RAM thru the USB transaction. I found a race hazard between my FSM that controls the write to RAM and the FSM that accesses memory, where I am moving forward too quickly.
Changes made and back to testing after a half hour for synthesis, etc. The new interlock works great, I am now writing and reading the RAM properly from USB, with one teeny problem. My logic for writing has the two bytes in a word swapped. Should be an easy fix, although not quick due to the 30 minute cycle time for each change, plus time for lunch.
It does show the value of a fully interlocked set of FSMs, which I skipped falsely believing that the first (read) cycle would be back to idle before I requested the second (write-back) cycle. Everything worked properly with RAM. Testing moved on to the WriteSector functionality.
My first test showed my WriteSector FSM stalling waiting for the sector to come around. I adjusted the logic in the FSM and prepared to test again in a half hour. Basically, I am running an entire WriteSector transaction and ending with a completion status.
It turns out I have some instrumentation error in that I am decoding the FSM states wrong. When I waited on the Start state, which has the bit clock for writing begin, I saw it move into the WriteField logic for the header record.
I also put a scope on the WriteDataClock output pin to see that I am emitting flux reversals at the timing. I see the WriteGate signal go on, the flux reversals begin, but they are occurring every 300 ns, when they should happen only once per 600 ns.
Effectively, I am writing a string of 1 bits to the disk when I intend to write 0 bits for the duration of the preamble. I also noted that my decoding of the WriteField FSM states is equally amiss to that of WriteSector.
I sat down with the logic and studied it to see where I am running afoul, as well as evaluating the FSM state discrepancy and the logic analyzer settings. The timing issue was the residue of a mental error I made and had caught earlier on my preambles and other wait states - the fpga clock of 50MHz I somehow began coding as 50ns, so that my timers for a given duration needed to be 2.5 times as large as I had.
With the basic bit timing adjusted, I tested again. The WriteDataClock output during the preamble was quite good and I scoped the output driven by my level shifter board which looked superb, exhibiting nice clean levels, along with fast rise and fall times.
|WriteClock&Data signal output of my level shifter/driver board|
I looked forward to the point where I sent the first sync word, which seemed to be modulating the output appropriately for the one bits (that is, adding a transition at the 300 ns point in between the clock transitions every 600 ns.)
However, I saw too many one bits going out, plus the WriteField record one, the header of two words, was producing enough bits for more than seven complete words by the time I ran out of logic analyzer memory.
Thus, I must now study the logic, examining how it sets up the word count and addresses, then begin checking those out carefully. While I did this, I started thinking about my state decoding issues, which will be resolved in the logic analyzer rather than fpga logic I think.
Instrumentation corrected and I could immediately see my problem. The logic wrote out the two header words, 32 bits total after the sync bit. What it wrote is not correct, but it did write the proper two words, then it sat in the checksum writeout stage for many word times. I suspect it is stalled there.
I will begin monitoring the RAM address passed to the logic, check that the correct word is returned from RAM, and then we can see if the serializer is processing it properly. Meanwhile I will look over the checksum logic to find the flaw there.
I remembered that my logic writes the postamble - that is, five words of all zero contents that follow each record written to the sector. That means that I would legitimately write 96 bits after the two header words, which runs out just past the end of the logic analyzer capture. Therefore, I may not have the error I think.
What I do have problems I can see from the trace. I see the wrong data stuffed into the serializer, which accounts for the wrong bits coming out to the write head. This is likely an error reading and transferring data from the memory access FSM, likely a race condition I can correct with an extra step in the WriteField FSM. I have to study this and turn on recording of the memory access as a cross check.
I have verified that my WriteField logic takes the following steps correctly and at the intended times:
- Waits until the sector number is matched, so that the target sector is now under the heads
- Turns on the WriteGate to enable writing (I have blocked this from actually reaching the drive)
- Begins emitting transitions with mixed clock and data values
- Writes the 34 word times of all zero data bits
- Emits the sync word 0001 and begins to write the first record
- Fetches location 0001 from RAM, which is the first word of the header to write
It is at this point that I no longer see correct behavior. The fetched word from RAM should be 0000 and it would be loaded into the serializer. Instead, I see a word whose lower half is 30 going into the serializer. The successive word has a lower half of 00, then the calculated checksum has 61 in its lower half.
The serializer delivers bits, which may or may not correspond to the loaded word (since I don't capture the top half of the word), but are definitely not the 0000 0000 words I should be sending. The serializer than delivers what it thinks is the checksum and proceeds to deliver what should be five words of 0000.
I need to zero in on the loading of the serializer from the RAM fetches, to be sure this is correct. Once it is, the next check is that the serializer returns the proper bits from the word that was loaded. When that works properly, I must see the checksum and 0000 values get stuffed properly into the serializer and come out to the write head.
It is getting late, thus I will work on instrumenting what needs to be captured and possibly producing the bitstream, but will cease testing for the day.
|Diablo 31 drive under test|
|PC talking over USB link and logic analyzer to capture status|
|FPGA board to left and driver role extender/level shifter board on right|