基于excel的16位CPU
简介
使用excel实现的简单16位cpu模拟,用于学习cpu原理。基于原上游库修改,重新设计了所有模块,并设计了基于sheet的汇编指令编辑/编译表格。
地址:GitHub - Jzice/excelCPU at new
组成
包含:
cpu:在excel sheet中实现的cpu,包含了
程序计数器(PC)
、取指单元(Fetch Unit)
、控制单元(Control Unit)
、MUX1/2(多路复用器)
、算逻单元(ALU)
、寄存器组(Registers)
和内存管理单元(MMU0)
组成。RAM:基于excel sheet的128KB(128x512x16b=128KB)内存。
DISPLAY: 基于excel sheet的(128x96)点阵显示器,每个像素点可显示16种色彩。
指令集:用于excel cpu的指令集,总共包含了27条excel cpu汇编指令,指令长度包括16bit/32bit两种。
ROM:用于存放编译后的二进制excel asm,并可加载到RAM中进行执行。
excel汇编代码编译表格:基于excel 表格实现的asm语句编辑、编译sheet。
Excel相关设置
- excel需开启迭代计算,并将计算次数设置为1,以支持迭代计算。
运行步骤
将
POWER
开关设为0,关闭电源在asm中编写汇编代码
先将
RESET
开关设为1,将寄存器和RAM中的相关数据清零;再将RESET
设为0,关闭清零;将
LOAD_ROM
先设为1,再设为0,以便将ROM
sheet中的数据载入到RAM
中;重新将
POWER
设为1,启动电源;依次按
F9
,通过触发CLOCK
驱动各部件运行。
CPU
开关
为了控制cpu的执行,在CPUsheet上方设置了几个单元格,用于设置cpu的运行状态和参数,如图所示
主要包括:
电源开关(POWER)
: 取值0/1, 用于指定是否通电。1是CPU才会执行,0时停止运行;时钟(CLOCK)
: 交替输出时钟脉冲0/1,用于驱动CPU运行,当POWER
为1时,按F9
可交替产生0/1;时钟计数(TICK)
:记录一次加电后总共执行了多少个时钟周期(COLCK由1->0->1);重置按钮(RESET)
: 1时,将内存(RAM)
中的所有数值清零, 0时无作用;加载ROM(LOAD_ROM)
: 1时,将ROM
sheet中的数据加载到RAM
中;0时无作用;PC启动值(BOOT_PC)
: 加电后,PC的初始值;字长(WORD_SIZE)
: CPU中的字长,16。
程序计数器(Program Counter)
程序计数器(Program Counter)
用于产生CPU下一条要访问的指令在内存中的地址。
下一个指令地址的产生主要有2种:
顺序指令,下一条指令地址为上一条指令地址按上一条指令类型的长度+2或+4
跳转指令,下一条指令地址为指令跳转的立即数(在MUX1的OPERAND2中)
PC的输入主要由CU的几个状态输出和MUX1的OPERAND2,同时在其内部的LAST_PC
中缓存了上个时钟周期的NEXT_PC
输出;
PC的输出为NEXT_PC
,存储了CPU在下一个时钟周期的1时要要执行的内存指令地址。
取值单元(Fetch Unit)
取指单元(Fetch Unit)
用于根据PC
的输出(NEXT_PC
)从内存(RAM)
相应地址中取出指令输出到指令总线(INST BUS)
中。
控制单元(Control Unit)
控制单元(Control Unit)
用于对取值单元(Fetch Unit)
取出的指令进行解码,按照指令集设计,设置各种状态标志,以作为后续各种内部单元的输入,控制个单元的运行。
多路选择器(MUX1)
MUX1
用于根据指令集设计获取当前指令的操作数2
的具体值。根据指令集寻址方式
设计,各个指令的操作数2
可能为:
立即数:
寄存器直接寻址:
寄存器间接寻址:
内存直接寻址:
内存间接寻址:
算逻单元(ALU)
算逻单元(Arithmetic Logical Unit)
用于按照指令集设计,根据不同的指令码
对指令操作数
进行运算,得到指令结果的部件。
多路选择器(MUX2)
MUX2
用于根据指令集设计,将ALU中指令执行的结果传递到相应的寄存器或内存地址中。
寄存器组(Registers)
寄存器组(Registers)
包含了16个通用寄存器
(每个16bit)和标志寄存器(FLAGS)
(包含4个标志位)。
内存管理单元(MMU)
内存管理单元(MMU)
用于根据指令对内存对于地址的数据进行读写操作。MMU
根据指令集设计通过控制单元CU
将ALU
的结果写入内存的对应地址中。
主存(RAM)
主存(RAM)
是用于存储CPU执行指令和数据的部件,使用excel sheet的单元格来表示,总共包含128x512个单元格,每个单元格表示16bit的内存单元。
主存的最后96x128的区域为显存位置。
显示器(Display Screen)
显示器
为128x96
个单元格矩阵,每个单元格根据RAM中最后的显存中的值,可输出16种颜色中的某一种颜色。
指令集
excel cpu指令集总共包含了27条指令,其中操作码0-6号指令长度位4Bytes(32bits)
, 7-26号指令长度2Bytes(16bits)。
OPCODE | 8b | 4b | 4b | 16b | OPERATION | ALU OP | |
---|---|---|---|---|---|---|---|
00 | 0 | JMP | IMD | IMD -> PC | |||
01 | 1 | JEQ | IMD | IF Z = 1, IMD -> PC | |||
02 | 2 | JLT | IMD | IF C = 0, IMD -> PC | |||
03 | 3 | JGE | IMD | IF C = 1 OR Z = 1, IMD -> PC | |||
04 | 4 | LOAD | REG | MEM | [MEM] -> REGA | ||
05 | 5 | LOAD | REG | IMD | IMD -> REGA | ||
06 | 6 | STORE | REG | MEM | REGA -> [MEM] | ||
07 | 7 | STORE | REG | REG | REGA -> [REGB] | ||
08 | 8 | TRAN | REG | REG | REGA -> REGB | ||
09 | 9 | ADD | REG | REG | REGA + REGB + C -> REGA | ||
0A | 10 | SUB | REG | REG | REGA - REGB - C -> REGA | ||
0B | 11 | MULT | REG | REG | REGA * REGB -> low 16 in REGA, high 16 in REGB | ||
0C | 12 | DIV | REG | REG | REGA / REGB -> result in REGA, MOD in 16 in REGB | ||
0D | 13 | INC | REG | REGA + 1 -> REGA (FLAGS not affected) | |||
0E | 14 | DEC | REG | REGA - 1 -> REGA (FLAGS not affected) | |||
0F | 15 | AND | REG | REG | REGA AND REGB -> REGA | ||
10 | 16 | OR | REG | REG | REGA OR REGB -> REGA | ||
11 | 17 | XOR | REG | REG | REGA XOR REGB -> REGA | ||
12 | 18 | NOT | REG | NOT REGA -> REGA | |||
13 | 19 | ROL | REG | IMD | REGA « IMD -> REGA | ||
14 | 20 | ROR | REG | IMD | REGA » IMD -> REGA | ||
15 | 21 | CMP | REG | REG | REGA - REGB -> ONLY FLAGS CHANGED | ||
16 | 22 | CLC | 0 -> C | ||||
17 | 23 | STC | 1 -> C | ||||
18 | 24 | NOP | NOTHING | ||||
19 | 25 | LOAD | REG | REG | [REGB] -> REGA | ||
20 | 26 | HALT |
ROM
ROM是excel cpu的自读存储器,用于保存汇编生成的二进制代码。
Excel asm汇编
excel asm汇编支持直接在asm sheet中编写汇编代码,支持数据段、代码段,编写的代码直接在ROM sheet中生成对应的二进制码。
存在的问题
- 由于excel单元格计算依赖的问题,无法直接根据指令集设计表格通过查表来实现ALU计算,需要根据硬编码到单元格计算公式中,后续希望能通过查表实现。