Hotdry.

Article

z386:基于原始微码的开源 80386 FPGA 实现

z386 项目通过执行原始 Intel 微码在现代 FPGA 上重建 80386,实现了仅 8K 行代码即可运行 Doom 的精简架构,为复古 CPU 设计与微码考古提供了可落地的工程范式。

2026-05-23hardware

项目概述

z386 是由开发者 nand2mario 发布的开源 80386 FPGA 软核,其核心创新在于直接使用从原始芯片中提取的 Intel 微码作为控制程序。与纯软件模拟或行为级 RTL 描述不同,z386 的目标是重建足够的原始硬件结构,使恢复出的 386 控制 ROM 能够驱动整个 CPU 运行。目前该项目已能启动 DOS 6 和 DOS 7,运行 DOS/4GW、DOS/32A 等保护模式扩展器,并流畅游玩 Doom II 和 Cannon Fodder 等经典游戏。

这一项目的独特之处在于它超越了单纯的微码逆向工程 —— 它证明了原始微码可以在全新的硬件基底上实际执行,而非仅仅作为历史文档被解读。

架构设计:八单元协作模型

z386 严格遵循 Intel 80386 的八单元组织结构,这种粗粒度的协作模型与现代 RISC 处理器的流水线设计形成鲜明对比:

前端流水线:预取单元维护 16 字节指令队列,以 32 位宽度从内存突发读取;解码器通过 Control PLA 和 Entry PLA 两张查找表,将变长 x86 指令映射为 111 位解码指令字;微码序列器则从 2,560 项、37 位宽的微码 ROM 中取出控制信号。

执行与内存子系统:ALU 与桶形移位器处理算术逻辑运算;分段单元计算逻辑到线性地址的转换;保护单元实现 386 Protection PLA 的特权级检查;分页单元管理 32 项 TLB 和页表遍历;总线接口单元则连接片上缓存、SDRAM 和外设。

这种设计的核心洞察是:386 并非传统意义上的流水线处理器,而是多个大型状态机的重叠协作。预取可以在执行单元忙碌时并行运行,地址转换可以在总线空闲时提前启动,保护测试的结果则可能在三个周期后才反馈到序列器。这种架构允许最多六条指令处于不同处理阶段,但执行单元仍保持每周期一条微指令的串行吞吐量。

微码驱动的控制哲学

z386 最引人注目的技术选择是将原始 Intel 微码作为控制程序直接执行。RTL 代码并不以行为级描述实现 ADDIRETSGDT 等指令,而是实现微码所期望操控的硬件资源。

每条 37 位微指令包含源 / 目标寄存器选择、ALU 操作、跳转目标、总线控制等字段。一个典型的寄存器间移动需要两个微周期:第一条指令选择源寄存器并标记 RNI(Run Next Instruction),第二条指令作为延迟槽将结果写入目标寄存器。这种两周期最小延迟是 386 架构的固有特性,与 486 及后续处理器追求的每周期一条指令的细粒度流水线形成对比。

微码分支同样具有延迟槽特性 —— 跳转指令后的下一条微指令总会执行。Protection PLA 的特权检查结果需要三个周期才能反馈,这意味着三条微指令可能在重定向生效前执行完毕。这种控制流的复杂性使得微码阅读如同解谜:看似线性的代码实际上充满了隐含的硬件时序假设。

VIPT 缓存与内存子系统

原始 386 没有片上 L1 缓存,依赖外部缓存控制器。z386 为提升 FPGA 实现效率,添加了 16KB、四路组相联的统一指令 + 数据缓存,采用 VIPT(Virtually Indexed, Physically Tagged)查找策略。

VIPT 的关键优势在于允许地址转换与缓存查找并行进行:使用线性地址的页内偏移位启动标签和数据 BRAM 的预读,待物理地址可用后在下一周期完成标签比较。这种设计将命中延迟压缩到接近零等待状态,同时避免了同义词问题 —— 因为索引位被限制在 4KB 页偏移范围内。缓存行大小为 16 字节,采用伪 LRU 替换策略和写直达策略,配合双入口写缓冲区缓解 SDRAM 压力。

性能表现与工程权衡

与成熟的 ao486 项目相比,z386 展现了精简架构的竞争力:

指标 z386 ao486
代码行数 8K 17.6K
ALUT 用量 18K 21K
FPGA 时钟 85MHz 90MHz
Doom 帧率 16.5 FPS 21.0 FPS

z386 的性能相当于约 70MHz 的带缓存 386 或低端 486。虽然 CPI(每指令周期数)略高,但通过高时钟频率和片上缓存弥补了差距。这种设计哲学优先考虑保持高核心时钟和紧凑代码量,而非追求最大化的缓存容量。

验证方法论

z386 的开发验证了复古 CPU 工程的一套实用测试流程:

单指令模糊测试:使用 SingleStepTests/80386 进行实模式单步比对,以及基于 86Box 构建的保护模式测试集,覆盖 IRETLAR、调用门、页故障等复杂场景。

集成测试链:从 SeaBIOS 的 I/O 端口调试输出,到 FreeDOS、HIMEM、EMM386 的渐进验证,最终通过 DOS/4GW 和 Doom 进行全系统压力测试。DOS 扩展器尤其具有挑战性 ——DOS/4GW 的保护模式初始化代码曾耗费两周的追踪和反汇编才完全调通。

波形追踪:使用 Verilator 仿真配合波形对比,将每个故障还原为可重复的最小测试用例。

工程启示

z386 项目为 FPGA CPU 设计提供了几点可落地的经验:

微码考古的价值:恢复的微码不仅记录了控制流程,更揭示了内部寄存器命名规范、可复用子程序结构以及隐含的硬件契约。当微操作名称映射到特定行为时,正确实现意味着还原原始架构的另一层细节。

粗粒度 vs 细粒度:386 风格的粗粒度单元协作与 486 风格的细粒度流水线各有优劣。前者控制逻辑更紧凑,后者潜在性能更高,但后者需要更复杂的冒险检测和前递逻辑。

FPGA 友好的折中:z386 在保持 386 结构 faithful 的同时,在关键路径采用 FPGA 优化 —— 使用 DSP 块加速乘法、用同步 BRAM 实现 VIPT 缓存、以高时钟频率补偿 CPI。这种平衡是实用复古 CPU 工程的核心。

现状与展望

目前 z386 已在 Altera Cyclone V 和 Gowin GW5A 等多个 FPGA 家族上验证通过,但仍有改进空间:Windows 尚未能完整启动,保护模式测试覆盖率有待扩展,部分 PLA 控制线仍未完全解读。

作为开源项目,z386 不仅提供了一个可运行的 80386 实现,更建立了一套基于原始微码的 CPU 重建方法论。对于希望在 FPGA 上实现复古处理器的工程师而言,它展示了如何将历史微码转化为可综合的硬件描述,以及如何在忠实还原与工程实用之间找到平衡点。


资料来源

hardware

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com