ما در قسمت دوازدهم تا قسمت شانزدهم از آموزش FPGA حافظههای تکبیتی یا همان فلیپفلاپها را به طور کامل مورد بررسی قرار دادیم و هر آنچه نیاز بود، یا بهتر است بگوییم هر آنچه در رابطه با فلیپفلاپها وجود داشت را به طور کامل بررسی کردیم و همهی پارامترهای یک حافظه تک بیتی را با همدیگر شناختیم.
اکنون در این قسمت قصد داریم که با استفاده از همان فلیپفلاپهایی که با همدیگر شناختیم، حافظههای چند بیتی که اصطلاحا به آنها رجیستر یا ثبات میگویند را توصیف کنیم. شاید دقیقا ندانید که رجیستر چیست یا به چه منظور از آنها استفاده میشود، پس بهتر است توضیحی کوتاه و مختصر در این رابطه داشته باشیم، سپس با استفاده از زبان VHDL یک رجیستر را توصیف کنیم.
Register (ثبات)
معمولا از رجیسترها به عنوان حافظههای چند بیتی یاد میشود و در بعضی از منابع فارسی با نام ثبات نیز شناخته میشوند. رجیسترها میتوانند مقادیر منطقی را در خود ذخیره کنند، این مقادیر منطقی میتوانند شامل داده یا اطلاعات، آدرس، شمارنده و … باشند.
به احتمال زیاد اسم رجیسترها را بیشتر در پردازندهها شنیده باشید، در پردازندهها رجیسترها از قبل ساخته شدند و ما فقط با توجه به عملکرد مورد نطرمان این رجیسترها را مقدار دهی یا تنظیم میکنیم. یکی از پارامترهایی که باعث تمایز پردازندهها میشود، چند بیتی بودن رجیسترهای آنهاست، به عنوان مثال پردازندههای AVR دارای رجیسترهای 8 بیتی و پردازندههای ARM دارای رجیسترهای 32 بیتی هستند.
اما در FPGAها رجیسترها از قبل وجود ندارند (اگرچه در FPGAها، شیفترجیسترها میتوانند جز منابع اختصاصی باشند و از قبل به صورت آماده وجود داشته باشند. در قسمتهای بعدی در رابطه با این موضوع صحبت خواهیم کرد).
در ادامه ما با استفاده از فلیپفلاپها و در کنار هم گذاشتن آنها رجیسترهای 8 بیتی را توصیف خواهیم کرد. برای اینکه بهتر درک کنید رجیسترها چگونه با استفاده از فلیپفلاپها ساخته میشوند، ابتدا به تصویر زیر دقت کنید تا در ادامه کد VHDL آن را بنویسیم.
همانطور که در تصویر بالا مشاهده میکنید برای ساختن رجیستر، چندین فلیپفلاپ را در کنار هم قرار میدهیم به نحوی که کلاک آنها مشترک است و با تغییرات کلاک مقادیر این فلیپفلاپها همزمان تغییر میکنند، اما ورودی هر فلیپفلاپ به صورت جداگانه با تغییرات کلاک به هر فلیپفلاپ اعمال میشود. بدین نحو با استفاده از فلیپفلاپها میتوانیم رجیسترهای موردنظر خود را بسازیم.
در ادامه چون میخواهیم یک رجیستر 8 بیتی را توصیف کنیم، پس باید 8 تا از این فلیپفلاپها را در کنار هم قرار دهیم و سپس به نحوی که گفته شد سیمکشی آنها را انجام دهیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Register_8bit is Port ( D : in unsigned (7 downto 0); Clock : in STD_LOGIC; Reset : in STD_LOGIC; Q : out unsigned (7 downto 0) ); end Register_8bit; architecture Behavioral of Register_8bit is begin process(clock) begin if rising_edge (clock) then Q <= D; if (Reset = '1') then Q <= (others => '0'); end if; end if; end process; end Behavioral; |
حال شاید از خود بپرسید چرا تنها با یک ارجاع ساده توانستیم یک رجیستر 8 بیتی را توصیف کنیم؟ اگر به خاطر داشته باشید قبلا گفته بودیم که اگر به سیگنالی ارجاع داده شود بسته به اینکه آن ارجاع کجا باشد، آن سیگنال میتواند تبدیل به سیم یا رجیستر شود. اگر به سیگنالی در محیط Concurrent ارجاع داده شود آن سیگنال تبدیل به سیم ولی اگر درون process به آن ارجاع داده شود آن سیگنال تبدیل به رجیستر میشود. چون در کد بالا ما درون process و در زیر شرط بالاروندهی کلاک به سیگنال Q ارجاع دادیم، این سیگنال تبدیل به رجیستر شده است (توجه کنید که در اینجا ما بین سیگنال و پورت تفاوتی قائل نمیشویم).
بهتر است برای درک هرچه بهتر موضوع شماتیک مدار پیادهسازی شده در FPGA را نیز مشاهده کنیم.
تصویر بالا کمی واضح نیست برای بهتر دیدن مدار پیادهسازی شده کمی روی آن زوم میکنیم تا به تصویر زیر برسیم.
مدار پیادهسازی شده علاوه بر فلیپفلاپها دارای بافرهای ورودی-خروجی، بافر کلاک و بخش ریست نیز میباشد، در مورد هر کدام از این بافرها بعدا صحبت خواهیم کرد. در مدار بالا همانطور که مشاهده میکنید کلاک فلیپفلاپها همزمان یا سنکرون میباشد و این موضوع باعث میشود که مقادیر فلیپفلاپها همزمان با یکدیگر تغییر کنند. از سمتی دیگر ورودیها پس از گذر از بافرهای ورودی به طور جداگانه به ورودی هر فلیپفلاپ اعمال میشوند.
شما تنها با تغییر دادن عرض بیت D و Q میتوانید تعداد بیتهای رجیستر پیادهسازی خود را تغییر دهید، اما راهی بهتر برای این کار وجود دارد که ما از این به بعد همیشه از این تکنیک استفاده میکنیم. در ادامه با این روش آشنا خواهیم شد.
خاصیتی وجود دارد به اسم Generic که ما با استفاده از آن میتوانیم یک پارامتر تعریف کنیم و به آن عددی را نسبت بدهیم و در قسمتهای مختلف کد از آن استفاده کنیم و هرگاه قرار بود قسمتهای مختلف کد تغییر کند به جای اینکه قسمتهای مختلف کد را تغییر بدهیم فقط همان پارامتر را تغییر میدهیم.
در ادامه میخواهیم یک رجیستر 32 بیتی را با استفاده از خاصیت Generic توصیف کنیم برای این منظور باید تکه کد زیر را به کد قبلی اضافه کنیم و عرض بیت ورودی و خروجی را با استفاده از این پارامتر تعریف کنیم.
1 2 3 4 | generic ( Number_of_bits: integer := 32 ); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Register_32bit is generic ( Number_of_bits: integer := 32 ); Port ( D : in unsigned (Number_of_bits - 1 downto 0); Clock : in STD_LOGIC; Reset : in STD_LOGIC; Q : out unsigned (Number_of_bits - 1 downto 0) ); end Register_32bit; architecture Behavioral of Register_32bit is begin process(clock) begin if rising_edge (clock) then Q <= D; if (Reset = '1') then Q <= (others => '0'); end if; end if; end process; end Behavioral; |
حال هر موقع خواستید عرض بیت رجیسترتان را تغییر دهید، فقط کافی است که تنها پارامتر Number_of_bits را تغییر دهید تا به کل کد اعمال شود. در کدهای بزرگ این موضوع میتواند در توسعهی کد بسیار سودمند و مفید باشد.
نکتهی دیگر اینکه چون ریست در انتهای کد نوشته شده است اولویت با آن است و اگر شرط آن برقرار باشد مقدار رجیستر 0 منطقی خواهد شد.
امیدوارم که به خوبی این موضوع ساده را فرا گرفته باشید. در قسمت هجدهم به توصیف شیفت رجیستر خواهیم پرداخت.
سلام وقت بخیر…ببخشید شما عکسی از معماری داخلی spartan6 یا یه مورد دیگه از خانواده FPGA شرکتxilinx دارین؟
اگه دارین لطفا عکسشو برام بفرستین
سلام دوست عزیز. آن چیزی که شما میخواهید احتمالا در یک عکس وجود ندارد مگر یک شماتیک کلی از امکانات. برای اینکه هر بخش را به طور دقیق بررسی کنید فایلهایی تحت عنوان ugxxx به معنای User Guide را در xilinx سرچ کنید. در این فایل ها عکسها و شماتیکهایی زیادی از منابع داخلی، مانند حافظهها، ضربکنندهها، منابع کلاک و … وجود دارد. همچنین زمانی که داریدیک ip را اضافه میکنید که نهایتا یکی از منابع درونی fpga است میتوانید در پایین سمت چپ، دیتاشیت آن را مشاهده کنید.
در تأیید پاسخ دوست عزیزم باید بگم که FPGA ها مجموعه از عناصر اختصاصی هستند که هر کدام برای خودشان یک شماتیک خاص دارند. این عناصر به صورت سطری یا سطونی در کنار هم قرار میگیرند و در نهایت یک FPGA شکل داده میشه.
برای دسترسی به مستندات کامل تراشه های spartan 6 می تونید از لینک زیر استفاده کنید.
https://www.xilinx.com/products/silicon-devices/fpga/spartan-6.html#documentation
و در بخش دانلود مستندات مربوط به عناصر مختلف از قبیل CLB و CLK و DSP و Memory رو دانلود و مطالعه کنید.
سپاس از شما دوست نازنینم که لینک مستندات مربوطه را برای راهنمایی هرچه بیشتر خوانندگان قرار دادید.
سلام
خسته نباشید
ممنون از آموزش های خوبتون .
کد رجیستر 32 بیتی که با generic نوشته شده … اسم Entity که قرار دادین Register_32bit هست اما خط 19 و 21 نوشتین Register_8bit که ارور میده و سنتز نمیشه … باید 8 به 32 اصلاح بشه.
منتظر سری بعدی آموزش های خوبتون هستیم …
سلام امیر عزیز. اره یادم رفته بود اون پایین هم اسمشو عوض کنم. ممنون از اینکه یادآوری کردید. الان تصحیح میکنیم.
بعد شما تمام رجیسترهایی که طراحی کردین ورودی موازی/خروجی موازی (PIPO) هست دیگه ؟
یعنی فقط با یک کلاک 32 بیت ورودی ذخیره میشه . درسته ؟
بله موازی است و تنها با یک کلاک، 32 بیت رجیستر مقداردهی میشود.