در قسمت هجدهم و قسمت نوزدهم از آموزش FPGA با شیفت رجیستر آشنا شدیم و شیفت رجیستر را با روشهای متفاوتی پیادهسازی کردیم. در این قسمت قصد داریم که ابتدا با عملگرها آشنا شویم و سپس به عملگرها و توابع در زبان VHDL بپردازیم.
عملگرها
خارج از دنیای دیجیتال ما در ریاضیات با عملگرها آشنا هستیم و بدون استفاده از عملگرها، یک سری عدد داریم که هیچ کاری با آنها نمیتوانیم انجام بدهیم. چهار عمل اصلی در ریاضیات شامل: جمع، تفریق، ضرب و تقسیم میباشد و ما با استفاده از همین عملگرها به ریاضیات معنا میدهیم و از ریاضیات در دنیای واقعی و کارهای خودمان استفاده میکنیم. در دنیای دیجیتال و کدنویسی که البته خود تا حدود زیادی برگرفته از ریاضیات است نیز ما همین کار را انجام میدهیم.
در دنیای دیجیتال و کدنویسی هم بدون استفاده از عملگرها، تقریبا هیچ کاری قابل انجام نیست. و اگر عملگرها وجود نداشته باشند یک سری دادهی دیجیتال به صورت صفر و یک یا همان باینری داریم که هیچ کاری با آنها نمیتوانیم انجام بدهیم.
توابع
با تابع هم در دنیای ریاضیات به خوبی آشنا هستید و مفهوم آن را میدانید. در دیجیتال و کدنویسی هم تقریبا تعریف همان است و در جزئیات کمی تفاوت دارد. مثلا تابع میتواند یک یا چند پارامتر را به عنوان ورودی بگیرد و یک یا چند پارامتر دیگر را به عنوان خروجی به ما بدهد.
کاری که توابع انجام میدهند کمی پیچیدهتر از عملگرهاست و در یک تابع ممکن است به تعداد دفعات زیادی از عملگرها استفاده کنیم. پس با توجه به همین پیچیدگی اگر یک عمگر بر روی یک سری داده اعمال شود، خروجیِ حاصل، نتیجه محاسبات سادهای بر روی ورودیهاست. اما اگر یک تابع بر روی یک سری داده اعمال شود، خروجیِ حاصل، نتیجه محاسبات بیشتری بر روی ورودیهاست.
فرض کنید میخواهیم تابع سینوس (Sin) را در دیجیتال پیادهسازی کنیم، راههای مختلفی برای این پیادهسازی وجود دارد یکی از این راهها استفاده از بسط تیلور است. در بسط تیلور به تعداد دفعات زیادی از عمگرهای جمع و تفریق استفاده میشود (البته از عملگرهای دیگری نیز استفاده میشود). پس وقتی میخواهیم تابع سینوس را پیادهسازی کنیم به تعداد دفعات زیادی از عملگرها استفاده خواهیم کرد و به نسبت محاسبات زیادتری را نیز انجام میدهیم.
اگر میبینید که تعاریف را کمی متاوتتر از آنچه که به عنوان معمول برای تعریف این مفاهیم وجود دارد، ارائه میدهیم برای این است که شما دقیقا با کاری که قرار است انجام شود به خوبی آشنا شوید نه صرفا آشنایی با یک تعریف کلیشهای.
اجازه بدهید کم کم با عملگرها و توابع در زبان VHDL آشتا شویم.
اگر با FPGA آشنایی ندارید اول مقاله FPGA چیست؟ را مطالعه نمایید.
عملگرها و توابع در زبان VHDL
همانطور که میدانید زبان VHDL یک زبان توصیف سختافزار و سطح پایین میباشد. سطح پایین به این معنا که نیاز است شما به خوبی با سختافزار، نحوهی پیادهسازی عملیات، تحلیل بیت به بیت دیتا، جبر بول و بسیاری از موارد دیگر به خوبی آشنا باشید. با همهی این تفاسیر بعضی از عملگرها و توابع در زبان VHDL از قبل برای ما وجود دارد و ما میتوانیم از آنها استفاده کنیم.
مثلا عملگر جمع و ضرب از جمله عملگرهایی هستند که در زبان VHDL تعریف شده و شناخته شده هستند و نیازی نیست که بخواهیم آنها را از ابتدا خودمان تعریف کنیم. به عنوان مثال دیگر، عملیات تقسیم در زبان VHDL تعریف شده نیست و باید با استفاده از الگوریتمهایی مختلف و همچنین دانش مدار منطقی و جبر بول خودمان این عملیات را پیادهسازی کنیم. ناگفته نماند که در زبان VHDL برای تقسیم، IP وجود دارد و ما میتوانیم از این IP بدون درگیر شدن با عملیات پیادهسازی، استفاده کنیم.
در ادامه با یک عملگر و یک تابع بسیار پرکاربرد از جمله عملگرها و توابع در زبان VHDL آشنا خواهیم شد.
عملگر Concatenation در زبان VHDL
همانطور که از معنای این عملگر پیداست، کار این عملگر چسباندن یا کنار هم قرار دادن دادهها یا سیگنالها است.
ما با استفاده از علامت & میتوانیم دو سیگنال را در کنار هم قرار دهیم.
فرض کنید که دو سیگنال هشت بیتی داریم و میخواهیم به نحوی آنها را کنار هم قرار دهیم. مثلا بیت سوم تا ششم یکی از سیگنالها را کنار بیت پنجم تا هفتم یکی دیگر از سیگنالها قرار بدهیم.
ابتدا به کد زیر توجه کنید تا در ادامه توضیحات لازم را بیان کنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std_all; entity Concatenation is port ( Output_R : out unsigned(6 downto 0) ); end Concatenation; architecture Behavioral of configuration is signal A : unsigned (6 downto 0); signal B : unsigned (7 downto 0); signal C : unsigned (7 downto 0); begin A <= B(5 downto 2) & C(6 downto 4); Output_R <= A; end Behavioral; |
همانطور که گفتیم دو سیگنال هشت بیتی داریم که میخواهیم در مجموع به نحوی این دو سیگنال را کنار هم قرار بدهیم که یک سیگنال هفت بیتی ساخته شود. پس ما در ابتدا دو سیگنال هشت بیتی و یک سیگنال هفت بیتی تعریف میکنیم.
در ادامهی کد، چهار بیت از سیگنال B و سه بیت از سیگنال C را با استفاده از عملگر & در کنار هم قرار دادیم و به سیگنال A که هفت بیتی است ارجاع دادیم.
شما در یک ارجاع میتوانید چندین بار از عملگر & استفاده کنید و بیتهای مختلف چندین سیگنال را به هم بچسبانید.
در ادامه بحث عملگرها و توابع در زبان VHDL به بحث جذاب توابع میپردازیم.
تابع resize در زبان VHDL
از کاربرد این تابع همین کافی که قوانین سختگیرانه زبان VHDL هرگز به شما اجازه نمیدهند که بخواهید از این تابع استفاده نکنید. جبر و دیکتاتوریهای قبل از این تابع سوتفاهم بود.
حقیقتا زبان VHDL یک زبان بسیار حساس و دقیق میباشد و در انواع ارجاعات آن باید بیت به بیت دیتا و پارامترهای دیگر را بررسی کرد و ملاحظات لازم را در نظر گرفت تا کار به درستی صورت بگیرد.
شاید بتوانید در یک پروژه کوچک از این تابع استفاده نکنید اما در یک پروژه بزرگ، مخصوصا اگر بخواهید پردازش سیگنال انجام بدهید، تابع resize جز لاینفک پروژه خواهد بود.
عملکرد تابع resize
بسته به اینکه سیگنال موردنظر باعلامت باشد یا بیعلامت، عملکرد این تابع میتواند متفاوت باشد. در ادامه به تشریح این دو حالت خواهیم پرداخت.
اگر سیگنال بیعلامت باشد:
- اگر سیگنال موردنظر به عرض بیت بزرگتری resize شود، به سمت چپ آن به تعداد لازم، تا رسیدن عرض بیت به تعداد بیتهایی که ما در ورودی این تابع در نظر گرفتیم، صفر افزوده میشود.
- اگر سیگنال موردنظر به عرض بیت کوچکتری resize شود، از سمت چپ آن به تعداد لازم، تا رسیدن عرض بیت به تعداد بیتهایی که ما در ورودی این تابع در نظر گرفتیم، بیت برداشته میشود.
اگر سیگنال باعلامت باشد:
- اگر سیگنال موردنظر به عرض بیت بزرگتری resize شود، به سمت چپ آن به تعداد لازم، تا رسیدن عرض بیت به تعداد بیتهایی که ما در ورودی این تابع در نظر گرفتیم، بیت علامت افزوده میشود.
- اگر سیگنال موردنظر به عرض بیت کوچکتری resize شود، بیت علامت حفظ میشود و سپس از سمت چپ آن به تعداد لازم، تا رسیدن عرض بیت به تعداد بیتهایی که ما در ورودی این تابع در نظر گرفتیم، بیت برداشته میشود.
ابتدا به کد زیر توجه کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std_all; entity Resize_F is port ( A_1 : out signed(11 downto 0); A_2 : out signed(3 downto 0); B_1 : out unsigned(11 downto 0); B_2 : out unsigned(3 downto 0) ); end Resize_F; architecture Behavioral of configuration is signal A : signed (7 downto 0) := "11110000"; signal B : unsigned (7 downto 0); := "11110000"; begin A_1 <= resize(A, 12); A_2 <= resize(A, 4); B_1 <= resize(B, 12); B_2 <= resize(B, 4); end Behavioral; |
در کد بالا ما دو سیگنال باعلامت و بیعلامت با مقدار اولیه یکسان تعریف کردیم و سپس با استفاده از تابع resize، این سیگنالها را هم به عرض بیت بزرگتر و هم به عرض بیت کوچکتر resize کردیم و به خروجی ارجاع دادیم.
حال میخواهیم ببینم که پس از resize کردن سیگنال، چه تغییراتی روی این سیگنال و به چه صورت رخ میدهد.
برای اینکه به خوبی متوجه بشوید پس از resize شدن سیگنال چه اتفاقی روی آن رخ میدهد به تصویر زیر توجه کنید:
تصویر بالا به خوبی مطابقت دارد با توضیحاتی که در رابطه با resize شدن به عرض بیت بزرگتر بیان کردیم و نیاز به هیچ گونه توضیح اضافی ندارد. resize شدن به عرض بیت کوچکتر را به عنوان تمرین به عهده خودتان میگذاریم.
تصویر بالا عملیات zero/sign extension را انجام میدهد، که میتوانید در این رابطه بیشتر تحقیق کنید.
امیدوارم که مقالهی عملگرها و توابع در زبان VHDL نیز مانند سایر مقالات برای شما مفید واقع شود و از آن در پروژههای خو بهره ببرید.
در قسمت بعدی کار بر روی برد و بحث عملی را شروع خواهیم کرد.
سلام میشه راهنماییم کنید این عملیات ها چطور میتونم بهVHDL بدون فلیپ فلاپ بنویسم؟
X0 := X0 <<<13
X2 := X2 <>> نماد گردش به چپ و >> هم نماد شیفت به چپ هست.
با سلام و تشکر بابت اموزش های عاااالی تون .پس چرا کار بر روی برد و بحث عملی را شروع نکردید ؟
سلام. حقیقتا دو سال پیش وقتی داشتم این مقالات را مینوشتم قرار بود که یک برد آموزشی تهیه و یا طراحی کنیم که متاسفانه هیچ کدام انجام نشد. اما من تمامی این کدهایی که در مقالات استفاده شده رو به صورت عملی تست کردم، نگران نباشید و بل خیال راحت از این کدها استفاده کنید.
سلام … خوب برای مابقی آموزش FPGA یه منبع خوب معرفی میکردی . تا اینجا که خوب پیش اومده بودی . ولی آخرش عاقبت به خیر نشد …
یه سوالم دارم از خدمتتون … اگر بخواهم با CPLD به جای FPGA کار کنم چه تغییراتی باید داده بشه؟ لطفا یه آموزش براش بذارید (این دفعه کامل باشه) … چون الان بورد های FPGA خیلی کم یاب و گرون شدند (اقتصادی نیست اصلا).
سلام دوست عزیز
احتمالا سری جدید اموزش FPGA رو منتشر خواهیم کرد
اما در خصوص سوال شما باید بگم کار خاصی از سمت شما نیاز نیست انجام بشه، و همه چیز مثل قبل هست فقط باید به تعداد گیت و میکروسل های موجود در CPLD دقت کنید که مقدار خیلی کمتری از FPGA هست
سلام تو hdlچجوری میشه تقسیم کننده با علامت با گیت ها ساخت الگوریتم بلدین ممنون میشم بفرستین
و این که یه گیم ساده تو این زبان از کجا میشه دانلود کرد
سلام دوست عزیز. برای عملیات تقسیم ip وجود دارد به اسم divider و میتوانید از این ip استفاده کنید. اگر میخواهید خودتان این کار را انجام بدهید ابتدا مدار منطقی تقسیمکننده را بررسی کنید، سپس کد hdl آن را بنویسید. قسمت آخر سوالتان را متوجه نشدم. واضحتر بفرمائید تا اگه بلد بودم پاسخ بدم.
بسیار ممنون از پاسخ و پیگیری شما
راستش یه پروژه تعیین کرده بود و میخواست با گیت های منطقی و بدون استفاده از توابع خاص تقسیم کننده بسازیم تا یه جایی نوشتم ولی حاصل تقسیم برای بعضی از اعداد درست در نمی امد و چون وقت اندکی دارم نمی تونم بسازم اگر ممکن بود یه ایمیل یا یه راه ارتباطی دیگه بفرمایین تا انجایی که نوشتم میفرستم البته میدانم زحمت میشه براتون به همین خاطر در صورت راضی بودن راه ارتباطی بفرمایین
خواهش میکنم دوست عزیز. حقیقتا کار شما یه تمرین دانشجویی ساده است نه یک پروژه که من بخواهم آن را به عنوان پروژه قبول کنم. اما خب کاری گه از دستم بر میآید راهنمایی کردن شماست. من قبلا همهی اینا را پیادهسازی کردم کار بسیار راحتی است. شما میتوانید ویدئوهای درس مدار منطقی دکتر نوابی را در سایت مکتب خونه ببینید اونجا به خوبی توضیحات لازم را داده خوب که درکش کردی بعد به سادگی پیادهسازی میشه.