Wednesday, October 7, 2026

Debugging the double increment of addresses during a write by the Virtual 2315 Cartridge Facility

MISSING DATA DURING A WRITE APPEARS TO BE A MEMORY ADDRESSING ISSUE

When writing a sector of 321 words to the Virtual 2315 Cartridge Facility (V2315CF), the first portion of the sector is captured correctly but by the middle of the sector, I see the data values being captured are every other word from the 1130 memory buffer. This means we are fetching every other word from memory using the File Address Register (FAR) of the disk controller logic in the 1130. 

The FAR should step by 1 after each memory fetch. The logic requests a cycle steal, a fetch from 1130 memory, with the address set in the FAR. The request signal -CS Req 0 drops low to request the fetch and once it is underway during a 3.6 microsecond 1130 memory cycle, we see +CS Level 0 go high for the duration of the fetch. The data is grabbed during the cycle steal and then when +CS Level 0 drops back to low, the falling edge should cause the FAR to increase by 1. 

Instead, the data returned from the cycle steal is two words past the last one. This suggests that the FAR is double stepping. However, it doesn't do the double stepping until well into the sector. I recorded signals with the logic analyzer to determine if this is what is happening and give clues as to what circuits might be causing the error. 

  • -Write Gate
  • -Req CS 0
  • +CS Level 0
  • +FAR 15
  • +FAR 14
  • -Load File Address
  • -Reset File Address
  • -B Bit 15
  • -Write Clock Phase B
  • -Write Clock and Data
  • -File Load Gate
  • -T6
DEEP DIVE INTO PREVIOUSLY RECORDED LOGIC ANALYZER CAPTURES

I slogged through all the detail of the trace that the logic analyzer captured, recreating the data being written to RAM by my logic and the correspondence with what I was intending to write. I spotted the point where the 1130 went off track. It occured during the 112th word, which should have been 0xC070 but was instead captured as 0x8070. 

The next word, which should have been 0x0071, was instead 0x00E2 and the machine began to step by two addresses at a time from this point until it exhausted the buffer I set up.  The word with 0x00E2 was the 226th word. The address register value while we were processing the 112th word was b0001001101111 (in hex, x26F) and the next word came from address b0001011100010 (in hex, x2E2) which is a huge jump. Further, from that point onward the memory addresses jumped up by two each time instead of one, meaning the data being shifted out by the 1130 to write on the disk was every other word in the buffer from that point. 

The signal that toggles the FAR to add 1 is the falling edge of the +CS Level 0 indicating the end of the fetch and I do NOT see double memory fetch requests on the line -CS Req 0 in the logic analyzer data I have. My next logic analyzer run will capture that signal, thus I can see if we are somehow fetching twice and bumping the FAR twice as a result. Once again, nothing seems to match the pattern and explain why we would work find for 111 words, then have a huge jump and start double fetching or at least double incrementing the FAR. 

Investigating the early end of a write on the Virtual 2315 Cartridge Facility

THE ISSUE I AM INVESTIGATING

As I was finishing testing of the Virtual 2315 Cartridge Facility (V2315CF), I was writing a sector of data to verify that my signal quality fixes had resolved earlier problems. The internal 2310 disk drive of the 1130 has sectors of 321 words in size, a word on the 1130 being 16 bits long. 

The disk has 203 cylindrical paths that the heads can access, changed by doing a seek command to move the arm. There is a head on both the upper and the lower surface of the single 14" disk platter inside the removable 2315 disk cartridge. One rotation of the platter is divided into sectors 0 to 3, thus with the arm at a particular cylinder and with one of the heads selected, the system can read or write any of the 4 sectors available. 

I loaded a buffer in the 1130 memory with a block of 321 words that I wanted to write to the disk cartridge loaded onto the V2315CF. I issued a write command on the 1130 and expected that the image of the 2315 disk cartridge held in the RAM of the V2315CF would have the chosen sector from the write command replaced by the words I placed into the memory buffer. 

I then cleared the buffer to all zeroes and issued a read command for the same sector. I expected to see all 321 words exactly matching what I had put in the buffer. However, it matched up to the 159th word out of 321, the remaining words were all zero instead of the values I intended to write.

MODIFIED FPGA LOGIC TO EMIT A DIAGNOSTIC SIGNAL

Among the questions I want to firmly resolve is whether the FPGA logic I designed in the V2315CF is abandoning the write operation at that midway point, or whether the issue is coming from the IBM 1130 itself. I set up a diagnostic signal that will be 1 when the write state machine is active and routed this out on the external signal lines on the V2315CF so that I could see it on an oscilloscope or logic analyzer.

WATCHING KEY SIGNALS ON THE 1130 PLUS THE DIAGNOSTIC SIGNAL

I put the oscilloscope on the control signal -Write Gate produced by the 1130 when it is writing to the sector. I also hooked up to the -Sector Marker signal to see where the failure occurs in relationship to the sector marking pulses. I recorded the combined output signal -Write Clock and Data from the 1130 to see if it is emitting the intended words after number 159 or is sending words of all zero. 

The -Write Gate signal stays high for the entire 10 milliseconds duration and the sector mark signal seemed reasonable. I wired up the logic analyzer to twelve signals and recorded it to help figure out what is happening here. The signals were:

  • -Write Gate
  • -Sector Marker
  • -Four Sector Pulses
  • -Int Req L2
  • -Full Wd Count
  • -Req CS 0
  • -Index Marker
  • -Increment Word Count
  • -Write Clock Phase B
  • -Write Clock and Data
  • -RW Condition
  • +Sector Marker

TIMING OF KEY SIGNALS CONFIRMED FROM LOGIC ANALYZER

One of the concerns I had was whether the various single shot timers were set properly to allow adequate time for the completion of a write of a sector. Fortunately, the timing is very good, thus no need to readjust the timers.

The sector marker starts the sector. The marker should go low for 160 microseconds, which is generated by my logic in the FPGA of the main unit of the V2315CF. A sector on the disk consists of one fourth of a revolution of the disk platter, marked with two sector marker pulses 5 milliseconds apart. Every other sector marker pulse is blocked, producing the signal -Four Sector Pulses which activates once every 10 milliseconds to delineate the next sector.

When the sector marker pulse ends, 160 ms into the sector, a timer of about 250 microseconds allows the clock and data pulses to transmit a long string of zero bits called the preamble. At the end of the preamble, the signal -RW Cond turns on for the remainder of the write activity. This happened at almost exactly the intended 250 microsecond from the end of the -Sector Marker pulse. 

The end of the preamble comes after we transmit the sync word, a data word of 0x8000 which is recorded on the disk with the last bit first. A word on the 1130 is 16 bits long, which is followed by four error checking bits that enforce the rule that the number of bits that are 1 must be an even multiple of four. Thus the ECC bits can be 0000, 1000, 1100 or 1110 depending on how many 1 bits are needed to reach the even multiple. The sync word needs three more 1 bits after the data is transmitted, so the sync word appears as a 1 followed by the ECC pattern 1110. 

Immediately after, data words are pumped out, with each 20 bits representing a data word plus the ECC bits. The sector consists of 321 words. After each word is completely transmitted, the signal -Incr Wd Count will blip low to count down by 1. When the count goes down from 321 to zero, meaning we have finished sending out the data, the signal -Full Wd Count will go low and end the sector. That also drops the -Int Req L2 signal to interrupt the CPU as the write command has completed. 

As each word is being transmitted, the signal -Req CS 0 will go low to ask for the next word to be fetched from the memory of the 1130. Everything in the trace above looks correctly and properly timed. We also see actual data patterns in the -Write Clock and Data signal for the words being written.

SEEING WHERE THE LIVE DATA STOPS BEING WRITTEN

Looking at the end of the trace, the last word is requested from memory, then the word count is decremented to zero, the interrupt request level is asserted, and the -Write Gate is turned off. This represents the correct end of the write operation, however I can see that the data words are all zeroes for about half of the sector. 


In the trace above, you see the request for the last word, the increment of the word counter and then the -Full Wd Count signal drop. That turns off -RW Cond and turns on -Int Req L2 as the write operation is done. The next -Sector Marker starts which is the end of our sector and causes -Write Gate to return high. All looks correct except that our data has been zeroes rather than the values in the 1130 memory. 

I looked at the point where I stopped seeing valid data words being emitted. It is soon after the -Sector Marker pulse, but that one is not passing through as -Four Sector Pulses so it should not be affecting the disk controller logic. 


I circled the -Req CS 0 signal that fetches the first word that is erroneously zero. I had loaded the memory buffer with 321 words each having its word number as the data value, thus none should be zero. The green circle shows the bits being shifted out have a mix of 1 and 0 data values - these are legitimate. However, once the ECC bits of the last correct word are shifted out, we see the pattern of nothing but zeros for all the remaining data words. 

The duration of the sync word plus 321 data words is 9.347 milliseconds. The first bad word takes place at about 4.6 ms into that duration which is just about the halfway point of the 321 words. That doesn't correspond to an even address multiple, nor even binary count value that would correspond to a bad signal line or gate that would cause us to mis-address memory. 

I decided to decode the last few words that were output and I believe I have a clue. Starting with the last non-zero word and going backwards, I saw x013C, x013A, x0138, and decreasing by twos. That was the clue! My address is jumping by two rather than one, which is why the data ran out early. What is funny is that the early data words step one address at a time, so something has happened to increase the stride from 1 to 2. 

The logic in the 1130 increments the address at the completion of fetching a word, when the signal +CS Level 0 drops. The dance that occurs fetching the data begins when the prior word has had its 16 data bits transmitted over -Write Clock and Data to the disk drive, but prior to the four ECC bits being transmitted. A request to fetch a word from memory (a cycle steal) is asserted by dropping the -CS Req 0 that asks for the top priority memory fetch. 

Once the cycle steal begins, signal +CS Level 0 goes high to report that. During that 3.6 microseconds of a memory cycle, at about 1.3 microseconds from the start, the data has arrived and is being stored in the register that shifts the data bits out to the disk drive. We have four ECC bits to shift out, requiring 11 microseconds which allows plenty of time for the cycle steal to overlap it and the new data to be ready in the register. 

When the cycle steal ends, the address register should increase by 1. A bit later the signal -Increment Word Count goes low to cause the count of words transmitted to be reduced, eventually the count reaches zero and the -Full Word Count goes low to end the write operation. 

If there is a hardware defect in the 1130, it is likely in the circuitry that holds the memory address (the File Address Register or FAR) inside the disk controller logic of the 1130. That circuit also performs the addition when the cycle steal signal +CS Level 0 drops back to low at the end of the fetch. 

The register is a chain of flipflops with combinatorial gates to set and reset each flipflop. There FAR can be reset with the -Reset File Address signal, loaded from memory at the start of the write operation with the -Load File Address signal, and incremented when +CS Level 0 drops low at the end of each memory fetch. The maximum size of an 1130 system is 32K words, thus we need 15 address bits for the FAR; on the 8K system I am restoring, only 13 bits are necessary but the design encompasses the largest configuration. 

In order to understand the circuit, the peculiarities of the IBM logic family used in the 1130 and the documentation methodology they use has to be explained first. The flipflops used in the 1130 are set or reset by the falling edge of an input, not by a steady state signal level. 


The outputs are both a regular and an inverted output, shown at the top and bottom of the right edge respectively. The outputs are steady state other than for undesirable pulses that occur if a flipflop is already set and receives another set input pulse, as well as when the flipflop is unset and receives another reset input pulse. The flipflop produces a brief pulse on the opposite output line - e.g. resetting a flipflop that is already in the off state will produce a brief spurious pulse on the positive output line. 

IBM designs around the spurious output pulses by using combinatorial logic gates that produce or block the input pulses that would cause this issue. The combinatorial gate used to create the set or reset pulses for the flipflop are what IBM called AC triggered gates. 

In the image above, there are two AC triggered gates which will produce a brief negative going pulse when they activate. These are combined together to produce the final pulse that is used to set a flipflop, so that if either of the gates on the left fire, its output sets the flipflop. An AC triggered gate will activate at the falling edge of one input trigger signal, marked with an N on the left side of the gate, but only if the conditioning (other) input to the gate is steady low at the time the trigger pulse. 

Thus, if the conditioning input -B Bit 15 is low at the time that -Load File Address has a falling edge, the lower gate will produce a set pulse for the flipflop. Similarly, if the flipflop is not set, then +File Address Bit 15, the output of the flipflop, is low and conditions the upper gate. When +CS Level 0 has its falling edge, the flipflop is set but only if it had been unset before. 


Thus our flipflop for FAR bit 15 will be set if it is not previously set, when the cycle steal memory fetch ends, or will be set if the value on B Bit 15 is low when we are loading the file address. -B Bit 15 is inverted, so it is low when bit 15 contains a 1. The lowest gate on the left simply carries the signal -Reset File Address through to the reset input of the flipflop; a negative pulse on the reset file address line will reset the flipflop immediately. 

This means we set the FAR flipflops to match what is in the B register (memory fetch output) when we drop the signal to load the file address. The flipflop will be reset when the cycle stead memory fetch ends but only if it had previously been set. We also can reset this if the signal -Reset File Address is dropped low. 

The effect of the +CS Level 0 signal is to toggle the state of the flipflop each time that we have a falling edge on the input signal - every time we complete a cycle steal memory fetch. This is the first step in the addition process that increments the FAR after each cycle steal.

Whenever a bit of the FAR goes off, it toggles the next higher bit, which is how we make this increment. Below, you see that the output of +File Address 15 is connected to the trigger of the gates for FAR bit 14, so that whenever bit 15 turns off, the falling edge will toggle the state of bit 14. The remaining bits are similarly connected, thus dividing by two on each bit position and yielding an address that steps by one every time we fetch a word from memory via cycle steal. 


FAR bit 14 has the same logic to load or reset in addition to its role toggling its state with each drop of bit 15 to zero. This all seems pretty straightforward and the logic analyzer traces show only a single falling edge of +CS Level 0 occuring on each word. Based on this, unless something is defective in the circuits, this should count up strictly by a stride of 1. Further, nothing I see in the circuit would make the low bit (FAR 15) jump based on the state of the upper bits. 

My only speculation is the part of the setting logic for FAR 15 that looks at the value in B bit 15 and turns on the flipflop when the -Load File Address signal drops. If this is failing, then any data word fetched from memory with bit 15 having a 0 value might set the flipflop, then the end of the cycle steal fetch would toggle it a second time. A mechanism like this would produce a stride of 2, which is supported by the data values of the final few words fetched which all had the low order bit value of 0. 

NEW LOGIC ANALYZER RUN TO LOOK FOR THE CAUSE

Since it appears that something goes wrong in the circuits that increment the FAR, I will capture those with the logic analyzer and look for a) confirmation that it double steps FAR bit 15 or fails to bump FAR bit 15, as well as b) indications of the signals that might contribute to that failure. Hopefully that will let me dive into the issue and look for the true cause. 


Tuesday, October 6, 2026

All Virtual 2315 Cartridge Facility utility programs now using Qt graphical user interface

REVAMPED ALL UTILITY PROGRAMS TO USE A GRAPHICAL USER INTERFACE

The programs had a mixture of Tk (John Ousterhout's graphical interface that goes with his Tcl language), direct python input and Qt toolkit interfaces. Many would pop up simple dialog boxes to grab input such as a sector number.

I decided to build up a more normal graphical interface. All the programs now open a window with buttons, text entry spaces and other elements. The user enters parameters such as cylinder number by pressing a button, typing in the value, and either having it accepted if properly formatted or seeing an error message inside the main window. Action buttons request the functionality such as 'convert a file' or 'update a sector'. 

CONVERTED ALL PROGRAMS TO STANDALONE EXECUTABLES FOR WINDOWS

I used Pyinstaller to build these into a single executable that does not require the user to install Python and the various libraries used by the utility programs. This does make them fairly big, around 50MB each. The github repository for the project holds both the Python script and the executable, for the convenience of the user. 

EXAMPLE MAIN SCREENS

The convert1130.exe program needs the user to select the input file in IBM 1130 simulator format, asks the user to create an output file, but also needs then to have entered the four hex digit cartridge ID to write on the virtual 2315 cartridge along with a free form text description of up to 199 characters that they can use to annotate the contents and usage of this cartridge. The button Convert the file causes the conversion to occur, as long as the required other information has been properly entered.


The updatesector.exe program asks the user to select the file in virtual 2315 disk format that will be opened. The user must enter the cylinder, head and sector address of the sector they wish to update. The cylinder is validated - it must be 1 or 2 hex digits in the range 0 to CA to correspond to cylinders 0 to 202 that can be accessed on the 2310 disk drive. The button Display Sector will cause a window to pop up with a grid that shows the contents of all 321 words of the sector. The user can click on any word in that grid and type in a replacement value. It must be a valid four digit hex value else it is rejected. The user can then click the Write changes back button to update the disk file, or choose a different sector address and display that, or quit the application. 

EXAMPLE OF ACTION WINDOWS THAT POP UP


Above shows the grid that pops up in the updatesector.exe program which allows the user to update any and all words of that sector. 


Above is the output of the listcartridges.exe application showing a list of all files in the selected folder/directory that are in valid 1130 simulator or virtual 2315 disk format. 

EXAMPLE OF BONUS INFORMATION

Additional information is printed to the DOS window that opens behind the executable program (or the script if running the Python code directly), where it might be useful in special cases. For example, while building the list of file names that are either virtual 2315 format or 1130 simulator format disk files, the listcartridges.exe program outputs additional data on the 2315 file extracted from its header.




Saturday, October 3, 2026

Wrote more utility programs to use with the Virtual 2315 Cartridge Facility

UPDATESECTOR IS GRAPHICAL EDITOR FOR ONE SECTOR OF A VIRTUAL 2315

This Python program opens a disk file used with the Virtual 2315 Cartridge Facility (V2315CF) allowing the user to edit the contents of one of the sectors on that virtual 2315 disk cartridge. A sector is 321 words long, a word on the IBM 1130 is 16 bits wide, and the words are displayed and edited in hexadecimal. A 2315 disk cartridge is organized into 203 cylinders and each cylinder is accessible by one of two read/write heads. Each of those 406 locations has four sectors of 321 words on it. 

At startup, the user selects the file in the V2315CF disk format, verifies that it is in the correct format, and then asks for the cylinder, head and sector number of the sector to be edited. 



The cartridge number and description are listed then the user is given a series of three pop up boxes to select the cylinder number, head number and sector number of the one sector they want to edit. A graphical grid editor is opened with a grid 

The grid is 16 columns wide and 21 rows long, the last row having only a single cell. The rows are the first two hex digits of the address of the word while the column headings are the third digit. Each cell is the word in the sector at that word number. For example, the bottom right cell shown above is at address 0x0EF and the value in that word is 0xDA34. The grid can be scrolled down to get words in addresses 0x0F0 to 0x140 as shown below.


Clicking in a cell allows entry of four hex characters before clicking elsewhere or hitting a tab to move to the next cell. The keys are validated - must be 0-9 or a-f and must be four long. Below you see the grid after I entered different values in two cells. At address 0x000 I typed in 3002 and then at address 0x016 I typed in AAAA. These replaced the prior values of 0x0000 in both cells. 


Once I click on the X in the upper right to dismiss the editor grid, the application writes the modified sector back to the virtual 2315 disk cartridge file and exits.


COMPAREDISKS WILL HIGHLIGHT EVERY SECTOR WHERE TWO 2315 DIFFER

The user selects the two files, each of which is validated to be in the correct format by the application before continuing to the comparison. The program then checks every word in the disk and reports the cylinder, head and sector number of each sector that has differences between the two files. 

The results are reported on a grid that pops up, with 8 columns across and 203 rows. The rows are the cylinder number in hexadecimal. The columns are:

  • H0 S0 - head 0 sector 0
  • H0 S1 - head 0 sector 1
  • H0 S2 - head 0 sector 2
  • H0 S3 - head 0 sector 3
  • H1 S0 - head 1 sector 0
  • H1 S1 - head 1 sector 1
  • H1 S2 - head 1 sector 2
  • H1 S3 - head 1 sector 3

Any sector where the data in the two files are different is colored yellow and has the cylinder number, head number and sector number reported. The cylinder number is given in hexadecimal and then decimal within parentheses. 

Simply click on the x in the upper right corner to close the grid and end the application.


AWAY UNTIL EARLY NEXT WEEK

I am visiting my daughter in Providence Rhode Island for a few days, but will be back and in the shop early next week. 





Wednesday, September 30, 2026

More debugging of write functionality of Virtual 2315 Cartridge Facility

RESOLUTION OF PREVIOUS ISSUES APPLIED

During testing of writing from the IBM 1130 to the Virtual 2315 Cartridge Facility (V2315CF) I had identified two areas of concern. First, the power supply that converted the 12V produced by the 1130 computer system down to 5V for delivery to the main unit of the V2315CF had periodic voltage glitches about every 30 microseconds. Second, the clock signal generated by the V2315CF that is delivered to the 1130 circuits so they can transmit the data stream for a write had several issues.

The power supply problem was due to economy mode operation because the DC to DC converter in the power supply was loafing along with the demands of the V2315CF relative to its 10A capacity. This caused it to turn off the switching oscillator and turn it back on every 30 us for a brief burst. That created a ringing of the supply with over 1 volt swing during each burst. 

The fix was to add about 2A of power dissipation using carbon power resistors so that the supply did not need to enter economy mode, as well as adding a couple of filter capacitors where the 5V enters the main unit of the V2315CF. The oscilloscope confirmed that the wild swings every 30 us had been managed. We now have less than a millivolt disturbance on the incoming 5V to the V2315CF main unit.

5V rail swing with scope set to 200mv per major division

The signal issues included a logic high level that never reached 2V, a major undershoot from ringing, and a slow rise time of the signal. The source of the signal is an open collector gate, which is what gives the dramatic falling edge. The slow rise time and low voltage at the 1130's input pin is due to the high value pullup resistor at the V2315CF and the capacitance involved in the long complex path between the V2315CF unit and the 1130's logic gates. 

The fix was to install a 169 ohm pullup resistor to 5V and a 249 ohm pulldown resistor to ground on the terminator board on the V2315CF. That gives a much stronger pull-up and ensures that the high voltage at the 1130 logic gate is much closer to 3V. It ensures a faster rise time for the signal. Lastly, it should provide a better impedance match to the signal path which hopefully will quench most of the ringing at the falling edge. Again, the oscilloscope on pin B03 of card slot K6 of compartment C1 in the 1130 logic gate A showed a better behaved signal. It is still low, having to do with the effects of all the resistances in the circuit, but the skipped shifts no longer occured. 

Some of the ringing is due to poor scope lead grounding

BETTER TEST RESULTS WITH WRITE IN VIRTUAL MODE ACHIEVED

This time I did achieve a capture of the data I wrote to the virtual 2315 cartridge with no shifted bits. I set up a known pattern in a memory buffer in the 1130 and issued an XIO instruction to write to a given sector of the disk (cylinder 0, head 0 and sector 1).  After clearing out the memory buffer, I issued an XIO to read in the same sector, confirming that the contents matched what I had written - up to a point!. An offline view of the mini 2315 cartridge using the Showsector.exe program I provided confirmed the content of the sector as well. 

The 1130 wrote 159 words out of the 321 correctly - zero errors encountered. However, it did not write anything other than zeroes for the remainder of the sector. This behavior is consistent - always gets the first 159 words captured correctly and then seems to give up on the write.

DEBUGGING REASON FOR EARLY TERMINATION OF THE WRITE

Writing is supposed to commence at the end of the sector marker pulse that defines the beginning of the sector we are writing into. The 1130 should wait 250 microseconds, controlled by a timer (single shot) gate, then begin emitting the sync word pattern. From the end of the sync word detection, it should write out the 321 words requested, shifting each word out as 16 data bits plus 4 error checking bits (total 20). 

These are transmitted in the bit cells that take 1.45 microseconds each, thus each word consumes 29 microseconds and the entire sector would require 9.39 milliseconds. Before the data begins shifting out, the duration of the initial sector marker pulse (160 microseconds), the 250 microsecond timer, and then the 29 microseconds for the sync word are added on top of that total. This gives us a 9.748 milliseconds out of a 10 ms sector. 

When I looked at the logic analyzer output, I did notice that the sync does not finish until about 650 microseconds not 278.7 microseconds as I would have expected. This exceeds the time budget we have! It should result in a slightly truncated sector, but we are seeing about half a sector written before it stops. 

Thus I have identified a few issues to resolve. First, I think the bit cell duration is too long and is causing the data to spill over out of the sector. Second, it appears that the timer that controls when the sync word appears is out of adjustment, starting the data portion of the sector some 375 microseconds later than it should. Third, the write is ending about where a sector marker pulse is arriving since they come once every 5 ms or twice per sector. 

Bit Cell Timing

The original design I developed, consuming 1.45 microseconds, is the equivalent of only a 690 KHz clock rate while the internal disk drive is nominally operating at 720KHz. That is the equivalent of almost 13 words that can't be fit in the sector because of the wastered time. 

The specification of the internal drive is a bit cell duration of 1.39 microseconds at 720KHz. I can get close with a simple change to my design, providing a bit cell of 1.40 microseconds or 715KHz clock rate. I think this is close enough and will make that happen. 

The FPGA operates at a 25 nanosecond clock time, which gives me the choice of the bit cell duration being 1.375 or 1.4 microseconds. There is a way to generate a different clock frequency that yields exactly 1.39 uS but then using signals generated require synchronization because we now have two clock domains that have to interact. For the time being, I will stick with the 1.4 uS as that is less than 1% off the spec.

Duration of the Preamble Before the Sync Word

The disk rotates at 1500 RPM and has eight equally spaced notches that produce sector marker pulses. Since a rotation takes 40 milliseconds so a sector marker pulse occurs once per 5 ms. The sector marker pulse drops the -Sector Marker signal for 160 microseconds then returns it to logic high. 

One of the sector marker notches has a second notch next to it, which produces a special Index Marker pulse once per rotation. This disk controller logic increments a counter on each sector marker pulse, but resets the count to zero when it sees the index marker. That ensures that the counter is always reporting the correct sector. 

The index marker pulse also sets a divider circuit which produces a signal called -Four Sector Pulses  which skips every other sector marker. Thus, we see four of the eight sector markers on that signal line, one for each of the four sectors that we write to. 

When we write to the disk, the command specifies a sector number so that the disk controller can turn on the -Write Gate signal to start the write when we match the sector number and the sector marker from the -Four Sector Pulses signal arrives. When the sector marker pulse ends after 160 microseconds which kicks off the writing on the -Write Clock and Data line. 

A single shot timer is started when the -Sector Marker signal returns to logic high. It is set to emit an output for 250 microseconds. During this time, bit cells are being written with the data value of 0. This is roughly 179 bit cells of zero. When the timer shuts off, the disk controller logic begins writing out words, the first of which is the special sync word. 

This means that the last preamble cell ends 410 uS after the sector marker pulse began. After another 27.8 uS, the sync word has completed and the controller begins writing 321 data words each taking 27.8 uS. In an ideal world, that means the entire sector ends after 9. 361.6 uS leaving 638.4 uS of spare space. 

However, our sync word as measured on the 1130 system ended at 690 uS into the sector instead of the expected 437.8 uS point. The timer must be seriously out of adjustment. Luckily it is an adjustable single shot and I will tune it 250 microseconds. I will also verify that the sector marker pulses are approximately 160 microseconds. If they are longer, it could also be a contributor to the late end of the sync word. 

Explaining the Point Where the Write Aborted

When I look at the data that was written into RAM when the write occurred, it ends at word 159 instead of continuing to 321. This is close enough to the halfway point in the sector that it is possible that somehow the sector marker pulse that is NOT part of -Four Sector Pulses is causing the write to abort. I don't see anything in my logic that could connect that, but if the issue is in the IBM 1130 disk controller logic then it might have aborted the write by deasserting the -Write Gate signal. 

Unless I can figure out some mechanism that could cause the V2315CF to stop the write, I need to do some diagnostics with the logic analyzer to figure out why the short write is happening. I will watch the signals like -Write Gate, -Four Sector Pulses, and -Sector Marker. Hopefully I can get a quick clue that will explain why I am seeing the exact failure that is occurring. 



Tuesday, September 29, 2026

Still working on write errors in the Virtual 2315 Cartridge Facility

RESTRUCTURED WRITE TEST PLAN SLIGHTLY

In the previous tests, I read in cylinder 0, head 0, sector 0, modified just a few words manually, and then wrote it back to C0 H0 S0. That left the remaining data from the original 2315 cartridge image intact, but it was not optimal for my testing. 

My new plan uses my core memory loading tool on the IBM 1130 to load the buffer with a known pattern, then I just do the write to cylinder 0, head 0 and sector 1. A second use of the memory loading tool will zero out the buffer location before I do a read of C0 H0 S1 to see what comes back. 

As usual, I will be capturing the signals with the logic analyzer while the write takes place. I will store that as an Excel file and analyze it with my Python programs. Lastly, I will unload the mini cartridge at the end of the test, move the microSD card to the offline tool, mount it on my PC and look at C0 H0 S1 with the Showsector.exe Python program I wrote. 

MY TESTING EXAMINED THREE THEORIES FOR ISSUES DURING PRIOR WRITES

I changed the logic to eliminate any chance that the cartridge ready condition is being glitched by errors over the SPI link between the Raspberry Pi PICO and the FPGA inside the main unit of the Virtual 2315 Cartridge Facility (V2315CF). It appeared that the write state machine erroneously reset to idle a few times in the midst of handling the writing of a sector from the IBM 1130 to the virtual 2315 disk cartridge. 

Another theory was that the power to the main V2315CF unit was having issues triggering incorrect behavior. The final theory is that the clock signal as it is received by the IBM 1130 electronics is ringing or malformed, inducing sporadic errors in the IBM disk controller logic rather than in my logic. 

5V POWER SUPPLY EXAMINATION

I set up the scope to trigger on the 5V input go the main unit just in case it wasn't able to support the instantaneous demands of the V2315CF. I could also monitor two internal voltage levels in the V2315CF produced by voltage regulators for 3.3V and 1.2V used with components such as the PICO and the FPGA. The 5V is used for terminator and driver circuits producing signals across the ribbon cables to the IBM 1130 and the internal disk drive, while the other voltage rails depend on 5V for their inputs. 

Watching the 5V input from the power supply module into the V2315CF main board showed me significant ringing on the line. It was a periodic ring, occurring roughly every 30 microseconds. That corresponds to a frequency of 33.3 KHz and is likely the result of the DC to DC converter saving power by turning its higher frequence switching action on and off because the load from the V2315CF main unit is not high enough for the module to run continuously. 

It is a module rated for 10A output at 5V and thus just loafing along in this role. The terminator resistors for the RK-05 disk drive application are 178 ohms from the signal line up to 5V and 383 ohms from the signal line down to ground, hooked to about 55 signal lines from the main unit. 

If all signals are outputs and set to high, the resistor pairs would draw about 100ma in total. If all signals were outputs and all were pulled to low, the draw would be 1.5A. If it were all inputs and they are all pulled low by the source, it could demand the same 1.5A from the supply. The actual requirement is going to be somewhere in the middle and dynamic, varying as signals are wiggled by the source and the main unit. 

The DC to DC converter on the power supply was chosen to support up to three of the RK-05 emulators at a time, The load from the electronics on the main unit itself are probably in the range of 600 to 700ma. Thus with three units, max load from terminators of 1.5A and 1.8 to 2.1A for the combined main unit draw, the converter is driving 5-6A which is right in its design range. 

In my application, most signals do NOT have termination resistor pairs on them. This sharply reduces the current demand of the terminator board, so that even with most signals asserted low the draw is down around 500-600ma. Add in my main unit electronics demand of 600 to 700ma, and the load on the converter is just a bit over 1 amp. I suspect this relatively light load is why the converter is dropping in and out of economy mode, producing the ringing as it switches back on at the 33.3KHz rate. 

PLAN TO RESOLVE THE POWER SUPPLY NOISE

I plan to add load so that the DC to DC converter in the V2315CF power supply module (TOBSON EA50 dropping the 1130's 12V down to 5V) will remain out of the economy mode that is producing the bursts every 30 microseconds. I will add 2.5 ohms of resistance able to dissipate the 10W of power this will consume. 

I will also look to quence the ringing by adding filtering capacitors at the input to the V2315CF main unit. A 100 uF low ESR electrolytic in parallel with a .1 uF ceramic should minimize ringing even if the converter does drop into economy mode. 

LOOKING AT WRITE CLOCK SIGNAL AS IT ENTERS THE IBM 1130 CIRCUITRY

Finally I monitored the clocking signal produced by the V2315CF that is sent to the IBM 1130 disk controller logic and causes it to output the serial bit stream that is written to a 2315 disk cartridge by the internal 2310 disk drive in the 1130 computer. It looked perfect when monitored on the source end at the V2315CF but I set the scope and logic analyzer to watch the destination in the 1130 for any signal abnormalities. 

The signal looks terrible! It pulls up to a max of 2V, has a very slow rise time indicative of the substantial capacitance of the signal path between the 1130 logic gate and the V2315CF main unit, and there is a plenty of ringing at the falling edge. 

It has a 1V undershoot and a max level of under 2V for logic high. Nominal voltage levels for IBM Solid Logic Technology (SLT) are 0 and 3V. Fortunately SLT quite tolerant of negative voltages on the inputs, but the SLT transition voltages (max logic low voltage and minimum logic high voltage) are 0.3 and 1.8V respectively. 

The ringing of the falling edge goes just above 0.3V although its duration is under 10 nanoseconds, which is too short for most SLT gates to switch. The max level is very near the minimum acceptable level for logic high. Most SLT input gates are diode-transistor logic (DTL) and look like this:

The diodes and transistors in SLT are germanium with voltage drops close to 0.3V each, which I have indicated on the diagram. If all the AND inputs are at the nominal 3V level. the voltage at the thick black vertical line would be 3V due to the voltage divider of the 2K resistor to +6V, the 5K resistor to -3V and the two diode voltage gaps. The voltage at the base of the transistor would be 2.4V, thus the transistor conducts to pull the output low. Since this is a NAND circuit, that is the correct behavior.

When any of the inputs is sinking to ground (logic low), if the actual voltage of the input is 0.3, the effect of the diode drop is to make the thick black junction drop to 0.6V and the transistor base sees 0V, so it is cut off. The transistor must see at least 0.3V for its base-emitter junction to conduct, thus the thick black junction needs a bare minimum of 0.9V. 

After many runs capturing the same writen data, but with slightly different results, it seems possible that the 1130 was seeing an extra clock transition, relatively rarely. The 1130 stays in sync for more than 12 data words, sometimes more sometimes less, but then sends an extra bit or drops a bit. That could be due to glitches on the line.

ODD OBSERVATIONS DURING THE TESTS

I did see a few things that don't make sense to me when looking at the logic analyzer traces and the results of what was captured and written to the RAM of the V2315CF and thus to disk. I will cover them here because achieving reliable write functionality requires that I understand what is going wrong so that I can develop a solution to each cause. 

Apparently missing instances of catch when word correctly captured

Below is the capture of the sync word - at the end of the preamble of a long string of zero bit cells, the pattern 1 1 1 1 0 indicates that we found the sync word. The bit cell just to the right of the vertical red line is the start of the first bit of the first word of the sector. 


The bottom trace is the diagnostic output catch which is should be 1 only when my logic detected that the bit cell was for a data value of 1. The trace above it is the -Write Clock Phase B signal that is the clock we generate and send to the 1130. Atop the clock line is the output from the 1130, the signal -Write Clock and Data which is inverted logic so high on the trace is a 0 and low is a 1 value. 

When the clock signal -Write Clock Phase B is low, it defines the half of the bit cell that represents a clocking pulse. The value of the -Write Clock and Data for the first half, the clocking pulse, will be a logical 1 which is low since that signal line is inverted. When the -Write Clock Phase B signal is high, this is the data half of the bit cell and we look at the predominant state of the -Write Clock and Data signal to pick up the data value. A low output indicates the data bit value is 1. 

Thus in this trace, we see that during the data half of the bit cells, we have low on the output line for four bit cells, giving us four bits of 1, followed by a bit cell where the data half has a high on the output meaning a bit value of 0. That represents the sync word pattern 1 1 1 1 0 and we have properly detected sync. Note that my catch output is high for the four bit cells that are a 1 and low for the last, showing that my logic picked up the pattern properly.

However, in the next section of the trace, the first data word being captured, we seen some places where catch should emit a 1 but did not. The word being transmitted is x8080, which when reversed to write on disk would be the pattern 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 and its four check bits will be 1 1 0 0 to pass the error checking algorithm. The data received was stored in RAM and the disk as 8080, so we know that it did read properly. 


We see the data extracted from that first word and the check bits. The values of the -Write Clock and Data signal are correct and represent the value 8080 plus a correct check bit pattern of 1 1 0 0 but the catch line seems to have missed the check bits that were 1. It turns out that this is a self inflicted error, see my Verilog logic producing the signal catch below. 


At the falling edge of -Write Clock Phase B when we are in the stage of the state machine that is collecting data words, I capture the inverted value of the signal -Write Clock and Data to emit catch. Foolishly, however, I only do this for the first 16 bits of the word being detected. I zero it out for the four error checking bits. 

My python program that interprets the excel spreadsheet stored from the logic analyzer run uses catch to detect the value of every bit, including the error checking bits, therefore it does not correctly check the ECC value. Look at the results of the program below and you will see that it flags the first word, 8080, as having an ECC error when it is only because my diagnostic output catch failed to emit them. 


By the time we get to word 5, however, we have a true issue with the logic which I will cover in the next section. Meanwhile I will correct the verilog code to include the ECC bits in the catch signal. 

Bits emitted by 1130 are out of sync with the detected values

The sequence that I wrote from the buffer in the 1130 was 8080, 6969, 0000, 0000, 0002, 2000 and other data - the V2315 gets it right for quite a while, judging by what was written to RAM. It only goes off when it is capturing data I wrote as F000 that it recorded as 01E0. This is a run I did after I completed the logic analyzer capture, so the results are a bit different than what I see in the spreadsheet and logic analyzer trace. 


Going by the data captured in RAM, it captured 0002 and 2000 properly, as shown below. The 1130 has correctly produced the pattern for 0002 (inverted 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 with ECC bits 1 1 1 0 and we saw that.  


Similarly, the next word (x2000) is correctly captured and the logic analyzer trace looks good. 


It is only when we get down to around word 50 that we see the capture go off the rails during the final test run. At least through word 10 everything was recognized properly. There are a bit less than 800 bit cells between the last known good word and the first known bad word. Sometime in the 116 microseconds that span took, a bit was shifted off. 

I turned to the run where I have the logic analyzer capture and produced a spreadsheet from it. When I look at the trace I see that the 1130 and V2315CF got out of sync by the time of word 5. It should have been reorded as 0002 just as we see in the picture above, but it came out as 0004 with malformed ECC bits. 

Somewhere from the correctly placed bit 15 (next to last bit) of word 2, which was decoded as x6969, up to word 5 bit 2 (second bit) which should have been a 1 but the 1 is shifted to the right one bit. All the 1 bits we expect are shifted to the right one bitcell from this point forward. 


The timestamps in the spreadsheet and the logic analyzer trace shows that the bit cells are in the correct place, it is the bit value sent by the 1130 that has shfited to the right. On this run, we saw another shift of a bit to the right somewhere from the end of word 9, which should have been 1236, and the first few bits of word 10 which should have been captured as 1237. What was captured for word 9 was 246C and word 10 was grabbed as 48DC. This is the second shift to the right during this run.

Thinking about how this could happen, it suggests that the IBM 1130 is how we are getting out of sync. The logic that transmits the data is driven by the -Write Clock Phase B that is generated by the V2315CF. That signal enters the logic of the 1130 disk controller in two places. The first generates the shifting operations that move the bits of an 1130 data word out serially bit by bit. The second controls the multiplexing of the -Write Clock and Data output signal between the 1 that is sent for the clock half of the bit cell and the data bit sent in the second half of the bit cell. 


Above we see that when a write is underway (+Write Select is high), the -Write Clock Phase B drives the -Counter Sample signal low while the clock is high. This means during the data half of the bit cell. Also, during a write (+Write Select high) whenever +Bit Counter Gate is high and -Bit Counter E is high, the signal -Shift Gate is asserted low. 

Each word from the buffer in memory is fetched into the disk controller and then the bits are shifted out one by one to write serially on the disk drive. Hardware in the controller counts out the bits, so that the data word, which consists of 16 bits, is shifted out and then four error checking bit are emitted. The counter counts out the 20 outgoing bits.

Bit counter E is on during the four error checking bits, otherwise it is off. Since it is inverted logic, when -Bit Counter E is high, we are outputing the 16 data bits of the word then low during the rror check bits. This means that the signal -Shift Gate is low when the +Bit Counter Gate is high and we are handling the data bits.  

During a write, when we are in the data half of a bit cell, the signal -Counter Sample is low. 


The actual pulse that causes the data to shift is triggered by a pulse called -Shift SP if the signal -Shift Gate is low and a pulse arrives because -Counter Sample goes low.  From above, -Counter Sample goes low when -Write Clock Phase B goes high which is when we are entering the data portion of the bit cell. The single shot timer delays this then activates the shift pulses and also increments the two bit counter for the ECC value if the data bit being transmitted is a 1. 

The output from the 1130 on -Write Clock and Data is a line that emits a 1 or 0 value (inverted) and the value emitted depends on whether we are in the clock half of the bit cell or the data half. The bit cell is defined by the -Write Clock Phase B signal coming from the V2315CF - when that signal is low, it defines the clock half of the bit cell and when it is high we are in the data half. 


It is only active when +Write Select is high, e.g. when we are in a write. The output is low when -Write Clock Phase B is low, meaning we send a 1 bit during the clock half of the bit cell. The output is also low during the data half of the bit cell if the bit at the end of the shift register is high and -Bit Counter E is high (we are processing the 16 data bits of the word) - this means that if the end of the shift register is a 1, we assert -Write Clock and Data low during the data half of the cycle.

Finally, if we are handling the four error checking bits after we shifted out and transmitted all 16 data values, then +Bit Counter E is high and as long as the two bit counter for the ECC value is not zero, we assert -Write Clock and Data low to output a 1 as an error checking bit. The two bit ECC counter is incremented by this output. As the bit counter counts out bits 17 to 20, we send out a bit value of 1 when the ECC counter is non-zero and then send out a bit value of 0 once it becomes zero. 

This is how we calculate the correct number of 1 bits to send in the ECC bits so that the total of all 1 bits transmitted becomes an even multiple of four - the two bit counter rolls over to zero if it reachs 3 and is incremented. This produces the only valid ECC patterns 0000, 1000, 1100, and 1100 as these occur when the initial value of the ECC counter was 0, 3, 2 or 1 respectively when we finished counting the 1 bits in the 16 bits of the data word. 

The failure we are seeing is that we are missing a shift of the data and not incrementing the bit timer even though we have a bit cell (a complete cycle of the -Write Clock Phase B signal). The bit cell comes in, generated by the V2315CF, and we emit the 1 value during the clock half of the bit cell, but since we didn't see the high value of -Write Clock Phase B during one of these glitches, it didn't drive -Counter Sample and we didn't produce the shifting and counting pulses. Whatever bit value was in the end of the shift register is just transmitted another time when this situation occurs. 

This has to be caused by the poor signal quality observed where the -Write Clock Phase B signal enters the 1130 at gate A, compartment C1, slot K6, pin B03. Once I correct the signal quality, I expect the slipped bit problem will disappear. 

PLAN TO FIX THE QUALITY OF THE CLOCK SIGNAL ENTERING THE 1130

I had installed some weak terminator resistors for this output, which don't seem to have the oomph to pull the signal line up even to 2V because of the voltage divider formed in the path from the terminator to the input of the gate at pin B03 of slot K6. I will restore the 169 and 249 ohm resistors at R33/R34 of the terminator board. That should also help with the ringing observed on the scope. 

I will observe the signal using the scope after making the change to the terminator resistor pair. Assuming I see the signal rise up closer to 3V, the rise time improve and the ringing ameliorate, I will run new tests to check the functionality of the write to the V2315CF. 

Monday, September 28, 2026

Testing Virtual 2315 Cartridge Facility capturing data written from the IBM 1130 to the virtual disk

RAN WITH THE NEW LOGIC, TESTING WRITE IN VIRTUAL MODE

Armed with the logic analyzer trace of the exact timing that the Virtual 2315 Cartridge Facility (V2315CF) would see of the two related signals, -Write Clock Phase B and -Write Clock and Data that are used during a write to the disk, I arranged the logic in the FPGA to capture the correct bit values so that they could update the sector data in the RAM, just as the sector would be updated on a 2315 cartridge in the internal disk drive of the IBM 1130 if we had not installed the V2315CF to intercept the signals. 

The method used to store data on the internal disk drive (2310) uses two 690 nanosecond long intervals, back to back, to record each bit. The first of the two intervals always has a pulse, which is a clock. The second of the two intervals only contains a pulse if the bit value is 1, otherwise the interval passes without a pulse. 

A sector begins with a long string of 0 bits, allowing the drive to synchronize in order to assign each pulse it sees to either a clock or a data signal line. The first 1 bit defines the start of an 1130 data word begins as the next pair of intervals. The 1130 has words of 16 bits, but on the disk an additional four bits are recorded for error checking. Thus there are twenty pairs of intervals per word, with up to 321 of these fitting on a sector of the disk. 

When a write begins, triggered by the 1130 activating the signal -Write Gate, the disk drive starts generating a clock signal of 1.44 MHz while which is assigned to be the clock, then on the other half of the cycle it will only emit a pulse if the data bit value is a 1. Both the clock and the data interval are s nt on the same signal line -Write Data and Clock, which the V2315CF has to evaluate to determine which bits are a 1 and which are a 0. 

When the -Write Clock Phase B signal drops from high to low, which marks the data interval, my logic will grab the value of -Write Data and Clock and if it is low, the bit value is a 1 otherwise if high the bit is a 0. It had previously waited through the initial sequence of 0 bit values until the first 1 bit is seen. We then collect the next 20 bits and save the first 16 as the word. 

The last four are a special pattern that matches the number of 1 bits in the first 16. This error checking code allows the disk drive to detect errors when reading back the data later; if the error checking bits aren't write, the 1130 flags the data has invalid. 

RESULTS OF WRITING A SECTOR TO THE V2315CF WITH THE NEW LOGIC

I started up the 1130 with the V2315CF in the virtual mode. A mini 2315 cartridge was inserted into the V2315CF and loaded, so that the File Ready light illuminated on the 1130 console. I executed an XIO Start Read instruction which brought the data from the sector into memory. I altered a couple of words of the data and then issued an XIO Start Write to put back the modified data in the sector. 

I zeroed out the area of memory then repeated an XIO Start Read to bring back the value from the V2315CF into memory. If it matches the modified version and as long as the V2315CF validates that each word had the correct error checking code when it was written, then we know that the write is working properly. 

However, initially I was getting garbage in the buffer and back on the mini cartridge after I unloaded it. I traced it down to an error that regressed into the code as I was adding in some diagnostic output. The memory controller was not properly advancing the address after writing each word to RAM. It took a while to find it, some simulation to prove it however the fix was quick. I just returned the proper logic statement to the code and that issue was gone.

However, I was back to the problem that the logic was not capturing the bit stream coming from the 1130 system. I put the logic analyzer on to the V2315CF and captured four signals: 

  • -Write Gate (which turns on a write to a sector)
  • -Write Clock Phase B (the clock signal I send to the 1130 to cause it to emit both clock and data bits depending on whether this signal is high or low)
  • -Write Clock and Data (a value of 1 that is either a clock bit or a 1 in the data. A 0 data value is sent as a zero during the data portion of the prior signal)
  • Bit value (a diagnostic output set to 1 when the data bit value of 1 is detected). 

I saw that the logic did NOT identify the start of the data on the sector, which would be a specific bit pattern that is the sync word. The capture during the time when the 1130 is sending the sync word is below. The four signals above are shown in order as horizontal traces. 

The sector begins with a long string of 0 data bits which is terminated by the bit sequence 1 1 1 1 0 causing the logic to begin sending 1130 data words as streams of 16 data bits plus four error checking code digits. The sync word is a word of value 1000000000000000 plus an ECC sequence of 1110 that validates the word as properly formatted. At the end of the sync word, the next bit is the start of the first data word of the sector. 

The -Write Clock Phase B signal alternates strictly at a 720 KHz rate, with the high level denoting the data portion of a bit cell and the low level of this signal signifying the clock portion. During the clock portion of every bit cell, the value of -Write Clock.  and Data is a logic low which means a 1 bit for the clock. There is always a clock bit in every bit cell but during the data portion of the bit cell we either have a logic low on -Write Clock and Data which means the data bit is 1, or a logic high that means the data bit value is 0. It can be confusing to interpret because of the inverted logic - a logic low means a value of 1.

The failure to detect the sync word is visible because the fourth signal in the trace should emit a 1 for each bit position that is transmitted as a 1, but it is a while later before the logic begins emitting that signal. This means it did NOT detect the sync word properly. 

At least I now have a view of the data coming in from the 1130 which should help me devise a strategy for reliably detecting the bit values. A bit of design work, some extensive simulation and then I resume testing in the workshop.