DE1-SOC开发笔记

verilog-FPGA
    采用verilog开发语言,使用时序和组合逻辑。进行行为,数据流,结构建模。RTL级编程,在实际板卡上面验证逻辑的正确性。
sopc:
    软硬件结合的开发方式,在FPGA内部内建CPU,实现与FPGA的交互,实现系统级的开发。
qsys:
    根据实际项目需求,可视化操作,自定义搭建硬件环境,在单核FPG内通常为类似单片机一样的东西。在双核FPGA内
搭建的是基于coetex-A9架构的处理器,拥有更高的性能。运行linux操作系统,从boot sd卡中启动。PC机终端设备为PUTTY,
或者secure—CRT等中断工具,来进行文件管理,或者和linux的交互。
nios:
    单核FPGA的软件搭建环境,是基于eclipse的IED,对软件进行编译,链接,下载。
eds
    双核soc-FPGA的嵌入式开发套件,ARM架构HPS的开发环境,编程,开发,调试优化应用程序。生成 Preloader
Image File(.img),和生成 Device Tree (.dtb)
opencl-sdk
    opencl是一个开放的面版税的编程模型,能够在异构系统上面实现加速算法处理。支持不同平台上面基于C语言的编程
例如CPU,GPU,DSP,FPGA。OPENCL包含API,一般通过PCI_E实现主机和硬件加速器的交互,或者一个内核和另外一个没有
主机控制的内核进行通信。
    opencl-sdk,抽象出复杂的FPGA设计,支持开发人员基于C来编写硬件加速内核函数,并支持其他的opencl结构,方便
了在FPGA上实现应用程序。 仿真器,优化报告,内核性能分析器,编译器,代码优化。
arm-Linux
    arm架构的处理器,运行linux操作系统。
cyclone-FPGA-HARDWARE
    硬件层面,稳定的运行平台,是开发的基础。

    
    
quartus prime15.1(hdl,rtl,编译,综合工具,产生SOF配置文件,配置)

qsys(搭建hps硬件系统,可视化操作界面):
{
1. SOPC info file(.sopcinfo):文档用于生成 Device Tree
2. Handoff Folder:里面有关于产生 preloader 相关配置文件
3. System View Descr(.svd):用于 DS-5 debug 功能
}

生成 Preloader Image File:
{
    Embedded_Command_Shell.bat
    bsp_editor
    new(ghrd\hps_isw_handoff\soc_system_hps_0\, create software folder and setting.bsp file)
    Generate 生成 preloader 的原始档以及 Makefile---在 shell 窗口,进入项目位置里的 softeare\spl_bsp 活页夹
    cd “C:\Users\Ma\Desktop\GHRD\software\spl_bsp”
    输入make指令 若 PC CPU 内核为多核, 如 4 核,可输入 make -j8 进行多核编译
    此项操作会需要一点时间,编译完成后可以在\sotware\spl_bsp\uboot-socfpga\spl 文件夹下看到 Preloader 的 elf 和 binary文档
    uboot-socfpga/spl/u-boot-spl Preloader ELF file
    uboot-socfpga/spl/u-boot-spl.bin Preloader binary file
    产生 preloader 的 image file
    先将\sotware\spl_bsp\uboot-socfpga\spl 下的 u-boot-spl.bin 复制到向上两层的\sotware\spl_bsp\文件夹下
    在 shell 窗口下, 路径也重新定位于此。
    输入指令 mkpimage -o preloader_with_header.img u-boot-spl.bin
    如此便可以产生 preloader_with_header.img 文件
    产生的新的 preloader image file 即可在 linux 环境下,通过输入相应命令更新到 boot SD card。
}

生成 Device Tree:
Device Tree 是一种有关硬件系统描述的数据结构, 它可以描述整个系统上挂载了多少
种类的硬件。 通过 device tree 系统上的硬件信息都可以传递给 OS ( linux)。如此
便可以不用在 Kernel 内放置大量的冗长的代码。 这样的特性对于硬件里面有 FPGA 的
情况下提供了很大的弹性与灵活性。
当 Qsys 产生出 FPGA 的设计后( .sopcinfo), 可以使用 Altera SoC EDS 工具里的 Device
Tree Generator 来产生 Device Tree 的源文档( dts)。 它描述了有关 HPS 的外设还有
选择使用到的 FPGA Soft IP 以及用户自定义的外设等信息。
.dtb 文件是.dts 文件被 Device Tree Compiler 编译后生成的二进制格式的 Device Tree
描述, 可被 Linux 内核解析。 通常在我们为开发板制作 NAND、 Sdcard 启动 image 时,
会为.dtb 文件预留一个很小的存放区域( FAT 分区)。 之后 bootloader 在引导 kernel
的过程中, 会先读取该.dtb 到内存。
{
    soc_system.sopcinfo 文件 hps_clock_info.xml 和soc_system_board_info.xml.
    Device Tree Generate 将使用这两个文件来产生出.dts 文件。
    Embedded Shell 下进入工程目录文件夹,输入命令以产生 .dts文件

    sopc2dts --input soc_system.sopcinfo --output soc_system.dts --board
    soc_system_board_info.xml --board hps_clock_info.xml --bridge-removal
    all

    接着输入 dtc -I dts -O dtb -o soc_system.dtb soc_system.dts 产生 .dtb文件
}


将介绍如何创建 HPS(Hard Processer System) 工程和使用 Altera SoC EDS tool( Altera Embedded Command Shell)
编译工程:

编写程序文件(C 语言程序文本)和makefile(制定 Altera Embedded Command Shell 编译工程的一系列规则)
使用 Altera Embedded Command Shell 编译工程
F:\EDS\de1_soc_sw_lab1
输入 “ make” 命令编译产生可执行文件

(1)如何使用 Linux “scp” 命令将可执行文件“ my_first_hps” 拷贝至 SDCard 中
{
    首先, 用 RJ45 网线将 PC 和 DE1-SOC 都接到同一个路由器上使其在同一个局域网中
    启动 Linux 并自动获取 IP ( PUTTY )
    通过网络(ssh) 传送可执行文件到 Linux
        1. root 账户登陆。
        2. 输入 “ udhcpc” 自动获取 ip。
        3. 输入 “ ifconfig” 查询获取的 IP 地址这个例子中 DE1-SOC 获得的 IP 是“ 192.168.1.113”
        定完 IP 后, 由于“ scp” 命令需要输入密码, 如果 root 账户还没有设定密码,可以输入
        “ passwd” 命令创建terasic” 。cd 至 my_first_hps 文件夹。 输入 “ scp my_first_hps root
        @192.168.1.113:/home/root” , 把文件拷贝到 “/home/root”路径下.可以在 PuTTY 终端中输入
        ls 命令, 这时候会发现“ my_first_hps” 已拷贝进来。最后,输入 “ ./my_first_hps” 运行程序
}
(2)如何使用 U 盘将可执行文件“ my_first_hps” 拷贝至 SD Card 中:
{
    将 U 盘插入电脑, Copy 编译好的可执行文件到 U 盘。
    将拷贝好文件的 U 盘, 插入 DE1-SoC 的 USB 接口 (USB1/2) 。
    在 DE1-SoC 的串口终端输入以下命令:
    mount -t vfat /dev/sda1 /mnt 加载 U 盘至/mnt 路径下。
    cp – p /mnt/my_first_hps /home/root 复制可执行文件至 /home/root 路径下
    umount /mnt 卸载 U 盘
    在运行可执行文件之前, 需要执行“ chmod 777 my_first_hps” 命令, 增加文件可执行属性
    最后, 输入 “./my_first_hps”
}

HPS_GPIO:
通过 linux 内核 memory-mapped device 驱动访问 GPIO 控制器的寄存器而控制 HPS 端的用户 LED 和 KEY
memory-mapped device 驱动允许应用程序访问系统所有外设寄存器物理地址空间, 包括 GPIO 控制器物理地址
用户 LED 和 KEY 都是连接到 HPS 的 GPIO1 控制器。 GPIO 控制器的行为通过其寄存器来控制
应用程序通过内存映射设备驱动访问 GPIO1 控制器的寄存器
GPIO[57..29] 被 GPIO1 控制器控制;
GPIO[70..58] 和input-onlyGPI[13..0] 被 GPIO2 控制器控制。

通过 gpio_swporta_ddr 寄存器配置 LED 引脚为输出引脚
通过gpio_swporta_dr 寄存器控制其输出高低电平
通过读取 gpio_ext_porta 寄存器来查询KEY 的状态

HPS 外设映射到 HPS 基地址 0xFC000000 上,共 64MB 的寻址空间。
GPIO0控制器的寄存器映射到基地址 0xFF708000 共 4KB 寻址空间
GPIO2 控制器映射到基地址 0xFF70A000 共 4KB 寻址空间。

LED 连接到 HPS_GPIO53,KEY 连接到HPS_GPIO54,被 GPIO1控制HPS_GPIO29~HPS_GPIO57。

GPIO1 bit-24,bit-25 控制 HPS_LED,HPS_KEY

LED 是高电平有效

软件 API:
开发者可以通过如下软件 API 访问 GPIO 控制器的寄存器
 open: 打开内存映射设备驱动
 mmap: 映射物理地址到用户空间
 alt_read_word: 从指定寄存器读取一个值
 alt_write_word: 写入一个值到指定寄存器
 munmap: 清除内存映射
 close: 关闭设备驱动.
开发者同样可以通过如下 MACRO 访问寄存器
 alt_setbits_word: 设定指定寄存器的指定位为 1
 alt_clrbits_word: 设定指定寄存器的指定位为 0

为了使用以上 API 来访问 GPIO 控制器的寄存器, 程序需要包含如下头文件。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "hwlib.h"
#include "socal/socal.h"
#include "socal/hps.h"
#include "socal/alt_gpio.h"
#define USER_IO_DIR (0x01000000)
#define BIT_LED (0x01000000)
#define BUTTON_MASK  (0x02000000)
//配置 LED 引脚为输出引脚。
alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DDR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), USER_IO_DIR );
//点亮 LED
alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED );
//读取 gpio_ext_porta 寄存器内容, bit 标记是用来检查 KEY 的状态。
alt_read_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_EXT_PORTA_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ) );

执行 demo 步骤:
1. 启动 DE1-SoC 中的 Linux 系统。
2. “ scp” 复制可执行文件“ hps_gpio” 到 Linux 路径下(home/root) 或使用 U盘拷贝。
3. 串口终端中输入“ chmod 777 hps_gpio” 更改文件可执行属性。
4. 输入“ ./hps_gpio” 执行 ARM 程序。 我们将会看到 HPS_LED 闪烁两次,然后再按 HPS_KEY 时候, HPS_LED 会显示 HPS_KEY 的状态。 使用 ctrl+c 终止程序运行。
5. 复制文件至 SD Card Linux 路径下。

HPS 和 FPGA 之间的协议通信主要是通过 AXI(AdvancedeXtensible Interface) -bridge.
HPS 作为主端(master) , 其可以访问 FPGA 端 Avalon MM slave 接口的所有组件
FPGA-to-HPS bridge 也可以作主端控制 L3 main switch, 允许 FPGA 端的主端访问大
部分的 HPS 从端。 比如, FPGA 资源可以通过 FPGA-to-HPS 桥可以访问到 HPS 端的加速
度传感器。
linux 应用程序通过 linux 内核 memory-mapped device 驱动访
问 PIO 控制器 pio_led 的寄存器物理地址进而控制 pio_led 进行相应动作。 Altera SoC
EDS 用来编译应用程序。

HPS 头文件:
{
    1. 运行 Altera SoC EDS command shell
    2. 通过 shell 命令 cd 定位到 QuartusII 工程文件夹根目录。
    3. 输入‘ ./generate_hps_qsys_header.sh” 并按 Enter 键执行, 成功执行后, 会生出
    名为 hps_0.h 的头文件。 在头文件中, 包含 pio_led 在 Qsys 中分配的相对于 lwaxi 的
    基地址, 它表现为一个宏定义 PIO_LED_BASE;pio_led 的位宽信息表示为宏定义
    PIO_LED_DATA_WIDTH. 这两个参数将会是应用程序访问 pio_led 寄存器所需要的。
}

映射 pio_led 地址:
{
    C 应用程序从 pio_led 基地址转换出虚拟地址。 首先, 系统调用函数 open
    用来打开 memory 设备驱动“ /dev/mem”, 然后用系统调用函数 mmap 映射 HPS 的 L3 外
    设区域物理地址到虚拟地址并表示为一个空指针变量 virtual_base. 然后可以通过

    virtual_base 增加如下两个偏移地址计算得出 pio_led 的虚拟地址。
        轻量级 HPS-to-FPGA AXI 总线相对于 HPS 的 L3 外设区域基地址的偏移地址
         pio_led 相对于轻量级 HPS-to-FPGA AXI 总线的偏移地址
    第一个偏移地址在 hps.h 中被宏定义为 ALT_LWFPGASLVS_OFST。
    hps.h 是 Altera SoC EDS 的一个头文件, 它位于Quartus 安装文件夹\embedded\ip\altera\hps\altera_hps\hwlib\include\socal
    第二个偏移地址是 pio_led 在 Qsys 中分配的相对 lwaxi 的基地址, 这个在之前章节提
    到的头文件 hps_0.h 中, 被宏定义为 PIO_LED_BASE。 pio_led 的虚拟地址被定义为空
    指针 h2p_lw_led_addr. 应用程序可以直接用这个指针变量访问 pio_led 控制器的寄存器。
    
    if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
        printf( "ERROR: could not open \"/dev/mem\"...\n" );
        return( 1 );
    }

    virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, HW_REGS_BASE );

    if( virtual_base == MAP_FAILED ) {
        printf( "ERROR: mmap() failed...\n" );
        close( fd );
        return( 1 );
    }
}

LED 控制:
{
    写 0x000003ff 到偏移地址为 0 的寄存器, 十个红色 LED 将会亮起。
    *(uint32_t *) h2p_lw_led_addr= 0x000003ff
    C 编译器知道写 32 位值0x000003ff 到 h2p_lw_led_addr 虚拟地址。
}

创建工程文件夹
创建程序文件
创建 Makefile 文件  白文本文档并命名为“ Makefile”
编译工程
执行 demo

lw_axi_virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, HW_REGS_BASE );
axi_virtual_base     = mmap( NULL, HW_FPGA_AXI_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, ALT_AXI_FPGASLVS_OFST);

FPGA 与 HPS 接口
FPGA to SDRAM 接口是 HPS 内部的 SDRAM 控制器提供给 FPGA 访问 HPS 内存的接口
FPGA – to-SDRAM 接口支持 AXI-3/4 协议和 Avalon-MM 协议。其中 Avalon-MM 协议可
以设定为只读, 只写或者读写双向。 接口数目和位宽都可以根据用户的实际需要在 Qsys
中进行设定

AXI bridge 是 FPGA 和 HPS 总线之间数据交互的接口 , 包括 FPGA-to-HPS AXI、 HPS-to-FPGA AXI 和 Light-weight HPS-to-FPGA AXI。
AXI bridge 在 HPS 端使用的是 AMBA AXI 协议, 用户在 FPGA 中逻辑设计时可以使用 AXI 协议与 HPS 通信。
另外 Qsys interconnect 也实现了 AXI 协议到 Avalon-MM 协议的自动转换, 所以用户可以在 Qsys 中实现 Avalon-MM 接口与 AXIbridge 的 IP 直接互联。

Qsys 中提供的 System console 工具可以通过 JTAG 访问到 JTAG to Avalon master IP
所连接的 slave 设备, 在本系统中即 FPGA-to-HPS 接口所能访问的 HPS 的外设或者 HPS
端的 DDR3。

fpga与hps通信方式:
(1) 互联逻辑:hps访问fpga端sdram,fpga操作sdram。(hps->fpga)
(2) 互联逻辑:fpga访问hps端ddr3,hps操作ddr3。   (fpga->hps)
(3) 互联逻辑:fpga通过axif2h存入ddr3中,hps读取ddr3数据。(fpga->hps)

自定义qsysIP组件:
interface的端口名要和verilog源文件的端口名相对应。。
分清楚slave和master的关系。做好元件地址的自动分配。
自定义IP组件的时候遵循一定的顺序就比较好看了。
先进行地址的分配,进行寄存器的读写,最后进行程序的控制代码。

完成硬件更改之后,qsys中的器件基地址会发生变化。记得要更新hps-0.h头文件。

————很多应用api可能存在于cv_soc_devkit_ghrd文件夹中。。。

猜你喜欢

转载自blog.csdn.net/weixin_42717395/article/details/88855349