设 计 报 告
课程名称 计算机组成原理
课题名称 8位模型计算机的设计与实现
设 计 任 务 书
课程名称 计算机组成原理
课 题 8位模型计算机的设计与实现
一、设计内容与设计要求
1.设计内容
模型机是计算机的缩细模型,通过它可以理解计算机整机的结构及功能,理解CPU、存储器、中断控制器、接口的结构及实现逻辑和各部件之间的接口关系。本次课程设计的主要内容是利用Intel公司的EPF10K10LC84-4的内部可编程资源,设计一个8位模型计算机。本课程设计的主要目的是通过部件级的8位模型机的设计和调试,使学生掌握计算机工作中“时间—空间”概念的理解,从而清晰地建立计算机的整机概念,并培养学生分析和解决实际问题的能力,同时增强学生的动手能力。
2.设计要求:
按照如下要求,设计一台硬布线控制器的8位模型计算机,用VHDL 语言完成设计并调试成功。
(1)模型机的设计要求
总线 | 单总线结构 |
数据线、地址线 | 8位 |
指令系统 | 寻址方式 2种(立即数寻址、直接寻址) 类型 5种(算术运算、逻辑运算、数据传送、程序控制) 指令 12条(add、sub、mul、div、neg、and 、not、 or、load、store、branch、halt) |
运算器 | 单累加器结构, 8种运算 |
控制器 | 硬布线,微控制信号根据需要确定 |
(2)模型机的逻辑框图
图1 8 位模型计算机逻辑框图
3.成绩评定
设计方案是否合理;设计是否正确;调试结果;设计说明书的质量高低;答辩时回答问题情况;设计表现情况。
二、课题的主要功能
(1)融会贯通本课程各章节的内容,通过知识的综合运用,加深对计算机系统各功能部件的工作原理及相互联系的认识,加深计算机工作中“时间—空间”概念的理解,从而清晰地建立计算机的整机概念;
(2)学习设计和调试计算机的基本步骤和方法,提高使用Quartus等软件仿真工具和集成电路的基本技能;
(3)培养科学研究的独立工作能力,取得工程设计与组装调试的实践和经验。
三、设计方案
1、模型机的逻辑框图
以控制器为中心,首控制器从指令寄存器取得指令,编译指令,再输出微控制信号,控制ALU的运算,PC加一,并且从RAM中取出数据运算,运算后再把结果通过数据总线存到RAM,在指令寄存器读去下一条指令,依次循环。
2、模型机的数据格式和指令系统
(1)数据格式:
数据的长度为8位,数据采用补码格式,相对于十进制数范围是:-27<N<27-1
(2)指令系统:
由于本模型机机器字长只有8位二进制长度,故使用单字长指令和双字长指令。要求该模型机能执行10条指令,各指令格式及功能如下:
- LOAD D
格式
7 4 3 0
0000 | X |
功能:把X单元的内容装入累加器A中。
- STORE D
格式:
7 4 3 0
0001 | X |
功能:把累加器A中的内容存入X单元。
(3)ADD
格式
7 5 4 0
000 | X |
功能:把A的内容加上(X)的内容,结果放入A中。
(4)SUB
格式:
7 5 4 0
001 | D |
功能:把A的内容减去(X)的内容,结果放入A中
(5)AND
格式:
7 5 4 0
011 | D |
功能:把A的内容与(X)的内容做与运算,结果放入A中
(6)OR
格式:
7 5 4 0
100 | D |
功能:把A的内容与(X)的内容做或运算,结果放入A中
(7)NOT
格式:
7 5 4 0
101 | 为任意值 |
功能:把A的内容求反,结果放入A中
(8)NEG
格式:
7 4 3 0
0011 | 0000 |
功能:把A的内容求补,结果放入A中
(9)HALT
格式:
7 4 3 0
0011 | 0001 |
功能:停机
(10)BRANCH
格式:
7 4 3 0
0100 | D |
功能:(D)->PC
3、模型机的寻址方式
模型主要实现的寻址方式为立即寻址和直接寻址,立即寻址的操作数在指令中。直接寻址方式是一种基本的寻址方法,其特点是:在指令格式的地址字段中直接指出操作数在内存中的地址D。由于操作数的地址直接给出而不需要经过某种变换或运算,所以称这种寻址方式为直接寻址方式。它的操作如下图所示
采取直接寻址方式时,指令字中的形式地址D就是操作数的有效地址EA,即EA=D。因此通常把形式地址D又称为直接地址。直接寻址的表示形式为:
4、模型机的指令执行
5、模型机的微操作控制信号及其实现方法
四、主要功能的实现
(1) Load #x (将立即数存入A)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=0,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | MEN->DBUS | Mem_rw=1,mem_enD=1 |
DBUS->A | Acc_ld=1 |
(2) STORE D (将A中的数据存入内存单元D中)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | A->DBUS | Acc_enD=1 |
DBUS->(MEM) | (MEM)_RW=0 |
(3)ADD D (将两数相加运算)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | PC->ABUS | PC_enA=1 |
T2 | (MEM)->DBUS | MEM_RW=1,mem_end=1 |
A+(MEM)->A | Acc_enD=1,(MEM)_RW=1 Acc_ld=1,acc_selalu=1 Mem_end=1,alu_op=1 |
(4)SUB D (将两数相减)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | PC->ABUS | PC_enA=1 |
T2 | (MEM)->DBUS | MEM_RW=1 |
A-(MEM)->A | Acc_enD=1,(MEM)_RW=1 Acc_ld=1,acc_selalu=1 Mem_end=1,alu_op=1 |
(5)AND D (将两数做与运算)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | PC->ABUS | PC_enA=1 |
T2 | (MEM)->DBUS | MEM_RW=1 |
A and (MEM)->A | Alu_op=1,mem_end=1 Acc_enD=1,(MEM)_RW=1 Acc_ld=1,acc_selalu=1 |
(6)OR D (将两数做或运算)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | PC->ABUS | PC_enA=1 |
T2 | (MEM)->DBUS | MEM_RW=1 |
A or (MEM)->A | Alu_op=1,mem_end=1 Acc_enD=1,(MEM)_RW=1 Acc_ld=1,acc_selalu=1 |
(7)NEG D (将数求补)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | PC->ABUS | PC_enA=1 |
T2 | (MEM)->DBUS | MEM_RW=1 |
0- M(D)->A | Alu_op=1,mem_end=1 (MEM)_RW=1 Acc_ld=1,acc_selalu=1 |
(8)NOT D (对数求反)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | PC->ABUS | PC_enA=1 |
T2 | (MEM)->DBUS | MEM_RW=1 |
Not M(D)->A | Alu_op=1,mem_end=1 (MEM)_RW=1 Acc_ld=1,acc_selalu=1 |
(9) BRANCH D (无条件转移)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | Pc_inc=1 | |
T1 | (MEM)->PC | (MEM)_RW=1,mem_enD=1 PC_ld=1 |
(10)HALT (停机指令)
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC)->ABUS | PC_enA=1 |
(MEN)->IR | (MEM)_RW=1,IRENA=1 | |
(PC)+1->PC CLK PC+1 | PC_inc=1 | |
T1 | halt |
五、各功能部件的VHDL的实现及仿真波形
1、ALU运算器
该运算器由单累加器实现加,减,乘,除,取反,逻辑与,逻辑异或,逻辑或等8种算术运算和逻辑运算。OP指定了不同的运算代码。
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;
仿真波形如下:
当OP=001时,进行的是加法运算,当OP=010时,ACCD与DBUS进行减法运算
其中OP是一个选择控制信号,控制运算类型,比如当它为000时表示做求补运算。accD是一个来自累加器的8位数据,用于做各种运算。.dBus 是来自数据总线的8位数据也及来自主存储器,也是用于各种运算。.result 是表示输出结果的
所以该运算器可以用于8位数据的运算。
2、程序计数器
CLK表示电平信号当CLK为零电平时锁存本系统通过进程语句中的IF语句引入锁存器.但锁存信号为真时,便将输入值相与后锁入锁存器中,并保存到下一次锁存时钟信号的到来.
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;
仿真波形如下:
本模块主要由以下几个端口组成:
1.clk 是个时钟信号,它是上生沿有效。 2 .en_A 是地址总线请求信号,当它为1是表示允许,为0时表示忙。 3 .ld 是总线数据信号当有总线上有数据时为1。4. inc是pc寄存器加1的标志,当它为1时需加1。5.reset 是一个给内部信号直接置0的信号。 6.aBus 表示地址总线。 7.dBus 表示数据总线。
3、累加器
此设计为单累加器,其中SELALU是数据输入控制信号。
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
波形如下:
;
本模块主要由以下几个部分组成:
其中clk 同样是个时钟信号。en_D 是数据总线请求信号,当它为1是表示允许,为0时表示忙。ld 是总线数据信号当有总线上有数据时为1。selAlu 是一个运算器访问的标志,如果运算器有访问为1。reset 是一个给内部信号直接置0的信号。aluD来自运算器的数据。dBus 表示数据总线。q表示累加器中存储数据的当前结果。
4、IR寄存器
它用来保存当前正在执行的一条指令代码,其操作码字段的输出就是指令译码器的输入。
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, neg,sub,mul,and1,or1,not1, halt, branch: out STD_LOGIC );
end instruction_register;
architecture irArch of instruction_register is
signal irReg: STD_LOGIC_VECTOR(7 downto 0);
波形如下:
其中clk 同样是个时钟信号。en_A 是数据总线请求信号,当它为1是表示允许,为0时表示忙。en_D是数据总线请求信号,当它为1是表示允许,为0时表示忙。ld是总线数据信号当有总线上有数据时为1。reset 是一个给内部信号直接置0的信号。aBus表示地址总线。dBus表示数据总线。load以下的全是定义指令,是根据每条指令的前4为进行标志的。store 将累加器中的数据存到主存储器中的指令。add加法指令。neg求补指令。halt 停机指令。branch无条件转移指令。sub减法指令。andd与运算指令。orr 或运算指令。nott 非运算指令。
5、RAM静态储存器
该采用的是静态存储器,用单译码方式把二进制代码表示的地址转换成输出端的高电位,用来驱动相应的读写电路,以便选择所要访问的存储单元。
entity ram is
port( r_w,en,reset:inSTD_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;
波形如下:
本模块主要由以下几个端口组成:r_w是存储器的读写控制线,当它为0是写操作,1时是读操作。en总线请求信号,当它为1是表示允许,为0时表示忙。reset是一个给内部信号直接置0的信号。aBus表示地址总线。dBus表示数据总线。
6、硬布线控制器
本设计采用组合逻辑技术,是硬布线控制器。
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);
波形如图:
本模块主要由以下几个端口组成:clk 同样是个时钟信号。Reset是一个给内部信号直接置0的信号。mem_enD输出存储器的enD 信号。mem_rw 输出存储器的r_w 信号。pc_enA输出pc的enA信号。pc_ld输出pc的ld信号。ir_load输出 ir的load 信号。ir_store输出ir的store 信号。ir_add输出ir的add信号。ir_sub 输出ir的sub信号。ir_neg输出ir的neg信号。ir_and 输出ir的andd信号。ir_or输出 ir的orr信号。ir_not输出 ir的nott信号.ir_halt输出ir的halt信号。ir_branche 输出ir的branch信号。acc_enD输出累加器的enD信号。
acc_ld 输出累加器的ld信号。acc_selAlu输出累加器selAlu信号。alu_op输出运算器的op信号。
7、由六大模块组成的模型机
此程序是计算机初步模型,它调用了前面六大模块程序,从而把前面六大模块有机结合起来。形成一整体。
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(3 downto 0) );
end top_level;
波形如下:
六、实验结果分析说明
1、CPU电路图
2、ram中测试程序说明
ram中测试程序说明
序号 | 指令字 | 汇编指令 | 说明 |
0 | ram(0) <= x"14"; | STORE 4 | 把累加器acc的内容存入地址4的存储单元 |
1 | ram(1) <= x"30"; | SUB 0 | acc中的内容减去0号单元的内容结果放到acc中 |
2 | ram(2) <= x"25"; | ADD 5 | acc中的内容加上5号单元的内容结果放到acc中 |
3 | ram(3) <= x"15"; | STORE 5 | 把累加器acc的内容存入地址5的存储单元 |
4 | ram(4) <= x"00"; | LOAD 4 | 0号单元的值存入acc中 |
5 | ram(5) <= x"1D"; | SUB 1 | acc中的内容加上1号单元的内容结果放到acc中 |
6 | ram(6) <= x"55"; | DIV 5 | acc中的内容除以5号单元的内容结果放到acc中 |
7 | ram(7) <= x"06"; | LOAD 6 | 将6号单元的内容存储到acc中 |
8 | ram(8) <= x"01"; | LOAD 0 | 将1号单元的内容存储到acc中 |
3、测试程序,波形图及指令的对应关系分析,数据运算过程分析
(1)测试程序: 11+22-10
序号 | 指令字 | 汇编指令 | 说明 |
0 | ram(0) <= x"05"; | LOAD 5 | 5号单元的值存入acc中 |
1 | ram(1) <= x"26"; | ADD 6 | acc中的内容加上6号单元的内容结果放到acc中 |
2 | ram(2) <= x"37"; | SUB 7 | acc中的内容减去7号单元的内容结果放到acc中 |
3 | ram(3) <= x"18"; | STORE 8 | 把累加器acc的内容存入地址8的存储单元 |
4 | ram(4) <= x"A1"; | HALT | 停机 |
5 | ram(5) <= x"0B"; | LOAD B | B号单元的值存入acc中 |
6 | ram(6) <= x"16"; | STORE 6 | 把累加器acc的内容存入地址6的存储单元 |
7 | ram(7) <= x"0A"; | LOAD A | A号单元的值存入acc中 |
8 | ram(8) <= x"00"; | LOAD 0 | 0号单元的值存入acc中 |
(2)程序数据运算过程分析,波形图及逐条指令、逐个部件逐个数据变化的对应关系分析。
程序数据运算过程分析
指令1:LOAD 5
第一步: PC存储的地址为(0000,0000),该地址通过地址总线abus传入ram。
第二步:从ram读取PC的指令地址即0号单元,读取数据得到(0000,0101)05(H)
第三步:该指令 05(H)通过数据总线dbus传入指令寄存器IR中,
第四步:IR中,(0000,0101)指令,前四位(0000)为操作码,解析为LOAD操作,后四位(0101)为地址码,解析为从ram5号单元读取数据。
第五步:IR将地址码(0101)与(0000)拼凑为(0000,0101)并传入地址总线abus,同时将LOAD信号传给控制器CU。
第六步:取指令周期结束,PC+1,此时地址指令为(0000,0001),待取指令周期结束再传到abus.
第七步:控制器CU向ram发出读出命令,ram从地址总线abus取(0000,0101),读取ram的5号单元的内容(0000,1011)并传到数据总线dbus.
第八步:从数据总线dbus的(0000,0101)存入acc中,acc的值从00(H)变成0B(H)。
指令1 PC为1,从ram1号单元读取数据得到26(H),第一位表示操作码,第二位表示地址码,2为add操作,将acc中的值0B(H)加上6号单元的值16(H),结果为21(H)存入acc中,acc的值从0B(H)变成21(H),PC加一。
指令2 PC为2,从ram2号单元读取数据得到37(H),第一位表示操作码,第二位表示地址码,3为sub操作,将acc中的值21(H)减去7号单元的值0A(H),结果为17(H)存入acc中,acc的值从21(H)变成17(H),PC加一。
指令3 PC为3,从ram3号单元读取数据得到18(H),第一位表示操作码,第二位表示地址码,1为store操作,将acc中的值17(H)存到8号单元,acc的值还是17(H),8号单元的值从00(H)变成17(H),PC加一。、
指令4 PC为4,从ram4号单元读取数据得到A1(H),停机
(3)任选一条指令为例,必须结合指令周期各个阶段(fetch0、fetch1、add0、add1...)、测试波形、电路图、代码、指令系统设计具体说明,标注控制信号,地址,数据等信息的每一次流动、变化。
数据通路及微操作序列:
周期 | 执行的操作 | 对应的微程序操作 |
Fetch0 | (PC)->MAR READ M(MAR)->MDR | PCout,MARin mem_enDX=1,mem_rwx=1,pc_enAX=1 |
Fetch1 | (MDR)->IR (PC)+1->PC | MDRout,IRin PC_inc =1 |
ADD0 | (IR)->MAR Read M(MAR)->MDR M(MDR)->ALU | IRout,(ir_enA=1),MARin (MEM)_RW=1,IRENA=1mem_enDX=1 |
ADD1 | A+(MEN)->A | Acc_enD=1,(MEN)_RW=1 Acc_ld=1,acc_selalu=1 Mem_end=1,alu_op=1 |
fetch0:
1.(pc_enAX=1),PCout和MARin有效,完成PC经过CPU内部总线送到MAR的操作,记作(PC)->MAR
2.men_rwx=1,pc_enAX=1,通过控制总线向主存发出读命令,记作Read
3.mem_enDX=1,mem_rwx=1,pc_enAX=1存储器通过数据总线将MAR所指的单元的内容(指令)送至MDR,记作M(MAR)->MDR
代码:
dBus <= ram(conv_integer(unsigned(aBus)))
when reset = '0' and en = '1' and r_w = '1' else
"ZZZZZZZZ";
fetch1:
4.ir_ldx=1,MDRout和IRin有效,将MDR的内容送至指令寄存器IR,记作(MDR)→IR。至此,指令被从主存中 取出,其操作码字段开始控制CU
5.pc_enAX=1,pc_incX=1,使PC内容加1,记作(PC)+1→PC。
代码:
if reset = '1' then
irReg <= "00000000";
elsif ld = '1' then
irReg <= dBus;
elsif inc = '1' then
pcReg <= pcReg + "00000001";
add0:
1.ir_enAx=1,ir_ldx=1,MARin有效,IR将解析出的地址码前四位(0110)与后四位(0000)进行拼接,得到 (0000,0110)送至abus.记作(IR)→MAR
2.mem_rwx=1,控制单元向主存发起读令,记作Read。
3。mem_endx=1,ram通过MAR传来的地址找到并输出对应单元中的数据到MDR,记作M(MAR)→MDR
4.MDR通过数据总线将数据传到ALU。
代码
instruction_register.vhd中:
aBus <= "0000" & irReg(3 downto 0) when en_A = '1' else
"ZZZZZZZZ";
add1:
1.alu_opx=010,控制器通过输出alu_op将“ADD”指令传到alu的输入op中。通过ALU将ACC与取出的数相 加,将结果送到ACC。
六、课程设计的收获及体会
通过这次课题设计的经历,我对VHDL语言有了更为深刻的理解。我深切体会到实验的重要性,并认识到作为计算机系的本科学生,仅仅依赖课本知识是远远不够的。因此,我们需要不断拓宽学习领域,丰富自身的知识体系。现在我深刻领悟到,要真正掌握实验技能,仅仅阅读书籍是不足够的,我们还需要更多地编写代码、运行程序。面对错误时,不必畏惧,因为在实际操作中修正错误反而能带来一种成就感,让我们感受到成功的甜美。
在实验过程中,我发现VHDL语言的形式和描述风格与常见的计算机高级语言如C语言或C++颇为相似。VHDL语言允许我们将一个工程设计或设计实体(如元件、电路模块或系统)划分为外部和内部两部分。一旦我们为设计实体定义了外部接口,并完成了内部开发,其他设计就可以直接调用这个实体。此外,VHDL语言还具有强大的行为描述能力,并提供了丰富的仿真语句和库函数,使我们在设计尚未完成时就能验证系统功能的可行性,随时对设计进行仿真模拟。
我还体验到了VHDL语言在设计描述方面的相对独立性。作为设计者,我们无需深入了解硬件的具体结构,也不必关注最终设计实现的物理目标。这种独立性使得我们可以进行更为灵活和独立的设计。另外,VHDL语言支持类属描述语句和子程序调用功能,这意味着对于已经完成的设计,我们只需改变类属参量或函数,就能轻松地调整设计的规模和结构。
最后,我认识到VHDL语言必须与实际电路系统的工作方式相适应,采用并行和顺序等多种语句方式来描述在同一时刻可能发生的所有事件。这要求我们摆脱一维的思维模式,以多维并发的思路来完成电路设计。功能仿真仅针对VHDL描述的逻辑功能进行测试模拟,以验证其实现的功能是否满足原始设计要求,而仿真过程并不涉及具体器件的硬件特性。
虽然这次设计并不完美,存在诸多不足,但我从中汲取了宝贵的经验教训。我期待着在未来的学习生活中,能够继续加强练习,努力提升自己的专业技能,不断完善自己的设计能力。
七、参考资料
[1] 陈华光. 计算机组成原理[M].北京:机械工业出版社,2004
[2] 侯伯亨等. VHDL硬件描述语言与数字逻辑电路设计(修订版)[M],西安:西安电子科技大学出版社,1999
[3] 杨东旭等.计算机组成原理实用教程[M]. 北京:清华大学出版社, 2001.
附录:8位模型机的VHDL程序
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆***************** 源 程 序 ********************
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;
- 算术运算器 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(3 downto 0)*dBUs(3 downto 0) when op="0110" else
accD(3 downto 0)*(not dBus(3 downto 0)) 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(3 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 <= "0001" when state = add0 or state = add1
else "0101" when state = sub0 or state = sub1
else "0110" when state = mul0 or state = mul1
else "0111" when state = div0 or state = div1
else "0000" when state = negate0 or state = negate1
else "1010" when state = and0 or state = and1
else "1100" when state = or0 or state = or1
else "1111" 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;
- 程序计数器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;
dBus: in STD_LOGIC_VECTOR(7 downto 0); --数据总线输入
aBus: out 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;
- 存储器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"05";
ram(1) <= x"26";
ram(2) <= x"37";
ram(3) <= x"18";
ram(4) <= x"A1";
ram(5) <= x"0B";
ram(6) <= x"16";
ram(7) <= x"0A";
ram(8) <= x"00";
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(3 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(3 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(3 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(3 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;