2013年6月份,我对用FPGA验证CPU模型产生了兴趣,第一次接触FPGA是在2010年,当时刚会使用51单片机,在学FPGA的过程中,就会以单片机的思维去理解FPGA的开发过程,并且总是把verilog HDL当做C语言来使用,自然会有很多无法理解的问题出现,后来在自己坚持不懈的努力下,在verilog方面算是入门了。对于C语言与verilog的区别,我当时最大的体会是C语言是被编译为汇编指令,最终编译为二进制代码,由CPU去运行。而verilog的每个逻辑块会被编译成一个由逻辑门组成的数字电路,这些数字电路完成由verilog描述的逻辑功能。
一次偶然的机会在网上看到了51单片机的verilog代码,这对于我来说是一件很兴奋的事,CPU在我们眼里是一个很神秘的芯片,而芯片内部主要由数字电路组成,当时尝试着去阅读51单片机的verilog源码,但是由于水平有限,发现根本看不懂。经过多年的学习,汇编语言、C、C++都已熟练掌握,对单片机内部的体系结构也有所了解,并且对于verilog的理解和使用也上了一个台阶。今年6月份再次在网上把51的verilog源码下载了下来,大概的浏览一遍,感觉整个逻辑结构不是很复杂,所以就萌生了自己写一个简单CPU的想法。我对430单片机的汇编语言比较熟悉,所以确定以430指令集为自己第一CPU的指令集。
设计目标
1. CPU流水线的各个模块不是同步工作,一条指令执行完成才能执行下条指令
2. 每条指令周期不超过10个机器周期
3. 以MSP430F147单片机为原型,能够运行IARfor430编译器为MSP430F147单片机编写的程序。
4. 实现27条核心指令中的26条,不实现BCD加法指令(一般运用用不到此指令)
5. 不包含中断功能,预留外设接口,用户可添加自定义外设。
由于是第一次尝试实现CPU逻辑,所以省去了中断、流水线同步等功能。
目前实现功能
1.实现了27条核心指令中的26条,没有实现BCD加法指令。
2.指令周期为6~8个机器周期,返回指令ret除外,需要11个机器周期
3.没有实现中断功能,所以类似定时器这类的外设没有添加,目前添加了乘法器外设,P1和P2端口,且P1和P2端口没有中断功能
4.流水线各个模块是异步工作方式,即前一级模块工作完成,下一级才开始工作。
5.留有外设接口,方便用户添加自定义外设
6.在EP4CE155F29C8器件上运行最高频率为100MHz
资源使用报告
memory使用了33Kbyte,如果用户目标器件不支持这么多ram,可以调节quartus II 宏模块rom的大小,只要足够存储程序即可。
使用方法
1.将IAR编译的可执行文件嵌入到FPGA的ram中
使用IARFor430建立430单片机工程,编写程序,然后对编译选项做如下设置
右键工程名称,点击Options选项,出现下图对话框。
选择General Options菜单项,在Device里选择单片机型号MSP430F147。
选择Linker菜单项,点击output选项卡,在输出文件Format里选择other。IAR编译参数设置完成,编译工程,在工程目录//Debug//exe 下会有txt后缀文件,这就是工程 源码对应的ASSIC码文件。文件内容如下:(我提供的测试C程序对应的二进制代码)
@800031 40 00 06 B0 12 0C 80 B0 12 56 81 F2 43 2A 00
F2 43 22 00 F2 43 21 00 3C 40 E8 03 B0 12 40 81
B0 12 C6 80 7E 40 48 00 5D 43 5C 43 B0 12 EC 80
7E 40 65 00 5D 43 6C 43 B0 12 EC 80 7E 40 6C 00
5D 43 7C 40 03 00 B0 12 EC 80 7E 40 6C 00 5D 43
6C 42 B0 12 EC 80 7E 40 6F 00 5D 43 7C 40 05 00
B0 12 EC 80 7E 40 20 00 5D 43 7C 40 06 00 B0 12
EC 80 7E 40 57 00 5D 43 7C 40 07 00 B0 12 EC 80
7E 40 6F 00 5D 43 7C 42 B0 12 EC 80 7E 40 72 00
5D 43 7C 40 09 00 B0 12 EC 80 7E 40 6C 00 5D 43
7C 40 0A 00 B0 12 EC 80 7E 40 64 00 5D 43 7C 40
0B 00 B0 12 EC 80 7E 40 21 00 5D 43 7C 40 0C 00
B0 12 EC 80 FF 3F 7C 40 38 00 B0 12 26 81 7C 40
0C 00 B0 12 26 81 7C 40 06 00 B0 12 26 81 5C 43
B0 12 26 81 3C 40 64 00 30 40 40 81 5D 93 03 20
7C 50 80 00 02 3C 7C 50 C0 00 B0 12 26 81 4C 4E
B0 12 0C 81 7C 40 0C 00 30 40 26 81 C2 4C 29 00
E2 D2 21 00 E2 C3 21 00 D2 D3 21 00 D2 C3 21 00
1C 43 30 40 40 81 C2 4C 29 00 E2 C2 21 00 E2 C3
21 00 D2 D3 21 00 D2 C3 21 00 1C 43 30 40 40 81
05 3C 1F 53 3F 90 90 01 FC 2B 3C 53 0C 93 02 24
0F 43 F8 3F 30 41 30 40 5A 81 30 40 5E 81 FF 3F
@FFFE
00 80
q
这里面包含了程序存储器中存储的程序十六进制值和地址,下一步用我提供的转换工具将此文件转换为quartus II ram的初始化mif文件。
将其重命名为mem.txt文件,与我提供的转换工具Transform.exe放在同一目录下,运行Transform.exe出现如下对话框。
关闭对话框,在此目录下回生成romdata.mif文件。
2.添加装换文件(romdata.mif)到quartusII工程
将第二部中生成的romdata.mif文件添加到我提供的quartusII工程(CPUCore430)中,编译工程,下载程序到FPGA中,即可验证FPGA的430软核和实际MSP430F147单片机运行结果是否一致。
总结
目前只实现了P1和P2端口,和乘法器模块,且P1和P2端口不具备中断功能,所以在编写测试程序时,用户只能使用这三种外设,对操作其他外设,比如定时器、P3端口、AD采样等是没有效果的。下一片文章将给出用户添加自定义外设的实例,用户可以自己完成P3端口等其他外设的添加工作,由于不支持中断功能,所以目前还不能添加定时器这类外设。
随着后面写的文章对于整个CPU运行的原理介绍的升入,我希望能够在最后在此基础上把中断功能添加上,希望读者能够更好的理解,在设计过程中,我以为添加中断功能留有余地。希望大家能够对我写的软核感兴趣,希望更多的同行能够参与其中。
这是我写的第一个CPU软核,虽然功能和性能简单,但是,我从中发现了很多想要提升CPU性能带来的问题,并且通过查阅资料,自己思考也想出了解决问题的思路,先静下心来学习CPU设计相关理论知识,我将会实现能够执行MIPS指令集的CPU为下一个目标,并且做到流水线同步工作和存储器cache功能,尝试添加分支预测功能,对于MIPS体系指令集的优点,读者可以自己查阅相关资料。
由于时间仓促,为了在2013年最后一天能够发表此软核,目前测试工作还不够充分,希望大家在使用过程中遇到问题及时反馈给我,我会及时更正并回复。下一篇文章将介绍如何添加自定义外设。