منطق باینری چیست؟

اگر بخواهیم از پایه وارد دنیای Digital Logic و بعداً طراحی CPU، مدار دیجیتال، FPGA و Verilog شویم، یکی از اولین مفاهیمی که باید کاملاً درک کنیم Binary یا دستگاه عددی دودویی است.

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

0 ↔ 1
خاموش / روشن
Low / High
False / True

به همین دلیل به این سیستم دودویی یا Binary می‌گوییم.

نکته مهم: 0 و 1 در کامپیوتر الزاماً به معنی «صفر ولت و یک ولت» نیستند. در مدار واقعی، محدوده‌های ولتاژ مشخص می‌کنند که یک سیگنال به‌عنوان Logic 0 یا Logic 1 تشخیص داده شود.

Bit چیست؟

کوچک‌ترین واحد اطلاعات دیجیتال را Bit می‌نامیم. یک بیت فقط می‌تواند دو حالت داشته باشد:

0 یا 1

برای مثال:

1 bit: 0 یا 1
2 bit: 00، 01، 10، 11
3 bit: 000 تا 111
4 bit: 0000 تا 1111

اگر تعداد بیت‌ها برابر n باشد، تعداد ترکیب‌های ممکن برابر است با:

2n حالت

مثلاً با 8 بیت داریم:

28 = 256 حالت

بنابراین یک مقدار 8 بیتی بدون در نظر گرفتن علامت می‌تواند اعداد 0 تا 255 را نمایش دهد.

Byte چیست؟

هر 8 بیت برابر یک Byte است:

1 Byte = 8 Bits

مثلاً:

10110110
↑──────↑
  8 بیت = 1 بایت

در معماری کامپیوتر، Byte یکی از واحدهای بسیار مهم برای بیان ظرفیت حافظه، Storage و اندازه داده است.

چرا Binary؟

مدارهای دیجیتال معمولاً با سیگنال‌هایی کار می‌کنند که در دو محدوده منطقی قرار می‌گیرند. این موضوع باعث می‌شود طراحی سیستم با دو حالت منطقی نسبتاً قابل اعتماد و قابل تشخیص باشد.

ترانزیستورها

سطوح منطقی

0 و 1

Logic Gates

مدارهای دیجیتال

CPU / RAM / FPGA / Controller

پس Binary فقط یک روش نوشتن عدد نیست؛ بلکه پایه‌ای برای نمایش و پردازش اطلاعات در سیستم‌های دیجیتال است.

دستگاه‌های عددی مهم

در مهندسی کامپیوتر چند مبنا بسیار مهم هستند:

مبنا نام ارقام کاربرد
2 Binary 0, 1 سخت‌افزار و منطق دیجیتال
8 Octal 0 تا 7 نمایش فشرده Binary در بعضی کاربردها
10 Decimal 0 تا 9 محاسبات معمول انسانی
16 Hexadecimal 0 تا 9 و A تا F نمایش فشرده Binary و آدرس‌ها

مفهوم Base یا مبنا

در یک سیستم عددی با مبنای b، ارزش هر رقم بر اساس توان‌های b تعیین می‌شود.

مثلاً در ده‌دهی:

583 = 5×10² + 8×10¹ + 3×10⁰

در Binary نیز دقیقاً همین ایده وجود دارد، با این تفاوت که مبنا 2 است.

1011₂ = 1×2³ + 0×2² + 1×2¹ + 1×2⁰

پس:

1011₂ = 8 + 0 + 2 + 1 = 11₁₀

تبدیل Binary به Decimal

برای تبدیل Binary به Decimal، هر بیت را در توان متناظر 2 ضرب می‌کنیم.

مثال:

110101₂
بیت 1 1 0 1 0 1
توان 2 2⁵ 2⁴ 2⁰
مقدار 32 16 0 4 0 1
110101₂ = 32 + 16 + 4 + 1 = 53₁₀

تبدیل Decimal به Binary

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

مثلاً عدد 13:

13 ÷ 2 = 6 باقی‌مانده 1
6 ÷ 2 = 3 باقی‌مانده 0
3 ÷ 2 = 1 باقی‌مانده 1
1 ÷ 2 = 0 باقی‌مانده 1

باقی‌مانده‌ها را از پایین به بالا می‌خوانیم:

13₁₀ = 1101₂
ترفند ذهنی: برای تبدیل Binary به Decimal معمولاً توان‌های 2 را جمع می‌کنیم؛ برای Decimal به Binary می‌توانیم از تقسیم‌های متوالی بر 2 استفاده کنیم.

جدول توان‌های 2

توان مقدار
2⁰1
2
4
8
2⁴16
2⁵32
2⁶64
2⁷128
2⁸256
2¹⁰1024
2¹⁶65536
2³²4294967296

MSB و LSB چیست؟

در یک عدد باینری، سمت چپ‌ترین بیت معمولاً MSB یا Most Significant Bit نام دارد. سمت راست‌ترین بیت نیز LSB یا Least Significant Bit است.

MSB → 1 0 1 1 0 1 ← LSB

در اعداد بدون علامت، LSB ارزش 2⁰ و بیت بعدی ارزش 2¹ دارد و به همین ترتیب ادامه پیدا می‌کند.

تبدیل Binary و Hexadecimal

یکی از مهم‌ترین تبدیل‌ها برای برنامه‌نویسی سطح پایین، FPGA و معماری کامپیوتر، تبدیل Binary به Hexadecimal است. دلیل مهم بودن Hex این است که هر رقم Hex دقیقاً معادل 4 بیت است.

Binary Hex
00000
00011
00102
00113
01004
01015
01106
01117
10008
10019
1010A
1011B
1100C
1101D
1110E
1111F

مثلاً:

1010 1101 0111 0011
A D 7 3
1010110101110011₂ = AD73₁₆

بنابراین به جای نوشتن 16 بیت، می‌توانیم فقط 4 رقم Hex بنویسیم.

تبدیل Hex به Binary

برعکس حالت قبل نیز بسیار ساده است. هر رقم Hex را با 4 بیت جایگزین می‌کنیم.

3F7A₁₆

0011 1111 0111 1010₂
هر رقم Hex = دقیقاً 4 بیت.
پس 2 رقم Hex = 8 بیت = 1 Byte.

تبدیل Binary و Octal

برای Octal، بیت‌ها را از سمت راست به گروه‌های 3تایی تقسیم می‌کنیم؛ چون:

2³ = 8

مثلاً:

101 110 011₂
5 6 3₈

بنابراین:

101110011₂ = 563₈

اعداد اعشاری باینری

Binary فقط برای اعداد صحیح نیست. می‌توانیم قسمت اعشاری نیز داشته باشیم. در سمت راست نقطه باینری، توان‌ها از 2⁻¹ شروع می‌شوند.

0.101₂

= 1×2⁻¹ + 0×2⁻² + 1×2⁻³
= 0.5 + 0 + 0.125
= 0.625₁₀

پس:

0.101₂ = 0.625₁₀

جمع باینری

قواعد جمع باینری بسیار ساده هستند:

عمل نتیجه Carry
0 + 000
0 + 110
1 + 010
1 + 101

حالت آخر بسیار مهم است:

1 + 1 = 10₂

یعنی نتیجه در همان ستون 0 است و یک Carry به ستون بعدی منتقل می‌شود.

مثال

1011
+ 0110
──────
10001

در ده‌دهی:

11 + 6 = 17

و:

17₁₀ = 10001₂

تفریق باینری

قواعد اصلی:

عمل نتیجه
0 − 00
1 − 01
1 − 10
0 − 1نیازمند Borrow

در سخت‌افزار، تفریق معمولاً با روش Two’s Complement به یک جمع تبدیل می‌شود؛ به همین دلیل مفهوم مکمل دو بسیار مهم است.

One’s Complement

برای به‌دست‌آوردن مکمل یک، تمام بیت‌ها را معکوس می‌کنیم:

10110010
↓ NOT
01001101

یعنی:

0 → 1
1 → 0

Two’s Complement

برای به‌دست‌آوردن Two’s Complement:

  1. تمام بیت‌ها را معکوس می‌کنیم.
  2. یک واحد به نتیجه اضافه می‌کنیم.

مثلاً:

عدد اصلی:
00101100

مکمل یک:
11010011

+ 1
──────
11010100

پس Two’s Complement عدد 00101100 برابر 11010100 است.

Two’s Complement یکی از مهم‌ترین روش‌های نمایش اعداد صحیح علامت‌دار در سیستم‌های دیجیتال و پردازنده‌ها است.

چرا Two’s Complement مهم است؟

فرض کنید می‌خواهیم:

7 − 3

را با سخت‌افزار انجام دهیم. به جای ساختن یک مدار کاملاً جدا برای تفریق، می‌توانیم از مکمل دو استفاده کنیم:

7 − 3 = 7 + (-3)

یعنی عملیات تفریق را به یک عملیات جمع تبدیل می‌کنیم. این ایده در طراحی ALU اهمیت بسیار زیادی دارد.

اعداد بدون علامت و علامت‌دار

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

مثلاً برای 8 بیت:

Unsigned: از 0 تا 255
Signed Two’s Complement: از −128 تا +127

این تفاوت در برنامه‌نویسی سطح پایین، معماری CPU و طراحی سخت‌افزار بسیار مهم است.

Overflow چیست؟

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

مثلاً در یک عدد Unsigned هشت‌بیتی، بیشترین مقدار:

11111111₂ = 255₁₀

اگر یک واحد دیگر اضافه کنیم:

11111111
+ 1
────────
1 00000000

اگر فقط 8 بیت را نگه داریم، نتیجه:

00000000

است و Carry از محدوده 8 بیت خارج شده است.

Bitwise چیست؟

در برنامه‌نویسی و سخت‌افزار، گاهی عملیات مستقیماً روی تک‌تک بیت‌ها انجام می‌شود. به این عملیات Bitwise Operation می‌گوییم.

مهم‌ترین عملیات Bitwise عبارت‌اند از:

AND
OR
XOR
NOT
Shift Left
Shift Right

AND، OR و XOR در Binary

A B AND OR XOR
00000
01011
10011
11110

در XOR فقط زمانی خروجی 1 است که ورودی‌ها با هم متفاوت باشند.

A XOR B = 1
اگر A ≠ B

Shift چیست؟

در Shift، بیت‌ها به چپ یا راست جابه‌جا می‌شوند.

Left Shift

0011 << 1

0110

در بسیاری از شرایط، Left Shift یک بیت معادل ضرب در 2 است؛ البته با توجه به اندازه داده و Overflow باید مراقب محدوده باشیم.

Right Shift

1100 >> 1

0110

در اعداد Unsigned، Right Shift معمولاً اثر تقسیم بر 2 را دارد. برای اعداد Signed، نوع Shift و نحوه پر شدن بیت جدید اهمیت دارد.

ترکیب بیت‌ها و ساخت داده‌های بزرگ‌تر

یکی از مفاهیم مهم در طراحی سخت‌افزار این است که چند بیت می‌توانند کنار هم قرار بگیرند و یک داده بزرگ‌تر بسازند.

1 Bit → 2 حالت
2 Bit → 4 حالت
4 Bit → 16 حالت
8 Bit → 256 حالت
16 Bit → 65,536 حالت
32 Bit → حدود 4.29 میلیارد حالت

برای مثال یک رجیستر 32 بیتی می‌تواند 32 بیت را هم‌زمان نگهداری کند. در طراحی CPU، اندازه Registerها، ALU، Bus و بسیاری از واحدهای دیگر با تعداد بیت‌ها ارتباط مستقیم دارد.

Nibble چیست؟

هر 4 بیت را یک Nibble می‌نامیم.

4 bit = 1 Nibble
2 Nibble = 1 Byte

به همین دلیل تبدیل Binary و Hexadecimal بسیار راحت است: هر Nibble دقیقاً یک رقم Hex را تشکیل می‌دهد.

رابطه Binary با حافظه

در مباحث قبلی RAM را بررسی کردیم. حافظه از تعداد زیادی سلول تشکیل شده و هر سلول می‌تواند داده را نگه دارد. در سطح معماری، معمولاً یک Address مشخص می‌کند به کدام محل حافظه دسترسی داریم و Data مقدار ذخیره‌شده را مشخص می‌کند.

Address

Memory

Data

خود Address و Data نیز مجموعه‌ای از بیت‌ها هستند. بنابراین Binary مستقیماً با نحوه آدرس‌دهی و انتقال داده در سیستم ارتباط دارد.

چرا Hexadecimal در مهندسی کامپیوتر خیلی مهم است؟

فرض کنید یک مقدار 32 بیتی داریم:

11010110101011110000111110101100

خواندن این مقدار برای انسان سخت است. اما با تبدیل هر چهار بیت به یک رقم Hex:

D6AF0FAC

نمایش بسیار کوتاه‌تر و قابل‌خواندن‌تر می‌شود. به همین دلیل در Debuggerها، Memory Addressها، Registerها، Opcodeها و بسیاری از ابزارهای مهندسی کامپیوتر با اعداد Hex زیاد روبه‌رو می‌شویم.

یک نکته مهم درباره نمایش داده

یک الگوی بیتی می‌تواند بسته به نحوه تفسیر، معنی‌های متفاوتی داشته باشد. مثلاً:

01000001

می‌تواند به‌عنوان یک عدد Unsigned برابر 65 باشد؛ اما همین الگو در ASCII متناظر با یک کاراکتر است.

پس بیت‌ها خودشان «معنی» ندارند. معنی بیت‌ها را نحوه تفسیر آن‌ها در سیستم مشخص می‌کند. این موضوع یکی از مفاهیم بسیار مهم در معماری کامپیوتر است.

جمع‌بندی مفاهیم مهم

مفهوم نکته اصلی
Bitکوچک‌ترین واحد دودویی، 0 یا 1
Byte8 بیت
Nibble4 بیت
Binaryمبنای 2
Decimalمبنای 10
Octalمبنای 8
Hexadecimalمبنای 16
MSBباارزش‌ترین بیت
LSBکم‌ارزش‌ترین بیت
Carryانتقال در جمع
Borrowقرض گرفتن در تفریق
One’s Complementمعکوس کردن بیت‌ها
Two’s Complementمکمل یک + یک
Overflowخارج شدن نتیجه از محدوده قابل نمایش
Bitwiseعملیات مستقیم روی بیت‌ها
XORخروجی 1 وقتی دو ورودی متفاوت باشند

نقشه ذهنی این بخش

Binary

Bit / Byte / Nibble

Base 2 / 8 / 10 / 16

تبدیل مبناها

جمع و تفریق

One’s Complement / Two’s Complement

Signed / Unsigned / Overflow

Bitwise Operations

Logic Gates

Combinational Circuits

ALU / CPU / FPGA

چرا این مباحث برای FPGA و Verilog مهم هستند؟

وقتی وارد Verilog و FPGA شویم، دیگر فقط با اعداد معمولی سر و کار نداریم. با Bit، Vector، Register، Bus، Binary، Hex، Signed و Unsigned کار خواهیم کرد.

برای مثال ممکن است در Verilog بنویسیم:

logic [7:0] a;
logic [7:0] b;
logic [7:0] result;

assign result = a + b;

اینجا [7:0] یعنی یک مقدار 8 بیتی داریم. در ادامه مسیر، همین مفهوم ساده به طراحی Register، ALU، Counter، Memory Interface و در نهایت CPU و پروژه FPGA تبدیل می‌شود.

مسیر یادگیری از اینجا:
Binary → Boolean Logic → Logic Gates → Truth Table → SOP/POS → Combinational Circuits → K-Map → Sequential Circuits → Registers/Counter → ALU → CPU → Verilog → FPGA