目录
- 1、实验目的
- 2、实验内容
- 3、实验步骤
- 3.1 实现流水灯
- 3.1.1、Verilog实现——功能:
- 3.1.2、Verilog实现——设计:
- 3.1.3、Verilog实现——代码:
- 3.1.4、仿真实现图
- 3.2.1、Nios实现——创建一个Quartus项目,并将芯片选择为EP4CE115F29C7
- 3.2.2、Nios实现——启动Platform Designer工具
- 3.2.3、Nios实现——添加并设置器件,并连线:
- 3.2.4、项目设置:
- 3.2.4、在原理图(BDF)文件中添加 PD 生成的系统符号
- 3.2.5、加入 Quartus II IP File 文件
- 3.2.6、进行逻辑连接和生成管脚
- 3.2.7、芯片引脚设置
- 3.2.8、编译工程
- 3.2.9、分配管脚
- 3.2.10、软件设计
- 3.2.11、运行项目
- 3.2.12、运行/调式程序
- 4、总结
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 软件的开发流程,软件的基本调试方法。
并完成以下试验:
- 在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编程对于我来说也是一种的新的技术,之后应该好好的进行学习。