عملگرهای جبری و توابع خاص، چگونه در FPGA پیادهسازی میشوند؟
برای پیادهسازی این عملیات، چه اقداماتی نیاز است که انجام شود؟
اقدامات انجام شده، توسط کاربر یا توسط نرمافزار پیادهسازی صورت میگیرد؟
در این مقاله میخواهیم در رابطه با پیادهسازی عملگرهای جبری اصلی و توابع خاص در FPGA صحبت کنیم.
به طور کلی در پیادهسازی با FPGAها، به جز موارد خیلی معدود، هیچ سختافزار از قبل آمادهای، برای هیچ عملیاتی وجود ندارد و باید برای انجام عملیات، یک سختافزار جدید از ابتدا طراحی شود.
More...
در موارد خیلی معدود که در بالا ذکر کردیم، سختافزاری مخصوص عملیاتی خاص از قبل وجود دارد، و فقط باید به پروژه اضافه شود.
اگر برای یک عملیات، سختافزار از قبل آمادهای وجود داشته باشد، معمولا نرمافزار پیادهسازی (مثل ISE یا ویوادو) با بررسی کد ما متوجه آن میشود، و آن سختافزار را به صورت خودکار به پروژه اضافه میکند.
به عنوان مثال، عملیات ضرب جزء مواردی است که سختافزاری از قبل آماده برای آن وجود دارد، و در ادامه توضیح خواهیم داد که نرمافزار پیادهسازی، چگونه سختافزار از قبل آماده را برای این عملیات به پروژه اضافه میکند.
پس برای هر عملیات جدید، یا باید سختافزار از قبل آماده به پروژه اضافه شود، یا با استفاده از منابع موجود درون FPGA، سختافزاری که قادر به انجام عملیات مورد نظر باشد، طراحی شود.
بنا به عملیات مورد نظر، طراحی این سختافزار میتواند توسط کاربر یا توسط نرمافزار انجام شود.
اگر قرار باشد کاربر مداری متناسب با عملیات مورد نظرش طراحی کند، باید با استفاده از منابع پایهای که درون FPGA وجود دارند، مدار را طراحی کند.
اما اگر قرار باشد که مدار توسط نرمافزار پیادهسازی طراحی شود، دو راه زیر وجود دارد:
طراحی مدار توسط نرمافزار پیادهسازی
راه اول این است که نرمافزار از کد ما متوجه میشود که چه مداری مورد نیاز است و با استفاده از الگوریتمهای داخلی خود و همچنین منابع پایهای درون FPGA، آن مدار را طراحی و به پروژه اضافه میکند.
راه دوم این است که نرمافزار به کمک کاربر، با استفاده از IPهایی که درون نرمافزار وجود دارند، مدار را طراحی و به پروژه اضافه میکند. (IPها توسط کاربر تنظیم میشوند.)
در مورد منابع پایهای درون FPGA، و IPها در ادامه توضیح خواهیم داد.
بیایید یک بار دیگر، راههای موجود برای انجام یک عملیات را بررسی میکنیم:
IPهای درون نرمافزارهای پیادهساز
IPها، ماجولهای از قبل آماده شدهای هستند که میتوانیم با استفاده از آنها در نرمافزارهای پیادهساز، کار پیادهسازی را راحتتر پیش ببریم.
IPها با استفاده از تنظیماتی که توسط کاربر اعمال میشود، ماجولهای از قبل طراحی شدهای را به پروژه اضافه میکنند.
منابع پایهای درون FPGA برای پیادهسازی
در FPGAها منابع مختلفی وجود دارد، که بعضی از این منابع برای پیادهسازی بخش خاصی از مدار مورد استفاده قرار میگیرد.
در این بین، منابعی وجود دارند که مشخصا مربوط به پیادهسازی بخش خاصی از مدار نیستند، و هرجا که هیچ مدار پیشبینی شدهای از قبل وجود نداشته باشد، و نیاز باشد که یک مدار جدید طراحی شود، معمولا از این منابع برای طراحی استفاده میشود.
ما به این منابع، منابع پایهای درون FPGA میگوییم.
بخش عمده مداری که قرار است از ابتدا توسط کاربر یا نرمافزار طراحی شود، از این منابع پایهای استفاده میشود.
اما این منابع پایهای دقیقا شامل کدام منابع درون FPGA میشود؟
منابع پایهای، شامل LUTها و فلیپفلاپهای درون FPGA میشود.
بهتر است بدانید که مهمترین و بیشترین منابع سختافزاری موجود در FPGAها، مجموعهی LUTها و فلیپفلاپها هستند.
LUTها در واقع حافظههای کوچکی هستند که میتوانند یک تابع کوچک دیجیتالی را پیادهسازی کنند.
این توضیحات را به این دلیل ذکر کردیم، که در ادامه بدانید که عملگرها و توابع مختلف درون FPGA چگونه و با استفاده از چه منابعی پیادهسازی میشوند.
شما همچنین برای اطلاعات بیشتر در رابطه با این موضوع، میتوانید به مقالهی "FPGA چیست؟ – منابع سختافزاری درون FPGA" مراجعه کنید.
عملگرهای جبری اصلی
عملگر ضرب
در بین عملگرهای جبری اصلی و به طور پیشفرض، فقط برای عمل ضرب، از یک سختافزار از قبل آماده شده استفاده میشود. یعنی زمانی که ما در کد، از عملگر "*" استفاده میکنیم، نرمافزار پیادهساز به طور خودکار، از ضربکننده سختافزاری از قبل آماده، برای عملیات ضرب استفاده میکند.
مورد بالا جزء همان مواردی بود که گفتیم معمولا نرمافزار از کد ما (عملگر "*") متوجه میشود، و سختافزار از قبل آماده را به صورت خودکار به پروژه اضافه میکند.
به صورت پیشفرض عملیات ضرب با استفاده از بلوک DSP48 پیادهسازی میشود.
برای آگاهی از چگونگی عملیات ضرب در FPGA، میتوانید ویدئوی "پشت پرده عملیات ضرب در FPGA" را مشاهده کنید.
عملگر جمع و تفریق
برای عمل جمع و تفریق، زمانی که ما در کد، از عملگرهای "+" و "-" استفاده میکنیم، نرمافزار با استفاده از الگوریتمهایی که دارد یک نوع مدار جمعکننده یا تفریقکننده را طراحی و به پروژه اضافه میکند.
توجه کنید که در عملیات جمع و تفریق به صورت مستقیم هیچ IPای مورد استفاده قرار نمیگیرد، و برای پیادهسازی این عملگرها، نرمافزار از کد ما (از طریق عملگرهای "+" و "-")، متوجه میشود که چه مداری مورد نیاز است، و با استفاده از الگوریتمهای داخلی خود، آن مدار را طراحی و به پروژه اضافه میکند.
به صورت پیشفرض عملیات جمع و تفریق، در اکثر موارد به کمک LUTها پیادهسازی میشوند.
عملگر تقسیم
بر خلاف عملگرهای "*"، "+" و "-" که برای نرمافزارهای پیادهساز، عملگرهای شناختهشدهای هستند، عملگر "/"، توسط نرمافزار قابل شناسایی نیست.
به همین دلیل ما برای پیادهسازی عملیات تقسیم، از یک IP به نام Divider استفاده میکنیم.
این IP توسط کاربر تنطیم میشود، و نرمافزار با استفاده از تنظیمات کاربر، مدار تقسیمکننده را طراحی و به پروژه اضافه میکند.
ما چگونگی عملیات تقسیم با استفاده از IP تقسیمکننده را در مقالهای تحت عنوان "پیادهسازی عملیات تقسیم در FPGA" به صورت کامل توضیح دادیم.
البته توجه داشته باشید که اگر عملیات تقسیم مورد نظر شما شامل تقسیم یک سیگنال بر یک عدد ثابت که توانی از دو است باشد، میتوان در کد از عملگر / استفاده کرد و بحثی که در بالا انجام شد مربوط به شرایطی است که قرار است یک سیگنال بر یک سیگنال دیگر تقسیم شود.
تقسیم به عدد ثابت توانی از دو
اگر عددی که میخواهیم در مقسومعلیه تقسیم قرار بگیرد، یک عدد ثابت توانی از ۲ باشد، نرمافزار آن را با استفاده از شیفت رجیستر پیادهسازی میکند.
به عنوان مثال کد VHDL زیر بدون هیچ خطایی توسط نرمافزار شناخته میشود، و از شیفت رجیستر برای طراحی مدار آن استفاده میکند.
A <= B/256;
در کد بالا اگر به جای عدد ۲۵۶، مثلا عدد ۱۸ را قرار میدادیم، به دلیل اینکه عدد ۱۸، توانی از ۲ نیست، نرمافزار قادر به پیادهسازی با استفاده از شیفت رجیستر نخواهد بود.
تا اینجا عملگرهای اصلی را به طور کامل بررسی کردیم و مفصلا توضیح دادیم که هر کدام از این عملگرها چگونه پیادهسازی میشوند.
اکنون میخواهیم در رابطه با توابع خاص و نحوهی پیادهسازی آنها صحبت کنیم.
نحوه پیادهسازی توابع خاص
توابع خاص، شامل توابع مثلثاتی مثل سینوس و کسینوس، رادیکال و ... هستند.
توابع خاص چگونه در FPGA پیادهسازی میشوند؟
این توابع در زبانهای توصیف سختافزار، مانند VHDL، عملگری ندارند و باید برای آنها مداری طراحی شود.
یک ایده برای پیادهسازی توابع خاص، استفاده از بسط تیلور است.
به کمک بسط تیلور، میتوان تقریبی از توابع خاص را بدست آورد.
بسط تیلور مجموعهای از جملات است، که اگر تمامی این جملات را با هم جمع کنیم، یک معادل تقریبی از آن تابع خاص است.
به دو دلیل بسط تیلور انتخاب مناسبی برای پیادهسازی توابع خاص نیست.
دلیل اول این است که تعداد جملات زیادی را باید با هم جمع کنیم، تا تقریبا معادل خوبی از تابع خاص را بدست آوریم.
در عمل چنین کاری انجامپذیر نیست، و با جمع کردن دو یا سه جمله اول هم نمیتوان تقریب خوبی از تابع خاص را بدست آورد.
دلیل دوم این است که خود این جملات، از جمع، ضرب و تقسیم تشکیل شدهاند، که باعث میشود منابع مصرفی زیادی درون FPGA استفاده شود.
بنا به دو دلیل بالا، برای پیادهسازی از بسط تیلور استفاده نخواهیم کرد.
راه دیگر پیادهسازی، استفاده از الگوریتم CORDIC است.
الگوریتم CORDIC، یک الگوریتم بسیار مناسب و کارآمد، چه از لحاظ سرعت و چه از لحاظ منابع مصرفی است.
نکته مهم در الگوریتم CORDIC این است که تمامی توابع خاص که در بالا معرفی کردیم را تنها با استفاده از عملگرهای جمع و شیفت پیادهسازی میکند.
و همانطور که به احتمال زیاد میدانید پیادهسازی عملگرهای جمع و شیفت، یکی از سادهترین کارها در دیجیتال است.
بنابراین به راحتی و با کمترین منابع مصرفی، به کمک الگوریتم CORDIC، میتوانید توابع خاص را پیادهسازی کنید.
ما همچنین در مقالهای جداگانه، با عنوان "چطور یک مولد موج سینوسی در FPGA پیادهسازی کنیم؟"، نحوهی پیادهسازی یک موج سینوسی را به طور کامل در IP مربوط به آن توضیح دادیم.
درک و شناخت عمیق مفاهیم در هر کاری باعث میشود که آن کار را به بهترین نحو ممکن انجام دهیم.
امیدوارم که با خواندن این مقاله، به شناخت خوبی از نحوه عملیاتهای مختلف درون FPGA رسیده باشید و با به کارگیری این شناخت در پروژههایتان بتوانید بهترین و بهینهترین پروژهها را پیادهسازی کنید.