完整的SOPC開發流程體驗

 

課程目標:學習並掌握完整的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工程轉換成本身開發可使用的工程。

相關文章
相關標籤/搜索