一、实验目的
1、通过实验,进一步理解微程序控制器的组成结构。理解微程序控制器的控制原理
2、加深理解微程序控制器的工作原理。掌握指令流程与功能
3、理解掌握微程序控制器的设计思路与方法
二、实验内容与步骤
1、微程序控制器的组成原理
控制存储器:实现整个指令系统的所有微程序,一般指令系统是规定的由高速半导体存储器构成,容量视机器指令系统而定,取决于微程序的个数,其长度就是微指令字的长度。
微指令寄存器:存放从控存读出的当前微指令。微操作控制字段将操作控制信号送到控制信号线上,微地址字段指出下一条微地址的形成。
微地址寄存器:存放将要访问的下一条微指令地址
地址转移逻辑:形成将要执行的微指令地址,形成方式:
取指令公操作所对应的微程序一般从控存的0地址开始,所以微程序的人口地址0是由硬件控制的。当出现分支时,通过判别测试字段、微地址字段、和执行部件的反馈信息形成后即微地址。
Cpu设计步骤:
- 拟定指令系统
- 确定总体结构(数据通路)
- 安排时序
- 拟定指令流程。根据指令系统,写出对应所有机器指令的全部微操作机器节拍安排,然后列出操作时间表
- 确定微指令的控制方式、下地址形成方式、微指令格式及微指令字长,编写全部的微指令的代码,最后将编写的微指令放入控制存储器中。
微程序控制器的设计步骤
(1)设计微程序
确定微程序流程图,也就是控制算法流程图。
(2)确定微指令格式
微指令格式中的操作控制字段取决于执行部件的子系统需要多少微指令。假定采用直接控制方式,执行部件需要10个微命令,则操作控制字段需要10位。
测试判别字段取决于微程序流程图中有多少处分支转移。假定有3处分支,则测试判别字段需要3位。
下址字段取决于微程序流程图的规模。假定微程序共用50条微指令,则下址字段至少需要6位。这是因为ROM地址译码时,26=64,6位地址可容纳64条微指令。
(3)将微程序编译成二进制代码
(4)微程序写入控制存储器
(5)设计硬件电路
三、实验现象
--CPU 头文件 cpu_defs
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
PACKAGE cpu_defs IS --定义程序包,包头,包体
TYPE opcode IS (load, store, add, sub, bne); --这个语句适合于定义一些用std_logic 等不方便定义的类型,综合器自动实现枚举类型元素的编码,一般将第一个枚举量(最左边)编码为0
CONSTANT word_w: NATURAL :=8;
CONSTANT op_w: NATURAL :=3;
CONSTANT rfill: STD_LOGIC_VECTOR(op_w-1 downto 0):=(others =>'0');
--FUNCTIOn slv2op(slv:IN STD_LOGIC_VECTOR) RETURN opcode;
FUNCTION op2slv(op:in opcode) RETURN STD_LOGIC_VECTOR;
END PACKAGE cpu_defs;
PACKAGE BODY cpu_defs IS
TYPE optable IS ARRAY(opcode) OF STD_LOGIC_VECTOR(op_w-1 DOWNTO 0);--数组有5个元素,其他均0
CONSTANT trans_table:optable :=("000", "001", "010", "011", "100");
FUNCTION op2slv(op:IN opcode) RETURN STD_LOGIC_VECTOR IS
BEGIN
RETURN trans_table(op);
END FUNCTION op2slv;
END PACKAGE BODY cpu_defs;
--实验 7-8 微程序控制器实验
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL,IEEE.NUMERIC_STD.ALL;
USE WORK.CPU_DEFS.ALL;--使用自己定义的程序包
ENTITY CPU IS
PORT( clock : IN STD_LOGIC;--时钟
reset : IN STD_LOGIC;--复位
mode : IN STD_LOGIC_VECTOR(2 DOWNTO 0); --查看用
mem_addr : INUNSIGNED(word_w-op_w-1 DOWNTO 0);--地址
output : OUT STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
data_r_out : OUT STD_LOGIC_VECTOR(19 DOWNTO 0);--微指令R
op_out : OUT STD_LOGIC_VECTOR(op_w-1 DOWNTO 0);--操作码
add_r_out : OUT UNSIGNED(4 DOWNTO 0) --微地址R
);
END ENTITY;
ARCHITECTURE rtl OF CPU IS
TYPE mem_array IS ARRAY (0 TO 2**(word_w-op_w)-1) OF STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);--定义RAM
SIGNAL mem : mem_array;
CONSTANT prog : mem_array:=(
0=> op2slv(load) & STD_LOGIC_VECTOR(TO_UNSIGNED(4,word_w-op_w)),
1=> op2slv(add) & STD_LOGIC_VECTOR(TO_UNSIGNED(5,word_w-op_w)),
2=> op2slv(store) & STD_LOGIC_VECTOR(TO_UNSIGNED(6,word_w-op_w)),
3=> op2slv(bne) & STD_LOGIC_VECTOR(TO_UNSIGNED(7,word_w-op_w)), --TO_UNSIGNED转换函数将4转换为5位“00100”
4=> STD_LOGIC_VECTOR(TO_UNSIGNED(2,word_w)),
5=> STD_LOGIC_VECTOR(TO_UNSIGNED(3,word_w)),
OTHERS => (OTHERS =>'0'));
TYPE microcode_array IS ARRAY (0 TO 14) OF STD_LOGIC_VECTOR(19 DOWNTO 0);
CONSTANT code : microcode_array:=(--控制存储器
0=> "00010100010000000001",
1=> "00000000000110000010",
2=> "00001010000000000011",
3=> "00000100001000001111",
4=> "00100010000000000000",
5=> "00000000000100000000",
6=> "00000010100001000000",
7=> "00000010100000100000",
8=> "00000000000110000100",
9=> "01000001000000000101",
10=> "00000000000110000110",
11=> "00000000000110000111",
12=> "00000000000110010000",
13=> "10000010000000000000",
14=> "00000000000000000000");
SIGNAL count : UNSIGNED(word_w-op_w-1 DOWNTO 0);
SIGNAL op : STD_LOGIC_VECTOR(op_w-1 DOWNTO 0);
SIGNAL z_flag : STD_LOGIC;
SIGNAL mdr_out : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
SIGNAL mar_out : UNSIGNED(word_w-op_w-1 DOWNTO 0);
SIGNAL IR_out : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
SIGNAL acc_out : UNSIGNED(word_w-1 DOWNTO 0);
SIGNAL sysbus_out : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
EGIN
PROCESS(reset,clock)
VARIABLE instr_reg : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
VARIABLE acc : UNSIGNED(word_w-1 DOWNTO 0);
CONSTANT zero : UNSIGNED(word_w-1 DOWNTO 0):=(OTHERS =>'0')
VARIABLE mdr : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
VARIABLE mar : UNSIGNED(word_w-op_w-1 DOWNTO 0);
VARIABLE sysbus : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
VARIABLE microcode : microcode_array;
VARIABLE add_r : UNSIGNED(4 DOWNTO 0);
VARIABLE data_r : STD_LOGIC_VECTOR(19 DOWNTO 0);
VARIABLE temp : STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
IF reset='0' THEN
add_r:=(OTHERS =>'0');
count <= (OTHERS =>'0');
instr_reg := (OTHERS =>'0');
acc := (OTHERS =>'0');
mdr := (OTHERS =>'0');
mar := (OTHERS =>'0');
z_flag <='0';
mem <= prog;
sysbus :=(OTHERS =>'0');
ELSIF RISING_EDGE(clock) THEN
--microprogram controller
data_r := code(TO_INTEGER(add_r));
IF data_r(4 DOWNTO 0)="01111" THEN --判断下地址
temp:="01" & op(2 DOWNTO 0);
add_r := UNSIGNED(temp);
ELSIF data_r(4 DOWNTO 0)="10000" THEN
IF z_flag='1' THEN
add_r:="01110";
ELSE
add_r :="01101";
END IF;
ELSE
add_r := UNSIGNED(data_r(4 DOWNTO 0));
END IF;
data_r_out <=data_r;
add_r_out <= add_r;
--PC
IF data_r(16)='1' THEN --PC_bus='1'
sysbus := rfill & STD_LOGIC_VECTOR(count);
END IF;
IF data_r(19)='1' THEN --load_PC='1'
count <= UNSIGNED(mdr(word_w-op_w-1 DOWNTO 0));
ELSIF data_r(10)='1' THEN --INC_PC='1'
count <= count+1;
ELSE
count <= count;
END IF;
--IR
IF data_r(15)='1' THEN --load_IR
instr_reg := mdr;
END IF;
IF data_r(9)='1' THEN --Addr_bus='1'
sysbus := rfill & instr_reg(word_w-op_w-1 DOWNTO 0);
END IF;
op <= instr_reg(word_w-1 DOWNTO word_w-op_w);
IR_out <= instr_reg;
op_out <=op;
--ALU
IF data_r(17)='1' THEN --load_ACC='1'
acc:=UNSIGNED(mdr);
END IF;
IF data_r(11)='1' THEN --ALU_ACC='1'
IF data_r(6)='1' THEN --ALU_add='1'
acc := acc + UNSIGNED(mdr);
ELSIF data_r(5)='1' THEN --ALU_sub='1'
acc := acc - UNSIGNED(mdr);
END IF;
END IF;
IF data_r(18)='1' THEN --ACC_bus='1'
sysbus := STD_LOGIC_VECTOR(acc);
END IF;
IF acc=zero THEN
z_flag <='1';
ELSE
z_flag <='0';
END IF;
acc_out<= acc;
--RAM
IF data_r(14)='1' THEN --load_MAR='1'
mar := UNSIGNED(sysbus(word_w-op_w-1 DOWNTO 0));
ELSIF data_r(12)='1' THEN --load_MDR='1'
mdr := sysbus;
ELSIF data_r(8)='1' THEN --CS='1'
IF data_r(7)='1' THEN --R_NW='1'
mdr := mem(TO_INTEGER(mar));
ELSE
mem(TO_INTEGER(mar))<=mdr;
END IF;
END IF;
IF data_r(13)='1' THEN --MDR_bus='1'
sysbus:=mdr;
END IF;
mdr_out <= mdr;
mar_out <= mar;
END IF;
sysbus_out <=sysbus;
END PROCESS;
PROCESS(mode,mem_addr)
BEGIN
--mode=0 -> sysbus
--mode=1 -> PC
--mode=2 -> result of ALU
--mode=3 -> IR
--mode=4 -> MAR
--mode=5 -> MDR
--mode=6 -> mem
output <= (OTHERS =>'0');
CASE mode is
WHEN "000" =>
output<=sysbus_out;
WHEN "001" =>
output(word_w-op_w-1 DOWNTO 0)<= STD_LOGIC_VECTOR(count);
WHEN "010" =>
output <= STD_LOGIC_VECTOR(acc_out);
WHEN "011" =>
output <= IR_out;
WHEN "100" =>
output(word_w-op_w-1 DOWNTO 0) <= STD_LOGIC_VECTOR(mar_out);
WHEN "101" =>
output <= mdr_out;
WHEN "110" =>
output <= mem(TO_INTEGER(mem_addr));
WHEN others =>
output <= (OTHERS =>'Z');
END CASE;
END PROCESS;
END ARCHITECTURE;
现象结果:
四、实验体会
原本对于控制器的设计还是一片空白,通过实验初步理解微程序控制器的组成结构。理解微程序控制器的控制原理,加深了理解微程序控制器的工作原理。