数据通路
为了理解微程序控制器的设计思想, 我们假设一个极简的数据通路(如下图 1 所示), 由并联在单条 8 位总线 BUS 上的三个部件组成: 指令寄存器 IR(寄存器 74LS273 构成), 程序计数器 PC(计数器 74LS163 构成), 程序存储器 PROGRAM(ROM 存储器 2764 构成).
图 1. 数据通路图
在数据通路上所能执行的某一种操作可以看作是一条对应的 "指令", 则该数据通路能执行的所有操作可以用一个极简的指令集 (只包含四条指令) 来描述, 如下表 1 所示:
表 1. 微程序控制器指令集列表
按照上述指令表 1 的指令格式, 用户可以编写一段机器语言程序存放在程序存储器 PROGRAM 中, 如下表 2 所示. 其中每一个存储器单元存放一个字节的数据, 对应唯一的 8 位二进制地址(由地址寄存器 AR 锁存). 若用户需要访问程序存储器的某个单元, 须由程序计数器 PC 提供该单元的地址, 才能从程序存储器取出该单元中的数据. 因为程序是顺序访问的, 所以程序计数器 PC 是由两个计数器 74LSl63 级联构成的一个 8 位递增计数器 PC. 当前指令从程序存储器 PROGRAM 取出, 并锁存到指令寄存器 IR 后, PC 自动执行 PC+1 操作, 指向相邻下一条指令.
表 2. 程序存储器 PROGRAM 中的机器语言程序
微程序设计原理
仔细分析上述图 1 和表 1 可知, 数据通路的各条指令状态图如下图 2 所示: 所有指令的取指操作都是相同的, 即是上图 1 中紫色箭头所示的指令流 (ROM→IR):CPU 从程序存储器 PROGRAM 取出指令, 经过总线 BUS 流向指令寄存器 IR.NOP 和 HLT 指令只有上述取指操作, 没有执行操作(HLT 指令取指后硬件停机); 而 JMP1 和 JMP2 指令除了上述取指操作外, 实际只有一种执行操作, 即上图 1 中红色箭头所示的数据流(ROM→PC):CPU 从程序存储器 PROGRAM 取出数据, 经过总线 BUS 流向程序计数器 PC. 两种跳转指令不同之处在于: JMP1 指令的第二字节是目标地址(直接寻址), 只要一次数据流(ROM→PC) 就把目标地址送入 PC; 而 JMP2 指令的第二字节是存放目标地址的存储器单元地址 (间接寻址), 需要连续两次数据流(ROM→PC) 才能把目标地址送入 PC.
图 2. 微程序控制器指令状态图
在上图 2 中, 虽然微程序控制器指令的状态类型只有两种(指令流和数据流), 但是每一条指令拥有的状态数目都不尽相同, 其中最关键问题是如何根据不同的指令来判断状态的转移. 因此我们可以采用微程序原理来解决这个问题: 图 2 中每一条指令都是一个任务, 一个状态则对应一条微指令. 若干条微指令组合成一段微程序, 解决相对应的任务.
微指令的字长设为 24 位, 结构如下图 3 所示:
1-5 位表示该微指令执行后, 下一条微指令的地址 [uA4, uA0](即下址转移方式);
6-7 位是判断字段 Px:P1=1 表示该微指令是取指微指令;,P2 空缺.
8-24 位是微命令字段: 微命令即是图 1 所示数据通路中的微操作信号, 其中某位置 "1", 表示该位的微命令有效; 反之, 置 "0" 则表示该位的微命令无效.
图 3. 微指令结构图
仔细观察数据通路图 1, 可以发现指令的取指或执行过程都是指令或数据从一个部件打入总线 BUS, 再从总线 BUS 打入另一个部件的过程. 为了保证上述操作先后次序, 指令流 (ROM→IR) 和数据流 (ROM→PC) 都分为 T1 和 T2 两个周期: T1 周期, 信息从源部件 (例如程序存储器 PROGRAM) 打入总线 BUS;T2 周期, 信息从总线 BUS 打入目标部件 (例如指令寄存器 IR 或者程序计数器 PC), 如下表 3 所示. 因此, 在图 3 所示的微操作信号中, 除了信号 #OE(存储器输出使能) 和 #LDPC(PC 加载使能)是全过程有效外, 其他信号需要与 T1 或 T2 周期节拍信号逻辑 "与", 产生新的边沿触发信号, 在指定周期开始时刻上升沿跳变, 例如 AR_CLK=LDAR•T1,IR_CLK=LDIR•T2,PC_CLK=PC_INC•T2
表 3. 数据通路的微操作信号列表
综合上述微指令结构图 3 和微操作信号列表 3, 通过分析微程序控制器指令状态图 2, 可以得到如下图 4 所示的微程序流程图: 图中每一个方框在时间上表示一个微指令周期, 包括 T1(源部件→总线)和 T2(总线→目标部件)两个周期; 在空间上表示一条微指令, 通过一系列微操作信号使得信息从某个源部件经过总线 BUS 到达目标部件. 图中每个方框的右上方是对应微指令的地址, 右下方是对应微指令的下一条微指令的地址(简称下址).
图 4. 指令的微程序流程图
上述微程序流程图 4 中, 最上方首先执行的方框是公共的取指微指令, 即指令流 (ROM→IR). 取出指令后, P1 菱形框表示指令译码及地址转移: 根据当前指令 OP 码的[I7,I6,I5] 位形成其执行周期第一条微指令地址 [0,0,I7,I6,I5], 从而选择该指令的执行周期. 菱形框下的四条路径对应指令列表 1 所述的四条指令的执行周期, 其中每个方框是一条执行微指令, 即数据流(ROM→PC). 值得注意的是, NOP 指令和 HLT 指令只有取指周期, 没有执行周期. NOP 指令的 OP 码是 000, 取指后译码得到的第一条微指令地址仍为[00000], 即直接返回下一条指令的取指周期. 而 HLT 指令的 OP 码是 111, 译码后直接令硬件停机. 在所有路径末尾, 最后一条微指令的下址[uA4-uA0] 都必须是取指微指令地址[00000], 即一条指令结束后必须返回取指微指令, 准备取出下一条指令. 如图 4 左上方所示, 整个数据通路的运行过程就是不断循环的取指令和执行指令. 图 4 中总共有三条微指令, 其编码如下表 4 所示(具体位置的微命令含义请参考微指令结构图 3).
表 4. 微指令列表
微程序控制器
上述微指令列表 4 相当于一个并行的操作开关序列, 用户根据微程序流程图 4, 在规定的微指令周期 (方框), 按照规定的节拍 Tx, 拨动特定的操作开关序列(微指令), 就可以实现从程序存储器 PROGRAM 中取出和执行一条机器指令. 更进一步, 我们可以用时序发生器输出预定的时序, 通过微程序控制器按时序自动产生操作信号, 代替用户在数据通路中完成的人工操作. 时序发生器(CLOCK UNIT), 微程序控制器(CONTROLL UNIT) 和数据通路共同构成一个最小版本的 CPU, 如下图 5 所示.
图 5. 最小版本 CPU 电路图
在上述 CPU 电路图 5 中, 代替用户人工操作的 CPU 部件是微程序控制器 (CONTROLL UNIT), 由控制存储器, 微指令寄存器, 微地址寄存器和地址转移逻辑电路组成, 如下图 6 所示. CPU 启动或复位后, 微地址寄存器清零, 控制存储器从地址[00000] 开始输出微指令. 如前述微指令结构图 3 所示, 微指令包括了控制字段, 下址字段和判断字段. 控制字段即下图 6 中的微命令字段, 直接输出微操作信号执行当前微指令; 下址字段锁存在微地址寄存器, 待当前微指令执行完后, 再从控制存储器取出下一条微指令. 若当前微指令是取指微指令, 则 P 字段启动地址转移, 根据指令寄存器 IR 中的 OP 码修改微地址寄存器, 转向指令执行周期的第一条微指令.
图 6. 微程序控制器结构图
存放上述微指令列表 4 的存储器电路如下图 7 所示: 微指令存储器字长 24 位, 由 3 个 2764 芯片 MROM1-3 组成, 其输出端则连接着微指令寄存器 MDR1-3(寄存器 74LS273 和 74LS175 构成). 在系统启动 (信号 ON=1) 或 T1 周期开始 (信号 T1=1) 时刻, MROM1-3 输出当前微指令的微操作信号, 锁存在 MDR1-3, 送往数据通路执行. 部分微操作信号 (LDAR,LDIR,PC_INC) 与 T1 或 T2 节拍组合, 产生边沿触发信号(AR_CLK,IR_CLK,PC_CLK), 在 T1 或 T2 周期开始时刻上升沿跳变.
图 7. 微程序控制器的存储器电路
如下图 8 所示, 控制器的微地址寄存器字长五位 (MA4-MA0), 由触发器 74LS74 组成, 其输入端通过 NMABUS 总线连接当前微指令的下址字段[uA4-uA0], 其输出端通过控制存储器的地址总线 MABUS 送到控制存储器的地址端 A4~A0. 值得注意的是, 上述微程序控制器结构图 6 中的地址转移逻辑(即微程序流程图 4 中的菱形框 P1) 在下图 8 中对应的就是三个三路与非门 74LS10. 在取指周期末尾, 微指令下址字段本来是 [00000]; 然而判断字段 P1=1, 启动地址转移逻辑, 根据指令寄存器 IR 的 OP 码[I7,I6,I5] 生成信号 #SET_MAx=0, 强制把微地址寄存器 MA4-MA0 置位为[0,0,I7,I6,I5], 即该指令执行周期的第一条微指令地址.
图 8. 微地址寄存器和地址转移逻辑
上述微程序的地址转移过程需要在微指令周期增加 T3 和 T4 两个周期: T3 周期, 当前微指令的下址字段 [uA4-uA0] 通过 NMABUS 总线打入微地址寄存器 MA4-MA0, 进而通过地址总线 MABUS 送往微指令存储器 MROM1-3 的地址端, 使其输出下一条微指令; T4 周期, 若当前微指令是执行周期微指令, 则 P1=0, 无任何操作; 若当前微指令是取指周期微指令, 则 P1=1, 启动地址转移逻辑, 重置微指令地址, 跳转到当前指令的执行周期第一条微指令.
综上所述, 一条 CPU 指令就是一段微程序, 其中包含若干条微指令 (至少有一条是取指微指令). 所以,"微程序" 时序如下图 9(左) 所示: 每个指令周期都包含了若干条微指令的机器周期 (即微指令周期), 其中至少有一个取指微指令周期. 而且, 每一条微指令的运行过程都可以看成是一个状态机, 如下图 9(右) 所示: 状态机有 4 个状态{T1,T2,T3,T4}, 每个状态[Tx] 完成从取指, 执行到判断下址的相应任务, 状态转移 T1→T4 的一次循环即是一个微指令周期. 因此, 每个微指令周期内部包含了四个节拍信号 Tx, 对应 "微指令" 状态机的 4 个状态{T1,T2,T3,T4}, 状态机周而复始在四个状态[Tx] 之间顺序转移,
图 9. 微程序的时序图和状态机
CPU 时序发生器如下图 10 所示, 主要功能是为上述微程序控制器提供时序控制. 其中最核心的状态转移电路是由两个 D 触发器组成的一个 2 位扭环计数器, 输出节拍序列{T1,T2,T3,T4}={00,01,11,10}.CLK 为整个 CPU 电路的时钟信号, 可以由手动按键 MANUAL_CLK 或方波信号源 AUTO_CLK 生成(双击信号源可以自行选择方波信号频率).
时序发生器还提供了硬件电路实现 HLT 指令的停机功能(即断点). 当指令寄存器 IR 的 OP 码 I7I6I5=111 的时候, 停机信号 #HLT=0, 阻塞 CLK 输出, CPU 停机在 HLT 指令的取指周期 T2 节拍上. 跳出 HLT 指令断点的复位过程与上述初始化过程相同, 信号 #RESET=0 令指令寄存器 IR 清零, OP 码[I7,I6,I5]=000, 则 #HLT=1, 跳出 "断点"; 同时, 扭环计数器强制为状态 T1={00}.#RESET=1, 复位成功, CPU 进入 HLT 指令后续下一条指令的取指周期 T1 节拍.
此外, 为了观测微程序的运行, 时序发生器电路提供了一个由节拍信号 T1 上升沿驱动的双位微指令计数器 MICRO-I(两个十进制加法计数器 74LS160 级联构成), 通过数码管显示当前运行第几条微指令, 显示范围是 1~99, 如下图 10 右边所示.
图 10. 微程序控制器的时序发生器
来源: http://www.bubuko.com/infodetail-3306699.html