آموزش FPGA : قسمت نهم

آموزش FPGA : قسمت نهم

ساختار شرطی if; در قسمت هشتم از مجموعه آموزشی FPGA با مدارات ترتیبی در محیط Sequential آشنا شدیم. عناصر پایه سازنده مدارات ترتیبی را شناختیم و به طور مفصل بررسی کردیم که در محیط ترتیبی، ارجاعات چگونه انجام می‌گیرند.

در این قسمت با ساختار شرطی if در محیط ترتیبی آشنا خواهیم شد، و به دو روش مختلف یک مالتی‌پلکسر 2 به 1 را توصیف خواهیم کرد. در همین حین نکات زیادی را در رابطه با محیط ترتیبی و نحوه کدنویسی فرا خواهیم گرفت.

توجه داشته باشید که مالتی‌پلکسر ذاتا یک مدار ترکیبی است، و شاید با خودتان بگویید چرا مداری که ذاتا ترکیبی است را در محیط ترتیبی توصیف می‌کنیم؟ بله، اصولا نباید مداری که ذاتا ترکیبی است را در محیط ترتیبی توصیف کرد، ولی ما برای آشنایی هرچه بیشتر با محیط ترتیبی، در ابتدا بعضی از مدارات ترکیبی که قبلا توصیف کرده بودیم را در این محیط توصیف می‌کنیم. اما در نهایت کاری که ما خواهیم کرد، هر مداری را در جای خود توصیف کرده و تا حد امکان به پیشنهاد شرکت زایلینکس، تمامی مدارات را از نوع ترتیبی سنکرون طراحی می‌کنیم.

در قسمت هفتم تعریفی از مالتی‌پلکسر ارائه دادیم و شما به خوبی با عملکرد و ساختار این مدار آشنا هستید. اگر به خاطر داشته باشید در آن‌جا، مالتی‌پلکسر را با استفاده از ساختار ارجاع انتخابی در محیط ترکیبی، توصیف کردیم. اما در این قسمت می‌خواهیم همان عملکرد را با استفاده از ساختار شرطی if توصیف کنیم. ساختار شرطی if، پرکاربرد‌ترین و قابل انعطاف‌ترین ساختار شرطی زبان VHDL می‌باشد. در قسمت‌های آتی با توجه به نحوه پیاده‌سازی ساختارهای شرطی درون FPGA و همچنین مقایسه‌ای که برای این ساختارها ارائه خواهیم داد، شما متوجه خواهید شد که چرا ساختار شرطی if، پرکاربرد‌ترین و قابل انعطاف‌ترین ساختار شرطی می‌باشد.

قبلا، در قسمت ششم گفتیم که در ساختار ارجاع شرطی در محیط Concurrent، شرط‌ها به صورت ذاتی و از لحاظ ساختاری، اولویت‌دار هستند. ساختار if نیز از همین قاعده پیروی می‌کند و شرط‌ها دارای اولویت هستند، بدین صورت که شرط‌ها به ترتیب قرار گرفتن در این ساختار مورد بررسی قرار می‌گیرند و اگر یکی از شرط‌ها برقرار شد، از شرط‌های دیگر صرف‌نظر می‌شود و این شرط‌ها مورد بررسی قرار نمی‌گیرند.

به توصیف مالتی‌پلکسر 2 به 1 با استفاده از ساختار شرطی if در کد توجه کنید:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity MUX is
    Port (
I0 : in   STD_LOGIC;
I1 : in   STD_LOGIC;
S : in   STD_LOGIC;
Y : out   STD_LOGIC
);
end MUX;
 
architecture Behavioral of MUX is
 
begin
 
process(I0,I1,S)
begin
 
if(S = '0') then
Y <= I0;
else
Y <= I1;
end if;
 
end process;
 
 
end Behavioral;

در لیست حساسیت سیگنال‌های ورودی و همچنین سیگنال خط فرمان قرار می‌گیرند، که با تغییر هر کدام از آن‌ها process فعال، و ارجاعات انجام می‌شوند. در ادامه ساختار شرطی if را به کار برده‌ایم، به این صورت که هرگاه خط فرمان مقدارش ‘0’ باشد وردی اول به خروجی منتقل می‌شود در غیر این‌صورت، ورودی دوم به خروجی منتقل خواهد شد.

اما روشی دیگر برای توصیف همین کد نیز وجود دارد که معمولا کدنویسان حرفه‌ای به این سبک کد می‌نویسند. به کد زیر توجه کنید:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity MUX is
    Port (
I0 : in   STD_LOGIC;
I1 : in   STD_LOGIC;
S : in   STD_LOGIC;
Y : out   STD_LOGIC
);
end MUX;
 
architecture Behavioral of MUX is
 
begin
 
process(I0,I1,S)
begin
 
Y <= I1;
if(S = '0') then
Y <= I0;
end if;
 
end process;
 
 
end Behavioral;

قبل از هر توضیحی، به این نکته توجه کنید که هر دو کد نوشته شده دقیقا یک عملکرد را توصیف می‌کنند و در نهایت نیز هر دو کد، یک سخت‌افزار واحد را در درون FPGA می‌سازند. پس تنها تفاوت این دو کد در ظاهر می‌باشد و هیچ تفاوت دیگری ندارند.

اگر توجه کنید در کد دوم، عبارت ارجاعی که بعد از else در کد اول آورده شد را برداشتیم و به قبل از if انتقال دادیم، و همانطور که گفتیم با این تغییر خطوط، عملکرد یکسان است. نحوه‌ی کار به این صورت است که می‌گوییم تحت هر شرایطی I1 به Y ارجاع داده شود، مگر اینکه S برابر با ‘0’ باشد. و این دقیقا همان عملکرد کد اول را دارد. شما به این صورت در نظر بگیرید، تا زمانی که می‌توانیم کدمان را به صورت if_then بنویسیم، هیچ لزومی ندارد که از if_then_else استفاده کنیم.

به صورت کلی در زبان VHDL جابه‌جایی خطوط در محیط Sequential هیچ تاثیر و تغییری در عملکرد کد ایجاد نخواهد کرد، چون تمامی ارجاعات همزمان باهم رخ می‌دهند و منطقا اینکه کدام خط ارجاع را اول بنویسیم، هیچ تاثیری در عملکرد نخواهد داشت.

اما حالت‌هایی وجود دارند که از این قاعده مستثنا هستند و تغییر یا جابه‌جایی خطوط باعث تغییر عملکرد خواهند شد. زمانی که خودم در حال یادگیری FPGA بودم و هنوز کدنویسی اصولی را نمی‌دانستم و همچنین فرق زبان برنامه‌نویسی با زبان توصیف سخت‌افزار را به خوبی تشخیص نمی‌دادم به حالت‌هایی برخورد کردم که جابه‌جایی خطوط می‌تواند باعث تغییر عملکرد شود. در زیر به دو حالت از این حالت‌ها اشاره خواهیم کرد:

  • جابه‌جایی خطوطِ ساختار‌های شرطی
  • جابه‌جایی دو یا چندین خط ارجاع، وقتی که در همه‌ی این ارجاعات سیگنال‎‌های مختلفی به یک سیگنال واحد ارجاع داده شوند (به عبارتی دیگر در سمت چپ همه‌ی ارجاعات یک سیگنال واحد وجود داشته باشد.)

خب همانطور که می‌دانید در ساختارهای شرطی، چون شرط‌ها داری اولویت هستند پس جابه‌جایی خطوط می‌تواند عملکرد را تغییر بدهد. البته ما بعضی اوقات با توجه به همین عملکرد اولویت‌دار بودن شرط‌ها، مداراتی که واقعا در ذات خود دارای اولویت هستند را به نحو خوبی توصیف می‌کنیم. در دیجیتال مداراتی وجود دارند که با دریافت ورودی‌های نامعتبر، عملکرد مدار صحیح نمی‌باشد و به احتمال زیاد در خروجی دیتای موردنظر را دریافت نکنیم، البته منطقی است که خروجی نامعتبر و ناشناخته‌ای دریافت کنیم چون ورودی پیش‌بینی نشده‌ای به مدار اعمال کردیم. همه‌ی این کارها نیز با زبان VHDL قابل انجام است، در قسمت‌های بعد مثال‌هایی خواهیم داشت که این موضوع را به خوبی پوشش می‌دهد.

ما قبلا گفتیم که جابه‌جایی ارجاعات در زبان VHDL تغییری در عملکرد ندارد، چون همه‌ی ارجاعات همزمان باهم انجام می‌شوند. اما حالتی استثنا وجود دارد. برای درک بیشتر موضوع ابتدا به کد زیر توجه کنید:

فرض کنید کد بالا در محیط ترتیبی نوشته شد، و طبق اصولی که تا الان بیان کردیم، می‌دانیم که هر دو ارجاع باید همزمان باهم انجام شوند. حال اگر قرار باشد هر دو ارجاع همزمان رخ بدهند، مقدار B یا C به A ارجاع داده می‌شود؟ چون سیگنال A در یک لحظه نمی‌تواند هم مقدار B و هم مقدار C را به خود بگیرد!

این دقیقا همان حالت استثنا است و در جواب می‌توان گفت که در زبان VHDL اگر دو یا چندین ارجاع مختلف به یک سیگنال داشته باشیم (در کد بالا دو ارجاع به سیگنال A) همیشه آخرین ارجاع در نظر گرفته می‌شود.

اکنون کد زیر را در نظر بگیرید:

اگر شما کد اول را در محیط ترتیبی بنویسید، ارجاع A <= C انجام خواهد گرفت، و اگر کد دوم را در محیط ترتیبی بنویسید، ارجاع A <= B انجام خواهد گرفت. پس نتیجه بسیار متفاوت خواهد بود که شما وقتی به یک سیگنال واحد چندین ارجاع مختلف دارید کدام حالت را انتخاب کنید.

شاید از خودتان بپرسید وقتی فقط آخرین ارجاع در نظر گرفته می‌شود، پس تکلیف بقیه ارجاعات چیست؟ بقیه ارجاعات قبل از مرحله سنتز توسط نرم‌افزار حذف می‌شوند و از دید نرم‌افزار بی‌اثر هستند.

البته این توضیحات داده شده است تا شما مفاهیم را به خوبی درک کنید، وگرنه شما هم پس از مدتی کدنویسی درک خواهید کرد که چرا چندین ارجاع مختلف در محیط ترتیبی به یک سیگنال، بدون استفاده از ساختارهای شرطی، با ذات سخت‌افزار در تناقض خواهد بود.

در قسمت دهم انکودرهای اولویت‌دار را با استفاده از اولویت‌دار بودن شرط‌ها، در ساختارهای شرطی توصیف خواهیم کرد .

درباره نویسنده

نویسنده و طراح الکترونیکا هستم . سوالی داشتید در کامنت ها یا پیج های اینستاگرام و تلگرام سایت بپرسید .