大师教你如何制作一个简单的16位CPU
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
这 个例子中使用了一个加法器一个减法器,没比上面的电路省(显然。。。。难道你想用减法器做加法器的功能?不可能吧!当然,加上 一个负数的补码确实就是减去 一个数,但是这里先不考虑这种问题),多了一组多路器,少了一组D触发器。总的来说,优势还是明显的 (两块电路板和一块电路板的差别)。 而sel信号就是用来选择的(0是递增,1是递减)。 如果我们把sel信号看做“程序”的话,这个电路就像一个“CPU”能根据“程序”执行不同的“操作”,这样的话,通过“程序”(sel 信号),这个电路就能够实现复用。 根据上面的结论,我认为(仅仅是个人认为啊~):程序就是硬件电路的延伸! 而CPU的基本思想,我认为就是这样的。 接下来我们就分析CPU的结构和各个部件,然后实现这个CPU。 【分页导航】
mv指令将Ry的数据转移到Rx中,mvi将立即数D转移到Rx当中,add将Rx和Ry的和放到Rx中,sub同上,不过执行的是减法。 首 先来说明mv指令是如何执行的:mv指令将Ry的值移入Rx寄存器当中,这两个寄存器都是由一组D触发器构成,而D触发器的个数取决 于寄存器的宽度,就像 32位机、64位机这样,那他们的寄存器使用的D触发器的个数就是不一样的。当执行mv rx,ry时,中间的多路器(图 中最大的那个multiplexer)选通Ry,让Ry寄存器驱动总线,这个时候Bus上的信号就是Ry的值;然后再看到 R0~R7上分别有R0in~R7in信 号,这个信号是使能信号,当这个信号有效时,在上升沿此触发器会将din的数据输入,所以说到这里大家一定想到 了,这个时候Rx触发 器上的Din信号就会变为有效,这样过了一个时钟周期后Ry的值就被送到了Rx当中。 与mv指令类似,mvi指令也将一个数据送入Rx当中,只不过这次的数据存在指令当中,是立即数,所以Rx的Din信号会变为有效,而多路 器会选择IR中的数据,因为mvi指令的立即数存在指令当中。并且进行一定处理,例如扩展等。 add 指令会让多路器先选择Rx,然后Ain信号有效,这样一个时钟周期后,Rx数据被送入Alu的A寄存器当中,这时多路器选择 Ry,addsub信号为 add以指示ALU进行加法操作,Gin有效让G寄存器存放运算结果,然后再过一个时钟周期G当中的数据就是Rx与Ry的 和,这时多路器再选择 Gin,Rx的Din有效,过了一个时钟周期后数据就被存放到Rx当中了。 sub的过程与add差不多,不过addsub信号是sub指示ALU进行减法。 【分页导航】
当然,实际的时钟信号可能远没有这么理想,可能上升沿是斜的,而且占空比也可能不是50%,有抖动,有偏移(相对于两个器件),可 能因为导线的寄生电容效应变得走形。 上面那段如果没听懂也没关系~~~反正就是告诉你,实际的时钟信号测出来肯定没这么标准。 而 cpu的工作频率,是外频与倍频的积(cpu究竟怎么算频率,其实这个我也不太清楚呵呵),因为cpu是通过外部的晶振产生一个时钟信 号,然后再通过内部 的电路(锁相环),倍频至需要的频率。当然,有人问,为什么要这么麻烦呢?直接在电路外边做个时钟晶振能产生 那么高的时钟信号就可以了嘛,这个是可以的, 在某些简单的系统上(例如51单片姬)就是这样的,但是计算姬的cpu比较复杂,因为一 些原因所以必须要做到cpu内。 下面简单说一下CPU的两种指令集:CISC和RISC。 说下我的看法(个人看法,如有错误还请高手指正): RISC是Reduced Instruction Set Computer,精简指令集计算机,典型例子是MIPS处理器。 CISC 是Complex Instruction Set Compute,复杂指令集计算机,典型例子是x86系列处理器(当然现在的x86指令还是当初cisc的指 令,但是实际处理器的结构都已经变成了 risc结构了,risc的结构实现流水线等特性比较容易,在计算机前的你如果用的是intel某系列的 处理器,则它使用的指令集看上去还是像cisc的 指令,但是实际上你的cpu的结构已经是risc的了)。 一般CISC的处理器需要用微指令配合运行,而RISC全部是通过硬连线实现的, 也就是说,当cisc的处理器在执行你的程序前,还得先从另 外一个rom里面读出一些数据来“指导”处理器怎么处理你的命令,所以cisc效率比较低,而 risc是完全通过部件和部件之间的连接实现 某种功能,极大的提高了工作效率,而且为流水线结构的出现提供了基础。cisc的寄存器数量较少,指令能够实 现一些比较特殊的功能, 例如8086的一些寄存器: ax,bx,cx,dx,si,di等;段寄存器有:cs,ds,es,ss等。相对的指令功能比较特殊,例如xlat将bx中的值作为基地址,al中的值作为偏移,在内存 中寻址到的数据送到al当中(以ds为段寄存器) 而risc的处理器则通用寄存器比较多,而指令的功能可以稍微弱一点,例如: 以nios嵌入式处理器来说明,nios处理器有32个通用寄存器(r0~r31),而指令功能相对x86的弱一些,而且x86进行内存访问是直接使 用mov指令,nios处理器读内存用的是load,写内存用的是store, 二 者响应中断的方式也不一样,举一个典型的例子,x86的处理器将中断向量表放在了内存的最低地址(0-1023,每个中断向量占四个字 节),能容纳256 个中断(以实模式的8086举例)响应中断时,将中断号对应的地址上的cs和ip的值装入到cs和ip寄存器而将原来的地址 保存,并且保存状态寄存器然后 进入中断处理,而risc则拥有一个共同的中断响应函数,这个函数会根据中断号找到程序向系统注册的函 数的地址,并且调用这个函数。一般来说而是用的 cisc指令的长度是不定的,例如x86的xor ax,bx对应机器码是0x31d8、而push ax是 0x50、pop cx是0x59。而risc的指令确是定长的,例如】
第1页:CPU是做什么的 第2页:什么是单周期CPU,什么是多周期CPU,什么是RISC,什么是CISC 第3页:一个CPU的基本结构以及必要组件 第4页:重头戏:我做的CPU模型
什么是单周期CPU,什么是多周期CPU,什么是RISC,什么是CISC 首 先大家得有时钟的概念:这个问题不好解释啊。。。。。。可以理解为家里面的机械钟,上上电池之后就会滴答滴答走,而它“滴答滴 答”的速度就是频率,滴答一 下用的时间就是周期,而人的工作,下班,吃饭和学习娱乐都是按照时钟的指示来进行的(熬夜的网瘾少年 不算),一般来说,时钟信号都是由晶体振荡器产生 的,0101交替的信号(低电平和高电平)。 数字电路都需要一个“时钟”来驱动,就像演奏交响乐的时候需要一个指挥家在前面指挥一样,所有的人都会跟着指挥的拍子来演奏,就 像数字电路中所有的部件都会跟着时钟节拍工作一样。 如下是一个理想的时钟信号:(注意是理想的)。
大师教你如何制作一个简单的16位CPU
大师教你如何制作一个简单的16位CPU 上网时间:2016年03月10日
如何制作一个简单的16位CPU,首先我们要明个CPU,首先得明白下计算机的组成结构(或者计算机的替代品,因为并不是只有计算机有CPU,现在的电子产品都很先 进,很多设备例如手机、洗 衣机甚至电视和你家的汽车上面都得装一个CPU),数字电路基础,还最好有点编程的基础(当然,没有也没 关系,这些知识都很容易获得,各种书上面都会提 到,并且在接下来的过程中我会提到这些知识) 我们要实现的是一个RISC指令集的CPU,并且我们最后要自己为这个CPU设计指令并且编码。 首先我们来听个故事,关于CPU的诞生的故事: 日 本客户希望英特尔帮助他们设计和生产八种专用集成电路芯片,用于实现桌面计算器。英特尔的工程师发现这样做有两个很大的问题。 第一,英特尔已经在全力开发 三种内存芯片了,没有人力再设计八种新的芯片。第二,用八种芯片实现计算器,将大大超出预算成本。英 特尔的一个名叫特德?霍夫(Ted Hoff)的工程师仔细分析了日本同行的设计,他发现了一个现象。这八块芯片各实现一种特定的功能。 当用户使用计算器时,这些功能并不是同时都需要的。比 如,如果用户需要计算100个数的和,他会重复地输入一个数,再做一次加法, 一共做100次,最后再打印出来。负责输入、加法和打印的电路并不同时工作。 这样,当一块芯片在工作时,其他芯片可能是空闲的。 霍夫有了一个想法:为什么不能用一块通用的芯片加上程序来实现几块芯片的功能呢?当需要某种功能时,只需要把实现该功能的一段程 序代码(称为子程序)加载到通用芯片上,其功能与专用芯片会完全一样。 经 过几天的思考后,霍夫画出了计算器的新的体系结构图,其中包含4块芯片:一块通用处理器芯片,实现所有的计算和控制功能;一块 可读写内存(RAM)芯片, 用来存放数据;一块只读内存(ROM)芯片,用来存放程序;一块输入输出芯片,实现键入数据和操作命 令、打印结果等等功能。 看完这个故事后,可以总结:CPU是一种用来代替专用集成电路的器件(这只是我的理解,不同人有不同理解,这个就智者见智了,我在 接下来的例子中也会说明我的想法)。 然后考虑如下这个例子: 例1-1: mov eax,0 repeat:inc eax jmp repeat 例1-2: int main() { unsigned int i = 0; while(1) i++; } 例1-3:
第1页:CPU是做什么的 第2页:什么是单周期CPU,什么是多周期CPU,什么是RISC,什么是CISC 第3页:一个CPU的基本结构以及必要组件 第4页:重头戏:我做的CPU模型
一个CPU的基本结构以及必要组件
这 个例子引用自DE2开发板套件带的光盘上的Lab Exercise 9,我们从图中可以看到,一个CPU包含了通用寄存器组R0~R7,一个 ALU(算术逻辑单元),指令寄存器IR,控制器(一般这部分是一个有限状态机或 者是用微指令实现),还有就是数据通路(图中的连 线)。当然真正的CPU不可能只包含这么一点点组件,这是一个模型CPU,也就是说只是说明CPU的原 理,真正复杂的CPU要涉及到很多 复杂的结构和时序,例如虚拟模式需要使用一些特殊的寄存器、为了支持分页需要使用页表寄存器等,为了加速内存的访问需要 使用 TLB,加速数据和指令的访问而使用data cache和instruction cache等等。。。。。当然,那都是后面该考虑的,所以我们先从这个简单 的部分开始讲起。 例子中能实现如下指令:
可 以看到,以上三个例子都产生了一个从0不断增加的序列,而且前两个例子会一直加到溢出又从开始(这个取决于计算机的字长也就 是多少位的CPU,eax是 32位寄存器所以必然是加到4294967295然后回0,而后面那个c程序则看不同编译器和不同平台不一样),后面 那个例子则看你用的是什么样的加法器 和多少个D触发器 那问题就来了,我假设要一个递减的序列怎么办呢?前两个例子很好解释,我直接改代码不就得了: 例2-1: mov eax,0 repeat:dec eax jmp repeat 例2-2: int main()
{ unsigned int i = 0; while(1) i--; } 你只需要轻轻敲击键盘,修改了代码之后,它就会如你所愿的执行。 但是后面那个例子怎么办呢?可能你已经想到办法了:如例2-3所示。 例2-3:
问题就来了,你在键盘上敲两下可不能改变实际电路!上面(例1-3)中是个加法器,但是跑到这里却变成了减法器(例2-3)! 这样的话,你就得再做一个电路,一个用来算加法,一个用来算减法,可是两个电路代表你得用更多的电路和芯片,你花的钱就得更多, 要是你不能同时使用这两个电路你就花了两份钱却只干了一件事! 这个问题能被解决吗?答案是能! 请看例3:
mv指令将Ry的数据转移到Rx中,mvi将立即数D转移到Rx当中,add将Rx和Ry的和放到Rx中,sub同上,不过执行的是减法。 首 先来说明mv指令是如何执行的:mv指令将Ry的值移入Rx寄存器当中,这两个寄存器都是由一组D触发器构成,而D触发器的个数取决 于寄存器的宽度,就像 32位机、64位机这样,那他们的寄存器使用的D触发器的个数就是不一样的。当执行mv rx,ry时,中间的多路器(图 中最大的那个multiplexer)选通Ry,让Ry寄存器驱动总线,这个时候Bus上的信号就是Ry的值;然后再看到 R0~R7上分别有R0in~R7in信 号,这个信号是使能信号,当这个信号有效时,在上升沿此触发器会将din的数据输入,所以说到这里大家一定想到 了,这个时候Rx触发 器上的Din信号就会变为有效,这样过了一个时钟周期后Ry的值就被送到了Rx当中。 与mv指令类似,mvi指令也将一个数据送入Rx当中,只不过这次的数据存在指令当中,是立即数,所以Rx的Din信号会变为有效,而多路 器会选择IR中的数据,因为mvi指令的立即数存在指令当中。并且进行一定处理,例如扩展等。 add 指令会让多路器先选择Rx,然后Ain信号有效,这样一个时钟周期后,Rx数据被送入Alu的A寄存器当中,这时多路器选择 Ry,addsub信号为 add以指示ALU进行加法操作,Gin有效让G寄存器存放运算结果,然后再过一个时钟周期G当中的数据就是Rx与Ry的 和,这时多路器再选择 Gin,Rx的Din有效,过了一个时钟周期后数据就被存放到Rx当中了。 sub的过程与add差不多,不过addsub信号是sub指示ALU进行减法。 【分页导航】
当然,实际的时钟信号可能远没有这么理想,可能上升沿是斜的,而且占空比也可能不是50%,有抖动,有偏移(相对于两个器件),可 能因为导线的寄生电容效应变得走形。 上面那段如果没听懂也没关系~~~反正就是告诉你,实际的时钟信号测出来肯定没这么标准。 而 cpu的工作频率,是外频与倍频的积(cpu究竟怎么算频率,其实这个我也不太清楚呵呵),因为cpu是通过外部的晶振产生一个时钟信 号,然后再通过内部 的电路(锁相环),倍频至需要的频率。当然,有人问,为什么要这么麻烦呢?直接在电路外边做个时钟晶振能产生 那么高的时钟信号就可以了嘛,这个是可以的, 在某些简单的系统上(例如51单片姬)就是这样的,但是计算姬的cpu比较复杂,因为一 些原因所以必须要做到cpu内。 下面简单说一下CPU的两种指令集:CISC和RISC。 说下我的看法(个人看法,如有错误还请高手指正): RISC是Reduced Instruction Set Computer,精简指令集计算机,典型例子是MIPS处理器。 CISC 是Complex Instruction Set Compute,复杂指令集计算机,典型例子是x86系列处理器(当然现在的x86指令还是当初cisc的指 令,但是实际处理器的结构都已经变成了 risc结构了,risc的结构实现流水线等特性比较容易,在计算机前的你如果用的是intel某系列的 处理器,则它使用的指令集看上去还是像cisc的 指令,但是实际上你的cpu的结构已经是risc的了)。 一般CISC的处理器需要用微指令配合运行,而RISC全部是通过硬连线实现的, 也就是说,当cisc的处理器在执行你的程序前,还得先从另 外一个rom里面读出一些数据来“指导”处理器怎么处理你的命令,所以cisc效率比较低,而 risc是完全通过部件和部件之间的连接实现 某种功能,极大的提高了工作效率,而且为流水线结构的出现提供了基础。cisc的寄存器数量较少,指令能够实 现一些比较特殊的功能, 例如8086的一些寄存器: ax,bx,cx,dx,si,di等;段寄存器有:cs,ds,es,ss等。相对的指令功能比较特殊,例如xlat将bx中的值作为基地址,al中的值作为偏移,在内存 中寻址到的数据送到al当中(以ds为段寄存器) 而risc的处理器则通用寄存器比较多,而指令的功能可以稍微弱一点,例如: 以nios嵌入式处理器来说明,nios处理器有32个通用寄存器(r0~r31),而指令功能相对x86的弱一些,而且x86进行内存访问是直接使 用mov指令,nios处理器读内存用的是load,写内存用的是store, 二 者响应中断的方式也不一样,举一个典型的例子,x86的处理器将中断向量表放在了内存的最低地址(0-1023,每个中断向量占四个字 节),能容纳256 个中断(以实模式的8086举例)响应中断时,将中断号对应的地址上的cs和ip的值装入到cs和ip寄存器而将原来的地址 保存,并且保存状态寄存器然后 进入中断处理,而risc则拥有一个共同的中断响应函数,这个函数会根据中断号找到程序向系统注册的函 数的地址,并且调用这个函数。一般来说而是用的 cisc指令的长度是不定的,例如x86的xor ax,bx对应机器码是0x31d8、而push ax是 0x50、pop cx是0x59。而risc的指令确是定长的,例如】
第1页:CPU是做什么的 第2页:什么是单周期CPU,什么是多周期CPU,什么是RISC,什么是CISC 第3页:一个CPU的基本结构以及必要组件 第4页:重头戏:我做的CPU模型
什么是单周期CPU,什么是多周期CPU,什么是RISC,什么是CISC 首 先大家得有时钟的概念:这个问题不好解释啊。。。。。。可以理解为家里面的机械钟,上上电池之后就会滴答滴答走,而它“滴答滴 答”的速度就是频率,滴答一 下用的时间就是周期,而人的工作,下班,吃饭和学习娱乐都是按照时钟的指示来进行的(熬夜的网瘾少年 不算),一般来说,时钟信号都是由晶体振荡器产生 的,0101交替的信号(低电平和高电平)。 数字电路都需要一个“时钟”来驱动,就像演奏交响乐的时候需要一个指挥家在前面指挥一样,所有的人都会跟着指挥的拍子来演奏,就 像数字电路中所有的部件都会跟着时钟节拍工作一样。 如下是一个理想的时钟信号:(注意是理想的)。
大师教你如何制作一个简单的16位CPU
大师教你如何制作一个简单的16位CPU 上网时间:2016年03月10日
如何制作一个简单的16位CPU,首先我们要明个CPU,首先得明白下计算机的组成结构(或者计算机的替代品,因为并不是只有计算机有CPU,现在的电子产品都很先 进,很多设备例如手机、洗 衣机甚至电视和你家的汽车上面都得装一个CPU),数字电路基础,还最好有点编程的基础(当然,没有也没 关系,这些知识都很容易获得,各种书上面都会提 到,并且在接下来的过程中我会提到这些知识) 我们要实现的是一个RISC指令集的CPU,并且我们最后要自己为这个CPU设计指令并且编码。 首先我们来听个故事,关于CPU的诞生的故事: 日 本客户希望英特尔帮助他们设计和生产八种专用集成电路芯片,用于实现桌面计算器。英特尔的工程师发现这样做有两个很大的问题。 第一,英特尔已经在全力开发 三种内存芯片了,没有人力再设计八种新的芯片。第二,用八种芯片实现计算器,将大大超出预算成本。英 特尔的一个名叫特德?霍夫(Ted Hoff)的工程师仔细分析了日本同行的设计,他发现了一个现象。这八块芯片各实现一种特定的功能。 当用户使用计算器时,这些功能并不是同时都需要的。比 如,如果用户需要计算100个数的和,他会重复地输入一个数,再做一次加法, 一共做100次,最后再打印出来。负责输入、加法和打印的电路并不同时工作。 这样,当一块芯片在工作时,其他芯片可能是空闲的。 霍夫有了一个想法:为什么不能用一块通用的芯片加上程序来实现几块芯片的功能呢?当需要某种功能时,只需要把实现该功能的一段程 序代码(称为子程序)加载到通用芯片上,其功能与专用芯片会完全一样。 经 过几天的思考后,霍夫画出了计算器的新的体系结构图,其中包含4块芯片:一块通用处理器芯片,实现所有的计算和控制功能;一块 可读写内存(RAM)芯片, 用来存放数据;一块只读内存(ROM)芯片,用来存放程序;一块输入输出芯片,实现键入数据和操作命 令、打印结果等等功能。 看完这个故事后,可以总结:CPU是一种用来代替专用集成电路的器件(这只是我的理解,不同人有不同理解,这个就智者见智了,我在 接下来的例子中也会说明我的想法)。 然后考虑如下这个例子: 例1-1: mov eax,0 repeat:inc eax jmp repeat 例1-2: int main() { unsigned int i = 0; while(1) i++; } 例1-3:
第1页:CPU是做什么的 第2页:什么是单周期CPU,什么是多周期CPU,什么是RISC,什么是CISC 第3页:一个CPU的基本结构以及必要组件 第4页:重头戏:我做的CPU模型
一个CPU的基本结构以及必要组件
这 个例子引用自DE2开发板套件带的光盘上的Lab Exercise 9,我们从图中可以看到,一个CPU包含了通用寄存器组R0~R7,一个 ALU(算术逻辑单元),指令寄存器IR,控制器(一般这部分是一个有限状态机或 者是用微指令实现),还有就是数据通路(图中的连 线)。当然真正的CPU不可能只包含这么一点点组件,这是一个模型CPU,也就是说只是说明CPU的原 理,真正复杂的CPU要涉及到很多 复杂的结构和时序,例如虚拟模式需要使用一些特殊的寄存器、为了支持分页需要使用页表寄存器等,为了加速内存的访问需要 使用 TLB,加速数据和指令的访问而使用data cache和instruction cache等等。。。。。当然,那都是后面该考虑的,所以我们先从这个简单 的部分开始讲起。 例子中能实现如下指令:
可 以看到,以上三个例子都产生了一个从0不断增加的序列,而且前两个例子会一直加到溢出又从开始(这个取决于计算机的字长也就 是多少位的CPU,eax是 32位寄存器所以必然是加到4294967295然后回0,而后面那个c程序则看不同编译器和不同平台不一样),后面 那个例子则看你用的是什么样的加法器 和多少个D触发器 那问题就来了,我假设要一个递减的序列怎么办呢?前两个例子很好解释,我直接改代码不就得了: 例2-1: mov eax,0 repeat:dec eax jmp repeat 例2-2: int main()
{ unsigned int i = 0; while(1) i--; } 你只需要轻轻敲击键盘,修改了代码之后,它就会如你所愿的执行。 但是后面那个例子怎么办呢?可能你已经想到办法了:如例2-3所示。 例2-3:
问题就来了,你在键盘上敲两下可不能改变实际电路!上面(例1-3)中是个加法器,但是跑到这里却变成了减法器(例2-3)! 这样的话,你就得再做一个电路,一个用来算加法,一个用来算减法,可是两个电路代表你得用更多的电路和芯片,你花的钱就得更多, 要是你不能同时使用这两个电路你就花了两份钱却只干了一件事! 这个问题能被解决吗?答案是能! 请看例3: