課程目標:學習並掌握完整的SOPC開發流程。html
開發環境:Quartus15.1ios
學習內容:一、使用QSYS工具創建可以運行流水燈項目的NIOS II處理器系統網絡
二、在quartus ii中添加NIOS II 系統文件(完成SOPC系統搭建);函數
三、在nios II EDS中建立NIOS ii軟件工程,實現流水燈代碼;工具
四、在開發板上運行流水燈程序。學習
設計流程:測試
建立一個新的project 工程spa
新建一個GHRD.v頂層文件設計
打開QSYS3d
選擇最新的NIOS II CPU 核
因爲是第一次使用NIOS ii 的CPU 核,因此選擇默認的設置點擊finish便可
添加on-chip-ram做爲CPU的運行內存
修改一下內存大小,保證內存足夠大
添加只輸出型的四位PIO
一樣,將其重命名爲易觀察的名字
主要單元添加完畢後,便可進行總線類型的鏈接了
首先是數據總線主機與從機相連
而後是指令總線與從機存儲數據的模塊的數據總線相連
鏈接時鐘
建立全局復位網絡
鏈接完畢後的鏈接圖
導出PIO信號
分配基地址
此時,警告框仍是有兩個錯誤,這是由於,在設置CPU時,沒有設置復位地址和異常地址,雙擊nios2_gen2_0,將vector指向指令存儲器
保存並生成.qsys文件
生成HDL文件
生成例化模板
點擊copy,將內容粘貼到以前建立的GHRD的頂層文件中
至此,系統的NIOS II處理器就搭建完成了
下面就是對SOPC系統進行完善,在quartus II 軟件中添加NIOS ii處理器系統並分配引腳
添加quartus II處理器系統QSYS文件
對頂層的GHRD文件進行編寫
module GHRD( clk50m, rst_n, led, ); input clk50m; input rst_n; output [3:0]led; cpu u0 ( .clk_clk (clk50m), // clk.clk .reset_reset_n (rst_n), // reset.reset_n .pio_led_export (led) // pio_led.export ); endmodule
編譯完成了能夠對比編譯結果查看本身所用的FPGA,觀察邏輯結構是否夠用,由圖可知是夠用的。
分配引腳
編寫EDS代碼
打開後將工做空間設置到GHRD開發環境的工做空間
新建一個模板工程
led_run_bsp的板級支持包的工程結構
爲了保證工程在後面能夠直接調用,這裏新建一個文件夾來編寫代碼
在文件夾下建立兩個文件夾啊inc(存放頭文件.h)src(存放源文件.c)
建立一個.h文件
編寫led.h代碼
#ifndef LED_H_ #define LED_H_ #include"system.h" #include"altera_avalon_pio_regs.h" #include"alt_types.h" typedef void *LED_HANDLE; typedef struct{ alt_u32 led_base; alt_u32 led_data; }CoreCourse_LED; #define LED_ALL_OFF 0xffffffff #define LED0 0x00000001 #define LED1 0x00000002 #define LED2 0x00000004 #define LED3 0x00000008 /* #define LED4 0x00000010 #define LED5 0x00000020 #define LED6 0x00000040 #define LED7 0x00000080 #define LED8 0x00000100 #define LED9 0x00000200 #define LED10 0x00000400 #define LED11 0x00000800 #define LED12 0x00001000 #define LED13 0x00002000 #define LED14 0x00004000 #define LED15 0x00008000 #define LED16 0x00010000 #define LED17 0x00020000 #define LED18 0x00040000 #define LED19 0x00080000 #define LED20 0x00100000 #define LED21 0x00200000 #define LED22 0x00400000 #define LED23 0x00800000 #define LED24 0x01000000 #define LED25 0x02000000 #define LED26 0x04000000 #define LED27 0x08000000 #define LED28 0x10000000 #define LED29 0x20000000 #define LED30 0x40000000 #define LED31 0x80000000 */ LED_HANDLE LED_Init(const alt_u32 led_base); void LED_Off(CoreCourse_LED *p, alt_u32 ledx); void LED_On(CoreCourse_LED *p, alt_u32 ledx); void LED_Toggle(CoreCourse_LED *p, alt_u32 ledx); void LED_WriteData(CoreCourse_LED *p, alt_u32 leds); #endif /* LED_H_ */
建立一個.c空文件
一樣編寫led.c代碼
#include "led.h" #include <string.h> #include <stdlib.h> /****************************************************************************** * 函數名 : LED_Init * 描述 : 初始化LED結構體並返回結構體指針地址 * 輸入 : led_base ,system.h中定義的LED的基地址 * 輸出 : 無 * Return :通過初始化的LED結構體指針 *******************************************************************************/ LED_HANDLE LED_Init(const alt_u32 led_base) { CoreCourse_LED *p; p = malloc(sizeof(CoreCourse_LED)); if (!p) return p; memset(p, 0, sizeof(CoreCourse_LED)); p->led_base = led_base; p->led_data = 0xffffffff; IOWR_ALTERA_AVALON_PIO_DATA(p->led_base, p->led_data); return p; } /****************************************************************************** * 函數名 : LED_Off * 描述 : 關閉一個或多個LED * 輸入 : p ,LED結構體指針 * :LEDx,須要關閉的LED * 輸出 : 無 * Return :無 *******************************************************************************/ void LED_Off(CoreCourse_LED *p, alt_u32 ledx) { p->led_data = p->led_data | ledx; IOWR_ALTERA_AVALON_PIO_DATA(p->led_base, p->led_data); } /****************************************************************************** * 函數名 : LED_On * 描述 : 打開一個或多個LED * 輸入 : p ,LED結構體指針 * :LEDx,須要打開的LED * 輸出 : 無 * Return :無 *******************************************************************************/ void LED_On(CoreCourse_LED *p, alt_u32 ledx) { p->led_data = p->led_data & (~ledx); IOWR_ALTERA_AVALON_PIO_DATA(p->led_base, p->led_data); } /****************************************************************************** * 函數名 : LED_Toggle * 描述 : 翻轉一個或多個LED * 輸入 : p ,LED結構體指針 * :LEDx,須要翻轉的LED * 輸出 : 無 * Return :無 *******************************************************************************/ void LED_Toggle(CoreCourse_LED *p, alt_u32 ledx) { p->led_data ^= ledx; IOWR_ALTERA_AVALON_PIO_DATA(p->led_base, p->led_data); } /****************************************************************************** * 函數名 : LEDS_WriteData * 描述 : 直接控制全部LED的狀態,輸入的LED將被點亮,未輸入的將被關閉 * 輸入 : p ,LED結構體指針 * :LEDx,須要點亮的LED * 輸出 : 無 * Return :無 *******************************************************************************/ void LED_WriteData(CoreCourse_LED *p, alt_u32 leds){ p->led_data = leds; IOWR_ALTERA_AVALON_PIO_DATA(p->led_base, p->led_data); } /* main函數中初始化示例代碼 * * LED_HANDLE hLED; hLED = LED_Init(PIO_LED_BASE); if (!hLED) { // printf("Failed to init LED\n"); } */ /* LED_WriteData()函數使用示例代碼 * *LED_WriteData(hLED, LED0 | LED2); //LED0和LED2點亮,LED1和LED3關閉 } */ /* LED_On()函數使用示例代碼 * *LED_On(hLED, LED0 | LED2); //點亮LED0和LED2 } */ /* LED_Off()函數使用示例代碼 * *LED_Off(hLED, LED1 | LED3); //熄滅LED1和LED3 }*/ /* LED_Toggle()函數使用示例代碼 * *LED_Toggle(hLED, LED3); //翻轉LED3 }*/
將helloworld.c文件更改成main.c文件,並編寫main.c
/******************************************************************** * 文 件 名:main.c * 功 能:LED顯示控制。 * 經過PIO直接控制4個LED產生亮滅效果 * 說 明: * ********************************************************************/ #include "system.h" #include "altera_avalon_pio_regs.h" #include "alt_types.h" #include "led.h" /****************************************************************************** * 函數名 : DelayNs * 描述 : 簡易延時 * 輸入 : 須要延時的數值 * 輸出 : 無 * Return :無 *******************************************************************************/ void DelayNs(alt_u32 i) { while (i--) ; } /******************************************************************** * 名 稱:main() * 功 能:使用全部LED API控制LED運行 ********************************************************************/ int main(void) { alt_u32 i; //volatile alt_u32 j; LED_HANDLE hLED; hLED = LED_Init(PIO_LED_BASE); if (!hLED) { // printf("Failed to init LED\n"); } while (1) { //測試LED_WriteData函數功能 i = 2; while (i--){ LED_WriteData(hLED, LED0 | LED2); //LED1和LED3點亮,LED0和LED2關閉 DelayNs(5000000); LED_WriteData(hLED, LED1 | LED3); //LED0和LED2點亮,LED1和LED3關閉 DelayNs(5000000); } LED_WriteData(hLED, LED_ALL_OFF); //關閉全部的LED DelayNs(10000000); //測試LED_On函數和LED_Off函數功能 i = 2; while (i--){ LED_On(hLED, LED0 | LED2); //點亮LED0和LED2 DelayNs(5000000); LED_On(hLED, LED1 | LED3); //點亮LED1和LED3 DelayNs(10000000); LED_Off(hLED, LED0 | LED2); //熄滅LED0和LED2 DelayNs(5000000); LED_Off(hLED, LED1 | LED3); //熄滅LED1和LED3 DelayNs(10000000); } LED_WriteData(hLED, LED_ALL_OFF); //關閉全部的LED //測試LED_Toggle函數功能 i = 8; while (i--){ LED_Toggle(hLED, LED3); //翻轉LED3 DelayNs(5000000); } } return 0; }
添加led_run_bsp的路徑
添加led.h的路徑
對工程進行編譯
將quartus以前生成的.sof文件燒寫到FPGA開發板中,而後在NIOS ii中選擇進行仿真運行
等待一會後會彈出以下界面,以後能夠按照keil仿真的方法進行
實驗現象http://v.youku.com/v_show/id_XMjk0NDQwOTQyOA==.html?spm=a2h3j.8428770.3416059.1
本文的源代碼將在下篇文章上傳,並講解如何將別人的NIOS ii工程轉換成本身開發可使用的工程。