用FPGA实现嵌入式微处理器

  • 时间:
  • 浏览:1

assign regfile[14] = 8'h01;

assign regfile[9] = 8'h100;

在使用硬件描述语言时,一定要时时刻刻想着硬件形态,没法了仅从逻辑上编写代码,硬件描述语言和编程语言有很大不同。RAM的双向端口也没法了想通了三态门在电路中的应用后才编写成功的。

行。有如果它没法了具有以下基本功能:

assign regfile[6] = 8'h87;

实验结果:

首次尝试了用机器码编写守护进程。

(8)地址多路器:

(2)累加器;

第有有有兩个时钟,若操作符为AND、ADD、XOR或LDA,读相应地址的数据;若为JMP,将目的地址送给守护进程计数器;若为STO,输出累加器数据。

五、基于PopCorn(PC)核搭建什儿 人的系统

1、ROM

写好的机器码没法了放入去守护进程存储器ROM中,以被CPU读取并执行。在编写ROM如果,没法了知道CPU读取ROM的时序,而下载的压缩包中没法了相应的资料,有如果没法了通过其它方式得出时序图。最简单可行的方式是黑匣子仿真测试,即提供CPU时钟,观察其地址总线,数据总线和各控制信号的变化,从而得出时序图。

//结果表明应该是1。

(7)守护进程计数器:

assign regfile[0] = 8'h87;

将cpu的功能进一步细化,可概括如下:

(3)执行指令—根据分析指令时产生的“操作命令”形成相应的操作控制信号序列,通过运算器、存储器及输入/输出设备的执行,实现每条指令的功能,其中包括对运算结果的外理以及下条指令地址的形成。

第7个时钟,若操作符为SKZ且累加器值为0,则PC值再增1,跳过第一根指令,有如果PC无变化。

3、简单的动态效果

所以CPU、ROM和端口还可以 正常使用。

指令寄存器用于寄存指令。

assign regfile[11] = 8'h00;

三、FPGA中实现CPU

(1)状态机;

(1)时钟发生器:

仿真结果:

第0个时钟,意味着CPU状态控制器的输出rd和load_ir为高电平,其余均为低电平。指令寄存器寄存由ROM送来的高8位指令代码。

assign regfile[8] = 8'h00;

(5)数据控制器:

(2)没法了了进行算术和逻辑运算;

//将累加器中的数据存到RAM地址0x0000中

assign regfile[1] = 8'hf0;

累加器用于存放当前的结果,它也是双目运算包暗饱含兩个数据来源。复位后,累加器的值是零。当累加器通过ena口收到来自CPU状态控制器load_acc信号时,在clkl时钟正跳沿时就收到来自于数据总线的数据。

仿真图中,要花费把机器码C8,23,01依次放入去ROM地址的0,1,2中,要花费指令JMP 0x0123。在仿真结果中,CPU取完前3条指令后,的确跳转到地址0x0123去读取指令了。

读写RAM时序测试:

第十个 时钟,若操作符为ANDD, ADD或XORR,算术运算器就进行相应的运算;若为LDA,就把数据通过算术运算器送给累加器;若为SKZ,先判断累加器的值是不是 为0,意味着为0,PC就增1,有如果保持原值;若为JMP,锁存目的地址。若为STO,将数据写人地址处。

指令寄存器的触发时钟是clkl,在clkl的正沿触发下,寄存器将数据总线送来的指令存入高8位或低8位寄存器中,但并都是每个clk 1的上升沿都寄存数据总线的数据,意味着数据总线上有时传输指令。有时传输数据。什儿 如果寄存,什儿 如果不寄存由CPU状态控制器的load_ir信号控制。load_ir信号通过ena口输入到指令寄存器,复位后,指令寄存器被清为零。

为了还可以 用实验验证CPU功能,上述有有有兩个模块是必不可少的。在ROM中写有有有兩个最简单的守护进程,向端口寄存器置一特定数字,在实验板上观察小灯的亮/灭,从而验证系统运行正确是不是 。ROM区控制CPU的机器码如下:

(l)取指令—当守护进程已在存储器中时,首先根据守护进程入口地址取出第一根守护进程,为此要发出指令地址及控制信号。

(2)指令寄存器:

实验结果:

(1)能对指令进行译码并执行规定的动作;

学习了FPGA中实现CPU的方式,并进行了初步尝试,取得了部分的成果。

CPU即中央外理单元的英文缩写,它是计算机的核心部件。计算机进行信息外理可分为有有有兩个步骤:

assign regfile[6] = 8'hc8;//JMP,无条件跳转到本条一句话

二、CPU原理介绍

1、什儿 是CPU

此外,上述结果是在笔者对原IP代码稍做修改后才得出的,原先代码的仿真结果中,在读、写RAM时都再次出先code_rd_l信号,而都是再次出先code_wr_l信号,改完会花费能区分是读还是写了。

assign regfile[1] = 8'h0f;//被装载的立即数

(2)分析指令—即指令译码,是对当前取得的指令进行分析,指出它要求什儿 操作,并产生相应的操作控制命令。

(4) RISC_ CPU算术逻辑运算单元:

由时序图可知,读取ROM的过程和常见的总线读方式相同,即现给出选通信号code_cs_l,有如果给出读信号code_rd_l。按此时序给出一简单指令,验证该时序。

assign regfile[2] = 8'h01;

assign regfile[13] = 8'h00;

原先,便没法了了放心大胆地编写ROM和其中的机器码了。

assign regfile[10] = 8'h00;

第有有有兩个时钟,空操作。

assign regfile[3] = 8'h68;//STM,将累加器中的数输出到RAM空间中

数据控制器的作用是控制累加器数据输出,意味着数据总线是各种操作时传送数据的公共通道,不同的状态下传送不同的内容。有没法了砖输指令,有没法了传送RAM区或接口的数据。累加器的数据没法了在没法了往RAM区或端口写时才允许输出,有如果应呈现高阻态,以允许什儿 部件使用数据总线。所以任何部件往总线上输出数据时,没法了了一控制信号。而此控制信号的启、停则由CPU状态控制器输出的各信号控制决定。数据控制器何时能 输出累加器的数据则由状态控制器输出的控制信号datactl_ena决定。

指令集(Pc_spec.pdf):

为了还可以 正确地使用这款CPU,没法了了解它的指令系统,资料中的相关部分如下:

assign regfile[4] = 8'h00;//低地址

assign regfile[3] = 8'h68;

assign regfile[5] = 8'h01;//高地址。0x0100地址对应于端口寄存器。

守护进程计数器用于提供指令地址,以便读取指令。指令按地址顺序存放入去存储器中。有什儿 途径可形成指令地址:其一是顺序执行的状态,其二是遇到要改变顺序执行守护进程的状态,类似执行JMP指令后,没法了形成新的指令地址。下面就来完整篇 说明PC地址是如可建立的。

assign regfile[2] = 8'h01;//按照资料中给的数据,应该是0代表累加器,但测试

assign regfile[4] = 8'h00;

复位后,指令指针为零,即每次CPU重新启动将从ROM的零地址如果刚现在开始读取指令并执行。每条指令执行完需有有有兩个时钟,这时pc_addr已被增2,指向下第一根指令(意味着每条指令占有有有兩个字节立。意味着正执行的指令是跳转一句话,这时CPU状态控制器意味着输出load_pc信号,通过load口进入守护进程计数器。守护进程计数器(pc_addr)将放入去目标地址(ir_addr),而都是增2。

(3)守护进程计数器;

算术逻辑运算单元根据输入的8种不同操作码分别实现相应的加、与、异或、跳转等8种基本操作运算。利用这几种基本运算没法了了实现所以种什儿 运算以及逻辑判断等操作。

时钟发生器clkgen利用外来时钟信号clk生成时钟信号clk1、fetch、alu_clk,送往CPU的什儿 部件。其中,fetch是内部内部结构时钟clk的8分频信号,利用fetch的上升沿来触发CPU控制器如果刚现在开始执行第一根指令,一起fetch信号还将控制地址多路器输出指令地址和数据地址;clkl信号用作指令寄存器、累加器、状态控制器的时钟信号;alu_clk则用于触发算术逻辑运算单元。

地址多路器用于选择输出的地址是PC(守护进程计数)地址还是数据/端口地址。每个指令周期的前有有有兩个时钟周期用于从ROM中读取指令,输出的应是PC地址;后有有有兩个时钟周期用于对RAM或端口的读写,该地址由指令给出。地址的选择输出信号由时钟信号的8分频信号fetch提供。

四、本实验所用CPU核

基本思路是将端口映射到特定的RAM空间中,向该RAM地址写数据便将数据写到了端口锁存器中。

assign regfile[0] = 8'h87;//LDI,将立即数装载到累加器中

该CPU提供了有有有兩个8位的IO端口,但同样没法了提供如可对其操作。笔者猜想是对PORT寄存器进行操作来控制IO口。但双向端口的方向是如可选择就谁能谁能告诉我了。做了几次尝试失败后,笔者决定什儿 人来写个简单的单向输出端口。

每条指令为有有有兩个字节,即16位。高3位是操作码,低13位是地址(CPU的地址总线为13位,寻址空间为8K字节)。本设计的数据总线为8位,所以每条指令需取两次。先取高8位,后取低8位。

笔者所采用的是最后什儿 方式,即下载免费IP核来使用。什儿 免费的IP核通常都是功能简单的,不完善的,仅供学习交流用途的。也正是简单、不完善等特点,使得免费IP核比较适合初学者。原先既没法了了加深对CPU的理解,又不至于太过繁复。

六、仿真、综合、实验

1、验证CPU、ROM、端口

http://www.eefocus.com/book/08-01/3285412710058786.html

(2)从第第一根指令的地址起如果刚现在开始执行该守护进程,得到所需结果,如果现在开始运行。

assign regfile[15] = 8'hc8;

通过课程设计,了解了CPU的原理,对CPU取指令,执行指令的过程有了比较深入的认识。

assign regfile[17] = 8'h00;

assign regfile[5] = 8'h00;

//将立即数“F0”装载到累加器中

第十个 时钟,PC增1,指向下第一根指令。若操作符为HLT,则输出信号HLT为高;意味着操作符不为HLT,除了PC增1外(指向下第一根指令),什儿 各控制线输出为零。

assign regfile[7] = 8'h06;// 跳转到地址0x0006,外理不可预测的结果

//为了证明累加器中的数据是从RAM中读出来的,而都是原先装载的,所以故意在读//RAM如果将累加器清零。

早期的FPGA意味着其资源很少,没法了实现简单逻辑,所以其在板级系统中所起的作用就是简单的“粘贴逻辑”, 连接CPU与外设,以取代的传统的琐碎的专用集成芯片(ASIC)。

上图为CPU写RAM时序。机器码68,23,01对应指令STM 0x0123。在读完什儿 指令后,RAM选通信号sram_cs_l和总线写信号code_wr_l先后被给出,与此一起地址总线为0x0123。但奇怪的是读信号code_rd_l也被给出,不过好在读和写操作没法了了区分开,通过有有有兩个简单组合逻辑电路就没法了了把信号code_wr_l、code_rd_l翻译成你会的RAM读、写信号。什儿 外理方式也意味着带来隐患:在写RAM时,code_wr_l、code_rd_l到来时刻的细微差别意味着给翻译输出的写信号带来毛刺,即竞争/冒险问提。

(5)时序和控制部件。

仿真结果:

2、RAM

为了使CPU实际可用,仅用CPU内部内部结构的寄存器是远远缺乏的,没法了有足够的RAM空间。测试RAM时序的指令采用LDM和STM。

另什儿 方式是把亲戚朋友 意味着写好的CPU代码直接拿来使用。什儿 已写好的模块代码称作IP核。 IP核的获取方式有几种:向厂商购买有知识产权的IP核代码;用IP核生成软件(如Xilinx的EDK等)生成可定制的IP核;从网络上下载免费的IP核等。

状态机控制器接受复位信号RST,当RST有效时通过信号ena使其为0,输入到状态机中停止状态机的工作。

第6个时钟,空操作。

本实验仅完成了及其简单的功能,有如果CPU守护进程的量不大,没法了了手工逐个地写到verilog代码中。对于大型的守护进程,什儿 方式显然不可行,没法了编译器将高级语言编译成机器码,生成机器码文件,笔者初步想到的方式是利用硬件描述语言中的文件操作一句话和循环一句话来把文件中的机器码读进来,再写进ROM中。

(3)累加器:

根据CPU的指令系统,验证RAM的方式是向RAM区中写数据,再读出来,有如果写到端口中,看小灯的亮灭。

(4)提供整个系统所没法了的控制。

(4)指令寄存器、译码器;

//死循环

状态机是CPU的控制核心,用于产生一系列的控制信号,启动或停止什儿 部件。CPU何时能 进行读指令读写I/O端口、RAM区等操作,都是由状态机来控制的。状态机的当前状态,由变量state记录,state的值就是当前什儿 指令周期中经过的时钟数〔从零计起)。

(3)能与存储器及外设交换数据;

//将RAM地址0x0000处的数据放入去累加器

(2)状态机控制器。

与指令对应的机器码(opcode.dat):

数字“0F”被成功送到输出端口“port”。



小灯显示数字“F0”,实验成功!

编写RAM的注意事项:

如果写的RAM中发生BUG,主就是双向端口带来的麻烦,没法了三态门。而如果三态门的关闭时刻采用的RD信号的上升沿,意味着CPU有意味着是在此刻锁存数据的,所以此时关闭三态门意味着意味着CPU读到的数据是“ZZ”而都是“F0”。如果该成CS信号的上升沿才关闭三态门,原先还可以 保证数据被可靠读入CPU。

什儿 改变没法了用状态机来实现。意味着三态门的开、关是由RD的下降沿和CS的上升沿一起控制的,而边沿敏感列表没法了有有有有兩个变量,有有有兩个always块又没法了给同有有有兩个变量赋值,没法了写在同有有有兩个always块中,没法了RD和CS信号就没法了为电平敏感信号了,但在每次读RAM时,是先置低CS,有如果置低RD,有如果拉高RD,有如果再拉高CS,在前后都是RD高、CS低的状态,而这什儿 状态是不同的状态,有如果没法了状态机来实现。

有如果意味着前面的分析,在RD信号的下降沿锁存了地址对应的数据,有如果就能正常使用了。

RAM形态见下图:

assign regfile[16] = 8'h0f;

成功实现用小灯显示数字“0F”。

本实验所用CPU核是从网络上下载的一款名为PopCorn的mini CPU,其形态如下图所示:

ROM区的机器码守护进程如下:

状态控制器由两部分组成:

上图为CPU读RAM时序。机器码100,23,01对应指令LDM 0x0123。在读完什儿 指令后,RAM选通信号sram_cs_l和总线读信号code_rd_l先后被给出,与此一起地址总线为0x0123。此时序有有有有兩个隐患:在读信号上升沿的如果,地址总线意味着不再保持原先的数据,这就要求设计的RAM没法了早在读信号下降沿的如果就将地址锁存,以保证在读信号上升沿那一时刻,RAM仍然提供正确的数据(尽管此刻的地址意味着意味着不正确了)。

没法了了用硬件描述语言(VHDL或verilog等)直接构造CPU,即构伟大的伟大的发明上述各个模块,有如果整合成CPU。但庞大的代码量使得什儿 方式在短期内先要实现。

assign regfile[7] = 8'h00;

指令格式(Pc_spec.pdf):

数据“F0”嘴笨 再次出先在了端口上,说明RAM在仿真层次上嘴笨 没法了了正常工作。

CPU的作用是协调并控制计算机的各个部件执行守护进程的指令序列,使其有条不紊地进

用指令JMP验证时序:

测试ROM读信号时序:

(6)状态控制器:

assign regfile[12] = 8'h68;

尽管各种CPU的性能指标和形态细节各不相同,但它们所能完成的基本功能相同。由功能分析可知,任何什儿 CPU内部内部结构形态要花费应饱含下面什儿 部件:

//将累加器中的数据输出至端口寄存器

(1)算术逻辑运算部件(ALU);

一、背景简介

第l个时钟,与上一时钟相比就是inc_pc从0变为1,故PC增1,ROM送来低8位指令代码,指令寄存器寄存该8位代码。

(1)将数据和守护进程(即指令序列)输入到计算机的存储器中;

、‘

随着FPGA集成度的增加,其所能提供的资源就是断增多,rom、ram、CPU等庞大的繁复的形态也逐渐能在FPGA中实现,从而有了“片上系统”(SOPC――System On a Programable Chip)。

下载的IP核压缩包中附带了汇编的编译器(编译器的C语言代码也已给出),其作用是对照表opcode.dat将汇编代码编译成机器码。意味着测试编译器的功能失败(把压缩包中的汇编语言写的例程直接拿来编译,产生的二进制文件完整篇 为“CD”),有如果考虑到汇编语言和机器码之间基本上是一一映射的关系,直接写机器码的工作量不不比写汇编语言多几次,有如果花所以的时间去看懂并调通编译器的C语言代码就显得什儿 得不偿失了,不如直接写机器码实用。

assign regfile[8] = 8'h01;

指令周期由8个时钟周期组成,每个时钟周期都是完成固定的操作。

这是有有有兩个“裸”的CPU,即RAM、ROM等寄存器没法了什儿 人打上去,还可以 构成有有有兩个可用的小系统。