Spec first, and the gateware is wrong in 12 places
I wrote SPEC.md and docs/VPLAN.md before correcting any RTL, and declared the spec authoritative. Every normative sentence has an ID like S-RX-3, every plan row cites one, and the plan bans the words “correctly”, “properly” and “as expected” from its pass conditions. Then I walked the existing gateware against it and wrote down where they disagreed. There were 12.
The worst ones. The cd_b8008 reset synchronizer was gated only on the PLL lock, with no power-on reset or button in the fan-in and no ordering against cd_sys, so the console logic and the core could come out of reset in either order. The console read register was a destructive pop, and LiteX’s CommUDP retries a read that times out, so a dropped reply packet ate a byte silently. The RX FIFO dropped bytes on the floor when full instead of stalling the 8008. A TX write while full was discarded without a flag. And five retired control inputs, run/stop, step, interrupt request and vector, were left undriven at the netlist boundary going into the CPU’s run and interrupt logic.
The fixes came in as their own commits. ConsoleBridge got extracted from the integration module as a pure Migen block. console_rx became a non-destructive read of data, valid and level in one word, with console_rx_pop as a separate write. Backpressure went in with hysteresis at 4032 and 3968 bytes, gating the core’s run_enable hold. A sticky console_err register with three bits, where a set that coincides with a clear resolves in favor of set. TX writes while full are rejected and flagged. The cd_b8008 reset is now synchronized off the PLL lock and the board reset together, and ordered after the console logic’s reset. The dead controls, the hardcoded triggered status and the Wishbone RAM window are gone from the CSR map and from the VHDL entity itself.
SPEC.md was wrong twice. S-RST-3 said no reset reached cd_b8008 at all, and it did, it was just mis-gated. S-CDC-1 miscounted the crossings. Both corrections are noted in the document where they happened instead of being quietly edited.
Then the first real bitstream build, yosys through ecppack. It succeeded, and the post-PnR report printed a critical path report for a cross-domain path from the etherbone clock to the b8008 clock. S-CLK-3 wants those two declared as separate clock groups. LiteX’s add_false_path_constraints() turns out to be inert on the ECP5 Trellis toolchain and never reaches the generated .lpf or nextpnr. I found no mechanism to declare the groups, so D-12 stays open.
A final review pass found six plan rows in the test suite tagged against the wrong assertion, and one row, RX-6, had no genuine test behind its tag and went back to unimplemented. The count went from 32 to 31.
Where it landed. 11 of 12 divergences resolved. 31 of 119 verification rows pass, 88 unimplemented, 11 imported from the core repo and never re-run here. The host package has 86 tests passing. make login exists as a console client with discovery by cache, then DNS, then a subnet sweep. Nothing had run on the board yet when this closed.