نمایش اعداد علامت دار در FPGA

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

مقدمه

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

روش علامت اندازه

در این روش برای نمایش اعداد از یک بیت اضافه استفاده می‌شود و این بیت اضافه به علامت عدد، اختصاص داده می‌شود. این بیت علامت بعد از با ارزشترین بیت در جایگاه MSB قرار داده می‌شود و مقدار آن برای اعداد مثبت صفر و برای اعداد منفی یک است. به عنوان مثال برای نمایش عدد مثبت و منفی ۹ داریم:

"01001" = +9, "11001" = -9

رِنج اعداد قابل نمایش در این روش به صورت زیر است و برای یک عدد ۵ بیتی مقادیر از منفی تا مثبت ۱۵ قابل نمایش هستند و دو مقدار برای عدد صفر داریم. در رابطه زیر N معرف تعداد بیت است.

-(2N-1-1) : 2N-1-1

همانطور که حتما حدس زدید یکی از معایب اصلی که در این شیوه نمایش، وجود دو مقدار "00000" و "10000" برای نمایش عدد صفر است. این شیوه نمایش به جز موارد بسیار خاص در FPGA مورد استفاده قرار نمی‌گیرد.

روش مکمل یک

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

"01001" = +9, "10110" = -9

رِنج اعداد قابل نمایش در این روش مشابه روش اول است و برای یک عدد ۵ بیتی مقادیر از منفی تا مثبت ۱۵ قابل نمایش هستند.

-(2N-1-1) : 2N-1-1

با توجه به اینکه با استفاده از N بیت می توان 2N عدد مثبت را نمایش داد، واضح است که با علامت دار شدن اعداد دامنه تغییرات اعداد نصف می‌شود. اما نکته اینحاست که بازهم برای نمایش عدد صفر مشکل داریم و دو مقدار "00000" و "11111" هر دو نمایانگر عدد صفر هستند. عملا این روش نیز در FPGA مورد استفاده قرار نمی‌گیرد.

روش مکمل دو

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

"01001" = +9, "10111" = -9

برخلاف دو شیوه نمایش قبلی دامنه اعداد قابل نمایش با استفاده از ۵ بیت از ۱۶- تا ۱۵ می‌باشد و برای نمایش عدد صفر تنها مقدار "00000" قابل استفاده است.

-2N-1 : 2N-1-1

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

جایگزینی تفریق با جمع

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

پیاده‌سازی عملیات جمع

در زبان VHDL برای استفاده از سیستم مکمل دو پیشنهاد می‌شود از کتابخانه ieee و از پکیج  numeric_std استفاده شود. در این کتابخانه دو نوع signed و unsigned بر اساس نوع std_logic_vector تعریف شده‌اند و برای تعریف سیگنال‌های علامت دار و بدون علامت بکار گرفته می‌شوند.

library ieee;
use ieee.numeric_std.all;

کد HDL زیر یک جمع کننده ۸ بیتی علامت دار را نشان می‌دهد. به نحوه اختصاص مقادیر پورت‌ها به سیگنال‌های درونی ماژول توجه کنید. در این کد فرض بر این است که حاصل جمع دو ورودی ai و bi در یک رجیستر ۸ بیتی ذخیره می‌شود. عبارت signed در خطوط ۱۷ و ۱۸ برای تغییر نوع std_logic_vector به نوع signed استفاده شده است. این تبدیل نوع در خط ۲۰ به شکل دیگری تکرار شده است.

-- Copyright 2019 Hexalinx.com

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adder is
    generic (M  : integer := 8);
    port (ai,bi : in std_logic_vector(M-1 downto 0);
          xo    : out std_logic_vector(M-1 downto 0));
end;

architecture arch of adder is
    signal a,b,x  : signed(M-1 downto 0);
begin	

    a <= signed(ai);
    b <= signed(bi);
    x <= a + b;
    xo <= std_logic_vector(x);

end architecture;

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

-- Copyright 2019 Hexalinx.com

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adder is
    generic (M  : integer := 8);
    port (ai,bi : in std_logic_vector(M-1 downto 0);
          xo    : out std_logic_vector(M-1 downto 0));
end;

architecture arch of adder is
    signal a,b  : signed(M-1 downto 0);
    signal x    : signed(M downto 0);
begin	

    a <= signed(ai);
    b <= signed(bi);
    x <= resize(a + b, M+1);
    xo <= std_logic_vector(x(M downto 1));

end architecture;

برای اینکه خروجی همچنان در ۸ بیت قابل نمایش باشد کمی از دقت حاصل جمع کاسته شده است و بیت کم ارزش آن کنار گذاشته شده است. تابع resize در پکیج numeric_std معرفی شده است و برای تغییر سایز سیگنال در زمان ارجاع استفاده می‌شود.

جمع بندی

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

در صورتی که علاقمند هستید با شیوه نمایش اعداد اعشاری ممیز ثابت آشنا شوید. پیشنهاد می‌کنم آموزش‌های تکمیلی هگزالینکس را مطالعه بفرمایید.

اشتراک در
بیشتر بخوانیم
پیاده سازی ماژول UART در FPGA توصیف سخت افزاری

پیاده سازی ماژول UART در FPGA

پیاده سازی ماژول UART در FPGA چندان دشوار نیست. ولی میزان انعطاف پذیری و بهینه بودن آن به سلیقه طراح و نیازمندی‌های پروژه بستگی دارد.

آموزش سریع Vivado HLS ابزارهای طراحی

قست سوم: پکیج کردن HLS IP برای Vivado IP Catalog

در این ویدئو شیوه پکیج کردن HLS IP برای Vivado IP Catalog را باهم مرور خواهیم کرد. این HLS IP می‌تواند در محیط Vivado IP Integrator فراخوانی و استفاده شود.

سنتز سطح بالا

خواندن و نوشتن در حافظه DDR با HLS

برای طراحی یک مسیر دیتای پرسرعت در یک سیستم ممکن است نیاز به خواندن و نوشتن در حافظه DDR داشته باشید. آیا می‌توانیم این کار را با HLS‌ انجام دهیم.

آموزش سریع Vivado HLS ابزارهای طراحی

قسمت هفتم: تعیین اینترفیس AXI4 برای طرح Vivado HLS

در این ویدئوی کوتاه فرایند تعیین اینترفیس‌ AXI4 برای طرح Vivado HLS را بررسی می‌کنیم و مفاهیم مهمی همچون سنتز اینترفیس و پروتکل‌های ورودی خروجی را معرفی می‌کنیم.

عناوین مطالب
    برای شروع تولید فهرست مطالب ، یک هدر اضافه کنید

    4 در مورد “نمایش اعداد علامت دار در FPGA”

    1. با سلام و تشکر بابت آموزش هاتون .سوال من اینه که چرا از resize استفاده کردین در حالی که سیگنال x یک بیت بیشتر از a وb هست .یعنی با اضافه کردن یک بیت به طول xآیا باز هم نیازه از resize استفاده بشه ؟

      1. گروه برنامه نویسی

        با سلام و احترام
        ممنون از دقتی که به خرج دادید. به صورت کلی تعداد بیت‌های متغیرهای سمت راست ارجاع (=>) و سمت چپ اون باید باهم برابر باشند. در غیر این صورت دو احتمال وجود داره. یا ابزار سنتز خطا میده و یا مقدار خروجی اشتباه میشه. البته در مواردی ممکنه پاسخ درست هم حاصل بشه ولی روش کار درست نیست.
        با استفاده از تابع resize در (x <= resize(a + b, M+1 تعدا بیت‌های سمت راست رو ۹ در نظر گرفتیم. یعنی پاسخ a+b رو ۹ بیتی کردیم و بعد به x ارجاع دادیم.

    دیدگاه‌ خود را بنویسید

    نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

    اسکرول به بالا