基于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,以便将ROMsheet中的数据载入到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时,将ROMsheet中的数据加载到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计算,需要根据硬编码到单元格计算公式中,后续希望能通过查表实现。