News:

I've successfully built LOS from source!: https://lisalist2.com/index.php/topic,644.0.html

Main Menu

A Lisa Inside An FPGA

Started by AlexTheCat123, September 04, 2025, 05:20:35 PM

Previous topic - Next topic

warmech

Hahaha, you're not kidding; there are a few Lisa Rambos out there.

Thinking he's talking about the LRambo mod as seen here.

Manzanavila

Hi, as the colleague says, the LRambo card was a mod for a Sun Remarketing 2mb RAM card that supported the 4mb option for use only with the Mac system, not with Lisa OS.

Manzanavila

This is a render of a 2MB SUN REMARKETING card. If you look in the center, there's a jumper to convert it to a 4MB card. A mod to the Lisa motherboard is necessary for it to work.

AlexTheCat123

Good suggestion, but I probably won't add 4MB of RAM because of the extra cost of a second RAM chip. The boards are already rather pricey, and another chip just increases that price further. And plus, I think only a select few people would use 4MB to begin with. I'm guessing that most people who want an FPGA Lisa are probably going to be using it to run the unique LOS/Workshop/Xenix/UniPlus OSes as opposed to your generic Mac OS that can be run (and run better, no less) on any old Mac.

AlexTheCat123

Sorry for the slower pace of updates lately! School has really picked up as we near the end of the semester, and I've had a lot less time to work on things than I did before. There's not a whole lot left to do at this point though; the main problems that come to mind are hard disk issues, and they might be ESProFile's fault.

I fixed one hard disk issue, where UniPlus would assert CRES midway through the boot process, which would obviously completely break communications with the ProFile. I had temporarily gotten around this by telling ESProFile to just ignore CRES, but I went in and fixed it for real a few days ago. It turns out that I was operating under the faulty assumption that the CRES pin from the VIA would always be set to an output, so I was ignoring the state of DDRB and just blindly piping the pin out to the CRES logic. But this doesn't work if the VIA sets CRES to an input and then puts a 0 in its output register; this will pull my CRES low even though it should actually be floating (which defaults to the desired state of high). So all I had to do was check the proper bit in DDRB. If the VIA's CRES pin is set to an output, then pass CRES on through, but if it's set to an input, then just force our CRES VIA output high.

This is really interesting because it means that UniPlus is setting the CRES output to an input for some reason. I wonder why?

The other two somewhat-major issues left to solve are also both ProFile-related.

One is that Xenix fails to boot with a bunch of ProFile handshake errors. On very, very rare occasions, it makes it to the login screen, but it's quite uncommon, and you're completely out of luck if you try it at anything higher than a 20MHz DOTCK. I'm thinking that this is an ESProFile issue more than it is a LisaFPGA issue though. Xenix works fine on the regular ESProFile, so perhaps it's some sort of subtle timing thing with porting it from a standard ESP32 to a slightly-faster ESP32-S3?

The second is that your very first attempt to boot from the onboard ESProFile at the 75MHz DOTCK will always result in an error 84, but then all subsequent attempts (until you hit ESProFile's reset button) will work fine. It's just that first attempt that's the problem, and only at the 75MHz DOTCK; all three lower speeds work fine. Looking at it with the logic analyzer, it seems that the problem is that ESProFile is sending its data bytes to the Lisa with a 1-byte delay, so it sends the Lisa status byte 3 when it expects data byte 0, data byte 0 when it expects data byte 1, and so on. I have no idea why this only happens on the first attempt and then never again, but it's clearly some kind of ESProFile issue!


sigma7

QuoteXenix fails to boot with a bunch of ProFile handshake errors

Reminder that Xenix's ProFile support is known to be problematic and needs patching to work with faster parallel port drives, see:

http://sigmasevensystems.com/xpf_xenix.html

I don't doubt you've just encountered additional bugs .
Warning: Memory errors found. ECC non-functional. Verify comments if accuracy is important to you.

sigma7

QuoteI've never heard of a LisaRambo card and Google and DuckDuckGo both just turn up a reality show contestant. What's a LisaRambo card?

Paul Capes devised a modification for the 512K Apple Lisa Memory Board using larger DRAM chips, making it a 2MB board. When I uploaded his design to CompuServe ca. 1986 (the days of 8.3 filenames), the filename was LRamBo.

The relevant part of the upload is shown here:

https://lisalist2.com/index.php/topic,392.msg2916.html#msg2916

The 4MB Modification referenced in the other replies came later. The initial implementation was using two LRamBo boards (hence the overlap in terminology), with a modification to support the AST RamStak boards coming shortly after.

The Sun Remarketing 2MB SIMM memory board was designed after that, and included the undocumented jumper to support the 4MB Modification.

The 4MB Modification does require modifications to the CPU Board, but not the motherboard. The LRamBo modification to make a 512K board into a 2M board doesn't require modifying any other boards.
Warning: Memory errors found. ECC non-functional. Verify comments if accuracy is important to you.

stepleton

Quote from: sigma7 on April 10, 2026, 07:31:57 PMWhen I uploaded his design to CompuServe ca. 1986 (the days of 8.3 filenames), the filename was LRamBo.

I love details like this. "Compuserve" is also an important clue, as at least at a certain point it only allowed 6.3 filenames (see PDF page 30 here) owing to running TOPS-10 behind the scenes (see also PDF page 243 here). This would explain why it's LRamBo (six letters) and not LisaRamB or LRamBrd or something longer.

The only inconsistency is that the SIXBIT character encoding used for TOPS-10 filenames didn't have lower case characters, so I would have expected the file to be called LRAMBO instead?

sigma7

QuoteI would have expected the file to be called LRAMBO instead?

That seems reasonable/likely.

IIRC, the upload contained three documents (Two pages of reverse engineered schematics of the 512K Memory Board, and one page for the modifications), so it was probably a .sit stuffit archive.

The documents were created on and uploaded from a Lisa running MacWorks XL, so the original files had long (guessing System 3.0, so up to 31 characters) mixed case names. I don't recall if the CompuServe upload process required pre-naming the upload or providing a (possibly different) name upon upload, but I don't see any uppercase "LRAMBO" file/folder/archive names here.

A brief look suggests the filenames in the archive were "MD2 Lisa RamBo Part 1", 2, 3, implying MacDraw 2 documents. The misaligned text in the pdf is a consequence of hastily converting the files to MacDraw II and then (I don't recall what steps) to create a pdf. Sometimes WYSInWYG.

IIRC, MacDraw 2 knew that it was running on a Lisa, and (assumed) that meant rectangular pixels, so would adjust the aspect ratio when drawing to the screen to compensate. However, it corrected in the wrong direction, so if one drew a circle for example, the circle would be about twice as tall as wide on the screen (but would print as a circle).
Warning: Memory errors found. ECC non-functional. Verify comments if accuracy is important to you.

AlexTheCat123

I finally got the idea to try a real ProFile (not sure why I didn't think of that before), and Xenix fails in the same way on there too, so it's looking like a LisaFPGA issue at this point. I wonder what's going on? Maybe another case of a ProFile control pin getting set to an input on the VIA and me making a bad assumption about it, just like on CRES? We'll have to find out!

AlexTheCat123

The semester is finally starting to wrap up, so I'm finally able to get back to work on LisaFPGA again!

Luckily, I've already been able to fix the two bugs that I talked about in the last update, which were:

Quote from: AlexTheCat123 on April 10, 2026, 05:46:20 PMOne is that Xenix fails to boot with a bunch of ProFile handshake errors. On very, very rare occasions, it makes it to the login screen, but it's quite uncommon, and you're completely out of luck if you try it at anything higher than a 20MHz DOTCK. I'm thinking that this is an ESProFile issue more than it is a LisaFPGA issue though. Xenix works fine on the regular ESProFile, so perhaps it's some sort of subtle timing thing with porting it from a standard ESP32 to a slightly-faster ESP32-S3?

The second is that your very first attempt to boot from the onboard ESProFile at the 75MHz DOTCK will always result in an error 84, but then all subsequent attempts (until you hit ESProFile's reset button) will work fine. It's just that first attempt that's the problem, and only at the 75MHz DOTCK; all three lower speeds work fine. Looking at it with the logic analyzer, it seems that the problem is that ESProFile is sending its data bytes to the Lisa with a 1-byte delay, so it sends the Lisa status byte 3 when it expects data byte 0, data byte 0 when it expects data byte 1, and so on. I have no idea why this only happens on the first attempt and then never again, but it's clearly some kind of ESProFile issue!

The Xenix bug ended up being a problem with the 6522 VIA core that I was using. I didn't write the VIA myself, I stole it from the NanoMac project, and up until now I thought it was 100% accurate to the original. But I've discovered several bugs over the past few days, one of which was causing Xenix to fail.

The specific issue that Xenix was having was that it would sometimes ignore the state of the BSY line coming from ESProFile. ESProFile would have BSY low telling the Lisa to wait while it was busy reading/writing to the SD card, but Xenix would sometimes just pretend like it didn't notice and would proceed with sending strobe pulses and expecting the drive to be sending/receiving data in return. And the strange part is that it would only do this sometimes, like once every several hundred ProFile accesses.

After isolating (with some help from Claude) and disassembling the Xenix ProFile driver, I discovered that it operates in an interesting way. During the portions of the code where it's waiting for the drive to raise BSY, there are actually two things that will cause it to move forward with the ProFile transaction. The first is (obviously) the actual raising of BSY, but the other is a timeout on VIA timer 2, which was presumably meant as a watchdog so that the whole computer wouldn't lock up if the ProFile never responded. The odd thing though is that it seems like they never implemented the watchdog; there's seemingly no code that calls the ProFile driver (or within the driver) that actually sets and starts the timer. But I noticed that, despite this, it was still running, timing out, and causing us to proceed before BSY was raised. But why?

Well, it turns out that it was a bug in the VIA like I mentioned earlier! When timer 2 is in one-shot mode (which is the mode that it's in while Xenix is running), you're supposed to load it with a value once, and then it counts down to zero and generates an interrupt when it gets there. After hitting zero, it actually underflows back around to FFFF and keeps counting down again forever, but it only generates the interrupt the very first time it hits zero (hence one-shot mode). But there was a bug in my VIA where, when the timer is in one-shot mode, it actually generates interrupts EVERY TIME it hits zero, not just the first time, which means that an interrupt is generated periodically the entire time that the Lisa is on (although it's masked, so it's just a bit being set in the VIA's IFR, not a physical interrupt going to the 68K).

But since Xenix is constantly polling this bit in the IFR to use alongside BSY as an indicator that it should proceed with the ProFile transaction, these spurious interrupts can cause us to move ahead when we shouldn't if they're timed just right. Which explains why this would only happen sometimes; most of the time, timer 2 would hit 0 at an inconsequential time, but occasionally it would happen while we were waiting for the drive to raise BSY.

Adding one line of code to the VIA fixed the problem so that the timer only generates one interrupt, and now Xenix boots and runs great, including at the full 75MHz DOTCK!

I'm honestly shocked that this hadn't caused a problem in any other OS! I guess none of them use timer 2 in a way in which it's allowed to count without reloading after a timeout, or don't use it in one-shot mode.

Now onto the second issue: the ESProFile thing where it always sends data bytes with a 1-byte skew on the very first transaction after it comes out of reset, but then never again. This turned out to be a caching issue on the ESP32 side of things, nothing wrong with LisaFPGA itself. Basically, the code that handles the really time-sensitive reading of strobe pulses from the Lisa and the sending of data in response isn't loaded into the ESP's instruction cache until it's been executed for the first time, and it takes quite a while to get it loaded in there when it first gets called. In fact, it takes so long that the ESP misses a strobe pulse before the code is loaded in and executed when the Lisa is running at a 75MHz DOTCK, which is what causes all of the data bytes to be sent with a 1-byte skew. But then all subsequent accesses are fine because the code is already cached at that point.

The fix here is simple: add the IRAM_ATTR attribute to all of these time-sensitive sections of code to tell the linker to place them in fast instruction RAM (as opposed to slow flash) from the very start, so that they never have to be loaded from the flash to begin with. Now things work flawlessly!

And one other thing: I got GEM working! It has never worked up until this point, and I thought that there was actually something wrong with my FPGA implementation, but no. It turns out that GEM just doesn't like having 2MB of RAM to play with. Dropping down to 1MB causes it to work great, and it's insanely fast when you're overclocked to 75MHz!

Unfortunately, it's not all good news. There are still several (rather small) problems left that need to be solved, and I just discovered one more that's actually a regression from where we were before.

This newly-discovered problem has to do with BLU, and it's pretty strange. BLU boots from a floppy just fine, but fails to boot from a hard disk or properly read a hard disk from the Hard Disk submenu. It gets data back from the disk, but the data is all shifted out of place (for example, the drive name is "PPROFFILE" or something like that). Upon closer inspection, it seems as if, for every 4 strobe pulses that BLU tries to send to the drive, the VIA actually only outputs 3 of them, one really long one and 2 normal-length ones.

I've always thought that BLU has a really unique strobe pattern compared to other OS's, so maybe that had something to do with what was going on. I decided to disassemble that section of the code to find out, and BLU sure does do things in a unique (and really clever) way!

If you've ever looked at BLU's strobe pulses, you'll notice that it always sends them in really fast groups of 4, with longer gaps between the groups. And the groups themselves seem impossibly fast; even if you sent two instructions immediately after each other, they wouldn't be able to touch the VIA that fast.

Well, that's the trick that BLU is using: it's not actually multiple instructions! Most ProFile drivers just use a series of MOVE.B's to grab each ProFile byte from the VIAs sequentially, but BLU uses a single MOVEP.L to grab 4 bytes at once instead! MOVEP grabs alternate bytes from within a word, and stitches them together into the destination register, and it's intended to allow the 68K to interface with 8-bit peripherals like the VIA that you'd like to read from sequentially but are only hooked up to one half of the 16-bit bus. The .L part is important because it's making the 68K do a longword operation in which it reads 4 bytes (32 bits) from the VIA, returning the next 4 bytes of ProFile data. Each read from the VIA's input register automatically pulses the strobe, so the very execution of each of MOVEP's reads will fetch the next byte without any extraneous instructions having to do anything.

But this might sound like a problem; we're reading from 4 sequential addresses (really 8 addresses since it's a MOVEP that jumps 2 bytes ahead on each read) but want all of our reads to be targeted to one single input register in the VIA. Well this actually works out just fine thanks to the way that the I/O board is designed. The VIA is addressed by address lines 6 down to 3, meaning that each register happens to be mirrored exactly 8 times. So even though we're reading 8 different addresses, they all point to the input register!

That's really clever, but why are our strobe pulses getting messed up? Well, that's the part that I haven't fully figured out yet, but it seems like we're somehow flying through each of the individual reads within the MOVEP too quickly. The VIA needs two clock cycles on the E clock in order to pulse its strobe, one to lower it and another to raise it, but for whatever reason the CPU is going so fast that it's already requesting the next data on that second clock pulse instead of leaving the VIA alone to let it raise the strobe, meaning that the strobe never gets raised for that particular address. I have no clue why the CPU isn't respecting this timing that is clearly respected on a real Lisa (and in some of my older builds), but it probably has something to do with VPA and/or VMA being generated at the wrong times (which could lead back to IOCY or CPUC1 on the CPU board), or perhaps me generating the E clock strobes at the wrong times.

My next step is going to be to pull one of my old working designs from a couple months ago off GitHub (apparently this has been broken for several months and I just haven't noticed) and build both the working and broken designs side by side to compare their logic analyzer traces. Hopefully something obvious shows up!

stepleton

Thanks for another fascinating and detailed dispatch, and good luck chasing down these last few bugs!