به کمک زبان VHDL انواع مدارات منطقی شامل مدارات منطقی ترکیبی، ترتیبی سنکرون و ترتیبی آسنکرون را میتوان توصیف و پیادهسازی کرد.
اما آنچه بیش از ۹۰ درصد مدار شما را در یک پیادهسازی حرفهای تشکیل میدهد، مدارات ترتیبی سنکرون هستند.
More...
مدارات ترتیبی در زبان VHDL به کمک ساختاری به نام process در دل محیط concurrent توصیف میشوند. برای آشنایی با محیط concurrent قسمت اول از برنامه ویدئویی آموزش زبان VHDL را ببینید.
به کمک ساختار process، هم میتوان مدارات ترکیبی را توصیف کرد و هم مدارات ترکیبی. اما همانطور که گفته شد، شما در طرح حرفهایتان فقط مدارات ترتیبی، آن هم از نوع سنکرون را در این ساختار توصیف خواهید کرد. برای آشنایی با نحوه توصیف مدارات ترکیبی در محیط concurrent این برنامه را ببینید.
در این برنامه ویدئویی، مفاهیم اولیه و اصول بسیار مهمی را در ارتباط با ساختار process به شما آموزش میدهم.
به این نکته توجه داشته باشید که حتی افرادی که سالها است در زمینه پیادهسازی با FPGA فعالیت دارند، ممکن است هنوز بعضی از مفاهیم ساختار process را به خوبی درک نکرده باشند.
بنابراین پیشنهاد میکنم با دقت به این برنامه و برنامههای مرتبط با ساختار process که در آینده منتشر خواهند شد توجه کنید تا در هنگام یک پیادهسازی جدی، تا حد امکان از سعی و خطا و دوباره کاری که منجر به اتلاف وقت شما خواهد شد جلوگیری کنید.
آشنایی با نحوه توصیف مدارات ترکیبی در محیط concurrent
ویدئو یا متن؟
محتوای این برنامه آموزشی، به دو صورت ویدئو و متن آماده شده است. اگر علاقمند به یادگیری این مطلب به صورت ویدئویی هستید، ویدئوی زیر را ببینید و اگر ترجیح میدهید آن را به صورت متن مطالعه کنید، ادامه این مطلب را بخوانید.
برای دانلود نسخه با کیفیت این ویدئو، روی دکمه زیر کلیک کنید:
این مقاله، بخش چهارم از مجموعهی آموزشی زبان VHDL است.
در این مقاله، قصد دارم شما را با نحوهی طراحی مدارات ترکیبی در محیط Sequential و به کمک ساختار if آشنا کنم.
مروری بر ساختار Architecture
به عنوان یادآوری از مقالههای قبلی، ساختار Architecture به صورت زیر است:
احتمالاً از مقالههای قبلی به یاد دارید که به طور کلی ساختار هر کد VHDL از دو بخش Entity و Architecture تشکیل شده است.
بخش Architecture، از سه ناحیه تشکیل شده که در ناحیهی اول سیگنالها و ماجولها را تعریف میکنیم.
در ناحیهی بعدی، که ناحیهی Concurrent است، میتوانید مدارات ترکیبی را توصیف کنید.
و در ناحیهی Sequential که در دل ناحیهی Concurrent تعریف میشود، میتوانید هم مدارات ترکیبی و هم مدارات ترتیبی را تعریف کنید.
موضوع این مقاله در ارتباط با تعریف مدارات ترکیبی در ناحیهی Sequential است.
بخش Architecture از کد VHDL، با کلمهی کلیدی Architecture آغاز میشود. ناحیهی بین خط اول و کلمهی کلیدی Begin، ناحیهی Declaration است که برای معرفی سیگنالها و ماجولها استفاده میشود.
از کلمهی کلیدی Begin، مربوط به بخش Architecture تا انتهای Architecture که با عبارت کلیدی end Architecture پایان مییابد، محیط Concurrent است که فقط میتوانید مدارات ترکیبی را در آن طراحی کنید.
میتوانید در دل محیط Concurrent به وسیلهی ساختار پراسس محیط جدیدی ایجاد کنید که آن را محیط Sequential مینامند؛ در محیط Sequential میتوانید مدارات ترتیبی و ترکیبی را پیادهسازی کنید.
همانطور که برای توصیف انواع مختلف مدارات ترکیبی در محیط Concurrent عبارات ارجاع ویژهای وجود داشت، در محیط Sequential نیز ساختارهای ارجاع ویژهای وجود دارد که به کمک آنها میتوانید هم مدارات ترتیبی و هم مدارات ترکیبی را توصیف کنید.
دو عبارت ارجاع پرکاربرد و اصلی در محیط Sequential، عبارت ارجاع if-then-elsif و عبارت ارجاع case است که در این مقاله راجع به عبارت if-then-elsif صحبت میکنم.
ساختار Process در کد VHDL
اجازه دهید ابتدا با ساختار پراسس و برخی از مفاهیم مربوط به آن آشنا شویم.
نکتهی مهمی که وجود دارد این است که ساختار پراسس، ساختار ویژهای است و مفاهیم آن با مفاهیم سایر بخشهای زبان VHDL تا حدی متفاوت است.
پس سعی کنید از ابتدا این مفاهیم را -که البته تعداد زیادی نیستند- به خوبی یاد بگیرید تا بتوانید به بهترین شکل ممکن مدارات مختلف را توصیف کنید.
اگر با مفاهیم این محیط به خوبی آشنا نباشید، ممکن است مداراتی که به وسیلهی این ساختار توصیف میکنید، مشکلات و ایراداتی داشته باشند که با بررسی منطقی آنها نمیتوانید به آن مشکلات پی ببرید.
پس مفاهیم ساختار پراسس بسیار مهم هستند.
نمونه کدی که در زیر میبینید، یک کد بسیار ساده است که صرفاً برای توضیح برخی از مفاهیم مرتبط با ساختار پراسس از آن استفاده میکنیم.
Architecture Behavioral of temp is begin -- concurrent. process(A,X) begin A <= B; C <= A; end process; -- concurrent. end Behavioral;
در این کد، در دل محیط Concurrent، یک محیط Sequential را به کمک ساختار پراسس ایجاد کردهام؛ محیط پراسس، با کلمهی کلیدی Process شروع میشود و با عبارت کلیدی end Process پایان مییابد.
توجه کنید که قبل از کلمهی کلیدی Process و بعد از عبارت کلیدی end Process، جزء محیط Concurrent محسوب میشود.
لیست حساسیت ساختار Process
مقابل عبارت Process و درون یک پرانتز، تعدادی سیگنال میبینید؛ به این سیگنالها لیست حساسیت یا Sensitivity List میگویند.
سیگنالهایی که در لیست حساسیت پراسس هستند، مشخص میکنند که چه موقع باید Process فعال شود و عبارات ارجاع درون آن ارزیابی شوند.
در واقع، عبارات ارجاع درون محیط Process زمانی ارزیابی میشوند که حداقل، مقدار یکی از سیگنالهای درون لیست حساسیت تغییر کند.
اگر بخواهیم این موضوع را با اصطلاحات زبان VHDL بیان کنیم به این صورت است که هنگامی که روی یکی از سیگنالهای درون لیست حساسیت پراسس، یک Event رخ دهد، پراسس فعال میشود و عبارات ارجاع درون آن ارزیابی میشوند.
در پراسس کد بالا، دو سیگنال A و X درون لیست حساسیت هستند.
در نتیجه، فقط زمانی که حداقل روی یکی از این دو سیگنال، Event رخ دهد، پراسس فعال میشود و عبارات درون آن ارزیابی می شوند.
فرض کنید که اکنون روی یکی از این سیگنالها، Event رخ داده باشد؛ یعنی، مقدار آن سیگنال تغییر کرده باشد؛ بدین ترتیب، پراسس فعال میشود و باید عبارات ارجاع درون آن ارزیابی شوند.
در این پراسس دو عبارت ارجاع ساده وجود دارد که مقدار رجیستر B را به A و مقدار رجیستر A را به C منتقل میکند.
اگر این دو عبارت ارجاع در محیط Concurrent نوشته شده بود، نحوهی ارزیابی به این صورت بود که مثلاً اگر مقدار سیگنال B تغییر میکرد، خط ارجاع B به A فعال میشد و مقدار B به A منتقل میشد. آنگاه چون A تغییر پیدا کرده بود، دوباره خط بعدی فعال میشد و مقدار A به C منتقل میشد و بعد از چند لحظه، هر سه سیگنال B، A و C با هم برابر بودند.
اما در محیط پراسس، داستان متفاوت است. بعد از فعال شدن پراسس، عبارات ارجاع، خط به خط و به ترتیب ارزیابی میشوند.
اما نکتهای که وجود دارد این است که بر خلاف زبانهای برنامهنویسی، پس از ارزیابی هر خط، مقدار رجیستر سمت چپ، بهروزرسانی یا آپدیت نمیشود؛ بلکه مقدار رجیسترهای سمت چپ (که مقداری به آنها ارجاع شده)، زمانی بهروزرسانی میشود که به انتهای پراسس برسیم.
بنابراین تا زمانی که به انتهای پراسس نرسیدهایم، مقدار رجیسترها همان مقداری است که قبل از فعال شدن پراسس بوده است.
یعنی، اگر در کد بالا پراسس فعال شود، پس از انجام ارجاع خط هشتم و وقتی به ارجاع خط نهم میرسیم، مقدار رجیستر A برابر با مقدار فعلی رجیستر B نیست؛ زیرا هنوز فعالیت پراسس تمام نشده است و مقادیر رجیسترها بهروزرسانی نشدهاند. در انجام ارجاع خط نهم از کد، مقدار A برابر با مقدار A قبل از فعال شدن پراسس است.
برای اینکه این موضوع را بهتر درک کنید، یک مثال را با هم بررسی میکنیم.
فرض کنید مطابق شکل زیر، قبل از فعال شدن پراسس در کد بالا (یعنی قبل از اینکه یکی از سیگنالهای لیست حساسیت تغییر کند)، مقادیر رجیسترهای B ،A و C برابر با 1، 2 و 3 بودهاند.
اکنون اگر یکی از رجیسترهای A یا X و یا هر دوی آنها تغییر کند، پراسس فعال میشود.
پس از فعال شدن پراسس، عبارات ارجاع درون آن خط به خط ارزیابی میشوند.
ابتدا، اولین ارجاع که در خط هشتم کد قرار دارد، ارزیابی میشود و مقدار B به A ارجاع داده میشود.
سپس، خط نهم ارزیابی میشود و مقدار A به C ارجاع داده میشود.
اکنون فکر میکنید بعد از اینکه به انتهای پراسس رسیدیم، مقادیر سیگنالهای B ،A و C چه تغییری خواهند کرد؟
به احتمال زیاد اتفاقی که میافتد، با آنچه شما اکنون در ذهن دارید، متفاوت است.
چون شما قاعدتاً از قبل تجربهی برنامهنویسی داشتهاید و ذهنیت یک برنامهنویس را دارید؛ احتمالاً با ذهنیت برنامهنویسی به این نتیجه رسیدهاید که B به A منتقل میشود؛ یعنی، مقدار ۲ به A منتقل میشود و مقدار A برابر با ۲ میشود و اکنون که A برابر با ۲ شده است، مقدار ۲ به C منتقل میشود و C هم برابر با ۲ میشود. بنابراین، پس از پایان پراسس، باید مقدار تمام این رجیسترها برابر با ۲ شود؛ اما اتفاقی که میافتد با این روند متفاوت است.
مقدار رجیستر A و B برابر با ۲ میشود اما رجیستر C برابر با ۱ خواهد بود. اکنون بررسی میکنیم که چرا مقادیر رجیسترها به این صورت میشود؟
ابتدا در خط هشتم کد، مقدار رجیستر B به رجیستر A منتقل میشود. قبل از فعال شدن پراسس، مقدار رجیستر B برابر با ۲ بوده است. پس، عدد ۲ به A منتقل شده است؛ اما همانطور که قبلاً گفتم، مقدار A قبل از پایان فعالیت پراسس، تغییری نمیکند و در طول پراسس مقدار A، همان مقداری است که قبل از فعال شدن پراسس بوده است.
در خط نهم از کد و در ارجاع دوم، مقدار A به C منتقل شده است.
چه مقداری به C منتقل میشود؟ مقدار رجیستر A، قبل از فعال شدن پراسس ۱ بوده است؛ بنابراین، عدد ۱ به C، منتقل میشود.
پس از اینکه به پایان پراسس رسیدیم، مقادیر رجیسترها بهروزرسانی میشوند.
بنابراین، مطابق جدول زیر، مقادیر رجیسترهای A و C به ترتیب ۲ و ۱ خواهد شد. به رجیستر B هیچ ارجاعی نشده است، پس مقدار آن بدون تغییر و برابر با ۲ باقی میماند.
ساختار if-then-elsif در محیط Process
برای درک بهتر این موضوع و همچنین برای معرفی ساختار ارجاع if-then-elsif در محیط پراسس، مثال دیگری را با هم بررسی میکنیم.
در مقالات قبلی، یک مالتیپلکسر چهار به یک را به کمک ارجاع انتخابی و ارجاع شرطی در محیط Concurrent توصیف کردیم.
در شکل زیر، شمای کلی این مالتیپلکسر چهار به یک و جدول درستی آن را میبینید:
در این مقاله، این مالتیپلکسر را با ساختار ارجاع if-then-elsif و در محیط Process پیادهسازی خواهیم کرد.
توصیف یک مالتیپلکسر چهار به یک در محیط Process
در زیر، کد VHDL توصیف کنندهی مالتیپلکسر چهار به یک در محیط Process را میبینیم:
library IEEE; uSe IEEE.STD_LOGIC_1164.ALL; entity MUX4to1_if iS Port ( A : in STD_LOGIC; B : in STD_LOGIC; C : in STD_LOGIC; D : in STD_LOGIC; S : in STD_LOGIC_VECTOR (1 downto 0); F : out STD_LOGIC ); end MUX4to1_if; architecture Behavioral oF MUX4to1_if iS begin -- concurrent. proceSS(A,B,C,D,S) begin -- Sequential. if (S = "00") then F <= A; elsif (S = "01") then F <= B; elsif (S = "10") then F <= C; else F <= D; end if; -- Sequential. end process; -- concurrent. end Behavioral;
همانطور که در شکل قبل دیدید، مالتیپلکسر ما چهار ورودی C ،B ،A و D دارد؛ در بخش entity این کد، برای هر کدام از این ورودیها، یک سیگنال یا پورت تک بیتی از نوع STD_Logic و به صورت ورودی تعریف کردهایم.
دو خط کنترلی داریم که آنها را به صورت برداری و به کمک نوع دادهی STD_Logic_Vector تعریف کردهایم.
خط خروجی F را نیز به کمک تایپ STD_Logic تعریف کردهایم.
اکنون به بررسی ادامهی کد میپردازیم تا ببینیم چگونه این مالتی پلکسر را به کمک ساختار پراسس و ساختار شرطی if-then-elsif میتوانیم توصیف کنیم.
از خط ۱۶اُم کد بالا، Architecture مربوط به توصیف این مالتیپلکسر را میبینید که درون آن یک ساختار پراسس به کار بردهایم.
ورودیهای مالتیپلکسر، یعنی سیگنالهای D ،C ،B ،A و S را درون لیست حساسیت پراسس قرار دادهایم.
اکنون به تحلیل ساختار if-then-elsif در کد میپردازیم:
خط ۲۶اُم و ۲۷اُم بدین معناست که اگر سیگنال کنترلی S برابر با "00" باشد، پورت ورودی A به پورت خروجی F منتقل شود.
در خط ۲۸اُم و ۲۹اُم داریم که در صورت برقرار نبودن شرط قبل (در غیر این صورت)، اگر سیگنال کنترلی S برابر با "01" بود، پورت ورودی B به پورت خروجی F منتقل شود.
و در خط ۳۱اُم و ۳۰اُم داریم که در صورت برقرار نبودن دو شرط قبلی (در غیر این صورت)، اگر سیگنال کنترلی S برابر با "10" بود، پورت ورودی C به پورت خروجی F منتقل شود.
و در نهایت، در خط ۳۳اُم و ۳۲اُم داریم که در صورت برقرار نبودن هیچکدام از شرطهای قبلی (در غیر این صورت)، پورت ورودی D به پورت خروجی F منتقل شود.
در خط ۳۴اُم، با عبارت کلیدی end if، ساختار شرطی if-then-elsif پایان مییابد.
چند نکته از کد توصیفکنندهی مالتیپلکسر در ساختار پراسس
چند نکته در این کد وجود دارد:
اول اینکه در این ساختار شرطی، آخرین شرط را به صورت else قرار دادیم و مقابل کلمهی else شرطی نگذاشتیم. به کار بردن کلمهی کلیدی else بدین معناست که اگر هیچ کدام از حالتهای قبل برقرار نبود. وقتی سیگنال دوبیتی S برابر با هیچ کدام از مقادیر "00"، "01" و "11" نباشد، برابر با "11" خواهد بود؛ پس، منظورمان از خط ۳۲ این است که اگر سیگنال S مساوی "11" بود.
نکتهی بعدی این است که وقتی از کلمهی کلیدی elsif استفاده میکنید، باید توجه کنید که این کلمه، ترکیب دو کلمهی else و if است و همانطور که میبینید حرف e آخر کلمهی else در ترکیب elsif حذف شده است و if و els به صورت چسبیده به هم نوشته میشوند.
اگر elseif را اشتباه بنویسید، نرمافزار، از کد شما خطای سینتکس میگیرد.
برای آشنایی بیشتر با مفاهیم مربوط به ساختار پراسس، اجازه دهید در این کد تغییری ایجاد کنیم و تاثیر آن را ببینیم.
اگر مطابق کد زیر، عبارت ارجاعی که در خط ۳۳ از کد قبل وجود داشت را برداریم و به خارج از ساختار if منتقل کنیم چه اتفاقی میافتد؟ آیا این کد با کد قبلی یکسان است یا در عملکرد مالتیپلکسری که توصیف کردهایم تغییری ایجاد میشود؟
library IEEE; uSe IEEE.STD_LOGIC_1164.ALL; entity MUX4to1_if iS Port ( A : in STD_LOGIC; B : in STD_LOGIC; C : in STD_LOGIC; D : in STD_LOGIC; S : in STD_LOGIC_VECTOR (1 downto 0); F : out STD_LOGIC ); end MUX4to1_if; architecture Behavioral oF MUX4to1_if iS begin -- concurrent. process(A,B,C,D,S) begin -- Sequential. F <= D; if (S = "00") then F <= A; elsif (S = "01") then F <= B; elsif (S = "10") then F <= C; end if; -- Sequential. end process; -- concurrent. end Behavioral;
اگر به این کد دقت کنید و با مفاهیم مربوط به ساختار پراسس آشنا باشید، میتوانید حدس بزنید که این کد دقیقاً مشابه با کد قبلی است.
در این کد، پس از اینکه ساختار پراسس فعال میشود، ابتدا در ارجاع خط 26، مقدار پورت ورودی D به پورت خروجی F منتقل میشود. سپس ساختار شرط بررسی میشود.
همان طور که گفتم، مقادیر رجیسترها و پورتها تا انتهای پراسس، بهروزرسانی نمیشوند؛ بنابراین، آخرین ارجاع مورد قبول واقع میشود؛ یعنی، اگر شما به یک سیگنال، چندین بار ارجاع داشته باشید، آخرین ارجاع عملی میشود.
بنابراین، اگر یکی از شروط ساختار if-then-elsif برقرار باشد، یک عبارت ارجاع به پورت خروجی F خواهیم داشت و چون این ارجاع بعد از ارجاع خط 26 آمده است، مقدار F بر اساس این ارجاع تعیین میشود.
اما اگر هیچ یک از سه شرط ساختار if برقرار نباشد، آخرین ارجاع به پورت خروجی F، همان ارجاع خط 26 خواهد بود.
در کد قبلی نیز، در صورتی که هیچ یک از سه شرط ساختار if برقرار نبودند، مقدار پورت ورودی D به پورت خروجی F منتقل میشد.
بنابراین، این کد کاملاً مشابه با کد قبلی است.
ما در ارجاع خط 26، بدون هیچ شرطی D را به F منتقل کردیم.
بنابراین ما در این کد، این نکته را نیز متوجه شدیم که اگر به یک سیگنال بیش از یکبار در محیط پراسس، ارجاع داشته باشیم، آخرین ارجاع به آن سیگنال عملیاتی میشود.
در مورد محیط پراسس، مفاهیم و موضوعات دیگری نیز وجود دارد که در مقالههای بعدی در مورد آنها بیشتر صحبت خواهم کرد.
امیدوارم این مقاله هم مورد توجه شما قرار گرفته باشد و بتوانید از موضوعاتی که یاد گرفتید در نوشتن کدهایتان استفاده کنید.
آیا قسمت چهارم برنامه ویدئویی آموزش زبان VHDL برای شما مفید بود؟
لطفا نظرتان را در مورد این برنامه در پایین همین پست با دیگران به اشتراک بگذارید. همچنین با کلیک روی هر کدام از دکمههای اشتراک گذاری ابتدای این مطلب و به اشتراکگذاری آن در شبکههای اجتماعی میتوانید افراد بیشتری را در یادگیری این مطالب سهیم کنید.
با تشکر از آموزش عالی شما.
من برای انجام پروژه ای احتیاج به تعریف یک خروجی با طول متغیر دارم آیا این امکان وجود دارد؟ چگونه؟
متشکر
فکر میکنم با generic می تونید این کار رو بکنید.
اگر هم جواب سوالتون رو پیدا کردین، لطفا به اشتراک بذارید تا من هم یاد بگیرم.
اکر هم از همین generic استفاده کردین، میشه بیشتر در مورد این خورجی تون توضیح بدین ؟
با درود آموزش بسیار عالی، جامع و خودآموز بود. سپاس فراوان.
سلام،
خوشحالم که این آموزش برای شما مفید بوده است.
موفق باشید.