📄 一句话概括
MREQ 和 IORQ 两根引脚一开一关,同一条地址总线上的点名就分流给内存或 I/O——一趟地址,两个去向。
📝 本节和前面几节的关系
两套门牌(内存地址、端口号)早就挂好了,这一节接上裁决它们的开关线。
一、两根请求线
MREQ(内存请求):有效表示【这趟地址是给内存的】; IORQ(I/O 请求):有效表示【这趟地址是给 I/O 的】。 注意这些控制线是【低电平有效】——0 表示生效,1 表示休息。别被绕晕:硬件这么设计有电路上的理由(抗干扰),记住约定就好。
二、一趟访问的完整表态
CPU 要读内存某格:地址总线放地址 -> MREQ 拉低(找内存)-> RD 拉低(读)-> 内存把内容放上数据总线。 CPU 要写数码管:地址总线放端口号 -> IORQ 拉低(找 I/O)-> WR 拉低(写)-> 数据总线上的内容进端口。 【去哪】加【干什么】,四个信号一组,一次访问的表态就完整了。
三、译码器:硬件中的分流员
光有请求线还不够,得有电路【看线办事】:译码器盯着 MREQ/IORQ 和地址高位,决定把读写信号递给哪块芯片。 这一步在真实硬件里由译码器芯片(或几根门电路)完成,一纳秒都不犹豫——软件里的 if 分支,硬件里有它的孪生兄弟。
四、动手 Demo:译码分流模拟器
模拟两趟访问,看地址如何按 MREQ/IORQ 的表态分流到内存或 I/O。
# 译码分流:一趟地址两个去向
def decode(addr, mreq, iorq):
if mreq == 0 and iorq == 1:
return "内存[0x%04X]" % addr
if mreq == 1 and iorq == 0:
return "I/O 端口[0x%02X]" % addr
return "非法状态"
print(decode(0x0100, 0, 1)) # 访问内存
print(decode(0x02, 1, 0)) # 访问 I/O
实跑输出:
--------------------------------------------------------------------
区分内存和 I/O 的引脚——一趟地址两个去向
--------------------------------------------------------------------
Z80 有两根关键的请求线:MREQ(内存请求) 和 IORQ(I/O 请求)。
同一趟点名,两根线一开一关,地址就流进不同的门:
MREQ IORQ 这趟点名给谁 例子
----------------------------------------------------------
1 0 I/O 端口号 2 的数码管
0 1 内存 地址 0x0100 的一条指令
用 Python 模拟一趟译码:
地址 = 0x0100, MREQ=0(有效), IORQ=1(无效)
-> 判定:访问内存[0x0100]
地址 = 0x02, MREQ=1(无效), IORQ=0(有效)
-> 判定:访问 I/O 端口[0x02]
硬件的译码器芯片干的就是这个【看线分流】的活,一纳秒都不犹豫。
函数里的判断就是译码器的逻辑——硬件把它做进了硅片,时序上比软件快几个量级。 两个 1 同时出现(都不请求)是空闲态;两个 0 同时出现是设计错误。
30 秒实验
- 把 decode 函数抄下来改一改:两个 0 时返回【设计错误】。
- 对照 2.4 节的两套门牌表,把每行配上 MREQ/IORQ 的取值。
常见误区
- 以为低电平有效是笔误——硬件控制线大量使用低有效,是约定不是错误。
- 以为译码靠软件——分流由译码器电路硬件完成,CPU 根本不用操心。
自测三问(点开对答案)
1. MREQ 和 IORQ 各管什么? —— MREQ 有效找内存,IORQ 有效找 I/O——同趟地址的去向开关。 2. 一次访问的完整表态是哪几个信号? —— 去哪(MREQ/IORQ)+干什么(RD/WR),四个信号一组。 3. 译码器的职责是什么? —— 盯着请求线和地址高位,把读写信号递给正确的那块芯片。- ☐ 下一节(2.7 连接剩余的控制引脚)
相关笔记
- 🔵 计算机基础 · 索引 — 门电路与译码在那边有更细的展开
- 软件是指令和数据的集合 — 内存里装的就是这两张表
- 💻 计算机是怎样跑起来的 · 索引