软件环境:Quartus Prime Standard 18.1 Window 10
硬件环境:小梅哥 AC501 开发板
主要参考:
本实验使用 Nios 的自定义组件控制开发板上 LED 闪烁。
本文首先建立了基于片上 RAM 的基础 Nios 工程,之后在该工程上添加基于 Avalon-MM 接口的自定义组件,修改 Nios 软件后实现 LED 闪烁。
打开 Quartus 软件,选择菜单 File > New …,在弹出窗口中选择 New Quartus Prime Project,点击 OK 按钮。
在 New Project Wizard 对话框中,按提示选择 Next 页面,需要进行特殊设置的页面包括以下页面,其它页面保持默认。
设置工程名称和路径:
选择 FPGA 芯片型号:
完成全部配置后点击 Finish 按钮创建新工程 cus_com。
在 Quartus 选择菜单项 Assignments > Settings,在配置窗口选择 Compilation Process Settings 页,选择 Use all available processors:
在 Quartus 选择菜单项 Tools > Platform Designer,打开 Platform Designer 界面:
双击 clk_0 模块,配置时钟频率为 50 MHz
通过 IP Catalog 界面添加 System ID 模块,保持默认配置点击 Finish 按钮:
添加 JTAG UART 模块,保持默认配置点击 Finish 按钮:
添加 On-Chip Memory 模块,并配置为 128 KB 大小(小于当前 FPGA 芯片 1400 Kb 的 RAM 空间总量),其它配置项保持默认,点击 Finish 按钮:
添加 Nios II Processor 模块,设置为 Nios II/e 模式,其它配置保持默认,点击 Finish 按钮:
按下图,在 System Contents 界面连接各模块接口,保存当前设计,选择菜单项 System > Assign Base Addresses:
注意将 nios2 模块的 instruction_master 连接至 onchip_memory 的 s1:
双击 nios2 模块打开配置界面,进入 Vectors 页,设置 Reset vector memory 和 Exception vector memory 都为 on_chip memory:
按前述方法保持当前设计后,选择菜单项 Generate > Generate HDL…,在弹出窗口保持默认配置并且点击 Generate 按钮:
回到 Quartus 软件,选择菜单项 Project > Add/Remove Files in Project,弹出窗口中点击 … 按钮,选择 Platform Designer 保存的后缀名为 qsys 的设计文件,完成后点击 OK 按钮:
在 Project Navigator 的 IP Components 页可以看到添加的 nios_kernel 模块
在 IP Catalog 界面选择并双击 PLL Intel FPGA IP:
在弹出窗口中设置 IP 名称,并点击 OK 按钮:
之后弹出的 IP 配置界面中设置参考时钟为 50 MHz(板上时钟),输出时钟为 50 MHz([作为 qsys 模块参考时钟](#用 Platform Designer 建立 qsys 模块)),其它配置项保持默认并点击 Finish 按钮:
之后弹出 Generation 窗口提示 IP 生成结束,点击 Exit:
在弹出的提示窗口中保持默认,点击 Yes,将刚生成的 IP 添加至工程:
选择菜单项 File > New,在弹出窗口中选择 Verilog HDL File,点击 OK
在生成的 v 文件中编写顶层 HDL 模块,模块名称与建立 Quartus 工程时设置的顶层模块名称一致。
注意:PLL IP 的模块端口定义在同名的 v 文件中,qsys 模块的端口定义在 Platform Designer 的菜单项 Generate > Show Instantiation Template 中。
代码如下:
module cus_com
(input clk_50m
);//时钟生成wire clk;wire locked;pll_50mhz pll_u(.refclk(clk_50m),.rst(1'b0),.outclk_0(clk),.locked(locked));//nios 例化nios_kernel nios_u(.clk_clk (clk), // clk.clk.reset_reset_n (locked) // reset.reset_n);endmodule
在 Tasks 界面双击 Analysis & Synthesis
完成综合后,Tasks 界面提示如下:
选择菜单项 Assignments > Pin Planner,在弹出窗口中设置 clk_50m 的 Location 为 PIN_U10,并设置全部管脚的 I/O Standart 为 3.3 V LVTTL
完成配置后关闭 Pin Planner 窗口。
在 Tasks 界面双击 Timing Analysis
完成后,选择菜单项 Tools > Timing Analyzer
在弹出窗口中双击 Create Timing Netlist:
在该窗口选择菜单项 Constraints > Create Clock,设置时钟名称和周期后点击 … 按钮选中时钟管脚 clk_50m,完成后点击 Run 按钮:
在当前窗口双击 Update Timing Netlist:
双击 Write SDC File…
在弹出窗口中保持默认,并点击 OK 按钮:
关闭 Timing Analyzer 窗口,回到 Quartus。
选择菜单项 Assignments > Settings,进入 Timing Analyzer 页,选择并添加生成的 SDC 文件,完成后点击 OK:
在 Tasks 界面双击 Compile Design
等待完成编译
选择菜单项 Tools > Nios II Software Build Tools for Eclipse(后文简称 SBT,与官方文档一致)
在 Quartus 工程目录下建立 workspace:
在 SBT 选择菜单项 File > New > Nio II Application and BSP from Template,在弹出窗口中选择 Quartus 工程目录下的 nios_kernel.sopcinfo 文件,并设置工程名称,并选择 Hello World 模板,完成后点击 Finish 按钮:
通过 Project Explorer 双击打开 hello_world.c 文件:
修改代码如下:
#include
#include
{while (1){printf("Hello from Nios II!\n");usleep(500000);}return 0;
}
在 Project Explorer 中选择 nios_app_bsp 工程,在右键菜单选择 Build Project;完成后,同样在 nios_app 工程上选择 Build Project。
连接 USB Blaster 加载器和开发板后,开发板上电。
在 Quartus 选择菜单项 Tools > Programmer,在 Programmer 窗口点击 Auto Connect,并在弹出窗口中选中 5CSEBA2,并点击 OK 按钮:
在 FPGA 器件点击右键,选择菜单项 Change File
在 Select New Programming File 窗口中选择 Quartus 工程目录下 output_files 文件夹中的 cus_com.sof 文件,完成后选中 Program/Configure,并点击 Start 按钮:
完成 FPGA 程序载入后,Progress 显示载入成功
关闭 Programmer。
回到 SBT 软件,在 nios_app 工程上右键菜单选择 Run As > Run Configurations:
在弹出窗口中右键点击 Nio II Hardware,选中 New 选项,之后进入 Target Connection 页,点击 Refresh Connections 按钮找到 USB Blaster,最后点击 Run 按钮:
在 SBT 界面的 Nios II Console 显示来源于 JTAG UART 的调试信息:
打开 Platform Desgner,并且在 IP Catalog 双击 New Component
在弹出窗口中配置组件:
按以下代码修改建立的 HDL 文件:
// new_component.v// This file was auto-generated as a prototype implementation of a module
// created in component editor. It ties off all outputs to ground and
// ignores all inputs. It needs to be edited to make it do something
// useful.
//
// This file will not be automatically regenerated. You should check it in
// to your version control system if you want to keep it.`timescale 1 ps / 1 ps
module new_component (input wire [3:0] avalon_slave_address, // avalon_slave.addressinput wire avalon_slave_chipselect, // .chipselectinput wire avalon_slave_write, // .writeinput wire [7:0] avalon_slave_writedata, // .writedatainput wire reset_sink_reset, // reset_sink.resetinput wire clock_sink_clk, // clock_sink.clkoutput wire conduit_end_led_out // conduit_end.new_signal);// TODO: Auto-generated HDL templatewire clk;assign clk &#61; clock_sink_clk;wire rst;assign rst &#61; reset_sink_reset;//输出 LED 值reg led &#61; 1&#39;b0;always &#64;(posedge clk or posedge rst) beginif (rst &#61;&#61; 1&#39;b1) beginled <&#61; 1&#39;b0;endelse begincase ({avalon_slave_chipselect, avalon_slave_write, avalon_slave_address}){1&#39;b1, 1&#39;b1, 4&#39;b1111}: begincase (avalon_slave_writedata)8&#39;hFF: beginled <&#61; 1&#39;b1;end8&#39;h0: beginled <&#61; 1&#39;b0;enddefault: begin//保持led <&#61; led;endendcaseenddefault: begin//保持led <&#61; led;endendcaseendendassign conduit_end_led_out &#61; led;endmodule
完成上述步骤后&#xff0c;点击 Finish 按钮。
在 IP Catalog 中双击刚才建立的组件&#xff0c;点击 Finish 按钮将组件添加至 System Contents 中
注意&#xff0c;在上图中 avalon_led_0 组件的地址范围是 0x0004_1000~0x0004_100f&#xff0c;对应自定义时配置的 4 位地址线。
在菜单中选择 System > Assign Base Addresses&#xff0c;之后选择 Generate > Generate HDL&#xff0c;生成 qsys 模块
向顶层模块中的 qsys 模块添加输出 LED 端口&#xff0c;并连接至 FPGA 管脚&#xff0c;代码如下&#xff1a;
module cus_com
(input clk_50m,output led0,output led1
);//时钟生成wire clk;wire locked;pll_50mhz pll_u(.refclk(clk_50m),.rst(1&#39;b0),.outclk_0(clk),.locked(locked));//nios 例化nios_kernel nios_u(.clk_clk (clk), // clk.clk.reset_reset_n (locked), // reset.reset_n.led_out_new_signal (led0) // led_out.new_signal);assign led1 &#61; ~led0;endmodule
按照与前述相同的办法在 Pin Planner 中设置 led0 和 led1 管脚的位置
在 Quartus 中直接双击 Tasks 界面的 Compile Design 完成编译&#xff0c;不需要再次添加时钟约束。
完成 Quartus 工程的编译后&#xff0c;打开 SBT 内的 workspace。
在 nios_app_bsp 工程选择&#xff0c;Generate BSP 后&#xff0c;再次运行 Build Project
按以下代码修改 hello_world.c 后&#xff0c;在 nios_app 工程选择 Build Project
#include
#include
#include "alt_types.h"int main()
{alt_u8* ptr_led &#61; AVALON_LED_0_BASE&#43;15;//偏移地址 15 即为组件 HDL 中的地址值while (1){printf("Hello from Nios II!\n");usleep(250000);*ptr_led &#61; 255;usleep(250000);*ptr_led &#61; 0;}return 0;
}
按前述相同的办法加载并运行程序&#xff0c;发现板上 2 个 LED 按设计闪烁。