实验f4a 8位12指令硬布线CPU设计
模型机是计算机的缩细模型,通过它可以理解计算机整机的结构及功能,理解CPU、存储器、中断控制器、接口的结构及实现逻辑和各部件之间的接口关系。本次课程设计的主要内容是利用Intel公司的EPF10K10LC84-4的内部可编程资源,设计一个8位模型计算机。本课程设计的主要目的是通过部件级的8位模型机的设计和调试,使学生掌握计算机工作中“时间—空间”概念的理解,从而清晰地建立计算机的整机概念,并培养学生分析和解决实际问题的能力,同时增强学生的动手能力。
一、实验目的
(1)融会贯通本课程各章节的内容,通过知识的综合运用,加深对计算机系统各功能部件的工作原理及相互联系的认识,加深计算机工作中“时间—空间”概念的理解,从而清晰地建立计算机的整机概念;
(2)学习设计和调试计算机的基本步骤和方法,提高使用Quartus等软件仿真工具和集成电路的基本技能;
(3)培养科学研究的独立工作能力,取得工程设计与组装调试的实践和经验。
二、设计要求
设计一台硬布线控制器的8位模型计算机,用VHDL语言完成设计并调试成功
三、实验原理
以控制器为中心,首控制器从指令寄存器取得指令,编译指令,再输出微控制信号,控制ALU的运算,PC加一,并且从RAM中取出数据运算,运算后再把结果通过数据总线存到RAM,在指令寄存器读去下一条指令,依次循环。
四、设计内容
五、CPU电路图展示
六、由六大模块组成模型机仿真图
将这六大模块连成一大整体它产生控制信号也即控制器产生的控制信号控制各大模块的运行,而且它能检测其它部件发送过来的信号,协调各个部件按指令要求完成规定任务,所以它的输出是各大控制信号也即前面涉及到的控制器的控制信号。
七、ram中测试程序,波形图及与指令的对应关系分析,数据运算过程分析
(1)测试程序
(2)波形图及逐条指令、逐个阶段、逐个操作、逐个部件逐个数据变化的对应关系分析,数据运算过程分析。
读取指令
第一步:PC将指令地址通过地址总线给MAR
abus中,若传输的为pc中的值,则为递增从0000到1001(9)的数
此时地址总线数值为0000,0000
第二步:向主存发送读命令
每当PC的值放到数据总线时,PC_enAX为1,即标志PC访问MAR
在该系统中,PC将指令地址直接传给RAM
第三步:将MAR所指的内存单元经过数据总线给MDR
以第一条例子中第一个指令,此时数据总线为0001,0100,即RAM中0号存储单元对应的数据;
第四步:将MDR中的内容给IR,
此时ir_ldx为1,标志被写入数据
第五步:将指令的操作码部分给CU
CU用IR的后4位(4到7位)作为操作码,进行译码;
指令为0001,0100
操作码为0001,存数指令
第六步:形成下一条指令
PC+1
此时,地址总线为0000,0001
执行周期(以存数指令为例)
存数指令
第一步:将指令的地址码(前四位)通过地址总线部分给MAR
指令为0001,0100
地址码为0100
此时地址总线的值为0000,0100
此时pc_enAx为1,标志cu向RAM写入数据
第二步:向主存发读指令
此时mem_rwX为1
第三步:将MDR中的数据写到MAR指定的主存单元内;
此时MDR放的不是指令,而是数据
此时数据总线为0000,0000
此时mem_rw为0,标志写操作
即将数据0000,0000写到4号存储单元;
七、其他测试程序,波形图及与指令的对应关系分析,数据运算过程分析
(2)波形图及及逐条指令、逐个阶段、逐个操作、逐个部件逐个数据变化的对应关系分析,数据运算过程分析。
LOAD 2
PC为0000,0000
PC将指令地址直接传给MAR,MAR通过数据总线传给RAM;
此时地址总线为0000,0000
拿到0号存储单元的指令后经过数据总线给MDR
此时数据总线为0000,0010即指令为0000,0010
操作码为0000,LOAD
地址码为0010,2号存储位
操作码部分给CU;
地址码部分给MAR,MAR通过地址总线给RAM,并将数据通过数据总线给MDR与ACC
此时地址总线为0000,0010
此时数据总线为0001,0010
此时ACC_QX为0001,0010
ADD 3
PC为0000,0001
PC将指令地址直接传给MAR,MAR通过数据总线传给RAM;
此时地址总线为0000,0001
拿到1号存储单元的指令后经过数据总线给MDR
此时数据总线为0010,0011即指令为0010,0011
操作码为0010,ADD
地址码为0011,3号存储体
操作码部分给CU;控制ALU进行加法操作
此时ALU_OP为000
对ACC的内容取反,ACC_QX为1110,1110
地址码部分给MAR,MAR通过地址总线给RAM,并将数据通过数据总线给MDR与ACC
此时地址总线为0000,0011
此时数据总线为0000,0001
此时cu操作ALU_OP为111,ALU完成两树相加
数据总线数值分别为:0001,0010;1110,1110;0000,0001;0010,0011;
得到和0010,0011输出到ACC
此时ACC_QX为0010,0011
STORE 2
PC为0000,0010
PC将指令地址直接传给MAR,MAR通过数据总线传给RAM;
此时地址总线为0000,0010
拿到2号存储单元的指令后经过数据总线给MDR
此时数据总线为0001,0010即指令为0001,0010
操作码为0001,STORE
地址码为0010,2号存储位
操作码部分给CU;
地址码部分给MAR,MAR通过地址总线给RAM,并将数据通过数据总线给MDR与ACC
此时地址总线为0000,0010
此时数据总线为1110,1110
此时mem_rw为0,写入操作
HALT
PC为0000,0011
PC将指令地址直接传给MAR,MAR通过数据总线传给RAM;
此时地址总线为0000,0011
拿到4号存储单元的指令后经过数据总线给MDR
此时数据总线为0000,0001即指令为0000,0001
操作码为HALT,程序结束
八、实验代码
1、 累加寄存器accumulator
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity accumulator is ----声明外部实体接口
port (
clk, en_D, ld, selAlu, reset: in STD_LOGIC; --时钟信号
aluD: in STD_LOGIC_VECTOR(7 downto 0);
dBus: inout STD_LOGIC_VECTOR(7 downto 0);
q: out STD_LOGIC_VECTOR(7 downto 0)
);
end accumulator;
architecture accArch of accumulator is
signal accReg: STD_LOGIC_VECTOR(7 downto 0);
begin
process(clk) begin
if clk'event and clk = '1' then
if reset = '1' then
accReg <= "00000000";
elsif ld = '1' and selAlu = '1' then
accReg <= aluD;
elsif ld = '1' and selAlu = '0' then
accReg <= dBus;
end if;
end if;
end process;
dBus <= accReg when en_D = '1' else
"ZZZZZZZZ";
q <= accReg;
end accArch;
2、 算术运算器 ALU
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity alu is -----实体声明外部接口
port (
op: in STD_LOGIC_VECTOR(3 downto 0); --选择控制运算类型
accD: in STD_LOGIC_VECTOR(7 downto 0); -- 累加器的8位数据
dBus: in STD_LOGIC_VECTOR(7 downto 0); -- 数据总线用于运算
result: out STD_LOGIC_VECTOR(7 downto 0); --结果的输出
accZ: out STD_LOGIC
);
end alu;
architecture aluArch of alu is
begin
result <= (not accD) + "00000001" when op ="0000" else
accD + dBus when op ="0001" else
accD+"10000000" when op="0010" else
dBus+"10000000" when op="0011" else
(not accD)-"00000001" when op="0100" else
accD-dBus when op="0101" else
accD*dBus when op="0110" else
accD*(not dBus) when op="0111" else
accD AND dBus when op="1010" else
accD NAND dBus when op="1011" else
accD OR dBus when op="1100" else
accD NOR dBus when op="1101" else
accD XNOR dBus when op="1110" else
NOT accD when op="1111" else
"00000000";
accZ <= not (accD(0) or accD(1) or accD(2) or accD(3) or
accD(4) or accD(5) or accD(6) or accD(7)
);
end aluArch;
3、 硬布线控制器(controller)
library IEEE;
use IEEE.std_logic_1164.all;
entity controller is ----声明实体外部接口
port (
clk, reset:
in STD_LOGIC;
mem_enD, mem_rw:
out STD_LOGIC;
pc_enA, pc_ld, pc_inc: out STD_LOGIC;
ir_enA, ir_enD, ir_ld: out STD_LOGIC;
ir_load, ir_store, ir_add: in STD_LOGIC;
ir_sub,ir_mul,ir_div: in STD_LOGIC;
ir_and,ir_or, ir_not: in STD_LOGIC;
ir_neg, ir_halt, ir_branch: in STD_LOGIC;
acc_enD, acc_ld, acc_selAlu: out STD_LOGIC;
alu_op: out STD_LOGIC_VECTOR(2 downto 0)
);
end controller;
architecture controllerArch of controller is
type state_type is ( reset_state,
fetch0, fetch1,
load0, load1,
store0, store1,
add0, add1,
sub0, sub1,
mul0, mul1,
div0, div1,
and0, and1,
or0, or1,
not0, not1,
negate0, negate1,
halt,
branch0, branch1
);
signal state: state_type;
begin
process(clk) begin
if clk'event and clk = '1' then
if reset = '1' then state <= reset_state;
else
case state is
when reset_state => state <= fetch0;
when fetch0 => state <= fetch1;
when fetch1 =>
if ir_load = '1' then state <= load0;
elsif ir_store = '1' then state <= store0;
elsif ir_add = '1' then state <= add0;
elsif ir_sub = '1' then state <= sub0;
elsif ir_mul = '1' then state <= mul0;
elsif ir_div = '1' then state <= div0;
elsif ir_and = '1' then state <= and0;
elsif ir_or = '1' then state <= or0;
elsif ir_not = '1' then state <= not0;
elsif ir_neg = '1' then state <= negate0;
elsif ir_halt = '1' then state <= halt;
elsif ir_branch = '1' then state <= branch0;
end if;
when load0 => state <= load1;
when load1 => state <= fetch0;
when store0 => state <= store1;
when store1 => state <= fetch0;
when add0 => state <= add1;
when add1 => state <= fetch0;
when sub0 => state <= sub1;
when sub1 => state <= fetch0;
when mul0 => state <= mul1;
when mul1 => state <=fetch0;
when div0 => state <=div1;
when div1 => state <=fetch0;
when and0 => state <=and1;
when and1 => state <=fetch0;
when or0 => state <=or1;
when or1 => state <=fetch0;
when not0 => state <=not1;
when not1 => state <=fetch0;
when negate0 => state <= negate1;
when negate1 => state <= fetch0;
when halt => state <= halt;
when branch0 => state <= branch1;
when branch1 => state <= fetch0;
when others => state <= halt;
end case;
end if;
end if;
end process;
process(clk) begin -- special process for memory write timing
if clk'event and clk = '0' then
if state = store0 then
mem_rw <= '0';
else
mem_rw <= '1';
end if;
end if;
end process;
mem_enD <= '1' when state = fetch0 or state = fetch1 or
state = load0 or state = load1 or
state = add0 or state = add1 or
state = sub0 or state = sub1 or
state = mul0 or state = mul1 or
state = div0 or state = div1 or
state = and0 or state = and1 or
state = or0 or state = or1 else '0';
pc_enA <= '1' when state = fetch0 or
state = fetch1 else '0';
pc_ld <= '1' when state = branch0
else '0';
pc_inc <= '1' when state = fetch1
else '0';
ir_enA <= '1' when state = load0 or
state = load1 or state = store0 or
state = store1 or state = add0 or
state = add1 or state = sub0 or
state = sub1 or state = mul0 or
state = mul1 or state = div0 or
state = div1 or state = and0 or
state = and1 or state = or0 or
state = or1 else '0';
ir_enD <= '1' when state = branch0
else '0';
ir_ld <= '1' when state = fetch1
else '0';
acc_enD <= '1' when state = store0 or state = store1 else '0';
acc_ld <= '1' when state = load1 or state = add1 or state = negate1
or state = sub1 or state = mul1 or state = div1
or state = not1 or state = or1 or state = not1 else '0';
acc_selAlu <='1' when state = add1 or state = negate1 or state = sub1 or
state = mul1 or state = div1 or state = not1 or
state = or1 or state = not1 else '0';
alu_op <= "000" when state = add0 or state = add1
else "001" when state = sub0 or state = sub1
else "010" when state = mul0 or state = mul1
else "011" when state = div0 or state = div1
else "100" when state = negate0 or state = negate1
else "101" when state = and0 or state = and1
else "110" when state = or0 or state = or1
else "111" when state = not0 or state = not1;
--alu_op <= "01" when state = add0 or state = add1 else "00";
end controllerArch;
4、 指令寄存器instruction_register
library IEEE;
use IEEE.std_logic_1164.all;
entity instruction_register is ----声明实体外部接口
port (
clk, en_A, en_D, ld, reset: in STD_LOGIC;
aBus: out STD_LOGIC_VECTOR(7 downto 0); ----数据总线输出
dBus: inout STD_LOGIC_VECTOR(7 downto 0);
load, store, add, sub,mul,div,andd,orr,nott,neg, halt, branch: out STD_LOGIC
);
end instruction_register;
architecture irArch of instruction_register is
signal irReg: STD_LOGIC_VECTOR(7 downto 0);
begin
process(clk) begin
if clk'event and clk = '0' then -- load on falling edge
if reset = '1' then
irReg <= "00000000";
elsif ld = '1' then
irReg <= dBus;
end if;
end if;
end process;
aBus <= "0000" & irReg(3 downto 0) when en_A = '1' else
"ZZZZZZZZ";
dBus <= "0000" & irReg(3 downto 0) when en_D = '1' else
"ZZZZZZZZ";
load <= '1' when irReg(7 downto 4) = "0000" else '0';
store <= '1' when irReg(7 downto 4) = "0001" else '0';
add <= '1' when irReg(7 downto 4) = "0010" else '0';
sub <= '1' when irReg(7 downto 4) = "0011" else '0';
mul <= '1' when irReg(7 downto 4) = "0100" else '0';
div <= '1' when irReg(7 downto 4) = "0101" else '0';
neg <= '1' when irReg = "0110" & "0000" else '0';
andd <= '1' when irReg (7 downto 4) = "0111" else '0';
orr <= '1' when irReg (7 downto 4) = "1000" else '0';
nott <= '1' when irReg (7 downto 4) = "1001" else '0';
halt <= '1' when irReg = "1010" & "0001" else '0';
branch <= '1' when irReg(7 downto 4) = "1011" else '0';
end irArch;
5. 程序计数器program_counter
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity program_counter is
port (
clk, en_A, ld, inc, reset: in STD_LOGIC;
aBus: out STD_LOGIC_VECTOR(7 downto 0); --数据总线输出
dBus: in STD_LOGIC_VECTOR(7 downto 0); --数据总线输入
);
end program_counter;
architecture pcArch of program_counter is
signal pcReg: STD_LOGIC_VECTOR(7 downto 0);
begin
process(clk) begin
if clk'event and clk = '1' then
if reset = '1' then
pcReg <= "00000000";
elsif ld = '1' then
pcReg <= dBus;
elsif inc = '1' then
pcReg <= pcReg + "00000001";
end if;
end if;
end process;
aBus <= pcReg when en_A = '1' else "ZZZZZZZZ";
end pcArch;
6、 存储器RAM
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity ram is
port (
r_w, en, reset: in STD_LOGIC;
aBus: in STD_LOGIC_VECTOR(7 downto 0); ----数据总线输入
dBus: inout STD_LOGIC_VECTOR(7 downto 0)
);
end ram;
architecture ramArch of ram is
type ram_typ is array(0 to 63) of STD_LOGIC_VECTOR(7 downto 0);
signal ram: ram_typ;
begin
process(
en, reset, r_w, aBus, dBus
) begin
if reset = '1' then
ram(0) <= x"14";
ram(1) <= x"30";
ram(2) <= x"25";
ram(3) <= x"15";
ram(4) <= x"46";
ram(5) <= x"31";
ram(6) <= x"55";
ram(7) <= x"06";
ram(8) <= x"01";
elsif r_w = '0' then
ram(conv_integer(unsigned(aBus))) <= dBus;
end if;
end process;
dBus <= ram(conv_integer(unsigned(aBus)))
when reset = '0' and en = '1' and r_w = '1' else
"ZZZZZZZZ";
end ramArch;
7、 由6大模块组成模型机(top_level)
library IEEE;
use IEEE.std_logic_1164.all;
entity top_level is ----声明实体外部接口
port (
clk, reset:
in STD_LOGIC;
abusX: out STD_LOGIC_VECTOR(7 downto 0); --数据总线输出
dbusX: out STD_LOGIC_VECTOR(7 downto 0);
mem_enDX, mem_rwX:
out STD_LOGIC;
pc_enAX, pc_ldX, pc_incX:
out STD_LOGIC;
ir_enAX, ir_enDX, ir_ldX:
out STD_LOGIC;
acc_enDX, acc_ldX, acc_selAluX:
out STD_LOGIC;
acc_QX: out STD_LOGIC_VECTOR(7 downto 0);
alu_accZX: out STD_LOGIC;
alu_opX: out STD_LOGIC_VECTOR(2 downto 0)
);
end top_level;
architecture topArch of top_level is
component program_counter
port (
clk, en_A, ld, inc, reset: in STD_LOGIC;
aBus: out STD_LOGIC_VECTOR(7 downto 0);
dBus: in STD_LOGIC_VECTOR(7 downto 0)
);
end component;
component instruction_register
port (
clk, en_A, en_D, ld, reset: in STD_LOGIC;
aBus: out STD_LOGIC_VECTOR(7 downto 0);
dBus: inout STD_LOGIC_VECTOR(7 downto 0);
load, store, add, sub,mul,div,neg,andd,orr,nott, halt, branch: out STD_LOGIC
);
end component;
component accumulator
port (
clk, en_D, ld, selAlu, reset: in STD_LOGIC;
aluD: in STD_LOGIC_VECTOR(7 downto 0);
dBus: inout STD_LOGIC_VECTOR(7 downto 0);
q: out STD_LOGIC_VECTOR(7 downto 0)
);
end component;
component alu
port (
op: in STD_LOGIC_VECTOR(2 downto 0);
accD: in STD_LOGIC_VECTOR(7 downto 0);
dBus: in STD_LOGIC_VECTOR(7 downto 0);
result: out STD_LOGIC_VECTOR(7 downto 0);
accZ: out STD_LOGIC
);
end component;
component ram
port (
r_w, en, reset: in STD_LOGIC;
aBus: in STD_LOGIC_VECTOR(7 downto 0);
dBus: inout STD_LOGIC_VECTOR(7 downto 0)
);
end component;
component controller
port (
clk, reset: in STD_LOGIC;
mem_enD, mem_rw: out STD_LOGIC;
pc_enA, pc_ld, pc_inc: out STD_LOGIC;
ir_enA, ir_enD, ir_ld: out STD_LOGIC;
ir_load, ir_store, ir_add: in STD_LOGIC;
ir_sub, ir_mul, ir_div: in STD_LOGIC;
ir_and, ir_or, ir_not: in STD_LOGIC;
ir_neg, ir_halt, ir_branch: in STD_LOGIC;
acc_enD, acc_ld, acc_selAlu: out STD_LOGIC;
alu_op: out STD_LOGIC_VECTOR(2 downto 0)
);
end component;
signal abus: STD_LOGIC_VECTOR(7 downto 0);
signal dbus: STD_LOGIC_VECTOR(7 downto 0);
signal mem_enD, mem_rw: STD_LOGIC;
signal pc_enA, pc_ld, pc_inc: STD_LOGIC;
signal ir_enA, ir_enD, ir_ld: STD_LOGIC;
signal ir_load, ir_store, ir_add: STD_LOGIC;
signal ir_sub, ir_mul, ir_div: STD_LOGIC;
signal ir_and, ir_or, ir_not: STD_LOGIC;
signal ir_negate, ir_halt, ir_branch: STD_LOGIC;
signal acc_enD, acc_ld, acc_selAlu: STD_LOGIC;
signal acc_Q: STD_LOGIC_VECTOR(7 downto 0);
signal alu_op: STD_LOGIC_VECTOR(2 downto 0);
signal alu_accZ: STD_LOGIC;
signal alu_result: STD_LOGIC_VECTOR(7 downto 0);
begin
pc: program_counter port map(clk, pc_enA, pc_ld, pc_inc, reset, abus, dbus);
ir: instruction_register port map(clk, ir_enA, ir_enD, ir_ld, reset, abus,dbus,ir_load,ir_store,ir_add,ir_sub,ir_mul,ir_div,ir_and,ir_or,ir_not,ir_negate, ir_halt, ir_branch );
acc: accumulator port map(clk, acc_enD, acc_ld, acc_selAlu, reset, alu_result, dbus, acc_Q);
aluu: alu port map(alu_op, acc_Q, dbus, alu_result, alu_accZ);
mem: ram port map(mem_rw, mem_enD, reset, abus, dbus);
ctl: controller port map (
clk, reset, mem_enD, mem_rw, pc_enA, pc_ld, pc_inc,
ir_enA, ir_enD, ir_ld, ir_load, ir_store, ir_add,ir_sub,
ir_mul,ir_div,ir_and,ir_or,ir_not,
ir_negate, ir_halt, ir_branch,acc_enD,
acc_ld, acc_selAlu, alu_op
);
abusX <= abus;
dbusX <= dbus;
mem_enDX <= mem_enD;
mem_rwX <= mem_rw;
pc_enAX <= pc_enA;
pc_ldX <= pc_ld;
pc_incX <= pc_inc;
ir_enAX <= ir_enA;
ir_enDX <= ir_enD;
ir_ldX <= ir_ld;
acc_enDX <= acc_enD;
acc_ldX <= acc_ld;
acc_selAluX <= acc_selAlu;
acc_QX <= acc_Q;
alu_opX <= alu_op;
alu_accZX <= alu_accZ;
end topArch;