Byte Hamr
Byte Hamr is a general-purpose FPGA expansion card for the Apple II family, designed in KiCad around a Lattice ECP5-85F with 64 MB of SDRAM, 128 Mb of SPI flash, USB programming through an FT231XQ, a JTAG header, and a 20-pin GPIO header. The whole gateware flow is open source: Yosys, nextpnr, ecppack, openFPGALoader. Rev 1 went to fab in December 2025 and worked with a bodge wire. Rev 2 arrived in April 2026 with the R/W inverter on board, a dedicated DATA_OE pin and an nRES the card can read.

Current state
As of 2026-07-10: The hardware is done. What was working on Rev 2 as of 2026-07-10: Block Hamr (ProDOS block device, Rev 2 port 2026-04-22), the Liron rebuild (boots ProDOS from FujiNet, 2026-05-03), the SDRAM monitor with all 1024 banks swept (2026-06-03), the soft 6502 coprocessor through C0 to C4 plus a flash-persistent task registry (2026-06-08 to 06-09), Conway’s Multiverse (2026-06-10), the farm and workshop economy on the coprocessor kernel (June 2026), and the Intel 8008 coprocessor with its on-Apple toolchain, ASM8 and A8 (2026-07-07 to 07-08). The most recent commit moved the 8008 netlist to build-time FuseSoC generation (2026-07-10).
The one open item is DMA, and it needs a Rev 3. Details under Open problems.
Two Rev 2 boards exist. DP0517RX is the primary, DP051FY9 the spare. Rev 1 lives on under the git tag rev1 with its gateware frozen under gateware/rev1/.
Architecture
The Apple II slot bus comes in through six 74LVC8T245 level shifters, 5 V on the slot side and 3.3 V at the FPGA: 16 address lines, 8 data lines, and the control set (PHI0, PHI1, 7M, Q3, R/W, RDY, IRQ, NMI, RES, DMA, INH, I/O SELECT, I/O STROBE, DEVICE SELECT, SYNC). Address and control are input-only by construction. Data is bidirectional through U12, direction slaved to the slot R/W through a 74AHC1G04 inverter (U7), output enable on a dedicated FPGA pin.
The FPGA is an LFE5U-85F-8BG381I, 84K LUTs, 3744 Kbit of block RAM. Beside it sit 64 MB of SDRAM (AS4C32M16SB, 32M x 16) and 128 Mb of SPI flash that holds the bitstream at the bottom and whatever the design wants above 0x400000, usually a disk image or a persisted task registry. A 100 MHz oscillator feeds the FPGA; most designs derive 25 MHz through a PLL and run the SDRAM controller and everything else in that one clock domain, with 2-FF synchronizers where the 7 MHz bus domain crosses in.
USB is an FT231XQ for programming and serial. JTAG is on a header. The 20-pin GPIO header is all 3.3 V LVCMOS33 with heavy ground interleaving, and is how the card talks to a FujiNet ESP32 or an SD card. Power comes from the slot or USB with Schottky OR-ing; three switchers make 3.3 V, 2.5 V and 1.1 V.
The recurring gateware shape is a register file at DEVICE SELECT ($C0C0 to $C0CF in slot 4), a 256-byte slot ROM at $C400 that gets you in with PR#4, and an optional 2 KB expansion ROM at $C800 that stays silent on the shared bus until software arms it with a magic write. That last rule came from a crash: an always-on $C800 collided with the IIe internal ROM during a CATALOG.
Hardware
Rev 1 went to fab 2025-12-06 and was revised to 1.1 through December: ECP5-85F, SDRAM, flash, USB, 12-pin GPIO, 25 MHz oscillator. The first boards arrived the week of 2026-01-17 with both protection diodes installed backwards; after that rework every rail came up. It ran the logic analyzer, the first Smart Hamr and the Flash Hamr series, with three faults worth a respin. The data transceiver DIR needed inverted R/W and got it from a dead-bugged 74F04 and a bodge wire. The transceiver OE was on a GPIO pin. And nRES was output-only, so the card could reset the Apple but could not see the Apple reset itself.

Rev 2 (boards in hand 2026-04-20) fixes all three and shrinks the footprint. U7, a 74AHC1G04, makes the inverted R/W for U12. DATA_OE is a dedicated FPGA pin (B20). nRES is bidirectional: the drive side stays at A8 and a separate nRES_READ input lands at A5, so gateware can watch Ctrl-Reset and recover. GPIO grew from 12 to 20 pins with ground between every signal pair. A 2x3 power breakout exposes 3V3, +5, -5, +12 and -12. The 5 V input diode moved ahead of the level-shifter rail so USB alone can power the bus side for bench work. The oscillator went from 25 MHz to 100 MHz for CDC oversampling and PLL headroom. SDRAM routes were shortened. The USB connector moved, since on Rev 1 it kept the IIe lid from closing. Ninety-three signals kept their exact BGA sites.
Both boards passed bring-up on 2026-04-21.
Assembly is PCBWay. I do not hand-solder a BGA381.
Gateware and firmware
All designs build with make DESIGN=<name> REV=rev2 through Yosys, nextpnr-ecp5 and ecppack. 6502 code is Merlin32 on the Mac, and every source is kept loadable in Merlin Pro on the IIe (single spaces, ASCII, 40-column lines) because a lot of it gets edited there. Gateware is tested in Icarus. Software is tested on the IIe, because iverilog with 48 KB of program is a fifteen-minute run and the IIe turns a fix around in under a minute.
Logic Hamr. The first design, on Rev 1. An 8-channel logic analyzer: 1 MHz capture into SDRAM, edge trigger, decimated readback, waveforms on HIRES with a cursor, A/B markers and four zoom windows from 38 us to 266 us. The IIe side is 6502 written in Merlin Pro on the IIe. Proof of concept on 2026-02-04, and it stayed a proof of concept.
Smart Hamr (Rev 1). The first Liron card emulation, 2026-03-02: IWM written from the patent and the IWM spec after the open-source Yellowstone Verilog turned out to be a dead end, verbatim Liron ROM, an ESP32 DevKitC running FujiNet on the GPIO header with two 22 pF bodge caps for signal integrity. Booted ProDOS and ran Total Replay. Replaced by smart_hamr_rev2 below.
PicoPort. Not gateware. A bare-metal SmartPort device on a Raspberry Pi Pico W, 2026-03-10, with PIO doing the 250 kbps FM layer and .2mg images served from SD. Reads were solid and writes were flaky on a breadboard. The boot-to-RAM idea that led to Block Hamr came out of it. Lives under software/SMARTPORT/.
Block Hamr. ProDOS block device. Boot copies a disk image from flash to SDRAM, the 6502 reads and writes 512-byte blocks through eight registers, and a write-through engine flushes dirty blocks back to flash. Up to 12 MB volumes. The driver fits in the 256-byte slot ROM. Working 2026-03-26, persistence 2026-03-30, Rev 2 port 2026-04-22.
Flash Hamr. SD-card disk system. A PicoRV32 soft core runs FatFS and serves images from a FAT32 card; a Merlin picker on the IIe chooses which images to mount. The first attempt was 4,800 lines of FAT32 in pure Verilog, replaced on 2026-04-09 by the soft core and about 970 lines of C. v8 is Duo Drive, two SmartPort units, D1 boot and D2 data. Rev 1 only, tagged flash-hamr-v8.
smart_hamr_rev2. Liron card rebuild. IWM ASIC emulation written from the IWM spec revision 19 and Wozniak’s patent, verbatim Liron ROM, bridged over GPIO to a FujiNet ESP32. Boots ProDOS from FujiNet with full 10-device SmartPort enumeration using spec-exact constants only. Phases 0 to 4 passed 2026-05-03. Phase 5 (second drive, WRITE and FORMAT) never started.
project_obscurus. SDRAM monitor and the platform everything after it sits on. A byte-addressed SDRAM controller with priority refresh, a register port with a sticky busy bit, 1024 banks of 64 KB, and a $C800 monitor with R, W, B, D and T commands. The SDRAMLIB driver library and SDMTEST swept all 1024 banks on 2026-06-03.
Coprocessor. Arlet Ottens’ verilog-6502 in the ECP5 with its own block RAM, sharing SDRAM with the host through a priority arbiter. Built up in gates: C0 writes SDRAM that the host reads (2026-06-08), C1 a protected resident kernel with live task registration, C2 a cooperative scheduler where two Merlin tasks race and tuning flips the winner, C3 preemptive timer ticks, C-flash a persistent task registry that survives power loss, C4 async skill dispatch with a CALL ABI and CPLIB on the host side, then an SDRAM read window (2026-06-09). BRAM grew from 8 KB to 48 KB in June. Demos: Conway’s Multiverse, eight Life universes on the card viewed from the IIe, and a farm, market and workshop economy that keeps running while the IIe looks in.

b8008_hamr. The core from my Intel 8008 VHDL project, netlist generated at build time by FuseSoC and GHDL, dropped into the card with a bootstrap FSM, 64-deep TTY FIFOs, and a slot ROM that turns PR#4 into a glass terminal on the 8008 monitor. On the Apple side: B8RUN loads objects over the FIFO, B8CMP is the byte-compare acceptance gate, ASM8 is a native 8008 assembler written in 6502, and A8 is an 80-column editor with ASM8 embedded and a load-to-card key. The acceptance test is HELLO8R assembled on the IIe coming out byte-identical to the ASL reference, and it did, 2026-07-08. The build, the bugs and screenshots of the whole edit, assemble, load and run loop are in the log An Intel 8008 in the card, and a whole 8008 toolchain that lives on the Apple IIe.
Decisions
- 2025-12-12: ECP5-85F over the 45K. Same package, and the soft cores that came later used the room.
- 2026-01-29: the expansion connector is one IDC header at the back edge, with power rails and a ground between every signal pair, and there is no SD slot or ESP32 on the board. Expose the minimum and let people extend it. That became the Rev 2 20-pin header and 2x3 power block.
- 2026-03-02: the IWM is written from the patent and the IWM spec. The open-source Yellowstone Verilog is the version its author abandoned, and it was a dead end here.
- 2026-03-26: the SmartPort protocol stack was replaced by a plain register interface for block storage. The IWM emulation was the hard part and a block device did not need it. Block Hamr v2 is the baseline. I do not re-test it or revert to it.
- 2026-03-30: flash persistence lives in its own module. The arbiter stays as it is.
- 2026-04-09: a PicoRV32 running FatFS replaces the pure-RTL FAT32 parser. 4,800 lines of Verilog state machines became about 970 lines of C.
- 2026-04-11: SDHC cards only for Flash Hamr. SDSC cards throw write garbage-collection storms that break persistence and corrupt data.
- 2026-04-21: Rev 1 gateware frozen under
gateware/rev1/at tagrev1. Rev 2 designs are separate ports. - 2026-05-03: Liron emulation is written from the spec and the patent. The spec-pure RTL booted without any of the prior design’s drain delays or flushes, so those were never load-bearing.
- 2026-06-05: no DMA bodge on Rev 2. Bus mastering waits for a Rev 3 respin. The hypervisor moved to write-through shadowing for save and a 6502-driven byte-port copy for restore, and was then parked on its branch when the coprocessor turned out to be the better goal.
- 2026-06-08: a second soft CPU instead of time-slicing the host. Slicing the one 6502 through the hypervisor costs seconds per switch; a soft core gives real concurrency.
- 2026-06-08: the expansion ROM at
$C800is armed by a magic write and disarmed on reset, so the shared expansion bus is never driven by default. - Testbenches cover the SDRAM controller, monitor, write-protect decode, flash and BRAM load paths. 6502 programs are written as self-tests and run on the IIe.
- Never flash without an explicit ask.
makebuilds;prog-flashis a separate decision every time. - Re-check the build graph after any build-affecting change. Stale embeds and stale .bin files shipped to the board several times, so a clean assemble gates every commit.
Open problems
- No DMA. Address transceivers U8, U11 and U13 have DIR tied to +5 V and OE to ground, so they only pass slot to FPGA, and R/W is input-only at the FPGA. The card can pull DMA low and halt the 6502 but cannot then drive an address. Rev 3 needs DIR and OE on those three parts and an R/W output routed to the FPGA. I am not bodging it, and Rev 3 is not scheduled.
- Liron phase 5 (second drive, WRITE_BLOCK, FORMAT) was never started.
- The hypervisor’s trap unit reached 5c-2b (an NMI handler in the
$C800ROM that survives a trashed vector page) and stopped. The hyperkey and the full suspend and resume loop are on branchobscurus-sdram-monitor, unmerged. - Flash Hamr never got a Rev 2 port. It is complete on Rev 1 and there was no reason to move it.
Links
Hardware:
hardware/byte_hamr/kicad/(KiCad schematic and PCB),hardware/byte_hamr/fabrication/Rev 2 pin constraints:
gateware/rev2/constraints/byte_hamr.lpfDesigns:
gateware/rev2/block_hamr/,gateware/rev2/smart_hamr_rev2/,gateware/rev2/project_obscurus/,gateware/rev2/b8008_hamr/6502 and 8008 software:
software/SDM/(SDRAM library, coprocessor skills, farm),software/B8008/(8008 toolchain)8008 core: Intel 8008 VHDL
Reference: Apple IWM Specification rev 19, US Patent 4,742,448, Apple SmartPort Bus Specification, Liron schematic 670-9107
Same core on the network: LiteX 8008 Node
Build thread on VCF: https://forum.vcfed.org/index.php?threads/byte-hamr-fpga-expansion-card-for-apple-iie.1256060/
Earlier thread on Applefritter: https://www.applefritter.com/content/fpga-expansion-card-apple-iie-byte-hamr
FujiNet firmware fork used by Smart Hamr: https://github.com/FujiNetWIFI/fujinet-firmware/compare/master...robertrico:fujinet-firmware:byte_hamr