Z80-open-silicon开发者手册:TV80 Verilog核心深度剖析
Z80处理器作为经典8位微处理器的代表,在嵌入式系统和复古计算领域具有不可替代的地位。随着Zilog宣布Z80系列产品停产,开源硬件社区亟需一个功能兼容且可硅验证的替代方案。z80-open-silicon项目基于TV80 Verilog核心实现了这一目标,本文将从架构设计、模块交互和代码实现三个维度深入剖析TV80核心的技术细节。
TV80核心架构概览
TV80核心采用模块化设计,通过分层抽象实现了Z80指令集的硬件描述。该架构以微程序控制为核心,配合算术逻辑单元(ALU)、寄存器文件和总线接口,构成完整的处理器数据通路。从src/tv80/tv80_core.v的顶层模块定义可见,TV80支持Z80/Fast Z80/8080/GB四种工作模式(通过Mode参数配置),并提供完整的中断、总线请求和刷新控制信号。
核心架构包含五大关键模块:
- 微程序控制器:通过tv80_mcode.v实现指令解码和时序控制
- 算术逻辑单元:处理所有算术运算和位操作,位于tv80_alu.v
- 寄存器文件:提供通用寄存器和特殊功能寄存器,定义于tv80_reg.v
- 地址生成单元:负责程序计数器(PC)和栈指针(SP)管理
- 总线接口单元:处理外部存储器和I/O设备交互,在tv80s.v中实现
核心模块技术解析
微程序控制单元
TV80采用微程序架构实现指令集,微码存储在tv80_mcode.v的组合逻辑中。该模块接收8位指令寄存器(IR)输入,通过状态机生成控制信号序列。关键实现包括:
always @(*) begin
casez (IR)
// 8位加载指令组
8'b01zzzzzz: begin
if (IR[2:0] == 3'b110) begin
// LD r,(HL) - 从HL指向的内存加载到寄存器
MCycles = 3'b010;
if (MCycle[1]) begin
Set_BusA_To[2:0] = DDD;
Read_To_Reg = 1'b1;
end
end
// 其他指令实现...
end
// 更多指令解码...
endcase
end
微程序控制器通过MCycles和TStates信号控制指令执行周期,Z80典型指令需要3-6个T状态(时钟周期)。例如,存储器读操作在T1状态发送地址,T2状态使能读信号,T3状态锁存数据。
算术逻辑单元(ALU)
ALU模块tv80_alu.v支持8位算术运算、逻辑操作和位操作,通过ALU_Op信号选择操作类型。核心运算单元采用先行进位设计,实现了高效的加法/减法:
function [4:0] AddSub4;
input [3:0] A, B;
input Sub, Carry_In;
begin
AddSub4 = {1'b0, A} + {1'b0, (Sub)?~B:B} + {4'h0, Carry_In};
end
endfunction
// 4位ALU实例,用于低半字节运算
{HalfCarry_v, Q_v[3:0]} = AddSub4(BusA[3:0], BusB[3:0], ALU_Op[1],
ALU_Op[1] ^ (UseCarry && F_In[Flag_C]));
状态标志寄存器(F)的更新逻辑是ALU设计的关键。Z80的标志位包括进位(C)、零(Z)、符号(S)等,在tv80_alu.v中通过组合逻辑实时计算:
F_Out[Flag_Z] = (Q_t == 8'b00000000) ? 1'b1 : 1'b0;
F_Out[Flag_S] = Q_t[7];
F_Out[Flag_C] = Carry_v;
F_Out[Flag_H] = HalfCarry_v;
寄存器文件
TV80的寄存器文件tv80_reg.v实现了Z80的16个8位寄存器,包括主寄存器组(AF, BC, DE, HL)和影子寄存器组(AF', BC', DE', HL')。寄存器采用双端口RAM结构,支持同时读写不同寄存器:
reg [7:0] RegsH [0:7]; // 高8位寄存器组
reg [7:0] RegsL [0:7]; // 低8位寄存器组
always @(posedge clk) begin
if (CEN) begin
if (WEH) RegsH[AddrA] <= DIH; // 写高字节
if (WEL) RegsL[AddrA] <= DIL; // 写低字节
end
end
// 三路输出:支持同时读取三个不同寄存器
assign DOAH = RegsH[AddrA];
assign DOBH = RegsH[AddrB];
assign DOCH = RegsH[AddrC];
在Z80模式下,寄存器文件通过Alternate信号切换主/影子寄存器组,实现快速上下文切换。
指令执行流程解析
以ADD A, r指令(将寄存器r内容加到累加器A)为例,TV80的执行流程如下:
-
取指周期(M1):
- PC寄存器输出指令地址到地址总线
- 从存储器读取指令码到IR寄存器
- PC自动加1指向下一条指令
-
执行周期(M2):
- 微程序控制器解码IR=0x80-0x87(ADD A,r指令)
- 通过Set_BusB_To信号选择源寄存器r
- ALU执行加法运算,结果存入ACC寄存器
- 更新标志寄存器F的Z/C/S等状态位
关键信号时序可参考项目测试规范中的波形图,docs/info.md提供了NOP指令执行的时序参考:
/M1 _________ ____________________
\__________________/ \_________
/MREQ ___________________ ______________________________
\________/
/RD ___________________ ______________________________
\________/
A0..A7
__ XXXXXXXXX ___#00___ ___#00___ XXXXXXXXX XXXXXXXXX ___#01___
高级功能实现
中断处理
TV80支持Z80的可屏蔽中断(INT)和非屏蔽中断(NMI),中断响应逻辑位于tv80_core.v。当检测到中断请求时:
- 完成当前指令执行(M1周期)
- 自动插入中断响应周期(IORQ=1且M1=0)
- 读取中断向量或执行RST指令
- 保存PC到栈并跳转到中断服务程序
总线控制
TV80的总线接口单元tv80s.v实现了Z80的总线仲裁逻辑,包括总线请求(BUSRQ)/响应(BUSAK)机制:
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
busak_n <= 1'b1;
end else if (busrq_n == 1'b0 && busak_n == 1'b1) begin
busak_n <= 1'b0; // 响应总线请求
// 释放地址和数据总线
end
end
总线周期包含存储器请求(MREQ)、I/O请求(IORQ)和刷新(RFSH)信号,支持标准Z80总线时序。
验证与测试
项目测试框架位于test/目录,包含Verilog测试台和Python验证脚本。测试台test/tb.v通过模拟外部存储器和I/O设备,对TV80核心进行功能验证。基础测试流程如下:
- 复位CPU后加载测试程序到仿真RAM
- 执行ZEXALL指令集测试套件
- 比较仿真输出与预期结果
测试 Makefile 提供自动化验证流程:
cd test && make # 执行完整测试流程
应用与扩展
TV80核心已通过TinyTapeout项目流片验证,GDSII文件位于gds/tinytapeout_07_skywater130A/目录。典型应用场景包括:
- 复古计算机重建(如ZX Spectrum克隆)
- 嵌入式控制系统
- FPGA原型验证平台
- 教学实验平台
项目未来计划包括:
- 完善指令集兼容性测试
- 优化时序以支持更高频率(目标50MHz@130nm工艺)
- 提供DIP40/QFN44封装的硅验证版本
- 开发与原始Z80兼容的物理布局
总结
TV80 Verilog核心作为z80-open-silicon项目的技术核心,通过模块化设计实现了Z80指令集的完整功能。本文详细解析了其架构设计、关键模块实现和指令执行流程,为开发者提供了深入理解和扩展该核心的技术基础。项目的开源特性和硅验证目标,使其成为替代停产Z80芯片的理想选择,同时为计算机体系结构教学和复古计算社区提供了宝贵的硬件资源。
完整源代码和文档可通过项目仓库获取,欢迎开发者参与测试和贡献。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



