توسط احمد ثقفی 

24 آبان, 1395

محاسبات علامتدار

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

More...

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

برای آشنایی با زبان VHDL این برنامه ویدئویی را ببینید….

در این برنامه ویدئویی، ابتدا سه روش مرسوم برای نمایش اعداد علامتدار را مرور می‌کنم و سپس در مورد روش مناسب برای پیاده‌سازی که روش نمایش مکمل دو یا two’s complement است شرح می‌دهم.

سیستم نمایش مکمل دو دارای خصوصیات منحصر به فردی است که بعضی از آنها کمتر مورد توجه طراحان دیجیتال است. در این برنامه، سه خصوصیت مهم این سیستم را شرح می‌دهم و مثالی هم در مورد یکی از خصوصیات مهم اما کمتر شناخته شده سیستم نمایش مکمل دو ارائه می‌کنم.

در ادامه این برنامه، روش استاندارد و امتحان شده‌ای را برای پیاده‌سازی محاسبات علامتدار در FPGA به شما آموزش خواهم داد و یک نمونه کد VHDL را هم به عنوان مثال بررسی خواهم کرد.

ویدئو یا متن؟

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

برای دانلود نسخه با کیفیت این ویدئو، روی دکمه زیر کلیک کنید:

در این برنامه قصد دارم در مورد نحوه‌ی نمایش و پیاده‌‌سازی محاسبات اعداد علامت‌‌دار در FPGA صحبت کنم.

در بسیاری از کاربردها، نیاز است که اعداد را به صورت علامت‌‌دار استفاده کنید و محاسباتی مثل ضرب، جمع، تقسیم و ... را روی آن‌ها انجام دهید.

خصوصاً اگر تصمیم داشته باشید در ادامه‌ی مسیر یادگیری FPGAها، به سراغ پیاده‌‌سازی الگوریتم‌‌های پردازش سیگنال‌های دیجیتال بروید، این ابتدایی‌‌ترین موضوعی است که در ارتباط با پیاده‌‌سازی، به آن نیاز خواهید داشت.

در ابتدا، اجازه دهید مروری بر روش‌‌های نمایش اعداد علامت‌‌دار داشته باشیم.

روش‌‌های نمایش اعداد علامت‌‌دار

اگر از درس مدار منطقی به یاد داشته باشید، به طور کلی سه روش برای نمایش اعداد علامت‌‌دار وجود دارد؛

روش علامت و مقدار یا sign & magnitude

اولین روش، روش علامت و مقدار یا sign & magnitude است. در این روش، یک عدد مثبت را به صورت عادی نمایش می‌‌دهیم و برای نمایش اعداد منفی، بیت سنگین یا بیت علامت را یک می‌‌کنیم. به بقیه‌ی بیت‌‌ها (به جز بیت علامت)، بیت‌های مقدار می‌‌گوییم.

برای مثال، عدد ۶ و ۶- را به صورت زیر نشان می‌دهیم:

​نمایش ​اعداد ۶ و ۶- به روش علامت و مقدار

​نمایش ​اعداد ۶ و ۶- به روش علامت و مقدار

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

نکته‌ی منفی دیگری که در این روش وجود دارد، این است که برای نمایش عدد صفر دو مقدار و دو نمایش وجود دارد؛ مثلاً اگر شما یک رجیستر پنچ بیتی را در نظر بگیرید، هر دو مقداری که در زیر می‌‌بینید، نشان‌‌دهنده‌ی عدد صفر هستند.

۰۰۰۰۰ = ۱۰۰۰۰ = صفر

روش مکمل یک یا one's complement

روش دوم، روش مکمل یک یا one's complement است. در این روش، مجدداً عددهای مثبت را به صورت باینری عادی نمایش می‌‌دهیم، اما برای نمایش اعداد باینری منفی باید مکمل یک آن عدد را حساب کنیم؛

برای محاسبه‌ی مکمل یک، باید تمامی رقم‌‌های عدد را not کنیم.

در زیر، نمایش عدد ۶ و ۶- را به روش مکمل یک می‌‌بینید:

​نمایش اعداد ۶ و ۶- به روش مکمل یک

​نمایش اعداد ۶ و ۶- به روش مکمل یک

برای به دست آوردن ۶- از روی عدد ۶، تمام بیت‌‌ها را not کرده‌ایم. در این روش نمایش نیز، سنگین‌ترین بیت، بیت علامت است و یک بودن آن، نشان‌‌دهنده‌ی منفی بودن عدد است.

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

۰۰۰۰۰ = ۱۱۱۱۱ = صفر

روش مکمل دو یا two's complement

روش سوم و محبوب‌‌ترین روش، روش مکمل دو یا two's complement است.

در روش مکمل دو، همانند دو روش قبل، برای نمایش عدد مثبت به صورت باینری عادی عمل می‌‌کنیم. اما برای نمایش اعداد منفی، مکمل دو اعداد مثبت را حساب می‌‌کنیم؛

برای محاسبه‌ی مکمل دو یک عدد مثبت، دو روش ذهنی وجود دارد:

اول آنکه مکمل یک را محاسبه کنید و یک واحد به عدد به دست آمده اضافه کنید.

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

نمایش اعداد ۶ و ۶- را به روش مکمل دو در زیر می‌ببینید:

​​نمایش عدد ۶ و ۶- به روش مکمل دو

​نمایش اعداد ۶ و ۶- به روش مکمل دو

مثل دو سیستم قبلی، در سیستم مکمل دو نیز ​سنگین‌ترین بیت، همان بیت علامت است​ و یک بودنش نشان دهنده‌ی منفی بودن عدد است.

بزرگ‌‌ترین حُسن روش نمایش اعداد علامت‌‌دار به روش مکمل دو، این است که در این روش، پیاده‌‌سازی تفریق بسیار ساده است؛ در واقع، در این روش با همان مداری که عمل جمع انجام می‌‌شود، می‌توان عمل تفریق را نیز انجام داد.

حُسن دیگر روش مکمل دو این است که برای هر عدد، یک نمایش یکتا وجود دارد؛

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

ویژگی مهم و کاربردی نمایش اعداد علامت‌‌دار به روش مکمل دو

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

اجازه دهید با ذکر یک مثال این موضوع را بیشتر توضیح دهم؛

در سیستم مکمل دو، اگر از n بیت برای نمایش یک عدد استفاده کنیم، محدوده‌ی نمایش یا رنج نمایش اعداد برابر با 2n-1- تا 2n-1-1 است.

مثلاً محدوده‌ی نمایش اعداد در یک سیستم مکمل دو سه بیتی، همانند آنچه در زیر می‌بینید، از ۴- تا ۳+ است.

محدوده‌ی نمایش اعداد در یک سیستم مکمل دو سه بیتی

همان‌‌طور که مشاهده می‌‌کنید در این سیستم نمایش، بزرگ‌‌ترین و کوچک‌‌ترین عدد قرینه یکدیگر نیستند. مثلاً، در نمایش مکمل دو چهار بیتی، کوچک‌‌ترین عدد ۸- و بزرگ‌‌ترین عدد ۷+ است.

حالا فرض کنید که می‌‌خواهیم پنج عدد ۲، ۳، ۴-، ۲ و ۵- را با هم جمع کنیم.

2 + 3 - 4 + 2 - 5 = -2

می‌‌دانیم که جواب نهایی این جمع برابر با ۲- است و ۲- در محدوده‌ی نمایش سه بیتی می‌گنجد.

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

در این مثال، در همان ابتدا که عدد ۲ را با ۳ جمع می‌کنیم، جواب برابر با ۵ می‌‌شود و عدد ۵ خارج از محدوده‌ی نمایش سه بیتی مکمل دو است؛ پس یک Overflow رخ داده است ولی این Overflow در رسیدن ما به جواب صحیح مشکلی ایجاد نمی‌‌کند؛ زیرا از قبل می‌‌دانیم که نتیجه‌ی جمع کل پنج عدد در رنج وجود دارد.

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

چه سیستم نمایشی در پیاده‌سازی سیستم‌‌های دیجیتال به کار می‌رود؟

به دلیل همین خصوصیات خوب و منحصر به فردی که سیستم نمایش مکمل دو دارد، بیش‌تر سیستم‌‌های دیجیتالی که در آن‌‌ها محاسبات علامت‌‌دار انجام می‌‌شوند را به کمک همین سیستم پیاده‌‌سازی می‌‌کنند.

در زبان VHDL نیز برای پیاده‌‌سازی اعداد علامت‌‌‌‌دار از همین روش استفاده می‌‌شود.

بنابراین، اجازه دهید که ببینیم به چه روشی می‌‌توانیم محاسبات اعداد علامت‌‌دار را در زبان VHDL انجام ‌‌دهیم و سیستم مکمل دو را در FPGA پیاده‌‌سازی کنیم.

چگونه می‌توانیم اعداد را به روش مکمل دو، در FPGA پیاده‌سازی کنیم؟

برای اینکه بتوانید از سیستم مکمل دو برای نمایش اعداد علامت‌‌دار و  محاسبات ریاضی استفاده کنید، پیشنهادی که من به شما دارم، استفاده از دوتا تایپ unsigned و signed، برای تعریف تمام سیگنال‌‌های داخلی FPGA و پورت‌‌ها است.

احتمالاً اطلاع داشته باشید که در زبان VHDL، روش‌‌های مختلفی برای نمایش و انجام محاسبات اعداد علامت‌‌دار وجود دارد.

اما روشی که به شما ارایه می‌‌کنم، روش توصیه‌ی شده، توسط مهندسان شرکت XILINX است؛ این روش نه تنها در حال حاضر به شما کمک می‌‌کند که بتوانید محاسبات ساده علامت‌‌دار را انجام دهید، بلکه در آینده نیز، که وارد مبحث پردازش سیگنال‌های دیجیتال شدید، به شما کمک می‌کند که بتوانید اعداد علامت‌‌دار را به راحتی و بدون مشکل و ابهامی نمایش دهید و در محاسباتتان استفاده کنید.

برای استفاده از دو تایپ unsigned و signed، باید به روشی که در زیر نوشته‌ شده، در بالای کد VHDL، پکیج numeric_std را از کتابخانه IEEE، فراخوانی کنید.

use ieee.numeric_std.all;

پس از آن، می‌‌توانید در کدتان سیگنال‌‌هایی با تایپ‌ unsigned و signed تعریف کنید.

مثلاً برای تعریف سیگنالی به نام X، می‌‌توانید کدی به صورت زیر بنویسید:

signal X : signed(7 downto 0) := (others=>’0’);

به این ترتیب، سیگنال X را با عرض بیت هشت و مقدار اولیه‌ی صفر تعریف کردیم.

حال ممکن است این سوال مطرح شود که چه سیگنال‌‌هایی را signed و چه سیگنال‌‌هایی را unsigned تعریف کنیم؟

در جواب باید گفت که اگر قصد دارید روی سیگنال مورد نظر، محاسبات ریاضی علامت‌‌دار انجام دهید، حتماً از تایپ signed استفاده کنید؛ در غیر این صورت، از تایپ unsigned استفاده کنید.

ذکر یک مثال از پیاده‌سازی اعداد به روش مکمل دو در FPGA

برای توضیح بیش‌تر مطالبی که تا اینجا گفته شد، مثال ساده‌ی زیر را با هم بررسی می‌کنیم؛

می‌‌خواهیم یک جمع کننده‌ی علامت‌‌دار ۱۶ بیتی را با هم پیاده‌‌سازی کنیم؛

​کد پیاده‌سازی این مثال را در زیر می‌بینید:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Multiplier_Top is
    Port ( 
		
           A 			: in 	 signed (15 downto 0);
           B 			: in   signed (15 downto 0);
           Sum 		: out  signed (15 downto 0);
           Overflow 	: out  STD_LOGIC;
			  );
end Multiplier_Top;

architecture Behavioral of Multiplier_Top is

	signal Sum_Int		signed (16 downto 0)	:=(others=>'0');

begin
		
			Sum_Int		<= Resize(A,17) + B;
			Sum			<= Sum_Int(15 downto 0);
			Overflow		<= Sum_Int(16) xor Sum_Int(15);

end Behavioral;

برای سادگی، ورودی Carry in را در نظر نمی‌گیریم و فقط یک خروجی سرریز یا Overflow برای آن در نظر می‌گیریم.

تحلیل کد VHDL پیاده‌سازی اعداد، به روش مکمل دو در FPGA

همان‌‌طور که گفتم، شما باید در ابتدای کدتان پکیج numeric_std را به شیوه‌ای که در خط سوم از کد بالا می‌‌بینید، فراخوانی کنید؛ بدین ترتیب می‌توانید از تایپ‌‌های signed و unsigned و قابلیت‌‌های دیگری که این سیستم به شما ارایه می‌‌دهد، استفاده کنید.

در Entity کد، دو سیگنال ورودی A و B را با تایپ signed تعریف کرده‌ام و عرض هرکدام از سیگنال‌ها را ۱۶ بیتی در نظر گرفته‌ام (خط هشتم و نهم).

در خط ۱۰اُم، یک خروجی Sum با تایپ unsigned و عرض بیت ۱۶ تعریف کرده‌ام.

 و نهایتاً در خط ۱۱اُم، یک خروجی تک بیتی به نام Overflow و از نوع STD_Logic تعریف کرده‌ام؛ به کمک این خروجی می‌‌خواهم مشخص کنم که آیا جمع دو عدد A و B دارای Overflow یا سرریز است یا خیر.

برای اینکه بتوانم جمع را به درستی انجام داده و سرریز را تشخیص دهم، در خط ۱۷اُم، یک سیگنال داخلی ۱۷ بیتی به نام Sum_Int و از نوع signed تعریف کرده‌ام؛ حاصل جمع A+B را به این سیگنال منتقل می‌‌کنم تا اگر بیت اضافه‌‌ای ایجاد شد، از بین نرود.

برای رعایت قانون ارجاع جمع در زبان VHDL، مواردی را در خط ۲۱ از کد، اعمال کرده‌ام:

اولاً که قانون ارجاع جمع این است که حداقل یکی از سیگنال‌‌هایی که با هم جمع می‌‌کنیم (در اینجا A و B)، باید هم عرض سیگنال سمت چپ ارجاع (در اینجا Sum_Int)، باشد؛ بقیه‌ی سیگنال‌ها می‌‌توانند هم عرض یا با عرضی کوچک‌‌تر از عرض سیگنال سمت چپ ارجاع باشند.

با توجه به اینکه A و B دارای عرض بیت ۱۶ و سیگنال Sum_Int عرض بیتی برابر با ۱۷ دارد، برای رعایت قانون ارجاع جمع، باید عرض بیت یکی از این سیگنال‌‌ها را به ۱۷ برسانم؛ این کار را به کمک تابع Resize انجام داده‌ام.

شما می‌‌توانید در هنگام Assignment، عرض بیت یک سیگنال را به کمک تابع Resize، بزرگ‌‌تر یا کوچک‌‌تر کنید.

در خط ۲۱، در هنگام Assignment، عرض بیت سیگنال A را تبدیل به ۱۷ بیت کرده‌ام تا قانون ارجاع جمع رعایت شود.

تا به اینجای کد، من جمع A و B را که ۱۶ بیتی بودند، به یک سیگنال ۱۷ بیتی منتقل کردم.

در خط ۲۲اُم، ۱۶ بیت سبک این سیگنال ۱۷ بیتی را جدا می‌کنم و به خروجی Sum منتقل می‌کنم.

در خط بعد، حاصل XOR دو بیت سنگین Sum_Int را که برابر سرزیر جمع است، به سیگنال Overflow منتقل می‌کنم؛ این بدان معنی است که اگر دو بیت سنگین یکسان نباشند، حتماً Overflow داریم.

در این مثال ساده، شما نحوه‌ی استفاده از تایپ signed، برای انجام محاسبات علامت‌‌دار در زبان VHDL را ملاحظه کردید.

امیدوارم بتوانید از آن در کدهایتان استفاده کنید و محاسبات علامت‌‌دار را به راحتی پیاده سازی کنید.

آیا برنامه ویدئویی پیاده‌سازی محاسبات علامتدار در FPGA برای شما مفید بود؟

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

کانال تلگرام آموزش FPGA از صفر

برای عضویت در کانال تلگرام و دسترسی به آموزش‌های بیشتر و اطلاع سریع از زمان انتشار آموزش‌ها و تخفیف‌های ویژه، روی دکمه زیر کلیک کنید:

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

احمد ثقفی

شاید به این موضوعات نیز علاقه داشته باشید:

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

۷ تکنیک پیشرفته کدنویسی برای FPGA

>