当先锋百科网

首页 1 2 3 4 5 6 7

1、实验目的

(1)学习 Quartus Prime 、Platform Designer、Nios II SBT 的基本操作;
(2)初步了解 SOPC 的开发流程,基本掌握 Nios II 软核的定制方法;
(3)掌握 Nios II 软件的开发流程,软件的基本调式方法。

2、实验内容

学习 Quartus 、Platform Designer、Nios-II SBT 的基本操作;初步了解 SOPC 的开发流程,基本掌握 Nios-II 软核的定制方法;掌握 Nios-II 软件的开发流程,软件的基本调试方法。
并完成以下试验:

  1. 在DE2-115开发板上分别用Verilog和Nios软件编程两种方式完成LED流水灯显示,理解两种方式的差异;

3、实验步骤

3.1 实现流水灯

3.1.1、Verilog实现——功能:

第一秒:点亮第一个LED灯,LED灯亮1s
第二秒:熄灭第一个LED灯,点亮第二个LED灯,第二个LED灯亮1s
第三秒:熄灭第二个LED灯,点亮第三个LED灯,第三个LED灯亮1s

如此循环,如下图所示:
在这里插入图片描述

3.1.2、Verilog实现——设计:

首先肯定需要一个计数器来计时是否已经到1s了。每计时到1s,就说明这个灯已经亮了1s了,该下一个灯亮了,这里可以再用一个计数器来判断状态。

3.1.3、Verilog实现——代码:

module water_led (
    clk,
    rst_n,
    leds
);
input           clk;
input           rst_n;
output  [7:0]   leds;

// 1s计时器
reg     [25:0]  cnt0;
wire            add_cnt0;
wire            end_cnt0;
always @(posedge clk or negedge rst_n)
begin
    if (rst_n == 0)
    begin
        cnt0 <= 0;
    end
    else if (add_cnt0)
    begin
        if (end_cnt0)
            cnt0 <= 0;
        else
            cnt0 <= cnt0 + 1; 
    end
end
assign add_cnt0 = 1;
assign end_cnt0 = add_cnt0 && cnt0 == 50_000_000 - 1;  // 开发板的频率是50MHz,所以一秒钟会有50M个周期

// 应该第几个灯亮
reg     [3:0]   cnt1;
wire            add_cnt1;
wire            end_cnt1;
always @(posedge clk or negedge rst_n)
begin
    if (rst_n == 0)
    begin
        cnt1 <= 3'b000;
    end
    else if (add_cnt1)
    begin
        if (end_cnt1)
            cnt1 <= 0;
        else
            cnt1 <= cnt1 + 1; 
    end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1 == 8 - 1;

// 根据cnt1控制灯的亮灭
reg     [7:0]   leds;
always @(posedge clk or negedge rst_n)
begin
    if (rst_n == 0)
    begin
        leds <= 7'b000_0001;
    end
    else if (cnt1 == 3'd0) begin leds <= 8'b0000_0001; end
    else if (cnt1 == 3'd1) begin leds <= 8'b0000_0010; end
    else if (cnt1 == 3'd2) begin leds <= 8'b0000_0100; end
    else if (cnt1 == 3'd3) begin leds <= 8'b0000_1000; end
    else if (cnt1 == 3'd4) begin leds <= 8'b0001_0000; end
    else if (cnt1 == 3'd5) begin leds <= 8'b0010_0000; end
    else if (cnt1 == 3'd6) begin leds <= 8'b0100_0000; end
    else if (cnt1 == 3'd7) begin leds <= 8'b1000_0000; end
end
endmodule

3.1.4、仿真实现图

由于在编写博客时,开发板不在身边,只能通过仿真来验证代码的正确性。
在这里插入图片描述
从仿真图中可以看到,在1s的时候cnt1等参数确实发生了变化。但是这张图的才仿真到1s,就已经花了差不多半分钟的时间。所以,为了能够更加直观的观察我们的结果,下面的图将cnt0中的50_000_000修改为了50_000,也就是将周期从1s修改到了1ms。
在这里插入图片描述

3.2.1、Nios实现——创建一个Quartus项目,并将芯片选择为EP4CE115F29C7

3.2.2、Nios实现——启动Platform Designer工具

在菜单栏中的Tools中,
在这里插入图片描述
启动后会出现如下图的界面:
在这里插入图片描述
先将这个项目保存到某个路径下(ctrl+s),最好就在项目路径下:将项目名称修改为kernel
在这里插入图片描述

3.2.3、Nios实现——添加并设置器件,并连线:

设置时钟:在这里插入图片描述
添加CPU:
在搜索栏中输入nios进行器件的查找,选择Nios II Processor,并点击Add按钮进行添加
在这里插入图片描述
添加成功之后会让配置,先保持默认配置。点击右下角的Finish返回PD界面
在这里插入图片描述
将 nios2_qsys_0 重命名为 cpu,右键点击之后选择”Rename”即可重新命名。
在这里插入图片描述
将 cpu 的 clk 和 reset_n 分别与系统时钟 clk_0 的 clk 和 clk_reset 相连。
在这里插入图片描述
添加 jtag uart 接口:
选择‘JTAG UART Intel FPGA IP’,并添加
在这里插入图片描述
添加之后保持默认即可。并将器件重命名为 jtag-uart。

进行连线:
在这里插入图片描述
添加片上存储器 On-Chip Memory(RAM)核:
在这里插入图片描述
在”Size”栏中的”Total memory size”窗口中输入 40960(即片上内存的大小为 40KB),其余保持默认。
在这里插入图片描述
将器件名称修改为“onchip_ram”,并进行连线:
在这里插入图片描述
添加 PIO 接口
在搜索框中输入pio
在这里插入图片描述
将其中的Width 修改为 8bits,Direction 选择为 output,其余选项保持默认。
在这里插入图片描述
将器件名称修改为“pio”,并在 Export 栏处双击,把输出口引出来,并命名为 out_led。进行连线。
在这里插入图片描述
添加片 System ID Peripheral:
在这里插入图片描述
各项参数保持默认即可。并将器件名称修改为“sysid”。

连线:
在这里插入图片描述

3.2.4、项目设置:

基地址分配:
在这里插入图片描述
完成后”Base”栏将出现不会重复的具体的地址,如下图:
在这里插入图片描述
分配中断号:在”IRQ”标签栏下点选”Avalon_jtag_slave”和 IRQ 的连接点就会为”jtag_uart”核添加一个值为 0 的中断号。在这里插入图片描述
指定 NIos II 的复位和异常地址: 双击建立好的 cpu 进入 Nios II Processor 的配置界面,配置 Reset Vector 和 Exception Vector 为”onchip_ram.s1”,点击Finish退出
在这里插入图片描述
连接所有复位端口:
点击主界面下System的Create Global Reset Network,即可完成所有复位端口的自动连接。
在这里插入图片描述
最终连接图: 仔细对照,否则后面的操作无法进行
在这里插入图片描述
生成 Qsys 系统: 点选”Generation”标签栏中 Generate HDL按钮生成 Qsys 系统。如果生成过程中提示是否保存文件的话,就选择保存文件。之后关闭Platform Designer工具。
在这里插入图片描述

3.2.4、在原理图(BDF)文件中添加 PD 生成的系统符号

点击框中的按钮,点击之后进入右边的界面中查找刚才生成的符号,也就是kernel.bsf文件。该文件应该在保存kernel.qsys文件路径下的同名文件夹(kernel)中。
在这里插入图片描述
在这里插入图片描述

3.2.5、加入 Quartus II IP File 文件

点击 Assignments->Settings,添加 kernel.qip 文件
在这里插入图片描述
.qip文件在保存.qsys文件路径的同名文件夹下的synthesis文件夹中,之后就ok和apply即可
在这里插入图片描述

3.2.6、进行逻辑连接和生成管脚

在bdf图中右键点击kernel,选择其中的“Generate Pin for Symbol Ports”生成管脚。(这里已经生成过了,所以按键会显示灰色)
在这里插入图片描述
将管脚”inclk0”改名为 clock,管脚”reset_reset_n”改名为 reset_n,管脚 out_led_export[7…0]改为 out_led[7…0]。
在这里插入图片描述

3.2.7、芯片引脚设置

Assignments -> device。
在这里插入图片描述
点击 Device pin options
在这里插入图片描述
进行 unused pin 设置,可能会收到外部信号的干扰,将未用引脚设置为 As input tri-stated。
在这里插入图片描述
特殊引脚设置,设置为常规引脚。
在这里插入图片描述

3.2.8、编译工程

点击上方的按钮进行编译,当左下角的进度条都完成时就可以进行下一步了。
在这里插入图片描述

3.2.9、分配管脚

在这里插入图片描述
按照开发板提供的管脚名称分配针脚
在这里插入图片描述
之后关闭Pin Planner返回Quartus主界面。

3.2.10、软件设计

Tool -> Nios II Software Build Tools for Eclipse
在这里插入图片描述
启动 Workspace 选择当前的项目目录,点 OK。
在这里插入图片描述
进入Eclipse主界面:
在这里插入图片描述
新建工程:
在这里插入图片描述
点击后出现下图,在”SOPC Information File name”窗口中选择 kernel.sopcinfo 文件,以便将生成硬件配置信息和软件应用关联,CPU 栏会自动选择”CPU”。在”Project name”输入hello_world,“Project template”选择 Hello_World。
在这里插入图片描述
然后系统会自动生成一个项目,在项目中会有一个hello_world.c文件,在这个文件中编写流水灯的代码

#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"
const alt_u8 led_data[8]={0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};
int main (void)
{
	 int count=0;
	 alt_u8 led;
	 volatile int i;
	 while (1)
	 { 
		 if (count==7)
		 {
		 	count=0;
		 }
		 else
		 {
		 	count++;
		 }
		 led=led_data[count];
		 IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, led);
		 i = 0;
		 while (i<500000) {i++;}
	 }
	 return 0;
}

右键项目名称,选择Build Project。之后等待编译完成即可。
在这里插入图片描述
在这里插入图片描述

3.2.11、运行项目

配置FPGA: 连接 JTAG 到开发板,确定 1、已正确安装驱动。 2、防火墙不会影响到 JTAG 的正常工作。最后给开发板上电。

启动 Quartus Prime Programmer。
在这里插入图片描述
点击Add File添加文件,然后点击 Start 开始下载。(这里似乎没有将线连好)下载完成之后返回Eclipse

在这里插入图片描述

3.2.12、运行/调式程序

在菜单栏中选择 Run →Run Configurations。
在这里插入图片描述
配置 Run Configurations,转到”Target Connection”标签栏,点击右侧的 Refresh
Connections 将 USB-Blaster 加入。
在这里插入图片描述
Apply 后,点击Run,就可以看到开发板上的LED灯在闪烁
在这里插入图片描述

4、总结

本次试验中最需要注意的是硬件配置的部分,稍不注意就会出现错误。同时,相较于Verilog代码,C++代码的编写更加符合我的思考,更容易想出来和理解。本次试验中使用C++代码代替Verilog进行FPGA编程对于我来说也是一种的新的技术,之后应该好好的进行学习。