July 23, 2016
作者:dengshuai_super
出处:http://blog.csdn.net/dengshuai_super/article/details/52004095
声明:转载请注明作者及出处。
来源:
这个实验练习集成了HLS IP 和(被HLS创建用来控制“实现在Zynq设备上的”设计的IP的)软件驱动程序。
(1)Create Block Design
(2)Add IP(ZYNQ7 Processing System)
(3)双击IP,Presets—>选择板子型号
(4)MIO Configuration—> Application Processor Unit—->取消对Timer 0的选择(被选择的定时器都被取消)
(5)Interrupts—->Fabric Interrupts—->选择IRQ_F2P[15:0]—->OK
(6)单击Run Block Automation—>确认processing_system7_0被选择—->确认Apply Board Presets没被选择(如果选择了,它将重新应用我们第4步取消的定时器,造成Zynq设计块中有额外的端口)
(7)Add HLS IP
(8)单击Run Connection Automation(自动连线)
(9)选择S_AXI_HLS_MACC_PERIPH_BUS—>单击OK
(10)连接hls_macc_0的中断引脚interrupt(光标变成铅笔形状) 到PS7(processing_system7_0)上的IRQ_F2P[0:0]端口。
(11)选择Address Editor选项卡,确认hls_macc_0周围都有一个主地址范围。如果没有,点击Auto Assign Address。
(12)单击Validate Design图标,验证设计。
(13)在成功验证后,保存块设计。
在进行系统设计之前,你必须生成执行源(implementation sources)并创建一个HDL包装器作为合成和实现的顶层模块。
(1)返回到Project Manager窗口。
(2)右键Design Sources下的Zynq_Design(.bd对象)—>Generate Output Products
(3)Generate
(4)右键Design Sources下的Zynq_Design(.bd对象)—>Create HDL Wrapper—>OK
设计源文件树的顶层变为Zynq_Design_wrapper.v 文件。设计现在准备被综合,实现并且生成一个FPGA 编程比特流(FPGA progamming bitstream)。
(5)点击Generate Bitstream —> Yes
(6)Open Implemented Design —->OK
你现在准备导出设计到Xilinux SDK。在SDK ,你创建运行在ZC702板子(如果有)上的软件。在HLS 导出Vivado IP Catalog package的期间生成这个HLS 块的驱动。为了让PS7软件可以和这个块通信,在SDK中必须提供这个驱动
(1)Vivado File menu 选择Export—>Export Hardward
(2)保证Include Bitstream 这个选项被选—>点击OK。
(3)Vivado File menu 选择Launch SDK。
(4)OK
(5)SDK 选择File–>New—>Application Project—>name:Zynq_Design_Test—>Next—>Hello World—>Finish
(6)给ZC702上电,并且测试这个HelloWolld程序,确保板子所有的连接允许你往FPGA设备上下载比特流。
(7)单击Xilinx Tools—>Program FPGA(or toolrar icon)
(8)Setup a Terminal in the Tab at bottom of workspace。(底部工具栏挨着Console,叫Terminal 1)
点击Connect图标—->选择Connection Type —>Serial—>选择USB串口线连接的端口(windows上可以打开设备管理器查看)—>波特率改为115200—>OK(也可以在右键应用程序项目Zynq_Design_Test—>Run as—>Run Configurations设置)
(9)在浏览窗格,右键应用程序项目Zynq_Design_Test—>Run as—>Launch on Hardware—>切换到Terminal标签—>确认Hello World接收到了。
这个完全修改好的源文件在教程文件的arm_code目录中。(将HelloWorld.c改为下面)
#include
#include "platform.h"
// Add BSP header files
#include // Standard C functions, e.g. exit()
#include // Provides a Boolean data type for ANSI/ISO-C
#include "xparameters.h" // Parameter definitions for processor periperals
#include "xscugic.h" // Processor interrupt controller device driver
#include "XHls_macc.h" // Device driver for HLS HW block
// HLS macc HW instance
XHls_macc HlsMacc;
//Interrupt Controller Instance
XScuGic ScuGic;
// Global variable definitions - used by ISR
volatile static int RunHlsMacc = 0;
volatile static int ResultAvailHlsMacc = 0;
// Setup and helper functions
int setup_interrupt();
int hls_macc_init(XHls_macc *hls_maccPtr);
void hls_macc_start(void *InstancePtr);
// The ISR prototype
void hls_macc_isr(void *InstancePtr);
// Software model of HLS hardware
void sw_macc(int a, int b, int *accum, bool accum_clr);
int main()
{
print("Program to test communication with HLS MACC block in PL\n\r");
int a = 2, b = 21;
int res_hw;
int res_sw;
int i;
int status;
//Setup the matrix mult
status = hls_macc_init(&HlsMacc);
if(status != XST_SUCCESS){
print("HLS peripheral setup failed\n\r");
exit(-1);
}
//Setup the interrupt
status = setup_interrupt();
if(status != XST_SUCCESS){
print("Interrupt setup failed\n\r");
exit(-1);
}
//set the input parameters of the HLS block
XHls_macc_SetA(&HlsMacc, a);
XHls_macc_SetB(&HlsMacc, b);
XHls_macc_SetAccum_clr(&HlsMacc, 1);
if (XHls_macc_IsReady(&HlsMacc))
print("HLS peripheral is ready. Starting... ");
else {
print("!!! HLS peripheral is not ready! Exiting...\n\r");
exit(-1);
}
if (0) { // use interrupt
hls_macc_start(&HlsMacc);
while(!ResultAvailHlsMacc)
; // spin
res_hw = XHls_macc_GetAccum(&HlsMacc);
print("Interrupt received from HLS HW.\n\r");
} else { // Simple non-interrupt driven test
XHls_macc_Start(&HlsMacc);
do {
res_hw = XHls_macc_GetAccum(&HlsMacc);
} while (!XHls_macc_IsReady(&HlsMacc));
print("Detected HLS peripheral complete. Result received.\n\r");
}
//call the software version of the function
sw_macc(a, b, &res_sw, false);
printf("Result from HW: %d; Result from SW: %d\n\r", res_hw, res_sw);
if (res_hw == res_sw) {
print("*** Results match ***\n\r");
status = 0;
}
else {
print("!!! MISMATCH !!!\n\r");
status = -1;
}
cleanup_platform();
return status;
}
void sw_macc(int a, int b, int *accum, bool accum_clr)
{
static int accum_reg = 0;
if (accum_clr)
accum_reg = 0;
accum_reg += a * b;
*accum = accum_reg;
}
int hls_macc_init(XHls_macc *hls_maccPtr)
{
XHls_macc_Config *cfgPtr;
int status;
cfgPtr = XHls_macc_LookupConfig(XPAR_XHLS_MACC_0_DEVICE_ID);
if (!cfgPtr) {
print("ERROR: Lookup of acclerator configuration failed.\n\r");
return XST_FAILURE;
}
status = XHls_macc_CfgInitialize(hls_maccPtr, cfgPtr);
if (status != XST_SUCCESS) {
print("ERROR: Could not initialize accelerator.\n\r");
return XST_FAILURE;
}
return status;
}
void hls_macc_start(void *InstancePtr){
XHls_macc *pAccelerator = (XHls_macc *)InstancePtr;
XHls_macc_InterruptEnable(pAccelerator,1);
XHls_macc_InterruptGlobalEnable(pAccelerator);
XHls_macc_Start(pAccelerator);
}
void hls_macc_isr(void *InstancePtr){
XHls_macc *pAccelerator = (XHls_macc *)InstancePtr;
//Disable the global interrupt
XHls_macc_InterruptGlobalDisable(pAccelerator);
//Disable the local interrupt
XHls_macc_InterruptDisable(pAccelerator,0xffffffff);
// clear the local interrupt
XHls_macc_InterruptClear(pAccelerator,1);
ResultAvailHlsMacc = 1;
// restart the core if it should run again
if(RunHlsMacc){
hls_macc_start(pAccelerator);
}
}
int setup_interrupt()
{
//This functions sets up the interrupt on the ARM
int result;
XScuGic_Config *pCfg = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
if (pCfg == NULL){
print("Interrupt Configuration Lookup Failed\n\r");
return XST_FAILURE;
}
result = XScuGic_CfgInitialize(&ScuGic,pCfg,pCfg->CpuBaseAddress);
if(result != XST_SUCCESS){
return result;
}
// self test
result = XScuGic_SelfTest(&ScuGic);
if(result != XST_SUCCESS){
return result;
}
// Initialize the exception handler
Xil_ExceptionInit();
// Register the exception handler
//print("Register the exception handler\n\r");
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
//Enable the exception handler
Xil_ExceptionEnable();
// Connect the Adder ISR to the exception table
//print("Connect the Adder ISR to the Exception handler table\n\r");
result = XScuGic_Connect(&ScuGic,XPAR_FABRIC_HLS_MACC_0_INTERRUPT_INTR,(Xil_InterruptHandler)hls_macc_isr,&HlsMacc);
if(result != XST_SUCCESS){
return result;
}
//print("Enable the Adder ISR\n\r");
XScuGic_Enable(&ScuGic,XPAR_FABRIC_HLS_MACC_0_INTERRUPT_INTR);
return XST_SUCCESS;
}
该实验演示了一种常见的高性能连接方案,用于连接(以流的方式消耗来源于CPU内存数据或者产生以CPU内存为目的地的数据的)硬件加速器模块。
本教程使用和“Using HLS IP in IP Intergrator”Lab1中相同的HLS和XFFT IP模块。在这个实验中,这些模块通过AXI DMA IP Core 连接到Zynq7 Processing System上的HP0 Slave AXI4 port。
硬件加速器模块是自由运行的,不需要驱动程序;只要数据被推进CPU或者从CPU被推出(通常简单的称为处理系统或者PS)。
这个实验强调软件需要避免高速缓存一致性问题。(avoid cache coherency issues)