for
در قسمت هجدهم از مجموعه آموزشی FPGA با شیفت رجیستر آشنا شدیم و مفصلا به تعریف آن پرداختیم، ساختارهای مختلف آنرا باهم دیدیدم، همچنین عملکرد انواع شیفت رجیسترها را بررسیکردیم و آنها را با رجیسترها مقایسهکردیم. درنهایت هم یک نوع از آن شیفت رجیسترها را یکبار با شیفت به راست و بار دیگر با شیفت به چپ بااستفادهاز کد VHDL توصیفکردیم. اما اگر میخواستیم عرض بیت شیفت رجیستر را افزایشبدهیم با یک مشکل جدی روبهرو بودیم، و باید تعداد خطوط کدی که مینوشتیم بیشتر و بیشتر میشد که این موضوع برای شیفت رجیسترهایی با تعداد بیت زیاد اذیتکننده است. چندینراه برای اینکه بتوانیم این مشکل را هموار کنیم وجود دارد یک راه استفادهاز عملگرهاست، اما چون هنوز با عملگرها در زبان VHDL آشنا نیستیم نمیتوانیم از آنها استفادهکنیم. شما بعدا که با این عملگرها آشنا شدید، میتوانید خودتان کد موردنظر را بنویسید. راهدیگر استفادهاز ساختار for در زبان VHDL میباشد که ابتدا باید با این ساختار آشنا شویم و پساز اینکه با عملکرد این ساختار آشنا شدیم کدهای قسمتقبل را با این ساختار توصیفکنیم.
ساختار for در زبان VHDL
اگر قبلا با زبانهای برنامهنویسی دستوپنجه نرم کردهباشید به احتمالزیاد با for آشنا هستید. ما نیز قصد نداریم که به تشریح حلقهها و انواع آنها بپردازیم بلکه توضیحاتی مختصر میدهیم تا هم یادآوری شود و هم بتوانیم ادامه صحبتمان را بهتر ارائهبدهیم تا موضوع بهخوبی تفهیم شود. مثلا اگر میخواستیم در خانههای یک آرایه بنویسیم دو راه وجود داشت، یک راه اینکه بااستفادهاز اندیس آن آرایه در هر خط کد مقادیری را به خانههای آرایه اختصاص بدهیم که این کار اگر تعداد خانههای آرایه زیاد باشد کاری حوصلهبر و وقتگیر است. راه دیگر این بود که بااستفادهاز حلقه for و تعیین شرطی متناسب با خانههای آرایه، فقط با چند خط در خانههای آرایه بنویسیم که راهی معقولتر و به نسبت خیلی راحتتر است. ما نیز قصد داریم که با همین ایده کدهای جلسه قبل را بهینهتر کنیم و تا هر مقدار که بخواهیم با تغییراتی بسیارکوچکی عرض بیت شیفت رجیستر را افزایشبدهیم. برای دسترسی به الگوی ساختار for در زبان VHDL میتوانیم همانند تصویر زیر در نرمافزار ISE، ابتدا روی علامت لامپ روشن کلیککنید و سپس طبق تصویر، For Loop را از دسته Loops انتخابکنید تا به الگویی که در ادامه کد آن آورده میشود برسید.
for <variable_name> in <lower_limit> to <upper_limit> loop <statement>; <statement>; end loop;
در کد بالا بهجای variable_name، باید از یک اندیس استفادهکنیم که عمل شمارش را برای ما انجام میدهد.
به این دلیل مشخصا اسم اندیس را بهکار میبریم و نمیگوییم متغیر یا سیگنال، چون که قرار نیست variable_name در ابتدای کد بهعنوان سیگنال یا متغیر تعریفشود و بعد در ساختار For Loop از آن استفادهکنیم، فقط و فقط بهجای variable_name یک اندیس قرار میدهیم و در هیچ کجای کد این اندیس نه تعریف میشود و نه مقداردهی.
حال شاید برایتان سوال پیشآمدهباشد که در زبانهای برنامهنویسی ما اندیسها یا همان شمارندههایی که در حلقهها بهکار میبردیم را باید از قبل بهعنوان متغیر تعریف میکردیم، اما چرا اینجا اینکار را نمیکنیم؟ بهصورت خیلیخلاصه جواب این سوال برمیگردد به ساختار FPGA و CPU و کد نهایی که برای FPGA و CPU تولید میشود، اما چون این مبحث از حوصلهی این مقاله خارج است، پیداکردن پاسخ را برعهده خودتان میگذاریم.
معمولا اسم این اندیس را i میگذاریم و بعدا در کد اصلی از همین اندیس کمک خواهیمگرفت. بهجای lower_limit از یک عدد صحیح مثبت بهعنوان کران پایین اندیس i و به جای upper_limit از یک عدد صحیح مثبت بهعنوان کران بالای اندیس i استفاده میکنیم. statementها هم همان ارجاعات هستند. در ادامه کدهای قسمت هجدهم را با ساختار for بازنویسی خواهیمکرد تا موضوعات بیانشده را بهخوبی درککنید. کد زیر همان شیفت رجیستری است که در قسمت قبل عمل شیفت به راست را انجام میداد:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Shift_Register is Port ( Input : in STD_LOGIC; Clock : in STD_LOGIC; Output : out unsigned (7 downto 0) ); end Shift_Register; architecture Behavioral of Shift_Register is signal Middle : unsigned (7 downto 0) := (others =>'0'); begin Output <= Middle; process(clock) begin if rising_edge(clock) then Middle(7) <= Input; for i in 0 to 6 loop Middle(i) <= Middle(i+1); end loop; end if; end process; end Behavioral;
کد زیر همان شیفت رجیستری است که در قسمتقبل عمل شیفت به چپ را انجام میداد:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Shift_Register is Port ( Input : in STD_LOGIC; Clock : in STD_LOGIC; Output : out unsigned (7 downto 0) ); end Shift_Register; architecture Behavioral of Shift_Register is signal Middle : unsigned (7 downto 0) := (others =>'0'); begin Output <= Middle; process(clock) begin if rising_edge(clock) then Middle(0) <= Input; for i in 0 to 6 loop Middle(i+1) <= Middle(i); end loop; end if; end process; end Behavioral;
کدهای بالا را بااستفادهاز generic میتوانید بهینهتر نیز بنویسید که این موضوع را چون قبلا به آن پرداختیم بهعهدهخودتان میگذاریم. در قسمت بیستم درمورد عملگرها صحبتخواهیمکرد.
منبع:سیسوگ