a2fpga-series — Part 3
The Clock Card That Just Works
The ThunderClock Plus is the only Apple II clock card with a built-in ProDOS driver. Emulating it means implementing a NEC uPD1990AC serial calendar clock in SystemVerilog — and exploiting a USB-C power trick to give the FPGA battery-like time persistence.
Part 3 of the A2FPGA series. Previous parts covered the Videx VideoTerm emulation. This part covers the ThunderClock Plus.
After the Videx VideoTerm implementation — two articles’ worth of MC6845 register state, VRAM bank switching, C8-space ownership, and Pascal boot debugging — the ThunderClock Plus was almost relaxing to implement.
It is a clock card. It keeps time. It has one I/O address. It has a 2KB firmware ROM. The most complex component is the NEC uPD1990AC serial calendar clock chip, which communicates through a 6-bit control register and 1-bit serial data output. By the standards of the Videx implementation, this is simple hardware doing a simple job.
But the ThunderClock Plus has one property that no other Apple II clock card has, and it’s the reason the card dominated the market for a decade: ProDOS finds it automatically.
Why the ThunderClock Is Special
The Apple II had many clock cards. The No-Slot Clock hid in a ROM socket. TimeMaster H.O. offered battery backup. The DClock provided a parallel interface. All of them required you to install a clock driver — a CLOCK file in the ProDOS boot volume, loaded at startup, that told ProDOS how to talk to your particular clock hardware.
The ThunderClock Plus requires none of that. During every ProDOS boot, the kernel scans slots 7 through 1, reading four bytes from each slot’s ROM: offsets 0, 2, 4, and 6. If those bytes are $08, $28, $58, $70, ProDOS recognizes a ThunderClock-compatible card and installs the firmware’s built-in clock driver automatically. The next time ProDOS needs a timestamp for a file operation, it calls the ThunderClock firmware directly through the standard clock interface.
Those four signature bytes are present in the ThunderClock Plus firmware ROM at exactly those offsets. Emulating them correctly is the entire ProDOS integration requirement. Everything else — the actual time reading, the BCD formatting, the call protocol — is handled by the firmware itself, which runs on the real 6502 in the Apple II.
This is worth sitting with for a moment. On the Apple ][+ test machine, the system has a 6502 CPU, and the ThunderClock firmware runs on that CPU — not on the FPGA. The FPGA emulates the hardware that the firmware talks to: the I/O register and the uPD1990AC clock chip behind it. The 6502 does the rest.
The uPD1990AC
The NEC uPD1990AC is a serial I/O calendar clock LSI from the early 1980s. It maintains a 40-bit BCD time register across six fields: seconds, minutes, hours, day-of-month, day-of-week, and month. It communicates through five signals:
- DATA IN — serial data input (1 bit, shifted in on clock edges)
- SHIFT CLOCK — clock for the serial shift register
- STROBE — latches shift register contents into the time counter
- COMMAND — 3-bit command code selecting the operation mode
- DATA OUT — serial data output (1 bit, shifted out)
The command modes cover register hold (freeze display), shift (read/write the shift register), time set (transfer shift register to time counter), time read (transfer time counter to shift register), and four timer pulse rates (64, 256, 2048, or 4096 Hz for interrupt generation).
The FPGA implementation models all seven command modes with a state machine driven by the SHIFT CLOCK and STROBE signals. The 40-bit BCD time counter increments in real time using a prescaler from the FPGA’s 54MHz logic clock: 54,000,000 cycles per second, divided down to produce a 1Hz tick that increments the seconds field, which carries into minutes, hours, and so on. BCD incrementing requires handling the 0-9 rollover within each nibble and carrying correctly across fields.
// Prescaler: 54 MHz → 1 Hz
localparam PRESCALER_MAX = 26'd54_000_000 - 1;
always @(posedge clk_logic or negedge device_reset_n) begin
if (!device_reset_n) begin
prescaler <= 26'd0;
tick_1hz <= 1'b0;
end else begin
if (prescaler == PRESCALER_MAX) begin
prescaler <= 26'd0;
tick_1hz <= 1'b1;
end else begin
prescaler <= prescaler + 1'b1;
tick_1hz <= 1'b0;
end
end
end
The BCD increment cascades through the time fields in the standard way, with each field having its own rollover value: seconds at 60, minutes at 60, hours at 24, and so on.
Time Persistence Across Resets
One of the subtler requirements for a clock card emulation is reset behavior. On real hardware, the ThunderClock Plus has a battery that keeps the uPD1990AC powered when the Apple II is off. The clock keeps running through power cycles, soft resets (Ctrl-Reset), and system crashes.
On the FPGA, there is no battery — but there are two different kinds of reset. The FPGA has a device-only reset that fires only on power-on (when the FPGA itself first receives power), and the Apple II system sends a system reset signal through the bus on every Ctrl-Reset and many other conditions.
The uPD1990AC emulation uses the device-only reset, not the system reset. This means:
- Apple II soft resets (
Ctrl-Reset,PR#6) do not affect the clock - Apple II hard power cycles do not affect the clock, as long as the FPGA remains powered
- Only FPGA power-on (the FPGA itself loses power) resets the clock to midnight, January 1
On power-on, the emulated clock initializes to midnight January 1 (Sunday) — exactly like a real ThunderClock Plus with dead batteries. You set the time once with the ThunderClock utility, and the clock runs from there.
The USB-C Persistence Trick
The Tang Nano 20K has a USB-C connector that accepts power independently from the Apple II’s slot power. If you connect a USB-C cable from an always-on device — a Raspberry Pi, a USB power adapter, a power bank — to the A2FPGA’s USB-C port, the FPGA stays powered even when the Apple II is switched off.
This means the FPGA’s device-only reset never fires during normal use. The clock runs continuously. When you turn off the Apple II at night and back on in the morning, the clock has been counting the whole time. The behavior becomes indistinguishable from a battery-backed ThunderClock Plus.
You set the time once after first connecting USB-C power. After that, the clock keeps time through every Apple II shutdown, startup, reset, and crash for as long as the USB-C supply remains connected. Disconnecting the USB-C while the Apple II is also off loses the time setting — but reconnecting and booting restores the ability to set time with the standard ThunderClock utility, after which the clock runs again indefinitely.
The Bus Interface
The ThunderClock card exposes a single I/O address per slot: $C0n0 where n is the slot number (1 for slot 1, giving $C090). Addresses $C0n1–$C0nF mirror $C0n0 on reads and are ignored on writes.
A write to $C090 drives the five uPD1990AC control signals: DATA IN (bit 0), SHIFT CLOCK (bit 1), STROBE (bit 2), and COMMAND (bits 5:3). The upper bits are unused.
A read from $C090 returns the DATA OUT signal in bit 0 and the IRQ status in bit 7. The firmware uses this to shift the 40-bit BCD time register out serially, one bit at a time: write a SHIFT command, toggle SHIFT CLOCK, read DATA OUT, repeat 40 times.
The slot ROM at $C1xx and expansion ROM at $C800–$CFFF serve the 2KB firmware ROM, with the C8-space ownership protocol following the same pattern as the Videx card.
ProDOS in Action
After flashing the bitstream with ThunderClock emulation enabled, the result:

Slot 1 now shows “ThunderClock Plus Card” where it previously showed “No Firmware Card Detected.” This is CardCat reading the ProDOS signature bytes from $C100 — the same bytes ProDOS reads during boot. If CardCat can find the ThunderClock, ProDOS can too.
On the next ProDOS boot, file timestamps appear automatically on every created or modified file. No driver installation. No configuration. The ThunderClock firmware is already in the ROM, and ProDOS installs it during its own boot sequence the moment it finds the signature bytes.
The total implementation cost: 1 BSRAM block for the firmware ROM, approximately 250 LUTs for the serial state machine and BCD counter, and 160 registers. The smallest card in the build by a significant margin — but the one that completes the daily usability story. An Apple II with a clock card is a different machine from one without.