Nios II 基礎工程和自定義組件

軟件環境:Quartus Prime Standard 18.1 Window 10

硬件環境:小梅哥 AC501 開發板

主要參考:

本實驗使用 Nios 的自定義組件控制開發板上 LED 閃爍。

本文首先建立了基於片上 RAM 的基礎 Nios 工程,之後在該工程上添加基於 Avalon-MM 接口的自定義組件,修改 Nios 軟件後實現 LED 閃爍。

建立 Quartus 工程

打開 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:

在這裏插入圖片描述

用 Platform Designer 建立 qsys 模塊

在 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 工程頂層模塊設計

添加 qsys 模塊

回到 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 添加至工程:

在這裏插入圖片描述

在這裏插入圖片描述

建立並編寫頂層 HDL 模塊

選擇菜單項 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

在這裏插入圖片描述

等待完成編譯

在這裏插入圖片描述

Nios 軟件

選擇菜單項 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 <stdio.h>
#include <unistd.h>

int main()
{
	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 Designer 建立自定義組件

打開 Platform Desgner,並且在 IP Catalog 雙擊 New Component

在這裏插入圖片描述

在彈出窗口中配置組件:

  1. 在 Component Type 頁設置組件名稱和顯示名稱,以及 Group

在這裏插入圖片描述

  1. 在 Signal & Interfaces 頁,雙擊 add interface 添加接口

在這裏插入圖片描述

  1. 在 Signal & Interfaces 頁,進入每個 interface 的配置界面進行配置,主要是時鐘與復位
  2. 在 Signal & Interfaces 頁,在每個 interface 下雙擊 add signal 添加接口信號,並配置
    • 由於 avalon_slave 只用於寫入數據,因此只有地址(4 位)、片選、寫使能和寫數據(8 位)
  3. 在 Files 頁,點擊 Create Synthesis File from Signals,根據提示建立關聯 HDL 文件,並且依據 Signal & Interfaces 頁的設置生成模塊端口
    • 比較麻煩的是不能修改默認文件名,可以在生成文件後,用 Remove File 移除默認文件,修改文件名和內部模塊名後再用 Add File 添加

在這裏插入圖片描述

在這裏插入圖片描述

按以下代碼修改建立的 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.address
		input  wire       avalon_slave_chipselect, //             .chipselect
		input  wire       avalon_slave_write,      //             .write
		input  wire [7:0] avalon_slave_writedata,  //             .writedata
		input  wire       reset_sink_reset,        //   reset_sink.reset
		input  wire       clock_sink_clk,          //   clock_sink.clk
		output wire       conduit_end_led_out      //  conduit_end.new_signal
	);

	// TODO: Auto-generated HDL template
	wire clk;
	assign clk = clock_sink_clk;
	wire rst;
	assign rst = reset_sink_reset;
	
	//輸出 LED 值
	reg led = 1'b0;

	always @(posedge clk or posedge rst) begin
		if (rst == 1'b1) begin
			led <= 1'b0;
		end
		else begin
			case ({avalon_slave_chipselect, avalon_slave_write, avalon_slave_address})
				{1'b1, 1'b1, 4'b1111}: begin
					case (avalon_slave_writedata)
						8'hFF: begin
							led <= 1'b1;
						end

						8'h0: begin
							led <= 1'b0;
						end

						default: begin
							//保持
							led <= led;
						end
					endcase
				end

				default: begin
					//保持
					led <= led;
				end
			endcase
		end
	end

	assign conduit_end_led_out = led;

endmodule

完成上述步驟後,點擊 Finish 按鈕。

在 IP Catalog 中雙擊剛纔建立的組件,點擊 Finish 按鈕將組件添加至 System Contents 中

在這裏插入圖片描述

在這裏插入圖片描述

注意,在上圖中 avalon_led_0 組件的地址範圍是 0x0004_1000~0x0004_100f,對應自定義時配置的 4 位地址線。

在菜單中選擇 System > Assign Base Addresses,之後選擇 Generate > Generate HDL,生成 qsys 模塊

修改 Quartus 工程

向頂層模塊中的 qsys 模塊添加輸出 LED 端口,並連接至 FPGA 管腳,代碼如下:

module cus_com
(
	input clk_50m,
	output led0,
	output led1
);
	//時鐘生成
	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
	.led_out_new_signal (led0)  // led_out.new_signal
	);
	
	assign led1 = ~led0;

endmodule

按照與前述相同的辦法在 Pin Planner 中設置 led0 和 led1 管腳的位置

在這裏插入圖片描述

在 Quartus 中直接雙擊 Tasks 界面的 Compile Design 完成編譯,不需要再次添加時鐘約束。

修改 nios 軟件

完成 Quartus 工程的編譯後,打開 SBT 內的 workspace。

在 nios_app_bsp 工程選擇,Generate BSP 後,再次運行 Build Project

在這裏插入圖片描述

按以下代碼修改 hello_world.c 後,在 nios_app 工程選擇 Build Project

#include <stdio.h>
#include <unistd.h>

#include "../nios_app_bsp/system.h"
#include "alt_types.h"

int main()
{
	alt_u8* ptr_led = AVALON_LED_0_BASE+15;//偏移地址 15 即爲組件 HDL 中的地址值

	while (1)
	{
		printf("Hello from Nios II!\n");
		usleep(250000);
		*ptr_led = 255;
		usleep(250000);
		*ptr_led = 0;
	}
	return 0;
}

前述相同的辦法加載並運行程序,發現板上 2 個 LED 按設計閃爍。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章