COMPLICATIONS THAT HAD TO BE VERIFIED
The design can operate in one of two modes - virtual only or hybrid where it operates in conjunction with a spinning, operating disk drive. The logic varies in quite a few places depending on whether we are completely driven by incoming sector and index pulses from the disk drive or whether we are generating them.
I wanted to check that even with jitter and speed variations, the hybrid mode would correctly produce the pulses and more importantly be in complete sync with the sector that is under the read/write heads. We have to pick up the proper sector's content to feed it to the 1130 during a read; for a write, we must be updating the proper sector's image in DRAM.
The pulses could arrive in any relationship to the logic in the FPGA, which I tested by shifting the pulses generated in my test bench. It is easier for virtual mode, since the FPGA is producing the sector and index pulses itself.
I very carefully checked all the emitted signals from the modules producing sector and index information. When this was as tested as I could achieve without real hardware, I moved on to test the process of reading a sector on disk. For this, the 1130 controller logic looks at the sector address, then raises the read gate signal when the appropriate sector pulse finishes in the targeted sector number.
My testbench produced the stream of clock and data pulses that the 1130 controller logic expects from the disk drive. This is approximately 250 microseconds of alternating pulses, which are a 1 for the clock and an absence of a pulse to represent a bit of 0. The 250 us of zero bits allows the disk drive to sync up and learn to separate data and clock bits, since they are simply sequential pulses or absence of pulses on the disk surface.
At the end of the 250 us, a word is written with only the high order bit set - x1000 - which the controller logic uses to know when a new word is starting. This sync word is followed by a stream of pulses which represent up to 321 words of 16 data bits plus 4 check bits, delineated by the controller based on the sync word identifying where a new word begins.
When the read logic was accurately generating the pulses in the proper timing, I could verify that the pulses delivered on the data and clock lines from the disk drive are correct. One aspect of my read logic is that it has to generate the four check bits for each word. Thus, after sixteen bits of data for a word is emitted, the next four bits are the check pattern that implements IBM's error checking algorithm.
The ECC is pretty simple - during the reading of each word, a two bit counter is advanced for every data bit that is a 1 value. The counter rolls over, so that after it saw three 1 bits, another 1 bit sets it to zero. Thus the counter is operating modulo four. After the sixteenth data bit, check bits are produced to bring the counter to zero.
This means if we had 1, 5, 9, or 13 bits with a 1 value, the counter is at 1 and we generate a check pattern of 1110 which advances the counter so it reaches 0 at the end of the word. If we had 2, 6, 10 or 14 bits with a 1 value, the counter was at 2 and the check bit pattern of 1100 advances it back to 0. Having 3, 7, 11, or 14 bits with a 1 value gives a counter of 3 and the check bit pattern 1000 gets it back to 0. Words with 0, 4, 8 or 12 bits with a 1 value ends with a counter that is already 0, so the check bit pattern is 0000 since we don't have to advance the counter.
For every 1130 data word - 16 bits - we write 20 bits onto disk in order to have the four check bits appended. The file containing the disk cartridge contents only saves the 16 bits per word, with our read logic generating check bits on the fly. If the controller logic doesn't end the 20 bit word with a counter value other than 0, it has detected a read error and flags the read as defective.
I verified that this read logic worked in both hybrid and virtual modes. It appeared very solid, but needs testing on real hardware to be certain I have it correctly generating the bits.
WRITE LOGIC INVOLVES A MIXED STREAM OF CLOCK AND DATA BITS
When the controller logic is writing to a sector, it is varying a single signal line. Whenever that signal is at logic low, a flux reversal is produced on the disk surface; if the signal is logic high, no flux reversal is produced, thus no pulse is on the disk. Timing is how you differentiate clock and data pulses, since they are a single stream on disk.
The disk drive produces a 720 KHz oscillator signal that is fed to the disk controller logic in the 1130. When that signal is at logic low, we are writing the clock pulse which is always present. Thus, the combined signal line to the disk drive is low when the oscillator signal is low. When the oscillator signal is high, this is the time where we write a pulse for a data bit value of 1 or we do nothing to signify the data value is 0.
My testbench had to produce the combined signal line that would come from the 1130 logic. It is fed by an oscillator we are generating in our write module. In hybrid mode, I plan to feed the actual 720KHz signal produced by the disk drive but in virtual mode, we generate the oscillator.
I know the logic gates involved in toggling the combined signal line so I could reproduce their impact pretty faithfully. Bit counter E is on when we are in the check bits, thus this writes a pulse if check bits haven't set the counter to 0 yet. When bit counter E is off, we are writing the sixteen data bits of the word, emitting a pulse if the current bit value is 1. Finally, if -Write Clock Phase B (our oscillator signal) is low, we always produce a pulse for the clock.
What happens in the real world is that there are delays in the oscillator signal from the disk to the controller, plus delays going through the logic gates, so the combined signal is not edge coincident with the oscillator coming from the disk or my write logic. This had to be simulated to be certain that my write logic would capture the intended data words coming from the 1130 to write onto the disk sector.
In write mode, I have to follow the 250 us of zero bit values (clock pulse followed by no pulse), then detect the sync word so I could separate the clock from the data bits on the combined line. As well, I had to know when a new word began, just as the controller logic must determine when it is reading.
When the oscillator signal is high, I open up a timing window but don't look too close to the signal edges. This protects me from the delays I mentioned two paragraphs above. During the window I open in the middle of the logic high portion of the oscillator, I look for a low value on the combined signal line. If I see one, I have captured a value of 1 for that data bit.
The one and zero bit values are shifted into a register as they coming in from the 1130 controller logic. I keep the two bit counter based on bits with a value of 1. When the sixteenth bit was received, I capture the next four bits only to advance the two bit counter. At the end of the 20th bit, if the counter is not 0 then I have detected an ECC error. The register only had the first 16 bits shifted in, then it was written to the DRAM and the address advanced to the next word in the sector.
I continue to grab words and store them sequentially in DRAM as the write from the 1130 continues. If we reach the next sector pulse while trying to write, an error is detected and reflected to the program requesting the disk write. As long as I am accurately producing the sector pulses as I capture bits from a read, my logic will work correctly with the disk controller.
The test bench code to produce the combined signal line properly based on the oscillator signal value is complicated. Not only emitting the sync word so the controller logic is in sync with us, but skipping the check bits and properly delineating the completion of each 1130 data word. On top of that, I had to introduce some delays just to understand what that does to my write logic.
I am not done yet with testing of the write logic. The test bench code is almost complete to my satisfaction, and I have adjusted some of the write logic already based on that simulation stream. I am going to take my time with this one as it is likely the most challenging part of the logic to get right.