仅供参考,有一些文字描述有误且有一些多余,没有修改
代码已修改,过测试用例
波形图按要求要用红线分隔,标出不同时期
具体一条指令为例,每次变化要标红电路图的自变量与因变量
1实验目标/做什么
在Quartus 软件上用VHDL实现8位12指令硬布线CPU
1.1文字描述,必要时画框图辅助说明
文字描述:
8位12指令硬布线CPU是一种基于硬布线设计的中央处理器,具有8位数据总线和12种指令。
8位12指令硬布线CPU框图
无
1.2实验原理
以控制器为中心,首控制器从指令寄存器取得指令,编译指令,再输出微控制信号,控制ALU的运算,PC加一,并且从RAM中取出数据运算,运算后再把结果通过数据总线存到RAM,在指令寄存器读去下一条指令,依次循环。
实验结果分析说明
1、CPU电路图
无
2、ram中测试程序说明
序号 | 指令字 | 汇编指令 | 说明 |
0 | ram(0) <= x"14"; | STORE 4 | 把累加器A中的内容存入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 | 把累加器A中的内容存入5单元 |
4 | ram(4) <= x"46"; | MUL 6 | ACC中数据乘上5号单元数据结果放到ACC中 |
5 | ram(5) <= x"31"; | SUB 1 | ACC中数据减去1号单元数据结果放到ACC中 |
6 | ram(6) <= x"55"; | DIV 5 | ACC中数据除以5号单元数据结果放到ACC中 |
7 | ram(7) <= x"06"; | LOAD 6 | 把6单元的内容装入累加器A中 |
8 | ram(8) <= x"01"; | halt | 终止程序 |
3、测试程序,波形图及指令的对应关系分析,数据运算过程分析
(1)测试程序: 11+22-10
序号 | 指令字 | 汇编指令 | 说明 |
0 | ram(0) <=x"05" | LOAD 5 | 把5单元的内容装入累加器A中 |
1 | ram(1) <=x"26" | ADD 6 | ACC中数据加上6号单元数据结果放到ACC中 |
2 | ram(2) <=x"37" | SUB 7 | ACC中数据减去7号数据结果放到ACC中 |
3 | ram(3)<=x"13" | STORE 3 | 把累加器A中的内容存入3单元 |
4 | ram(4)<="10100001" | HALT | 终止程序 |
5 | ram(5)<=x"11" | 原始数据 | |
6 | ram(6)<=x"22" | 原始数据 | |
7 | ram(7)<=x"10" | 原始数据 | |
(2)程序数据运算过程分析,波形图及逐条指令、逐个部件逐个数据变化的对应关系分析。
波形图
需要用红线分隔,标出不同时期
LOAD 5 |
ADD 6 |
SUB 7 |
STORE 3 |
HALT |
因为只出现过MAR,MDR,在下面的地址总线ABUS和数据总线DBUS,要修改为MAR和MDR,该版本未修改
逐条指令运算过程
第一条指令 LOAD 5 : 从指定内存地址('00000101')加载数据到累加器。
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | (IR) → MAR | ir_enAX=1 |
T2 | MEM(MAR) → MDR | mem_rw=1,mem_enD=1 |
Fetch0:(PC) → MAR,M(MAR) → MDR
Fetch1: (MDR) → IR, (PC) + 1 → PC
Load0:(IR) → MAR,M(MAR) → MDR
Load1:(IR) → MAR,M(MAR) → MDR,MDR → ACC
取指周期: 从内存地址'00000000'中取出指令'00000101'(LOAD 5),将其存入指令寄存器IR,并将程序计数器PC递增到'00000001'。
执行周期: 根据指令寄存器IR中的指令,将内存地址'00000101'的内容('00010001')加载到累加器ACC。
第二条指令 ADD 6 :将累加器中的数据('00010001')与指定内存地址的数据('00100010')相加,结果存回累加器。
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | (IR) → MAR | ir_enAX=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
T2 | ACC + MDR → ACC | alu_op=0001,Acc_ld=1,acc_selalu=1 |
Fetch0:(PC) → MAR,M(MAR) → MDR
Fetch1: (MDR) → IR, (PC) + 1 → PC
ADD0:(IR) → MAR,M(MAR) → MDR
ADD1:(IR) → MAR,M(MAR) → MDR,ACC + MDR→ ACC
取指周期: 从内存地址'00000001'中取出指令'00100110'(ADD 6),将其存入指令寄存器IR,并将程序计数器PC递增到'00000010'。
执行周期: 根据指令寄存器IR中的指令,将内存地址'00000110'的内容('00010010')与累加器ACC中的内容('00010001')相加,结果存回累加器ACC。
第三条指令 SUB 7:将累加器中的数据('00110011')与指定内存地址的数据('00010000')相减,结果存回累加器。
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | (IR) → MAR | ir_enAX=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
T2 | ACC - MDR → ACC | alu_op=0101,Acc_ld=1,acc_selalu=1 |
Fetch0:(PC) → MAR,M(MAR) → MDR
Fetch1: (MDR) → IR, (PC) + 1 → PC
SUB0:(IR) → MAR,M(MAR) → MDR
SUB1:(IR) → MAR,M(MAR) → MDR,ACC - MDR→ ACC
取指周期: 从内存地址'00000010'中取出指令'00110111'(SUB 7),将其存入指令寄存器IR,并将程序计数器PC递增到'00000011'。
执行周期: 根据指令寄存器IR中的指令,将累加器ACC中的内容('00110011')与内存地址'00000111'的内容('00010000')相减,结果存回累加器ACC。
第四条指令 STORE 3:将累加器中的数据('00100011')存储到指定内存地址('00000011')。
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | (IR) → MAR | ir_enAX=1 |
ACC → MDR | Acc_enD=1 | |
T2 | MDR → M(MAR) | mem_rw=0 |
Fetch0:(PC) → MAR,M(MAR) → MDR
Fetch1: (MDR) → IR, (PC) + 1 → PC
STORE0:(IR) → MAR,ACC → MDR
STORE1:MDR → M(MAR)
取指周期:从内存地址'00000011'中取出指令'00010011'(STORE 3),将其存入指令寄存器IR,并将程序计数器PC递增到'00000100'。
执行周期:根据指令寄存器IR中的指令,将累加器ACC中的内容('00100011')存储到内存地址'00000011'。
第五条指令 HALT:停止CPU的执行。
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(ABUS) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | 停机 | halt <= '1' when irReg = "10100001" |
Fetch0:(PC) → MAR,M(MAR) → MDR
Fetch1: (MDR) → IR, (PC) + 1 → PC
HALT
取指周期: 从内存地址'00000100'中取出指令'10100001'(HALT),将其存入指令寄存器IR,并将程序计数器PC递增到'00000101'。
执行周期: 根据指令寄存器IR中的指令,CPU停止执行指令。
(3)以任一一条指令为例,必须结合指令周期各个阶段(fetch0、fetch1、add0、add1...)、测试波形、电路图、代码、指令系统设计具体说明,标注控制信号,地址,数据等信息的每一次流动、变化。
以 LOAD 5 指令为例,结合指令周期各个阶段(fetch0、fetch1、add0、add1...)、测试波形、电路图、代码、指令系统设计具体说明,标注控制信号,地址,数据等信息的每一次流动、变化。
在其(LOAD 5 指令)下面有剩余指令的文字描述
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | (IR) → MAR | ir_enAX=1 |
T2 | MEM(MAR) → MDR | mem_rw=1,mem_enD=1 |
取指周期
Fetch0:(PC) → MAR,M(MAR) → MDR
(PC) → MAR
第一步:PC将指令地址通过地址总线给MAR
每当PC的值放到地址总线时,pc_enA为1,即标志PC访问MAR,即aBus <= pcReg
PC将指令地址直接传给RAM
ABUS中,若传输的为pc中的值,则为递增从0000到1001(9)的数
此时地址总线数值为0000,0000,MAR数值为0000,0000
M(MAR) → MDR
第二步:将MAR所指的内存单元经过数据总线给MDR
mem_rw=1,mem_enD=1,即标志将MAR所指的内存单元经过数据总线给MDR,即dBus <= ram(conv_integer(unsigned(aBus)))
此时地址总线的数值为0000,0000,即RAM中0号存储单元对应的数据;
数据总线的数值为0000,0101,MDR数值为0000,0101
Fetch1: (MDR) → IR, (PC) + 1 → PC
(MDR) → IR
第三步:将MDR中的内容给IR
MAR数值与MDR数值不变
此时mem_rw=1,mem_enD=1,ir_ldx为1标志IR被写入数据,即irReg <= dBus;
IR的寄存器数值为0000,0101
(PC) + 1 → PC
第四步:形成下一条指令
PC_inc=1,即标志pc移动到下一位,即PC+1
此时,PC寄存器数据数值为0000,0001
执行周期
Load0:(IR) → MAR,M(MAR) → MDR
(IR) → MAR
第五步:将指令的操作码部分给CU
ir_enAX = '1',标志着CU用IR的后4位(4到7位)作为操作码,进行译码,
即aBus <= "0000" & irReg(3 downto 0)
IR的寄存器数值为0000,0101,指令为0000,0101
操作码为0000,标志着执行LOAD指令
地址总线数值为0000,0101,MAR数值为0000,0101
M(MAR) → MDR
第六步:将MAR所指的内存单元经过数据总线给MDR
reset = '0',mem_rw=1,mem_enD=1,即标志将MAR所指的内存单元经过数据总线给MDR,即dBus <= ram(conv_integer(unsigned(aBus)))
此时地址总线的数值为0000,0101,即RAM中5号存储单元对应的数据;
数据总线的数值为0001,0001
MDR数值为0001,0001
Load1:(IR) → MAR,M(MAR) → MDR,MDR → ACC
(IR) → MAR,M(MAR) → MDR没有数值变化
电路图如上面的两个图一样
MDR → ACC
第七步:将MDR的数据加载到ACC寄存器中
Acc_ld=1,selAlu = '0',标志着将MDR的数据加载到ACC寄存器中,即DBUS->ACC
accReg <= dBus;
MDR数值为0001,0001,
在执行周期的最后,上升沿时,ACC寄存器的数据数值改为0001,0001
ADD 6
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | (IR) → MAR | ir_enAX=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
T2 | ACC + MDR → ACC | alu_op=0001,Acc_ld=1,acc_selalu=1 |
取指周期
Fetch0:(PC) → MAR,M(MAR) → MDR
(PC) → MAR
第一步:PC将指令地址通过地址总线给MAR
每当PC的值放到地址总线时,pc_enA为1,即标志PC访问MAR,即aBus <= pcReg
PC将指令地址直接传给RAM
ABUS中,若传输的为pc中的值,则为递增从0000到1001(9)的数
此时地址总线数值为0000,0001
MAR数值为0000,0001
M(MAR) → MDR
第二步:将MAR所指的内存单元经过数据总线给MDR
mem_rw=1,mem_enD=1,即标志将MAR所指的内存单元经过数据总线给MDR,即dBus <= ram(conv_integer(unsigned(aBus)))
此时地址总线的数值为0000,0001,即RAM中1号存储单元对应的数据;
数据总线的数值为0010,0110
MDR数值为0010,0110
Fetch1: (MDR) → IR, (PC) + 1 → PC
(MDR) → IR
第三步:将MDR中的内容给IR
MAR数值与MDR数值不变
此时mem_rw=1,mem_enD=1,ir_ldx为1,标志IR被写入数据,即irReg <= dBus;
IR的寄存器数值为0010,0110
(PC) + 1 → PC
第四步:形成下一条指令
PC_inc=1,即标志pc移动到下一位,即PC+1
此时,PC寄存器数据数值为0000,0010
执行周期
ADD0:(IR) → MAR,M(MAR) → MDR
(IR) → MAR
第五步:将指令的操作码部分给CU
ir_enAX = '1',标志着CU用IR的后4位(4到7位)作为操作码,进行译码,
即aBus <= "0000" & irReg(3 downto 0)
IR的寄存器数值为0010,0110
指令为0010,0110
操作码为0010,标志着执行ADD指令
地址总线数值为0000,0110
MAR数值为0000,0110
M(MAR) → MDR
第六步:将MAR所指的内存单元经过数据总线给MDR
mem_rw=1,mem_enD=1,即标志将MAR所指的内存单元经过数据总线给MDR,即dBus <= ram(conv_integer(unsigned(aBus)))
此时地址总线的数值为0000,0110,,即RAM中6号存储单元对应的数据;
数据总线的数值为0010,0010
MDR数值为0010,0010
ADD1:(IR) → MAR,M(MAR) → MDR,ACC + MDR→ ACC
(IR) → MAR,M(MAR) → MDR没有数值变化
ACC + MDR → ACC
第七步:将MDR的数据与ACC寄存器的数据累加,放到ACC寄存器中
alu_op="0001",Acc_ld=1,acc_selalu=1,标志着将MDR的数据与ACC寄存器的数据累加,放到ACC寄存器中,即result <=accD + dBus when op ="0001",accReg <= aluD;
ACC寄存器放的数据原来数值为0001,0001
MDR数值为0010,0010
在执行周期的最后,上升沿时,ACC寄存器的数值改为0011,0011
SUB 7
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | (IR) → MAR | ir_enAX=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
T2 | ACC - MDR → ACC | alu_op=0101,Acc_ld=1,acc_selalu=1 |
取指周期
Fetch0:(PC) → MAR,M(MAR) → MDR
(PC) → MAR
第一步:PC将指令地址通过地址总线给MAR
每当PC的值放到地址总线时,pc_enA为1,即标志PC访问MAR,即aBus <= pcReg
PC将指令地址直接传给RAM
ABUS中,若传输的为pc中的值,则为递增从0000到1001(9)的数
此时地址总线数值为0000,0010
MAR数值为0000,0010
M(MAR) → MDR
第二步:将MAR所指的内存单元经过数据总线给MDR
mem_rw=1,mem_enD=1,即标志将MAR所指的内存单元经过数据总线给MDR,即dBus <= ram(conv_integer(unsigned(aBus)))
此时地址总线的数值为0000,0010,即RAM中2号存储单元对应的数据;
数据总线的数值为0011,0111,MDR数值为0011,0111
Fetch1: (MDR) → IR, (PC) + 1 → PC
(MDR) → IR
第三步:将MDR中的内容给IR
MAR数值与MDR数值不变
此时mem_rw=1,mem_enD=1,ir_ldx为1,标志IR被写入数据,即irReg <= dBus;
IR的寄存器数值为0011,0111
(PC) + 1 → PC
第四步:形成下一条指令
PC_inc=1,即标志pc移动到下一位,即PC+1
此时,PC寄存器数据数值为0000,0011
执行周期
SUB0:(IR) → MAR,M(MAR) → MDR
(IR) → MAR
第五步:将指令的操作码部分给CU
ir_enAX = '1',标志着CU用IR的后4位(4到7位)作为操作码,进行译码,
即aBus <= "0000" & irReg(3 downto 0)
IR的寄存器数值为0011,0111
指令为0011,0111
操作码为0011,标志着执行SUB指令
地址总线数值为0000,0111
MAR数值为0000,0111
M(MAR) → MDR
第六步:将MAR所指的内存单元经过数据总线给MDR
mem_rw=1,mem_enD=1,即标志将MAR所指的内存单元经过数据总线给MDR,即dBus <= ram(conv_integer(unsigned(aBus)))
此时地址总线的数值为0000,0111,,即RAM中7号存储单元对应的数据;
数据总线的数值为0001,0000
MDR数值为0001,0000
SUB1:(IR) → MAR,M(MAR) → MDR,ACC - MDR→ ACC
(IR) → MAR,M(MAR) → MDR没有数值变化
ACC - MDR→ ACC
第七步:将ACC寄存器的数据减去MDR的数据,放到ACC寄存器中
alu_op="0101",Acc_ld=1,acc_selalu=1,标志着将MDR的数据与ACC寄存器的数据累加,放到ACC寄存器中,即result <=accD-dBus when op="0101",accReg <= aluD;
ACC寄存器放的数据原来数值为0011,0011
MDR数值为0001,0000
在执行周期的最后,上升沿时,ACC寄存器的数值改为0010,0011
STORE 3
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(MAR) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | (IR) → MAR | ir_enAX=1 |
ACC → MDR | Acc_enD=1 | |
T2 | MDR → M(MAR) | mem_rw=0 |
取指周期
Fetch0:(PC) → MAR,M(MAR) → MDR
(PC) → MAR
第一步:PC将指令地址通过地址总线给MAR
每当PC的值放到地址总线时,pc_enA为1,即标志PC访问MAR,即aBus <= pcReg
PC将指令地址直接传给RAM
ABUS中,若传输的为pc中的值,则为递增从0000到1001(9)的数
此时地址总线数值为0000,0011
MAR数值为0000,0011
M(MAR) → MDR
第二步:将MAR所指的内存单元经过数据总线给MDR
mem_rw=1,mem_enD=1,即标志将MAR所指的内存单元经过数据总线给MDR,即dBus <= ram(conv_integer(unsigned(aBus)))
此时地址总线的数值为0000,0011,即RAM中3号存储单元对应的数据;
数据总线的数值为0001,0011
MDR数值为0001,0011
Fetch1: (MDR) → IR, (PC) + 1 → PC
(MDR) → IR
第三步:将MDR中的内容给IR
MAR数值与MDR数值不变
此时mem_rw=1,mem_enD=1,ir_ldx为1,标志IR被写入数据,即irReg <= dBus;
IR的寄存器数值为0001,0011
(PC) + 1 → PC
第四步:形成下一条指令
PC_inc=1,即标志pc移动到下一位,即PC+1
此时,PC寄存器数据数值为0000,0100
执行周期
STORE0:(IR) → MAR,ACC → MDR
(IR) → MAR
第五步:将指令的操作码部分给CU
ir_enAX = '1',标志着CU用IR的后4位(4到7位)作为操作码,进行译码,
即aBus <= "0000" & irReg(3 downto 0)
IR的寄存器数值为0001,0011
指令为0001,0011
操作码为0001,标志着执行STORE指令
地址总线数值为0000,0011
MAR数值为0000,0011
ACC → MDR
第六步:将ACC寄存器的数据经过数据总线给MDR
Acc_enD=1,,即标志将ACC寄存器的数据经过数据总线给MDR,即dBus <= accReg when en_D = '1'
此时ACC寄存器的数据数值为0010,0011,
数据总线的数值为0010,0011,MDR数值为0010,0011
STORE1:MDR → M(MAR)
MDR → M(MAR)
第七步:将MDR的数据存到存储器对应的存储单元中
mem_rw <= '0',标志着写入操作,将MDR的数据存到存储器对应的3号存储单元中,即ram(conv_integer(unsigned(aBus))) <= dBus;
地址总线数值为0000,0011,MAR数值为0000,0011
dBus数据数值为0010,0011,MDR数值为0010,0011
MAR对应的3号存储单元存放数据修改为0010,0011
HALT
周期 | 所执行的操作 | 对应的微程序操作 |
T0 | (PC) → MAR | PC_enA=1 |
MEM(ABUS) → MDR | mem_rw=1,mem_enD=1 | |
MDR → IR | ir_ld=1 | |
(PC) + 1 → PC | PC_inc=1 | |
T1 | 停机 | halt <= '1' when irReg = "10100001" |
取指周期
Fetch0:(PC) → MAR,M(MAR) → MDR
(PC) → MAR
第一步:PC将指令地址通过地址总线给MAR
每当PC的值放到地址总线时,pc_enA为1,即标志PC访问MAR,即aBus <= pcReg
PC将指令地址直接传给RAM
ABUS中,若传输的为pc中的值,则为递增从0000到1001(9)的数
此时地址总线数值为0000,0100
MAR数值为0000,0100
M(MAR) → MDR
第二步:将MAR所指的内存单元经过数据总线给MDR
mem_rw=1,mem_enD=1,即标志将MAR所指的内存单元经过数据总线给MDR,即dBus <= ram(conv_integer(unsigned(aBus)))
此时地址总线的数值为0000,0100,即RAM中4号存储单元对应的数据;
数据总线的数值为"10100001",MDR数值为"10100001",十六进制表现为A1
Fetch1: (MDR) → IR, (PC) + 1 → PC
(MDR) → IR
第三步:将MDR中的内容给IR
MAR数值与MDR数值不变
此时mem_rw=1,mem_enD=1,ir_ldx为1,标志IR被写入数据,即irReg <= dBus;
IR的寄存器数值为"10100001"
(PC) + 1 → PC
第四步:形成下一条指令
PC_inc=1,即标志pc移动到下一位,即PC+1
此时,PC寄存器数据数值为'0000,0101'
执行周期
HALT
停机
ram(4) <= "10100001";
halt <= '1' when irReg = "10100001" else '0';
when halt => state <= halt;
测试波形
包括且不限类似讲课于PPT中的:
⑴取指周期
取指周期完成的微操作序列是公共的操作,与具体指令无关。
① PCout和MARin有效,完成PC经CPU内部总线送至MAR的操作,记作(PC)→MAR;
代码
附录: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;
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(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 ---
else "1000"; --查无此人
--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 = "10100001" 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) <= "10100001";
ram(0) <= x"05";
ram(1) <= x"26";
ram(2) <= x"37";
ram(3) <= x"13";
ram(4) <= "10100001";
ram(5) <= x"11";
ram(6) <= x"22";
ram(7) <= x"10";
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;