Altera Nios II处理器简介
本文介绍的Altera Nios II处理器是一个可在Altera FPGA器件里实现的软核处理器。主要讲述Nios II的基本架构和其指令集。配合Quartus II软件,使用Altera的SOPC Builder可以很容易的把Nios II处理器和它的内存及外围组件例化。
关于Nios II处理的完整描述请参阅《Nios II处理器参考手册》,在Altera官网的文献区可找到该手册。SOPC Builder的简介在入门简介里有提供,也可在官网的大学计划板块找到。
本文包含的内容:
目录
Altera Nios II处理器是一个软核处理器,用硬件描述语言定义,使用Quartus II软件可在Altera的FPGA器件里实现。本文为想要在Altera DE2开发板上实现一个基本Nios II系统的用户提供一个关于Nios II处理器的简介。
1 Nios II系统
Nios II处理器可使用许多其他组件构成一个完整的系统。这些组件包括许多标准外设之外,还可由用户自定义外设。Altera DE2开发板含有几个可集成在Nios II系统里的组件。图1就是一个这样的系统。
Nios II处理器和用来连接DE2上其他芯片的接口都在Cyclone II FPGA里实现。这些组件通过Avalon 交换结构连接。Cyclone II器件的内存块可为Nios II处理器提供片上内存。它们可直接或通过Avalon网络与处理连接。通过相应的接口访问DE2上的SRAM和SDRAM。系统使用的I/O设备例化为I/O接口。连接主机和DE2的USB线缆接口由一个特殊的JTAG UART接口提供。这个接口电路和其相应的软件叫做USB_Blaster。另一个名为JTAG Debug的模块,用来使主机控制Nios II处理器。这样,就可以执行操作,比如,下载程序到内存里,启动和停止执行,设置程序断点,和搜集实时数据。
既然在FPGA里实现的Nios II系统的每个部分都由硬件描述语言定义,那么一个熟练的用户可以书写并实现系统的任一部分。这是一个繁琐又费时的任务。所以,我们用Quartus II软件里的SOPC Builder,只需要选择需要的组件并指定参数就可实现目标系统。
2 Nios II处理器特性概览
要实现目标系统,Nios II处理器有许多特性需要配置。3种不同的配置可实现处理器:
l Nios II/f 是高性能的版本。它有很多配置,可用来优化处理器的性能。
l Nios II/s 是标准版本,需要较少的资源,性能也有所降低。
l Niso II/e 是经济版,使用最少的资源,可配置的特性也最少。
Nios II处理器是精简指令架构(RISC)。其算术和逻辑运算的操作数在通用寄存器执行。
通过Load和Store指令在内存和寄存器之间传送数据。
Nios II处理器的字长为32 bits。所有的寄存器都是32 bits。32-bit的字节地址可用从小到大或从大到小的风格赋值。在配置时,用户可能会选择一种赋值风格。本文使用从小到大的风格。
Nios II架构使用单独的指令和数据总线,通常叫做哈佛架构。
Nios II处理器可能以以下3种模式操作:
l 管理模式 ——允许处理器执行所有的指令和功能。当处理器复位后,进入这种模式。
l 用户模式——这种模式的意图是防止某些用于系统进程的指令的执行。在这种模式,某些特性不可用。
l 调试模式——用于软件调试工具,比如设置断点和观测点。
应用程序可在用户模式或管理模式运行。目前可用的Nios II处理器版本不支持用户模
式。
3 寄存器结构
如图2所示,Nios II处理器有32个32-bit的通用寄存器。其中一些有特殊用途并指定汇编器识别的名字。
l 寄存器r0作为0寄存器。它通常包含常数0.因此,当它写无效时,读这个寄存器的返回值为0.
l 寄存器r1被汇编器作为临时寄存器使用,在用户程序里不应提到它。
l 寄存器r24和r29用于处理表达式;它们在用户模式不可用。
l 寄存器r25和r30是JTAG调试模式专用。
l 寄存器r27和r28用于控制Nios II处理器使用的栈。
l 寄存器r31用于保存子程序调用的返回地址。
如图3所示,有6个32-bit的控制寄存器。名称为汇编器可识别的命名。这些寄存器用于自动控制。在管理模式,用特殊指令rdctl和wrctl可读和写这些寄存器。这些寄存器的使用如下:
l 寄存器ctl0反应处理器的操作状况。这个寄存器只用2-bit有意义:
-U是User/Supervisor模式位;U=1是用户模式,而U=0是管理模式。
-PIE是处理器中断使能位。PIE=1,处理器接收外部中断,而PIE=0,处理器忽略外部中断。
l 寄存器ctl1在表达式处理时保存一个状况寄存器的拷贝。Eu和EPIE位是保存的U和PIE位的值。
l 寄存器ctl2在调试断点时保存状况寄存器的拷贝。BU和BPIE位是U和PIE位的值。
l 寄存器ctl3用于使能独立的外部中断。每位对应一个中断irq0到irq31.值为1表示中断使能,为0表示无效。
l 寄存器ctl4表示在等待那个中断。如果中断irqk有效并且由中断使能位ctl3k为1使能中断,ctl4k的值为1。
l 寄存器ctl5保存用于多处理器系统里识别处理器的值。
4 访问内存和I/O设备
图4显示一个Nios II处理器如何访问内存和I/O设备。为获得最佳性能,Nios II/f处理器可包含指令和数据缓存。用FPGA的内存块实现这些缓存。使用SOPC Builder在生成系统是指定使用选项和大小。Nios II/s可包含指令缓存。Nios II/e没有缓存。
另一种让处理器快速访问片上内存的方法是使用紧耦合存储器排列,这样,存储器通过一个直接路径访问内存,而不是通过Avalon网络。访问一个紧耦合内存旁路内存缓存。可能由一个或多个紧耦合指令和数据内存。如果在系统里不包含指令缓存,对于Nios II/f和Nios II/s处理器必须至少有一个紧耦合内存。通过Avalon网络当然也可以访问片上内存。
非片上存储设备,比如SRAM,SDRAM和Flash通过例化相应的接口来访问。输入/出设备做内存映射可当做内存位置来访问。
通过Load和Storte指令访问内存位置的数据和I/O接口。
5 寻址
Nios II处理器有32-bit地址,其内存空间按字节划分。指令可读写字(32-bit),半字(16-bit),或字节(8-bit)的数据。读或写一个不依赖已存在的内存或I/O位置的地址产生一个未定义的结果。
有5种地址模式:
l 快速模式——在指令里给定一个16-bit的操作数,当执行算术运算时可扩展为32-bit。
l 寄存器模式——操作数在处理器的一个寄存器里。
l 位移模式——有效的地址是一个寄存器和一个有符号的16-bit位移值的和。
l 寄存器直接模式——操作数的有效地址是指令指定的寄存器的内容。等效于位移模式里位移值为0的情况。
l 绝对模式——一个操作数的16-bit的绝对地址可用位移模式里寄存器r0总是0来指定。
6 指令
所有的Nios II指令都是32-bit长。除了处理器直接执行的机器指令外,Nios II指令集包含许多可在汇编语言里使用的伪指令。汇编器用一个或多个机器指令替代每条伪指令。
图5列出3种可能的指令格式:I,R,J。每种情况下,b5-0表示OP码。其他位指定寄存器,快速操作数或扩展OP码。
l I-type:5-bit的区域A和B用于指定通用寄存器。一个16-bit区域IMMED 16提供可扩展为32-bit的快速数据。
l R-type:5-bit的区域A和B,C用于指定通用寄存器。一个11-bit区域OPX用于扩展OP码。
l J-type:一个26-bit区域IMMED26含有一个无符号的立即值。这种格式仅用于指令调用。
以下章节主要讨论Nios II指令集的特性。更完整的描述,参阅手册。
6.1 Load和Store指令
Load和Store指令用来在内存(和I/O接口)和通用寄存器之间传送数据。它们是I-type。比如,加载字指令
决定了内存位置的有效地址是偏移字节的值与寄存器A的内容之和。16-bit的字节偏移值可扩展为32-bit。32-bit的内存操作数加载到寄存器B。
比如,假定寄存器r4的内容是(1260)10,字节偏移值是(80)10.那么,指令
将在内存地址为(1340)10的32-bit的操作数加载到寄存器r3.
Store指令的格式是
它将寄存器B的内容存到地址为字节偏移与寄存器A的内容之和的位置。
有只使用8和16-bit操作数的Load,Store指令。参考Load/Store 字节和Load/Store半字指令。这些Load指令是:
当一个较短的操作数加载到一个32-bit的寄存器里,它的值必须与寄存器适配。在ldb和ldh指令里通过符号扩展使得8-bit或16-bit的值变为32-bit。在ldbu和ldhu指令里,将操作数补0扩展。
相应的Store指令是:
Stb指令将寄存器B的低字节存到有效地址指定的内存字节。指令sth将寄存器B的低半字存储。这种情况下,有效地址必须半字匹配。
每条Load和Store指令都有一个访问I/O设备位置的版本。这些指令是:
不同之处在于如果存在其中一条,这些指令绕过缓存。
6.2 算术指令
算术运算操作的数据要么在通用寄存器里,要么是指令给定的立即数。这些指令是R-type或I-type。它们是:
加指令
将寄存器A,B的内容相加,和保存在寄存器C里。
立即数的加指令
将寄存器A的内容和指令给定的16-bit的符号扩展数相加,和保存在寄存器B里。这些加指令对有符号数和无符号数的操作相同;操作未设置条件标记。这意味着当执行无符号数相加运算时,最高位的进位需要一个单独的指令检测。类似,有符号数相加时,要单独检测算术溢出。6.11节将讨论如何检测。
减指令
从寄存器A里减去寄存器B的内容,差保存在寄存器C。同样,进位和溢出需要使用另外的指令检测。
立即数的减指令,其实是下面的伪指令
乘指令
将寄存器A、B的内容相乘,积的低32-bit保存在寄存器C里。操作数作为无符号数看待。进位和溢出另外检测。其立即数版本
16-bit的立即数符号扩展为32-bit。
除指令
寄存器A的值除以寄存器B的值,商的整数部分保存在寄存器C。操作数作为有符号数看待。Divu指令类似,除了将操作数看做无符号数之外。
6.3 逻辑指令
逻辑指令有and,or,xor和nor。操作数由通用寄存器或立即数提供。这些指令是R-type或I-type。
And指令
对寄存器A和B的值按位求与,结果保存在寄存器C。其他逻辑指令操作类似。
And立即数指令
按位将寄存器A和立即数IMMED16与,立即数补0扩展为32-bit,结果保存在寄存器B。
在逻辑运算里,有可能用16-bit的立即数作为高16位,这样低16位就是0.用以下指令操作:
6.4 Move指令
Move指令将一个寄存器的内容复制到另一,或给寄存器写一个立即值。
将寄存器A的值复制到寄存器C,效果类似
Move立即数指令
将立即数符号扩展为32-bit,并加载到寄存器B。效果类似
Move无符号立即数指令
立即数补0扩展为32-bit,加载到寄存器B。效果类似
Move立即地址指令
加载地址LABEL的32-bit的值到寄存器B。效果类似
这里的%hi(LABEL)和%lo(LABEL)是汇编器的宏,获得32-bit的LABEL值的高、低16位。指令orhi设置寄存器B的高位,指令ori设置寄存器B的低位。注意,应为I-type格式的立即数是16-bit,所以这里用2条指令。
6.5 comparison 指令
Comparison指令比较2个寄存器的值或寄存器的值与立即数的值比较,保存比较的结果。它们是R-type或I-type。这些指令与C语言里的相应操作类似。
小于
比较rA<rB,为真则写1到寄存器C,为假则写0.
其他这个类型的指令有:
立即数比较指令。
如果rA<IMMED16,写1到B,反之写0.
无符号的值的比较。
其他指令:
6.6 shift指令
Shift指令将寄存器的值向左或有移。它们是R-type。类似C语言里的<<,>>。这些指令有:
6.7 Rotate指令
有3条rotate指令,使用R-type格式:
6.8 分支和跳转指令
Branch和Jump指令可改变程序的执行流程。
Jump指令
无条件分支指令
6.9 subroutine linkage指令
Nios II有2条调用子程序的指令。
6.10 control指令
控制寄存器的读写。
6.11 carry和overflow指令
7 汇编器指令
8 程序范例
9 异常处理
10 缓存
11 紧耦合内存
Reference
Introduction to the Altera Nios II soft Processor