Saturday, February 15, 2025

Simulating capturing a write to the Virtual 2315 Cartridge Facility

WRITING TO THE DISK FROM 1130 INVOLVES SIGNALS ORIGINATING IN THE DRIVE

The disk drive generates a 720KHz signal which defines the bit cells that will be written onto the platter. This signal is passed to the IBM 1130 controller logic which uses it to gate signals out a combined clock and data write line. When the bit cell is in the first half (clock) the 1130 always emits a 1 value, while in the second half of the bit cell we emit either 1 or 0 depending on the bit value encoded in that bit cell. 

USED PREVIOUSLY DEVELOPED LOGIC TO SIMULATE THE COMBINED CLK + DATA LINE

I had developed macros and logic to simulate the output from the controller as it wrote a sector to the drive. I used this as input to my design, triggering it to command a write at sector 1 of head 1 of cylinder 1. The data was decoded and written to SDRAM at the correct addresses, exactly as desired. 

NEXT - GENERATE THE FPGA LOGIC AND DOWNLOAD ONTO THE RK-05 EMULATOR

Next up I should shift over to the Lattice toolchain to generate the FPGA bitstream and load it to the RK-05 Emulator hardware that I am leveraging for this virtual disk drive. A similar generation must be done for the C code that runs on the Raspberry Pi Pico inside the RK-05 Emulator, then update the Pico. That enables the start of live testing on an IBM 1130 with its internal disk drive. 

Simulating the download of a sector from the PICO to the SDRAM

SIMULATING THE SPI TRAFFIC THAT WOULD COME FROM THE PICO SOFTWARE

The software opens the virtual cartridge file on microSD card and reads through it, sending the words down to the FPGA using SPI messages. Each word is pushed using two SPI x06 messages, each transporting 8 bits of the word over the link. It produces the intended RAM address and pushes it over SPI before each sector, thus using three x05 messages. 

An entire sector is written with three x05 and 642 x06 messages. I simulated a download of one sector, again using cylinder 1, head 1 and sector 1 to validate the address generation, however I didn't write all 321 words since the first few is enough to ensure the logic is working. This worked perfectly.

I then simulated an upload from the same location, which I did by issuing three x05 to set the address and then pairs of x88 to read the data. It gave me the proper data. 

Simulating Virtual 2315 Cartridge Facility doing a read

MUST SIMULATE CONTROLLER, DISK AND THE PICO LOADING SDRAM CONTENT

Another layer of complexity was added here as I must set up the SDRAM contents if I am going to verify that an attempt by the controller logic to read a sector receives the data properly. As I wish to verify the RAM addresses being generated, I can't just read the first sector as that has cylinder, head and sector values of zero. 

The Raspberry Pi PICO reads the virtual cartridge image from the microSD card and pushes the contents over SPI to the FPGA, which writes them in the SDRAM. This involves 643 SPI messages which I can simulate because of my macros. If I see that the proper data is being written to SDRAM addresses to match the intended sector, that would be sufficient for the test. 

My SDRAM simulation can pull data from a text file which I preload with the contents that represent the sector. The file must be large enough to get to cylinder 1, head 1 and sector 1 at least in order to have non-zero values for these fields that make up the RAM address. This requires 4,494 lines in the file to cover 321 words for each of 14 sectors, but due to the sparse addressing scheme of the SDRAM that sector starts at word 6656 and ends at 6977 thus the file is larger. 

I used a Python program to generate the file and stored values that correspond to the sector and word so that I can easily tell if the correct word is fetched at any time. 

RESULTS WERE GOOD - THE DATA BEING EMITTED IS WHAT I PUT IN TEXT FILE

I did see the program receive the values 1A00 to 1B40 which are the ones in the file corresponding to that sector. Further, the clock and data pulses generated by my design and sent to the IBM 1130 controller logic were correct for those values. 

EXAMINING PROPER ADDRESS TO SDRAM

Looking at the values used in the SDRAM controller module, it was reading from the intended addresses 1A00 to 1B40 just as it should. It is time to turn my attention to simulating a sector write from the 1130 and ensure that I capture the data properly and store it in the intended RAM locations. 

Simulating Virtual 2315 Cartridge Facility - modeling disk and 1130 controller to do seeks

MUST MODEL BOTH DISK DRIVE AND IBM 1130 CONTROLLER LOGIC/SOFTWARE

This facility is interposed between the internal disk drive (Ramkit or 2310) and the disk controller logic in the IBM 1130 that would be driven by software attempting to use the disk cartridge. Thus to properly test this I must simulate both sides faithfully and verify the actions of my design.

For example, the controller logic won't attempt a seek until it sees that the disk is ready (FILE_READY signal) and that arm movement is possible (ACCESS_READY). The disk drive will assert FILE_READY when it believes it has loaded the heads on a cartridge that is spinning in the drive. It will turn off ACCESS_READY when an arm movement is underway (or for certain error conditions). 

My design won't turn on FILE_READY to the controller logic until we have the disk signal FILE_READY and we have a valid virtual 2315 cartridge image loaded into the SDRAM ready for access. It passes the ACCESS_READY state from the disk to the controller logic. 

As you can see from the above, every signal that normally passes between controller and disk drive becomes two signals connected to my design, one to the drive and the other to the controller. For many I just pass them along but observe them to shadow the results in the disk drive or controller. For others, I generate these and ignore those from the disk drive - this includes the clock and data signals that normally would be detected by the disk heads. 

SEEK MODELED AS A MACRO I CAN CALL IN SIMULATION

I set up a macro that will perform a seek, modeling the signals that would be produced by the controller and the result signals that would be produced by the disk drive. A seek is requested by the controller dropping ACCESS_GO and the drive responds based on the direction (ACCESS_REVERSE) and step size (ACC_10_20_MIL) signals from the controller. 

ACCESS_READY drops, the arm moves and 15 milliseconds later the movement ends with the raising of ACCESS_READY. In the interim the controller raised ACCESS_GO and reset the ACCESS_REVERSE and ACC_10_20_MIL signals. 

SEEK RESULTS ARE GOOD

Using the macro I verified various movements of the arms and that it properly dealt with the stops that occur if a seek is attempted past the last cylinder or reversed before the first cylinder. I  carefully watched the tracked cylinder number, which is what selects the proper area of SDRAM for reading and writing data. 

Friday, February 14, 2025

Building simulation of entire Virtual 2315 Cartridge Facility - FPGA side

CHALLENGES IN SIMULATING THE DESIGN

The SDRAM chip would need simulation but we have previously handled that in prior simulations. 

The IBM 1130 controller logic will produce various signals and expects responses. Too, it relies on signals that originally would have come from a 2310 disk drive but are produced by my design instead. I have simulated a number of such behaviors thus this shouldn't be too onerous.

Finally, the FPGA interacts with a Raspberry Pi Pico running code by exchanging messages over an SPI link between the two bits of hardware. The contents of SDRAM are loaded by the RPi, which reads the from an SD Card and transmits them down to the FPGA. Some interactions are needed to start up the virtual disk drive since signals involved in startup are produced on both sides. 

The most straightforward way to handle the SPI simulation is to faithfully simulate the far end of an SPI link and therefore the signaling over that channel. This involves modulating the SPI clock and transitioning signals on both leading and falling edges. 

Alternatively I could create a shim between the actual SPI logic and the higher levels of my design, injecting just what would be emitted by the SPI logic. Turns out that module is interwoven with all the logic creating and decoding the messages between the RPi and FPGA, so I would lose the important debugging of the messages. 

BUILT UP SPI SIMULATION AND TESTED IT

I defined a macro SPIWORD that would spit out the SPI transmission from the RPi Pico and made use of it to initialize the FPGA as it would be had a disk cartridge been virtually loaded. The Pico code controls everything by either writing changes down to the FPGA or reading the state from the FPGA. 

When the Pico has an entire virtual cartridge loaded into the SDRAM (via the FPGA) it has the FPGA make the disk drive active to the IBM 1130 controller logic. Only the FPGA is involved in actively emulating the disk drive, up to the point that the drive is switched off by the operator of the 1130. The Pico then extracts the updated cartridge image and writes it back to the microSD card on the Pico, before returning to its idle condition with the drive virtually unlocked. 

When the Pico reads a virtual cartridge file from the microSD card, as coded for the RK-05 Emulator, extracts some configuration information from the header of that file and transmits it down to the FPGA. My version skips using that configuration information and does NOT transmit those message types. 

Each message over SPI is a two byte transfer, the first byte is a register number and the second is a data byte. By convention, if the high bit is 1 for a register number, it is used to extract data from the FPGA and use it in the Pico, while a high bit of 1 is used when we are setting signals in the FPGA from data shipped out of the Pico. 

A virtual disk cartridge file is transmitted down by the Pico using register x05 to load the address in SDRAM and register x06 to load the data words. Since we only carry 8 bits on the SPI link but our RAM address is 24 bits and our data word is 16 bits, the design sends multiple of these messages for each address or word.

Thus, we send three x05 messages to load all 24 bits of the SDRAM address where the next data word will be stored. We send two x06 messages to transmit all 16 bits of a data word which is then written to SDRAM. The address automatically bumps up so that successive data words are written by pairs of x06 without the need to change the start address with triplets of x05. 

A virtual cartridge consists of 521,304 words, thus there are more than a million x06 messages involved in loading one cartridge to SDRAM. With the SPI link able to send over 25,000 per second at its 460K clock rate, we can still load a cartridge in under a minute. However, that would be a punishing amount of SPIWORD macros to code. I will send some sample data to a number of locations and verify that it is being written to the intended SDRAM addresses. 

If I wanted to load an entire cartridge, I would set up file IO in the simulator to pull the messages from a text file and fit them into the macro, running in a large loop, but I have confidence I can validate the logic without needing an entire cartridge to be loaded. 

When a cartridge has finished being used, with the operator switching off the drive motor, the Pico needs to upload the entire SDRAM virtual cartridge data, since it may have been changed by write activity from the IBM 1130. This is done by again starting the address with a triplet of x05 messages and then issuing pairs of x88 messages to read a word of SDRAM and send it back, half in each of the pair of messages. 

The major message coming from the Pico is the x00 register which sends a few signals to the FPGA:

  • Cart_Ready - is turned on when the virtual cartridge data has been pushed down to SDRAM
  • Fault_Latch - is turned on when various errors show that a cartridge image is compromised
Another message, x04, toggles the Write Protect status. If on when the drive power is switched off, it means the cartridge image is not written back to microSD at the end. This gives us a disk image that is restored to its fresh condition after each use, unlike normal mode where anything done by the IBM 1130 has changed the cartridge image on the micoSD card. 

A corresponding message xA0 will inform the Pico of the state of conditions in the FPGA:
  • Disk Ready - the drive is spinning at speed, thus the chosen virtual cartridge can be downloaded into SDRAM
  • Disk Fault - an error such as check bit validation or other failure was detected
  • Cart Ready - the virtual cartridge is loaded into SDRAM
  • Drive Unlocked - the drive has come to a stop so that physical cartridges COULD be removed or inserted, but in this case it means we can mount a virtual cartridge when this is on. 

To start up the system, the Pico reads the virtual cartridge file and downloads its contents to SDRAM as described earlier. When done, Cart Ready is turned on. Once we see the BUS_UNLOCKED_DRIVE_H signal go low, it indicates we are spinning up the physical drive. The logic watches the drive's 90 second delay relay signal BUS_90S_RELAY_DRIVE_L which gives time to clear out dust and stabilize the platter before the heads attempt to load. 

The Pico sees the drive is ready after the 90 seconds have elapsed.  This causes the IBM 1130 to see the signal BUS_FILE_READY_CTRL_L go low indicating that disk access is now permitted. 

 I simulated an x00 message to turn on Cart Ready. I then manipulated the unlocked and 90 second delay signals, ensuring that our drive was ready. This did produce the file ready indication however I now want to work through all variations and scrutinize the state of the design for correct operation. . 

Wednesday, February 12, 2025

Finished simulation of sector write for Virtual 2315 Cartridge Facility

CAPTURED OUTPUT FILE MATCHED WHAT I SIMULATED COMING FROM 1130

My test bench modulates the 720KHz clock that would be produced by the real disk drive and fed into the IBM 1130 controller to drive its output during a write. The 1130 then modulates the combined clock and data line to write, which my logic must strip apart to decode the output data being written. 

The testbench produces the signals that would be coming from the 1130 controller logic and the disk drive, while my design attempts to extract the data words and write them to DRAM. In the simulation of the sdram_controller function I extract each word that is written to DRAM and write it to a simulation text file. The resulting text file matches exactly the data pattern I was producing in the test bench. 

NO NEED TO TEST ERRATIC EARLY CLOCK SEPARATION

The disk drive separates the sequential clock and data pulses (or absence of a data pulse when the bit value is zero). It does this by locking onto a long sequence of zero bits that are written as a preamble before actual data is put on a disk sector. It is possible that some clock bits from that pattern will be emitted out of the data bit signal line until the drive has locked onto the preamble. 

The IBM 1130 controller logic ignores the first 200 microseconds of clock and data signals during a read, allowing the drive to lock to the proper position of the serial stream. If my logic was going to be collecting data from a real disk drive that was reading a disk cartridge, it would need to deal with this reality. 

Fortunately, however, my product produces the clock and data signals instead of using those coming from the disk drive. Thus no issue exists with incorrect separation. When my logic is capturing data being written by the IBM 1130, the controller logic has no fault mode that could confuse data and clock bits, unlike the data separate hardware in a disk drive. 

SECTOR WRITE (CAPTURE OF DATA WRITTEN BY 1130) IS VERIFIED

My confidence was bolstered by these tests, which combined the logic I wrote for reading and writing with the sdram_controller logic which is known to correct store and fetch data from the SDRAM chip.



DRAM simulation shortcut for Virtual 2315 Cartridge Facility testing of sector read

WHY I DON'T NEED TO GET DRAM CHIP SIMULATION TO TEST THE LOGIC

Examining the logic of the sdram_controller function that was part of the RK-05 Emulator that I leveraged to create this product, I see that it does not receive any signals back from the SDRAM chip that effects its behavior in any way. It simply steps forward in 40MHz intervals through a state machine that first configures and then drives the reads and writes from the chip.

This means that, since it is proven to work properly in the unaltered RK-05 version, I can assume it will work properly in mine. All I need to do is drive the proper signals into the module that cause it to perform reads or writes and I can have confidence that my logic will drive it properly. 

Interestingly, it doesn't even have a confirmation signal back from a write, thus the only signal that comes back from sdram_controller is the 16 bit data word from a successful read request. My simulation thus only has to provide the data word at the proper time for read requests. 

USING SIMULATION FILES TO FEED DATA WHEN SDRAM CONTROLLER CALLED

The Vivado simulator supports files that can be read or written during simulation. I will use the control various tests. The input file has 322 words which are ascending values thus I can look to see that the proper value is emitted when our IBM 1130 is reading a sector and that it does NOT read the extraneous 322nd word - each 1130 sector has up to 321 words. The output file will record the cylinder, sector and head requested when the 1130 writes a sector, along with the 321 words captured from the 1130's stream of clock and data pulses. 

SECTOR READ VERIFIED WITH ITS INTERACTION TO SDRAM CONTROLLER

Using the simulation method, I satisfied myself that the sector read logic works properly.