目录
1. 简介
回顾此博文《Vitis HLS 学习笔记--Syn Report解读(1)-CSDN博客》。
我们在代码中使用了如下指令:
#pragma HLS INTERFACE mode=s_axilite bundle=BUS_A port=return
便得到了这些寄存器:
* S_AXILITE Registers
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
| Interface | Register | Offset | Width | Access | Description | Bit Fields |
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
| s_axi_BUS_A | CTRL | 0x00 | 32 | RW | Control signals | 0=AP_START 1=AP_DONE 2=AP_IDLE 3=AP_READY 7=AUTO_RESTART 9=INTERRUPT |
| s_axi_BUS_A | GIER | 0x04 | 32 | RW | Global Interrupt Enable Register | 0=Enable |
| s_axi_BUS_A | IP_IER | 0x08 | 32 | RW | IP Interrupt Enable Register | 0=CHAN0_INT_EN 1=CHAN1_INT_EN |
| s_axi_BUS_A | IP_ISR | 0x0c | 32 | RW | IP Interrupt Status Register | 0=CHAN0_INT_ST 1=CHAN1_INT_ST |
| s_axi_BUS_A | reg_in | 0x10 | 32 | W | Data signal of reg_in | |
+-------------+----------+--------+-------+--------+----------------------------------+----------------------------------------------------------------------+
本文将对这些寄存器进行详细解释。
2. S_AXILITE Registers 寄存器详解
2.1 “隐式”优势
使用 Vitis HLS 工具进行硬件设计带来了额外的“隐式”优势,即在驱动程序的自动生成方面。
这极大地简化了硬件设计流程,为工程师省了大量的时间。
在传统的硬件设计过程中,FPGA逻辑工程师的RTL代码完成设计后,还需要手动编写与之配套的驱动程序。不仅包括编写驱动程序本身,还要精确指定硬件设计中各个模块的地址和偏移量。这一过程不仅耗时耗力,而且极易出错,因为任何地址或偏移量的错误指定都可能导致整个系统无法正常工作。
相比,Vitis HLS提供了一个自动化的解决方案。如果使用Vitis HLS进行设计,工具不仅能够将高层次的算法描述转换成高效的硬件实现,而且还能自动创建与之匹配的驱动程序,包含了地址和偏移量指定,大大降低了设计复杂性和出错的可能性。
2.2 驱动程序文件
如简介中说指出的,一旦使用了 s_axilite 协议,工具会自动创建一组 C 语言驱动程序文件。
#pragma HLS INTERFACE mode=s_axilite ...
这些驱动文件位于如下目录中:
<proj>/solution1/impl/ip/drivers/func_v1_0/data
<proj>/solution1/impl/ip/drivers/func_v1_0/src
文件路径 |
使用模式 |
描述 |
data/func.mdd |
独立 |
驱动程序定义文件 |
data/func.tcl |
独立 |
共 SDK 用于将软件集成到 SDK 工程中 |
src/xfunc_hw.h |
独立 or Linux |
定义所有内部寄存器的地址偏移 |
src/xfunc.h |
独立 or Linux |
API 定义 |
src/xfunc.c |
独立 or Linux |
标准化的 API 实现 |
src/xfunc_sinit.c |
独立 |
初始化 API 实现 |
src/xfunc_linux.c |
Linux |
初始化 API 实现 |
src/Makefile |
独立 |
Makefile |
2.3 硬件头文件
在这几个文件中,对于硬件涉及最重要的文件就是这个 src/xfunc_hw.h 宏定义的硬件头文件了。它提供了存储器映射位置完整列表,对应分组到 AXI4-Lite 从接口内的所有端口。
此头文件包含两部分:
- 块级控制信号
- 映射到 s_axilite 接口内的函数实参
以下是 xfunc_hw.h 的完整内容:
// ==============================================================
// Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2022.1 (64-bit)
// Tool Version Limit: 2022.04
// Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
// ==============================================================
// BUS_A
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/SC)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read/COR)
// bit 7 - auto_restart (Read/Write)
// bit 9 - interrupt (Read)
// others - reserved
// 0x04 : Global Interrupt Enable Register
// bit 0 - Global Interrupt Enable (Read/Write)
// others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
// bit 0 - enable ap_done interrupt (Read/Write)
// others - reserved
// 0x0c : IP Interrupt Status Register (Read/COR)
// bit 0 - ap_done (Read/COR)
// others - reserved
// 0x10 : Data signal of reg_in
// bit 7~0 - reg_in[7:0] (Read/Write)
// others - reserved
// 0x14 : reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)
#define XFUNC_BUS_A_ADDR_AP_CTRL 0x00
#define XFUNC_BUS_A_ADDR_GIE 0x04
#define XFUNC_BUS_A_ADDR_IER 0x08
#define XFUNC_BUS_A_ADDR_ISR 0x0c
#define XFUNC_BUS_A_ADDR_REG_IN_DATA 0x10
#define XFUNC_BUS_A_BITS_REG_IN_DATA 8
代码中的注释部分已经描述了寄存器的作用,以及每个寄存器的用途和位字段的含义。
下面是对这些注释的详细解释:
0x00地址,是控制寄存器,包含启动、完成、空闲、准备等控制信号,以及自动重启和中断信号的标志位。
- ap_start (bit 0):启动操作,可读写,自清除(SC)。
- ap_done (bit 1):操作完成标志,可读,读取后自清除(COR)。
- ap_idle (bit 2):表示设备空闲,只读。
- ap_ready (bit 3):表示设备准备就绪,可读,读取后自清除(COR)。
- auto_restart (bit 7):自动重启操作,可读写。
- interrupt (bit 9):中断标志,只读。
- 其他位保留。
0x04地址,是全局中断使能寄存器,用于控制是否允许全局中断。
- 位0:全局中断使能,可读写。
- 其他位保留。
0x08地址,是IP中断使能寄存器,用于控制特定中断的使能。
- 位0:使能ap_done中断,可读写。
- 其他位保留。
0x0c地址,是IP中断状态寄存器,用于显示当前的中断状态。
- 位0:ap_done中断状态,可读,读取后自清除(COR)。
- 其他位保留。
0x10地址,是reg_in数据信号的寄存器,用于读写reg_in的值。
- 位7~0:reg_in[7:0]的值,可读写。
- 其他位保留。
接下来的代码定义了宏,这些宏将上述寄存器地址映射到具体的常量,方便在软件中引用这些寄存器地址。
2.4 硬件头文件中 SC/COR/TOW/COH 的解释
- SC - Self Clear
在写入操作中,当写入的寄存器位为1时,该位会被自动清除为0,而写入0时则不受影响。这通常用于只需要一次性设置某个寄存器位的情况。
- COR - Clear on Read
在读取操作中,当读取的寄存器位为1时,该位会被自动清除为0,而读取0时则不受影响。这通常用于需要清除某个中断标志的情况。
- TOW - Toggle on Write
在写入操作中,当写入的寄存器位为1时,该位会被取反,即原来为0的变成1,原来为1的变成0。这通常用于切换某个功能或状态的情况。
- COH - Clear on Handshake
在某个操作完成后,该寄存器位会自动清除为0。这通常用于需要等待某个操作完成的情况。
比如等待DMA传输完成后清除中断标志。
2.5 驱动控制过程
在软件中可使用 API 函数来控制硬件块,驱动的基本流程:
- 1. 创建硬件实例
XFunc HlsXFunc
- 2. 查找器件配置
XFunc_LookupConfig(DeviceId)
- 3. 初始化器件
XFunc_CfgInitialize(InstancePtr, ConfigPtr)
- 4. 设置 HLS 块的输入参数
XFunc_Set_reg_in(InstancePtr, Data)
- 5. 启动器件并读取结果
XFunc_Start(InstancePtr)
XFunc_Get_reg_in(InstancePtr)
初始化函数合并,在src/xfunc_sinit.c中:
XFunc_Initialize(InstancePtr, DeviceId)
=
XFunc_LookupConfig(DeviceId)
+
XFunc_CfgInitialize(InstancePtr, ConfigPtr)
所以使用XFunc_Initialize()可以一步实现查找和配置器件,完成初始化。
3. 总结
本文重点关注了 Vitis HLS 在设计过程中自动生成的驱动程序及其相关文件。通过对 s_axilite 协议下生成的寄存器进行解释,我们了解了这些寄存器的作用和每个寄存器位的含义,以及驱动程序中的控制过程。这种自动化的设计流程减少了手动编写驱动程序的工作量,同时也降低了出错的可能性,为硬件设计带来了更高的可靠性和稳定性。