ল্যাচ — SR ল্যাচ ও D ল্যাচ
এই পাঠে যা শিখবেন
- কম্বিনেশনাল বনাম সিকোয়েনশিয়াল সার্কিটের মৌলিক পার্থক্য — মেমরি কী এবং কেন গুরুত্বপূর্ণ
- SR ল্যাচের Set/Reset/Hold আচরণ এবং কেন S=R=1 অবৈধ
- D ল্যাচ কীভাবে Enable সিগন্যাল দিয়ে এই সমস্যা এড়িয়ে যায়
- Python ক্লাসে প্রকৃত স্টেট-হোল্ডিং আচরণ বাস্তবায়ন ও একটি বাস্তব সিকোয়েন্স ট্রেস করে যাচাই
১ · কম্বিনেশনাল বনাম সিকোয়েনশিয়াল সার্কিট
M1 থেকে M2 পর্যন্ত (লজিক গেট, অ্যাডার, মাল্টিপ্লেক্সার, কম্প্যারেটর) — যা কিছু শিখেছেন সবই কম্বিনেশনাল সার্কিটCombinational Circuitযে সার্কিটের আউটপুট শুধুমাত্র বর্তমান ইনপুটের একটি pure ফাংশন — কোনো মেমরি নেই, একই ইনপুট বারবার দিলে সবসময় একই আউটপুট পাওয়া যায়। — এদের আউটপুট শুধুই বর্তমান ইনপুটের একটি pure ফাংশন। একই ইনপুট হাজার বার দিলেও আউটপুট প্রতিবার একই হবে। কিন্তু বাস্তব কম্পিউটারের একটা মৌলিক প্রয়োজন আছে যা কম্বিনেশনাল সার্কিট দিয়ে সম্ভব নয় — মনে রাখা। একটি রেজিস্টারের মান, একটি প্রোগ্রাম কাউন্টার, একটি ক্যাশ লাইন — এসবের প্রতিটাই অতীতে কী ঘটেছে তার উপর নির্ভর করে বর্তমান আউটপুট দেয়।
সিকোয়েনশিয়াল সার্কিটSequential Circuitযে সার্কিটের আউটপুট বর্তমান ইনপুট এবং সার্কিটের অভ্যন্তরীণ অতীত অবস্থা (state) — দুটোর উপরই নির্ভর করে। ঠিক এই ফাঁকটাই পূরণ করে — একই ইনপুট দিলেও, সার্কিটের ভেতরে সংরক্ষিত অবস্থার উপর ভিত্তি করে ভিন্ন ভিন্ন সময়ে ভিন্ন আউটপুট পাওয়া সম্ভব। M3-এর পাঁচটি পাঠ (L13-17) ঠিক এই সিকোয়েনশিয়াল সার্কিটের বিল্ডিং ব্লকগুলোই একে একে বানাবে — ল্যাচ থেকে শুরু করে ফাইনাইট স্টেট মেশিন পর্যন্ত।
২ · SR ল্যাচ — সবচেয়ে সরল মেমরি এলিমেন্ট
SR ল্যাচ তৈরি হয় দুটি গেট (সাধারণত NOR বা NAND) কে cross-coupled করে — অর্থাৎ প্রথম গেটের আউটপুট দ্বিতীয় গেটের একটি ইনপুটে ফিডব্যাক হয়, আর দ্বিতীয় গেটের আউটপুট প্রথম গেটের একটি ইনপুটে ফিডব্যাক হয়। এই ফিডব্যাক লুপটাই মেমরির উৎস — যখন বাইরের ইনপুট (S ও R) দুটোই 0 থাকে, তখনো গেট দুটো একে অপরের আগের আউটপুট "মনে রেখে" নিজেদের অবস্থা ধরে রাখে।
Q জোর করে 1 করে দেয়, S=1 থাকা অবস্থায় Q=1-ই থাকবে।
Q জোর করে 0 করে দেয়।
Q তার আগের মান অপরিবর্তিত রাখে — এটাই আসল মেমরি আচরণ।
Set আর Reset দুটোই একসাথে দাবি করা — ফলাফল অনির্ধারিত (undefined), মৌলিক SR ল্যাচে এড়িয়ে চলতে হয়।
৩ · D ল্যাচ — অবৈধ অবস্থার সমস্যা সমাধান
D ল্যাচD Latch (Data Latch)একক D ইনপুট এবং একটি Enable সিগন্যাল ব্যবহার করে তৈরি ল্যাচ — Enable সক্রিয় থাকলে Q, D অনুসরণ করে; না থাকলে Q তার আগের মান ধরে রাখে। SR ল্যাচের সেই বিরক্তিকর সমস্যাটাই দূর করে দেয় — S ও R নামের দুটো আলাদা ইনপুটের বদলে এখানে থাকে একটাই ডেটা ইনপুট D, আর একটা Enableযখন সক্রিয় (1), তখনই ল্যাচ D-এর মান গ্রহণ করে; নিষ্ক্রিয় (0) থাকলে ল্যাচ তার আগের মান ধরে রাখে, D যা-ই হোক না কেন। সিগন্যাল। যখন Enable=1, তখন Q সরাসরি D অনুসরণ করে (যেমন একটা স্বচ্ছ দরজা খোলা)। যখন Enable=0, তখন Q তার শেষ মান আটকে রাখে, D যতই বদলাক না কেন (দরজা বন্ধ)। যেহেতু S=R=1-এর মতো কোনো দ্বন্দ্বমূলক ইনপুট কম্বিনেশনই এখানে সম্ভব নয়, তাই অবৈধ অবস্থার সমস্যাটা পুরোপুরি এড়িয়ে যাওয়া যায় — একটা প্রকৃত, ব্যবহারিক উন্নতি।
SR ও D — দুই ল্যাচই level-triggered: Enable যতক্ষণ উঁচু (high) থাকে, ততক্ষণ Q পরিবর্তন হতেই থাকতে পারে, D যতবার বদলায়। এই ধারাবাহিক সংবেদনশীলতা বড় সিস্টেমে টাইমিং সমস্যা তৈরি করতে পারে। পরের পাঠে (L14) দেখবেন ফ্লিপ-ফ্লপ কীভাবে এর বদলে শুধু একটি নির্দিষ্ট ক্লক-এজ মুহূর্তে সাড়া দিয়ে এই সমস্যা সমাধান করে।
৪ · কোড সেলে যাচাই — genuine স্টেট-হোল্ডিং আচরণ
নিচের কোডে SRLatch ও DLatch ক্লাস দুটোর .q অ্যাট্রিবিউট সত্যিকারের
অবস্থা ধরে রাখে — প্রতিটি update() কলের আগে-পরের মান প্রিন্ট করে দেখানো হচ্ছে hold আচরণ
সত্যিই কাজ করছে কি না।
class SRLatch:
"""cross-coupled গেট দিয়ে তৈরি SR ল্যাচের আচরণ সিমুলেট করে -- .q আসল স্টেট মনে রাখে"""
def __init__(self, initial_q=0):
self.q = initial_q
def update(self, s, r):
if s == 1 and r == 1:
raise ValueError("S=R=1 -- SR ল্যাচের জন্য অবৈধ অবস্থা (ফলাফল undefined)")
if s == 1 and r == 0:
self.q = 1 # Set
elif s == 0 and r == 1:
self.q = 0 # Reset
# s == 0 and r == 0 -> Hold, .q অপরিবর্তিত থাকে
return self.q
class DLatch:
"""একক D ইনপুট + Enable -- enable=1 হলে Q, D অনুসরণ করে; enable=0 হলে Q hold করে"""
def __init__(self, initial_q=0):
self.q = initial_q
def update(self, d, enable):
if enable:
self.q = d # Enable সক্রিয় -- Q, D অনুসরণ করে
# enable=0 -> Hold, .q অপরিবর্তিত থাকে (D যা-ই হোক না কেন)
return self.q
print("SR ল্যাচ -- Set, Hold, Reset আচরণ ধাপে ধাপে যাচাই")
print("-" * 60)
sr = SRLatch(initial_q=0)
sequence = [(1, 0, "Set"), (0, 0, "Hold"), (0, 0, "Hold"), (0, 1, "Reset"), (0, 0, "Hold")]
for s, r, label in sequence:
before = sr.q
after = sr.update(s, r)
print(f"S={s} R={r} ({label:5s}) | আগে Q={before} -> পরে Q={after}")
print()
print("SR ল্যাচের অবৈধ অবস্থা (S=R=1) -- silently ভুল ফলাফল না দিয়ে explicit ভাবে ধরা হচ্ছে")
try:
sr.update(1, 1)
except ValueError as e:
print(f"ValueError ধরা পড়েছে: {e}")
print()
print("D ল্যাচ -- enable=0 অবস্থায় D পাল্টালেও Q hold করে")
print("-" * 60)
dl = DLatch(initial_q=0)
d_sequence = [
(1, 1, "enable=1 -> Q, D=1 অনুসরণ করে"),
(0, 0, "enable=0 -> D=0 বললেও Q hold করে (আগের মান রাখে)"),
(0, 0, "enable=0 -> এখনও hold করছে"),
(0, 1, "enable=1 -> এখন Q, D=0 অনুসরণ করে"),
]
for d, enable, label in d_sequence:
before = dl.q
after = dl.update(d, enable)
print(f"D={d} enable={enable} | {label} | আগে Q={before} -> পরে Q={after}")
enable=0, এবং D=0 বলা সত্ত্বেও Q তার
আগের মান (1) ধরে রেখেছে। শুধু চতুর্থ ধাপে যখন enable=1 হলো, তখনই Q আবার D অনুসরণ করে 0 হলো।
এটাই প্রমাণ করে hold আচরণ সত্যিই enable সিগন্যালের উপর নির্ভরশীল, D-এর উপর নয়।
SR ল্যাচ মেমরির সবচেয়ে মৌলিক রূপ দেখায় — cross-coupled ফিডব্যাক দিয়ে অবস্থা ধরে রাখা — কিন্তু S=R=1-এর অবৈধ অবস্থা রেখে যায়। D ল্যাচ সেই সমস্যা এড়িয়ে একটি ব্যবহারযোগ্য, নির্ভরযোগ্য মেমরি এলিমেন্ট দেয়, তবে এখনো level-triggered। পরের পাঠে (L14) এই একই ধারণা এজ-ট্রিগারড ফ্লিপ-ফ্লপে রূপান্তরিত হবে, যা CPU-এর মতো ক্লক-সিঙ্ক্রোনাইজড সিস্টেম বানানোর জন্য প্রকৃতপক্ষে প্রয়োজনীয়।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ S=R=0 দিলে SR ল্যাচ কীভাবে Q-এর মান "মনে রাখে" — কোথাও তো সেই মান আলাদাভাবে সংরক্ষিত নেই?
আসলে সংরক্ষণটা ঘটে cross-coupled ফিডব্যাক লুপেই — গেট ১-এর আউটপুট গেট ২-এর ইনপুটে যায়, আর গেট ২-এর আউটপুট আবার গেট ১-এর ইনপুটে ফিরে আসে। S=R=0 হলেও এই দুই গেট একে অপরের সাম্প্রতিক আউটপুট "খাইয়ে" নিজেদের বর্তমান আউটপুট বজায় রাখে — এটা একটা স্থিতিশীল (stable) ইলেকট্রিক্যাল লুপ, আলাদা কোনো "স্টোরেজ সেল" নেই। এই সহজ ফিডব্যাক কৌশলটাই ডিজিটাল মেমরির সবচেয়ে মৌলিক ভিত্তি।
প্র ০২ D ল্যাচ যদি SR ল্যাচের সব সমস্যা সমাধান করে দেয়, তাহলে SR ল্যাচ পড়ার দরকার কী ছিল?
কারণ D ল্যাচ আসলে SR ল্যাচের উপরেই তৈরি — বাস্তব হার্ডওয়্যারে একটা D ল্যাচ প্রায়ই একটা SR ল্যাচ প্লাস বাড়তি গেট দিয়ে বানানো হয় যা নিশ্চিত করে S ও R কখনো একসাথে 1 না হয় (যেমন S=D·Enable, R=D'·Enable)। SR ল্যাচ না বুঝলে D ল্যাচের ভেতরের প্রকৌশল-যুক্তিটাই বোঝা অসম্ভব — এটা ঠিক যেমন ফুল অ্যাডার বুঝতে হলে আগে হাফ অ্যাডার বুঝতে হয় (L08)।
প্র ০৩
কোড সেলে SRLatch.update() S=R=1 হলে ব্যতিক্রম (exception) ছুঁড়ে দেয় — বাস্তব হার্ডওয়্যারেও কি এমন কিছু "ছুঁড়ে দেওয়া" হয়?
না — বাস্তব হার্ডওয়্যারে কোনো "exception" নেই, বরং S=R=1 অবস্থায় দুটো গেটই তাদের আউটপুটে 1 (বা
গেট টাইপ অনুযায়ী 0) পাঠাতে চেষ্টা করে, এবং S=R=0-তে ফিরে গেলে ফলাফল কোন গেট আগে সুইচ করল তার
ইলেকট্রিক্যাল টাইমিং-এর উপর নির্ভর করে অনির্ধারিত (race condition) হয়ে যায়। কোডে আমরা
ValueError ছুঁড়ে সেই "বাস্তবে কী হবে বলা যায় না" পরিস্থিতিটাকে স্পষ্টভাবে চিহ্নিত করে
দিচ্ছি, যাতে ভুল করে একটা silently-wrong মান কোথাও প্রচার না হয়ে যায় — এটা একটা ইঞ্জিনিয়ারিং
সততা, বাস্তব সার্কিটের হুবহু অনুকরণ নয়।
অনুশীলন
-
হাতে ট্রেস করুন: একটি SR ল্যাচ শুরু হয় Q=0 দিয়ে। এই ইনপুট সিকোয়েন্সের প্রতিটি ধাপের পর Q-এর মান কী হবে হাতে লিখুন: (S=0,R=1), (S=0,R=0), (S=1,R=0), (S=0,R=0), (S=0,R=0)।
ধাপ ১ (S=0,R=1, Reset): Q=0 (আগে থেকেই 0, তাই অপরিবর্তিত মনে হলেও এটা আসলে "জোর করে 0")। ধাপ ২ (S=0,R=0, Hold): Q=0 থাকে। ধাপ ৩ (S=1,R=0, Set): Q=1 হয়ে যায়। ধাপ ৪ (S=0,R=0, Hold): Q=1 থাকে। ধাপ ৫ (S=0,R=0, Hold): Q=1-ই থাকে। চূড়ান্ত মান: Q=1 — কোডের
SRLatchক্লাসে এই ঠিক এই সিকোয়েন্স চালালে একই ফলাফল পাওয়া যাবে। -
চিন্তা করুন: D ল্যাচে যদি
enableসবসময় 1 (সবসময় সক্রিয়) রাখা হয়, তাহলে এটি কার্যত কেমন আচরণ করবে — তখন এটি কি এখনো "মেমরি" হিসেবে গণ্য হবে?enable সবসময় 1 থাকলে D ল্যাচ কার্যত একটা সাধারণ "wire" বা pass-through বাফারের মতো আচরণ করবে — Q সবসময় সরাসরি D-কে অনুসরণ করবে, কোনো hold ঘটবে না। এই অবস্থায় এটি সত্যিকারের মেমরি হিসেবে কাজ করে না, কারণ মেমরির সংজ্ঞাই হলো ইনপুট বদলে গেলেও পুরনো মান ধরে রাখতে পারা — যা enable=1 অবস্থায় সম্ভব নয়। মেমরির প্রকৃত সুবিধা পেতে হলে enable-কে নির্দিষ্ট সময়ে নিয়ন্ত্রিতভাবে 0/1 করতে হবে, যা বাস্তবে একটা ক্লক সিগন্যাল দিয়ে করা হয় (L14-এ বিস্তারিত)।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ মডিউল ৩ (সিকোয়েনশিয়াল সার্কিট) সবে শুরু হলো — ফ্লিপ-ফ্লপ, রেজিস্টার, কাউন্টার ও FSM পরবর্তী চার পাঠে।
- কম্প্যারেটর ও প্যারিটি সার্কিট আগের পাঠ মডিউল ২-এর শেষ পাঠ — কম্বিনেশনাল সার্কিটের সাথে এই পাঠের সিকোয়েনশিয়াল সার্কিটের পার্থক্য বুঝতে সহায়ক।
- ফ্লিপ-ফ্লপ — D, JK, T ফ্লিপ-ফ্লপ পরবর্তী পাঠ ল্যাচের level-triggered সীমাবদ্ধতা থেকে এজ-ট্রিগারড ফ্লিপ-ফ্লপে উত্তরণ — CPU সিঙ্ক্রোনাইজেশনের ভিত্তি।
- Operating Systems কোর্স সহোদর কোর্স প্রসেস স্টেট মেশিন (Ready/Running/Waiting) ধারণাগতভাবে এই পাঠের "স্টেট মনে রাখা" নীতির সফটওয়্যার-স্তরের প্রতিফলন।