در بسیاری از طراحی های مدارات دیجیتال استفاده از حافظه ها اجتناب ناپذیر است. حافظهها یکی از منابع بسیار مهم در تراشه های FPGA هستند. در هنگام بهره بردن از حافظهها درون FPGA یکی از دو نوع حافظه موجود در آن استفاده میشود:
- حافظههای توزیع شده یا Distributed RAM
- حافظههای بلوکی یا Block RAM
حافظههای توزیع شده نوعی از حافظه است که توسط LUTها پیاده سازی میشوند. در بخش مربوط به CLBها گفته شد که LUTهای درون اسلایسهای SLICEM، میتوانند به صورت حافظه پیکرهبندی شوند. هر LUT میتواند جهت ذخیره سازی ۶۴ عدد تک بیت یا ۳۲ عدد دو بیتی استفاده شود.
با اتصال آبشاری LUT های درون یک اسلایس امکان افزایش این ظرفیت تا ۲۵۶ بیت نیز وجود دارد.برای ایجاد حافظه های با ظرفیت بزرگتر، استفاده از ظرفیت CLBهای دیگر نیز فراهم میشود. ولی افزایش مسیرهای بین CLBها از طریق ماتریس سوئیچ ها و همچنین استفاده از منابع اضافی دیگر، آن را از حالت بهینه خارج میکند. در این صورت در مواردی که نیاز به حجم حافظه بیشتری است راهکار چیست؟
در این مواقع شرکت سازنده FPGA منابع اختصاصی سخت افزاری به صورت بلوکهایی با ظرفیت ذخیره سازی چندین کیلوبیت روی تراشههای FPGA پیشبینی کرده است. ظرفیت هر کدام از بلوکهای حافظه در تراشههای سری ۷ برابر با ۳۶ کیلوبیت و در SPARTAN6 بلوکهای 18 کیلو بیتی قرار داده شده است. این بلوکهامیتوانند به ترتیب به عنوان دو حافظه 18 و 9 کیلوبیتی نیز استفاده شوند. تعداد بلوکهای حافظه در هر تراشه بسته به حجم منابع و خانواده آن متفاوت است.
مزیت مهم بلوکهای حافظه بهره گیری از دو پورت کاملا مستقل است بطوریکه هر پورت دارای کلاک، آدرس، ورودی فعال ساز کلاک، ورودی داده و فرمان مستقل برای خواندن و نوشتن حافظه است. این پورتها از نظر پهنای بیت داده و همچنین کلاک کاری نیز میتوانند مستقل از یکدیگر پیکره بندی شوند. البته باید این نکته را در نظر داشت که هر دو پورت به فضای یکسانی از حافظه دسترسی دارند. همچنین این بلوک ها دارای رجیستر اختصاصی در خروجیهای خود میباشد. استفاده از این رجیستر ها باعث کاهش تاخیر مسیر و بهبود عملکرد مدار میشود. بطور کلی حافظه های بلوکی به هر یک از حالتهای زیر میتوانند پیکرهبندی شوند:
- تک پورت: در این حالت یک پورت برای دسترسی به درون حافظه قرار داده میشود که برای خواندن و نوشتن به صورت سنکرون با کلاک استفاده میشود.
- دو پورت ساده: در حالت دو پورت ساده یک پورت برای خواندن و پورت دیگر برای نوشتن استفاده میشود، همانطور که قبلا بیان شد هر کدام از پورتها دارای کلاک و سیگنالهای کنترلی مستقل هستند.
- دو پورت کامل: این حالت دو پورت کاملا مستقل برای خواندن و نوشتن در اختیار کاربر قرار میدهد.
در زمان نوشتن در حافظه هنگامی که پایه WE فعال میشود و داده برای نوشتن در ورودی DI قرار میگیرد، نحوه عملکرد خروجی DO میتواند به یکی از سه حالت زیر باشد:
- حالت Read_first
- حالت Write_first
- حالت No_change یا بدون تغییر
حالت خروجی در هنگام نوشتن برای هر پورت بطور جداگانه میتواند مشخص شود. در صورتی حالتی مشخص نشود بطور پیش فرض خروجی های RAM در هنگام نوشتن داده، Write_first در نظر گرفته میشود.
در حالت WRITE_FIRST، داده های ورودی به طور همزمان در حافظه نوشته شده و در خروجی نیز قرار داده می شوند. در واقع داده جدید نوشته شده در خروجی ظاهر میشود.
در حالت READ_FIRST، در حالی که دادههای جدید ورودی در حافظه با آدرس مورد نظر نوشته میشود، دادههایی که قبلاً در همان آدرس ذخیره شدهاند، روی لچهای خروجی ظاهر میشوند.
در حالت NO_CHANGE، خروجی در طول عملیات نوشتن بدون تغییر باقی می ماند. در این حالت هنگامی که سیگنال WE برای نوشتن بالا می آید خروجی حافظه آخرین مقداری که در زمان خواندن از حافظه را در خروجی قرار داده بود حفظ نموده و در طول زمان نوشتن داده ها در حافظه تغییر نمیکند.
به این نکته دقت شود که نمایش خروجی حافظه در سه شکل بالا بدون در نظر گرفتن رجیستر خروجی نشان داده شده است و در صورتی که در خروجی از رجیستر داخلی آن استفاده شود به اندازه یک کلاک تاخیر به آن افزوده خواهد شد.