68kMLA Classic Interface

This is a version of the 68kMLA forums for viewing on your favorite old mac. Visitors on modern platforms may prefer the main site.

Click here to select a new forum.
Vibecoded FPGAintosh Quadra 700 w/ custom 68040 core
Posted by: qwertyoruiop on 2026-09-20 09:22:01
I've been trying to see how far can AI really go when applied to RTL and FPGA development, so decided to let it go at at a full-scale CPU and SoC development.
Goal was to design a "modern" Macintosh SoC / core, so this is not bus-faithful whatsoever: in fact, we run AXI under the hood.
The CPU is not derived off the usual 68K RTL but is a custom derivative of NaxRiscv, and is a superscalar (2-wide-retire) OoO core targeting a 68040 feature set written in SpinalHDL. It internally cracks CISCy ops and complex EA modes into simpler uOps.
There's still some bugs in the CPU for sure (for example I am unable to run TattleTech) - but it seems to mostly work.

It's still got a lot of known issues and it's certainly got cruft, over-engineering and generally doesn't seem like the cleanest RTL codebase, but it successfully closes
CPU and fabric timing @ 200MHz and runs to Finder on 7.5.3 correctly.
Clock-for-clock though it's currently not doing great vs the real 68040 because we still have a pretty poor mispredict rate and pipeline flushes are quite expensive.

macq.JPG

The reference system peripherals were implemented after is the Macintosh Quadra 700.
The target board is a "cheapo" (although price has been rising lately) used Chinese board I've acquired off eBay, the RK-XCKU5P-F V1.2.
SCSI currently emulates a HDD served off of a SD card, video-out goes to an AN9134 24-bit-RGB-to-HDMI board off the 40pin I/O.
SIWM is just a stub at the moment.
Gigabit Ethernet is supported using FPGA Taxi's RGMII stack, and I've successfully used it to go on the internet via OpenTransport on 7.5.3.

board.jpg

I'd eventually like to try and get a board done with the required level conversion to expose real SCSI and NuBus off the FMC header in order to allow physical hardware to be connected, and I'll likely move to a different (still UltraScale+ KU5P based) board that also has HDMI TMDS already on-board in order to free the 40 pin header up for low-speed signaling such as physical ADB.

ADB - due to lack of I/O - is currently only usable via JTAG-based event injection. A really awful Vivado TCL based REPL currently implements this, and a janky vibecoded webUI exposes the most commonly used functionality and a video stream off a capture card (which I've used to do remote development).

A bunch of video modes (eg 832×624 @ 24bpp) also break scanout, still, but 1bpp and 24bpp both work in general.
VRAM and ROM are in DDR, and BRAM is used as line buffer to smoothen out DDR refresh cycles for scanout.
All of KU5P's URAM is used as a 2MB L2 cache, and we're using roughly 150k LUTs, ~100k of which for the CPU alone.

You can check out the SoC's repo at https://github.com/kpwn/macqd700-soc, while the CPU is at https://github.com/kpwn/m68k-core-040-ooo.
I've uploaded a pre-built bitstream @ 200MHz in the SoC GH releases if you wanna try it out; you'll need both the target board and the AN9134 though.

A ROM patch is needed due to some calibration loop running too fast relative to VBL (which does 60Hz rather than 60.15) when the CPU is clocked at these speeds, but we otherwise run a normal Quadra 700 ROM.

I know AI use is controversial, and I'm not claiming any of this is either accurate, complete or reliable, quite the contrary actually.
It's just a project I've wanted to do for a while (esp. the CPU design side), and I'm quite surprised it got anywhere close to this.
All the relevant thanks and copyrights go to original authors of NaxRiscv (for the CPU), MAME (hardware reference for peripherals) and FPGATaxi (for SoC builds with Ethernet). Testbeds and differential CPU fuzzing use Musashi as reference.

I'd love any feedback and potential features/peripherals to add! LUTs are quite tight but a couple nontrivial peripherals can be squeezed in still.
Posted by: Melkhior on 2026-09-20 09:42:18
Nice job! The KU5P is a a pretty big FPGA for hobbyist though and I don't think it's supported by the free vivado license? 150k LUTs is a lot, but that fill only about a third of the KU5P - might be able to shrink that into a more affordable Artix... (perhaps going the cheap way and replacing the full MC68040 by a MC68LC040, I imagine the FPU is taking quite a lot of resources).

NaxRiscv is a great RISC-V core - a worthy successor to the awesome VexRiscv. For some reason I've always tried to recreate the cores from scratch rather than coerce a RISC core into executing M68K code; but if the approach works, Nax is a great starting point.

EDIT: looking at the project, you can't execute from I/O space, does that mean for now you can't run DeclRom from devices? If so that will limit your options for adding external devices.
Posted by: qwertyoruiop on 2026-09-20 09:53:03
Nice job! The KU5P is a a pretty big FPGA for hobbyist though and I don't think it's supported by the free vivado license? 150k LUTs is a lot, but that fill only about a third of the KU5P - might be able to shrink that into a more affordable Artix... (perhaps going the cheap way and replacing the full MC68040 by a MC68LC040, I imagine the FPU is taking quite a lot of resources).

Thanks! I think you might be mixing KU5P and (probably) KU15P up. There's "only" 200k LUTs on the KU5P, but the upside is that it is supported by the free Vivado license. I believe it might be possible to sacrifice a lot of the complexity to target a smaller device; quite a bit of area was traded in order to close 200MHz. It might make more sense to try and come up with an in-order CPU though, which probably delivers a better area/perf point for smaller devices.

EDIT: looking at the project, you can't execute from I/O space, does that mean for now you can't run DeclRom from devices? If so that will limit your options for adding external devices.
That is a valid point that I hadn't considered. Since I depend on I-cache miss-time predecode to precalculate instruction lengths, fixing this issue is not going to be simple, since that depends on a single fetch being able to return a large amount of bits at once. A cheap hack would be to try and coerce L2C into holding DeclRom address space, or more properly some slow path that still manages to keep the core fed albeit at a slower rate for cache-inhibited instruction fetches.
Posted by: Melkhior on 2026-09-20 10:04:51
Thanks! I think you might be mixing KU5P and (probably) KU15P up. There's "only" 200k LUTs on the KU5P, but the upside is that it is supported by the free Vivado license
I'm probably mixing them up - the UltraScales I don't practice much, they are usually too expensive for a hobbyist. AliExpress boards are more "affordable", but are usually terrible in terms of publicly available documentation (and documentation in general). I have a couple of QMTech board because they're an exception - the documentation it still terrible, but at least it's public on GitHub so you can do dry-run synthesis before actually buying anything.

fixing this issue is not going to be simple
Darn. Also the lack of proper '040 external bus means it can't be directly use to provide acceleration to a real Quadra; not that it would fit in the xc7a35t I have in the QuadraFPGA (and as mentioned elsewhere, doing another Quadra PDS board with a more suitable FPGA is blocked by the unavailability of the connector).

Have you thought about the bus issue? Not specifically for the '040 - I'm wondering if a Nax-based high-performance '030 (FPU-less) would fit in a xc7a50t (which I already have in my IIsiA7 Mini) or xc7a100t (which it can can accomodate, I might need a respin to fully support CPU-replacing mode anyway). My experience so far is that AI-generated cores are big and slow, but deriving from the lean-and-mean Nax is certainly a way to avoid that problem.
Posted by: qwertyoruiop on 2026-09-20 10:38:54
I'm probably mixing them up - the UltraScales I don't practice much, they are usually too expensive for a hobbyist. AliExpress boards are more "affordable", but are usually terrible in terms of publicly available documentation (and documentation in general). I have a couple of QMTech board because they're an exception - the documentation it still terrible, but at least it's public on GitHub so you can do dry-run synthesis before actually buying anything.
The board in question was exactly one of those mystery boards and I got it for ~$250; thankfully the vendor on eBay was nice enough to share a bunch of example projects with constraints, but it was a total gamble when I got it. Nowadays I think it's actually been documented by several people, and I assume prices spiked because of that.

Does any real hardware out there do self-modifying or banking in DeclRom? I'm thinking it might be possible to simply have "cache-inhibited" fetches not actually inhibit the cache line but split the fetch into many 8-bit-wide reads (or 32, although 8 is probably the conservative pick for MMIO). Horrible for performance, but it'd only affect early ROM and DeclRom. It would still not be a real cache-inhibition though, but maybe it can be made to work.

Have you thought about the bus issue? Not specifically for the '040 - I'm wondering if a Nax-based high-performance '030 (FPU-less) would fit in a xc7a50t (which I already have in my IIsiA7 Mini) or xc7a100t (which it can can accomodate, I might need a respin to fully support CPU-replacing mode anyway).
Yeah, i don't think the core design used here really makes sense for interfacing with actual 68k buses. The best shot is probably going to be an in-order but lower area and high clock design. It may even outcompete this OoO core, honestly. Vex is probably a better starting point for that, and a lot more care will be required on the forwarding side of things since read-after-write dependencies are super prevalent due to uOp cracking and there won't be OoO to hide stalls.

Question is: how are you going to keep a high-clocked CPU fed with the legacy bus? Only expose peripheral accesses over the real bus at real bus clock-speed while using on-board DRAM as high-speed memory?
I'm thinking it would take large amounts of caching to actually deliver perf. UltraScale's URAM would be quite nice to have in this scenario, heh.

My experience so far is that AI-generated cores are big and slow, but deriving from the lean-and-mean Nax is certainly a way to avoid that problem.
There was an earlier "v1" core that was developed without Nax as a reference. It was worse in every metric: area, fmax and IPC. I think the biggest issue with AI use is that it's really bad at creative thinking and it needs to be grounded to some kind of reality and be fed inspiration and experience. Giving it something to ground the result against really did improve things dramatically.
Posted by: lauland1 on 2026-09-20 11:46:59
Caching would be troublesome with dma devices possibly also writing to on board ram. Ignoring on board ram, and just running the majority of code out of fpga ram would be the way to do it.

There are a LOT of "smaller" FPGA boards out there that can be gotten for very low cost. This is a VERY interesting idea I hadn't thought of.

I really like the idea for the core, and is also something I hadn't thought of, and really need to look into.
Posted by: Melkhior on 2026-09-21 00:06:27
Does any real hardware out there do self-modifying or banking in DeclRom?
Would banking matters? Self-modifying is not an option for a ROM, if the code wanted so self-modify, it would need a copy in RAM which would solve your problem - unless it uses in-device RAM... but I don't know of any device that does that. There's a thread on 68kMLA from someone collecting DeclRoms if you want to double-check.

I'm thinking it might be possible to simply have "cache-inhibited" fetches not actually inhibit the cache line
I'm not sure I understand the issue. Vex (and I assume Nax) supports non-cacheable I/O area, and have no problem running code from them. If the underlying bus interface can break wide accesses into sequence of smaller accesses, except for performance, the CPU shouldn't care...

Yeah, i don't think the core design used here really makes sense for interfacing with actual 68k buses
Yeah, in particular as for some use cases (old Suns 🙂 ) who need accurate FC handling...

Question is: how are you going to keep a high-clocked CPU fed with the legacy bus?
MC68030 has data cache and the programming interface is such you can likely extend them without patching software - not the most efficient way (write-through, ...), but larger caches would help and wouldn't interfere with existing code (provided they support handle the existing caches properly).
Posted by: qwertyoruiop on 2026-09-21 11:22:07
Would banking matters? Self-modifying is not an option for a ROM, if the code wanted so self-modify, it would need a copy in RAM which would solve your problem - unless it uses in-device RAM... but I don't know of any device that does that. There's a thread on 68kMLA from someone collecting DeclRoms if you want to double-check.
Banking would be the only real user (except RAM-backed DeclRoms, ofc) of an inhibited memory region that actually does depend on the I-cache being inhibited.
I'm not sure I understand the issue. Vex (and I assume Nax) supports non-cacheable I/O area, and have no problem running code from them. If the underlying bus interface can break wide accesses into sequence of smaller accesses, except for performance, the CPU shouldn't care...
Since M68K has variable-width instruction length, doing two-wide decode results in a deep combinatorial loop due to the instruction length of the first instruction being needed to kick off the decode of the second one. The design works around this by doing a pre-decode step upon instruction cache line miss that pre-calculates lengths, and this is needed to feed the decode stage.
I could kill the two-wide decoder for inhibited fetches, but it would involve fmax sensitive stuff, and I don't have any real headroom in the decode stage. Moving the complexity to I-cache miss (or yeah, bus) case where I'm relaxed with timings (it's off the hot path) would be nice, but short of just letting the line auto-invalidate after being accepted by decode, it'd still leave lines resident, thus breaking eg banking / ram self-modifying DeclRom.
MC68030 has data cache and the programming interface is such you can likely extend them without patching software - not the most efficient way (write-through, ...), but larger caches would help and wouldn't interfere with existing code (provided they support handle the existing caches properly).
Yeah, with extensive caching I could see this working, and maybe the Nax-derived core might be shoehorned into it. Dropping the FPU, the second ALU and squeezing some functionality I think it might just fit your FPGA, but it'd require some work.
I'm interested in trying the same approach on Vex to come up with a '030 instead, though, and maybe I can try to aim for a much lower LUT count there.

I'm also thinking about what @lauland1 mentioned about having on-board FPGA DRAM.
Ignoring DMA it would be quite fun to just run the peripheral bus off the actual M68040 bus interface, and I think it's achievable even with a core design like the one here.
I guess to successfully pull DMA off we'd need to inhibit accesses on to system DRAM, and somehow backpressure DMA traffic somehow, then snoop the bus when externally mastered.
I'm not familiar with the PDS pinout, but it'd be pretty cool to run the real Macintosh's IO off a FPGA. I have a 475, and we shouldn't have any DMA problem with that one...
Posted by: impressionist on 2026-09-24 10:09:35
Very interesting. If I understand this correctly you fuzz tested for equivalence against Musashi and then used counterexamples from that as test cases for the CPU implementation, and did that repeatedly until it passed?
Posted by: lauland1 on 2026-09-24 10:28:17
The pistorm mac people got some good results by ignoring as much motherboard ram as possible, and running code out of the pi's. Some interesting things are going on with them finding (and possibly solving) some very long standing timing bugs, causing floppies and other things to fail.

I think the only "dma" they have to deal with is scsi, which isn't working in a basic sense so bypassed...for now. They may soon have scsi working, so will run into that, but I don't think it's "real dma" so shouldn't be too much of a problem.
1