The debug card: theory of operation¶
Status: DESCRIBES THE NETLIST AS BUILT (2026-10-30),
generators/card_debug.py (every chip, net and GAL equation comes from
there). The card's purpose and decisions are in the debug
card; the bus cycle and slot 0 in the bus. What
the gate-level simulation (generators/sim_debug.py) verifies is §14;
what is unclear, §15. D48, D50, D64, D73, D76. Brought up to D100 and D101
(2026-11-11): a status display, two TIL311s written at 4D; the mode
switch turned so its lever points out past the front edge; the capture
SRAMs written in the sample clock's high half (the write race gone);
CRESN clearing GO, ARM, STEP and the two state machines; -BREQ0
released at once in LISTEN; DRIVE reaching -BGNT3–10, -FAST and
-IRQ0–7; the buffer's wrap readable.
1. What the card does¶
The debug card is the machine's bus tester. It sits in slot 0, which every backplane signal reaches, in one of two modes chosen by a switch at its front edge, never both at once (D64):
- LISTEN: a logic analyzer. It samples 167 lines (the bus, the system lines, J3, the CPU card's local link, and the two lines that say which of those cards are in) into 32 K samples, with a trigger. None of its bus drivers can turn on.
- DRIVE: a bus master. With the CPU and MMU / data cards in, it
borrows the bus by DMA, one cycle at a time, and can pull any of
-IRQ0–7low. Alone (the CPU card pulled) it makesCLKand-CLKand may drive the bus cycle,-RES,-BREQ3–10,-BGNT3–10,-FASTand the CPU card's side of J3. Never against a card that is in (D102): with a CPU card in, "alone" does nothing; with an MMU / data card in, that card's lines are left to it (§9).
In either mode it can clock the CPU card over its own two bus lines,
XCLK and -XCLKEN (D76). A Raspberry Pi Pico 2 is the host link: USB
to the Mac, an 8-bit local bus to the registers. Its firmware, USB
command set and Mac-side tools are not written yet: this chapter gives
the register interface, and §12 walks a host through it.
2. Slot 0¶
Slot 0 is an eleventh backplane position beside slot 1 (D64). It carries
169 signals (p32bus.busnet()): J1's 70 (the bus cycle); J2's 35 (CLK,
-CLK, -RES, PWROK, -LOCK, -IRQ0–7, -IACK, -FAST, XCLK,
-XCLKEN, every requester's -BREQ3–10 / -BGNT3–10 as the arbiter in
slot 2 sees them, and the card's own pair); J3's 64 (LR0–31, the CPU
card's 24 control lines, FAULT, FC0–3, STALL, and since D102
-CPUIN and -MMUIN). The card samples 167: all but XCLK and
-XCLKEN, which are its own outputs.
-CPUIN and -MMUIN (J3 B28, B30; D102) say which cards are in. They
are two of the J3 pins that were spare, which the backplane joins between
slots 0, 1 and 2 (D99). The CPU card ties its -CPUIN pin straight to its
ground plane, the MMU / data card its -MMUIN pin: no part, nothing to
fit or to forget. On the debug card each has a 10k pull-up (R6, R7), so a
line is high only when that card is out of its slot. §9 has what they do.
The card's own pair, its -BREQ / -BGNT pins (J2 A16, A17), is in
slot 0 the backplane's -BREQ0 / -BGNT0: the first priority of GAL ARB,
the arbiter on the MMU / data card (mmu-card-theory §9). This chapter uses
the backplane's names.
3. The host link¶
The Pico (A1) sits at the front edge, its USB port facing out (D48). It runs from the backplane's 5 V through a 1N5817 Schottky into its VSYS; its 3.3 V output supplies the 74LVC245 and two pull-ups.
| Pico | Net | What |
|---|---|---|
| GP0–7 | PD0–7 | data, through a 74LVC245 to the card's 5 V XD0–7 |
| GP8–14 | XA0–6 |
the register address |
| GP15, GP16 | -XWR, -XRD |
the write and read strobes |
| GP17 | XDIR |
high: the Pico drives XD; low: XD drives the Pico |
| GP18 | CRESN |
low: the control registers held clear |
The 245 is always enabled: XDIR alone decides who drives XD. The
address and strobes go straight to the decoders. Until the firmware
runs, 10k pull-ups hold -XWR and -XRD high and a 10k pull-down holds
CRESN low, so the control registers, the GO, ARM and STEP flip-flops and
the two state machines stay clear whichever way the mode switch stands
(§5). A write: address and data out,
XDIR high, -XWR low, then high; registers take XD at the strobe's
rising edge, and the GO, ARM and STEP flip-flops are preset while it is
low. A read: XDIR low, -XRD low; a 74HCT541 drives XD. sim_debug's
Pico holds each strobe low for two periods of the card's 24 MHz
oscillator.
4. The local bus decode¶
GAL DBADR decodes XA6–XA3 and the strobes into seven decoder
enables: SWLON / SWHIN (a write with XA6, XA5 low; XA4 picks the
74HCT154 for slices 0–15 or 16–21), SRLON / SRHIN (the same for a
read), CW0N / CW1N (a write with XA6 high; XA3 picks the 74HCT138
for 40–47 or 48–4E) and CRN (a read with XA6 high: the 74HCT138
for 40–42). The 154s decode XA3–XA0, the 138s XA2–XA0. The map
(every local-bus address and value here is hex):
XA |
A write | A read |
|---|---|---|
00–12 |
slice 0–18's drive register (§7) | slice 0–18 (§7) |
13–15 |
nothing (no drive register) | slice 19–21 |
40 |
CTRL0 | status |
41 |
CTRL1 | the capture address CA, bits 7–0 |
42 |
the post-trigger count, bits 7–0 | CA bits 14–8; bit 7 is CA15: the buffer has wrapped (D101) |
43 |
the post-trigger count, bits 15–8 | — |
44 |
GO: one DMA cycle | — |
45 |
ARM: a capture | — |
46 |
STEP: one CLK period alone, or one XCLK pulse |
— |
47 |
CSTEP: CA + 1 | — |
48, 49 |
the trigger setup address TS, bits 7–0, 14–8 | as 40, 41 |
4A, 4B |
trigger RAM A, B at TS | 4A as 42 |
4C |
CAPCLR: CA = 0 | — |
4D |
the status display (D100): two hex digits, bits 7–4 and 3–0 | — |
4E |
the interrupt lines (D101): bit n = 1 pulls -IRQn low (§9) |
— |
GO, ARM, STEP, CSTEP and CAPCLR act by their strobe; their data is not used.
The status display (D100; Ken: for status information, always visible,
since the debug card is the front card of the machine). Two TIL311
hexadecimal displays, U143 (the high digit, XD7–4) and U144 (the low one,
XD3–0), stand at the front edge just below the LEDs, on 0.45 in centres.
A TIL311 holds its own 4-bit latch, decoder and LED drivers: its latch
follows its data inputs while its strobe is low and holds them when it is
high. The strobe of both is DISPN, the 48–4F decoder's output for 4D,
so a write to 4D shows its byte and the digits keep it; no register chip
is needed. Their blanking inputs are tied low and their decimal points are
not connected. They are never cleared: from power-on until the Pico's
firmware first writes 4D they show what their latches woke up with. What
the byte means is the firmware's to define. Each draws about 105 mA
(180 mA at most), 0.2 A of the card's 3.2 A. The data must be steady 50 ns
before the write ends and 40 ns after it (TI SODS001D): the firmware's
concern, as for the other registers.
Above 3F the writes ignore XA5–XA4 and the reads XA5–XA3, so the
registers repeat; nothing answers at 16–3F.
5. The control and status registers¶
Six 74HCT273s hold CTRL0, CTRL1, the post-trigger count (POSTL, POSTH) and
TS (TSAL, TSAH). CRESN low clears them. They cannot be read back, so
the host keeps copies.
| Bit | CTRL0 (40) |
CTRL1 (41) |
|---|---|---|
| 0 | GD: alone, D0–31's drive registers on | ODLOCK: -LOCK low |
| 1 | GBUS: alone, the bus cycle's | CLKRUN: DBCLK runs (CLK alone; XCLK with XCLKEN) |
| 2 | GSYS: alone, -RES, -BREQ3–10, -FAST and the grants |
SCLKSEL: the sample clock is 12 MHz, not CLK |
| 3 | GLR: alone, LR0–31 | SETUP: the trigger RAMs being written; no trigger |
| 4 | GJ3: alone, the CPU card's J3 control lines | TNOW: trigger now |
| 5 | ALONE: the card drives CLK, -CLK; the groups may drive; GO needs no grant |
LIVE: the slices read the latches, not the SRAMs |
| 6 | ODACK: -ACK low |
DMAWR: a DMA cycle drives D (a write) |
| 7 | ODWAIT: -WAIT low |
XCLKEN: -XCLKEN low, the CPU card on XCLK (D76) |
ALONE and the five group bits are what the host asks for. GAL DBDRV gives a group its drivers only if the cards whose lines they are are out (§9, D102). ODACK, ODWAIT and ODLOCK act only in DRIVE. Three flip-flops are set by the host and cleared by the card: GOQ (74HCT74; GAL DBSEQ clears it at SNAP), ARMQ (74HCT74; GAL DBCAP, once the capture runs) and STEPQ (74ACT74, D73; GAL DBCLK, when the step is done).
The reset (D101). CRESN low clears, besides the six registers: GOQ,
ARMQ and STEPQ (each GAL's clear line takes CRESN), GAL DBSEQ's REQ, CYC
and SNAP and GAL DBCAP's RUN, POST and DONE (the 22V10s' asynchronous
reset), and the interrupt register (§9). So with no firmware running, or
while it holds the card in reset, no cycle can start and no line is
pulled, whichever way the switch stands. Not cleared, and harmless until
the host loads them: the drive registers (their groups are off), the
trigger RAMs and the status display's latches.
Status (40) bit |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| Signal | DRIVE | -BGNT0 |
GOQ | ACT | DONE | ARMQ | TRIG | SNAP |
DRIVE: the switch at DRIVE. -BGNT0 low: slot 0 granted. GOQ: a DMA cycle
not yet done. ACT: a capture running. DONE: it has finished. ARMQ: armed,
not yet running. TRIG: the trigger condition now. SNAP: the clock after a
DMA cycle.
6. LISTEN and DRIVE¶
The mode switch S1 (E-Switch's EG1224, a right-angle SPDT slide switch
at the front edge: Ken, D101) is turned so that its lever points out past
the card's edge (D100): about 4 mm of it stands beyond the edge. It is labelled MODE, with
LISTEN at one end of the lever's travel and DRIVE at the other. It ties the
net DRIVE to 5 V (DRIVE) or to ground. DRIVE
gates every driver: GAL DBDRV makes every drive register's output
enable and CLK's, none without DRIVE, and none against a card that is
in its slot (§9); a 74HCT08 passes ODACK,
ODWAIT and ODLOCK on only with DRIVE, and holds the interrupt register
cleared without it; GAL DBSEQ asks for the bus only with it, and lets
-BREQ0 go the moment it is gone (§10, D101); and GAL DBCAP captures
only without it (§8). So LISTEN
captures and drives nothing; DRIVE drives, and keeps only its DMA cycles'
snapshots. XCLK and -XCLKEN, the card's own lines, are driven in both
modes (D76).
A 74HC05 lights the mode LEDs through 470 Ω each: DRIVE (red) from
DRIVE, LISTEN (green) from DBDRV's LISTEN (DRIVE inverted). The
green POWER LED is every card's (D76).
7. The slices¶
The 167 lines are cut into 22 slices of eight (spare inputs
grounded). Each slice has a 74ACT574 sample latch clocked by the
sample clock SCLK, a CY7C199 capture SRAM (32 K × 8, 15 ns) on the
same 8-bit bus, addressed by CA14–0, and a 74HCT541 from that bus onto
XD for the host's reads. Slices 0–18 also have a 74HCT574 drive
register, written from XD at the slice's address and driving its lines
while its group is enabled.
| Slice | Its lines, bit 0 first | Group |
|---|---|---|
| 0–3 | D0–7, D8–15, D16–23, D24–31 | D |
| 4–6 | A2–9, A10–17, A18–25 | BUS |
| 7 | A26–31, BE0, BE1 | BUS |
| 8 | BE2, BE3, -MRD, -MWR, -IACK |
BUS |
| 9 | -RES, -BREQ3–9 |
SYS |
| 10 | -BREQ10, CLK, -CLK, -FAST |
SYS (not CLK, -CLK) |
| 11 | -BGNT3–10 |
GNT: the SYS group's bit, its own enable (§9) |
| 12–15 | LR0–7, LR8–15, LR16–23, LR24–31 | LR |
| 16 | RSRC0–3, RDST0–2, MEM0 | J3 |
| 17 | MEM1, MEM2, SIZE0, SIZE1, SIGNED, SUPER, TLBW, CRSEL0 | J3 |
| 18 | CRSEL1, CRSEL2, -WSTB, LOCKREQ, PCINC, MARPC, MARINC, CCLK |
J3 |
| 19 | PWROK, -LOCK, -IRQ0–5 |
— |
| 20 | -IRQ6, -IRQ7, -BREQ0, -BGNT0, -ACK, -WAIT, FAULT, FC0 |
— |
| 21 | FC1–3, STALL, -CPUIN, -MMUIN |
— |
A line's bit is its place in the row: in slice 8 -IACK is bit 4, in
slice 20 -ACK is bit 4. (D101 moved the grants into the SYS group and
added -FAST, so the slices from 11 on are one higher than they were.
D102 gave the grants slice 11 to themselves, -FAST moving to slice 10,
and put -CPUIN and -MMUIN in slice 21: bits 4 and 5, a 0 for a card
that is in.)
Slices 19–21 are listened to only; -ACK, -WAIT, -LOCK, -BREQ0 and
-IRQ0–7 have open-drain drivers of their own (§9), and CLK, -CLK come
from GAL DBCLK. A slice's bus is driven by its
latch while LIVE is set, a capture runs or its last write is still to
come (WQ, §8), or during SNAP; otherwise by its SRAM, showing the sample at
CA (DBCAP's LATOEN, SROEN).
8. LISTEN: the capture¶
The sample clock. A 74ACT157 makes SCLK from CLK (SCLKSEL = 0) or
T12, GAL DBCLK's register toggling at every edge of the card's 24 MHz
oscillator: 12 MHz (D73). At CLK's rise a sample is the state at a bus
cycle's end (CCLK rises at the same edge); 32 K are about 11 ms at 3 MHz
(debug-card.md §7). At 12 MHz there are four per microcycle, taken
asynchronously like a logic analyzer's; 32 K are about 2.7 ms (D73).
The write (D101). A sample is latched at SCLK's rise and written in
the high half that follows: a 74ACT00 makes the SRAMs' -WE = NAND
(WEX, SCLK). So the write ends at SCLK's fall, with the data steady
since just after the rise and for half a period more, until the latches
next change. (Before D101 the write was in the low half and ended with the
next rise, two gate delays after the edge that changed the latches: a
race the SRAMs' 9 ns of data set-up lost, §15.) Which high halves write is
WEX, from GAL DBCAP and WQ. WQ is DBCAP's SWEN taken by a 74ACT74
at SCLK's fall (its clock is SCLK through a 74ACT04), so it changes
only while SCLK is low and -WE cannot glitch:
- listening, WEX = WQ: a sample is written when the capture was active
half a period earlier. The first sample written is the one latched at
the edge after RUN begins, the last the one latched at the edge that
ends the capture;
- in DRIVE, WEX = SNAP and not WQ: the one high half after the edge that
ended a DMA cycle, on the sample that edge latched (§10).
The capture address. Four 74F161s count CA; bits 14–0 address the
SRAMs, so the buffer is a circle of 32 768 samples, and bit 15, read as
bit 7 of 42, says it has gone round (D101). The counter's clock is
-WE's own rising edge, two gates later (a 74ACT00 and a 74ACT04): CA
moves on by one after every sample written, never before the write has
ended; or it is a CSTEP's end (a 74HCT32 lets CSTEP through only when no
capture runs). CAPCLR clears CA at once (the 74F161's clear is
asynchronous); nothing else sets it.
GAL DBCAP, clocked by SCLK, runs the capture:
1. ARM sets ARMQ. While it is set and nothing runs, PLDN has the
post-trigger counter load.
2. At the next sample edge, in LISTEN: RUN (ACT). ARMCLRN clears
ARMQ; DONE clears. At SCLK's fall WQ sets.
3. At every later sample edge the latches take the lines, and in the high
half the SRAMs write them at CA, which then steps by one.
4. At the sample edge that finds TRIG high: POST. The post-trigger
counter counts at each edge while POST (its enable is DBCAP's POST pin).
5. At a sample edge in POST that finds its carry PDONE high: DONE,
until the next ARM. That edge's sample is still written (WQ), and CA
then points one past the last address written.
So with a post-trigger count of n, the sample the trigger's edge latched
is at CA − n − 1, and n samples follow it. RUN and POST need LISTEN:
moving the switch to DRIVE abandons a capture without DONE. CRESN low
clears RUN, POST and DONE (§5). In DRIVE, the one write is SNAP's (§10).
The post-trigger count. Four more 74F161s on SCLK, loaded from
POSTH:POSTL; PDONE, their carry, is high at FFFF. Written as
65 536 − n, the count brings DONE n sample edges after the edge that saw
the trigger: FFFF is n = 1, FF00 is 256. A count beyond the buffer
overwrites the trigger's own sample.
The trigger. Two more CY7C199s are the trigger RAMs: A is
addressed by A16–A2, B by A31–A17, and bit i of each belongs to pattern
i, 0–7. Pattern i matches when A's bit i at the cycle's A16–A2 and B's
bit i at its A31–A17 are both 1 (two 74HCT08s make M0–M7). A pattern is
thus any set of low halves with any set of high halves: one word, a mask
(a don't-care bit set at both values), a range within one half.
GAL DBTRIG makes TRIG: never during SETUP; otherwise TNOW, or a bus
cycle (-MRD, -MWR or -IACK low) whose address any pattern matches.
Reads and writes are alike to it.
Setting the trigger up (SETUP = 1): eight 74HCT157s switch both RAMs'
address inputs from the bus to TS14–0; the RAMs' outputs turn off (-OE
is SETUP); two 74HCT541s, enabled by DBTRIG's SETUPN, put XD on their
data pins; a write to 4A or 4B strobes RAM A's or B's -WE. TS is a
register, not a counter. Nothing clears the RAMs: at power-on they hold
anything (the simulated ones read 0).
Reading back. After DONE, 41 and 42 give the final CA. For each
sample the host reads the slices it wants (LIVE off), then CSTEPs; once
the buffer has wrapped, starting at the final CA gives the samples oldest
first. Read-back and trigger setup happen only while nothing is captured
(timing.md §3); during a capture a slice read shows the latest sample.
9. DRIVE: the drivers¶
GAL DBDRV makes the output enables, each needing DRIVE. Two of its
inputs are the backplane's -CPUIN and -MMUIN (§2), and it writes
"alone" in two strengths (D102):
- alone =
DRIVEand ALONE and-CPUINhigh: the host asks, and no CPU card is in; - the bus is the card's = alone and
-MMUINhigh: no MMU / data card either.
| Group | Slices | Its enable | On when |
|---|---|---|---|
| D | 0–3 | DOEN |
the bus is the card's, and GD; or a DMA cycle with DMAWR |
| BUS | 4–8 | BUSOEN |
the bus is the card's, and GBUS; or a DMA cycle |
| SYS | 9–10 | SYSOEN |
alone and GSYS |
| GNT | 11 | GNTOEN |
the bus is the card's, and GSYS |
| LR, J3 | 12–15, 16–18 | LROEN, J3OEN |
alone and GLR, GJ3 |
CLK, -CLK |
(GAL DBCLK) | CLKOE |
alone |
"A DMA cycle" is GAL DBSEQ's BUSEN (§10), and it counts in two cases
only: ALONE clear, when the cycle began on the arbiter's grant; or the bus
the card's. The drive registers are not cleared at power-on: the host
loads them before enabling their group.
Why each card takes what it takes. The CPU card drives CLK, -CLK
and -RES and its side of the local link at all times, so with it in
there is nothing "alone" could drive without a second driver on a line:
ALONE counts for nothing, the clock included. The MMU / data card is the
CPU's way onto the bus: its address drivers and strobes are on the bus
whenever no grant is out (mmu-card-theory §9), it drives D in a write,
and its arbiter makes every grant. So with it in the card leaves D, the
bus cycle's lines and the grants alone, and a GO that no arbiter granted
drives nothing (GAL DBSEQ still runs its cycle, and GO clears). What is
left is what testing that card needs: the clock, -RES, the other
masters' -BREQ3–10 to its arbiter, and the CPU card's side of LR and J3
(debug-card.md §1).
Before D102 nothing but the host's ALONE bit stood between the card and a
CPU card that was in: a wrong command, or a firmware fault, put two
drivers on CLK. The lines are tied to ground on the cards themselves, so
the check needs no firmware and cannot be left out of a build. A broken
line reads as "card out": it is a guard against a mistake at the keyboard,
not against a faulty backplane.
The SYS group also has -FAST, and the grants ride on its bit (D101):
with the MMU / data card out too, nothing else drives the grants, and the
card can hand a device's DMA engine the bus (a disk card's, D75) and watch
what it does; -FAST low sets the I/O card's timer for the 4 MHz clock
(D74). -FAST is a jumper to ground on the CPU card, which is out when
the card is alone.
The open-drain lines come from 74HC05s: -ACK, -WAIT and -LOCK
from ODACK, ODWAIT and ODLOCK (through the 74HCT08: only in DRIVE), and
-BREQ0 from GAL DBSEQ.
The interrupt lines (D101). A seventh 74HCT273, written at 4E, has a
bit for each of -IRQ0–7: a 1 pulls that line low through a 74HC05 (two
of them), as a device would; the backplane's 2.2k pull-ups hold the rest
high. It needs DRIVE but not ALONE, so it works beside a running CPU: the
way to test the CPU card's interrupt logic, or a handler, without the
device. The register's clear is CRESN AND DRIVE (the 74HCT08's fourth
gate), so it is empty after a reset and whenever the switch is at
LISTEN: in LISTEN no line is pulled, by wiring, and back in DRIVE the
lines stay released until 4E is written again.
10. The DMA cycle: GAL DBSEQ¶
GAL DBSEQ, clocked by CLK, runs one bus cycle per GO, from GOQ,
-BGNT0, -WAIT, ALONE and DRIVE:
- REQ (DRIVE, not alone): set at a CLK edge when GO is pending and
nothing is under way; held until the grant;
- CYC, the cycle: set at the edge that finds REQ and the grant (alone:
at the first edge after GO, with no request); held while -WAIT is low;
- SNAP, the clock after: set at the edge that ends CYC.
Its outputs: BUSEN = CYC; BREQOD = DRIVE and (REQ or CYC) (-BREQ0
low: it goes the moment the switch leaves DRIVE, not at the next CLK,
D101); GOCLRN = not SNAP, and CRESN (GO cleared). CRESN low clears
REQ, CYC and SNAP. It does not look at -ACK.
A DMA cycle, edge by edge (the CPU, MMU / data and memory cards in, no wait; sim_debug's dma case runs it):
CLK edge |
What happens |
|---|---|
| (any time) | the host writes GO: GOQ (status bit 2) |
| 1 | REQ: -BREQ0 low |
| 2 | the arbiter, the bus free, grants: -BGNT0 low (bit 1); the MMU / data card's drivers are off while the grant is out (mmu-card-theory §9) |
| 3 | CYC: the card drives A2–31, BE0–3 and the strobe from its registers, and D for a write |
| 4 | the cycle ends (a slave's -WAIT would hold it): a write is taken; the latches sample the lines; SNAP: GO clears, -BREQ0 released, drivers off |
| 5 | SNAP ends; the arbiter drops -BGNT0 |
GO clears three clocks after edge 1: three to four clocks from the host's
GO, about 1–1.3 µs at 3 MHz. Another master or a held -LOCK delays the
grant; the CPU is held (STALL) only if it wants the bus meanwhile
(bus.md).
SNAP keeps the result (D101): in the high half that opens it, the
SRAMs write what the latches took at the edge that ended the cycle, at CA,
which then moves on by one, so a run of DMA cycles leaves its snapshots at
consecutive addresses. During SNAP the slices show the latches; after it,
the SRAMs (at the new CA: CAPCLR before the cycle and again after it puts
the snapshot under the slices). The word read is in slices 0–3, -ACK in
slice 20 bit 4 (0: a card answered). The snapshot is the cycle's end only
with the sample clock at CLK. sim_debug's dma case reads one back.
11. The clock: GAL DBCLK¶
CLK alone. GAL DBCLK is clocked by the card's 24 MHz oscillator.
Its phase counter, P2–P0, counts the oscillator's edges
while CLKRUN or STEPQ is set. With CLKOE (DBDRV: DRIVE and ALONE) it
drives CLK high in phases 0–3 and -CLK in 4–7: the oscillator divided
by eight, 3 MHz, as the CPU card makes it (cpu-card.md §1).
STEP presets STEPQ; the counter runs until phase 3, where STEPCLRN
clears STEPQ. From phase 3 a STEP is one whole period: CLK falls at
phase 4, rises at phase 0, and stands high at phase 3. The first STEP
after power-on only takes the counter from 0 to 3, with no rising edge
(sim_debug's alone case steps once first). At phase 3 STEPCLRN goes low
as soon as STEPQ is set, so the host's strobe, which holds the preset,
must span an oscillator edge (the simulation's spans two).
XCLK (D76). -XCLKEN is XCLKEN inverted; low, it makes the CPU
card's GAL CKSEL take XCLK as its oscillator, ahead of that card's CLOCK
switch and oscillators (cpu-card.md §1). XCLK is DBCLK's register XCK:
with XCLKEN and CLKRUN it toggles at every oscillator edge (12 MHz, a
1.5 MHz machine); with XCLKEN and a STEP it is high for one oscillator
period, one edge for the CPU card, one of its eight phases (XDN marks the
pulse given while the host's strobe still holds STEPQ); without XCLKEN it
stays low. CRESN low clears XCLKEN, so with no firmware running the CPU
card keeps its own oscillator. Change XCLKEN with RESET held (D76):
CKSEL is a plain multiplexer, and a change mid-phase can cut a phase short.
T12 toggles at every oscillator edge, whatever else is set: the 12 MHz sample clock.
12. Using it¶
There is no firmware yet: each step below is one local-bus write
(XA ← value) or read. Sequences marked tested are what sim_debug.py's
Pico script does in make test; the rest follow from the netlist.
Start-up. -XWR, -XRD high, XDIR low, GP0–7 inputs; then raise
CRESN (GP18). Every control register starts at 0.
(a) A capture with a trigger. The switch at LISTEN. Trigger on any bus
cycle at the word 0x0018_0000 (pattern 0) and keep 256 samples from it:
1. 41 ← 08 (SETUP).
2. For t = 0000 to 7FFF: 48 ← t's bits 7–0, 49 ← its bits 14–8
(when they change), 4A ← RAM A's byte, 4B ← RAM B's. Here A's byte
is 01 at t = 0000 (the word's A16–A2), B's 01 at t = 000C (its
A31–A17), and both 00 elsewhere.
3. 41 ← 00 (SETUP off; the sample clock CLK, or 04 for 12 MHz).
4. 42 ← 00, 43 ← FF (65 536 − 256). 4C (CA = 0). 45 (ARM).
5. Read 40 until bit 4 (DONE). Without a trigger: 41 ← 10 (TNOW),
wait for DONE, 41 ← 00.
6. Read 41, 42 (the final CA); 4C; then for each address read the
slices wanted among 00–15 and write 47 (CSTEP).
By §8 the trigger's sample lies 257 addresses before the final CA (CA − n
− 1), with the 256 after it. Tested without the trigger RAMs:
sim_debug's listen case does steps 3–6 with the count FFFF, ending by
TNOW after HALT and reading samples 0 to CA − 1.
(b) A write and a read as bus master. The switch at DRIVE, CTRL0 =
00, the CPU and MMU / data cards in. The word 5A5A1234 to
0x0018_0000 by DMA (tested: sim_debug's dma case):
1. 41 ← 40 (DMAWR; the sample clock CLK, LIVE off).
2. 00–03 ← 34 12 5A 5A (D); 04–07 ← 00 00 06 C0 (A2–A31, BE0,
BE1); 08 ← 17 (BE2, BE3; -MRD 1, -MWR 0, -IACK 1).
3. 44 (GO); read 40 until bit 2 (GOQ) is 0.
Reading it back by DMA (tested: the dma case, after the program has
halted): 41 ← 00; 4C (CA = 0); 04–07 as before, 08 ← 1B
(-MRD 0, -MWR 1); 44; read 40 until bit 2 is 0; 4C again (the
snapshot is at 0, CA now 1); read 00–03 (the word) and 14 (bit 4:
-ACK).
Alone, with only a memory card besides, C0FFEE42 to 0x0010_0040 and
back (tested: sim_debug's alone case):
1. 40 ← 20 (ALONE: the card drives CLK); 46 (STEP) once.
2. 00–03 ← 42 EE FF C0; 04–08 ← 10 00 04 C0 17; 09 ← FF,
0A ← 09, 0B ← FF (-RES, -BREQ3–10, -FAST and -BGNT3–10
high). 40 ← 27 (GD, GBUS, GSYS,
ALONE) puts the write on the bus; 46 gives it one CLK period (the
memory card writes while CLK is low, mem-card-theory §5); 40 ← 20.
3. 41 ← 20 (LIVE); 08 ← 1B; 40 ← 26 (GBUS, GSYS, ALONE); 46.
The latches took D at CLK's rise and the clock stands still: read
00–03.
(d) An interrupt by hand (tested as far as the lines: the alone
case). The switch at DRIVE: 4E ← 04 pulls -IRQ2 low, 4E ← 00
lets it go. Moving the switch to LISTEN lets every line go at once.
(e) Which cards are in (D102; tested: the alone and listen cases).
41 ← 20 (LIVE) and a CLK edge, then read 15 (slice 21): bit 4 is
-CPUIN, bit 5 -MMUIN, a 0 for a card that is in. Every captured sample
has them too. A host should read them before it sets ALONE, and tell its
user when a card that is in makes a command do nothing: the card itself
refuses silently.
(c) Stepping the machine's clock. The CPU card in, the switch either
way (tested: sim_debug's xclk case, in LISTEN):
1. Holding the CPU card's RESET, 41 ← 80 (XCLKEN): its clock stops.
Release RESET.
2. 46 (STEP): one XCLK pulse, one phase of eight, nothing moving
between. Eight STEPs are one microcycle, one bus clock.
3. 41 ← 82 (XCLKEN, CLKRUN) runs the machine at 1.5 MHz; 80 stops it.
4. Back to the CPU card's oscillator: hold RESET, 41 ← 00.
To watch it (not tested): arm a capture as in (a), keeping XCLKEN in every
CTRL1 write: one sample per eight STEPs, and slice reads show the latest.
Or 41 ← A4 (XCLKEN, LIVE, SCLKSEL): the latches follow the lines at
12 MHz, so between steps the slices show them as they stand.
13. Timing¶
The timing pass (D71, D73; timing.md §1) times the card alone in its
12 MHz mode: every path meets the oscillator's 41.7 ns, at 41.0 ns worst
case (26.5 typical). It takes the sample latches as asynchronous, leaves
the read-back and the trigger setup untimed (only while stopped) and
checks no hold times (timing.md §3, §5); the card is also timed in the
whole machine at 3 MHz. The local bus is not timed: nothing yet specifies
the host's strobe widths or read access time. -BREQ0, released at SNAP,
rises through its 10k pull-up in about 255 ns (timing.md §4), before the
arbiter's next look.
The write, by hand (D101; the pass checks set-up, not the order of
edges). -WE falls a 74ACT00's delay after SCLK rises and rises one
after it falls. The data: the 74ACT574s' outputs are steady 10.5 ns after
the rise at most, 31 ns before -WE rises in the 12 MHz mode (the SRAMs
want 9), and stay until the next rise, half a period after it. The
address: CA changes two gates and a 74F161 after -WE has risen, by
construction, and is steady 9 ns or more before -WE next falls at
12 MHz. WQ and WEX change only in SCLK's low half, 13 ns or more
before it ends at 12 MHz, so -WE has no short pulses.
14. Verified¶
card_debug.py checks that every pin is connected or declared unused, and
each GAL's equations against its spec for every input (make test,
run_tests.sh 6c6); p32jed.py checks the six JEDEC files in
hardware/gal/debug/ through their fuse maps (6c8). At gate level,
sim_debug.py in make test, the Pico a script of local-bus operations:
- listen: hello beside the CPU, MMU / data and memory cards, one
sample a CLK; read back after HALT, the samples hold every bus cycle
from the capture's start to HALT as the bus carried it (768 samples, 355
cycles), and -CPUIN and -MMUIN low in every one (D102);
- dma: one DMA write while the CPU polls the word (dma_test.asm); the
program halts with 5A5A1234; then a DMA read of the word, whose
snapshot in the capture SRAMs holds the cycle as it ended: its address,
-MRD and -ACK low, the data, with CA one further (D101);
- alone: the debug and memory cards, ALONE and STEP: a word written and
read back through the latches; and (D100, D101) the status display
showing a byte written to 4D; CRESN clearing GO, ARM and STEP; 4E
pulling interrupt lines low in DRIVE and none in LISTEN; the SYS group
driving -BGNT5 and -FAST low and the other grants high; and (D102)
the cards that are in: a GO alone turns the bus cycle's drivers on; with
every group and ALONE set and -MMUIN held low, the enables of D, the
bus cycle and the grants are off, the grants float, -FAST and CLK
are still driven, and the same GO turns nothing on; with -CPUIN low
every enable is off and CLK floats; let go, all of them return;
- xclk (D76): the debug and CPU cards: XCLKEN off, the CPU card on its
own oscillator; on, ten STEPs advance its phase by exactly ten; CLKRUN, a
phase per two of the card's oscillator periods; the CPU card's CLOCK
STEP button, a phase a press.
Not exercised: the trigger RAMs' patterns (the simulated RAMs read 0,
so none matches), a post-trigger count other than 1, the 12 MHz mode,
CLKRUN alone, what a GO alone puts on the bus (only that its drivers come
on), -WAIT in a DMA cycle, ODACK / ODWAIT / ODLOCK, the
buffer's wrap, and the J3 and LR groups.
15. Open questions¶
Settled by D102 (2026-11-11): the grants beside the arbiter, and with
them every line the card alone could have driven against a card that was
in (§9). Settled by D100 and D101 (2026-11-11; they were items 1–4 and 6–9 here):
the SRAMs' write race (§8), the power-on state (§5), -BREQ0 in LISTEN
(§10), the lines DRIVE did not reach (§9), the buffer's wrap (§8), the
stale comments, debug-card.md's drift from the netlist, and the mode
switch's part (a slide switch, E-Switch EG1224).
- RESET for XCLKEN (D76): with the CPU card in, the card cannot drive
-RES(GSYS needs ALONE, and since D102 ALONE does nothing with a CPU card in), so someone holds the CPU card's RESET button. Intended? - Which end of S1 is LISTEN. The silkscreen puts LISTEN at pin 1's end of the lever's travel (pin 1 is the grounded one) and DRIVE at pin 3's, taking the usual slide switch, whose common joins the end the lever stands at. E-Switch's drawing could not be fetched: to check on the part with a meter before the board is ordered. (The LEDs show the true mode either way.)
- The firmware. The Pico's firmware, its USB commands and the Mac's tool are not written; nothing yet specifies the host's strobe widths. The trigger RAMs hold anything at power-on: the firmware writes all of both before the first armed capture.
- The mode LEDs' colours are only in their function text (DRIVE red, LISTEN green); the parts list says "LED 3mm".