如何使用logisim

更新时间:2024-05-17 05:42:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Logisim的简单入门

一,准备工作 参考:

罗老板的计算机结构与组成课程 http://xgxy.cug.edu.cn/rjgcx/lzw/COD/

Machine Structures. Spring 2010, UC Berkeley http://www-inst.eecs.berkeley.edu/~cs61c/sp10/ 软件环境:

Logisim仿真软件(需要JAVA虚拟机) http://ozark.hendrix.edu/~burch/logisim/ QuartusII 8.1

http://www.altera.com.cn/ 硬件环境:

PC机with Windows XP

DE2开发板(DE2 Development and Education Board User Manual) 参考书:

Computer.Organization.and.Design 关于QuartusII的使用教程

先来以一个与门电路的实验,来看一下基本的操作,在Logisim中一个与门电路生成过程如下:

1.按与门的选择按钮,添加一个与门到电路中。

2.使用按钮添加一个输入引脚,用于设置输入电平。

3.添加一个引脚,通过属性中设置Pin的属性为输出:

这样得到一个输出引脚。

4.移动以上添加的元素,得到原理图:

注意选中按钮,此时可以拖拽连线,那么我们把电路各部分连接如下:

5. 接下来通过选中按钮就可以鼠标点击设定输入管脚上的电平为1或0了,输出引脚

也会相应改变,输出结果。

当然通过左下方的属性设定,还可以设定当前选择元件的朝向,数据位数,输入端口数等参数。

6.另外推荐大家后面设计的时候使用一下tunnel这个工具,代替复杂的连线,在后面

复杂设计的地方,让你从蜘蛛网一样的连线中解脱出来,例如上面的电路可以这样表示:

图中输入,与门模块,输出三部分结构分的很清晰,tunnel的使用使我们的电路设计更加规范,类似logisim中的tunnel工具在其他原理图工具中类似的工具是经常见到的,虽然名字会有不同,用途是一样的。

7.最后是子电路添加方法,选择Project--->Add Circuit…,如下图“:

子电路的绘制与上面基本相同,注意的是输入输出引脚要连接Pin引脚,并设定好输入输出属性。

右击子电路选择Edit Circuit Appearance可以调整子电路的外观,通过拖拽将外观调整好,后面加到上层电路设计中的时候就不会显得布线拥挤了。

显然上面的要比下面的元件效果好一些。

以上描述的这些技巧与绘制规范整齐的原理图是关系密切的,后面实际应用中设计复杂电路时会突出显现出来。

几个关键的地方:

1,请尽量使用标准模块,如果需要建立自己的模块,请学习标准模块的设计风格。 2,请合理划分层次,清楚定义输入输出端口,尽量使定义的风格和规范保持一致。 3,请使用网络标识代替直接连线,会使你的原理图更加清晰易读。 4,为每个模块设计测试用例,用于测试和说明其使用方法。 5,这里用的软件比罗老板课上用的版本高一点,操作有细微差别。 打开QuartusII软件,程序主界面如下:

1, 新建一个工程

点击File——>New Project Wizard,打开创建新工程向导,这里你将完成工程的基本设定选项。

1, Project name and directory——工程的名称与目录

2, Name of the top-level design entity——顶层设计实体的名称

3, Project files and libraries——项目文件与库

4, Target device family and device——目标设备的族类 5, EDA tool settings——EDA工具设定

这里一般设定好工程名称和目录,顶层设计实体名称以及目标设备族类就可以了,其他的暂时直接使用默认项就可以了。

2, 新建一个设计文件

通过点击File——>New打开新建文件选择框,由于我们这里使用原理图描述实现的,则文件类型选择Design Files——>Block Diagram/Schematic File,就新建了一个原理图文件,将其保存起来,注意命名要跟前面设置的顶层设计实体名称相同。

3, 编写设计文件

接下来开始在文件中绘制原理图,这里首先完成与门的添加,点击左侧工具栏中的Symbol Tool按钮,打开Symbol选择框,选择primitives——>logic——>and2,点击OK后即可在原理图中添加一个2输入的与门了。在同样通过Symbol Tool中的加入和

primitives——>pin——>output加入输入和输出引脚,然后在原理图中把他们用Orthogonal Node Tool即导线连接起来,双击输入输出引脚,为他们设定好名字,pinA,pinB,pinC,就完成了原理图中的设计。

4, 编译(分析综合)

点击Processing——>Start——>Start Analysis & Synthesis,进行分析综合,就好像是对程序进行编译,等待片刻,如果没有错误,编译报告会输出出来。

5, 配置管脚

接下来配置管脚,就是设定刚才加入的输入输出管脚与实验板上FPGA芯片外部引脚之间的对应关系,设定好这个,我们设计的与门电路才能通过FPGA外部引脚与实验板上的其他设备连接起来,我们才好观察到电路的设计效果。点击Assignment——>Pins,打开Pin Planner设定框,这里查看实验板的说明文件,我们使用两个拨动开关来连接输入引脚,用一个led灯来连接输出引脚,对照说明中的表格,为pinA,pinB,pinC分配PIN_N25,PIN_N26和PIN_AE23,设定好后点击Assignment——>Device进入设定框,点击Device and Pin Options按钮,在Device and Pin Option框中的Unused Pins标签下将Reserve all unused pins设定为As output drivingground。因为我们的设计最终会以电路的表达形式工作,错误的设计极其容易导致实验板的损坏。

6, 下载程序

当然我们实际设计中可能会用到波形仿真工具进行验证,进行时间分析验证,甚至要设定布局布线等工作,反复迭代修正,才能完成一个复杂电路的设计,不过这里这个与门的demo很简单,完成以上设计工作后,可以开始编译了,点击Processing——>Start Compilation开始吧。如果没有错误,输出编译报告,就可以准备下载到实验板上去了。点击

Tool——>Programmer,打开下载工具。这里我们选择使用JTAG的下载方式,注意先给实验板上电,点击Start开始,等待片刻,走完下载进度条,下载完成。

7, 完成

现在你可以在实验板上通过SW0和SW1来设定与门的输入了,实验板上的LEDR0相应的亮或者灭。我们实现的与门在哪呢?就在你面前实验板的芯片中,实际上实验板的芯片中有很多电路单元,通过我们的编程选择我们需要的电路单元用连线连接起来,在通过配置引脚连接到FPGA芯片的外部引脚上,FPGA是焊接在PCB板上的,PCB板上的铜线把FPGA引脚与外部设备比如开关,发光二极管等连接起来,我们的电路就真正的连接到了这个系统当中了。他们之间的连接关系在图中表示出来。

8,总结

经过了这么多繁杂的步骤,我们仅仅完成的是一个简单的与门电路,好在通过这个过程我们只是了解一下FPGA设计的基本过程与简单操作,熟悉了这个流程,以上步骤还是很清楚的,而且实现一个复杂的设计也基本是沿这个过程走的。后面我们用FPGA实现一个CPU也可以这样下载到FPGA芯片当中,这可是一个真正的电路,真正工作的CPU,麻雀虽小五脏俱全,不再是仅仅在电脑上仿真了,你必然会满心欢喜。而且实际中,这样的设计(当然还有一些其他的工作要做),是能够送到工厂中去生产真正的ASIC专用电路,也就是真正的,我们能摸到能使用的CPU,会有这样的一天。 1, 使用MegaWizard添加一个RAM模块。

RAM模块属于原理图设计中一个较为复杂的模块,并非如一个简单的二输入与门那样直接添加就可以了,还有一些参数需要配置和设定。在QuartusII中添加一个类似RAM的复杂模块需要用到MegaWizard,通过使用MegaWizard添加一个RAM模块,可以了解如何用MegaWizard为库提供的模块配置参数。

依然是使用Symbol tool打开添加模块对话框,MagaWizard的模块多数在megafunctions目录下,我们使用的是megafunctions——>storage——>lpm_ram_dq,勾选上Launch MegaWizard Plug-In,OK,打开MegaWizard Plug-In Manager,选择为库文件生成的文件类型,有AHDL语言,VHDL语言和Verilog HDL语言三种选择,根据需要和自己对他们的熟悉程度选择,设定为其生成的目录文件,建议生成到工程所在目录下,并在其名称基础上加上些有意义的后缀。接下来是关于模块具体参数的设定,不同的模块会有所不同,这里请先按照图中的配置方式选择,使用8位容量32个字的RAM,不带有输出口寄存功能。 为了让RAM有一个初始值,我们要为其写个初始化数据文件,下面选中Yes, use this file for the memory content data,并设定好文件路径名称。下一步是生成文件的清单,最后Finish将生成模块添加到设计文件中。

2,添加总线与提取总线上一位数据的方法。

以上是通过MegaWizard添加模块的方法,用相同的方法,我们可以添加lpm_add_sub模块。

本例中涉及到的就是以上两种模块,通过联系和实践,可以测试试验一下其他的模块。 接下来添加输入输出引脚,这个前面介绍过,这里有点不同的是,输出引脚是8位的,这个在命名的时候后面加上[7..0]就表示是个8位的输出,例如fib_res[7..0],如果要用到其中一位就是名字加上下方括号跟标号,例如fib_res[5]。 3,用手动按钮作为时钟信号测试。

实验板上的时钟太快了,不利于我们观察,那就用仿真时学的办法,加一个输入按钮,模拟时钟,按一下,时钟跳一下,于是加了一个输入引脚,用于连接实验板上的按钮开关。输入引脚后面要加一个非门,因为实验板上松开按钮时候输入是高电平,所以用一个非门也就是反相器来取反向。

需要指出的是,用手动按钮做时钟信号来测试是一个权宜的方法,实际的设计中是不推荐的,包括组合电路的输出用做时钟信号都是不好的设计习惯,因为时序电路工作的时钟要求波形稳定,组合逻辑电路中产生波形的毛刺对其工作影响较大,造成错误的数据或不可预测的结果。

4,常量的加入。

由于加入的ram模块至少含有32个字的存储,只需用到其中一个,地址线置零就可以了,每次时钟来临都进行写入操作,那么写入使能始终设为Enable。那么这些常量该怎么设定呢?在原理图设计中,有GND和VCC两个常量,分别代表逻辑1和逻辑0,将他们引入到电路中就可以了,多位数据合并到一条总线上是将各位数据用逗号隔开,添加到总线命名中。

5,让你的电路更加清晰。

前面介绍到,当电路规模愈加复杂时,将各模块直接连接到一起会严重影响其清晰美观,那么推荐的方式是采用网络标识的形式,也可以为GND,VCC添加一个网络标识,把他们改名为b1和b0如图,那么内存地址我们可以写为b0 ,b0, b0, b0,b0。

再把上图整理一下,看看效果是否好一点了。

6,初始化RAM中数据

7,波形仿真工具

这里在学习一下使用QuartusII自带的波形仿真工具,新建一个Vector Waveform File。

在图中位置右击,搜索添加Node和Bus,在Insert Node or Bus框中点击Node Finder按钮,弹出Node Finder框,点击List将所有输入输出节点列出,添加到Selected Nodes中,OK。

选中clk_button,点击工具栏的Overwrite Clock,在Clock框中填好起始时间,结束时间,时钟周期等参数,为其添加一个时钟输入。

在编译过整个工程后,如无错误,点击Start Simulation,片刻后,仿真波形输出出来,仿真结果如图,由于只是8位存储器,所以233后面的数结果会有问题,但是仿真结果与我们设计的电路所应得到的输出效果是一致的。

8, 总结

这里我们学习了利用MegaWizard添加megafunctions库中的复杂模块,学习了如何使用Node和Bus,以及如何使用节点标识取代直接连线,是原理图层次划分更加清楚,另外还有如何进行波形仿真,对设计进行有效验证,基本在Logisim中可能用到的常用功能在QuartusII设计工具中都能找到。会使用Logisim构建一个电路,相应使用QuartusII工具的原理图设计也不会有难度了,当然他们库中包含的模块还有些不同,但一般常见的标准模块QuartusII都有,而是是我们在实际设计中会用到的标准接口标准功能的模块,要好好了解熟悉他们的用法。

设计一个7段数码管的控制逻辑电路,用于控制数码管显示,后面他将作为一个子模块添加到我们的顶层设计中。 1, 7段数码管译码电路

Hex 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC

Seg(binary) 11000000 11111001 10100100 10110000 10011001 10010010 10000010 11111000 10000000 10010000 10001000 10000011 11000110

0xD 0xE 0xF

10100001 10000110 10001110

共阳极数码管编码表

有的同学可能看到真值表就开始画卡诺图了,呵呵,其实可以偷一点懒,看看图中这种实现。

通过使用选择器实现的这种译码电路,完成了一个真值表到电路的转换,并且实现结构清晰,可读性很好。

1, 创建7段数码管的子电路

为设计好的数码管译码电路创建硬件描述语言文件,点击

File——>Create/Updata——>Create HDL Design File for Current File。

为设计好的数码管译码电路创建一个封装,点击File——>Create/Updata——>Create Symbol File for Current File,这样我们在顶层设计中就可以调用这个子电路了。 2, 把子电路应用到顶层设计中

添加刚才创建的子电路,点击Assignment——>Settings,在Settings对话框中的Libraries中添加刚才子电路的目录,现在在Symbol中可以看到刚才创建的子电路模块了,我们再添加一个计数器,以及需要的输入输出引脚,完成我们的设计吧。

3, 总结

这个例子主要是联系子电路的创建以及如何将子电路应用到顶层设计中,在复杂设计中,分层设计的方法是必须要掌握的。

至此,QuartusII中的原理图设计的基本操作方法就足够我们使用了,Logisim中所能完成的操作,在QuartusII中都能够对应起来,所以建议后面的设计中,我们来参考课件中的使用Logisim设计简单CPU的方法,对应在QuartusII中实现一个真正的CPU。 由于Logisim是一个仿真软件,使用较QuartusII方便一些,可以先行做实验,然后再用QuartusII实现设计方案。

至此,我们要真正开始CPU设计了,前面的内容是给不熟悉QuartusII的同学热身用的。这里都是假定同学们已经熟悉了QuartusII基本操作,会使用原理图设计方法设计电路,并且会使用MegaWizard添加标准模块,会分层设计电路。

需要说明的是,我们选择使用原理图的设计方法,是考虑与罗老板的课件相结合,能够对照Logisim的操作,使同学们在学会使用Logisim软件仿真设计出一个CPU后,平滑的过度过来。另外原理图的设计更加直观一点,更容易入门。当然由于实际设计中主流的方式还是使用硬件设计语言,推荐大家了解一下Verilog HDL,VHDL或System C等语言。 1,设计总揽

我们这里设计的是一个简单的16位处理器(即每个指令字长为16位,寄存器也是16位),该处理器有四个寄存器($r0到$r3)。具有独立的数据和指令内存(即有两个内存,一个指令内存,一个数据内存)。

需要注意的是由于器件的限制,也为了让事情更简单一些,我们以半字(16位)为单位对内存编址。这和MIPS 不同,MIPS指令是字长是32位,而内存是以字节(8位)为单位编址。 2,准备步骤

第一步:熟悉一下QuartusII的操作,这个在前面我们已经完成了,对应于Logisim中操作都介绍到了,后面完成Proj3所需要的技术也都具备了(当然,想深入的了解数字电路设计,可能需要更多),也就是说如果能够用Logisim完成Proj3,用QuartusII实现也不再话下。 第二步:做一下相关的实验,了解QuartusII下的一些模块和组件,如何建立简单模块,如何将简单模块构建到一起,成为复杂的模块,直至成为一个系统。MegaWizard中提供的是

数字电路中常见的标准模块,我们的设计中要用到其中一些模块,所以熟悉他们,熟练应用是完成设计的前提。 3, 阅读ISA 第三步:阅读ISA

ISA(Instruction Set Architecture)是硬件设计师跟软件设计师之间的协议,他规定了硬件设计师设计的CPU所需要具备的功能,以及软件设计师所能够使用的CPU指令。 设计一个CPU首先要设计一个ISA,之后才是软硬件设计:软件设计师设计汇编器,编译器;硬件设计师设计CPU。我们需要的ISA在Proj3这里已经给出了,如下表:

通过查询 opcode字段(高四位,即15-12位)的值,可知半字编码所对应的指令。注意,表中的opcode不到16个,而funct也不到8个。原因是指令少一些,使同学们更容易实现(呵呵,好象比老师上课讲的CPU指令数还是多了很多)。

(如果需要更加细致的了解原理,请认真学习罗老板课件中关于单指令周期CPU设计的这几节课的内容。)

我们可以了解到需要实现的几个基本模块:

1, 指令指针寄存器PC 2, 指令存储器ROM 3, 寄存器文件 4, ALU 5, 内存单元 6, 控制逻辑单元

一个大体的CPU的结构图:

4,总结

从分析结果来看,我们需要的实现的几个模块都在图中表现出来了,他们之间的关系也基本如上图所示,更详细的说明请参考罗老板的课件吧。

我们要设计中可能用到的库中的模块有以下几种,寄存器模块,RAM,ROM,算术以及逻辑运算单元比如加法器,移位,与或门等。

当然还有前面我们讲到的数据选择器,这个会在Controller中用到,另外在每个单元模块前做数据选择也会用到。

第四步:制作一个寄存器组(也称寄存器文件)模块(组件)。 1,输入与输出

根据前面设计总揽中得到的模块间的关系,设计出输入输出端口,包括rs,rt,rw,另外是rsBus,rtBus,当然还有使能控制,时钟,reset等。

2,寄存器

作为第一小步你可以先放四个寄存器,然后做出一个输出,即可选择四个寄存器中的任意一个的值输出。

注意:用MegaWizard生成模块文件的时候,别忘了加一个后缀,因为这里都是子模块设计,后面要应用到顶层设计中去,为避免各个子模块设计中引入的标准模块文件重名,推荐加一个子模块名字的后缀,例如lpm_dff_reg0,就表示reg模块中引入的lpm_dff模块。

3, 输入输出数据选择器

四个寄存器不能同时全部加到两个数据输出端口rsBus和rtBus上,rwBus一次也只能对一个寄存器写入,那么就需要相应的数据选择以及写使能控制。

4, 整体设计

全部完成好的原理图如下:

各个部分之间的关系如结构框图:

5, 总结

从设计一开始要养成良好的绘图习惯,以结构清晰为原则,设计按照一定顺序完成,比如这里的顺序就是:

输入输出端口——>核心模块——>数据通路控制 另外将各部分功能用注释文字标好,方便阅读。 书接上回……

第四步:制作一个ALU 输入输出端口

ALU的输入输出相对简单,输入是两个操作数和一个操作符,输出是计算结果。

各运算单元

为了节省片上资源,加减法器使用一个,用一根选择线控制加或减,逻辑左右移位也是用一根选择线控制左右移。

数据通路选择

上面的各运算单元是并行工作的,对于输入的两个操作数,几个运算单元都会计算结果,至于输出哪一个,要通过后面的数据选择器来控制了。选择器的选择开关接的是操作符,这样输出结果就是操作数对应的操作运算得到的的结果了。

第五步:制作一个PC指针寄存器 4,PC指针寄存器

关于PC指针的操作很多,有一般指令所需的PC+1操作(这里是+1操作,与课件中+4稍有不同,因为我们后面设计ROM的时候按16位数据线设计,每个地址存储的是16位数

据,那么PC+1就能读取完整的一条指令),另外还有绝对跳转需要的PC = (PC & 0xF000) | address,beq和bne指令所需的PC = PC + 1 + offset。

设计模块要求模块完成的功能尽量单一,模块的功能定义要清楚,上面跳转所需的address,判断所需的offset都是从指令中提取的,全部设计到PC寄存器模块中来,会使设计一下子变得复杂。在实现PC寄存器模块时,需要更多的外部信息,从而使顶层设计的修改会影响到子电路。所以PC寄存器就是由输入输出端口和一个寄存器组成,其余部分要放到控制逻辑和顶层设计中去。 5,总结

ALU暂时可以仅实现ADD,SUB,AND,OR以及移位,比较运算,将来再扩展更多功能。(对于各种运算单元有两种办法实现,其一是自己用基本的与或非门电路搭建,其二是直接使用QuartusII的MegaWizard库实现)。

PC寄存器的实现也很简单,基本在前面的基础上,完成一个ALU和一个PC寄存器不会遇到任何困难,我们这里关注的是模块的划分,模块功能的定义,高内聚,低耦合的设计不只是软件设计中提倡的,这也是硬件设计中推荐的。 原来很多道理是相通的

数据存储在RAM里,程序存储在ROM里,这是大家经常听到的,那么怎么设计一个存储数据的RAM和一个存储程序的ROM呢?这里我们就来亲手试验一下。

有一点要说明的QuartusII中提供的ROM和Logisim中提供的ROM模块有一点点不同,他们相差一根时钟线,虽然只有这一点不同,但却是很重要的一点,这就涉及到了一个组合逻辑实现的ROM与时序逻辑实现的ROM的区别。

这里给出了QuartusII中的两种实现方式,一种是用库中提供的模块,另一种是组合逻辑的实现方式,关于两者的不同究竟会产生怎样的影响,后面我们再详细讨论。 第六步:实现一个RAM

直接上图吧,基本操作的问题不多叙述了,有问题的话请查看前面的学习或者参考QuartusII的教程。

第七步:ROM的实现 用组合逻辑实现ROM的方法

用组合逻辑实现的ROM其本质是电路,如果感觉难以理解,你可以认为你的程序就是一堆门电路按某种顺序排列表示出来的,而不是存在真正意义的存储器当中,我们写程序的时候其实是搭建了一个电路。 这里给出一种实现方法

这是一个16个字的16位ROM,是用选择器实现的(前面说过了选择器是个有用的好东西), 由于只有16个存储单元,所以4位地址就能表示出来,ROM中的内容就是接到选择器data0x到data15x上的数据,每一次对ROM的编程写入,就是将综合的电路下载到FPGA实验板中。

2,用时序电路实现ROM

实际的ROM应该是可以在系统编程的,也就是说不改变电路结构,能够把程序写入ROM。 在QuartusII软件中库提供的ROM是时序电路实现的,我们时序电路实现的ROM跟RAM的形式是一样的,看图就知道了。

其实在QuartusII中ROM也是通过一个RAM实现的,引入的ROM中有这样的代码 ……

COMPONENT altsyncram GENERIC (

clock_enable_input_a : STRING; clock_enable_output_a : STRING; init_file : STRING; ……

widthad_a : NATURAL; width_a : NATURAL; width_byteena_a : NATURAL ); PORT (

clock0 : IN STD_LOGIC ;

address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0); q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0) );

END COMPONENT; ……

这里altsyncram经过封装,也就是MegaWizard的配置,引出相应的引脚,就成了一个ROM模块交给我们,在我们设计中调用了(上面是一段VHDL语言的代码,关于VHDL语言就不在这里详细介绍了)。

最后需要注意的是这个ROM模块用到我们顶层设计的时候不能用CPU的时钟,而是单独为其提供一个刷新输出数据的高速时钟。在介绍完整个CPU后,我们会把这样做的原因连

同说明组合逻辑与时序逻辑实现ROM的不同一起讨论。当然如果你现在有兴趣可以在自己的CPU设计中使用这个ROM模块的时候为其加上CPU的时钟,看看效果。 1,再次推荐使用库

在设计中,推荐大家使用库中的模块,因为库中的模块都是经过精心设计验证好的电路,并在长期的设计实践中反复验证的成熟方案,另外还有可能经过了专门的优化。

比如下面我们将用到一个比较典型的模块——选择器,选择器的一个比较典型的应用是根据已知逻辑关系,通过选择通路数据得出电路,就是说如果知道真值表的话,选择的通路设定为常量,选择开关为输入的逻辑值,通过这种类似解码的电路结构很容易的实现组合逻辑的功能,并且在程序、电路结构上有很好的可读性,结构也很清晰。 在下面控制逻辑开关表中,我们就使用了这种方法。 2,推荐的指令实现顺序

这里给一个推荐指令的实现顺序: lui和ori指令 andi和addi指令 R指令 j指令

beq,bne,lw和sw指令 3,顶层设计的条理

按照老师课上讲的CPU的几个模块,大致也为顶层设计划分出几块来,每一块的核心是前面设计的模块电路,由于要增加控制逻辑以及对输入数据进行处理,信号进入模块前,先通过选择端连接控制逻辑的选择器,根据指令不同,控制逻辑打开关闭不同的开关,控制选择输入每个模块的数据。 大致的示意图为

这样模块间数据是各个核心模块的输出,由于核心模块是采用的标准的库模块设计的,其输出数据的形式是标准的易被多数人接受的,从而使我们不必更多的考虑分块间数据的表示形式,无需再依赖更多的外部信息。

顶层设计是由这样一个一个的分块电路组成的,这是整个顶层设计图

其中输入选择都是由选择器实现的,可见选择器在设计中的应用是十分频繁的。

接下来对于一条条的指令,就是控制一个个选择器选择哪个数据输入到模块中了,控制逻辑就是把指令译码为一个个的通路选择开关。

我们把各部分模块控制参数的信息集中到这里,各个控制位的设定情况可以通过下表得出:

根据表中的信息,控制逻辑开关表电路也是用一个选择器实现,下图中给出了一个实现方法,图中可以清晰的从表中的位开关设置找到对应的数据位。

4,写程序测试

在你完成了CPU设计后,需要编写程序在CPU上运行以测试CPU能否工作。 试着将以下汇编指令翻译成机器码: add $2,$1,$0 add $1,$1,$0 add $1,$2,$0

然后将机器码存入指令内存中。

如果你成功地完成了此最简单的CPU,则时钟每跳一次,将执行一条指令。为了你看到一些有意义的结果,你可能需要手动设置一下各个寄存器的初值,这在仿真中可以较容易的实现,如将寄存器1的值设为1,寄存器2的值设为2,寄存器3的值设为3。但是硬件实现时候就要想一些别的方法了,前面推荐大家优先实现lui和ori指令就是这个道理。 首先让你的CPU能运行lui和ori指令是非常重要的,因为在程序中通过他们使CPU中的寄存器载入数据,让其他测试的数据初始化成为可能。在前面最后组合各功能模块,实现每条命令的控制逻辑时强烈推荐优先完成这两条指令,待这两条指令工作正常后,就可以用来测试其他指令了。

为了更好的观察输出结果一个数码管显示是必要的,应用这种选择器似的解码电路就能实现,选择端输入的要显示的16进制数据,各数据通路上的常量为0——f的数码管字段编码,这是一个典型的译码电路实现,当然使用ROM查表的方法也可以实现,不过要多一个刷新时钟,前面我们实现过数码管的译码电路了,使用它就可以了。

写几个程序测试你的CPU,把一条条指令都调试好,至此,你的Proj3中的CPU设计作业就完成了。

前面我们以尽量快的速度完成了Proj3的任务,但是还有一些问题遗留下来,这里我们就来讨论下这些问题。

1, Logisim与QuartusII的比较

前面已经提到,使用QuartusII进行数字电路设计,更多情况下使用的是硬件描述语言,硬件描述语言功能更加强大,标准更加规范,应用十分广泛。这里选择使用原理图的设计描述方式是为了让我们容易的从Logisim过渡过来。

从前面的内容来看,我们实验课上使用到的Logisim软件实现Proj3中CPU的设计所涉及到的操作,在QuartusII中对应的实现方式都一一对应的演示了,当然QuartusII软件的库中包含的电路模块可能会与Logisim中的有所差别。

Logisim是一款可视化的仿真软件,我们也是在学习罗老板的计算机组成原理课上第一次了解到的,基本算是实验用的,实验演示很方便。QuartusII是Altera公司用于自家器件设备的数字电路设计的软件,我们做实验用的DE2板子上的FPGA芯片就是Altera公司的,QuartusII软件可以完成硬件电路设计的整个流程。

Logisim的仿真表现效果比较直观,直接通过点击就能完成输入输出设定,模块间连线上的电平在电路实时运行中通过连线颜色表示出来。寄存器,RAM中的数据都能进行设定,包括在电路实时运行时。

QuartusII中仿真的方式也很多,比如自带波形仿真功能,另外可以使用第三方的仿真软件如ModelSim等。但是如果想直观的观察电路实时运行状态则不太容易,无论是设定电路初始状态,修改寄存器与RAM中的存储内容等,都不是很容易,所以要先实现一些简单模块,并设法将电路运行状态通过外部设备表现出来,设定一些调试开关,帮助设定电路状态。 2, 为什么是时序逻辑的ROM

这个问题可以这样解释,组合电路的ROM相当于使用电路搭建的,向ROM中写入一个程序,就相当于做一个电路。我们使用计算机,写一个程序进CPU,应该是能够在系统的把程序下载到ROM中,而不是把这个CPU拆了,重新设计一个,这样来说,用过单片机的同学可能更容易理解。

时序电路的ROM更接近于我们实际使用的ROM器件。 3, 为什么我们的ROM工作在另一个时钟下

这是Logisim中的RAM与ROM模块,他们的区别就在于下面的那个小三角,也就是时钟信号输入端,也就是说Logisim里面的ROM是不带时钟信号的。在QuartusII里面我们给出了两种实现方式,上面我们也指出来时序逻辑的ROM是更接近于实际设计中的ROM,所以我们使用时序逻辑的ROM实现方式。

这里重点是这一张课件,在伯克利2010CS61C课程的

2010SpCS61C-L26-ddg-1cyclecpuII-6up里面,从中我们可以清楚的看到一个完整CPU工作周期里,从寄存器输出到计算的结果写入寄存器,各部分信号的更新过程。

一个时钟周期内电路分别进行下面几个工作步骤: 时钟到达Instruction Memory的时候。 读出当前周期执行指令

指令通过译码模块即一个Mux电路选出控制逻辑部分的控制信号 从指令中取立即数部分,或者rs,rt,rw等

控制信号与立即数数据到达各模块部分 根据rs,rt,寄存器文件输出相应数据 ALU计算得出相应结果

时钟到达Data Memory的时候。

如果是sw指令,将数据写入Data Memory。 时钟到达寄存器文件的时候。

如果是lw指令或其他写寄存器的指令,将数据写入rw寄存器。

每一步至最后电路保持到稳定状态,需经历了一段时间,经过这个延时后,时钟信号到达下一步相应模块的位置,这样整个电路才能有足够时间进入稳定状态,否则在进入稳定状态前写入寄存器,写入内存的数据将是错误的,甚至是结果不可预测的紊乱数据。

对于上面几个步骤,即准备电路组合逻辑——>写入内存——>写入寄存器。由于唯一内存写入指令sw的同时并不做写寄存器的操作,那么Data Memory和寄存器文件的时钟一致。 这里整个过程没有时钟到达ROM更新ROM输出信号的步骤,对于没有时钟信号ROM,输出信号随地址改变而改变这没有问题,与前面的实现结果相一致,因为即使ROM输出信号改变由于组合逻辑的延迟,但这个传输延迟在一个CPU时钟周期内信号到达稳定状态的过程中的,不会影响最终的结果。

那么增加了一个时钟其实是相当于在ROM前级增加一个地址锁存,那么就把整个电路有由一个时序电路分出了又一个时钟状态,即PC寄存器前一个时钟状态,PC寄存器至ROM的地址锁存寄存器前一个时钟状态,ROM地址锁存寄存器后面一个时钟状态,这样PC指针要在两个时钟周期后才能更新到ROM输出端。

使ROM工作在另一个时钟下(使远高于CPU工作时钟),就相当于高速刷新ROM的输出,模拟出了组合逻辑实现中ROM输出随输入改变即改变,而无需等待工作时钟的效果。 4, 再起一段

在学习罗老板的计算机组成原理的课程时,笔者了解了mips体系结构的CPU,在做课程实验Proj3中用Logisim体验了一把设计CPU的瘾。罗老板的课程是翻译的伯克利大学的CS61C,国外大学在讲组成原理这门课时的确与国内有很大不同的,感觉最明显的就是让

你在实践中学习理论,让你上组成原理这种枯燥的理论课程时也不再瞌睡,^_^。于是我不禁产生了用FPGA实现下课程实验Proj3的想法,并决定将自己的实验记录下来。 停更两天,查下资料,接下来该思考完善这个CPU了,在Proj3的基础上将有更大的提高……

本文来源:https://www.bwwdw.com/article/97l7.html

Top