Zing AXI總線Chipscope參考設計

URL: http://xilinx.eetrend.com/article/4315?quicktabs_1=0

按鍵點燈設計 (使用14.3版本軟件)

本參考設計基於Zing開發板。主要是熟悉ZYNQ器件開發及調試的基本步驟。主要包括,UART測試、採用PL端邏輯設計PS外設、AXI總線Chipscope調試、定時器中斷設計、按鍵及點燈的設計。

一、建立工程:
1、 打開PlanAhead開始設計。

2、 點擊Create New Project建立新的工程-> Next-> 填好項目名稱和文件路徑 Next -> RTL Project -> Next -> Next -> Next 直至界面:

3、 如圖,選擇Xilinx ZC702開發板 Next –> Finish

二、添加ARM處理器
1、點擊Add sources ->選擇Add or Create Embedded Sources -> Next ->Create Sub-Design -> 填入處理器名稱 -> finish

2、彈出對話框,是否使用Base System Builder,選擇Yes

3、默認採用AXI總線架構,點OK

4、默認選擇Xilinx ZC702開發板,點Next

5、Remove GPIO_SW and LEDs_4Bits,點Finish

此時已添加和PS部分,並參照Xilinx ZC702開發板設計配置好外設、時鐘、DDR內存等。

三、添加PL部分的外設,並連接到PS上
1、添加一個外部按鍵。點擊IP Catalog-> 展開General Purpose IO菜單 ->雙擊AXI General Purpose IO

2、點擊Yes -> 把Channel 1中的GPIO Data Channel Width改爲1,點擊OK,用PL部分邏輯實現一個板上按鍵。

4、 彈出對話框,是否把添加的IP連接到處理器總線上。默認選擇,點OK。

5、此時在ZYNQ的菜單下可以看到,PS部分的GP0口被使能了。剛加入的GPIO IP連接到了處理器上。點擊Address菜單可以看到給其分配了0x41200000地址。

6、同樣的方法加入定時器IP。雙擊AXI Timer/Counter -> Yes -> OK -> OK

7、切換到Ports菜單,展開processing_system7_0,點擊L to H: No Connection

8、把定時器的中斷信號添加到右邊,可以看到系統自動給其分配了中斷號91,點擊OK

四、使能PS部分的外設GPIO,並使用EMIO
1、切換到ZYNQ菜單,點擊I/O Peripherals

2、把GPIO改爲用EMIO,把位寬改爲1。用EMIO實現一個板上按鍵。

3、切換到Ports菜單,把GPIO的管腳連接到外部。

五、添加Chipscope模塊用來觀察AXI總線上的信號。
1、在IP Catalog中找到Chipscope AXI Monitor IP,雙擊添加,點Yes,點OK。

2、雙擊添加Chipscope Intergrated Controller,點Yes,點OK。

3、切換到Bus Interfaces菜單。把MON_AXI連接到GPIO的S_AXI總線上,用於觀測PL部分GPIO的總線信號。

4、切換到Ports菜單,把Chipscope_icon_0中的control0信號連接到Chipscope_axi_monitor_0的CHIPSCOPE_ICON_CONTROL信號上。

5、 點擊DRC,檢查設計中是否存在錯誤。至此EDK部分的完成。關閉EDK工具,轉回到PlanAhead界面。

六、添加頂層文件,管腳約束,導出硬件至SDK中。
1、在Design Sources中找到處理器,點右鍵選擇Create Top HDL自動生成頂層文件。

2、點擊Add Sources,添加約束文件,Next-> Create File ->輸入約束名稱-> OK -> Finish

3、在Constraints中找到剛添加的約束文件,雙擊打開。按照Zing開發板的連接分配好管腳。PL部分的GPIO按鍵指定到PU1,PS部分GPIO按鍵指定到PU2。

4、點擊Generate Bitstream生成PL部分的Bit文件。

5、待編譯完成後,點擊File ->Export -> Export Bitstream File,輸入文件名,點擊Save。導出PL部分的bit文件便於之後的設計。

6、點擊File ->Export -> Export Hardware For SDK,勾選Launch SDK,點OK。

七、在SDK中設計軟件程序。
1、進入到SDK界面,點擊File -> New -> Application Project,輸入軟件工程名,選擇Hello World,點Finish。建立了一個簡單的在串口上打印Hello World的工程,並自動編譯驅動庫及程序。

2、展開Led目錄下src菜單,雙擊Hellowrold.c打開文件。

3、用以下程序替換Helloword.c中的內容。點擊保存,程序自動編譯。
/*
* Copyright (c) 2009 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/*
* helloworld.c: simple test application
*/
#include 
#include "platform.h"
#include "xil_types.h"
#include "xgpio.h"
#include "xtmrctr.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xil_io.h"
#include "xil_exception.h"
#include "xscugic.h"
static XGpioPs psGpioInstancePtr;
extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES];
static int iPinNumber = 10;
XScuGic InterruptController; /* Instance of the Interrupt Controller */
static XScuGic_Config *GicConfig;/* The configuration parameters of the
controller */
static int InterruptFlag;
void print(char *str);
extern char inbyte(void);
void Timer_InterruptHandler(void *data, u8 TmrCtrNumber)
{
print("\r\n");
print("\r\n");
print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n");
print(" Inside Timer ISR \n \r ");
XTmrCtr_Stop(data,TmrCtrNumber);
// PS GPIO Writting
print("LED 'DS23' Turned ON \r\n");
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,1);
XTmrCtr_Reset(data,TmrCtrNumber);
print(" Timer ISR Exit\n \n \r");
print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n");
print("\r\n");
print("\r\n");
InterruptFlag = 1;
}
int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr)
{
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
XScuGicInstancePtr);
/*
* Enable interrupts in the ARM
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
int ScuGicInterrupt_Init(u16 DeviceId,XTmrCtr *TimerInstancePtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
* */
GicConfig = XScuGic_LookupConfig(DeviceId);
if (NULL == GicConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&InterruptController, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the Interrupt System
* */
Status = SetUpInterruptSystem(&InterruptController);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an
* interrupt for the device occurs, the device driver handler performs
* the specific interrupt processing for the device
*/
Status = XScuGic_Connect(&InterruptController,
XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR,
(Xil_ExceptionHandler)XTmrCtr_InterruptHandler,
(void *)TimerInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the device and then cause (simulate) an
* interrupt so the handlers will be called
*/
XScuGic_Enable(&InterruptController, XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR);
return XST_SUCCESS;
}
int main()
{
static XGpio GPIOInstance_Ptr;
XGpioPs_Config*GpioConfigPtr;
XTmrCtr TimerInstancePtr;
int xStatus;
u32 Readstatus=0,OldReadStatus=0;
//u32 EffectiveAdress = 0xE000A000;
int iPinNumberEMIO = 54;
u32 uPinDirectionEMIO = 0x0;
// Input Pin
// Pin direction
u32 uPinDirection = 0x1;
int exit_flag,choice,internal_choice;
init_platform();
/* data = *(u32 *)(0x42800004);
print("OK \n");
data = *(u32 *)(0x41200004);
print("OK-1 \n");
*/
print("##### Application Starts #####\n\r");
print("\r\n");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-1 :AXI GPIO Initialization
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xStatus = XGpio_Initialize(&GPIOInstance_Ptr,XPAR_AXI_GPIO_0_DEVICE_ID);
if(XST_SUCCESS != xStatus)
print("GPIO INIT FAILED\n\r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-2 :AXI GPIO Set the Direction
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XGpio_SetDataDirection(&GPIOInstance_Ptr, 1,1);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-3 :AXI Timer Initialization
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xStatus = XTmrCtr_Initialize(&TimerInstancePtr,XPAR_AXI_TIMER_0_DEVICE_ID);
if(XST_SUCCESS != xStatus)
print("TIMER INIT FAILED \n\r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-4 :Set Timer Handler
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XTmrCtr_SetHandler(&TimerInstancePtr,
Timer_InterruptHandler,
&TimerInstancePtr);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-5 :Setting timer Reset Value
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XTmrCtr_SetResetValue(&TimerInstancePtr,
0, //Change with generic value
0xf0000000);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-6 :Setting timer Option (Interrupt Mode And Auto Reload )
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XTmrCtr_SetOptions(&TimerInstancePtr,
XPAR_AXI_TIMER_0_DEVICE_ID,
(XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION ));
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-7 :PS GPIO Intialization
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
if(GpioConfigPtr == NULL)
return XST_FAILURE;
xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,
GpioConfigPtr,
GpioConfigPtr->BaseAddr);
if(XST_SUCCESS != xStatus)
print(" PS GPIO INIT FAILED \n\r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-8 :PS GPIO pin setting to Output
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection);
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-9 :EMIO PIN Setting to Input port
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XGpioPs_SetDirectionPin(&psGpioInstancePtr,
iPinNumberEMIO,uPinDirectionEMIO);
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumberEMIO,0);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-10 : SCUGIC interrupt controller Intialization
//Registration of the Timer ISR
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xStatus=
ScuGicInterrupt_Init(XPAR_PS7_SCUGIC_0_DEVICE_ID,&TimerInstancePtr);
if(XST_SUCCESS != xStatus)
print(" :( SCUGIC INIT FAILED \n\r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-11 :User selection procedure to select and execute tests
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
exit_flag = 0;
while(exit_flag != 1)
{
print(" SELECT the Operation from the Below Menu \r\n");
print("###################### Menu Starts ########################\r\n");
print("Press '1' to use NORMAL GPIO as an input (SW5 switch)\r\n");
print("Press '2' to use EMIO as an input (SW7 switch)\r\n");
print("Press any other key to Exit\r\n");
print(" ##################### Menu Ends #########################\r\n");
choice = inbyte();
printf("Selection : %c \r\n",choice);
internal_choice = 1;
switch(choice)
{
//~~~~~~~~~~~~~~~~~~~~~~~
// Use case for AXI GPIO
//~~~~~~~~~~~~~~~~~~~~~~~~
case '1':
exit_flag = 0;
print("Press Switch 'SW5' push button on board \r\n");
print(" \r\n");
while(internal_choice != '0')
{
Readstatus = XGpio_DiscreteRead(&GPIOInstance_Ptr, 1);
if(1== Readstatus && 0 == OldReadStatus )
{
print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
print("SW5 PUSH Button pressed \n\r");
print("LED 'DS23' Turned OFF \r\n");
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,0);
//Start Timer
XTmrCtr_Start(&TimerInstancePtr,0);
print("timer start \n\r");
//Wait For interrupt;
print("Wait for the Timer interrupt to tigger \r\n");
print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
print(" \r\n");
while(InterruptFlag != 1);
InterruptFlag = 0;
print(" ###########################################\r\n ");
print("Press '0' to go to Main Menu \n\r ");
print("Press any other key to remain in AXI GPIO Test \n\r ");
print(" ###########################################\r\n ");
internal_choice = inbyte();
printf("Select = %c \r\n",internal_choice);
if(internal_choice != '0')
{
print("Press Switch 'SW5' push button on board \r\n");
}
}
OldReadStatus = Readstatus;
}
print(" \r\n");
print(" \r\n");
break;
case '2' :
//~~~~~~~~~~~~~~~~~~~~~~~
//Usecase for PS GPIO
//~~~~~~~~~~~~~~~~~~~~~~~~
exit_flag = 0;
print("Press Switch 'SW7' push button on board \r\n");
print(" \r\n");
while(internal_choice != '0')
{
Readstatus = XGpioPs_ReadPin(&psGpioInstancePtr,
iPinNumberEMIO);
if(1== Readstatus && 0 == OldReadStatus )
{
print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
print("SW7 PUSH Button pressed \n\r");
print("LED 'DS23' Turned OFF \r\n");
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,0);
//Start Timer
XTmrCtr_Start(&TimerInstancePtr,0);
print("timer start \n\r");
//Wait For interrupt;
print("Wait for the Timer interrupt to tigger \r\n");
print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
print(" \r\n");
while(InterruptFlag != 1);
InterruptFlag = 0;
print(" ###########################################\r\n ");
print("Press '0' to go to Main Menu \n\r ");
print("Press any other key to remain in EMIO Test \n\r ");
print(" ###########################################\r\n ");
internal_choice = inbyte();
printf("Select = %c \r\n",internal_choice);
if(internal_choice != '0')
{
print("Press Switch 'SW7' push button on board \r\n");
}
}
OldReadStatus = Readstatus;
}
print(" \r\n");
print(" \r\n");
break;
default :
exit_flag = 1;
break;
}
}
print("\r\n");
print("***********\r\n");
print("BYE \r\n");
print("***********\r\n");
cleanup_platform();
return 0;
}

八、採用JTAG模式調試程序。
1、按照下圖,接好電源、JTAG電纜、UART口。模式管腳JS3、JS4、JS5、JS6、JS7的連接見圖中所示,跳線均接2、3針。

2、點擊Xilinx Tools -> Program FPGA,指定之前生成的PL部分下載文件,點擊Program。

3、切換到Terminal 1串口調試工具,點擊Settings,設置好串口,點擊OK,串口自動連接。

4、在Project Explorer菜單下,選擇軟件工程,右鍵Run As -> Run configurations,點擊Xilinx C/C++ ELF,按照圖中選擇需要Debug的工程,點擊Run。

6、 在Terminal 1中出現如下打印信息:
##### Application Starts #####
SELECT the Operation from the Below Menu
###################### Menu Starts ########################
Press '1' to use NORMAL GPIO as an input (PU1 switch)
Press '2' to use EMIO as an input (PU2 switch)
Press any other key to Exit
##################### Menu Ends #########################

在鍵盤上輸入1或2,此時開始做按鍵掃描。按照屏幕提示按下按鍵,DDP11燈熄滅,此時計數器開始計數。當計數器計滿後產生中斷,DDP11燈重新點亮。

九、在TF卡中啓動程序,並用ChipScope觀察AXI4總線信號。

1、切換至Console菜單,點擊Terminate中斷JTAG調試。

2、點擊File –> New -> Application Project,輸入工程名,點Next。選定ZYNQ FSBL,點Finish。此時自動生成ZYNQ的初始化文件。

3、點擊Xilinx Tools -> Create Boot Image,點擊上面的Browse指定剛纔編譯完成FSBL ELF文件,點擊Add加入PL部分的配置bit文件,點擊Add加入軟件編譯後的文件ELF。點擊下面的Browse,指定文件輸出的路徑,點擊Create Image。生成TF卡啓動文件。

4、在生成文件的路徑中找到生成的文件。把其中的BIN文件的文件名改爲BOOT。從PC中拷貝至TF卡中。

5、如圖所示連在開發板中,接好電源、UART線。模式管腳JS3、JS4、JS5、JS6、JS7,除JS5、JS6接1、2針外,其他接2、3針。在SDk的Terminal 1中連接好串口。之後打開電源。

6、在調試終端中出現和之前相同的打印信息。證明ZYNQ正常啓動。
7、確認JTAG電纜已接好。在PlanAhead中點擊Launch Chipscope Analyzer運行Chipscope工具。

8、 點擊左上角的Open Cable/Search JTAG Chain,在JTAG鏈上找到兩個Device。點OK。

9、 點擊File -> Import -> Select New File,從下圖所示的路徑中找到CDC文件並加入。點OK。

10、 在Trigger Setup菜單中,設置觸發條件,把M1:MON_AXI_ARADDRCONTROL下的MON_AXI_ARVALID改爲1。Position改爲512。Trigger Condition Equation改爲M1。

11、 點擊Apply Settings And Arm Trigger,開始採樣。可以看到由於此時AXI讀總線上沒有信號,故無法觸發採樣。

12、 切換至SDK的Terminal 1中,在鍵盤上輸入1。此時ARM開始讀GPIO的按鍵,Chipscope中採樣到波形。可以根據此波形熟悉AXI總線協議。


發佈了11 篇原創文章 · 獲贊 37 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章