z486: A 486-Class Pipelined FPGA CPU with Integrated Floating-Point - Small Things Retro
I released z386, an open-source 80386 CPU<br>core, in May and added the 80386<br>early-start optimization in June. Early start overlaps<br>address generation for one instruction with completion of its predecessor. It<br>was an important 386 performance feature, but it also previewed the more<br>systematic i486 pipeline. The<br>MiSTer core needed more<br>performance, so I continued in that direction and added further 486-class<br>mechanisms.
The result is z486, an open-source,<br>80486-class pipelined x86 CPU written in SystemVerilog. It combines hardwired,<br>pipelined execution for common instructions with microcode for complex<br>architectural behavior.
z486 is not an i486 clone. Its design draws on three i486-inspired elements:
a pipelined D1/D2 frontend;
hardwired execution of common instructions, with microcode<br>retained for complex instructions; and
an experimental integrated x87 unit implementing the subset exercised by<br>Quake.
On the same MiSTer system, the current core runs the Doom timedemo at 29.1<br>FPS at maximum detail, compared with 21.0 FPS on ao486. This is roughly<br>486DX2-66-class performance for the measured workload. Dhrystone reaches<br>0.330 DMIPS/MHz , versus 0.225 for z386 and 0.194 for ao486. These<br>results show that a practical pipelined x86 CPU with broad architectural<br>support, including x87, can fit on a mid-range FPGA.
The i486 five-stage pipeline
A finite-state or microcoded CPU limits combinational depth by performing<br>decode, address generation, memory access, ALU work, and commit in separate<br>cycles. This supports a high clock frequency but gives simple instructions a<br>high cycles-per-instruction (CPI) count. Combining all work into one cycle<br>reduces CPI but creates long paths through wide multiplexers and interconnect.<br>Pipelining separates the work with registers and overlaps successive<br>instructions.
Variable-length x86 instructions require a different stage division from the<br>classic RISC pipeline,<br>commonly written as IF-ID-EX-MEM-WB. The i486 uses five stages:
Stage<br>Main work
FI<br>Fetch a 16-byte line into the instruction queue.
D1<br>Decode prefixes, opcode, ModR/M structure, instruction length, and D2 actions.
D2<br>Capture displacement or immediate data and calculate an effective address.
EX<br>Execute ALU or microcode work; access cache and TLB for memory instructions.
WB<br>Write an ALU or load result into the register file.
The two decode stages replace the single RISC ID stage, and cache access occurs<br>in EX rather than in a separate MEM stage. Microcoded instructions can use several EX cycles. One-clock throughput is<br>therefore the common case, not a property of every instruction.
Intel's functional block diagram, reproduced with the<br>references, shows how internal buses<br>connect decode, address generation, translation, cache access, and execution.
Decoding variable-length x86 instructions
By the time the i486 was designed, x86 instructions already had a complex,<br>variable-length encoding. Prefixes, two-byte opcodes, ModR/M and SIB bytes,<br>displacements, and immediates are all optional, and some fields cannot be<br>located until earlier fields have been interpreted. Earlier x86 frontends used<br>sequential decode machinery that could take several clocks. The i486 instead<br>divides decode into two explicit pipeline stages: D1 determines instruction<br>structure and boundaries, while D2 captures literals and generates addresses.
D1 identifies instruction structure and boundaries; D2 consumes literals and computes the effective address.
In the common case, D1 decodes the opcode, ModR/M, and SIB together. It also<br>determines the instruction length and tells the aligner where both the next<br>instruction and the current instruction's literals begin. Prefixes are<br>processed one byte per clock, and a 0F escape consumes another D1 clock.
D2 consumes one 1- to 4-byte displacement or immediate per clock. In parallel,<br>it reads the base and index registers and calculates the effective address.<br>Separate structural and literal ports in the prefetch queue let D1 work on one<br>instruction while D2 works on its predecessor.
Common forms complete D2 in one clock. Two cases extend D2:
an instruction with both a displacement and an immediate uses two D2 clocks;
an address containing base, displacement, and scaled index can use a second<br>D2 clock for the second addition.
This is also the pipelined version of the 386's early-start idea. On the 386,<br>the instruction queue presents address operands during the final cycle of the<br>previous instruction. On the i486, D2 is an explicit stage where the next<br>instruction performs the same work while its predecessors occupy EX and WB.
The extra cycles are a deliberate area and timing tradeoff. Allowing both<br>decoders to select every field from every possible byte position in the<br>prefetch queue would require large alignment networks. The bounded D1 and D2<br>windows keep common instructions fast without making worst-case...