完整的SOPC開發流程體驗


 

課程目標:學習並掌握完整的SOPC開發流程。

開發環境:Quartus15.1

學習內容:1、使用QSYS工具建立能夠運行流水燈項目的NIOS II處理器系統

     2、在quartus ii中添加NIOS II 系統文件(完成SOPC系統搭建);

     3、在nios II EDS中創建NIOS ii軟件工程,實現流水燈代碼;

     4、在開發板上運行流水燈程序。

 

設計流程:

 創建一個新的project 工程

新建一個GHRD.v頂層文件

 

打開QSYS

 選擇最新的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工程轉換成自己開發可以使用的工程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM