خواندن و نوشتن در حافظه DDR با HLS

برای طراحی یک مسیر دیتای پرسرعت در یک سیستم ممکن است نیاز به خواندن و نوشتن در حافظه DDR داشته باشید. آیا می‌توانیم این کار را با HLS‌ انجام دهیم.

مقدمه

به صورت پیش فرض Vivado-HLS به عنوان ابزاری برای توسعه سیستم‌‌ها و الگوریتم‌های پردازشی در FPGA‌ شناخته می‌شود. ممکن است این سوال برای شما هم پیش آمده باشد که آیا می‌توان از HLS برای طراحی یک مسیر دیتای پرسرعت بین بخش‌های مختلف سیستم استفاده کرد. پاسخ به این سوال مثبت است. در این آموزش از پایگاه دانش هگزالینکس قصد داریم شما را با شیوه خواندن و نوشتن در حافظه خارجی DDR با HLS آشنا کنیم.

کار با حافظه های خارجی

ما علاوه بر توسعه الگوریتم‌های پردازشی می‌توانیم برای ساخت مسیرهای تبادل داده نیز از HLS استفاده کنیم. زمان‌هایی وجود دارد که در هنگام استفاده از HLS‌ ما نیاز داریم تا با حافظه‌های خارجی همچون حافظه‌های DDR ارتباط بر قرار کنیم و به تبادل اطلاعات بپردازیم. این کار ممکن است برای ذخیره دیتا، بازیابی دیتا و یا خواندن داده‌هایی که توسط ماژول یا فانکشن دیگر روی حافظه نوشته شده باشد، صورت بپذیرد.

در ابتدا ممکن است ایده تبادل اطلاعات با یک حافظه DDR و خواندن و نوشتن در حافظه خارجی با استفاده از HLS‌ کمی پیچیده به نظر برسد. اما هیچ چیز نمی‌تواند جذاب تر از حقیقتی باشد که در ادامه تصمیم دارم برای شما به اثبات برسانم.

برای این کار تصمیم دارم از بورد Arty که دارای یک تراشه FPGA از نوع Artix35T با 256MB حافظه DDR3L است، استفاده کنم. البته شما می‌توانید از هر بوردی که در اختیار دارید استفاده کنید. آموزشی که در ادامه خدمتتان ارائه می‌کنم یک HLS IP است که می‌تواند درون طراحی Vivado ما قرار بگیرد و با حافظه DDR به تبادل اطلاعات بپردازد. عملکرد این بلوک HLS بسیار ساده خواهد بود. من تنها یک الگوی مشخص از اعداد را در حافظه DDR می‌نویسم.

پروژه Vivado

برای انجام این پروژه خواندن و نوشتن در حافظه DDR، به یک طراحی در Vivado با مشخصات زیر نیاز داریم.

  • استفاده از Memory Interface Generator و پیکره بندی آن برای کار با DDR3L
  • استفاده از JTAG to AXI IP Core برای خطایابی و بازبینی دسترسی به DDR3L
  • استفاده از AXI Interconnect برای ایجاد امکان دسترسی همزمان بلوک طراحی شده در HLS و JTAG to AXI IP Core به MIG.
  • استفاده از VIO برای ارسال فرمان شروع به کار به بلوک HLS
  • استفاده از ILA برای بازبینی و دیباگ ماژول‌های داخلی طرح
  • بلوک تست ساخته شده در HLS

ایده اصلی پشت این پروژه به این صورت است که ابتدا بلوک HLS عملیات نوشتن در DDR را آغاز می‌کند و بعد ما با استفاده از JTAG to AXI IP Core شروع به خواندن از حافظه DDR می‌کنیم.

ماژول تست HLS

برای ساخت بلوک HLS قاعدتاً باید از ابزار Vivado HLS استفاده کنیم و یک پروژه جدید ایجاد کنیم. پس پروژه جدید را بر اساس تراشه Artix روی بورد Arty ایجاد می‌کنیم.

بلوک دیاگرام پروژه طراحی شده در Vivado IPI
بلوک دیاگرام نهایی پروژه طراحی شده در Vivado IPI

پیش از هر کاری بهتر است سورس فایلی که برای این پروژه استفاده می‌کنیم را با هم بررسی کنیم. وقتی با زبان C برنامه نویسی می‌کنیم برای کپی کردن دیتا از فانکشن memcopy استفاده می‌کنیم. با استفاده از این فانکشن ما می‌توانیم داده‌ها را از مبدا به مقصد کپی کنیم. وقتی در HLS‌ هستیم باز هم از این تابع استفاده می‌کنیم. رفتار این فانکشن همچنان به همان صورت قبل است با این تفاوت که در اینجا انتقال و جابجایی داده‌ها با استفاده از اینترفیس AXI4 Memory Mapped انجام می‌شود.

به طور کلی اینترفیس AXI4 برای استفاده از MIG و سایر اینترفیس‌های حافظه ایده‌ال است. از این رو کدهایی که ما در این پروژه برای ساخت یک بلوک تستی HLS‌ استفاده می‌کنیم، مثال بسیار ساده هستند.

// test.h

void memcpy_test( int *ddr);
// test.c

#include "test.h"
#include "string.h"

void memcpy_test(int *ddr)
{
	int i;
	int data[256];

#pragma HLS INTERFACE m_axi port=ddr depth=256 offset=direct
	for (i =0;i<256;i++){
		data[i] = i;
	}
	memcpy(ddr,data,256*sizeof(int));

کد testbench نوشته برای این کد نیز بسیار ساده مشابه کدهای زیر است.

// test_tb.c

#include <stdio.h>
#include "test.h"

int main()
{
	int ddr[256];
	memcpy_test(&ddr);
}

با نگاه دقیق‌تر به جزئیات کد، ملاحظه می‌کنید که فانکشن main درای یک اشاره‌گر از نوع int به سمت حافظه DDR‌ است، در واقع این همان اینترفیسی است که تصمیم داریم از آن برای نوشتن دیتا در حافظه DDR استفاده کنیم. در صورت نیاز، ما می‌توانیم از این اینترفیس برای خواندن از DDR نیز استفاده کنیم.

پیکره‌بندی اینترفیس

ما این اینترفیس را به صورت یک اینترفیس AXI Master تعریف می‌کنیم. برای این کار از پراگمای HLS Interface با پارامترهایی به صورت زیر استفاده می‌کنیم.

interface type = m_axi
port = ddr
depth = 256
offset = direct

به این ترتیب یک اینترفیس AXI Master به پورت ddr نسبت داده می‌شود. پارامتر عمق (depth) در این پراگما برای co-simulation، هنگامی که اشاره‌گرها به جای آرایه‌ها استفاده می‌شوند، بکار برده می‌شود. در واقع این پارامتر تعداد دفعات نوشتن و خواندن را تعیین می‌کند.

مقدار offset نیز به عنوان یک پارامتر دیگر برای کنترل فضای آدرس استفاده می‌شود. ما از آن برای آدرس دهی و دسترسی به اینترفیس AXI استفاده می‌کنیم. در اینجا سه انتخاب داریم که هر کدام متد خاصی را فعال می‌کنند.

  • گزینه اول Off : گزینه Off گزینه پیش فرض است، با انتخاب این گزینه آدرس دهی از آدرس 0x00000000 آغاز می‌شود.
  • گزینه دوم Direct : با انتخاب این گزینه یک پورت روی ماژول HLS ایجاد می‌شود، به این ترتیب، تعریف و کنترل مقدار offset از درون Block Design در زمان فراخوانی HLS IP در Vivado امکان پذیر می‌شود.
  • گزینه Slave : با انتخاب این گزینه یک اینترفیس AXI-4 Lite ایجاد می‌شود و با استفاده از یک رجیستر، مقدار offset تعیین می‌شود.

برای این مثال، ما از گزینه direct استفاده می‌کنیم و کار را ساده می کنیم. با این کار طرح ما بر پایه منابع منطقی و به صورت ثابت پیاده سازی می‌شود. در حالی که اگر گزینه AXI4-Lite انتخاب می‌کردیم طراحی ما بیشتر شبیه یک سیستم نهفته با کنترل پذیری بالاتر می‌شد.

شبیه سازی ماژول HLS

اما هنگامی که سخن از ارزیابی و صحه گذاری طرح به میان می‌آید، طراحی و استفاده از test bench مناسب اجتناب ناپذیر است. با استفاده از test bench ما می‌توانیم c-based simulation و صد البته C/RTL co-simulation انجام دهیم. در این پروژه test bench طراحی شده بسیار ابتدایی است. در واقع test bench من دارای یک آرایه ۲۵۶ بیتی است که به سمت فانکشن یا ماژول HLS‌ ارسال می‌شود و آن را پر می‌کند.

شبیه سازی

در Vivado-HLS تست و صحه گذاری کدهای C با استفاده از test bench نوشته شده به زبان C انجام می‌شود. این شبیه سازی تحت عنوان c-based simulation یا به بیان فارسی شبیه سازی C نام گذاری شده است.

عبارت C/RTL co-simulation معرف شبیه سازی توامان سخت افزاری و نرم افزاری است. در واقع برنامه test bench نوشته شده به زبان C به صورت اتوماتیک به RTL test bench تبدیل می‌شود و امکان فراخوانی و اجرای آن در Vivado امکان پذیر می‌گردد. این شبیه سازی که روی طرح RTL خروجی اجرا می‌شود، تحت عنوان co-simulation نام گذاری شده است. در طول این آموزش و به طور کلی کلیه آموزش‌های HLS ما به اختصار عبارت شبیه سازی RTL را برای مخاطب قرار دادن این مفهوم استفاده می‌کنیم. تست و صحه گذاری کدهای C نیز با عنوان شبیه سازی C مخاطب قرار داده می‌شود.

در واقع شبیه سازی در محیط C امکان بررسی صحت عملکرد کد قبل از سنتز HLS و شبیه سازی RTL را فراهم می‌آورد. مشابه هر فرایند خطایابی و دیباگ دیگری در زبان C ، ما باید از break point‌ برای متوقف کردن اجرا و بررسی محتوای متغیرها استفاده کنیم.

اجرای شبیه سازی توامان سخت افزاری و نرم افزاری
اجرای شبیه سازی توامان سخت افزاری و نرم افزاری
C-RTL co-simulation

با اتمام کار طراحی و کدنویسی، نوبت به سنتز و شبیه سازی RTL می‌رسد، پیش از اجرای شبیه سازی RTL از فعال بودن تیک گزینه dump trace port اطمینان حاصل کنید. با این کار شما یک کپی از سیگنال‌ها و پورت‌های ماژول سنتز شده در محیط شبیه ساز Vivado ایجاد می‌کنید. به این ترتیب ما می‌توانیم شکل موج روی ورودی‌ها و خروجی‌های ماژول HLS پیاده‌سازی شده را مشاهده کنیم.

نتایج شبیه سازی RTL
مشاهده نتایج شبیه سازی RTL در Vivado-Simulator

در زمان شبیه سازی یک testbench دقیقاً مشابه کد C اما به صورت RTL تولید می‌شود. سپس با اعمال همان ورودی‌های درون کد C به مدار RTL موفقیت یا عدم موفقیت شبیه سازی با یک پیغام در کنسول خروجی Vivado HLS گزارش می‌شود.

ساخت HLS IP

در صورت رضایت نتایج شبیه سازی RTL گام آخر ساخت یک IP Core از ماژول HLS طراحی شده و اضافه کردن آن به لیست مخازن IP ها در Vivado است. به این ترتیب امکان فراخوانی و استفاده از IP‌ در محیط Vivado-IPI فراهم می‌آید.

بعد از اضافه کردن ماژول HLS‌ به طراحی صورت گرفته در Vivado ، زمان آن فرا می‌رسد که آدرس‌های ماژول HLS‌ را تعیین کنیم. قرار است IP Core جدیدمان از این آدرس‌ها برای تبادل اطلاعات استفاده ‌کند. برای این کار لازم است از یک constant block استفاده کنیم.  

تعیین آدرس‌های ماژول HLS‌ با استفاده از بلوک constant
تعیین آدرس‌های ماژول HLS‌ با استفاده از بلوک constant

با پایان این بخش باید طرح را سنتز و پیاده سازی کنیم و در نهایت بیت ‌فایل خروجی را تولید کنیم. بعد از پایان تمامی این مراحل، بیت فایل تولید شده را با استفاده از Hardware Manger روی تراشه برنامه‌ریزی می‌کنیم.

تست روی سخت افزار

نوبتی هم که باشد نوبت VIO است. به لطف VIO ما می‌توانیم سیگنال ap_start در ورودی ماژول HLS را کنترل کنیم. این بدان معناست که قبل از شروع کار ما می‌توانیم با استفاده JTAG to AXIS درون حاقظه DDR را بخوانیم. به این ترتیب می‌توانیم مطمئن شویم که مقادیر تستی ما از قبل روی حافظه DDR نوشته نشده‌اند.

خواندن آدرس‌ 0X80000010 از حافظه DDR

بعد از اینکه از مقدار دهی اولیه و البته تصادفی حافظه مطمئن شدیم، می‌توانیم فرمان آغاز بکار HLS IP را با استفاده از VIO صادر کنیم و بررسی کنیم که آیا عملیات نوشتن در حافظه DDR به درستی صورت پذیرفته است یا خیر؟

برای بازبینی و بررسی موفقیت آمیز بودن عملیات نوشتن دیتا، دو گزینه پیش رو داریم:

گزینه اول: استفاده از ILA‌ و پیکره بندی آن به نحوی که تریگر آن روی AXI Write قرار داده شود و در نهایت بررسی مقادیری که در حال نوشته شدن درون حافظه است.

استفاده از ILA‌ و بررسی مقادیری که در حال نوشته شدن روی حافظه است
استفاده از ILA‌ و بررسی مقادیری که در حال نوشته شدن روی حافظه است
استفاده از ILA‌ و بررسی مقادیری که در حال نوشته شدن روی حافظه است (ادامه)
استفاده از ILA‌ و بررسی مقادیری که در حال نوشته شدن روی حافظه است (ادامه)

گزینه دوم: استفاده از JTAG to AXI bridge برای خواندن آدرس‌های نوشته شده و تایید صحت مقادیری که در حافظه نوشته شده است.

استفاده از JTAG to AXI bridge برای خواندن آدرس‌های نوشته شده در حافظه
استفاده از JTAG to AXI bridge برای خواندن آدرس‌های نوشته شده در حافظه

با این نتایج موفقیت آمیز بودن عملیات نوشتن در حافظه تایید می‌شود، این یعنی طراحی HLS ما بسیار انعطاف پذیر و البته قابل اطمینان است.

در انتها در لازم است به چند نکته مهم توجه کنید:

  • مطمئن شوید که بلوک HLS‌ به درستی ریست می‌شود.
  • مطمئن شوید که سیگنال ap_start تا زمانی که سیگنال ap_ready فعال نشده است در وضعیت ‘1’ منطقی باقی می‌ماند.
  • در نظر داشته باشید که نگه داشتن سیگنال ap_start در وضعیت ‘1’ منطقی منجربه به اجرای چندباره ماژول HLS می‌شود.
  • و در نهایت مطمئن شوید که رنجِ آدرس برای دسترسی به حافظه از درون سخت افزار به درستی تنظیم شده است.

جمع بندی

امیدوارم از مطالعه این آموزش بهره کافی را برده باشید. در این آموزش من در قالب یک پروژه ساده شیوه خواندن و نوشتن در حافظه خارجی با Vivado HLS را به شما توضیح دادم. همانطور که در ابتدای آموزش نیز اشاره شد، شما می‌توانید از هر بوردی که در اختیار دارید برای انجام این پروژه استفاده کنید، فقط کافی است این بورد دارای یک FPGA‌ از خانواده آموزشی سری ۷ یا ZYNQ باشد و حافظه DDR روی بورد وجود داشته باشد.


منبع: برگرفته از adiuvoengineering.com نوشته Adam Taylor


اشتراک
بیشتر بخوانیم
مفهوم حافظه در FPGA و کاربردهای آن توصیف سخت افزاری

بهره گیری از پایتون در Zynq

پروژه PYNQ یک پروژه منبع باز، برای تسهیل فرایند طراحی سیستم‌های نهفته (embedded) روی Zynq است. هدف آن بهره گیری از پایتون در Zynq است.

آشنایی با مفهوم Device Tree سیستم‌های نهفته و لینوکس

آشنایی با مفهوم Device Tree

آیا با مفهوم Device Tree آشنا هستید؟ برای اکثر ما Device Tree جایی است که اضافه یا حذف قطعات کوچک سخت افزاری به کرنل لینوکس گزارش می‌شود.

آموزش سریع Vivado HLS ابزارهای طراحی

قست سوم: پکیج کردن HLS IP برای Vivado IP Catalog

در این ویدئو شیوه پکیج کردن HLS IP برای Vivado IP Catalog را باهم مرور خواهیم کرد. این HLS IP می‌تواند در محیط Vivado IP Integrator فراخوانی و استفاده شود.

مقدمه‌ای بر فیلترها عمومی

مقدمه‌ای بر فیلتر ها

فیلتر مداری است که قابلیت عبور (یا تقویت) مؤلفه‌های از پیش تعیین شده فرکانسی و همینطور مسدود کردن یا تضعیف کردن سایر مؤلفه‌های فرکانسی یک طیف را دارد.

عناوین مطالب
    Add a header to begin generating the table of contents

    5 دیدگاه دربارهٔ «خواندن و نوشتن در حافظه DDR با HLS»

    1. با سلام.ممنون از این آموزش سور س فایل های این طراحی را از کجا می شه پیدا کرد ممنون می شم از کمککتون.

      1. گروه برنامه نویسی

        سلام و درود فراوان بر شما دوست عزیز،
        از اظهار لطف شما نسبت به مطالب منتشر شده سپاسگزارم.
        برای دسترسی به فایل‌های پروژه می‌توانید به گیت هاب آدام تیلور که لینکش در قسمت منبع این مقاله هست، مراجعه کنید. اما توجه داشته باشید که پروژه های Vivado معمولاً حجیم هستند و فایل پروژه به صورت مستقیم در فضای ابری (آنلاین) قرار داده نمی‌شود و در عوض فایل‌های Tcl برای ساخت مجدد پروژه مورد استفاده قرار می‌گیرد.

        شما می‌توانید از پروژه شماره ۲۳۹ در این گیت هاب و به شکل دقیق تر فایل part_239.tcl برای ساخت مجدد این پروژه استفاده کنید. البته کار یک مقدار سخت تر هستش چون حتماً باید پروژه Vivado HLS را هم قبلش بسازید و به صورت IP به Repository های Vivado اضافه کنید و بعد این فایل را اجرا کنید.

        نسخه Vivado مورد استفاده 2017.4 است. موفق باشید.

    2. خیلی خیلی اموزش خوبی بود ممنون میشم اگر باز هم اموزش هایی از این دست چه با پروژه های ساده چه پیشرفته تر منتشر کنید.

      1. درود بر شما دوست عزیز و گرامی
        امیدوارم سرحال و پیروز باشید و روز به روز در مسیر موفقیت و پیشرفت گام بردارید. حتماً از نظر ارزشمند شما در تهیه مطالب آموزشی استفاده خواهیم کرد.

    دیدگاه‌ خود را بنویسید

    نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

    اسکرول به بالا

    25% off

    کد تخفیف qnyz99IX