آموزش FPGA : قسمت دهم
در قسمت نهم از مجموعه آموزشی FPGA ساختار شرطی if را تشریح کردیم و با استفاده از توصیف مالتیپلکسر، با بعضی از قابلیتهای این ساختار آشنا شدیم.
در این قسمت قصد داریم با ساختار شرطی if بیشتر آشنا شویم و قابلیتهای دیگر این ساختار را با استفاده از توصیف انکودر اولویتدار شناسایی کنیم.
انکودر
انکودر مداری شناخته شده در دیجیتال میباشد و به احتمال زیاد شما هم به عنوان یک مهندس الکترونیک، که در حال خواندن این مقاله هستید با ماهیت انکودر آشنا هستید. پس به توضیح این مدار نخواهیم پرداخت و فقط برای یادآوری، جدول صحت یک انکودر 2*4 را در زیر برای شما خواهیم آورد. در ادامه همین جدول صحت را با استفاده از زبان VHDL توصیف خوهیم کرد.
در جدول صحت بالا مشاهده میکنید که در هر لحظه فقط یکی از ورودیها میتواند مقدار ‘1’ را داشته باشد. به بیان دیگر انکودر انتظار دارد در هر لحظه فقط یکی از ورودیهایش مقدار ‘1’ را داشته باشد چون در غیر اینصورت مقدار خروجی مدار، آن مقدار موردانتظار ما نخواهد بود و یک خروجی غیرصحیح خواهیم داشت. و همانطور که در قسمت قبل ذکر کردیم در چنین مداراتی یا سازندگان تراشهها، این موارد را پیشبینی و تمهیداتی برای این موارد در نظر میگیرند یا اینکه ما باید حواسمان باشد و ورودی ناشناختهای به مدار اعمال نکنیم.
ما قصد داریم در این قسمت کد انکودر را به نحوی بنویسیم که اگر ورودی ناشناختهای به انکودر اعمال شد، به نحوی طبق خواستهی ما ورودی تصحیح شود. اما چگونه؟
انکودر اولویتدار
حال اگر برحسب اشتباه حالتی به غیر از حالت بیان شده به ورودیها اعمال شود، باید تصحیح صورت گیرد. ما این روند تصحیح شدن را با استفاده از اولویت در بیتهای ورودی هموار میکنیم. این اولویت میتواند سنگینترین بیت، یا سبکترین بیتِ ورودی باشد. ما در این آموزش قصد داریم مبنای اولویت را بیتِ سنگین قرار بدهیم. روند به این صورت است که از بیت سنگین به بیت سبک مقدار بیتها بررسی میشود تا به اولین بیتی برسیم که مقدارش ‘1’ باشد. به مجرد اینکه به اولین بیتی رسیدم که مقدارش ‘1’ است، بقیه بیتها دیگر بررسی نمیشوند و فرض میشود که به جز بیت موردنظر بقیه بیتها مقدارشان ‘0’ است و این روند معادل حالتی است که در هر لحظه فقط یک بیت مقدارش ‘1’ است. به مداری که به واسطه عملیات بالا در زبان VHDL توصیف میشود انکودر اولویتدار میگویند.
مدار انکودر اولویتدار را با استفاده از ساختار شرطی if در زبان VHDL توصیف میکنیم. نحوهی توصیف به این صورت است که اولویت بیتها را با استفاده از اولویتی که در ذات ساختار شرطی if وجود دارد هموار میکنیم.
قبل از توضیحات بیشتر ابتدا به کد زیر توجه کنید:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Encoder is Port ( D : in unsigned (3 downto 0); Q : out unsigned (1 downto 0) ); end Encoder; architecture Behavioral of Encoder is begin process(D) begin if D(3) = '1' then Q <= "11"; elsif D(2) = '1' then Q <= "10"; elsif D(1) = '1' then Q <= "01"; else Q <= "00"; end if; end process; end Behavioral;
در جلسه قبل ساختار if به طور کامل توضیح داده نشد و قول دادیم که در قسمت بعد، که این قسمت باشد ساختار if را به طور کامل و مفصل توضیح بدهیم، اکنون در کد بالا سینتکس و الگوی کلی این ساختار را به طور کامل مشاهده میکنید و عملکرد بدین گونه است که زمانی که process فعال میشود، شرطها با اولویت از بالا به پایین بررسی میشوند تا زمانی که به اولین شرط صحیح برسیم. پس از اینکه به اولین شرط صحیح رسیدیم، بقیه شرطها دیگر بررسی نمیشوند و در نتیجه نهایتا یکی از این ارجاعات انجام خواهد گرفت.
اگر خاطرتان باشد در قسمت نهم ذکر کردیم که اگر در محیط ترتیبی دو یا چندین ارجاع داشته باشیم که در سمت چپ آنها یک سیگنال واحد باشد، فقط آخرین ارجاع در نظر گرفته میشود و بقیهی ارجاعات قبل از مرحله سنتز حذف میشوند. حال شاید از خودتان بپرسید چرا در کد بالا که سمت چپ همهی ارجاعات سیگنال Q قرار دارد، همهی ارجاعات به جز ارجاع آخر، قبل از مرحله سنتز حذف نشدهاند؟ در پاسخ باید بگوییم که اینجا ارجاعات با شروط خاصی انجام میگیرند و موضوع خیلی متفاوت خواهد بود با زمانی که چندین ارجاع به یک سیگنال را در محیط ترتیبی بدون هیچ شرطی بنویسیم.
در این قسمت نیز ما همانند سایر قسمتها در وهلهی اول کدی به صورت مقدماتی نوشتیم، اما اکنون قصد داریم همین کد را کمی بهتر بنویسیم و تغییراتی در کد اولیه ایجاد کنیم.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Encoder is Port ( D : in unsigned (3 downto 0); Q : out unsigned (1 downto 0) ); end Encoder; architecture Behavioral of Encoder is begin process(D) begin Q <= "00"; if D(1) = '1' then Q <= "01"; end if; if D(2) = '1' then Q <= "10"; end if; if D(3) = '1' then Q <= "11"; end if; end process; end Behavioral;
اولین چیزی که در کد بالا توجه شما را جلب میکند اولویتهای نوشتن خطوط ارجاع است، در کد دوم ظاهرا به نظر میرسد که اولویتها را برعکس کردیم. خیر اینگونه نیست، کد اول و کد دوم از لحاظ عملکرد دقیقا یکی هستند. برای درک بیشتر موضوع با دقت به توضیحات زیر توجه کنید.
در ساختار if_then_else (کد اول) شرطها از بالا به پایین بررسی میشوند و هر زمانی که شرطی برقرار شد، شرطهای زیرین دیگر بررسی نمیشوند و همانطور که حدس میزنید اولویت از بالا به پایین است. در نهایت تنها یک ارجاع بیرون آمده از این شرطها وجود دارد. اما در ساختار if_then (کد دوم) شرطها موازی باهم بررسی میشوند (برخلاف کد اول، همهی شرطها بررسی میشوند) و هیچ اولویتی وجود ندارد. در نهایت ممکن است چندین ارجاع مختلف بیرون آمده از شرطها داشته باشیم.
فرض کنید در کد دوم، دو تا از شرطها برقرار باشند، حال دو ارجاع مختلف بیرون آمده از دل این شرطها داریم. هر دوتای این ارجاعات، ارجاع به سیگنال Q هستند، شبیه به این میماند که دو ارجاع به یک سیگنال یکسان، بدون هیچ شرطی در محیط ترتیبی داشته باشیم. و همانطور که از گذشته میدانید آخرین ارجاع انجام خواهد گرفت و ارجاع دیگر بیاثر خواهد بود. پس ما همیشه بالاترین اولویتمان را در آخرین شرط قرار خواهیم داد تا زمانی که قرار است آخرین ارجاع انجام بگیرد، هیچ مشکلی در رعایت اولویتها نباشد و در نهایت انکودر اولویتدار به خوبی توصیف شود.
ساختار شرطی if را به طور کامل بررسی کردیم و هرآنچه نیاز بود شما از کلیات این ساختار بدانید بیان شد. در قسمت یازدهم ساختار شرطی case را بررسی خواهیم کرد.