در قسمت هفدهم از مجموعه آموزشی FPGA با رجیسترها آشنا شدیم و از کاربردهای رجیسترها گفتیم، نهایتا هم بااستفادهاز زبان VHDL یک رجیستر را بهصورت Generic توصیف کردیم، که شما میتوانستید تنها با تغییر یک عدد عرض بیت رجیستر خود را تغییردهید. در قسمت گذشته ما از کنار هم قراردادن فلیپفلاپها توانستیم رجیسترها را بسازیم، در این قسمت نیز قصد داریم همان فلیپفلاپها را کنارهم قراردهیم و شیفت رجیسترها را بسازیم. اینکه فلیپفلاپها به چهنحوی کنار همدیگر قرار بگیرند، میتوانند تشکیل رجیستر یا شیفت رجیستر بدهند. با تعریف رجیستر و اینکه چگونه ساخته میشود ازقبل آشنا هستید، برای تعریف و آشنایی هرچه بیستر با شیفت رجیسترها به ادامه توضیحات بادقت توجهکنید.
شیفت رجیستر
کمترین امکانات یک فلیپفلاپ یک ورودی دیتا، یک خروجی دیتا و یک ورودی کلاک میباشد. حال اگر خروجی فلیپفلاپی را به ورودی فلیپفلاپی دیگر متصلکنیم و این عمل را به تعداد nبار تکرار کنیم، همچنین ورودی کلاک تمامی این فلیپفلاپها را بهم متصلکنیم، آنگاه یک شیفت رجیستر nبیتی خواهیمداشت.
پس هم رجیسترها و هم شیفت رجیسترها، زنجیرهای از فلیپفلاپها هستند که کنارهم قرار گرفتهاند. حال اینکه این فلیپفلاپها به چهنحوی کنار همدیگر قرار بگیرند، میتوانند تشکیل رجیستر یا شیفت رجیستر را بدهند.
در رجیسترها خروجی هر فلیپفلاپ به ورودی فلیپفلاپ دیگر متصل نیست، اما در شیفت رجیسترها خروجی هر فلیپفلاپ به ورودی فلیپفلاپ دیگر متصل است.
نحوهی عملکرد شیفت رجیسترها
اگر یک شیفت رجیستر را آرایهای از بیتهای پشت سرهم درنظر بگیریم، به سه روش عمل شیفت میتواند انجام بگیرد، درمورد دو روش اول در این قسمت، و درمورد سومین روش در قسمتهای بعدی صحبت خواهیم کرد.
شیفت به راست
در این نوع از شیفت رجیسترها با هر کلاک، بیتی که در ورودی سمت چپ شیفت رجیستر قرار دارد، به داخل شیفت رجیستر وارد میشود. از سوی دیگر، آخرین بیت از سمت راست از شیفت رجیستر خارج خواهد شد یا بهتر است بگوییم که ازبین خواهد رفت.
شیفت به چپ
در این نوع از شیفت رجیسترها با هر کلاک، بیتی که در ورودی سمت راست شیفت رجیستر قرار دارد، به داخل شیفت رجیستر وارد میشود. از سوی دیگر، آخرین بیت از سمت چپ از شیفت رجیستر خارج خواهد شد یا بهتر است بگوییم که از بین خواهد رفت.
انواع شیفت رجیسترها
ورودی سریال-خروجی سریال (SISO)
در این نوع از شیفت رجیسترها، دیتای ورودی بهصورت سریال وارد شیفترجیستر میشود، یعنی با هر کلاک تنها یک بیت وارد شیفترجیستر خواهد شد. از سوی دیگر در خروجی در هر کلاک تنها یک بیت در دسترس خواهد بود. اینکه کدام بیت در دسترس باشد بستگی به این دارد که شیفترجیستر ما شیفت به راست میدهد یا شیفت به چپ.
ورودی سریال-خروجی موازی (SIPO)
در این نوع از شیفت رجیسترها، دیتای ورودی بهصورت سریال وارد شیفترجیستر میشود، اما در خروجی تنها در یک کلاک میتوانیم به تمامی بیتها دسترسی داشتهباشیم.
ورودی موازی-خروجی موازی (PIPO)
در این نوع از شیفت رجیسترها تنها در یک کلاک میتوان تمامی بیتهای شیفترجیستر را مقداردهی کرد، در خروجی نیز میتوانیم تنها در یک کلاک به تمامی بیتها دسترسی داشتهباشیم.
ورودی موازی-خروجی سریال (PISO)
در این نوع از شیفت رجیسترها تنها در یک کلاک میتوان تمامی بیتها را مقداردهی کرد، اما در خروجی با هر کلاک تنها به یک بیت دسترسی خواهیم داشت. برای اینکه این تعاریف را بهخوبی درک کنید و از نحوهی عملکرد این نوع شیفت رجیسترها بهخوبی آگاه شوید به تصویر زیر بهخوبی توجهکنید.
همچنین میتوانید گیف زیر را که از این لینک دانلود شده است نیز مشاهدهکنید.
در ادامه میخواهیم یک نوع از این شیفت رجیسترها را بااستفادهاز زبان VHDL توصف کنیم. اول کد مربوطه را خواهیمنوشت سپس به تشریح این کد خواهیمپرداخت:
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; Middle(6) <= Middle(7); Middle(5) <= Middle(6); Middle(4) <= Middle(5); Middle(3) <= Middle(4); Middle(2) <= Middle(3); Middle(1) <= Middle(2); Middle(0) <= Middle(1); end if; end process; end Behavioral;
اگر به جزئیات کد توجهکنید متوجهخواهید شد که شیفت رجیستر توصیفشده از نوع SIPO میباشد و همچنین شیفت به راست انجام میدهد.
در کد بالا ما از یک سیگنال به اسم Middle نیز استفادهکردیم، دلیل آن چیست؟ تنها به این دلیل از سیگنال میانی استفادهکردیم که هم میخواهیم از آن بخوانیم و هم در آن بنویسم و این قابلیت در پورت تعریفشده از نوع out وجود ندارد که بخواهیم هم در آن بنویسیم و هم از آن بخوانیم. در پورت نوع out فقط میتوانیم بنویسیم.
با تغییرات کوچکی میخواهیم همین نوع شیفت رجیستر را این بار با شیفت به چپ پیادهسازی کنیم.
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; Middle(1) <= Middle(0); Middle(2) <= Middle(1); Middle(3) <= Middle(2); Middle(4) <= Middle(3); Middle(5) <= Middle(4); Middle(6) <= Middle(5); Middle(7) <= Middle(6); end if; end process; end Behavioral;
اکنون سوالی که شاید برایتان پیش بیاید این است که اگر بخواهیم عرض شیفترجیستر را افزایش بدهیم، باید با همین سختی پشت سرهم یک بیت را به بیت دیگر ارجاع بدهیم؟ خیر، راهحلهای سادهتری نیز وجود دارد که ما در قسمتهای بعدی این راهحلها را توضیح خواهیم داد، پس با ما همراه باشید.
منبع: سیسوگ