معالجة الإشارات باستخدام السبورة السوداء الرقمية الحقيقية
الأشياء المستخدمة في هذا المشروع
مكونات الأجهزة
Xilinx's portfolio of FPGAs
منصة البرامج الموحدة Xilinx Vitis
قصة
مقدمة
سيستخدم هذا المشروع السبورة الرقمية الحقيقية لتنفيذ سلسلة معالجة إشارة بسيطة باستخدام XDAC و DMA لنقل الإشارات إلى الذاكرة.
إذا لم تكن مألوفًا ، فإن لوحة Real Digital Black هي عبارة عن جهاز Zynq 7007S أحادي النواة وهو مثالي لتعلم تطوير Zynq.
لبدء استخدام السبورة السوداء الرقمية الحقيقية ، فإن أول شيء يتعين علينا القيام به هو تنزيل الأصول من GitHub الرقمي الحقيقي.
سيوفر لنا هذا البرامج النصية للتكوين لنظام المعالجة وتكوين تسجيل الوقت و DDR الخاص به.
في هذا المثال ، سنقوم بالاتصال بقنوات XADC المتاحة عبر قنوات XADC المساعدة على واجهة Pmod.
نحن نقوم بذلك لأن واجهة Vp / Vn المخصصة على Blackboard متصلة بمقياس الجهد. هذا بالطبع رائع للتدريس ولكن في هذا المشروع نريد التقاط إشارة حقيقية
إنشاء مشروع Vivado
على عكس العديد من المشاريع السابقة ، لن نبدأ المشروع مستهدفًا لوحة بل مكونًا. قم بإنشاء مشروع جديد باستخدام xc7007sclg400-1
بمجرد إنشاء المشروع ، فإن الخطوة التالية هي إنشاء مخطط كتلة IP Integrator. أضف نظام معالجة Zynq.
لتكوين Zynq PS كما في Blackboard ، نحتاج إلى تطبيق البرنامج النصي الذي قمنا بتنزيله مسبقًا. انقر نقرًا مزدوجًا فوق كتلة Zynq لإعادة التخصيص وتحديد تطبيق التكوين.
في مربع الحوار الذي يظهر ، حدد ملف tcl للإعدادات المسبقة لـ Blackboard وانقر فوق "موافق"
سيؤدي هذا إلى تكوين Zynq PS بشكل صحيح لتكوين Blackboard
بمجرد إغلاق نافذة إعادة التخصيص ، يمكننا إعادة تشغيل أتمتة الكتلة
عند الانتهاء من أتمتة الكتلة ، يجب تكوين نظام معالجة Zynq للاستخدام في تطبيقنا.
لبدء القدرة على تلقي إشارة ، نحتاج إلى إضافة XADC إلى مخطط كتلة IP Integrator
بمجرد إضافة XADC ، فإن المرحلة التالية هي تكوين XADC للاستخدام.
نظرًا لأننا نريد دفق البيانات من XADC واستخدام DMA ، نحتاج إلى تمكين واجهة AXIS Stream.
لقد عطلت أيضًا جميع الإنذار
أخيرًا ، قمت بتمكين قنوات الإدخال المساعدة المتصلة بـ Pmod
بمجرد توصيل XADC ، قم بتشغيل أتمتة الاتصال لتوصيل XADC بـ Zynq PS باستخدام شبكة AXI Lite.
يجب أن يبدو مخطط الكتلة المكتمل كما يلي.
انقر بزر الماوس الأيمن على قناة Vaux0 وحدد make خارجي
الخطوة التالية هي توصيل خرج AXIS من XADC بإدخال S_AXI في Zynq PS Block.
سيمكن هذا الاتصال Vivado من إنشاء نظام DMA بين XADC ونظام المعالجة.
سيكون المخطط المكتمل كما هو موضح أدناه
قم بتشغيل أتمتة الاتصال وسيتم إضافة اتصال AXI Lite الموجود على DAM إلى شبكة AXI Lite.
سيكون المخطط المكتمل على النحو التالي.
ومع ذلك ، لا يحتوي خرج XADC AXI Stream على جميع الإشارات اللازمة لدعم DMA. لا يتم توفير إشارة TLast في خرج AXIS Stream
سيؤدي ذلك إلى منع DMA من العمل بشكل صحيح ، لذلك نحتاج إلى تحديد إخراج AXIS بين XADC ومدخل DMA
احذف الإشارة
أضف محول مجموعة فرعية AXIبمجرد اكتمال ذلك ، نكون قادرين على التحقق من صحة تصميم الكتلة ، ويجب ألا تكون هناك أخطاء أو تحذيرات خطيرة.
تتمثل المرحلة التالية في إنشاء غلاف HDL للمشروع وإنشاء تدفق البتات. وهذا قد يستغرق بضع دقائق.
بمجرد اكتمال التصميم ، قم بتصدير XSA بما في ذلك تدفق البتات.
تطوير Vitis SW
من Vivado افتح Vitis وحدد مساحة عمل لتطوير البرامج.
قم بإنشاء مشروع تطبيق جديد وحدد XSA الذي تم تصديره للتو من Vivado لتحديد النظام الأساسي.
قم بإنشاء مشروع تطبيق جديد يستهدف معالج A9 الفردي
قم بإنشاء المجال باستخدام نظام تشغيل مستقل
حدد قالب تطبيق hello world.
بمجرد إنشاء المشروع ، نحتاج إلى تحديث برنامج الدفع لتسوية الفواتير (BSP) لاستخدام PS UART1 للاتصالات التسلسلية.
سنستخدم أيضًا نظام البرنامج ،
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "stdlib.h"
#include "xsysmon.h"
#include "xaxidma.h"
#include "ff.h"
#define SYSMON_DEVICE_ID XPAR_SYSMON_0_DEVICE_ID
#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID
#define DDR_BASE_ADDR XPAR_AXIDMA_0_BASEADDR
#define RX_BUFFER_BASE (0x00100000)
#define MAX_PKT_LEN 512 //bytes
XSysMon SysMonInst;
int main()
{
int Status;
u8 xfer_size;
u16 TempData;
int Temp;
int reset_done;
u16 *RxBufferPtr;
u32 value;
u32 addr;
XSysMon_Config *SYSConfigPtr ;
XSysMon* SysMonInstPtr = &SysMonInst;
XAxiDma_Config *CfgPtr;
XAxiDma AxiDma;
UINT NumBytesWritten;
int i,len,position,n;
static FIL fil; /* File object */
static FATFS fatfs; // Pointer to the filesystem object
static char FileName[50] = "XADC.CSV";
static char *SD_File;
char buffer[100] ;
UINT *ByteRead;
FRESULT Res;
TCHAR *Path = "0:/";
u32 BuffCnt;
Res = f_mount(&fatfs, Path, 0); //0 is the mounting option
SD_File = (char *)FileName;
init_platform();
print("Hello World\n\r");
SYSConfigPtr = XSysMon_LookupConfig(SYSMON_DEVICE_ID);
if (SYSConfigPtr == NULL) {
return XST_FAILURE;
}
CfgPtr = XAxiDma_LookupConfig(DMA_DEV_ID);
if (!CfgPtr) {
printf("No config found for %d\r\n", DMA_DEV_ID);
return XST_FAILURE;
}
Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr);
if (Status != XST_SUCCESS) {
printf("Initialization DMA failed %d\r\n", Status);
return XST_FAILURE;
}
XSysMon_CfgInitialize(SysMonInstPtr, SYSConfigPtr, SYSConfigPtr->BaseAddress);
XSysMon_SetSequencerMode(SysMonInstPtr, XSM_SEQ_MODE_SAFE);
XSysMon_SetAlarmEnables(SysMonInstPtr, 0x0);
XSysMon_SetSeqChEnables(SysMonInstPtr, XSM_SEQ_CH_AUX00);
XSysMon_SetAdcClkDivisor(SysMonInstPtr, 32);
XSysMon_SetSequencerMode(SysMonInstPtr, XSM_SEQ_MODE_CONTINPASS);
//TempData = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_TEMP);
//Temp = XSysMon_RawToTemperature(TempData);
RxBufferPtr = (u16 *)RX_BUFFER_BASE;
addr = (u32)RX_BUFFER_BASE;
XAxiDma_Reset(&AxiDma);
reset_done = XAxiDma_ResetIsDone(&AxiDma);
while(reset_done != 1){
}
XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA);
XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE);
while(1){
Status = XAxiDma_SimpleTransfer(&AxiDma,(u32) RX_BUFFER_BASE,MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
if (Status != XST_SUCCESS) {
printf("XFER failed %d\r\n", Status);
return XST_FAILURE;
}
while ((XAxiDma_Busy(&AxiDma,XAXIDMA_DEVICE_TO_DMA))){
/* Wait */
}
position = 0;
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, MAX_PKT_LEN);
Res = f_open(&fil, SD_File, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);
Res = f_lseek(&fil, 0);
for(i=0;i<MAX_PKT_LEN/2;i++){
n=sprintf(buffer, "%d,%04x\r\n",i,RxBufferPtr[i]);
Res = f_lseek(&fil, position); //find ext write position
Res = f_write(&fil, (const void*)buffer, MAX_PKT_LEN,&NumBytesWritten);
len = strlen(buffer);
position=position+len;
}
Res = f_close(&fil);
return 0;
//usleep(1000000);
}
cleanup_platform();
}