در قسمت دوم از مجموعه آموزش زبان VHDL با نحوه توصیف و پیادهسازی مدارات ترکیبی به کمک زبان VHDL آشنا میشوید. زبان VHDL امکان توصیف انواع مدارات منطقی ترکیبی و ترتیبی را دارا است و به کمک ساختارها و عبارات توصیفی موجود در آن میتوان از سادهترین تا پیچیدهترین مدارات را طراحی نمود.
More...
در این برنامه با ساختار ارجاع شرطی یا Selected signal assignment آشنا میشوید. همچنین با یکی از تکنیکهای کدنویسی آشنا میشوید که در اکثر پیادهسازیها به کمک شما خواهد آمد.
اگر هنوز قسمت اول برنامه آموزش زبان VHDL را ندیدهاید، پیشنهاد میکنم قبل از دیدن این قسمت حتما آن را ببینید، چون درک مطالب مطرح شده در قسمت دوم، تا حد زیادی مستلزم آشنایی با موضوعات قسمت اول این برنامه است.
آموزش زبان VHDL – قسمت اول
ویدئو یا متن؟
محتوای این برنامه آموزشی، به دو صورت ویدئو و متن آماده شده است. اگر علاقمند به یادگیری این مطلب به صورت ویدئویی هستید، ویدئوی زیر را ببینید و اگر ترجیح میدهید آن را به صورت متن مطالعه کنید، ادامه این مطلب را بخوانید.
برای دانلود نسخه با کیفیت این ویدئو، روی دکمه زیر کلیک کنید:
مرور کلی مطالب مقالهی قبل
ابتدا، مطالب مقالهی قبل را مرور میکنیم:
در مقالهی قبلی گفتیم که مدارات منطقی، به دو گروه ترکیبی و ترتیبی تقسیم میشوند.
همچنین، میتوانید به کمک زبانهای توصیف سختافزاری، هر کدام از این انواع مدارات منطقی را، توصیف و پیادهسازی کنید.
در زبان توصیف سختافزاری VHDL، میتوانید مدارات ترکیبی را در بخشی به نام محیط Concurrent، توصیف کنید. همچنین، مدارات ترتیبی در محیط Process توصیف میشوند.
طراحی و توصیف مدارات منطقی ترکیبی، به کمک زبان VHDL
در این مقاله، قصد دارم راجع به طراحی و توصیف مدارات منطقی ترکیبی به کمک زبان VHDL صحبت کنم.
برای توصیف مدارات ترکیبی به کمک زبان VHDL و در محیط Concurrent، دو عبارت ارجاع وجود دارد:
یکی از آنها، عبارت ارجاع انتخابی یا Selected Signal Assignment است و دیگری عبارت ارجاع شرطی یا Conditional Signal Assignment است.
در این مقاله، راجع به عبارت ارجاع انتخابی صحبت میکنم.
عبارت ارجاع انتخابی
به کمک پیادهسازی یک مثال، ارجاع انتخابی یا Selected Signal Assignment را به طور کامل توضیح خواهم داد.
پیادهسازی یک مالتیپلکسر به کمک ارجاع انتخابی
احتمالاً، از درس مدار منطقی، قطعهی مالتیپلکسر را به یاد دارید؛ این قطعه، یک قطعهی ترکیبی محسوب میشود.
در مجموعهی مدارات منطقی، مالتیپلکسرها، تعدادی سیگنال ورودی، یک سیگنال خروجی و چند خط کنترلی دارند؛ با توجه به مقداری که در خطوط کنترلی قرار داده میشود، یکی از سیگنالهای ورودی به خروجی منتقل میشود.
مثلاً، در مالتیپلکسر چهار به یک، که در شکل زیر میبینید، چهار ورودی A تا D و یک خروجی F داریم.
از آنجا که چهار ورودی داریم، باید دو بیت کنترلی داشته باشیم؛ پس به دو ورودی کنترلی (یا دو ورودی انتخاب) نیاز داریم؛ که اینجا، آنها را S0 و S1 نامگذاری کردهایم.
با توجه به عددی که در مقابل این ورودی کنترلی قرار داده میشود، یکی از ورودیها، به خروجی منتقل خواهد شد.
شکل زیر، جدول صحت این مالتیپلکسر را نشان میدهد:
همانطور که مشاهده میکنید، اگر در ورودی S0 و S1، مقدار صفر قرار داده شود، ورودی A به خروجی F منتقل میشود.
اگر در ورودی S0 و S1، مقدار یک قرار داده شود، B به خروجی F منتقل میشود.
اگر در این ورودی، مقدار دو قرار داده شود، C به خروجی F متصل میشود.
و در نهایت، اگر مقدار سه، در ورودی S0 و S1 قرار داده شود، ورودی D به خروجی F منتقل میشود.
اکنون به این مسئله میپردازیم که در زبان VHDL و به کمک ساختار Selected Signal Assignment، چگونه میتوانیم این مالتیپلکسر را تعریف کنیم.
همانطور که در مقالهیهای قبلی گفته شد، برای تعریف یک ماژول در زبان VHDL، دو بخش اصلی داریم:
بخش اول، Entity است که میتوانیم پورتهای ورودی و خروجی را در آن مشخص کنیم.
بخش دوم، بخش Architecture است که میتوانیم مدار مورد نظرمان را در آن توصیف کنیم.
البته، یک بخش ابتدایی هم وجود دارد که کتابخانهی IEEE را در آن فراخوانی میکنیم.
در واقع، تمام ساختارهایی که در کدنویسی با زبان VHDL استفاده میکنیم، در کتابخانه IEEE، قرار داده شدهاند.
شما همیشه باید در اولین خط کد VHDL، عبارت زیر، را قرار دهید.
Library IEEE;
به این ترتیب، شما Library یا کتابخانهی IEEE را فراخوانی میکنید.
این Library، ازپکیجهای مختلفی تشکیل شده، که چند مورد از آنها پرکاربرد هستند.
یکی از این پکیجهایی که همیشه باید در ابتدای کدهای شما فراخوانی شود، پکیج STD_Logic_1164 است، که برای صدا کردن آن، کدی مانند زیر مینویسیم:
use IEEE.STD_LOGIC_1164.ALL;
ابتدا، کلمهی کلیدی use را مینویسیم، سپس نام Library را مینویسیم (که در اینجا IEEE است)، سپس یک نقطه قرار میدهیم و اسم پکیج را مینویسیم. هر پکیج قابلیتهای مختلفی دارد؛ برای فراخوانی تمام قابلیتهای آن، در انتهای سطر، از عبارت All استفاده میکنیم.
پس در ابتدای کد، این دو خط را مینویسیم:
Library IEEE; use IEEE.STD_LOGIC_1164.ALL;
اولین کار برای توصیف مالتیپلکسر، توصیف ورودی-خروجیهای آن، به کمک ساختار Entity است؛ چون این مالتیپلکسر یک مالتیپلکسر چهار به یک است، مانند کد زیر، چهار ورودی و یک خروجی تعریف میکنیم.
entity MUX4to1 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;
مُد پورتهای ورودی را Input قرار میدهیم و نوع آنها را STD_Logic انتخاب میکنیم.
نام خروجی را F میگذاریم و مُد آن را از نوع out تعریف میکنیم؛ چون خروجی، تکبیتی است، از نوع STD_Logic استفاده میکنیم.
اما در مورد سیگنال کنترلی S، چون سیگنال دو بیتی است، ما دو راه داریم:
اول اینکه، دو سیگنال تکبیتی با نوع STD_Logic تعریف کنیم.
و روش دوم، روشی است که در کد بالا میبینید؛ به جای استفاده از دو سیگنال تکبیتی، از یک سیگنال دو بیتی استفاده میکنیم.
برای این کار، از یک نوع جدید، به نام STD_Logic_Vector استفاده میکنیم.
STD_Logic_Vector، مواقعی استفاده میشود که شما بخواهید سیگنالهایی با عرض بیش از یک بیت تعریف کنید.
برای تعریف چنین سیگنالی، از عبارت STD_Logic_Vector استفاده میکنیم و در ادامه، عرض آن سیگنال را مشخص میکنیم.
مثلاً، در اینجا چون ما یک سیگنال دو بیتی لازم داشتیم، کد زیر را نوشتهایم:
S : in std_logic_vector(1 downto 0);
معنی این عبارت این است که ما یک سیگنال دو بیتی داریم، که اندیس این دو بیت، یک و صفر است. همانطور که گفتم، میخواهیم برای تعریف مالتیپلکسر، از ساختار Selected Signal Assignment استفاده کنیم.
تعریف یک مالتیپلکسر چهار به یک، با استفاده از ساختار Selected Signal Assignment را، در کد زیر میبینید:
with S select F <= A when "00", B when "01", C when "10", D when others;
عبارت Selected Signal Assignment، با کلمهی کلیدی with شروع میشود. پس از آن، سیگنالی که میخواهیم روی آن شرط بگذاریم را مینویسیم که این سیگنال در مسئلهی ما، سیگنال S است.
سپس، کلمهی کلیدی Selected را مینویسیم.
در خط بعد، سیگنال A را به سیگنال F، ارجاع میدهیم. در ادامهی این خط، کلمهی کلیدی when و "00" نوشته شده است؛ منظور، این است که وقتی سیگنال شرط (که در این مثال S است)، مساوی "00" شد، ورودی A به خروجی F، Assign شود.
در خط بعدی میگوییم، وقتی که سیگنال کنترلی S برابر با "01" شد، B به F، Assign شود.
در خط بعدی نیز میگوییم، وقتی که سیگنال S، برابر با 01"" شد، C به F، Assign شود.
و در انتها، نوشتهایم که در غیر این صورت، سیگنال D، به F اعمال شود.
عبارت "when others"، به معنی حالتهای دیگر است.
بعد از اینکه کد را نوشتیم، برای اینکه مطمئن شویم که از نظر Syntax مشکلی ندارد، مطابق شکل زیر، روی فایل کد، کلیک میکنیم و سپس در پایین صفحه، در قسمت Synthesize-XST، روی عبارت Check Syntax دبل-کلیک میکنیم.
نرمافزار ISE، کد را بررسی میکند که آیا از نظر Syntax و استفاده از عبارات، مشکلی دارد یا خیر.
اگر مطابق شکل زیر، عبارت Process "check syntax" completed successfully را دیدید، یعنی مشکلی در سینتکس کد وجود ندارد.
اگر مشکلی وجود داشته باشد، نرمافزار خطاها را در پایین صفحه به شما نشان میدهد و میتوانید این خطاها را یکی یکی مطالعه کنید و آنها را برطرف کنید.
برای آشنایی بیشتر با عبارت ارجاع انتخابی، و همچنین یادگیری نکاتی از کدنویسی، مثال مالتیپلکسر را کمی تغییر میدهیم.
پیادهسازی یک مالتیپلکسر به همراه سیگنال Enable، به کمک ارجاع انتخابی
این بار، به جز ورودیهای کنترلی S0 و S1، یک ورودی کنترلی جدید به نام سیگنال Enable اضافه میکنیم و آن را با En نشان میدهیم.
طبق جدول صحت زیر، اگر مقدار En یا سیگنال Enable، یک باشد، عملکرد مالتیپلکسر مشابه قبل خواهد بود؛ یعنی، با توجه به مقدار سیگنال کنترلی S، یکی از ورودیهای A تا D به خروجی متصل میشود.
اما اگر سیگنال Enable برابر با صفر باشد، بدون توجه به مقدار S0 و S1، سیگنال خروجی برابر با صفر میشود.
حالا ببینیم که چطور میتوانیم این مدار را به کمک ساختار Selected Signal Assignment پیادهسازی کنیم؟
کد زیر، پیادهسازی این مدار را نشان میدهد:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; entity Example_03_With_Select_MUX4to1 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); En : in std_logic; F : out std_logic ); end Example_03_With_Select_MUX4to1; architecture Behavioral of Example_03_With_Select_MUX4to1 is signal SEn : std_logic_vector(2 downto 0) := (others=>'0'); begin SEn <= S & En; with SEn select f <= A when "001", B when "011", C when "101", D when "111", '0' when others; end Behavioral;
قسمت Entity این کد، تفاوت زیادی با حالت قبلی ندارد؛ به جز اینکه سیگنال Enable به آن اضافه شده است؛ چون این سیگنال، تک بیتی است، از تایپ STD_Logic استفاده میکنیم.
تفاوت این کد با کد قبلی این است که برای انتخاب سیگنال خروجی، به جز سیگنال S، سیگنال Enable هم دخیل است.
بنابراین، وقتی میخواهیم از عبارت Selected Signal Assignment استفاده کنیم، باید به نحوی، هم سیگنال S و هم سیگنال En را دخیل کنیم.
اما عبارت Selected Signal Assignment، فقط میتواند یک سیگنال انتخاب، داشته باشد.
فکر میکنید راه حل چیست؟
برای این کار، میتوانید یک سیگنال میانی تعریف کنید و سیگنال S و En را، به آن سیگنال ارجاع دهید. سپس، آن سیگنال را به عنوان سیگنال انتخاب، در عبارت Selected Signal Assignment قرار دهید.
برای این کار، باید با یک عملگر جدید آشنا شویم.
عملگر Concatenation در زبان VHDL
در زبان VHDL، یک عملگر بسیار پرکاربرد به نام عملگر Concatenation وجود دارد.
این عملگر را در زبان VHDL، با علامت & نشان میدهند.
برای اینکه این عملگر را خوب بشناسید، فرض کنید در کد VHDL، دو رجیستر به نام A و B تعریف کردهایم؛ رجیستر A، سه بیتی و رجیستر B، پنج بیتی است.
برای توضیح بهتر موضوع، بیتهای رجیسترهای A و B را به صورت زیر نامگذاری کردهام:
اگر از عبارت ارجاع زیر استفاده کنیم:
C <= A&B;
مقداری که به رجیستر C، ارجاع میشود برابر با شکل زیر خواهد بود:
به عبارت دیگر، رجیستر A و B در کنار هم قرار داده شده و به رجیستر C، ارجاع شدهاند.
باید دقت کنید که همواره، عرض رجیستر C، یعنی رجیستری که سمت چپ عبارت ارجاع است، برابر با جمع عرض بیت رجیسترهای سمت راست ارجاع (رجیستر A و B) باشد.
در این مثال، رجیستر A سه بیت و رجیستر B، پنج بیت دارد که جمعاً برابر با هشت بیت میشود. بنابراین، ما رجیستر C را هشت بیتی انتخاب کردهایم.
شما میتوانید به کمک عملگر Concatenation، چند سیگنال را کنار هم قرار داده و به یک سیگنال جدید ارجاع دهید.
حال ببینیم که این قابلیت، چطور میتواند در تبدیل دو سیگنال کنترلی S و En به یک سیگنال، به ما کمک کند؛ بدین ترتیب، میتوانیم این تک سیگنال را، در ساختار Selected Signal Assignment به کار ببریم. برای این کار، ابتدا باید درون FPGA، یک سیگنال میانی یا یک رجیستر تعریف کنیم.
همانطور که در مقالهی قبلی گفتم، در زبان VHDL، برای اینکه بتوانیم سیگنالها یا رجیسترها را تعریف کنیم، از فضای بین Architecture تا کلمهی کلیدی Begin استفاده میکنیم.
این فضا، محل تعریف سیگنالها و ماژولها است.
برای اینکه یک سیگنال را در این فضا تعریف کنید، کافی است، مطابق با کد زیر، از کلمهی کلیدی Signal استفاده کنید:
signal SEn : std_logic_vector(2 downto 0) := (others=>'0');
پس از آن، نام سیگنال مورد نظرتان را بنویسید که در اینجا ما نام آن را SEn گذاشتهایم؛ چون میخواهیم دو سیگنال کنترلی S و Enable را ترکیب کنیم.
سپس، یک علامت ":"، و بعد از آن، باید نوع سیگنال را بنویسیم.
چون میخواهیم یک سیگنال تکبیتی (سیگنال Enable) را به یک سیگنال دو بیتی (سیگنال S) متصل کنیم، باید یک سیگنال سه بیتی و از نوع برداری استفاده کنیم؛ که ما در اینجا، از نوع std_logic_vector استفاده کردهایم.
هنگامی که شما سیگنالی را تعریف میکنید، میتوانید در لحظهی تعریف، یک مقدار اولیه به آن سیگنال دهید.
برای این کار، از علامت := استفاده میشود. بعد از این علامت، درون دو گیومه، مقدار مورد نظر را مینویسید که من مقدار صفر را به عنوان مقدار اولیهی سیگنال مشخص کردهام.
بعد از Begin آرکیتکچر، که محل تعریف مدار است (محیط Concurrent)، به صورت کد زیر، سیگنال S و سیگنال Enable را، به کمک عملگر Concatenation به هم متصل میکنیم و به سیگنال SEn منتقل میکنیم:
SEn <= S & En;
اکنون، سیگنال SEn، یک سیگنال سه بیتی است که بیت سبک آن، سیگنال Enable، و دو بیت سنگینترش سیگنال S است.
همانطور که گفتم، ساختار Selected Signal Assignment، فقط میتواند یک سیگنال شرط داشته باشد؛ پس، اکنون میتوانم سیگنال SEn را در محل سیگنال شرط قرار دهم.
اما میدانم که در دل سیگنال SEn، هر دو سیگنال S و Enable قرار دارند.
اکنون مطابق کد زیر، شرطها را بازنویسی میکنم:
with SEn select f <= A when "001", B when "011", C when "101", D when "111", '0' when others;
سطر اول، معادل این است که اگر سیگنال SEn، برابر با "001" باشد، سیگنال A به F منتقل شود؛ در واقع، اگر Enable برابر با یک و S برابر "00" باشد، A را به خروجی منتقل میکند.
سطر دوم، معادل این است که اگر Enable برابر با یک و S برابر "01" باشد، B را به خروجی منتقل میکند. و برای سطر سوم و چهارم نیز به همین ترتیب است.
اما حالتهای دیگر، (یعنی when others)، حالتهایی هستند که Enable برابر با 1 نیست؛ در این حالتها، برای ما مهم نیست که مقدار کنترلی S چه مقداری است؛ بنابراین، مینویسیم در صورتی که مقدار Enable برابر با 1 نبود، 0 را به خروجی منتقل کن.
دقت کنید که وقتی شما میخواهید به یک سیگنال، مقداری را ارجاع دهید، اگر این مقدار تکبیتی است، آن را داخل دو علامت ' (Single Quotation) می نویسیم و اگر این مقدار بیش از یک بیت است، آن را بین دو علامت گیومه (Double Quotation) مینویسیم.
به این ترتیب، ما در این کد، به کمک زبان VHDL، کد مالتیپلکسر چهار به یک، با سیگنال ورودی فعالساز (Enable) را توصیف کردیم.
امیدوارم از خواندن این مقاله هم لذت برده باشید و بتوانید از نکات یاد گرفته شده، در انجام پروژههایتان استفاده کنید.
آیا قسمت دوم برنامه ویدئویی آموزش زبان VHDL برای شما مفید بود؟
لطفا نظرتان را در مورد این برنامه در پایین همین پست با دیگران به اشتراک بگذارید. همچنین با کلیک روی هر کدام از دکمههای اشتراک گذاری ابتدای این مطلب و به اشتراکگذاری آن در شبکههای اجتماعی میتوانید افراد بیشتری را در یادگیری این مطالب سهیم کنید.
اموزش شما اقای ثقفی بسیار مفید و ارزشمند است لطفا ادامه دهید.
ممنون از شما. امیدوارم مطالب و آموزشهای بعدی هم مورد توجه شما قرار گیرند.
سلام خسته نباشید خیلی خیلی ممنون بابت آموزش هاتون فقط اگ این فیلم های آمورش vhdl تون رو سریع تر بر روی سایت قرار دهید لطف میکنید
سلام، ممنون از شما.
در مورد برنامههای ویدئویی لطفا به این نکته توجه داشته باشید که این برنامهها کاملا تولیدی هستند و گردآوری مطالب از منابع دیگر یا کپی آنها نیستند. در نتیجه زمان قابل توجهی برای ساخت با کیفیت هر کدام از آنها صرف میشود.
ba tashakor az zahamte faravane shoma
سلام تشکر از شما کارتون واقعا عالیه و امیدوارم ادامه پیدا کنه…خسته نباشید.
سلام، ممنون از لطف شما.
با سلام و ادب
تشکر فراوان بابت زحمات ارزنده شما در قراردادن این فیلم های کارآمد
سلام،
ممنون از شما. خوشحالم که این برنامهها براتون مفید بوده.
سلام جناب ثقفی
خسته نباشید و ممنون از زحماتتان
من ۵ فایل pdf رو که گذاشته بودید خوندم.
در قسمت اول و توضیح:چرا fpga?
فرمودید که برای کاری که ۵ میلی ثانیه طول میکشه کلاک مدار باید بالا باشه.
برای ۱گیگ چطور محاسبه میکنید؟ تناوب میشه ۱ns
و ۱/۴ اون میشه ۰٫۲۵ نانوثانیه روی یک لبه کلاک
آیا این درست است؟ من میخوام کلاک رو طوری در بیارم که مدت زمان به صدا در آمدن آژیر و پیاده شدن الگوریتم دو و نیم نانوثانیه باشد؟ روی یک لبه کلاک چه فرکانسی؟
۱ghz*.25ns
سلام، ممنون از شما.
سوال شما کمی برای من نامفهوم است. اما مساله کلی این است که شما باید ببینید که برای انجام الگوریتم مورد نظرتون چقدر زمان در اختیار دارید و چه حجمی از محاسبات باید انجام شود.
اگر به این نتیجه رسیدید که به کمک تکنولوژی FPGA پیاده سازی کنید، آنوقت ممکن است مساله کلاک سیستم آنقدر حیاتی نباشد و موازی سازی نقش بیشتری داشته باشد.
بسیار عالی بود.
خیلی قشنگ و جامع توضیح دادین.
آیا میشه اینجا به جای with select از generic استفاده کرد ؟
اگر استفاده از generic امکان پذیر هست، لطفا مختصر راهنمایی کنید.
ببخشید اشتباه شد. اصلا generic ربطی به with select نداره!!!!!
آیا میشه یه mux رو با generic بنویسیم و بعد برای mux با خط enb از generic استفاده کنیم (یعنی generic رو تغییر ش بدیم)؟
سلام،
اگر منظورتون این هست که مقدار generic در حین کار مدار روی FPGA تغییر کند، خیر، امکانپذیر نیست.
موفق باشید.
خسته نباشید
عالی بود
ممنون از شما که در راه گسترش و پیشرفت علم تلاش میکنید
سلام،
خوشحالم که این آموزش برای شما مفید بود.
موفق باشید.
بسیار عالی و روان بود ممنون از لطف شما
خوشحالم که برای شما مفید بوده است.
خیلی لذت بردم