2.5 使用 Qsys创建 Nios II 系统2.5.1 Qsys简介
Qsys包含在Quartus II软件中,它为建立SOPC设计提供了图形化环境,是早期Quartus II软件中SOPC Builder版本的升级,在保持基本功能不变的前提下,增加了系统建设的灵活性。 SOPC由CPU、存储器接口、标准外设和用户自定义的外设等组件组成。Qsys允许选择和自定义系统模块的各个组件和接口。利用Qsys,用户可以很方便地将处理 器、存储器和其它外设模块连接起来,形成一个完整的系统。Qsys中已经包含了 Nios II处理器以及一些常用的外设IP模块,用户也可以设计自己的外设IP。用户在Qsys中定义Nios II系统的硬件特性,例如使用哪个Nios II内核,系统中包括什么外设。 Qsys不定义软件操作,例如存储器中哪里存储指令或哪里发送stderr字符流,这些 工作在Nios II HDE中完成,见2. 9. 2小节。
Avalon总线和外设的配置是在Qsys的图形用户界面(GUI)中指定的。用户 在GUI界面中指定各种参数和选项,这些参数和选项会存入一个系统qsys文件。qsys文件是一个文本文件,它完整地定义了以下内容:
(1) Avalon总线模块结构与功能参数;
(2) 每个外设结构与功能参数;
(3) 每个外设的主/从角色;
(4) 每个外设提供的端口信号;
(5)每个可被多个主端口访问的从端口的仲裁机制。
从内部来看,Qsys包含两个主要部分:图形用户界面(GUI)和系统生成程序。 图形用户界面提供管理IP模块、配置系统和报告错误等功能。用户通过图形用户界面设计系统时,所有的设置都保存在一个以系统命名的qsys文件中,所以图形用户界面实际上就是qsys文件的专用编辑器。用户通过图形用户界面完成设计之后,单击Generate将启动系统生成程序。系统生成程序完成大量的功能,创建了几乎所有的Qsys输出文件(HDL逻 辑文件、C程序的头文件和库文件、模拟仿真文件等)。
qsys文件是图形用户界面和系统生成程序之间的唯一交互渠道。对大部分用户来说,仅仅了解qsys文件是由图形用户界面产生,并且系统生成程序要读取qsys文件的内容就足够 了。髙级用户可以使用文本编辑器来修改qsys文件编辑自己的设计,而不是使用图形用户界面。qsys文件传递给HDL生成器,用来创建系统模块实际的寄存器传输级(RTL)描述。
当用户使用Qsys创建一个新的系统时,Qsys自动生成一个以系统名 命名的系统qsys文件,所有的设计信息都保存在该qsys文件中。当使用Qsys重新打开一个已有的系统时,qsys文件是Qsys工具读取该系统具体设计信息的唯一来源。系统qsys文件的内容随着用户吐信用户界面对系统的编辑而改变。
当Qsys完成一个系统的搭建并生成了系统之后,会在工程文件夹下生成如下若干文件或文件夹。例如将Qsys系统保存为mycpu.qsys,则工程文件夹下将会生成如下的文件或文件夹。
mycpu.qsys:Qsys系统文件(.qsys)——用于描述系统的硬件结构。
mycpu.sopcinfo:Sopc信息文件(.sopcinfo),Nios II IDE使用.sopcinfo文件来信息来为目标硬件编译软件程序。
mycpu文件夹:mycpu下包含了整个Qsys系统生成的各种详细文件,包括整个系统的例化文件(mycpu_inst.v)以及Qsys中使用到的所有组件的硬件描述语言(HDL)文件(在synthesis文件夹中), QuartusII符号模块文件(.bsf)——该文件中的符号(Symbol)用于在使用原理图设计顶层时添加到Quartus II工程顶层文件,使用Verilog设计顶层的方式不使用。
所有Qsys的菜单命令如表2.1所列。:
在下一小节中,将以一个实例来讲述Qsys的使用,读者将执行下列步骤:
1) 启动 Qsys;‘
2) 指定目标FPGA和时钟设置;
3) 增加Nios II内核,片内存储器和其它外设。
4) 指定基地址和中断请求(IRQ)优先级。
5) 指定更多的Nios II设置。
6) 生成 Qsys 系统。
Qsys设计过程不需要按固定的顺序进行,本节所述的设计步骤是常用的,便于读者理解。然而,读者可使用不同的顺序来执行Qsys设计步骤。
表2.1 Qsys菜单命令列表
2.5.2 启动 Qsys
打开Quartus II软件。在Quartus II中选择【Tools】->【Qsys】选项来启动Qsys,建议首先新建一个Quartus II工程,然后再打开Qsys,如图2. 14所示。 .. ,
Qsys启动后,将自动创建好一个名为unsaved.qsys的工程,该项目中仅仅包含了一个时钟管理单元,如下图所示:
图 2. 14 启动 Qsys
这个时候我们点击【File】【Save】即可保存当前项目,这里我们将项目命名为mysystem.qsys
图 2. 15 保存项目对话框
在图2.15中输入项目名称。在本例中项目名为mysystem。
特别注意,项目名称不能与2.4. 2小节中建立的顶层HDL文件名同名,否則在后期Quartus II编译该工程时将会报错。
图 2. 16 Qsys 界面
2.5.3指定系统输入时钟频率
Qsys工具打开后,clk_0是自动添加进来的,该元件是用来对输入的时钟和复位信号进行处理的。我们双击该元件的名称(clk_0),将会在右侧弹出时钟设置对话框,这里我们可以设置输入时钟频率,因为系统默认为50MHz,而我们芯航线FPGA开发板上使用的也是50MHz的晶振,即与系统默认一致,因此,这里我们不需要修改。当读者在使用自己的目标板时,就需要根据自己的目标板实际情况进行设置。需要注意的是,所设置的频率一定要与系统实际运行的时钟频率相匹配。否则一些涉及到精确时序参数的外设(定时器、UART、SPI等等)可能无法正常工作。
2.5.4添加Nios II处理器内核
执行下面的步骤,添加Nios II/s内核到系统:
在图2. 16所示IP Catlog栏,搜索框中输入nios,在搜索结果中选中Nios II Processor,双击或者点击Add按钮打开NiOS II 处理器配置窗口。这里分别对该设置窗口中的一些参数进行介绍。
main:选择NIOS II处理器的内核类型。从main选项卡可以看到,Nios II系列支持两种类型的CPU,并给出了其支持的相关功能特性,详细内容见3. 10节所列。根据应用要求和目标FPGA中的器件约束(逻辑资源)条件,选择适合的CPU核。由于芯航线FPGA学习套件上使用的FPGA器件(EP4CE10)的逻辑资源比较充足(10K),因此本实例选择快速型CPU核Nios II/f,如果用户使用的是逻辑资源有限的器件,如EP4CE6,则使用快速型内核比较紧张,建议选择经济型内核。这也是我们选择EP4CE10这款器件的原因,为了给用户学习和使用NIOS II处理器留出相当的逻辑资源。
Vectors:设置CPU的复位向量(Reset Vevtor)、异常向量(Exception Vector)和快速TLB命中异常向量(Fast TLB Miss Exception Vector)。
Reset Vevtor:复位向量用于设置CPU复位后从何处启动,例如我们在调试系统时,为了方便,常设置CPU的复位向量为SDRAM或SRAM,而当我们的系统开发完成后,则将CPU的复位向量设置于FLASH,例如EPCS存储器。这样系统即可上电后自动从FLASH中复制程序代码到内存中并运行。该选项只有当CPU的存储器系统就绪后方可配置,因此,当我们添加NIOS II CPU时,因为此时CPU的存储器组件并未就绪,因此此项无法配置,只有等我们后续为NIOS II添加好存储器组件后,再回头来进行修改。
Exception Vector:异常向量用于存放CPU处理异常事件的代码,例如中断处理代码。在一个典型的系统中,该向量应该指向一个低延迟的存储器,例如SDRAM、SRAM、或者片上存储器(On Chip RAM)。
Fast TLB Miss Exception Vector:快速TLB命中异常向量主要与MMU协作,管理存储器,本书所讲解的知识赞不涉及到MMU方面的内容,因此此部分内容暂不做介绍。
Caches and Memory Interfaces Tab:本选项卡主要设置CPU的数据和指令缓存部件。
Instruction cache:指令缓存用于缓存NIOS II处理器的各种指令,以提高CPU的运行效率。该缓存的大小从512字节到64K字节用户可自定义设置,,当然也可以不使用指令缓存。当选择不使用指令缓存时,NIOS II处理器的指令总线将会被移除,因此,我们必须要包含一个紧耦合型指令存储器(tightly-coupled instruction memory)。关于此部分的深入应用,需要用户扎实掌握NIOS II处理器的知识后,再来深入研究,刚开始接触时,在芯片资源充足的情况下,使用默认设置即可。
Data cache:数据缓存用于存放数据,
Data cache数据缓存选项用于指定缓存的大小。该缓存的大小从512字节到64K字节用户可自定义设置,当然也可以不使用指令缓存。关于此部分的深入应用,需要用户扎实掌握NIOS II处理器的知识后,再来深入研究,刚开始接触时,在芯片资源充足的情况下,使用默认设置即可。
Arithmetic Instructions:该选项卡用来设置NIOS II处理器实现算术指令的方式,这里我们可以通过选择Divide Hardware来设置NIOS II处理器是否支持硬件除法运算。也可以选择乘法、移位等运算的实现方式。
JTAG Debug选项卡
为了方便调试,为CPU加人JTAG调试模块。JTAG调试模块要占用较多的逻辑单元,如果整个系统已经调试完毕了,可以选用取消勾选Include JTAG Debug,以减少系统占用资源。JTAG调试模块根据功能的不同可设置是否使用硬件断点,使用数据触发,跟踪类型和跟踪存储等
其他选项为用户在实际的应用情况中根据自己的需求合理设置,这里不做过多的介绍。
在本实例中,我们选择使用Nios II/f型内核,不使用硬件除法器,指令缓存默认设置为4K字节,数据缓存默认设置为2K字节。Jtag Debug默认,其他设置不变。点击Finish按钮即可完成NIOS II处理器的添加。
添加完成后,系统自动将该NIOS II处理器命名为nios2_gen2_0,我们可以选中改名字,点击鼠标右键选择rename以对处理器进行重命名,这里我们不做改变,使用默认名。
注意,大家在给Qsys中创建的各个组件重命名是,名字最前面应该使用英文字母。能使用的字符只有英文字母、数字和“_”,不能连续使用“_”符号,在名字的最后也不能使用“_”。
2.5.5添加片内存储器
众所周知,处理器系统至少要有一个存储器用于数据和指令。本章实例设计一个4KB 片内ROM存储器(Onchip_ROM),用于存储程序代码以及程序运行空间;4KB片内RAM存 储器(onchip_RAM)用于变童存储(R/W数据)、Heap、stack等。
执行下列步骤来添加存储器:
(1) 如图,在IP Catalog中,输入onchip来进行过滤,在搜索结果中选择并双击On-Chip Memory (RAM or ROM),弹出片内存储器配置向导对话框,如 图2. 21所示。
(2)在Memory Type选项区域中选中ROM (read-only),即指定为ROM型。FPGA内部其实 并没有专用的ROM硬件资源,实现ROM的思想是对RAM赋初值,并保持该初值,使其为只读的。ROM的内容在对FPGA进行配置时,一起写入FPGA。
(3) 在Total Memory Size文本框中输入4096,即指定4 KB的存储容量。
(4) 不要改变其它任何默认设置。
(5) 单击
,在激活元件窗口中出现名称为onchip_memory2_0的片内存储器。
(6) 右击激活元件窗口中〇nchip_memory_0,然后选择Rename将onchip_memory_0重命名为onchip_ROM,如图2. 22所示。
(7)更改了ROM的名称后,我们在此双击onchip_ROM以对其参数进行编辑或查看,在最底部可以看到Memory will be initialized from mysystem_onchip_ROM. hex,即onchip_ROM存储器在上电时将使用mysystem_onchip_ROM. hex文件进行初始化。mysystem_onchip_ROM.hex在Quartus II工程目录下,该文件可以由用户编辑生成,也可以由IDE编译生成,见2. 9. 3小节。在本实例中,将使用onchip_rom来存储用户程序,mysystem_onchip_ROM. hex将由IDE编译生成,文件的内容即用户程序。
使用与添加onchip_RAM相同的方法,添加一个4KB的onchip_RAM。添加步骤中不
同之处在于:
(1) 在第(2)步中,Memory Type选项区中选中RAM(writeable),即指定为RAM型;
(2) 在第(3)步中,Total Memory Size文本框中输人4096,即指定4 KB的存储容量。
(3) 在第(6)步中,重命名为onchip_RAM。
2.5.6 添加 PIO
PIO为Nios II处理器系统接收输人信号以 及输出信号提供了一种简易的方法。本实例设计使用1个PIO来驱动1个LED。
执行下列步骤添加PIO:
(1) 如图,在IP Catalog中,输入PIO来进行过滤,在搜索结果中选择PIO (Parallel I/O)并双击弹出PIO配置向导对话框,如 图2. 23所示。
(2) 在Width选项区的文本框中输人1,将 PIO的宽度改为1位;在Direction选项区选择 Output,即仅输出模式。Output Port Reset Value处修改值为1,即设定PIO复位时为1。这里设置为1主要是为了使系统复位后LED处于熄灭状态。
(3) 单击
,在激活元件窗口中出现名称为 pio_0 的 PIO。
(4) 右击激活元件窗口中pio_0,选择Rename将pio_0重命名为pio_led。给出硬件外设的描述名称是一种良好的习惯。这样会方便我们在分配引脚和编写软件程序时对外设的理解。
注意:在Nios II IDE的用户程序中,将使用PIO_LED(NIOS II IDE中不论组件名的大小写,统一使用大写字母,无需用户强制使用大写字母命名)这个名称来访问外设,所以在这里推荐将PIO命名为pio_led当然,用户也可以命名为其他的名称,只是要在IDE的用户程序中,使用相应的名称来访问PIO即可,由于考虑到是第一个实例,为了尽量减少学习者的出错几率,这里还是强烈建议大家直接使用PIO_LED或者pio_led来命名。
关于PIO的更多细节,请参见4. 1节。
2.5.7添加系统ID外设
如果系统包括系统ID外设,则当Qsys生成Nios II系统时,将为该Nios II系统生成一个标识符(ID号)。该标识符会被写入SYSTEM ID寄存器中,供IDE编译器和用户辨别所运行的程序是否与目标系统匹配。在IDE中,如果用户程序不是基于对应的Nios II系统的,那么调试时,Nios II IDE将阻止用户下载程序到Nios II系统,当然,我们也可以在调试时选择忽略系统ID的核对来跳过这个校验。具体操作见后续软件开发部分
在IP Catalog中,输入” system id”来进行过滤,在搜索结果中选择System ID Peripheral并双击弹出System ID配置向导对话框,在这里,我们可以在“32 bit System ID”处手动的输入一个ID作为系统标识符,本实例我们设置0x00000008。
单击
,在激活元件窗口中出现名称为sysid_qsys_0的System ID Peripheral。
右击激活元件窗口中sysid_qsys_0,选择Rename将sysid_qsys_0重命名为sysid。
关于系统ID外设的更多细节,请见4. 12节。
2.5.8连接各外设到Avalon MM总线上
通过以上步骤,我们完成了添加实现点亮LED灯所需的所有外设组件,然而,这些组件当前都还是各自独立的,与系统核心NIOS II CPU并没有关联起来。因此我们需要使用Avalon MM总线或Avalon ST总线来将这些组件连接起来,因为本实例中不存在数据流组件,因此不涉及到Avalon ST总线的连接。
本系统中,总共涉及到Avalon MM总线的指令总线、数据总线、时钟网络、复位网络和中断网络。一个完整的系统由至少一个主设备和至少一个从设备构成,本实例中NIOS II CPU为主设备,sysid和PIO_LED为从设备。onchip_ROM和onchip_RAM为存储器设备。我们连接时,首先将存储器设备的slave(s1)同时和NIOS II CPU的数据总线(data master)和指令(instruction master)总线连接,然后将pio_led和sysid的slave(s1)与NIOS II CPU的数据总线(data master)相连,不要将s1与指令总线相连接。连接总线的方法很简单,将两个需要连接到一起的总线交叉处的空心圆圈点击一下,即可实现两个网络的连接。
关于什么时候需要连接指令总线,什么时候不需要,这里给出一个连接技巧:凡是不涉及到存储CPU 指令的外设,如串口,定时器,SPI等非存储器外设,只需要将s1连接到CPU的data master即可。而对于需要存储CPU程序指令的存储器,如EPCS、onchip_ROM、SDRAM等,需要将s1和CPU的data master 和instruction master同时连接。当然,一些明确不会存储指令的存储器,也不需要连接instruction master。连接完成的网络如下图所示:
以上完成了所有组件的数据总线和指令总线的连接,接下来还需要完成时钟网络和复位网络的连接。本实例中只有一个时钟网络,因此将所有组件的时钟网络连接到一起即可,连接时钟网络的系统如下图所示:
接下来我们需要连接全局复位网络,连接复位网络有两种方式,第一种方式和连接时钟网络一样,手动一个一个的去点击交叉点连接。第二种方式就是直接点击菜单栏【System】 【Create Global Reset Network】来连接复位网络,这里推荐初次接触Qsys的用户使用第二种方式,以减少出错的概率。
由于本系统中没有添加能够产生中断请求的组件,因此没有中断网络需要连接。关于中断网络的连接和中断号的分配,我们将在后续章节讲解中断的使用的时候进行讲解。
所有总线连接完成后的系统如下图所示。
2.5.9指定基地址和中断请求优先级
在添加和完成组件间的总线网络连接后,我们就需要为每个外设分配基地址和中断请求优先级,由于本实例中所有外设都不含有中断,所以无需进行中断优先级分配。
Qsys提供Assign Base Addresses和Assign Interrupt Numbers命令,如下图所示,这两个命令可以分别简单的实现分配外设基地址和中断优先级。
对于许多系统,包括本实例设计,Assign Base Addresses能满足要求。当然,用户可以自己调整基地址和中断优先级来满足系统的需求。NIOS II处理器的内核可寻址31位地址范围(2G),用户必须分配0x00000000~0x7fffffff之间的基地址。NIOS II程序使用宏定义的符号常量来访问外设,基地址的改变不会造成程序的修改。
由于Qsys只是搭建系统,并不处理软件操作,因此它不能做出关于最好的IRQ分配的有根据猜测,因此建议用户不采用自动分配的方式,而是自己根据系统结构手动分配中断优先级。
这里,我们要分配系统基地址,可以使用自动分配的方式,直接点击【System】【Assign Base Addresses】即可。
2.5.10设置NIOS II复位和异常地址
双击nios2_gen2_0组件,在打开的选项卡中,点击Vectors切换到向量设置选项卡。本实例,系统上电后,从内部ROM开始运行,所以Reset Vector的Reset Vector memory选择onchip_ROM.s1,offset为0x00000000。异常向量表放在内部RAM里面,所以,Exception Address选择onchip_RAM.s1,Offset地址为0x00000020。
注意:Reset Address和Exception Address的Offset只有在多处理器的系统中才进行设置,且其值必须为0x20的倍数,如果地址设置违反规则,信息窗口会给出错误提示。
2.5.11设置需要引出到Qsys系统顶层的信号
在最终形成的FPGA系统中,Qsys所创建的组件是以一个子模块的形式添加到Quartus II工程中的,而作为子模块,就存在相应的输入输出,在Qsys系统中,当系统组件添加完成后,还需要手动的将系统中各个组件对应的信号导出到顶层,这样才能正常的加入到Quartus II工程中。
那么具体有哪些信号是需要导出到模块顶层的呢?在本例中clk_0模块的clk_in和clk_in_reset信号是需要导出到顶层的,但是这两个信号在系统创建之时就自动存在并导出到顶层了,因此不需要我们手动再去操作。
而onchip_ROM、onchip_RAM、systemID等外设仅与CPU进行交互,没有需要导出到系统顶层与其他模块或引脚连接的信号,因此不用连接。pio_led作为一个输出引脚,最终是通过引脚连接到开发板上的LED灯的控制角,因此需要导出到顶层。每一个模块,如果有需要导出到系统顶层的信号,则有一个名为external_connection的总线名,其属性为Conduit。因此,对于刚接触Qsys系统的用户,只需要认准这种属性的信号,即为需要导出到顶层的信号。
导出这个信号,只需要在该信号的export一栏双击,并输入你希望命名的信号名称即可。例如,本实例中,我们双击Double-click to即可输入信号名,这里我们双击并经信号名修改为pio_led即可。如下图所示:
至此,我们整个系统就搭建完成了,接下来点击【File】->【Save】保存当前系统,然后即可开始生产该系统对应的HDL文件了。
2.5.12 生成NIOS II系统
使用Qsys生成NIOS II系统,执行以下步骤:
1、 点击【Generate】->【Generate HDL】打开Generation对话框。
2、 默认输出路径不变
3、 点击Generate按钮,系统生成开始。
在系统生成过程中,Qsys会执行一系列操作,Qsys会为添加的所有部件生成Verilog HDL源文件,并生成每个硬件部件以及连接部件的片内总线结构、仲裁和中断逻辑。Qsys会为系统生成NIOS II IDE软件开发所需的硬件抽象层(HAL)、C以及汇编头文件。这些头文件定义了存储器映射、中断优先级和每个外设寄存器空间的数据结构。这样的自动生成过程有助于软件设计者处理硬件潜在的变化性。如果硬件改变了,Qsys会自动更新这些头文件。Qsys也会为系统中现有的诶个外设生成定制的C和汇编函数库。如果添加了片内存储器,Qsys还将为片内ROM、RAM生成其初始化所使用的HEX文件(空白文件)。在生成阶段的最后一步,Qsys创建适合于系统部件的总线结构,并把所有部件连接在一起。
生成过程时间随计算机的性能而不同,一般需要几分钟。生成结束后,显示Finished: Create HDL design files for synthesis,点击Close即可。然后关闭Qsys工具。
这时,在Quartus II工程中会弹出以下窗口提示,点击OK即可。此时,我们一个基于NIOS II处理器的系统就搭建完成了。
NIOS II系统生成后将产生下列文件:
Qsys系统文件:mysystem.sopcinfo,它定义了Qsys生成完整系统必须的详细信息,该文件存储NIOS II系统的硬件内容,NIOS II IDE需要使用该文件信息来为目标硬件编译软件程序。详细内容见2.9.1小节。
硬件描述语言(HDL)文件——mysystem.v以及各外设的HDL文件,这些文件是描述NIOS II系统硬件设计文件。Quartus II软件将使用这些HDL文件来编译整个FPGA设计。这些文件位于E:easysopc_class 1_CoreCourse_GHRDmysystemsynthesis路径下。
至此,已经完成NIOS II处理器系统的创建。生成系统结束后,要将系统集成到Quartus II硬件工程并使用NIOS II IDE来开发软件,可以先使用NIOS II IDE进行软件开发,也可以先将系统集成到Quartus II。当然,如果是多人合作开发,两者可同时进行。
2.5 使用 Qsys创建 Nios II 系统2.5.1 Qsys简介
Qsys包含在Quartus II软件中,它为建立SOPC设计提供了图形化环境,是早期Quartus II软件中SOPC Builder版本的升级,在保持基本功能不变的前提下,增加了系统建设的灵活性。 SOPC由CPU、存储器接口、标准外设和用户自定义的外设等组件组成。Qsys允许选择和自定义系统模块的各个组件和接口。利用Qsys,用户可以很方便地将处理 器、存储器和其它外设模块连接起来,形成一个完整的系统。Qsys中已经包含了 Nios II处理器以及一些常用的外设IP模块,用户也可以设计自己的外设IP。用户在Qsys中定义Nios II系统的硬件特性,例如使用哪个Nios II内核,系统中包括什么外设。 Qsys不定义软件操作,例如存储器中哪里存储指令或哪里发送stderr字符流,这些 工作在Nios II HDE中完成,见2. 9. 2小节。
Avalon总线和外设的配置是在Qsys的图形用户界面(GUI)中指定的。用户 在GUI界面中指定各种参数和选项,这些参数和选项会存入一个系统qsys文件。qsys文件是一个文本文件,它完整地定义了以下内容:
(1) Avalon总线模块结构与功能参数;
(2) 每个外设结构与功能参数;
(3) 每个外设的主/从角色;
(4) 每个外设提供的端口信号;
(5)每个可被多个主端口访问的从端口的仲裁机制。
从内部来看,Qsys包含两个主要部分:图形用户界面(GUI)和系统生成程序。 图形用户界面提供管理IP模块、配置系统和报告错误等功能。用户通过图形用户界面设计系统时,所有的设置都保存在一个以系统命名的qsys文件中,所以图形用户界面实际上就是qsys文件的专用编辑器。用户通过图形用户界面完成设计之后,单击Generate将启动系统生成程序。系统生成程序完成大量的功能,创建了几乎所有的Qsys输出文件(HDL逻 辑文件、C程序的头文件和库文件、模拟仿真文件等)。
qsys文件是图形用户界面和系统生成程序之间的唯一交互渠道。对大部分用户来说,仅仅了解qsys文件是由图形用户界面产生,并且系统生成程序要读取qsys文件的内容就足够 了。髙级用户可以使用文本编辑器来修改qsys文件编辑自己的设计,而不是使用图形用户界面。qsys文件传递给HDL生成器,用来创建系统模块实际的寄存器传输级(RTL)描述。
当用户使用Qsys创建一个新的系统时,Qsys自动生成一个以系统名 命名的系统qsys文件,所有的设计信息都保存在该qsys文件中。当使用Qsys重新打开一个已有的系统时,qsys文件是Qsys工具读取该系统具体设计信息的唯一来源。系统qsys文件的内容随着用户吐信用户界面对系统的编辑而改变。
当Qsys完成一个系统的搭建并生成了系统之后,会在工程文件夹下生成如下若干文件或文件夹。例如将Qsys系统保存为mycpu.qsys,则工程文件夹下将会生成如下的文件或文件夹。
mycpu.qsys:Qsys系统文件(.qsys)——用于描述系统的硬件结构。
mycpu.sopcinfo:Sopc信息文件(.sopcinfo),Nios II IDE使用.sopcinfo文件来信息来为目标硬件编译软件程序。
mycpu文件夹:mycpu下包含了整个Qsys系统生成的各种详细文件,包括整个系统的例化文件(mycpu_inst.v)以及Qsys中使用到的所有组件的硬件描述语言(HDL)文件(在synthesis文件夹中), QuartusII符号模块文件(.bsf)——该文件中的符号(Symbol)用于在使用原理图设计顶层时添加到Quartus II工程顶层文件,使用Verilog设计顶层的方式不使用。
所有Qsys的菜单命令如表2.1所列。:
在下一小节中,将以一个实例来讲述Qsys的使用,读者将执行下列步骤:
1) 启动 Qsys;‘
2) 指定目标FPGA和时钟设置;
3) 增加Nios II内核,片内存储器和其它外设。
4) 指定基地址和中断请求(IRQ)优先级。
5) 指定更多的Nios II设置。
6) 生成 Qsys 系统。
Qsys设计过程不需要按固定的顺序进行,本节所述的设计步骤是常用的,便于读者理解。然而,读者可使用不同的顺序来执行Qsys设计步骤。
表2.1 Qsys菜单命令列表
2.5.2 启动 Qsys
打开Quartus II软件。在Quartus II中选择【Tools】->【Qsys】选项来启动Qsys,建议首先新建一个Quartus II工程,然后再打开Qsys,如图2. 14所示。 .. ,
Qsys启动后,将自动创建好一个名为unsaved.qsys的工程,该项目中仅仅包含了一个时钟管理单元,如下图所示:
图 2. 14 启动 Qsys
这个时候我们点击【File】【Save】即可保存当前项目,这里我们将项目命名为mysystem.qsys
图 2. 15 保存项目对话框
在图2.15中输入项目名称。在本例中项目名为mysystem。
特别注意,项目名称不能与2.4. 2小节中建立的顶层HDL文件名同名,否則在后期Quartus II编译该工程时将会报错。
图 2. 16 Qsys 界面
2.5.3指定系统输入时钟频率
Qsys工具打开后,clk_0是自动添加进来的,该元件是用来对输入的时钟和复位信号进行处理的。我们双击该元件的名称(clk_0),将会在右侧弹出时钟设置对话框,这里我们可以设置输入时钟频率,因为系统默认为50MHz,而我们芯航线FPGA开发板上使用的也是50MHz的晶振,即与系统默认一致,因此,这里我们不需要修改。当读者在使用自己的目标板时,就需要根据自己的目标板实际情况进行设置。需要注意的是,所设置的频率一定要与系统实际运行的时钟频率相匹配。否则一些涉及到精确时序参数的外设(定时器、UART、SPI等等)可能无法正常工作。
2.5.4添加Nios II处理器内核
执行下面的步骤,添加Nios II/s内核到系统:
在图2. 16所示IP Catlog栏,搜索框中输入nios,在搜索结果中选中Nios II Processor,双击或者点击Add按钮打开NiOS II 处理器配置窗口。这里分别对该设置窗口中的一些参数进行介绍。
main:选择NIOS II处理器的内核类型。从main选项卡可以看到,Nios II系列支持两种类型的CPU,并给出了其支持的相关功能特性,详细内容见3. 10节所列。根据应用要求和目标FPGA中的器件约束(逻辑资源)条件,选择适合的CPU核。由于芯航线FPGA学习套件上使用的FPGA器件(EP4CE10)的逻辑资源比较充足(10K),因此本实例选择快速型CPU核Nios II/f,如果用户使用的是逻辑资源有限的器件,如EP4CE6,则使用快速型内核比较紧张,建议选择经济型内核。这也是我们选择EP4CE10这款器件的原因,为了给用户学习和使用NIOS II处理器留出相当的逻辑资源。
Vectors:设置CPU的复位向量(Reset Vevtor)、异常向量(Exception Vector)和快速TLB命中异常向量(Fast TLB Miss Exception Vector)。
Reset Vevtor:复位向量用于设置CPU复位后从何处启动,例如我们在调试系统时,为了方便,常设置CPU的复位向量为SDRAM或SRAM,而当我们的系统开发完成后,则将CPU的复位向量设置于FLASH,例如EPCS存储器。这样系统即可上电后自动从FLASH中复制程序代码到内存中并运行。该选项只有当CPU的存储器系统就绪后方可配置,因此,当我们添加NIOS II CPU时,因为此时CPU的存储器组件并未就绪,因此此项无法配置,只有等我们后续为NIOS II添加好存储器组件后,再回头来进行修改。
Exception Vector:异常向量用于存放CPU处理异常事件的代码,例如中断处理代码。在一个典型的系统中,该向量应该指向一个低延迟的存储器,例如SDRAM、SRAM、或者片上存储器(On Chip RAM)。
Fast TLB Miss Exception Vector:快速TLB命中异常向量主要与MMU协作,管理存储器,本书所讲解的知识赞不涉及到MMU方面的内容,因此此部分内容暂不做介绍。
Caches and Memory Interfaces Tab:本选项卡主要设置CPU的数据和指令缓存部件。
Instruction cache:指令缓存用于缓存NIOS II处理器的各种指令,以提高CPU的运行效率。该缓存的大小从512字节到64K字节用户可自定义设置,,当然也可以不使用指令缓存。当选择不使用指令缓存时,NIOS II处理器的指令总线将会被移除,因此,我们必须要包含一个紧耦合型指令存储器(tightly-coupled instruction memory)。关于此部分的深入应用,需要用户扎实掌握NIOS II处理器的知识后,再来深入研究,刚开始接触时,在芯片资源充足的情况下,使用默认设置即可。
Data cache:数据缓存用于存放数据,
Data cache数据缓存选项用于指定缓存的大小。该缓存的大小从512字节到64K字节用户可自定义设置,当然也可以不使用指令缓存。关于此部分的深入应用,需要用户扎实掌握NIOS II处理器的知识后,再来深入研究,刚开始接触时,在芯片资源充足的情况下,使用默认设置即可。
Arithmetic Instructions:该选项卡用来设置NIOS II处理器实现算术指令的方式,这里我们可以通过选择Divide Hardware来设置NIOS II处理器是否支持硬件除法运算。也可以选择乘法、移位等运算的实现方式。
JTAG Debug选项卡
为了方便调试,为CPU加人JTAG调试模块。JTAG调试模块要占用较多的逻辑单元,如果整个系统已经调试完毕了,可以选用取消勾选Include JTAG Debug,以减少系统占用资源。JTAG调试模块根据功能的不同可设置是否使用硬件断点,使用数据触发,跟踪类型和跟踪存储等
其他选项为用户在实际的应用情况中根据自己的需求合理设置,这里不做过多的介绍。
在本实例中,我们选择使用Nios II/f型内核,不使用硬件除法器,指令缓存默认设置为4K字节,数据缓存默认设置为2K字节。Jtag Debug默认,其他设置不变。点击Finish按钮即可完成NIOS II处理器的添加。
添加完成后,系统自动将该NIOS II处理器命名为nios2_gen2_0,我们可以选中改名字,点击鼠标右键选择rename以对处理器进行重命名,这里我们不做改变,使用默认名。
注意,大家在给Qsys中创建的各个组件重命名是,名字最前面应该使用英文字母。能使用的字符只有英文字母、数字和“_”,不能连续使用“_”符号,在名字的最后也不能使用“_”。
2.5.5添加片内存储器
众所周知,处理器系统至少要有一个存储器用于数据和指令。本章实例设计一个4KB 片内ROM存储器(Onchip_ROM),用于存储程序代码以及程序运行空间;4KB片内RAM存 储器(onchip_RAM)用于变童存储(R/W数据)、Heap、stack等。
执行下列步骤来添加存储器:
(1) 如图,在IP Catalog中,输入onchip来进行过滤,在搜索结果中选择并双击On-Chip Memory (RAM or ROM),弹出片内存储器配置向导对话框,如 图2. 21所示。
(2)在Memory Type选项区域中选中ROM (read-only),即指定为ROM型。FPGA内部其实 并没有专用的ROM硬件资源,实现ROM的思想是对RAM赋初值,并保持该初值,使其为只读的。ROM的内容在对FPGA进行配置时,一起写入FPGA。
(3) 在Total Memory Size文本框中输入4096,即指定4 KB的存储容量。
(4) 不要改变其它任何默认设置。
(5) 单击
,在激活元件窗口中出现名称为onchip_memory2_0的片内存储器。
(6) 右击激活元件窗口中〇nchip_memory_0,然后选择Rename将onchip_memory_0重命名为onchip_ROM,如图2. 22所示。
(7)更改了ROM的名称后,我们在此双击onchip_ROM以对其参数进行编辑或查看,在最底部可以看到Memory will be initialized from mysystem_onchip_ROM. hex,即onchip_ROM存储器在上电时将使用mysystem_onchip_ROM. hex文件进行初始化。mysystem_onchip_ROM.hex在Quartus II工程目录下,该文件可以由用户编辑生成,也可以由IDE编译生成,见2. 9. 3小节。在本实例中,将使用onchip_rom来存储用户程序,mysystem_onchip_ROM. hex将由IDE编译生成,文件的内容即用户程序。
使用与添加onchip_RAM相同的方法,添加一个4KB的onchip_RAM。添加步骤中不
同之处在于:
(1) 在第(2)步中,Memory Type选项区中选中RAM(writeable),即指定为RAM型;
(2) 在第(3)步中,Total Memory Size文本框中输人4096,即指定4 KB的存储容量。
(3) 在第(6)步中,重命名为onchip_RAM。
2.5.6 添加 PIO
PIO为Nios II处理器系统接收输人信号以 及输出信号提供了一种简易的方法。本实例设计使用1个PIO来驱动1个LED。
执行下列步骤添加PIO:
(1) 如图,在IP Catalog中,输入PIO来进行过滤,在搜索结果中选择PIO (Parallel I/O)并双击弹出PIO配置向导对话框,如 图2. 23所示。
(2) 在Width选项区的文本框中输人1,将 PIO的宽度改为1位;在Direction选项区选择 Output,即仅输出模式。Output Port Reset Value处修改值为1,即设定PIO复位时为1。这里设置为1主要是为了使系统复位后LED处于熄灭状态。
(3) 单击
,在激活元件窗口中出现名称为 pio_0 的 PIO。
(4) 右击激活元件窗口中pio_0,选择Rename将pio_0重命名为pio_led。给出硬件外设的描述名称是一种良好的习惯。这样会方便我们在分配引脚和编写软件程序时对外设的理解。
注意:在Nios II IDE的用户程序中,将使用PIO_LED(NIOS II IDE中不论组件名的大小写,统一使用大写字母,无需用户强制使用大写字母命名)这个名称来访问外设,所以在这里推荐将PIO命名为pio_led当然,用户也可以命名为其他的名称,只是要在IDE的用户程序中,使用相应的名称来访问PIO即可,由于考虑到是第一个实例,为了尽量减少学习者的出错几率,这里还是强烈建议大家直接使用PIO_LED或者pio_led来命名。
关于PIO的更多细节,请参见4. 1节。
2.5.7添加系统ID外设
如果系统包括系统ID外设,则当Qsys生成Nios II系统时,将为该Nios II系统生成一个标识符(ID号)。该标识符会被写入SYSTEM ID寄存器中,供IDE编译器和用户辨别所运行的程序是否与目标系统匹配。在IDE中,如果用户程序不是基于对应的Nios II系统的,那么调试时,Nios II IDE将阻止用户下载程序到Nios II系统,当然,我们也可以在调试时选择忽略系统ID的核对来跳过这个校验。具体操作见后续软件开发部分
在IP Catalog中,输入” system id”来进行过滤,在搜索结果中选择System ID Peripheral并双击弹出System ID配置向导对话框,在这里,我们可以在“32 bit System ID”处手动的输入一个ID作为系统标识符,本实例我们设置0x00000008。
单击
,在激活元件窗口中出现名称为sysid_qsys_0的System ID Peripheral。
右击激活元件窗口中sysid_qsys_0,选择Rename将sysid_qsys_0重命名为sysid。
关于系统ID外设的更多细节,请见4. 12节。
2.5.8连接各外设到Avalon MM总线上
通过以上步骤,我们完成了添加实现点亮LED灯所需的所有外设组件,然而,这些组件当前都还是各自独立的,与系统核心NIOS II CPU并没有关联起来。因此我们需要使用Avalon MM总线或Avalon ST总线来将这些组件连接起来,因为本实例中不存在数据流组件,因此不涉及到Avalon ST总线的连接。
本系统中,总共涉及到Avalon MM总线的指令总线、数据总线、时钟网络、复位网络和中断网络。一个完整的系统由至少一个主设备和至少一个从设备构成,本实例中NIOS II CPU为主设备,sysid和PIO_LED为从设备。onchip_ROM和onchip_RAM为存储器设备。我们连接时,首先将存储器设备的slave(s1)同时和NIOS II CPU的数据总线(data master)和指令(instruction master)总线连接,然后将pio_led和sysid的slave(s1)与NIOS II CPU的数据总线(data master)相连,不要将s1与指令总线相连接。连接总线的方法很简单,将两个需要连接到一起的总线交叉处的空心圆圈点击一下,即可实现两个网络的连接。
关于什么时候需要连接指令总线,什么时候不需要,这里给出一个连接技巧:凡是不涉及到存储CPU 指令的外设,如串口,定时器,SPI等非存储器外设,只需要将s1连接到CPU的data master即可。而对于需要存储CPU程序指令的存储器,如EPCS、onchip_ROM、SDRAM等,需要将s1和CPU的data master 和instruction master同时连接。当然,一些明确不会存储指令的存储器,也不需要连接instruction master。连接完成的网络如下图所示:
以上完成了所有组件的数据总线和指令总线的连接,接下来还需要完成时钟网络和复位网络的连接。本实例中只有一个时钟网络,因此将所有组件的时钟网络连接到一起即可,连接时钟网络的系统如下图所示:
接下来我们需要连接全局复位网络,连接复位网络有两种方式,第一种方式和连接时钟网络一样,手动一个一个的去点击交叉点连接。第二种方式就是直接点击菜单栏【System】 【Create Global Reset Network】来连接复位网络,这里推荐初次接触Qsys的用户使用第二种方式,以减少出错的概率。
由于本系统中没有添加能够产生中断请求的组件,因此没有中断网络需要连接。关于中断网络的连接和中断号的分配,我们将在后续章节讲解中断的使用的时候进行讲解。
所有总线连接完成后的系统如下图所示。
2.5.9指定基地址和中断请求优先级
在添加和完成组件间的总线网络连接后,我们就需要为每个外设分配基地址和中断请求优先级,由于本实例中所有外设都不含有中断,所以无需进行中断优先级分配。
Qsys提供Assign Base Addresses和Assign Interrupt Numbers命令,如下图所示,这两个命令可以分别简单的实现分配外设基地址和中断优先级。
对于许多系统,包括本实例设计,Assign Base Addresses能满足要求。当然,用户可以自己调整基地址和中断优先级来满足系统的需求。NIOS II处理器的内核可寻址31位地址范围(2G),用户必须分配0x00000000~0x7fffffff之间的基地址。NIOS II程序使用宏定义的符号常量来访问外设,基地址的改变不会造成程序的修改。
由于Qsys只是搭建系统,并不处理软件操作,因此它不能做出关于最好的IRQ分配的有根据猜测,因此建议用户不采用自动分配的方式,而是自己根据系统结构手动分配中断优先级。
这里,我们要分配系统基地址,可以使用自动分配的方式,直接点击【System】【Assign Base Addresses】即可。
2.5.10设置NIOS II复位和异常地址
双击nios2_gen2_0组件,在打开的选项卡中,点击Vectors切换到向量设置选项卡。本实例,系统上电后,从内部ROM开始运行,所以Reset Vector的Reset Vector memory选择onchip_ROM.s1,offset为0x00000000。异常向量表放在内部RAM里面,所以,Exception Address选择onchip_RAM.s1,Offset地址为0x00000020。
注意:Reset Address和Exception Address的Offset只有在多处理器的系统中才进行设置,且其值必须为0x20的倍数,如果地址设置违反规则,信息窗口会给出错误提示。
2.5.11设置需要引出到Qsys系统顶层的信号
在最终形成的FPGA系统中,Qsys所创建的组件是以一个子模块的形式添加到Quartus II工程中的,而作为子模块,就存在相应的输入输出,在Qsys系统中,当系统组件添加完成后,还需要手动的将系统中各个组件对应的信号导出到顶层,这样才能正常的加入到Quartus II工程中。
那么具体有哪些信号是需要导出到模块顶层的呢?在本例中clk_0模块的clk_in和clk_in_reset信号是需要导出到顶层的,但是这两个信号在系统创建之时就自动存在并导出到顶层了,因此不需要我们手动再去操作。
而onchip_ROM、onchip_RAM、systemID等外设仅与CPU进行交互,没有需要导出到系统顶层与其他模块或引脚连接的信号,因此不用连接。pio_led作为一个输出引脚,最终是通过引脚连接到开发板上的LED灯的控制角,因此需要导出到顶层。每一个模块,如果有需要导出到系统顶层的信号,则有一个名为external_connection的总线名,其属性为Conduit。因此,对于刚接触Qsys系统的用户,只需要认准这种属性的信号,即为需要导出到顶层的信号。
导出这个信号,只需要在该信号的export一栏双击,并输入你希望命名的信号名称即可。例如,本实例中,我们双击Double-click to即可输入信号名,这里我们双击并经信号名修改为pio_led即可。如下图所示:
至此,我们整个系统就搭建完成了,接下来点击【File】->【Save】保存当前系统,然后即可开始生产该系统对应的HDL文件了。
2.5.12 生成NIOS II系统
使用Qsys生成NIOS II系统,执行以下步骤:
1、 点击【Generate】->【Generate HDL】打开Generation对话框。
2、 默认输出路径不变
3、 点击Generate按钮,系统生成开始。
在系统生成过程中,Qsys会执行一系列操作,Qsys会为添加的所有部件生成Verilog HDL源文件,并生成每个硬件部件以及连接部件的片内总线结构、仲裁和中断逻辑。Qsys会为系统生成NIOS II IDE软件开发所需的硬件抽象层(HAL)、C以及汇编头文件。这些头文件定义了存储器映射、中断优先级和每个外设寄存器空间的数据结构。这样的自动生成过程有助于软件设计者处理硬件潜在的变化性。如果硬件改变了,Qsys会自动更新这些头文件。Qsys也会为系统中现有的诶个外设生成定制的C和汇编函数库。如果添加了片内存储器,Qsys还将为片内ROM、RAM生成其初始化所使用的HEX文件(空白文件)。在生成阶段的最后一步,Qsys创建适合于系统部件的总线结构,并把所有部件连接在一起。
生成过程时间随计算机的性能而不同,一般需要几分钟。生成结束后,显示Finished: Create HDL design files for synthesis,点击Close即可。然后关闭Qsys工具。
这时,在Quartus II工程中会弹出以下窗口提示,点击OK即可。此时,我们一个基于NIOS II处理器的系统就搭建完成了。
NIOS II系统生成后将产生下列文件:
Qsys系统文件:mysystem.sopcinfo,它定义了Qsys生成完整系统必须的详细信息,该文件存储NIOS II系统的硬件内容,NIOS II IDE需要使用该文件信息来为目标硬件编译软件程序。详细内容见2.9.1小节。
硬件描述语言(HDL)文件——mysystem.v以及各外设的HDL文件,这些文件是描述NIOS II系统硬件设计文件。Quartus II软件将使用这些HDL文件来编译整个FPGA设计。这些文件位于E:easysopc_class 1_CoreCourse_GHRDmysystemsynthesis路径下。
至此,已经完成NIOS II处理器系统的创建。生成系统结束后,要将系统集成到Quartus II硬件工程并使用NIOS II IDE来开发软件,可以先使用NIOS II IDE进行软件开发,也可以先将系统集成到Quartus II。当然,如果是多人合作开发,两者可同时进行。
举报