পাঠ ১২ · ৫৭-এর মধ্যে · মডিউল ২
Home / Courses / Computer Architecture & Digital Logic / কম্প্যারেটর ও প্যারিটি

কম্প্যারেটর ও প্যারিটি সার্কিট

Comparator & parity circuit
৭ মিনিট পড়া শুরু · Beginner Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • ডিজিটাল কম্প্যারেটর কীভাবে MSB থেকে শুরু করে বিট-বাই-বিট তুলনা করে A>B / A=B / A<B নির্ধারণ করে
  • ইকুয়ালিটি কম্প্যারেটর বনাম ম্যাগনিচিউড কম্প্যারেটরের পার্থক্য
  • প্যারিটি বিট কী, even ও odd parity কীভাবে গণনা ও চেক করা হয়
  • প্যারিটির বাস্তব সীমাবদ্ধতা — কী ধরনের এরর ধরা পড়ে, কোনটা ধরা পড়ে না

১ · ডিজিটাল কম্প্যারেটর — MSB থেকে বিট-বাই-বিট তুলনা

ডিজিটাল কম্প্যারেটরDigital Comparatorদুটি বাইনারি সংখ্যা ইনপুট হিসেবে নিয়ে সেগুলোর মধ্যে সম্পর্ক (বড়/সমান/ছোট) নির্ধারণ করে এমন একটি কম্বিনেশনাল সার্কিট। দুটি বাইনারি সংখ্যা A ও B তুলনা করে বলে দেয় A বড়, নাকি সমান, নাকি ছোট। এই তুলনাটা ঠিক ডিকশনারিতে দুটো শব্দ বর্ণানুক্রমে (lexicographically) তুলনা করার মতোই — প্রথম যে বিট পজিশনে দুটো সংখ্যা ভিন্ন হয়, সেখানেই ফলাফল নির্ধারিত হয়ে যায়। এই তুলনা শুরু হয় সবচেয়ে বাম দিকের বিট, অর্থাৎ MSBMost Significant Bitএকটি বাইনারি সংখ্যার সবচেয়ে বড় স্থানমান (place value) বহনকারী বিট — সবচেয়ে বাম দিকের বিট। থেকে — কারণ MSB-ই সবচেয়ে বেশি স্থানমান বহন করে। যদি একটি বিট পজিশনে A এর বিট B এর চেয়ে বড় হয়, তাহলে বাকি বিটগুলো না দেখেই বলে দেওয়া যায় A>B — ঠিক যেমন "ব্যাঘ্র" শব্দটা "ব্যতিক্রম"-এর চেয়ে বড় কি না তা প্রথম ভিন্ন অক্ষরেই বোঝা যায়।

ইকুয়ালিটি কম্প্যারেটর
শুধু বলে A ও B সমান কি না — প্রতিটি বিট-জোড়ায় XNOR নিয়ে সবগুলোর AND করলেই ফল পাওয়া যায় (সব বিট মিলে গেলে সব XNOR=1, তাই AND-ও 1)।
ম্যাগনিচিউড কম্প্যারেটর
শুধু সমান কি না নয়, বরং কোনটা বড় সেটাও বলে দেয় — MSB থেকে শুরু করে প্রথম ভিন্ন বিটেই ফলাফল নির্ধারিত হয়।
MSB থেকে বিট পজিশন i=0 শুরু A[i] ও B[i] তুলনা করো A[i]>B[i] → ফল A>B A[i]=B[i] → পরের বিটে যাও A[i]<B[i] → ফল A<B সব বিট শেষ, কখনো ভিন্ন হয়নি → ফল A=B
প্রথম যে বিটে A ও B ভিন্ন হয়, সেখানেই সিদ্ধান্ত হয়ে যায় — বাকি বিট দেখার দরকার পড়ে না।

২ · প্যারিটি বিট — সবচেয়ে সরল এরর-ডিটেকশন কৌশল

প্যারিটি বিটParity Bitএকগুচ্ছ ডেটা বিটের সাথে যোগ করা একটি অতিরিক্ত বিট, যার মান নির্ধারিত হয় মোট 1-বিটের সংখ্যা জোড় বা বিজোড় রাখার লক্ষ্যে। হলো এমন একটি অতিরিক্ত বিট যা ডেটার সাথে যোগ করা হয় যাতে মোট 1-বিটের সংখ্যা সবসময় জোড় (even parity) অথবা সবসময় বিজোড় (odd parity) থাকে। এই বিটটা গণনা করা হয় সব ডেটা বিটের XOR নিয়ে —

$P = d_0 \oplus d_1 \oplus \cdots \oplus d_{n-1}$

even parity-র জন্য parity বিট P সরাসরি এই XOR-এর ফলাফল, odd parity-র জন্য এর উল্টো (complement)। রিসিভার পাশে আবার সব বিট (ডেটা + parity) মিলিয়ে XOR নিলে, যদি ফলাফল প্রত্যাশিত মান (even হলে 0) না হয়, তাহলে বোঝা যায় ট্রান্সমিশনের সময় কোথাও একটা বিট পাল্টে গেছে।

সীমাবদ্ধতা — যা প্যারিটি করতে পারে না

প্যারিটি বিট শুধু একটি বিট ফ্লিপ হলে সেটা ধরতে পারে — কোনটা ফ্লিপ হয়েছে সেটা বলতে পারে না, তাই সংশোধন করা সম্ভব নয়। আরও গুরুত্বপূর্ণ সীমাবদ্ধতা: যদি ঠিক দুটি বিট একসাথে ফ্লিপ হয়, তাহলে দুটো ফ্লিপ একে অপরকে "ক্যানসেল" করে ফেলে (XOR-এ দুটো পরিবর্তন মিলে আবার আগের মানে ফিরে আসে) — parity চেক পাস করে যায়, অথচ ডেটা আসলে ভুল। এই কারণেই বাস্তব সিস্টেমে আরও শক্তিশালী এরর-কারেক্টিং কোড (এই কোর্সের সিলেবাসের বাইরে) ব্যবহার করা হয়।

৩ · কোড সেলে যাচাই — কম্প্যারেটর ও প্যারিটি

নিচের কোড সেলে compare() ফাংশনটি MSB-first বিট তুলনা বাস্তবায়ন করে এবং প্রতিটি ফলাফল সরাসরি পূর্ণাঙ্গ ইন্টিজার তুলনার বিপরীতে যাচাই করা হয়েছে। এরপর compute_parity() ও check_parity() দিয়ে দেখানো হবে একটি বিট ফ্লিপ কীভাবে ধরা পড়ে, আর দুটি বিট ফ্লিপ কীভাবে সীমাবদ্ধতা হিসেবে অধরা থেকে যায়।

Python
def compare(a_bits, b_bits):
    """MSB-first বিট-বাই-বিট তুলনা -- প্রথম differing বিট থেকেই ফলাফল বের হয়"""
    for a, b in zip(a_bits, b_bits):
        if a > b:
            return "A>B"
        if a < b:
            return "A<B"
    return "A=B"

def bits_to_int(bits):
    value = 0
    for b in bits:
        value = value * 2 + b
    return value

test_pairs = [
    ([1, 0, 1, 1], [1, 0, 0, 1]),   # 11 বনাম 9
    ([0, 1, 1, 0], [0, 1, 1, 0]),   # 6 বনাম 6
    ([0, 0, 1, 1], [0, 1, 0, 0]),   # 3 বনাম 4
]

print("কম্প্যারেটর যাচাই (MSB-first বিট তুলনা বনাম পূর্ণাঙ্গ ইন্টিজার তুলনা)")
print("-" * 62)
for a_bits, b_bits in test_pairs:
    result = compare(a_bits, b_bits)
    a_val, b_val = bits_to_int(a_bits), bits_to_int(b_bits)
    expected = "A>B" if a_val > b_val else ("A<B" if a_val < b_val else "A=B")
    match = "মিলেছে" if result == expected else "গরমিল!"
    print(f"A={a_bits} ({a_val:2d})  B={b_bits} ({b_val:2d})  -> {result}  (প্রত্যাশিত {expected}, {match})")

print()
print("প্যারিটি বিট -- এরর ডিটেকশন")
print("-" * 62)

def compute_parity(data_bits, even=True):
    """even parity: সব ডেটা বিটের XOR-ই parity বিট -- মোট 1-এর সংখ্যা জোড় রাখে
       odd parity: তার উল্টো (complement)"""
    x = 0
    for b in data_bits:
        x ^= b
    return x if even else 1 - x

def check_parity(data_bits_with_parity, even=True):
    x = 0
    for b in data_bits_with_parity:
        x ^= b
    expected = 0 if even else 1
    return x == expected

data = [1, 0, 1, 1, 0, 1]   # 4 টি 1 -- ইতিমধ্যে জোড়
p = compute_parity(data, even=True)
transmitted = data + [p]
print(f"ডেটা বিট: {data}  |  even parity বিট: {p}  |  পাঠানো ফ্রেম: {transmitted}")
print(f"রিসিভারে চেক (বিট ফ্লিপ ছাড়া): {'পাস' if check_parity(transmitted, even=True) else 'ফেইল'}")

corrupted = transmitted.copy()
corrupted[2] = 1 - corrupted[2]   # ঠিক একটি বিট ফ্লিপ
print(f"একটি বিট ফ্লিপ করার পর: {corrupted}")
print(f"রিসিভারে চেক (১ বিট ফ্লিপ): {'পাস' if check_parity(corrupted, even=True) else 'ফেইল -- এরর সঠিকভাবে ধরা পড়েছে'}")

double_corrupted = transmitted.copy()
double_corrupted[1] = 1 - double_corrupted[1]
double_corrupted[4] = 1 - double_corrupted[4]
print(f"দুটি বিট ফ্লিপ করার পর: {double_corrupted}")
result = check_parity(double_corrupted, even=True)
print(f"রিসিভারে চেক (২ বিট ফ্লিপ): {'পাস -- সীমাবদ্ধতা! এরর ধরা পড়েনি' if result else 'ফেইল'}")

    
লক্ষ্য করুন শেষ অংশে — একটি বিট ফ্লিপ হলে check_parity() ঠিকই "ফেইল" রিটার্ন করে (এরর ধরা পড়েছে), কিন্তু দুটি বিট একসাথে ফ্লিপ হলে XOR-এর হিসাবে দুটো পরিবর্তন একে অপরকে কাটাকাটি করে ফেলে এবং চেক "পাস" দেখায় — অথচ ডেটা আসলে ভুল। এটাই কোডে-যাচাইকৃত প্রমাণ যে প্যারিটির সীমাবদ্ধতা নিছক তত্ত্ব নয়, বাস্তব।
মূল কথা · Key takeaway

কম্প্যারেটর ও প্যারিটি সার্কিট দুটোই কম্বিনেশনাল — কোনো মেমরি নেই, আউটপুট শুধু বর্তমান ইনপুটের উপর নির্ভর করে। এখানেই মডিউল ২ শেষ হচ্ছে। পরের পাঠ থেকে শুরু হবে এমন সার্কিট যেগুলোর মেমরি আছে — একই ইনপুট দিলেও আউটপুট আলাদা হতে পারে, কারণ সার্কিট তার অতীত অবস্থা মনে রাখে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ কম্প্যারেটরে কেন MSB থেকে তুলনা শুরু হয় — LSB থেকে শুরু করলে কী সমস্যা হতো?

MSB সবচেয়ে বেশি স্থানমান বহন করে, তাই MSB-তেই প্রথম ভিন্নতা পাওয়া গেলে বাকি সব বিট না দেখেই চূড়ান্ত ফলাফল নিশ্চিত করা যায় — যেমন 1011 বনাম 0111-এ প্রথম বিটেই A বড় বলে জানা যায়, বাকি তিন বিট গুরুত্বহীন। LSB থেকে শুরু করলে প্রতিটি বিট পরীক্ষা করেও চূড়ান্ত সিদ্ধান্তে নিশ্চিত হওয়া যেত না, কারণ পরের (আরও বড় স্থানমানের) বিটগুলো পুরো ফলাফল উল্টে দিতে পারত — তাই পুরো তুলনাটাই অর্থহীন জটিল হয়ে যেত।

প্র ০২ যদি প্যারিটি বিট শুধু "ধরতে" পারে, "ঠিক" করতে পারে না, তাহলে ধরা পড়া এরর নিয়ে বাস্তবে কী করা হয়?

সাধারণত রিসিভার সেই ফ্রেমটি বাতিল করে এবং পাঠানোর পক্ষকে (sender) পুনরায় পাঠানোর অনুরোধ জানায় — "retransmission" — কারণ কোনটি ভুল বিট তা পার্সিটি বিট দিয়ে বোঝার উপায় নেই, শুধু এটুকু বোঝা যায় যে কোথাও একটা ভুল ঘটেছে। প্রকৃত এরর-সংশোধনের (correction) জন্য আরও জটিল কোড — যেমন Hamming code — দরকার হয়, যা একাধিক প্যারিটি বিট কৌশলগতভাবে সাজিয়ে ভুল বিটের অবস্থানও বলে দিতে পারে (এই কোর্সের সিলেবাসের বাইরে, তবে concept-টা এখান থেকেই শুরু)।

প্র ০৩ কোড সেলের শেষ পরীক্ষায় দুটি বিট ফ্লিপ করার পরও চেক কেন "পাস" দেখাল — এটা কি বাগ?

বাগ নয় — এটাই প্যারিটির গাণিতিক সীমাবদ্ধতা। XOR অপারেশনে একই পজিশনে দুইবার পরিবর্তন ঘটলে সেগুলো একে অপরকে বাতিল করে দেয় (x ^ 1 ^ 1 = x)। দুটো ভিন্ন পজিশনে দুটো বিট ফ্লিপ হলেও সামগ্রিক XOR-এর ফলাফলে মোট 1-এর সংখ্যার parity (জোড়/বিজোড়) অপরিবর্তিত থাকে — তাই একক-বিট প্যারিটি চেক এই ধরনের জোড়-সংখ্যক ফ্লিপ কখনোই ধরতে পারে না। এটাই কোড দিয়ে হাতেকলমে প্রমাণিত হলো, নিছক তাত্ত্বিক দাবি নয়।

অনুশীলন

  1. হাতে করুন: A=1101 (দশমিক 13) ও B=1100 (দশমিক 12) — MSB থেকে বিট-বাই-বিট তুলনা করে হাতে দেখান কোন বিট পজিশনে ফলাফল নির্ধারিত হয়, এবং তা কি উপরের কোডের ফলাফলের সাথে মিলবে বলে মনে হয়?

    বিট ০ (MSB): A=1, B=1 — সমান, চালিয়ে যান। বিট ১: A=1, B=1 — সমান, চালিয়ে যান। বিট ২: A=0, B=0 — সমান, চালিয়ে যান। বিট ৩ (LSB): A=1, B=0 — A বড়, তাই ফলাফল A>B। যেহেতু প্রথম তিন বিট সমান এবং চতুর্থ (শেষ) বিটেই পার্থক্য, তুলনাটা একদম শেষ পজিশন পর্যন্ত চলবে — compare() ফাংশন ঠিক এই লজিকই অনুসরণ করে "A>B" রিটার্ন করবে, যা 13>12-এর সাথেও মেলে।

  2. চিন্তা করুন: odd parity ব্যবহার করলে (even parity নয়) উপরের কোডের data = [1, 0, 1, 1, 0, 1] উদাহরণে parity বিটের মান কী হতো, এবং কেন?

    এই ডেটায় 1-এর সংখ্যা ৪টি (ইতিমধ্যে জোড়)। even parity হলে parity বিট 0 হয় (যাতে মোট 1-সংখ্যা জোড়ই থাকে — ৪+0=৪, জোড়)। odd parity হলে ঠিক তার উল্টো দরকার — parity বিট 1 হতে হবে, যাতে মোট 1-সংখ্যা বিজোড় হয় (৪+1=৫, বিজোড়)। কোডের compute_parity() ফাংশনে even=False দিলে এটাই ঘটবে, কারণ ফাংশনটি XOR-এর ফলাফলের complement রিটার্ন করে (1 - x) যখন even=False।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
এনকোডার ও ডিকোডার