এই পর্বে যা শিখবেন
- Combinational আর sequential circuit-এর পার্থক্য, আর feedback কীভাবে এক বিট ধরে রাখে
- NOR ও NAND দিয়ে SR latch, gated latch আর D latch — নিষিদ্ধ অবস্থা কেন সমস্যা, D latch কীভাবে তা দূর করে
- Level-sensitive বনাম edge-triggered — master–slave D flip-flop-এর ভেতরের কাজ, waveform ধরে ধরে
- SR, D, JK, T-এর characteristic ও excitation table, আর এক flip-flop দিয়ে আরেকটি বানানোর পদ্ধতি
- Asynchronous preset/clear, enable, setup-hold-এর প্রাথমিক ধারণা আর Verilog-এ flip-flop লেখার সঠিক নিয়ম
১ · Combinational থেকে sequential — যখন circuit-কে মনে রাখতে হয়
মডিউল ২-এ যত circuit বানিয়েছেন — adder, multiplexer, decoder, ALU — সবগুলোর একটি মিল আছে: output নির্ভর করে শুধু এই মুহূর্তের input-এর ওপর। এদের বলে combinational circuit. Input সরিয়ে নিলে output-ও হারিয়ে যায়; circuit-টি কিছুই মনে রাখে না।
কিন্তু একটি কম্পিউটারের অর্ধেক কাজই মনে রাখা। Program counter মনে রাখে পরের instruction কোথায়, register মনে রাখে হিসাবের ফল, মেমরি মনে রাখে আপনার ফাইল। যে circuit-এর output এই মুহূর্তের input আর অতীতের ইতিহাস — দুটির ওপর নির্ভর করে, তাকে বলে sequential circuit. অতীতের যে সারাংশটুকু circuit ধরে রাখে, তার নাম state (অবস্থা)।
ঘরের দেয়ালের সাধারণ বাতির সুইচ ভাবুন। সুইচ নিচে থাকলে বাতি জ্বলে, ওপরে থাকলে নেভে — বাতির অবস্থা সুইচের এখনকার অবস্থান দেখেই বলা যায়। এটি combinational. এবার ভাবুন অনেক টেবিল-ল্যাম্পের একটিমাত্র push-button: একবার চাপলে জ্বলে, আবার চাপলে নেভে। Button ছেড়ে দিলে সেটি সবসময় একই অবস্থায় ফিরে আসে — তবু ল্যাম্প জ্বলবে না নিভবে, তা বোঝা যায় না যতক্ষণ না জানেন আগে কতবার চাপা হয়েছে। ল্যাম্পের ভেতরের ছোট circuit-টি একটি বিট মনে রাখছে: “এখন জ্বলে আছি কি না।” এটি sequential.
ব্যাংকের টোকেন মেশিনও একই কথা বলে। আপনি বোতাম চাপলেন, পেলেন টোকেন ৫৭; পরের জন পেলেন ৫৮. দুজনের চাপ হুবহু এক, তবু উত্তর আলাদা — কারণ মেশিনটি মনে রেখেছে শেষ নম্বর কত ছিল। কাউন্টারের ডিসপ্লেও মনে রাখে এখন কোন নম্বর ডাকা হচ্ছে। “এখনকার input + মনে রাখা state → output আর নতুন state” — sequential circuit-এর পুরো সংজ্ঞা এই একটি বাক্যে।
Sequential circuit = combinational logic + স্মৃতি-উপাদান। Combinational অংশ হিসাব করে next state আর output; স্মৃতি-উপাদান সেই next state ধরে রাখে পরের বার পর্যন্ত। এই পর্বের বিষয় সেই স্মৃতি-উপাদান — latch আর flip-flop. পর্ব ১৬-এ এগুলো জুড়ে register আর counter, পর্ব ১৭-এ পূর্ণ finite state machine বানাবেন।
বেশিরভাগ ডিজিটাল নকশা synchronous: সব স্মৃতি-উপাদান একটি সাধারণ clock সংকেতের ছন্দে একসাথে নতুন মান নেয়, ঠিক যেন রেলস্টেশনের ঘণ্টা বাজলে সব ট্রেন একসাথে ছাড়ে। Clock ছাড়া, যেকোনো সময় বদলাতে পারা নকশাকে বলে asynchronous. এই পর্বে দুটিই দেখবেন: latch-গুলো মূলত clock ছাড়া (বা clock-এর স্তর দেখে) চলে, আর flip-flop চলে clock-এর ধার দেখে।
এই পর্বের প্রতীক: কোনো সংকেতের উল্টো লেখা হবে prime দিয়ে — Q′ মানে NOT Q, যেমন পর্ব ০৭-এ। কোডে লেখা হবে ~q বা !q. Q+ (কোথাও Q(t+1) লেখা হয়) মানে পরের clock ধারের পর বা input-এর সাড়া স্থির হওয়ার পর Q-এর মান। ⊕ মানে XOR.
২ · Feedback আর দুই স্থির অবস্থা — দুটি inverter-এর লুপ
স্মৃতি বানানোর সবচেয়ে ছোট উপায়টি দেখতে প্রায় হাস্যকর রকম সরল। দুটি inverter নিন। প্রথমটির output দ্বিতীয়টির input-এ দিন, আর দ্বিতীয়টির output আবার প্রথমটির input-এ ফিরিয়ে দিন। বাইরে থেকে কোনো input নেই — শুধু একটি লুপ। একে বলে feedback.
এখন হিসাব করুন। ধরুন প্রথম inverter-এর output (নাম দিই Q) = 1. তাহলে দ্বিতীয়টির input 1, output 0. সেই 0 প্রথমটির input, তাই প্রথমটির output 1 — যা দিয়ে শুরু করেছিলাম! লুপটি নিজেকে নিজে সমর্থন করছে। আবার Q = 0 ধরলে দ্বিতীয়টির output 1, প্রথমটির output 0 — এটিও নিজেকে সমর্থন করে। অর্থাৎ এই circuit-এর ঠিক দুটি স্থির অবস্থা আছে: (Q, Q′) = (1, 0) অথবা (0, 1). দুই স্থির অবস্থার এমন circuit-কে বলে bistable, আর যেকোনোটিতে একবার পড়লে সে সেখানেই থাকে, যতক্ষণ বিদ্যুৎ আছে। একটি বিট মনে রাখার জন্য এর চেয়ে বেশি কিছু লাগে না।
একটি দুই দিকে হেলানো সুইচবোর্ডের টগল সুইচ ভাবুন, যার ভেতরে একটি স্প্রিং আছে: সুইচ হয় পুরো ওপরে, নয় পুরো নিচে থাকে — মাঝখানে রাখলে স্প্রিং ঠেলে একদিকে ফেলে দেয়। Cross-coupled inverter-এর লুপ ঠিক এমন: প্রতিটি gate অন্যটির মানকে আরও জোরে ঠেলে দেয় (CMOS gate-এর gain এক-এর বেশি), তাই একটু ঝুঁকলেই পুরো 0 বা পুরো 1-এ গিয়ে থামে।
এই “মাঝখানে রাখলে” কথাটি গুরুত্বপূর্ণ। দুটি স্থির বিন্দুর মাঝে একটি অস্থির ভারসাম্য-বিন্দুও আছে, যেখানে দুটি output-ই প্রায় অর্ধেক ভোল্টেজে — পাহাড়ের চূড়ায় বসানো একটি বলের মতো। বাস্তবে সামান্য noise-এ বলটি কোনো এক দিকে গড়িয়ে পড়ে, কিন্তু কতক্ষণে পড়বে তার নিশ্চয়তা নেই। এই অবস্থার নাম metastability — পর্ব ১৮-এ এর ঝুঁকি আর প্রতিকার বিস্তারিত দেখবেন।
শুধু দুটি inverter দিয়ে একটি সমস্যা: মান বদলানোর কোনো দরজা নেই। লুপটি যে অবস্থায় চালু হয়েছে, সেখানেই থাকবে। দরজা বানাতে হলে inverter-এর জায়গায় এমন gate লাগবে যার একটি অতিরিক্ত input বাইরে থেকে লুপকে জোর করে একদিকে ঠেলতে পারে। NOR আর NAND ঠিক এই কাজের — পরের অংশে।
১৯১৮ সালে ব্রিটিশ পদার্থবিদ William Eccles আর F. W. Jordan দুটি vacuum tube একে অপরের সাথে জুড়ে একটি “trigger relay” বানান — একটি pulse-এ এক অবস্থায় যায়, আরেক pulse-এ অন্য অবস্থায়, আর মাঝখানে নিজে নিজেই অবস্থা ধরে রাখে। এটিকেই সাধারণত প্রথম ইলেকট্রনিক flip-flop ধরা হয়। পরের কয়েক দশকে ENIAC-সহ প্রথম যুগের ইলেকট্রনিক কম্পিউটারের গণনা আর স্মৃতির বড় অংশ চলেছে এমন tube-flip-flop দিয়ে। আজ একটি ফোনের chip-এ এমন বিট-ধরা উপাদানের সংখ্যা কোটি কোটি।
আধুনিক chip-এর সবচেয়ে প্রচলিত দ্রুত মেমরি — cache-এর SRAM cell — আসলে ঠিক এই cross-coupled inverter-এর জোড়া, সাথে পড়া-লেখার জন্য দুটি “দরজা” transistor (মোট ছয়টি transistor). পর্ব ৪৯-এ SRAM আর DRAM-এর তুলনায় সেটি দেখবেন।
৩ · SR latch — NOR দিয়ে, আর NAND দিয়ে S′R′
NOR gate-এর নিয়ম মনে করুন (পর্ব ০৮): যেকোনো input 1 হলে output 0; সব input 0 হলেই কেবল output 1. লক্ষ করুন, একটি input 0 রাখলে NOR ঠিক inverter-এর মতো আচরণ করে (output = অন্য input-এর উল্টো)। তাই দুটি NOR-কে cross-couple করে তাদের বাড়তি input দুটি 0 রাখলে আগের অংশের দুই-inverter লুপই পাই। আর বাড়তি input 1 করলে সেই gate-এর output জোর করে 0 — লুপকে একদিকে ঠেলার দরজা পেয়ে গেলাম। এই circuit-টিই SR latch: S (set) আর R (reset) দুটি input, Q আর Q′ দুটি output.
NOR gate দিয়ে SR latch
Q = NOR(R, Q′) · Q′ = NOR(S, Q)
খেয়াল করুন, R ঢোকে Q-এর gate-এ: R = 1 হলে Q = 0 জোর করে — অর্থাৎ reset. আর S ঢোকে Q′-এর gate-এ: S = 1 হলে Q′ = 0, তারপর ওপরের gate-এর দুটি input-ই 0 বলে Q = 1 — set. চারটি input-সংমিশ্রণ মিলিয়ে টেবিলটি এমন:
| S | R | Q+ | Q′+ | নাম |
|---|---|---|---|---|
| 0 | 0 | Q | Q′ | Hold — আগের মান ধরে রাখে (স্মৃতি) |
| 1 | 0 | 1 | 0 | Set |
| 0 | 1 | 0 | 1 | Reset |
| 1 | 1 | 0 | 0 | নিষিদ্ধ — Q আর Q′ আর উল্টো নয় |
এবার ধাপে ধাপে একটি input-ক্রম চালিয়ে দেখুন। প্রতিটি ধাপে দুটি gate কীভাবে একে অপরকে ঠেলে স্থির হয়, সেটিই আসল শিক্ষা:
| S R | |
| Gate-এর হিসাব | |
| Q Q′ | |
| অবস্থা |
- S = 0, R = 0, শুরুতে Q = 0. ওপরের gate দেখে R = 0 আর Q′ = 1, তাই Q = 0; নিচের gate দেখে S = 0 আর Q = 0, তাই Q′ = 1. দুটি হিসাবই আগের মানের সাথে মেলে — circuit স্থির। এটি hold অবস্থা।
- S = 1 (set). নিচের gate-এর একটি input 1, তাই Q′ = 0 হয়ে যায়। এক gate-delay পরে ওপরের gate দেখে R = 0, Q′ = 0 — দুটিই 0, তাই Q = 1. মোট দুই ধাপের delay-তে latch set হলো: Q = 1, Q′ = 0.
- S আবার 0. এখন কোনো input সক্রিয় নয়, তবু Q = 1-ই থাকে: Q = NOR(0, 0) = 1 আর Q′ = NOR(0, 1) = 0. S-এর ছোট্ট একটি pulse চলে গেছে, কিন্তু তার ফল লুপের ভেতরে আটকে আছে। এটাই স্মৃতি — push-button ছেড়ে দেওয়ার পরও ল্যাম্প জ্বলছে।
- R = 1 (reset). এবার ওপরের gate জোর করে Q = 0 করে, এক delay পরে নিচের gate দেখে S = 0, Q = 0, তাই Q′ = 1. Latch reset হলো।
- R আবার 0. Q = 0 মনে রইল। দুটি hold ধাপে (৩ আর ৫) input হুবহু এক — S = R = 0 — কিন্তু output আলাদা, 1 আর 0. Output ইতিহাসের ওপর নির্ভর করছে; combinational circuit-এ এটা অসম্ভব।
- S = 1, R = 1 — নিষিদ্ধ। দুটি NOR-এরই একটি input 1, তাই দুটি output-ই 0. Circuit স্থির, কিন্তু Q′ আর Q-এর উল্টো নয় — “Q′” নামটাই মিথ্যা হয়ে গেল। যে circuit Q′-কে Q-এর উল্টো ধরে কাজ করে, সে ভুল তথ্য পাবে।
- S আর R একই মুহূর্তে 0-তে নামল। দুটি gate একসাথে দেখে দুটি input 0, তাই দুটি output একসাথে 1; পরের delay-তে দুটিই দেখে একটি input 1, তাই একসাথে 0 — ১ ১, ০ ০, ১ ১… দুটি gate হুবহু সমান দ্রুত হলে দোল চলতেই থাকে। বাস্তবে একটি gate সামান্য দ্রুত হয় বলে latch শেষে কোনো এক দিকে পড়ে — কিন্তু কোন দিকে, তা আগে থেকে বলা যায় না। এটাই race, আর এজন্যই S = R = 1 নিষিদ্ধ।
নিচের simulator ঠিক এই মডেলটি চালায়: প্রতিটি gate-এর delay এক একক, আর প্রতি এককে দুটি gate-ই পুরোনো মান দেখে একসাথে নতুন মান বসায়। Output না বদলানো পর্যন্ত (বা ৬ একক পর্যন্ত) চলে, তারপর জানায় স্থির হলো কি না:
// NOR SR latch, gate level: Q = NOR(R, Qn), Qn = NOR(S, Q).
// Unit delay: both gates look at the OLD outputs, then update together.
const NOR = (a, b) => (a | b) ? 0 : 1;
let Q = 0, Qn = 1; // start in the "reset" state
function apply(S, R, label) {
const trace = [`${Q}${Qn}`];
for (let t = 1; t <= 6; t++) {
const q = NOR(R, Qn), qn = NOR(S, Q); // both computed from old values
if (q === Q && qn === Qn) break; // nothing changed: stable
Q = q; Qn = qn; trace.push(`${Q}${Qn}`);
}
const stable = NOR(R, Qn) === Q && NOR(S, Q) === Qn;
const note = !stable ? "OSCILLATES (never settles)"
: Q === Qn ? "stable, but Q = Q' (not complements!)"
: "stable";
console.log(`S=${S} R=${R} ${label.padEnd(10)} QQ': ${trace.join(" -> ").padEnd(28)} ${note}`);
}
apply(0, 0, "hold");
apply(1, 0, "set");
apply(0, 0, "hold");
apply(0, 1, "reset");
apply(0, 0, "hold");
apply(1, 1, "forbidden");
apply(0, 0, "release"); // S and R drop at the SAME instant
Q = 0; Qn = 0; // back to the forbidden outputs
apply(1, 0, "R first"); // R drops first, S a moment later
apply(0, 0, "then S");আউটপুট (নির্ধারিত — প্রতিবার একই):
S=0 R=0 hold QQ': 01 stable
S=1 R=0 set QQ': 01 -> 00 -> 10 stable
S=0 R=0 hold QQ': 10 stable
S=0 R=1 reset QQ': 10 -> 00 -> 01 stable
S=0 R=0 hold QQ': 01 stable
S=1 R=1 forbidden QQ': 01 -> 00 stable, but Q = Q' (not complements!)
S=0 R=0 release QQ': 00 -> 11 -> 00 -> 11 -> 00 -> 11 -> 00 OSCILLATES (never settles)
S=1 R=0 R first QQ': 00 -> 10 stable
S=0 R=0 then S QQ': 10 stable
Set-এর সারিতে 01 -> 00 -> 10 — প্রথম একক পরে Q′ নামে, Q তখনো ওঠেনি, তাই এক মুহূর্তের জন্য দুটিই 0; দ্বিতীয় এককে Q ওঠে। Reset-এর 10 -> 00 -> 01 একই ছবির উল্টো। Hold-এর সারিগুলোতে একটিও বদল নেই — 10 বা 01, যেটি আগে ছিল। নিষিদ্ধ input-এ ফল স্থির, কিন্তু simulator সতর্ক করছে Q = Q' (not complements!). আর আসল বিপদ পরের সারিতে: S আর R একসাথে নামলে 00 -> 11 -> 00 -> 11 … OSCILLATES (never settles). শেষ দুই সারি দেখায় উল্টো ঘটনা: R আগে নামলে (S তখনো 1) latch পরিষ্কারভাবে set হয় — 00 -> 10 — আর তারপর S নামলেও 10 থাকে। অর্থাৎ সমস্যা S = R = 1 নিজে নয়, সমস্যা হলো সেখান থেকে একসাথে ছাড়া, যখন ফলাফল নির্ভর করে কোন gate কয়েক picosecond দ্রুত তার ওপর।
NAND দিয়ে S′R′ latch — active-low সংস্করণ
NAND gate-এর কোনো input 0 হলে output জোর করে 1. তাই দুটি NAND cross-couple করলে input-গুলো 0 হলে সক্রিয় হয় — একে বলে active-low input, নাম লেখা হয় S′ আর R′ (বা S̄, R̄). গঠন: Q = NAND(S′, Q′), Q′ = NAND(R′, Q). এখানে S′ ঢোকে Q-এর gate-এ (NOR-এর উল্টো ছবি), কারণ NAND-এর 0 input তার output-কে 1 করে।
| S′ | R′ | Q+ | Q′+ | নাম |
|---|---|---|---|---|
| 1 | 1 | Q | Q′ | Hold |
| 0 | 1 | 1 | 0 | Set |
| 1 | 0 | 0 | 1 | Reset |
| 0 | 0 | 1 | 1 | নিষিদ্ধ — দুটি output-ই 1 |
পরীক্ষায় সবচেয়ে বেশি ভুল এখানে: NOR latch-এর নিষিদ্ধ অবস্থা S = R = 1, output 0 0; NAND latch-এর নিষিদ্ধ অবস্থা S′ = R′ = 0, output 1 1. Hold-ও উল্টো: NOR-এ 00, NAND-এ 11. টেবিল মুখস্থ না করে প্রতিবার gate-এর নিয়ম থেকে বের করুন — “NOR-এ 1 জেতে, NAND-এ 0 জেতে।”
SR latch-এর একটি খুব বাস্তব ব্যবহার আছে: যান্ত্রিক সুইচের contact bounce দূর করা। একটি বোতাম চাপলে ধাতব পাত কয়েক millisecond ধরে কয়েকবার লাফিয়ে ওঠে-নামে, ফলে 0-1-0-1-এর ঝাঁক আসে। দুই-দিকের (SPDT) সুইচের দুই প্রান্ত একটি S′R′ latch-এর S′ আর R′-তে দিলে প্রথম ছোঁয়াতেই latch set হয়ে যায়, পরের লাফগুলোতে input “hold”-এ (11) ফেরে বলে output আর নড়ে না। পুরোনো ল্যাবের ট্রেনার বোর্ডের “debounced” বোতামের ভেতরে প্রায়ই এটাই থাকে।
৪ · Gated SR latch আর D latch — দরজাওয়ালা স্মৃতি
সাধারণ SR latch যেকোনো মুহূর্তে S বা R-এ সাড়া দেয়। কিন্তু বড় নকশায় আমরা চাই, স্মৃতি-উপাদান শুধু নির্দিষ্ট সময়ে নতুন মান নিক — যখন আগের combinational হিসাব শেষ হয়ে মান স্থির হয়েছে। এজন্য S আর R-এর সামনে দুটি AND gate বসিয়ে তাদের অন্য input-এ একটি enable সংকেত (EN, অনেক বইয়ে C বা clock) দেওয়া হয়। EN = 0 হলে দুটি AND-এর output 0, তাই latch-এর কাছে S = R = 0 — hold, বাইরে যা-ই ঘটুক। EN = 1 হলে S আর R পার হয়ে যায়। এটি gated SR latch. NAND দিয়ে বানালে চারটি NAND লাগে: সামনের দুটি NAND(S, EN) আর NAND(R, EN) সরাসরি S′R′ latch-এর active-low input দেয়।
কিন্তু নিষিদ্ধ অবস্থাটি এখনো আছে: EN = 1 অবস্থায় S = R = 1 হলে সেই একই সমস্যা, আর তারপর EN নামলে আবার race. সমাধানটি চমৎকার রকম সরল — S আর R-কে আলাদা input রাখবেন না। একটি মাত্র data input D নিন, আর দিন S = D, R = D′ (একটি inverter দিয়ে)। তাহলে S আর R কখনো একসাথে 1 হতে পারে না; নিষিদ্ধ অবস্থা গঠনগতভাবেই অসম্ভব। এই circuit-ই D latch.
| EN | D | Q+ | আচরণ |
|---|---|---|---|
| 0 | x | Q | বন্ধ (opaque) — D যা-ই হোক, আগের মান |
| 1 | 0 | 0 | খোলা (transparent) — Q = D |
| 1 | 1 | 1 | খোলা (transparent) — Q = D |
সূত্রটি চেনা লাগছে? এটি ঠিক একটি 2:1 multiplexer-এর সূত্র (পর্ব ১২): EN হলো select, EN = 1-এ নতুন D, EN = 0-এ পুরোনো Q. সত্যিই, অনেক CMOS standard-cell latch ভেতরে একটি mux আর feedback-এর লুপ — mux-এর একটি input বাইরের D, আরেকটি নিজের output.
EN = 1 থাকার পুরো সময় latch-টি একটি স্বচ্ছ কাচের জানালার মতো: D বদলালে Q-ও সঙ্গে সঙ্গে (একটু delay-তে) বদলায়। এজন্য একে transparent latch বলে। EN নামার মুহূর্তে জানালা বন্ধ হয়, আর তখন D-এর যে মান ছিল সেটিই ভেতরে আটকে থাকে। পর্ব ১৪-এর latch-এর ফাঁদে অসম্পূর্ণ if (en) q = d; লিখে ঠিক এই উপাদানটিই অনিচ্ছায় পেয়েছিলেন — একটি inferred latch.
ঢাকার একটি রেলক্রসিংয়ের গেট ভাবুন। গেট খোলা থাকলে রিকশা, বাস, মানুষ — যে আসছে সে-ই পার হচ্ছে, ওপারের রাস্তার ছবি এপারের সাথে সাথে বদলাচ্ছে। গেট নামলে ওপারে শেষ মুহূর্তে যারা ঢুকেছিল তারাই থাকে, এপারে যত ভিড়ই জমুক। D latch-এর EN = 1 মানে গেট খোলা, EN = 0 মানে গেট নামানো।
৫ · Level-sensitive বনাম edge-triggered — master–slave D flip-flop
D latch সাড়া দেয় EN-এর স্তর দেখে — EN = 1 থাকার পুরো সময়। একে বলে level-sensitive. ছোট নকশায় এটি সমস্যা নয়, কিন্তু CPU-র মতো synchronous pipeline-এ এটি বিপজ্জনক। কারণটা বুঝতে একটি register-এর শিকল ভাবুন: latch A-এর output যায় কিছু combinational logic হয়ে latch B-তে, B থেকে আবার logic হয়ে C-তে, আর সবার EN একই clock. Clock = 1 হওয়া মাত্র A খুলে যায়, তার নতুন মান logic পেরিয়ে B-তে পৌঁছায় — আর B-ও তো খোলা! মানটি B পার হয়ে C-র দিকে ছুটতে থাকে। Clock-এর high অংশ যথেষ্ট লম্বা হলে একটি মান এক টিকে একাধিক ধাপ পেরিয়ে যায়। একে বলে race-through: আমরা চেয়েছিলাম প্রতি টিকে ঠিক এক ধাপ, পেলাম “যত দূর দৌড়াতে পারে”। ফলাফল তখন নির্ভর করে gate-এর delay আর clock-এর pulse-এর দৈর্ঘ্যের ওপর — যা তাপমাত্রা আর ভোল্টেজে বদলায়।
সমাধান: এমন স্মৃতি-উপাদান, যা clock-এর একটি মুহূর্তে — ধারে — একবার মান নেয়, আর বাকি পুরো সময় input-কে উপেক্ষা করে। একে বলে edge-triggered উপাদান, আর এটিই flip-flop. Clock 0 থেকে 1-এ ওঠার মুহূর্ত rising edge (positive edge), 1 থেকে 0-তে নামার মুহূর্ত falling edge (negative edge).
দুটি latch দিয়ে একটি flip-flop
সবচেয়ে প্রচলিত গঠনটি হলো master–slave flip-flop: দুটি D latch পরপর, কিন্তু তাদের enable উল্টো। প্রথমটি (master) খোলা থাকে clock = 0-তে (EN = clk′), দ্বিতীয়টি (slave) খোলা থাকে clock = 1-এ (EN = clk). যেকোনো মুহূর্তে ঠিক একটি latch খোলা — তাই D থেকে Q পর্যন্ত কখনো সরাসরি স্বচ্ছ পথ থাকে না।
Positive-edge-triggered master–slave D flip-flop
Two D latches with opposite enables
- Dবাইরের data
- Master D latch
EN = clk′clk = 0 হলে খোলা - Slave D latch
EN = clkclk = 1 হলে খোলা - Qবাইরে দেখা মান
একটি পূর্ণ clock period ধরে দেখুন কোন latch কখন খোলা, আর Q কখন বদলায়:
| clk | |
| D | |
| Master | |
| Qm | |
| Slave | |
| Q |
- clk = 0, D = 0. Master খোলা, তাই Qm = D = 0. Slave বন্ধ, Q আগের মান 0 ধরে আছে। Master যেন ঘরের দরজায় দাঁড়িয়ে বাইরের খবর শুনছে, কিন্তু ভেতরে কিছু বলছে না।
- clk এখনো 0, D বদলে 1. Master স্বচ্ছ, তাই Qm সঙ্গে সঙ্গে 1. কিন্তু Q বদলায় না — slave-এর দরজা বন্ধ। Clock low থাকার পুরো সময় D যতবার খুশি বদলাক, Q নড়বে না।
- Rising edge: clk 0 → 1. এই মুহূর্তে দুটি ঘটনা একসাথে: master বন্ধ হয়ে Qm = 1 আটকে ফেলে, আর slave খুলে সেই 1 Q-তে পাঠায়। Q = 1. অর্থাৎ Q পেল ধারের ঠিক আগের D-এর মান।
- clk = 1, D নামল 0-তে. একটি সাধারণ D latch হলে Q এখনই 0 হয়ে যেত। কিন্তু master বন্ধ, Qm = 1-ই থাকে; slave খোলা থাকলেও সে দেখছে Qm, D নয়। তাই Q = 1 অটল। Race-through বন্ধ — এখানেই flip-flop-এর মূল্য।
- Falling edge: clk 1 → 0. Slave বন্ধ হয়ে Q = 1 ধরে রাখে; master আবার খোলে, Qm এখন D = 0 অনুসরণ করে। Q তবুও 1 — positive-edge flip-flop falling edge-এ output বদলায় না।
- পরের rising edge, D = 0. Master বন্ধ হয়ে 0 আটকায়, slave খুলে Q = 0 দেখায়। এক period-এ Q ঠিক একবার বদলেছে, আর দুবারই ধারের মুহূর্তের D নিয়েছে। পরের পর্বের প্রতিটি register আর counter এই আচরণের ওপর দাঁড়িয়ে।
Enable দুটি অদলবদল করলে (master খোলা clk = 1-এ, slave clk = 0-তে) পাওয়া যায় negative-edge-triggered flip-flop — সেটি falling edge-এ মান নেয়। Circuit-এর প্রতীকে clock input-এর পাশে একটি ছোট ত্রিভুজ (>) মানে edge-triggered; ত্রিভুজের আগে একটি ছোট বৃত্ত (bubble) থাকলে falling edge. ত্রিভুজ না থাকলে সেটি latch — level-sensitive.
আরও একটি নির্মাণ: master–slave একমাত্র উপায় নয়। পুরোনো TTL chip-এ (যেমন 7474) ব্যবহার হতো তিনটি SR latch-এর একটি চতুর গঠন; আধুনিক CMOS-এ প্রচলিত transmission-gate দিয়ে বানানো দুই-latch রূপ, আর উচ্চ-গতির নকশায় কখনো খুব ছোট pulse দিয়ে চালানো latch. বাইরে থেকে আচরণ একই — ধারে মান নেওয়া — তাই characteristic table-ও এক।
এবার একটি দীর্ঘ waveform-এ একটি D latch (clk = 1-এ খোলা) আর একটি rising-edge D flip-flop পাশাপাশি চালিয়ে দেখি। প্রতিটি অক্ষর এক একক সময়; দুটিই শুরু করে Q = 0 থেকে:
// D latch (transparent while clk = 1) vs rising-edge D flip-flop.
// One character = one time unit. Both start with Q = 0.
const clk = "0001111000011110000111100001111";
const D = "0011100000001100110000000111111";
let qL = 0, qF = 0, latch = "", ff = "", diff = "";
for (let t = 0; t < clk.length; t++) {
const c = +clk[t], d = +D[t];
if (c === 1) qL = d; // latch: Q follows D while open
const rising = t > 0 && clk[t - 1] === "0" && c === 1;
if (rising) qF = d; // FF: sample D only at 0 -> 1
latch += qL; ff += qF;
diff += qL !== qF ? "^" : " ";
}
const wave = s => [...s].map(b => (b === "1" ? "‾" : "_")).join("");
const edges = [...clk].map((b, t) => (t > 0 && clk[t - 1] === "0" && b === "1" ? "|" : " ")).join("");
console.log("edge " + edges);
console.log("clk " + wave(clk));
console.log("D " + wave(D));
console.log("Q latch " + wave(latch));
console.log("Q FF " + wave(ff));
console.log("differ " + diff);
console.log("Q latch = " + latch);
console.log("Q FF = " + ff);
let n = 0; for (const ch of diff) if (ch === "^") n++;
console.log(`they differ in ${n} of ${clk.length} time units`);আউটপুট (নির্ধারিত — প্রতিবার একই; ‾ = 1, _ = 0, | = rising edge):
edge | | | |
clk ___‾‾‾‾____‾‾‾‾____‾‾‾‾____‾‾‾‾
D __‾‾‾_______‾‾__‾‾_______‾‾‾‾‾‾
Q latch ___‾‾_______‾‾_____________‾‾‾‾
Q FF ___‾‾‾‾‾‾‾‾________________‾‾‾‾
differ ^^^^^^ ^^
Q latch = 0001100000001100000000000001111
Q FF = 0001111111100000000000000001111
they differ in 8 of 31 time units
প্রথম rising edge-এ (t = 3) D = 1, তাই দুটিই 1 হয়। তারপর clock high থাকতেই t = 5-এ D নেমে যায় — খোলা latch সঙ্গে সঙ্গে 0 (Q latch সারিতে মাত্র দুই একক উঁচু), কিন্তু flip-flop পরের edge (t = 11) পর্যন্ত 1 ধরে রাখে; এখানেই প্রথম ^^^^^^. দ্বিতীয় high অংশে D-তে একটি ছোট pulse (t = 12, 13) — latch সেটি হুবহু বাইরে পাঠায়, flip-flop উপেক্ষা করে: আরও দুটি ^. তৃতীয় ঘটনা দুই দিকেই নীরব: clock low থাকাকালীন t = 16, 17-এর pulse কেউ দেখে না, কারণ latch বন্ধ আর কোনো edge নেই। শেষ edge-এ (t = 27) D = 1 আর clock high থাকাকালীন D স্থির, তাই দুটি একই ফল দেয়। মোট they differ in 8 of 31 time units — আর প্রতিটি পার্থক্যই clock high থাকার সময়ে, যখন latch স্বচ্ছ। ডিজাইনে এই আটটি একক মানেই সম্ভাব্য race-through.
৬ · চার রকম flip-flop — characteristic table আর equation
Edge-triggering-এর কৌশল একবার পেলে ধারে কী মান নেবে, সেই নিয়ম বদলে চার রকম flip-flop বানানো যায়। প্রতিটির আচরণ বর্ণনার দুটি মানক উপায়: characteristic table (input আর বর্তমান Q থেকে Q+-এর টেবিল) আর characteristic equation (সেই টেবিলের Boolean সূত্র)।
| Flip-flop | Input → Q+ | Characteristic equation |
|---|---|---|
| SR | 00 → Q (hold), 01 → 0, 10 → 1, 11 → নিষিদ্ধ | Q+ = S + R′Q, শর্ত SR = 0 |
| D | 0 → 0, 1 → 1 | Q+ = D |
| JK | 00 → Q, 01 → 0, 10 → 1, 11 → Q′ (toggle) | Q+ = JQ′ + K′Q |
| T | 0 → Q, 1 → Q′ | Q+ = TQ′ + T′Q = T ⊕ Q |
সূত্র বের করা — SR আর JK-এর K-map
Characteristic equation মুখস্থ করার দরকার নেই, পর্ব ০৯-এর K-map দিয়ে এক মিনিটে বের হয়। SR-এর জন্য তিন চলক S, R, Q নিয়ে Q+-এর টেবিল: SRQ = 000 → 0, 001 → 1, 010 → 0, 011 → 0, 100 → 1, 101 → 1, আর 110, 111 নিষিদ্ধ, তাই don't care (x). 1-গুলো আছে 001, 100, 101-এ। চারটি S = 1-এর ঘর (100, 101 আর দুটি x) মিলে একটি চারের দল: S. বাকি 001 আর 101 জোড়া (দুটির মিল R = 0, Q = 1): R′Q. তাই Q+ = S + R′Q. Don't care ছাড়া এটি হতো SR′ + R′Q — x দুটিই সূত্রকে ছোট করেছে, আর বিনিময়ে শর্ত দিয়েছে SR = 0.
JK-তে নিষিদ্ধ ঘর নেই; JKQ = 110 → 1 আর 111 → 0 (toggle). 1-গুলো: 001, 100, 101, 110. জোড়া ১: 100 আর 110 (J = 1, Q = 0) → JQ′. জোড়া ২: 001 আর 101 (K = 0, Q = 1) → K′Q. Q+ = JQ′ + K′Q. সূত্রটি পড়ুন এভাবে: “Q এখন 0 হলে J ঠিক করে উঠবে কি না; Q এখন 1 হলে K ঠিক করে নামবে কি না।” এভাবে পড়ার অভ্যাস excitation table বুঝতেও সাহায্য করবে।
JK — SR-এর নিষিদ্ধ ঘরের সদ্ব্যবহার
JK flip-flop হলো SR, যেখানে নিষিদ্ধ 11-কে একটি কাজের অর্থ দেওয়া হয়েছে: toggle, অর্থাৎ মান উল্টে দেওয়া। এজন্য ভেতরে output দুটি ফিরিয়ে এনে input gate-এ দেওয়া হয়: S = JQ′, R = KQ. তাহলে Q = 0 হলে শুধু J কাজ করে, Q = 1 হলে শুধু K — S আর R কখনো একসাথে 1 হয় না। J = K = 1-এ প্রতিটি সক্রিয় ধারে Q উল্টায়।
কিন্তু এই feedback-ই পুরোনো, level-triggered JK-তে একটি বিখ্যাত সমস্যা তৈরি করে: race-around condition. ধরুন JK-টি gated latch-এর মতো clock = 1 থাকার পুরো সময় সাড়া দেয়, আর J = K = 1. Q উল্টাল; নতুন Q feedback হয়ে input gate-এ ফিরল; clock তখনো 1, তাই আবার উল্টাল… clock pulse যতক্ষণ high, ততক্ষণ Q দোল খায়, আর pulse শেষে কোন মানে থামবে তা নির্ভর করে pulse-এর দৈর্ঘ্য আর gate delay-এর অনুপাতের ওপর। প্রতিকার তিনটি: (১) clock pulse-কে flip-flop-এর propagation delay-এর চেয়ে ছোট রাখা — অনির্ভরযোগ্য; (২) master–slave গঠন — master যখন খোলা, slave বন্ধ, তাই feedback লুপ কখনো এক pulse-এ সম্পূর্ণ হয় না; (৩) সত্যিকারের edge-triggered গঠন। আধুনিক সব JK এই শেষ দুটির একটি।
| Edge | |
| J K | |
| হিসাব | |
| Q | |
| কাজ |
- শুরু: Q = 0. কোনো edge আসেনি। প্রতিটি ধাপে সূত্র Q+ = JQ′ + K′Q-এ বর্তমান Q বসিয়ে হিসাব করবেন — এটাই characteristic equation-এর ব্যবহার।
- Edge ১: J = 1, K = 0. Q = 0, তাই Q′ = 1: JQ′ = 1·1 = 1, K′Q = 1·0 = 0. Q+ = 1 — set.
- Edge ২: J = 0, K = 0. JQ′ = 0·0 = 0, K′Q = 1·1 = 1. Q+ = 1 — hold, আগের মান রইল।
- Edge ৩: J = 0, K = 1. JQ′ = 0·0 = 0, K′Q = 0·1 = 0. Q+ = 0 — reset.
- Edge ৪: J = 1, K = 1. Q = 0: JQ′ = 1·1 = 1, K′Q = 0. Q+ = 1 — toggle. SR flip-flop-এ এই input নিষিদ্ধ ছিল; JK-তে এটি সবচেয়ে কাজের input.
- Edge ৫: আবার J = K = 1. এবার Q = 1: JQ′ = 1·0 = 0, K′Q = 0·1 = 0. Q+ = 0 — আবার উল্টাল। J = K = 1 রেখে দিলে Q প্রতি দুই edge-এ একটি পূর্ণ চক্র দেয় — clock-এর অর্ধেক কম্পাঙ্ক। পর্ব ১৬-এর binary counter ঠিক এভাবে বানানো।
- যদি flip-flop level-triggered হতো. J = K = 1 আর clock high থাকার পুরো সময় latch স্বচ্ছ: Q উল্টায়, নতুন Q feedback হয়ে আবার উল্টায় — 1, 0, 1, 0 … pulse শেষে Q কোথায় থামবে বলা যায় না। এটাই race-around; edge-triggering বা master–slave এক ধারে ঠিক একবার উল্টানো নিশ্চিত করে।
T flip-flop হলো JK-এর J আর K একসাথে বাঁধা রূপ: T = 0 হলে hold, T = 1 হলে toggle. Counter আর frequency divider-এ এটি স্বাভাবিক পছন্দ। বাজারে আলাদা T flip-flop-এর IC প্রায় পাওয়া যায় না; JK বা D দিয়েই বানানো হয় — পরের অংশে ঠিক কীভাবে, দেখবেন।
৭ · Excitation table আর এক flip-flop দিয়ে আরেকটি বানানো
Characteristic table প্রশ্ন করে: “এই input দিলে Q+ কী হবে?” নকশা করার সময় প্রশ্নটা উল্টো: “Q এখন 0, পরের edge-এ 1 চাই — কোন input দেব?” এর উত্তরের টেবিলই excitation table. পর্ব ১৬-এর counter আর পর্ব ১৭-এর FSM নকশায় এটিই প্রধান হাতিয়ার, আর বিশ্ববিদ্যালয় ও চাকরির পরীক্ষায় বারবার আসা টেবিলও এটি।
| Q → Q+ | S R | J K | D | T |
|---|---|---|---|---|
| 0 → 0 | 0 x | 0 x | 0 | 0 |
| 0 → 1 | 1 0 | 1 x | 1 | 1 |
| 1 → 0 | 0 1 | x 1 | 0 | 1 |
| 1 → 1 | x 0 | x 0 | 1 | 0 |
JK-এর সারিগুলো যুক্তি দিয়ে বের করুন: 0 → 1 চাই। J = 1, K = 0 দিলে set হয়ে 1; J = 1, K = 1 দিলে toggle হয়েও 1. দুই ক্ষেত্রেই কাজ হয়, তাই K = x (don't care). একইভাবে 1 → 0-তে K = 1 দরকার, J যা-ই হোক (reset বা toggle). JK-এর excitation table-এ প্রতিটি সারিতে একটি x থাকে — এজন্যই counter নকশায় JK দিলে K-map-এ x বেশি, সূত্র ছোট। D-এর টেবিল সবচেয়ে সহজ: D = Q+. T-এর: T = Q ⊕ Q+ — বদলাতে চাইলে 1, না চাইলে 0.
রূপান্তরের পদ্ধতি — পাঁচ ধাপ
“আপনার কাছে শুধু D flip-flop আছে, একটি JK বানান” — এমন প্রশ্নের একটি নির্দিষ্ট পদ্ধতি আছে: (১) যে flip-flop বানাতে চান তার characteristic table লিখুন — input আর Q থেকে Q+; (২) প্রতিটি সারিতে Q → Q+ দেখুন; (৩) যে flip-flop হাতে আছে তার excitation table থেকে সেই রূপান্তরের input লিখুন; (৪) K-map দিয়ে সরল করুন; (৫) circuit এঁকে সব সারিতে simulate করে মিলিয়ে নিন।
কাজ করা উদাহরণ ১ — D flip-flop থেকে JK
| J | K | Q | Q+ (JK-এর নিয়ম) | D লাগবে (= Q+) |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 (hold) | 0 |
| 0 | 0 | 1 | 1 (hold) | 1 |
| 0 | 1 | 0 | 0 (reset) | 0 |
| 0 | 1 | 1 | 0 (reset) | 0 |
| 1 | 0 | 0 | 1 (set) | 1 |
| 1 | 0 | 1 | 1 (set) | 1 |
| 1 | 1 | 0 | 1 (toggle) | 1 |
| 1 | 1 | 1 | 0 (toggle) | 0 |
D-এর কলামে 1 আছে JKQ = 001, 100, 101, 110-এ — হুবহু JK-এর characteristic equation-এর minterm. K-map-এ সরল করলে D = JQ′ + K′Q. Circuit: দুটি AND (একটিতে J আর Q′, অন্যটিতে K′ আর Q), একটি OR, আর তার output D flip-flop-এর D-তে; Q আর Q′ ফিরে আসে AND-গুলোতে। D flip-flop থেকে রূপান্তর সবসময় এমন সরল — D-এর কলাম মানেই কাঙ্ক্ষিত flip-flop-এর characteristic equation.
কাজ করা উদাহরণ ২ — JK flip-flop থেকে T
T-এর characteristic table: TQ = 00 → 0, 01 → 1, 10 → 1, 11 → 0. প্রতিটি সারিতে JK-এর excitation table থেকে input: 00-তে 0 → 0, তাই JK = 0x; 01-তে 1 → 1, JK = x0; 10-তে 0 → 1, JK = 1x; 11-তে 1 → 0, JK = x1. J-এর কলাম 0, x, 1, x — x-গুলো সুবিধামতো বসালে J = T. K-এর কলাম x, 0, x, 1 — K = T. অর্থাৎ J = K = T: JK-এর দুটি input একসাথে জুড়ে দিলেই T flip-flop.
হাতে করা এই রূপান্তর দুটি নিচের generator নিজে বের করে আর simulate করে মিলিয়ে নেয়। প্রথমে চার flip-flop-এর characteristic equation থেকে excitation table, তারপর রূপান্তরের “লাগবে” কলাম, আর শেষে প্রস্তাবিত সূত্রটি সব সারিতে চালিয়ে যাচাই — একটি ইচ্ছাকৃত ভুল সূত্রসহ:
// Characteristic equations -> excitation tables -> flip-flop conversion.
const FF = { // Q+ from (inputs..., Q); null = input combination not allowed
SR: { ins: "SR", next: (S, R, Q) => (S & R ? null : S | (!R & Q)) },
JK: { ins: "JK", next: (J, K, Q) => (J & !Q) | (!K & Q) },
D: { ins: "D", next: (D) => D },
T: { ins: "T", next: (T, Q) => T ^ Q },
};
const combos = n => [...Array(1 << n)].map((_, v) => [...Array(n)].map((_, i) => (v >> (n - 1 - i)) & 1));
const nxt = (f, x, Q) => { const r = f.next(...x, Q); return r === null ? null : +r; };
function excite(f, q, qp) { // inputs needed for Q -> Q+, "x" = don't care
const ok = combos(f.ins.length).filter(x => nxt(f, x, q) === qp);
return [...f.ins].map((_, i) => { const v = new Set(ok.map(x => x[i])); return v.size === 2 ? "x" : [...v][0]; }).join("");
}
for (const [name, f] of Object.entries(FF))
console.log(`${name.padEnd(2)} ` + [[0, 0], [0, 1], [1, 0], [1, 1]].map(([q, p]) => `${q}->${p}:${excite(f, q, p)}`).join(" "));
// Build flip-flop `want` from flip-flop `have`: per row, read Q+ from want, inputs from have's excitation.
function convert(want, have, guess) {
const W = FF[want], H = FF[have], cols = [...H.ins].map(() => []);
let ok = 0, rows = 0;
for (const x of combos(W.ins.length)) for (const Q of [0, 1]) {
const need = excite(H, Q, nxt(W, x, Q)), g = guess(...x, Q).map(Number);
need.split("").forEach((c, i) => cols[i].push(c));
rows++; if (nxt(H, g, Q) === nxt(W, x, Q)) ok++; // simulate the guess
}
console.log(`${want} from ${have}:`);
console.log(` ${(W.ins + "Q").padEnd(9)}: ` + combos(W.ins.length + 1).map(v => v.join("")).join(" "));
cols.forEach((c, i) => console.log(` ${(H.ins[i] + " needed").padEnd(9)}: ` + c.join(" ".repeat(W.ins.length + 1))));
console.log(` candidate simulated: ${ok}/${rows} rows give the right Q+`);
}
convert("JK", "D", (J, K, Q) => [(J & !Q) | (!K & Q)]); // D = JQ' + K'Q
convert("T", "JK", (T) => [T, T]); // J = K = T
convert("JK", "D", (J, K, Q) => [J | (!K & Q)]); // a wrong guess: D = J + K'Qআউটপুট (নির্ধারিত — প্রতিবার একই):
SR 0->0:0x 0->1:10 1->0:01 1->1:x0
JK 0->0:0x 0->1:1x 1->0:x1 1->1:x0
D 0->0:0 0->1:1 1->0:0 1->1:1
T 0->0:0 0->1:1 1->0:1 1->1:0
JK from D:
JKQ : 000 001 010 011 100 101 110 111
D needed : 0 1 0 0 1 1 1 0
candidate simulated: 8/8 rows give the right Q+
T from JK:
TQ : 00 01 10 11
J needed : 0 x 1 x
K needed : x 0 x 1
candidate simulated: 4/4 rows give the right Q+
JK from D:
JKQ : 000 001 010 011 100 101 110 111
D needed : 0 1 0 0 1 1 1 0
candidate simulated: 7/8 rows give the right Q+
প্রথম চার সারি excitation table — উপরের হাতে লেখা টেবিলের সাথে প্রতিটি ঘর মেলে: SR-এর 0->0:0x আর 1->1:x0, JK-এর 0->1:1x আর 1->0:x1. Program-টি x নিজে বের করেছে: যে input দুই মানেই সঠিক Q+ দেয়, সেটি x. এরপর JK from D-এর D needed কলাম 0 1 0 0 1 1 1 0 — হাতের টেবিলের শেষ কলামের হুবহু মিল — আর D = JQ′ + K′Q বসিয়ে simulate করলে 8/8 rows give the right Q+. T from JK-এ J needed : 0 x 1 x আর K needed : x 0 x 1 — x-গুলো বাদ দিলে দুটি কলামই T-এর মান, তাই J = K = T, আর 4/4. শেষ অংশটি সতর্কবার্তা: D = J + K′Q দেখতে কাছাকাছি, কিন্তু 7/8 — JKQ = 111 সারিতে toggle করে 0 হওয়ার কথা, এই সূত্র দেয় 1. আটটির মধ্যে সাতটি ঠিক উত্তর পরীক্ষায় শূন্য নম্বর পায়, আর hardware-এ একটি counter ভুল গোনে — তাই সব সারিতে simulate করে যাচাই অভ্যাস করুন।
আরও কয়েকটি প্রচলিত রূপান্তর, একই পদ্ধতিতে বের করা (অনুশীলনে দুটি নিজে করবেন): D থেকে T — D = T ⊕ Q; JK থেকে D — J = D, K = D′; T থেকে JK — T = JQ′ + KQ; JK থেকে SR — J = S, K = R (শর্ত SR = 0).
৮ · বাস্তবের flip-flop — preset, clear, enable আর timing
Asynchronous preset আর clear
কম্পিউটার চালু হওয়ার মুহূর্তে প্রতিটি flip-flop-এ কী মান থাকবে? Power-on-এ cross-coupled লুপ এলোমেলোভাবে যেকোনো দিকে পড়ে। তাই বাস্তবের বেশিরভাগ flip-flop-এ দুটি বাড়তি input থাকে: preset (PRE, Q-কে জোর করে 1) আর clear (CLR, Q-কে জোর করে 0). এগুলো সাধারণত active-low (PRE′, CLR′), আর asynchronous — clock-এর অপেক্ষা না করে সঙ্গে সঙ্গে কাজ করে, আর সক্রিয় থাকাকালীন clock আর D-কে পুরোপুরি উপেক্ষা করা হয়। ভেতরে এরা সরাসরি শেষ ধাপের latch-এর NAND-এ ঢোকে।
| PRE′ | CLR′ | clk | D | Q |
|---|---|---|---|---|
| 0 | 1 | x | x | 1 (সঙ্গে সঙ্গে) |
| 1 | 0 | x | x | 0 (সঙ্গে সঙ্গে) |
| 0 | 0 | x | x | সাধারণত Q = Q′ = 1 — ব্যবহার নিষেধ |
| 1 | 1 | ↑ | 0 / 1 | D (সাধারণ flip-flop) |
| 1 | 1 | 0, 1 বা ↓ | x | Q (hold) |
খেয়াল করুন তৃতীয় সারি — NAND S′R′ latch-এর নিষিদ্ধ অবস্থার পুরোনো বন্ধু ফিরে এসেছে। Clock-এর সাথে বাঁধা আরেক রকম reset-ও আছে: synchronous reset, যা শুধু clock edge-এ কাজ করে (ভেতরে D-এর সামনে একটি AND). কোনটি কখন ভালো, তা FPGA আর ASIC-এ ভিন্ন; তবে একটি নিয়ম সবখানে খাটে — asynchronous reset ছাড়ার (নিষ্ক্রিয় হওয়ার) মুহূর্তটি clock-এর সাথে মিলিয়ে নিতে হয়, নইলে পর্ব ১৮-এর metastability-র ঝুঁকি।
Enable — mux দিয়ে feedback
প্রায়ই চাই, register প্রতি clock-এ নয়, শুধু “লেখার” সংকেত এলে নতুন মান নিক। সঠিক উপায় হলো flip-flop-এর সামনে একটি 2:1 mux (পর্ব ১২): Din = EN ? d : Q. EN = 0 হলে flip-flop নিজের পুরোনো মানই আবার নেয় — বদল নেই। একে বলে clock enable. লোভনীয় কিন্তু বিপজ্জনক বিকল্প হলো clock-কেই একটি AND gate দিয়ে আটকে দেওয়া; সেই gate-এর delay আর glitch clock-এ ঢুকে timing নষ্ট করতে পারে। Chip-এ বিদ্যুৎ বাঁচাতে clock gating সত্যিই ব্যবহার হয়, তবে tool-এর দেওয়া বিশেষ latch-ভিত্তিক cell দিয়ে, হাতে বসানো AND দিয়ে নয়।
Timing-এর তিনটি সংখ্যা — প্রথম পরিচয়
“ধারের মুহূর্তের D নেয়” কথাটি আদর্শ রূপ। বাস্তবে flip-flop-এর ভেতরের latch-গুলো বন্ধ হতেও সময় লাগে, তাই তিনটি সংখ্যা মানতে হয়:
- Setup time (tsetup): clock edge-এর আগে অন্তত এতক্ষণ D স্থির থাকতে হবে — master latch-কে ঠিক মানটি ধরার সময় দিতে।
- Hold time (thold): edge-এর পরে অন্তত এতক্ষণ D বদলানো যাবে না — master পুরোপুরি বন্ধ হওয়া পর্যন্ত।
- Clock-to-Q delay (tclk→Q বা tpcq): edge-এর পর Q-তে নতুন মান আসতে যত সময় লাগে।
Setup বা hold ভাঙলে flip-flop ভুল মান নিতে পারে, অথবা অংশ ২-এর সেই পাহাড়-চূড়ায় কিছুক্ষণ আটকে থাকতে পারে — metastability. আধুনিক chip-এ এই সংখ্যাগুলো সাধারণত কয়েক দশ picosecond-এর ঘরে, পুরোনো TTL IC-তে কয়েক থেকে কয়েক দশ nanosecond — নির্দিষ্ট মান সবসময় datasheet বা cell library থেকে নিতে হয়। এরা কীভাবে সর্বোচ্চ clock speed ঠিক করে (tclk→Q + logic-এর delay + tsetup ≤ clock period), critical path, clock skew আর synchronizer — সব পর্ব ১৮-এ।
প্রতিটি register-এর ভেতরে
এ পর্যন্ত যা দেখলেন, তা কোনো বিচ্ছিন্ন খেলনা নয়। RISC-V CPU-র ৩২-বিট program counter মানে ৩২টি D flip-flop, একই clock-এ চলা। ৩২টি ৩২-বিট general-purpose register (x0 সবসময় শূন্য, তাই আসলে ৩১টি) মানে প্রায় এক হাজার flip-flop. পর্ব ৩৫-এর পাঁচ ধাপের pipeline-এ প্রতিটি ধাপের মাঝে বসে একটি pipeline register — একসারি flip-flop, যা প্রতি clock-এ এক ধাপের ফল পরের ধাপে তুলে দেয়; এখানে race-through হলে একটি instruction এক cycle-এ দুই ধাপ পেরিয়ে যেত। পর্ব ১৭-এর FSM-এ state register মনে রাখে যন্ত্রটি এখন কোন অবস্থায়। Cache-এর SRAM cell অবশ্য flip-flop নয়, তবে একই cross-coupled লুপ (পর্ব ৪৯)।
৯ · Verilog-এ flip-flop — posedge, reset আর non-blocking <=
পর্ব ১৪-এর শেষে flip-flop-এর আগাম চেহারা দেখেছিলেন। এবার পূর্ণ রূপ — asynchronous active-low reset আর clock enable-সহ একটি D flip-flop, আর পাশে একটি D latch তুলনার জন্য (synthesizable Verilog-2001, চালানো যায় না — উদাহরণ):
module dff_r (input wire clk, rst_n, en, d,
output reg q);
always @(posedge clk or negedge rst_n) // edge list = flip-flop
if (!rst_n) q <= 1'b0; // async clear: wins over the clock
else if (en) q <= d; // enable: synthesis adds the mux
// no else: q keeps its value
endmodule
module d_latch (input wire en, d, output reg q);
always @(*) // level-sensitive
if (en) q = d; // no else -> a latch, on purpose
endmoduleতিনটি বিষয় লক্ষ করুন। (১) Sensitivity list-এ posedge clk থাকলেই synthesis flip-flop বানায়; or negedge rst_n যোগ করলে reset asynchronous হয়, কারণ block-টি reset নামার মুহূর্তেও জাগে। Reset-কে if-এর প্রথম শাখায় রাখা বাধ্যতামূলক — এটাই “clock-এর ওপর অগ্রাধিকার”। (২) else if (en)-এর পরে else নেই, তবু এখানে latch হয় না — clock-চালিত block-এ “মান না দেওয়া” মানে flip-flop-এর enable mux, যা আমরা চাই। পর্ব ১৪-এর latch-এর ফাঁদ শুধু always @(*)-এ। (৩) Latch সত্যিই চাইলে (বিরল) সেটি always @(*)-এ অসম্পূর্ণ if দিয়ে লেখা হয়, আর synthesis report-এ “latch inferred” সতর্কবার্তা আসে।
কেন <= — অদলবদলের ক্লাসিক উদাহরণ
Hardware-এ একই clock edge-এ সব flip-flop একসাথে মান নেয়: প্রত্যেকে edge-এর ঠিক আগের মান দেখে। Non-blocking assignment (<=) ঠিক এটাই মডেল করে — একটি time step-এ সব ডান পাশ আগে পড়ে, তারপর সব বাঁ পাশ একসাথে বসায়। Blocking assignment (=) software-এর মতো লাইন ধরে ধরে চলে, পরের লাইন আগের লাইনের নতুন মান দেখে। দুটি register-এর মান অদলবদল করতে গেলে পার্থক্যটা চোখে পড়ে:
1// edge-এর আগে: a = 1, b = 02always @(posedge clk) begin3 a = b; // blocking4 b = a;5end6always @(posedge clk) begin7 a <= b; // non-blocking8 b <= a;9end
| a | |
| b | |
| অপেক্ষমাণ |
- Edge-এর আগে. a = 1, b = 0. লক্ষ্য: edge-এর পর a = 0, b = 1. Hardware-এ দুটি flip-flop-এর D আড়াআড়ি জুড়লেই এটা হয় — প্রত্যেকে অন্যটির পুরোনো মান নেয়।
- Blocking, লাইন ৩:
a = b. a সঙ্গে সঙ্গে 0 হয়ে যায়। a-এর পুরোনো মান 1 আর কোথাও নেই। - Blocking, লাইন ৪:
b = a. b পড়ে a-এর নতুন মান 0. ফল: a = 0, b = 0 — অদলবদল ব্যর্থ, একটি মান হারিয়ে গেল। Synthesis-ও এই অর্থ মেনে দুটি flip-flop-এর D-তে b-ই দেবে। - Non-blocking, আবার a = 1, b = 0 থেকে; লাইন ৭:
a <= b. ডান পাশ b = 0 পড়ে রাখা হলো, কিন্তু a এখনো বদলায়নি — হালনাগাদটি অপেক্ষমাণ তালিকায়। - লাইন ৮:
b <= a. b-এর জন্য a পড়া হলো — a এখনো পুরোনো 1, কারণ আগের হালনাগাদ বসেনি। অপেক্ষমাণ: a ← 0, b ← 1. - Time step শেষ: সব একসাথে বসে. a = 0, b = 1 — নিখুঁত অদলবদল, ঠিক যেমন আসল hardware করে। তাই নিয়ম: clock-চালিত block-এ সবসময়
<=, combinational block-এ=, আর এক block-এ দুটি মেশানো নয়।
এই নিয়ম না মানলে আরও সূক্ষ্ম বিপদ আছে: দুটি আলাদা always @(posedge clk) block-এ = ব্যবহার করলে simulator কোন block আগে চালাবে তার ওপর ফল নির্ভর করে — এক simulator-এ ঠিক, আরেকটিতে ভুল, আর synthesis-এর hardware হয়তো তৃতীয় কিছু। <= এই ক্রম-নির্ভরতা দূর করে।
আরও গভীরে: আধুনিক chip-এর standard-cell library-তে flip-flop-এর ডজনখানেক রূপ থাকে — reset-সহ, set-সহ, enable-সহ, আর প্রায় সবসময় “scan” রূপ, যার ভেতরে একটি বাড়তি mux সব flip-flop-কে একটি লম্বা shift register-এ জুড়ে দেয়, যাতে কারখানায় tester প্রতিটি chip-এর ভেতরের state বাইরে থেকে লিখে-পড়ে পরীক্ষা করতে পারে। উচ্চ-গতির কিছু CPU নকশায় flip-flop-এর বদলে দুই-phase-এর latch বা খুব ছোট pulse-চালিত latch ব্যবহার হয়, কারণ latch-এর স্বচ্ছতা এক ধাপের logic-কে পরের ধাপ থেকে কিছু সময় “ধার” নিতে দেয় (time borrowing) — তবে তার timing যাচাই অনেক কঠিন। আর flip-flop-এর ভেতরের clock সংকেতই একটি chip-এর dynamic power-এর বড় অংশ খায়, এজন্য clock gating আজ প্রায় সব low-power নকশার মানক কৌশল।
পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:
- Latch আর flip-flop-এর পার্থক্য কী? — Latch level-sensitive (enable চালু থাকার পুরো সময় স্বচ্ছ); flip-flop edge-triggered (শুধু clock-এর ধারে মান নেয়)।
- NOR SR latch-এ S = R = 1 কেন নিষিদ্ধ? — Q = Q′ = 0 হয়ে complement সম্পর্ক ভাঙে, আর দুটি একসাথে 0-তে নামলে race-এ ফল অনিশ্চিত বা দোলায়মান।
- Race-around condition কী, আর প্রতিকার? — Level-triggered JK-তে J = K = 1 আর clock pulse propagation delay-এর চেয়ে লম্বা হলে Q বারবার উল্টায়; প্রতিকার master–slave বা edge-triggered গঠন।
- JK-এর excitation table লিখুন। — 0→0: 0x, 0→1: 1x, 1→0: x1, 1→1: x0.
- D flip-flop দিয়ে T flip-flop? — D = T ⊕ Q (একটি XOR gate); আর Verilog-এ flip-flop-এ
<=কেন — সব flip-flop একসাথে পুরোনো মান দেখে, তাই অদলবদল ঠিক থাকে।
১০ · AI-এর যুগে — টেবিল AI দিয়ে, যাচাই simulation দিয়ে
Flip-flop-এর টেবিল আর রূপান্তর দেখতে যান্ত্রিক কাজ, তাই AI চ্যাটবট দ্রুত উত্তর দেয় — কিন্তু এখানে ছোট একটি উল্টোপাল্টা পুরো উত্তর নষ্ট করে, আর ভাষা মডেল টেবিলটি সত্যিই simulate করে না। এই বিষয়ে প্রায়ই দেখা ভুলগুলো:
| AI প্রায়ই যা ভুল করে | কীভাবে ধরবেন |
|---|---|
| NAND latch-এর নিষিদ্ধ অবস্থাকে NOR-এর মতো “S = R = 1, output 00” লেখা | Gate-এর নিয়ম থেকে প্রতিটি সারি নিজে হিসাব করুন: NAND-এ 0 জেতে |
| Characteristic আর excitation table গুলিয়ে ফেলা, বা JK-এর excitation-এ x-এর জায়গা ভুল | প্রতিটি সারির input characteristic equation-এ বসিয়ে দেখুন সত্যিই সেই Q+ আসে কি না |
| Master–slave-এ কোন latch কখন খোলা, উল্টে বলা; ফলে positive-edge-কে negative-edge বানানো | Rising edge-এর মুহূর্তে কোন latch বন্ধ হচ্ছে আর কোনটি খুলছে, এক period ধরে trace করুন |
| রূপান্তরের সূত্র “প্রায় ঠিক” — যেমন D = J + K′Q | সব ২n+1টি সারিতে simulate করুন (এই পর্বের generator বা নিজের script) |
Flip-flop-এ =, বা always @(posedge clk or rst_n)-এর মতো ভুল sensitivity list | Testbench-এ simulate করুন, synthesis report-এ latch আর warning দেখুন |
| IC-র নম্বর, pin বা setup/hold-এর মান বানিয়ে বলা | নির্মাতার datasheet বা cell library-র timing ফাইল — সংখ্যা সবসময় উৎস থেকে |
শুধু উত্তর না চেয়ে প্রতিটি সারির যুক্তি আর একটি স্বয়ংক্রিয় যাচাই চাইলে ভুল সহজে ধরা পড়ে:
AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। এগুলোই আপনাকে টেবিল-মুখস্থকারী থেকে নকশাকারী বানাবে।
প্র ০১Latch যদি এত বিপজ্জনক হয়, তাহলে কিছু দ্রুততম CPU-তে এখনো latch ব্যবহার হয় কেন?
Latch-এর বিপদ আর latch-এর সুবিধা — দুটিই আসে একই বৈশিষ্ট্য থেকে: স্বচ্ছতা। Flip-flop প্রতিটি pipeline ধাপের মাঝে একটি কঠিন দেয়াল তোলে: এক cycle-এর logic যত দ্রুতই শেষ হোক, ফল পরের edge-এর আগে এগোবে না; আর কোনো ধাপের logic একটু ধীর হলে পুরো clock-কেই ধীর করতে হয়। প্রতিটি দেয়াল নিজেও সময় খায় — setup time আর clock-to-Q delay প্রতি cycle-এ একবার করে দিতে হয়। খুব উঁচু clock speed-এ, যখন এক cycle-এ মাত্র কয়েক ডজন gate-এর delay ধরে, তখন এই “দেয়ালের খরচ” cycle-এর একটি বড় অংশ হয়ে দাঁড়ায়।
Latch-ভিত্তিক নকশায় দুই phase-এর clock থাকে, আর পরপর latch-গুলো পালা করে খোলে। যেহেতু latch খোলা থাকার সময় data পার হতে পারে, একটি ধীর ধাপ পরের ধাপের সময় থেকে কিছুটা “ধার” নিতে পারে — একে বলে time borrowing. ফলে ধাপগুলোর delay নিখুঁত সমান না হলেও clock দ্রুত রাখা যায়, আর clock skew-এর প্রতি সহনশীলতাও বাড়ে। উচ্চ-গতির কিছু custom CPU নকশায় latch বা খুব সরু pulse দিয়ে চালানো “pulsed latch” এজন্য ব্যবহার হয়েছে বলে প্রকাশিত গবেষণা ও শিল্প-প্রবন্ধে উল্লেখ আছে; তবে কোন chip-এ ঠিক কোথায়, তা নির্মাতারা সবসময় প্রকাশ করেন না।
দাম হলো যাচাই। Flip-flop-ভিত্তিক নকশায় timing tool প্রতিটি পথ আলাদা করে মাপতে পারে — এক register থেকে পরের register. Latch-ভিত্তিক নকশায় পথগুলো একে অপরের মধ্যে গড়িয়ে যায়, তাই বিশ্লেষণ জটিল, আর অংশ ৫-এর race-through সত্যিই ঘটার ঝুঁকি থাকে যদি দুই phase-এর মাঝে যথেষ্ট ফাঁক না থাকে। এজন্য সাধারণ ASIC আর প্রায় সব FPGA নকশা নিয়ম করে edge-triggered flip-flop ব্যবহার করে, আর FPGA tool অনিচ্ছাকৃত latch পেলে সতর্ক করে।
মূল উপলব্ধি: প্রকৌশলে “নিষিদ্ধ” জিনিস প্রায়ই আসলে “বিশেষজ্ঞের জন্য সংরক্ষিত”। Flip-flop নিরাপদ আর বিশ্লেষণযোগ্য বলে মানক; latch দ্রুত আর ঝুঁকিপূর্ণ বলে কেবল যেখানে প্রতিটি picosecond মূল্যবান আর যাচাইয়ের জন্য দক্ষ দল আছে।
প্র ০২বইয়ে JK আর T flip-flop এত গুরুত্ব পায়, অথচ আধুনিক chip প্রায় পুরোটাই D flip-flop দিয়ে বানানো — কেন?
১৯৬০ আর ৭০-এর দশকে ডিজিটাল নকশা হতো ছোট IC জুড়ে — একটি chip-এ দুটি বা চারটি flip-flop, কয়েকটি gate. তখন প্রতিটি বাড়তি gate মানে বাড়তি chip, বাড়তি তার, বাড়তি দাম। JK flip-flop সেখানে অসাধারণ উপযোগী ছিল: এর excitation table-এ প্রতিটি সারিতে একটি x, তাই counter নকশায় K-map-এ প্রচুর don't care, আর input-এর সূত্র প্রায়ই একটি তার বা একটি gate. একটি binary counter বানাতে JK-এর J আর K-তে 1 দিলেই চলে। এজন্য 7476 বা 74LS73-এর মতো JK IC তখন খুব জনপ্রিয় ছিল, আর বইগুলোও সেই যুগের নকশা-পদ্ধতি ধরে লেখা।
আজ নকশা হয় একটি chip-এর ভেতরে, synthesis tool দিয়ে। সেখানে কয়েকটি gate বাঁচানোর চেয়ে অনেক গুরুত্বপূর্ণ হলো একটি সরল, একরকম timing মডেল। D flip-flop-এর আচরণ সবচেয়ে সরল — Q+ = D — তাই পরের state-এর পুরো হিসাব combinational logic-এ থাকে, যা tool নিজের মতো সরল করে। JK বানাতে হলে tool তো ভেতরে D-এর সামনে JQ′ + K′Q-এর gate-ই বসাবে, তাই আলাদা JK cell রাখার লাভ কম। FPGA-তে তো প্রতিটি logic block-এ D flip-flop-ই থাকে; JK বা T চাইলে LUT দিয়ে সামনের logic বানানো হয়।
JK-এর নাম নিয়েও একটি মজার অনিশ্চয়তা আছে। অনেক জায়গায় লেখা হয় যে নামটি integrated circuit-এর উদ্ভাবক Jack Kilby-র নামে, কিন্তু এর পক্ষে নির্ভরযোগ্য প্রমাণ পাওয়া যায় না; প্রচলিত আরেকটি বিবরণ অনুযায়ী ১৯৫০-এর দশকে Hughes Aircraft-এর প্রকৌশলীরা নকশার খাতায় অক্ষর দুটি বেছে নিয়েছিলেন। নিশ্চিত না হলে “নামের উৎস বিতর্কিত” বলাই নিরাপদ।
তাহলে JK শেখা কেন? কারণ excitation table আর রূপান্তরের পদ্ধতি — “Q থেকে Q+-এ যেতে কোন input লাগবে” — হলো যেকোনো state machine নকশার মূল চিন্তা, আর JK-তে don't care-এর ব্যবহার K-map-এর দক্ষতা পরীক্ষার চমৎকার উপায়। পরীক্ষা আর ইন্টারভিউ এখনো এগুলো জিজ্ঞেস করে।
মূল উপলব্ধি: কোন উপাদান “সেরা”, তা প্রযুক্তি আর খরচের কাঠামো ঠিক করে। আলাদা IC-র যুগে gate কম লাগানোই জিতত; chip-এর ভেতরে, tool-এর যুগে সরলতা আর পূর্বানুমানযোগ্য timing জেতে।
প্র ০৩নিষিদ্ধ অবস্থা যদি এত বড় সমস্যা হয়, তাহলে SR latch আজও কোথায় কাজে লাগে, আর নিষিদ্ধ input এলে বাস্তব নকশা কী করে?
SR latch হারিয়ে যায়নি, শুধু চোখের আড়ালে গেছে। সবচেয়ে বড় উদাহরণ মেমরি: SRAM-এর প্রতিটি cell আসলে দুটি cross-coupled inverter — set আর reset input ছাড়া SR latch-এর কেন্দ্র। সেখানে মান লেখা হয় bit line দিয়ে লুপকে জোর করে একদিকে ঠেলে, যা S বা R দেওয়ার সমতুল্য। Flip-flop-এর ভেতরেও latch আছে, আর asynchronous preset/clear ঠিক SR-এর মতো কাজ করে।
দ্বিতীয় ক্ষেত্র সুইচ আর সংকেত ধরা। অংশ ৩-এ দেখেছেন, দুই দিকের সুইচের bounce দূর করতে S′R′ latch ক্লাসিক সমাধান। Interrupt বা error-এর “sticky flag”-ও প্রায়ই SR ধরনের: কোনো ঘটনা ঘটলে set, আর software পড়ে নেওয়ার পর reset. Microcontroller-এর status register-এ “write 1 to clear” ধরনের বিটগুলো এই চিন্তারই রূপ।
নিষিদ্ধ input সামলানোর বাস্তব কৌশল তিন রকম। (১) গঠনগতভাবে অসম্ভব করা — D latch যেমন S = D, R = D′ দিয়ে। (২) অগ্রাধিকার দেওয়া — set-dominant বা reset-dominant latch, যেখানে দুটি একসাথে এলে একটি নিশ্চিতভাবে জেতে; নিরাপত্তা-সংক্রান্ত নকশায় প্রায়ই reset জেতে, যাতে সন্দেহ হলে যন্ত্র বন্ধ থাকে। Verilog-এ if (r) q <= 0; else if (s) q <= 1; লিখলেই reset-dominant. (৩) Datasheet-এ নিষেধ লেখা — 7474-এর মতো IC-তে PRE′ আর CLR′ একসাথে 0 দিলে দুটি output-ই উঁচু হয়, আর datasheet সাধারণত সতর্ক করে যে দুটি একসাথে ছাড়লে অবস্থা স্থির থাকবে না।
অংশ ৩-এর simulator-এর দোলটি বাস্তবে আরেকটি সমস্যার আত্মীয়: দুটি gate প্রায় সমান হলে লুপ কিছুক্ষণ মাঝামাঝি ভোল্টেজে ঝুলে থাকতে পারে — metastability. Clock-এর সাথে না মেলা কোনো সংকেত (বোতাম, অন্য chip-এর সংকেত) flip-flop-এর setup-hold ভাঙলে একই জিনিস ঘটে। এর প্রতিকার, যেমন দুই flip-flop-এর synchronizer, পর্ব ১৮-এ।
মূল উপলব্ধি: “নিষিদ্ধ” input মানে প্রকৌশলীর দায়িত্ব — হয় সেটি অসম্ভব বানান, নয় একটি নিশ্চিত অর্থ দিন, নয় স্পষ্ট লিখে দিন যে এটি ব্যবহার করা যাবে না। চুপ করে থাকা কোনো বিকল্প নয়।
প্র ০৪স্মৃতির জন্য feedback-ই কি একমাত্র উপায়? DRAM, flash আর flip-flop কীভাবে ভিন্নভাবে “মনে রাখে”?
না, feedback একটি উপায় — তবে digital logic-এর ভেতরে সবচেয়ে দ্রুত আর নির্ভরযোগ্য উপায়। Flip-flop আর SRAM সক্রিয়ভাবে মনে রাখে: লুপের প্রতিটি gate বিদ্যুৎ খরচ করে অন্যটিকে প্রতিনিয়ত ঠেলে যাচ্ছে, তাই noise এলে লুপ নিজেই সংশোধন করে। বিদ্যুৎ চলে গেলে স্মৃতিও যায় — একে বলে volatile.
DRAM মনে রাখে নিষ্ক্রিয়ভাবে: প্রতিটি বিট একটি ক্ষুদ্র capacitor-এর চার্জ আর একটি transistor-এর দরজা। Feedback নেই, তাই cell অনেক ছোট — একটি transistor আর একটি capacitor, SRAM-এর ছয়টির জায়গায় — আর এক chip-এ অনেক বেশি বিট ধরে। কিন্তু চার্জ ধীরে ধীরে ফুটো হয়ে যায়, তাই memory controller-কে নিয়মিত (সাধারণত কয়েক দশ millisecond-এর মধ্যে) প্রতিটি সারি পড়ে আবার লিখতে হয় — refresh. Flash মনে রাখে একটি বিচ্ছিন্ন “floating gate” বা চার্জ-ফাঁদ স্তরে আটকানো ইলেকট্রন দিয়ে, যা বিদ্যুৎ ছাড়াও বছরের পর বছর থাকে, কিন্তু লেখা ধীর আর লেখার সংখ্যা সীমিত। পর্ব ৪৯-এ এগুলো বিস্তারিত দেখবেন।
ইতিহাসেও এই বৈচিত্র্য। ১৯১৮ সালের Eccles–Jordan circuit-এর পর tube-flip-flop দিয়ে প্রথম কম্পিউটারের register বানানো হয়, কিন্তু হাজার হাজার বিট tube দিয়ে রাখা ব্যয়বহুল ছিল। তাই ১৯৪০-৫০-এর দশকে mercury delay line (শব্দ-তরঙ্গে বিট ঘোরানো), Williams tube (পর্দায় চার্জের বিন্দু) আর পরে magnetic core memory (চুম্বকীয় আংটির দিক) — প্রতিটি আলাদা ভৌত নীতিতে স্মৃতি। Core memory-ও volatile নয়, আর ১৯৭০-এর দশকে semiconductor DRAM আসা পর্যন্ত এটিই ছিল প্রধান main memory.
আজকের কম্পিউটারে তিনটিই একসাথে: register আর pipeline-এ flip-flop (সবচেয়ে দ্রুত, সবচেয়ে কম), cache-এ SRAM, main memory-তে DRAM, আর storage-এ flash. এই স্তরবিন্যাস — দ্রুত কিন্তু ছোট থেকে ধীর কিন্তু বিশাল — মডিউল ৮-এর memory hierarchy-র মূল কথা।
মূল উপলব্ধি: “মনে রাখা” মানে কোনো ভৌত অবস্থাকে স্থির রাখা — feedback লুপ, চার্জ, চুম্বক বা আটকানো ইলেকট্রন। গতি, ঘনত্ব, বিদ্যুৎ আর স্থায়িত্বের মধ্যে প্রতিটির আলাদা trade-off, আর সেজন্যই একটি কম্পিউটারে একসাথে কয়েক রকম স্মৃতি থাকে।
প্র ০৫Simulator তো একটার পর একটা লাইন চালায় — তাহলে non-blocking assignment কীভাবে “সবকিছু একসাথে” ঘটার ভান করে, আর নিয়ম ভাঙলে বাস্তবে কী হয়?
Verilog simulator একটি event-চালিত প্রোগ্রাম। প্রতিটি simulation সময়-বিন্দুতে সে কাজগুলোকে কয়েকটি সারিতে (region) ভাগ করে। Clock-এর rising edge এলে সব always @(posedge clk) block জাগে আর “active” সারিতে চলে — কিন্তু কোন block আগে চলবে, ভাষার মান তা নির্দিষ্ট করে না। Blocking = সঙ্গে সঙ্গে মান বসায়। Non-blocking <= শুধু ডান পাশ হিসাব করে, আর বাঁ পাশে বসানোর কাজটি একটি আলাদা “NBA” সারিতে জমা রাখে। Active সারির সব কাজ শেষ হলে simulator সেই জমানো হালনাগাদগুলো একসাথে প্রয়োগ করে। তাই কোন block আগে চলল তাতে কিছু যায় আসে না: সবাই পুরোনো মানই পড়েছে — ঠিক যেমন আসল flip-flop-গুলো edge-এর আগের মান দেখে।
নিয়ম ভাঙার ফল তিন রকম। প্রথমত, এক block-এ = দিয়ে shift register লিখলে (b = a; c = b;) simulation-এ c সরাসরি a পায় — দুই ধাপের শিকল এক ধাপ হয়ে যায়, অনুশীলন ৪-এ যেমন দেখবেন। দ্বিতীয়ত, দুটি block-এ = হলে ফল simulator-এর ক্রমের ওপর নির্ভর করে — এক tool-এ পরীক্ষা পাস করে, আরেক tool-এ ফেল করে। তৃতীয়ত, synthesis tool লেখার অর্থ মেনে hardware বানায়, যা হয়তো simulation-এর কোনোটির সাথেই মেলে না; এই “simulation-synthesis mismatch” chip কারখানা থেকে ফেরার পর ধরা পড়লে খরচ বিশাল।
এই সমস্যাগুলো এত সাধারণ ছিল যে শিল্পে কয়েকটি সরল কোডিং নিয়ম মানক হয়ে গেছে, যা ২০০০ সালের দিকে Clifford Cummings-এর একটি বহুল-উদ্ধৃত সম্মেলন-প্রবন্ধে (“Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill!”) সুন্দরভাবে গুছিয়ে বলা হয়: sequential logic-এ <=, combinational logic-এ =, এক block-এ দুটি না মেশানো, আর একই variable দুই block থেকে না লেখা। SystemVerilog পরে always_ff আর always_comb যোগ করেছে, যাতে tool নিজেই ভুল ধরতে পারে।
মূল উপলব্ধি: HDL-এর কোড একটি প্রোগ্রাম নয়, একটি circuit-এর বর্ণনা। Simulator-কে hardware-এর সমান্তরালতার অনুকরণ করাতে ভাষার একটি বিশেষ নিয়ম লাগে — আর সেই নিয়ম মেনে লেখাই নিশ্চিত করে যে আপনি যা পরীক্ষা করছেন, chip-এ ঠিক তাই তৈরি হবে।
অনুশীলন
কাগজ-কলমে করুন, তারপর উত্তর খুলে মেলান। প্রতিটি উত্তর একটি script দিয়ে যাচাই করা।
-
Waveform trace: সময় t = 0 থেকে 11, প্রতিটি একক একটি ঘর। clk =
0 0 1 1 0 0 1 1 0 0 1 1, D =1 0 0 1 1 0 0 0 0 1 1 0. শুরুতে সব Q = 0, আর D কখনো ঠিক clock edge-এর মুহূর্তে বদলায় না। Q বের করুন (ক) clk = 1-এ খোলা D latch-এর, (খ) positive-edge D flip-flop-এর, (গ) negative-edge D flip-flop-এর।আগে edge চিহ্নিত করুন: rising edge t = 2, 6, 10; falling edge t = 4, 8.
t 0 1 2 3 4 5 6 7 8 9 10 11 clk 0 0 1 1 0 0 1 1 0 0 1 1 D 1 0 0 1 1 0 0 0 0 1 1 0 (ক) latch 0 0 0 1 1 1 0 0 0 0 1 0 (খ) pos-edge 0 0 0 0 0 0 0 0 0 0 1 1 (গ) neg-edge 0 0 0 0 1 1 1 1 0 0 0 0 (ক) Latch শুধু clk = 1-এর ঘরগুলোতে D অনুসরণ করে: t = 2, 3-এ D = 0, 1 → Q = 0, 1; t = 4, 5-এ বন্ধ, 1 থাকে; t = 6, 7-এ D = 0 → 0; t = 10, 11-এ 1, তারপর 0. খেয়াল করুন, t = 0-তে D = 1 হলেও latch বন্ধ ছিল, তাই Q = 0. (খ) Rising edge-এ D: t = 2-এ 0, t = 6-এ 0, t = 10-এ 1 — তাই Q শেষ দুই ঘর ছাড়া পুরো সময় 0. (গ) Falling edge-এ D: t = 4-এ 1, t = 8-এ 0 — তাই t = 4 থেকে 7 পর্যন্ত 1, তারপর 0. একই D থেকে তিনটি সম্পূর্ণ আলাদা Q — কোন উপাদান আর কোন ধার, তা না জেনে timing diagram আঁকা যায় না।
-
রূপান্তর: (ক) শুধু একটি D flip-flop আর প্রয়োজনীয় gate দিয়ে T flip-flop বানান। (খ) শুধু একটি T flip-flop আর gate দিয়ে JK flip-flop বানান। প্রতিটির জন্য পূর্ণ টেবিল আর সরল সূত্র দিন।
(ক) T থেকে চাওয়া, D হাতে। TQ = 00 → Q+ = 0, 01 → 1, 10 → 1, 11 → 0. D-এর excitation হলো D = Q+, তাই D-এর কলাম 0 1 1 0 — এটি XOR-এর টেবিল: D = T ⊕ Q. Circuit: একটি XOR gate, input T আর Q, output D-তে।
(খ) JK থেকে চাওয়া, T হাতে। T-এর excitation: T = Q ⊕ Q+. JKQ সারিগুলো: 000 → Q+ 0, T = 0; 001 → 1, T = 0; 010 → 0, T = 0; 011 → 0, T = 1; 100 → 1, T = 1; 101 → 1, T = 0; 110 → 1, T = 1; 111 → 0, T = 1. T-এর 1 আছে 011, 100, 110, 111-এ। K-map-এ জোড়া: 100 আর 110 (J = 1, Q = 0) → JQ′; 011 আর 111 (K = 1, Q = 1) → KQ. T = JQ′ + KQ. পড়ুন এভাবে: “Q = 0 হলে J = 1 মানে উল্টানো; Q = 1 হলে K = 1 মানে উল্টানো।” দুটি সূত্রই ৮টি (আর ৪টি) সারিতে script দিয়ে simulate করে মেলানো হয়েছে।
-
Excitation table প্রয়োগ: একটি flip-flop-এর output পরপর পাঁচটি clock edge-এ এই ক্রম মানতে হবে: Q = 0 → 1 → 1 → 0 → 0 → 1. প্রতিটি edge-এর জন্য SR, JK, D আর T flip-flop-এ কী input দিতে হবে, লিখুন (don't care হলে x).
Edge Q → Q+ S R J K D T ১ 0 → 1 1 0 1 x 1 1 ২ 1 → 1 x 0 x 0 1 0 ৩ 1 → 0 0 1 x 1 0 1 ৪ 0 → 0 0 x 0 x 0 0 ৫ 0 → 1 1 0 1 x 1 1 প্রতিটি সারি excitation table থেকে সরাসরি। লক্ষ করুন: D-এর কলাম হুবহু পরের Q-এর ক্রম (1 1 0 0 1), আর T-এর কলামে 1 শুধু যেখানে মান বদলেছে। JK-তে প্রতিটি edge-এ একটি x — counter নকশায় (পর্ব ১৬) এই স্বাধীনতাই K-map-এ বড় দল বানাতে দেয়। একটি সম্ভাব্য সরল JK সমাধান: J = 1 আর K = 1 যেখানে x — যেমন edge ১-এ J = 1, K = 1 দিলেও 0 → 1 (toggle) ঠিকই হয়।
-
Output অনুমান — Verilog: দুটি নকশা: (ক)
always @(posedge clk) begin b = a; c = b; end(খ)always @(posedge clk) begin b <= a; c <= b; end. শুরুতে b = c = 0; পরপর চারটি rising edge-এ a-এর মান 1, 0, 1, 1 (প্রতিটি edge-এর আগে স্থির)। প্রতিটি edge-এর পর b আর c কত? প্রতিটি নকশা কোন hardware হবে?(ক) Blocking: edge-এর পর (b, c) = (1, 1), (0, 0), (1, 1), (1, 1).
c = bপড়ে b-এর নতুন মান, যা সবে a থেকে এসেছে — তাই c সবসময় a-এর সমান। Synthesis দুটি flip-flop-এর D-তেই a জুড়ে দেবে (বা একটিতে মিলিয়ে দেবে) — দুই ধাপের শিকল হলো না।(খ) Non-blocking: (b, c) = (1, 0), (0, 1), (1, 0), (1, 1). প্রতিটি edge-এ c পায় b-এর পুরোনো মান — a-এর মান এক edge দেরিতে c-তে আসে। এটি দুই বিটের shift register (পর্ব ১৬): a → b → c. দুই কোড দেখতে প্রায় এক, কিন্তু hardware আলাদা — এজন্যই flip-flop-এ সবসময়
<=.
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএক flip-flop দিয়ে আরেকটি বানানোর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- যে flip-flop বানাতে চান, তার characteristic table লেখা
- প্রতিটি সারিতে Q → Q+ রূপান্তরটি চিহ্নিত করা
- হাতে থাকা flip-flop-এর excitation table থেকে দরকারি input লেখা
- K-map দিয়ে input-এর সূত্র সরল করা
- Circuit এঁকে সব সারিতে simulate করে মেলানো
দুটি NOR gate দিয়ে বানানো SR latch-এ S = 1 আর R = 1 দেওয়া হলো। স্থির হওয়ার পর Q আর Q′ কত?
- Q = 1, Q′ = 0
- Q = 0, Q′ = 0
- Q = 1, Q′ = 1
- Q ক্রমাগত 0 আর 1-এর মধ্যে দোল খায়
NAND gate দিয়ে বানানো S′R′ latch-এ এখন Q = 0. S′ = 0 আর R′ = 1 দেওয়া হলো। স্থির হওয়ার পর Q কত?
- Q = 1
- Q = 0 (আগের মান থাকে)
- অনির্ধারিত — নিষিদ্ধ অবস্থা
- Q দোল খেতে থাকে
একটি edge-triggered JK flip-flop-এ Q = 1, J = 1, K = 1. একটি সক্রিয় clock edge-এর পর Q কত? (Q+ = JQ′ + K′Q)
- 1, কারণ J = 1
- অনির্ধারিত, race-around হয়
- 0
- 1, কারণ hold
একটি JK flip-flop-কে পরের clock edge-এ Q = 1 থেকে Q = 0-তে নিতে হবে। Excitation table অনুযায়ী J আর K কত হবে? (x = don't care)
- J = 0, K = x
- J = 1, K = x
- J = x, K = 0
- J = x, K = 1
একটি D latch (clk = 1-এ খোলা) আর একটি positive-edge D flip-flop-এর D আর clk একই। দুটিরই Q = 0. clk = 1 থাকাকালীন (কোনো edge ছাড়া) D 0 থেকে 1-এ গেল আর clk নামা পর্যন্ত 1-ই থাকল। clk নামার পর দুটির Q কত?
- Latch 1, flip-flop 1
- Latch 1, flip-flop 0
- Latch 0, flip-flop 0
- Latch 0, flip-flop 1
একটি positive-edge D flip-flop-এ active-low asynchronous clear (CLR′) আছে। D = 1, আর একটি rising edge আসার সময় CLR′ = 0 রাখা হলো। Q কত হবে?
- 0
- 1
- আগের মান, কারণ clear শুধু পরের edge-এ কাজ করে
- অনির্ধারিত
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Sequential = combinational + স্মৃতি; স্মৃতি আসে feedback থেকে — দুটি cross-coupled gate-এর দুটি স্থির অবস্থা এক বিট।
- NOR SR latch: 00 hold, 10 set, 01 reset, 11 নিষিদ্ধ (Q = Q′ = 0, একসাথে ছাড়লে race). NAND S′R′: 11 hold, 00 নিষিদ্ধ (দুটি output 1).
- D latch (S = D, R = D′) নিষিদ্ধ অবস্থা দূর করে, কিন্তু enable চালু থাকার পুরো সময় স্বচ্ছ; master–slave (master clk′-এ, slave clk-এ খোলা) rising edge-এর মুহূর্তের D নেয়, race-through বন্ধ করে।
- Q+: SR = S + R′Q (SR = 0), D = D, JK = JQ′ + K′Q, T = T ⊕ Q. JK excitation: 0x, 1x, x1, x0. রূপান্তর: D থেকে JK — D = JQ′ + K′Q; JK থেকে T — J = K = T; D থেকে T — D = T ⊕ Q.
- বাস্তবে: async active-low preset/clear clock-এর ওপর জেতে; enable = সামনে mux; setup, hold, clock-to-Q মানতে হয় (পর্ব ১৮); Verilog-এ
always @(posedge clk or negedge rst_n)আর<=.
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ১৬ · Register, shift register আর counterপরবর্তী পর্বFlip-flop জুড়ে n-বিট register, shift register আর binary counter.
- পর্ব ১৪ · Hardware description language — Verilog-এর পরিচয় আর simulationঝালিয়ে নিনModule, testbench আর অনিচ্ছাকৃত latch-এর ফাঁদ।
- পর্ব ১২ · Multiplexer, decoder আর encoder — বেছে নেওয়া আর ঠিকানা খোঁজাএই পর্বে ব্যবহারFlip-flop-এর enable আর D latch-এর ভেতরের 2:1 mux.
- কম্পিউটার আর্কিটেকচার ও ডিজিটাল লজিক · কোর্স হোম৬২টি পর্বপুরো কোর্সের রোডম্যাপ — লজিক গেট থেকে multicore.
- কম্পিউটার ফান্ডামেন্টালস · সিকোয়েন্সিয়াল সার্কিটসহজ পরিচয়Flip-flop, register আর counter-এর ছবিসহ প্রাথমিক ধারণা।
- অপারেটিং সিস্টেম · Hardware primerসফটওয়্যারের দিকCPU-র register, clock আর মেমরি OS-এর চোখে।