CPU设计初探
习惯了“实践-理论-实践”的学习模式,对硬件知之甚少却学完了《计算机组成原理》,我努力尝试让自己找到这门课的感觉。没有FPGA的试验器材,也没有多少真实芯片在身边,于是我拾起《数字电路》,准备在虚拟环境下,用Proteus设计一个简单的虚拟CPU。
现在的网络确实方便,我找到两篇最满意的文章就设计好一个最简单的了。
起初使用wikipedia,查阅了CPU design词条,了解到CPU主要是有Finite-state Machin,其间经历了一次设计失败:
当时翻了几遍《计算机组成原理》来找设计的切入点,指令设计被我认为是起点。于是不假思索地列出22种指令,并按6-bit二进制串编好码,等所有指令格式确定以后,问题便出现了:①制作CPU需要哪些芯片?②如何让搭好的CPU自动运转?③BUS是怎么使用的?
对于①,我仔细查看了学校实验箱上的芯片型号,包括
74LS299(8-bit REG),
74LS381(ALU),
74LS74/175/273/374(D-Type Flip-Flops),
74LS245(BusTransceiver),
74LS139(2 line to 4 line Decoder),
6116(2K*8 SRAM),
8255(Programmable Peripheral Interface),
74LS240/244(Buffer)
74LS393(4-bit Counter)
74LS161(Synchronous 4-bit Counter)
芯片类型有了,但是还是不会用啊,只能打开proteus,把相应芯片找出来,再到网上下载各自的datasheet,这才逐渐清楚每个芯片具体的功用。进入下一步,设计再次卡壳了。谁连谁以什么方式连,②和③怎么解决?
对于③,我用74LS273配合总线尝试:
在figure 2.中,当片选有效时,更改data有时会出现警告信号,也就是有管脚出现0,1不确定信号。后来看了Magic-1的设计,才明白两种地方总线应该分开(如figure 3.)这样③也就解决了。
而对于②,确实经历了一个漫长的过程。
我先绕开问题②。为了便于观察,我舍弃使用RAM芯片,每次指令通过开关确定(figure 4.)。但很快就发现,当某开关没有闭合时,其中一边是没有信号的,这样设计不合理,于是我学会了使用下拉电阻(figure 5.),这样开关闭合时是高电平,释放时是低电平。
接着我立即用了4个74LS273,但当时竟然把这个芯片当寄存器使用,现在才想起应该按figrue 6.设计寄存器。当时的4个74LS273我准备用作AR、DR、PC和IR的,其实没有一个有用,最后我留了一个74LS273作IR缓冲器(figure 7.)。
设想了很多方案,逐步化简后,我决定只使用两个指令nop(00)和add(01),nop用来放空操作,而add则使用add imval,让ACC <- ACC + imval,这样也就省去了AR和DR。
将add分解后,有:
ADD1: REG <- D[3..0], ACC <- ACC + REG
ADD2: (goto FETCH1)
而取指和译指微指令有:
FETCH1: IR <- D[7..6]
FETCH2: decode(IR)
有了FETCH1,FETCH2,ADD1,ADD2是还不能够设计出figure 8.所示的译指电路的。这个问题的解决还要归功于④手动激发CPU运行的探索。
对于④,新接触真是无从下手。把电子版的《Computer System Organization And Architecuture》中第6章CPU Design看了看,再结合FSM的资料,明白这部分需要使用计数器。再回到刚才的4条微指令:
0000 FETCH1: IR <- D[7..6]
0001 FETCH2: decode(IR)
0010 ADD1: REG <- D[3..0], ACC <- ACC + REG
0011 ADD2: (goto FETCH1)
得到一个FSM:
计数器有/PL(并行加载)和MR(清零)这两个信号控制,故完整的微指令有:
0000 FETCH1: IR <- D[7..6],MR = 1, /PL = 1
[act=1] MR = 0, /PL = 1
0001 FETCH2: decode(IR), MR = 0, /PL = 0
0010 ADD1: REG <- D[3..0], ACC <- ACC + REG, MR = 0, /PL = 1
0011 ADD2: MR = 1, /PL = 1
注:
当act=0时,0000和0011状态下 MR = 1
act是触发CPU运行的信号,高电平为触发
总结上面的微指令有:
/PL = FETCH2
MR = act and (C0000 or C0011) = not (act or ((not C000) and (not C0011)))
其电路设计如figure 9.。同样的,figure 8.中IR=00则状态机仍为0000,IR=1则状态机为0010,故译指器这样就设计完毕了。到这里②也就解决了。只要/PL有效,MR无效,计数器就会自动工作并带着CPU运行啦~
最后,我把电路统一起来,并加上ACC,则有figure 10.:
把电路完整放入Proteus中,单击运行开始模拟。将S6=1,S7=0,再设置S3 S2 S1 S0,单击ACT按钮,电路运转正常,ACC中将存储累加后的结果,CPU设计完成。
但这个CPU并没有中断功能,也没有使用流水线技术,故下一步要考虑增加这两部分了。总体来说,设计比较成功。^_^
参考文献
[1] Magic-1 Homebrew CPU [OL/A] www.homebrewcpu.com/Magic1.pdf
[2] John.D.Capinelli, Computer System Organization and Architecture[M] Addison-Wesley, October 2000, p217-235
[3] CPU Design[OL/A] en.wikipedia.org/wiki/CPU_Design
[4] Finite-state Machin[OL/A] en.wikipedia.org/wiki/Finite-state_Machin
[5] Lecture 14: FSM and Basic CPU Design[OL/A] www.cs.utah.edu/~rajeev/cs3810/slides/3810-14.pdf