সরাসরি পর্বে যান
পর্ব ১৭ · ৬২-এর মধ্যে · মডিউল ৩

Finite state machine — Moore, Mealy আর state diagram থেকে circuit

Finite State Machines — Moore, Mealy and From State Diagram to Circuit

Taught in Bangla, this lesson turns word problems into finite state machines: state register, next-state and output logic, Moore versus Mealy timing and state counts, the overlapping and non-overlapping 1011 sequence detector, serial parity and divisible-by-3 machines, state minimisation by partitioning and implication tables, binary, Gray and one-hot assignment, D and JK equations from K-maps, unused states and reset, synthesizable three-block Verilog FSMs and coverage testing, with simulators and a live C program.

এই পর্বে যা শিখবেন

  • State, input, output আর transition দিয়ে একটি বাস্তব সমস্যাকে state diagram আর state table-এ রূপ দেওয়া
  • Moore আর Mealy machine-এর পার্থক্য — output কখন আসে, কতগুলো state লাগে, আর কেন
  • “1011” sequence detector (overlapping ও non-overlapping, দুই মডেলেই), serial parity আর ৩ দিয়ে বিভাজ্যতা যাচাইয়ের FSM
  • Partition আর implication table দিয়ে state কমানো, binary/Gray/one-hot encoding-এর দর-কষাকষি, আর D ও JK flip-flop-এর সমীকরণ
  • অব্যবহৃত state, synchronous বনাম asynchronous reset, Verilog-এ synthesizable FSM লেখা আর coverage দিয়ে পরীক্ষা

১ · State machine কী — যে circuit অতীত মনে রাখে

মডিউল ২-এর circuit-গুলোর output শুধু এই মুহূর্তের input দেখত — একে বলে combinational circuit. কিন্তু বহু কাজে আগে কী ঘটেছে তা মনে রাখতে হয়। মোবাইল ব্যাংকিং অ্যাপে ভুল PIN দিলে অ্যাপ বলে “আর ২ বার সুযোগ আছে” — অর্থাৎ সে গুনে রেখেছে আগে কতবার ভুল হয়েছে। এই গোনা একটি স্মৃতি। স্মৃতির প্রতিটি সম্ভাব্য অবস্থাকে বলে state, আর যে যন্ত্র নির্দিষ্টসংখ্যক state-এর একটিতে থাকে আর input অনুযায়ী state বদলায়, তাকে বলে finite state machine (FSM).

প্রতিটি FSM চারটি জিনিস দিয়ে পুরো বর্ণনা করা যায়:

  • State-এর তালিকা — সসীম (finite), তাই নাম “finite”. যেমন: ভুল ০ বার, ১ বার, ২ বার, খোলা, বন্ধ (locked).
  • Input — বাইরে থেকে যা আসে: সঠিক PIN, ভুল PIN, logout.
  • Output — যন্ত্র যা জানায় বা করে: “২ বার সুযোগ আছে”, “স্বাগতম”, “অ্যাকাউন্ট বন্ধ”।
  • Transition-এর নিয়ম — কোন state-এ কোন input এলে কোন state-এ যাবে। একটি transition মানে এক state থেকে আরেক state-এ যাওয়া।

একটি অফিসভবনের লিফটের কথা ভাবুন। লিফটের “মন” আসলে কয়েকটি অবস্থা: থেমে আছে দরজা খোলা, থেমে আছে দরজা বন্ধ, ওপরে যাচ্ছে, নিচে যাচ্ছে। Input হলো বোতাম চাপা, তলার sensor, দরজার sensor. লিফট কখনো “ওপরে যাচ্ছে” অবস্থা থেকে সোজা “দরজা খোলা”-য় যায় না — আগে থামতে হয়। এই “কোন অবস্থা থেকে কোন অবস্থায় যাওয়া চলে” — নিয়মের তালিকাটিই FSM. নিয়মের বাইরে কিছু ঘটে না, তাই লিফট নিরাপদ।

সবচেয়ে ছোট উদাহরণ মেট্রোরেলের প্রবেশ-গেট বা টোকেন গেট (turnstile). দুটি state: বন্ধ আর খোলা. টোকেন বা কার্ড ছোঁয়ালে বন্ধ থেকে খোলা; কেউ ঢুকে গেলে (ধাক্কা) খোলা থেকে আবার বন্ধ। টোকেন ছাড়া ধাক্কা দিলে বন্ধই থাকে। এই তথ্য ছবিতে আঁকলে হয় state diagram — প্রতিটি state একটি বৃত্ত, প্রতিটি transition একটি তীর:

reset বন্ধ গেট আটকানো খোলা গেট ঘোরে টোকেন ধাক্কা (মানুষ ঢুকল) ধাক্কা টোকেন
ছবি ১৭.১ — Turnstile: দুটি state, চারটি transition. “reset” তীরটি দেখায় চালু হওয়ার সময় যন্ত্র কোন state-এ থাকে।

একই তথ্য টেবিলেও লেখা যায় — একে বলে state table. ছবি মানুষের বোঝার জন্য, টেবিল হিসাবের জন্য:

বর্তমান stateinput = টোকেনinput = ধাক্কাoutput (গেটের তালা)
বন্ধখোলাবন্ধতালা লাগানো
খোলাখোলাবন্ধতালা খোলা

PIN-এর উদাহরণে state পাঁচটি: WRONG0, WRONG1, WRONG2 (কতবার ভুল হয়েছে), UNLOCKED আর LOCKED. WRONG2-তে আরেকবার ভুল এলে LOCKED, আর LOCKED থেকে সঠিক PIN দিলেও আর খোলে না — শুধু গ্রাহকসেবা বা নির্দিষ্ট নিয়মে reset হলে ফেরে। এই নকশাটি অংশ ৯-এ একটি C প্রোগ্রামে চালিয়ে দেখবেন। খেয়াল করুন, FSM-এর state-এ পুরো ইতিহাস থাকে না — শুধু ভবিষ্যতের সিদ্ধান্তের জন্য যতটুকু দরকার ততটুকু। কোন ভুল PIN দেওয়া হয়েছিল তা মনে রাখার দরকার নেই, শুধু কতবার।

মূল ধারণা

State হলো অতীতের সারাংশ: অতীতের দুটি ভিন্ন ইতিহাস যদি ভবিষ্যতের সব input-এ একই আচরণ ঘটায়, তাদের একই state-এ রাখা যায়। এই ভাবনাই পরে state কমানোর (অংশ ৫) মূল ভিত্তি।

২ · Hardware-এ FSM-এর গঠন — register আর দুই টুকরো logic

Digital circuit-এ FSM প্রায় সবসময় synchronous: state বদলায় শুধু clock-এর সক্রিয় ধারে। গঠন তিন টুকরো:

x Next-state logic D State register clk, reset Q Output logic z বর্তমান state ফিরে আসে (feedback) শুধু Mealy: input সরাসরি output logic-এ
ছবি ১৭.২ — Synchronous FSM: মাঝখানের register-ই একমাত্র স্মৃতি; দুই পাশের logic স্মৃতিহীন। ড্যাশ দেওয়া তারটি থাকলে Mealy, না থাকলে Moore.
  • State register: কয়েকটি D flip-flop, যা বর্তমান state-এর বিট-নকশা ধরে রাখে। n বিটে সর্বোচ্চ ২nটি state. Flip-flop-এর ভেতরের গঠন পর্ব ১৫-এ (Latch আর flip-flop), আর register-এর বিস্তারিত পর্ব ১৬-এ।
  • Next-state logic: বর্তমান state Q আর input x থেকে পরের state হিসাব করে — সাধারণ combinational circuit. এর output যায় flip-flop-এর D-তে; পরের clock ধারে সেটিই নতুন state.
  • Output logic: output z হিসাব করে। এখানেই দুই মডেলের পার্থক্য।

গাণিতিকভাবে: state-এর সেট S, input-এর সেট I, output-এর সেট O, শুরুর state s0, আর transition function δ : S × I → S. Output function দুই রকম:

Moore machine

λ : S → O. Output শুধু বর্তমান state-এর। State diagram-এ output লেখা হয় বৃত্তের ভেতরে (যেমন S4/1). নাম Edward F. Moore-এর নামে — একে বলে Moore machine.

z = λ(Q)

Mealy machine

λ : S × I → O. Output বর্তমান state আর বর্তমান input দুটির। Output লেখা হয় তীরের গায়ে, input/output আকারে (যেমন 1/1). নাম George H. Mealy-র নামে — Mealy machine.

z = λ(Q, x)

রেস্তোরাঁর দুই রকম ওয়েটারের কথা ভাবুন। একজন (Moore) টেবিলে এসে প্রথমে খাতায় অর্ডার লেখেন, রান্নাঘরে দেন, পরের বার এসে খাবার দেন — সাড়া দেন একটু পরে, কিন্তু সবসময় খাতা দেখে, তাই ভুল কম। আরেকজন (Mealy) আপনার কথা শোনামাত্র তখনই কিছু একটা হাতে তুলে দেন (যেমন পানির গ্লাস) — সাড়া তাৎক্ষণিক, কিন্তু আপনি কথার মাঝে মত বদলালে তাঁর হাতের জিনিসও বদলে যায়।

৩ · নকশার ধাপ ১–২ · কথা থেকে state diagram — “1011” detector

FSM নকশার পূর্ণ পদ্ধতি সাত ধাপের — এই পর্বের বাকিটা এই ক্রমেই চলবে:

  1. কথার সমস্যা → state diagram (প্রতিটি state-এর অর্থ এক লাইনে লিখে রাখা)
  2. State table
  3. State minimisation — সমতুল্য state একত্র করা (অংশ ৫)
  4. State assignment — প্রতিটি state-কে বিট দেওয়া (অংশ ৬)
  5. Next-state আর output সমীকরণ — K-map দিয়ে (অংশ ৬)
  6. Circuit — flip-flop আর gate জোড়া
  7. Simulation দিয়ে যাচাই

উদাহরণ হিসেবে নিন পরীক্ষার সবচেয়ে প্রচলিত প্রশ্নটি: একটি serial তারে প্রতি clock-এ একটি বিট x আসে। যখনই শেষ চারটি বিট 1011 হয়, output z = 1. এই ধরনের নকশাকে বলে sequence detector. প্রথমে একটি প্রশ্নের উত্তর ঠিক করতে হয়: একটি মিলের শেষ অংশ কি পরের মিলের শুরু হতে পারবে? যেমন 1011011-এ দুটি মিল, মাঝের 1টি দুজনেরই। এটি গুনলে overlapping, না গুনলে non-overlapping. প্রশ্নে স্পষ্ট না থাকলে নিজের ধারণাটি লিখে দেওয়া ভালো অভ্যাস।

পদ্ধতি: প্রতিটি state-এর অর্থ হবে “লক্ষ্যের শুরুর কতটুকু এই মুহূর্তে মিলে আছে”। তাই A = কিছুই মেলেনি, B = 1, C = 10, D = 101. নতুন বিট এলে প্রশ্ন একটাই: এখন পর্যন্ত দেখা লেখার শেষ অংশের সবচেয়ে লম্বা কোন টুকরো 1011-এর শুরুর সাথে মেলে? নিচের stepper-এ Mealy নকশাটি state ধরে ধরে বানানো হলো:

State table (প্রতিটি ঘরে: পরের state / output z)
A (কিছু মেলেনি) — x = 0
A — x = 1
B (“1”) — x = 0
B — x = 1
C (“10”) — x = 0
C — x = 1
D (“101”) — x = 0
D — x = 1
  1. শুরুর state A. কিছুই মেলেনি। 0 এলে লাভ নেই, কারণ লক্ষ্য শুরু হয় 1 দিয়ে — A-তেই থাকি। 1 এলে লক্ষ্যের প্রথম বিট মিলল — B-তে যাই। Output এখনো 0.
  2. B = “1” মিলেছে। 0 এলে “10” — দুই বিট মিলল, C. 1 এলে দেখা লেখা “11”; লক্ষ্যের শুরু “10”, তাই “11” মেলে না, কিন্তু শেষের “1”টি নতুন শুরু হতে পারে — B-তেই থাকি। নতুনদের একটি প্রচলিত ভুল এখানে A-তে ফিরে যাওয়া।
  3. C = “10”. 1 এলে “101” — D. 0 এলে “100”: এর শেষ অংশ “00” বা “0” — কোনোটিই 1 দিয়ে শুরু নয়, তাই একেবারে শুরুতে, A.
  4. D-তে 1 = লক্ষ্য পূর্ণ। “1011” এসেছে, তাই এই তীরেই output z = 1 (Mealy — output তীরের গায়ে)। পরের state কী? “1011”-এর শেষ অংশগুলো: “011”, “11”, “1” — এর মধ্যে শুধু “1” লক্ষ্যের শুরুর সাথে মেলে। তাই overlapping নিয়মে B.
  5. D-তে 0. দেখা লেখা “1010”. শেষ অংশ “010” মেলে না, কিন্তু “10” মেলে — তাই C, A নয়। এই ঘরটিও পরীক্ষায় প্রায়ই ভুল হয়।
  6. সম্পূর্ণ। ৪টি state × ২টি input = ৮টি ঘর, প্রতিটি ঘরে পরের state আর output. Non-overlapping চাইলে শুধু D-তে 1-এর ঘরটি বদলায়: মিলের পর সব ভুলে A-তে ফেরা, তাই D --1/1--> A. বাকি সাতটি ঘর একই।

এই “শেষ অংশের সবচেয়ে লম্বা টুকরো যা লক্ষ্যের শুরুর সাথে মেলে” — নিয়মটি string matching-এর KMP অ্যালগরিদমের failure function-এর সাথে হুবহু এক; আগ্রহী হলে DSA কোর্সের string matching পর্ব দেখতে পারেন। নিচে একই Mealy নকশার ছবি:

A — B 1 C 10 D 101 1/0 0/0 1/0 0/0 0/0 1/0 0/0 1/1 (মিল!)
ছবি ১৭.৩ — “1011” overlapping Mealy detector. প্রতিটি তীরে input/output. লাল তীরেই z = 1; non-overlapping নকশায় এই তীরটি B-র বদলে A-তে যায়।

একই detector, Moore মডেলে

Moore-এ output state-এর গায়ে থাকে, তাই “1011 পূর্ণ হয়েছে” — এই খবরের জন্য একটি আলাদা state লাগে। S0 = কিছু মেলেনি, S1 = 1, S2 = 10, S3 = 101, আর নতুন S4 = 1011 এইমাত্র এসেছে (output 1). S4 থেকে পরের transition-গুলো ঠিক Mealy-র B-এর মতো, কারণ overlapping নিয়মে “1011”-এর শেষ “1” নতুন শুরু:

State (অর্থ)x = 0x = 1z
S0 (কিছু না)S0S10
S1 (“1”)S2S10
S2 (“10”)S0S30
S3 (“101”)S2S40
S4 (“1011” পূর্ণ)S2S11

S4-এ 0 এলে “10110”-এর শেষ “10” মেলে, তাই S2; 1 এলে “10111”-এর শেষ “1”, তাই S1. Non-overlapping Moore-এ S4-এর সারি হবে S0 আর S1 (মিলের পর নতুন করে শুরু; তবু নতুন 1টি প্রথম বিট হিসেবে গোনা যায়)।

৪ · Moore বনাম Mealy — output কখন আসে, state কত লাগে

দুই নকশাকে একই input দিয়ে চালালে আসল পার্থক্য চোখে পড়ে। আগে Moore detector-কে 1101011 দিয়ে cycle ধরে ধরে দেখুন। প্রতি cycle-এ output হলো বর্তমান state-এর output; clock ধারে state বদলায়:

Cycle-এর অবস্থা (Moore, পাশে একই input-এ Mealy)
cycle
এখন পর্যন্ত আসা বিট
এই cycle-এর input x
Moore বর্তমান state
Moore z (state থেকে)
ধারের পর Moore state
Mealy state / z
  1. Cycle ০. Reset-এর পর S0, তাই z = 0. Input x = 1 আসছে; clock ধারে S1-এ যাবে। Mealy-ও A-তে, z = 0.
  2. Cycle ১ — S1. আবার 1. “11”-এর শেষ “1” নতুন শুরু, তাই ধারের পর S1-এই থাকে। এই ধাপে বহু হাতে-করা উত্তর ভুল করে S0-তে ফেরে।
  3. Cycle ২ — S1, x = 0. “110”-এর শেষ “10” মেলে, তাই পরের state S2.
  4. Cycle ৩ — S2, x = 1. “1101”-এর শেষ “101” — S3-এর দিকে। এখনো z = 0.
  5. Cycle ৪ — S3, x = 0. লক্ষ্য ছিল 1, এল 0. সব হারায়নি: “11010”-এর শেষ “10” মেলে, তাই S2 (S0 নয়)।
  6. Cycle ৫ — S2, x = 1. আবার “101” — S3. দেখুন, ভুল বিটের পরেও যন্ত্র দুই বিট এগিয়ে থেকে আবার চেষ্টা করছে।
  7. Cycle ৬ — S3, x = 1. “1011” পূর্ণ হলো এই cycle-এর input-এ। Moore-এর z এখনো 0, কারণ সে শুধু state দেখে, আর state এখনো S3. কিন্তু Mealy (D-তে x = 1) এই cycle-এই z = 1 দিচ্ছে।
  8. Cycle ৭ — S4, z = 1. ধারের পর Moore S4-এ, আর এখন z = 1 — Mealy-র চেয়ে ঠিক এক cycle পরে, আর পুরো একটি cycle জুড়ে স্থির। Input যা-ই আসুক, এই cycle-এ Moore-এর output বদলাবে না।

এবার একটি ছোট simulator দিয়ে তিনটি নকশা — Moore, Mealy আর non-overlapping Mealy — একই input 10110110-এ পাশাপাশি চালানো যাক। Simulator-টি সাধারণ: যেকোনো state table আর বিট-স্ট্রিং দিলে প্রতিটি cycle ছাপে:

// Generic synchronous FSM simulator: give it a state table, it prints every clock cycle.
// Moore: out[state]. Mealy: out[state][x]. One input bit x is sampled per clock edge.
const moore = { kind: "Moore", start: "S0",
  next: { S0: ["S0", "S1"], S1: ["S2", "S1"], S2: ["S0", "S3"], S3: ["S2", "S4"], S4: ["S2", "S1"] },
  out:  { S0: 0, S1: 0, S2: 0, S3: 0, S4: 1 } };              // only S4 ("1011 seen") says 1
const mealy = { kind: "Mealy", start: "A",
  next: { A: ["A", "B"], B: ["C", "B"], C: ["A", "D"], D: ["C", "B"] },
  out:  { A: [0, 0], B: [0, 0], C: [0, 0], D: [0, 1] } };       // output on the D --1--> B arc
const noOv = { ...mealy, kind: "Mealy-nonoverlap",
  next: { ...mealy.next, D: ["C", "A"] } };                     // after a hit, start again from A
function step(m, s, x) {                                        // one clock cycle
  const z = m.kind === "Moore" ? m.out[s] : m.out[s][x];        // output during this cycle
  return { z, next: m.next[s][x] };                             // state after the clock edge
}
function simulate(machines, bits) {
  const st = machines.map(m => m.start), zs = machines.map(() => "");
  console.log(("cyc x | " + machines.map(m => m.kind.padEnd(17)).join("| ")).trimEnd());
  [...bits].forEach((ch, t) => {
    const x = +ch, cells = machines.map((m, i) => {
      const r = step(m, st[i], x), cell = `${st[i]}->${r.next} z=${r.z}`;
      st[i] = r.next; zs[i] += r.z; return cell.padEnd(17);
    });
    console.log((` ${t}  ${x} | ` + cells.join("| ")).trimEnd());
  });
  machines.forEach((m, i) => console.log(`${m.kind.padEnd(16)} z = ${zs[i]}`));
}
simulate([moore, mealy, noOv], "10110110");

আউটপুট (নির্ধারিত — প্রতিবার একই):

cyc x | Moore            | Mealy            | Mealy-nonoverlap
 0  1 | S0->S1 z=0       | A->B z=0         | A->B z=0
 1  0 | S1->S2 z=0       | B->C z=0         | B->C z=0
 2  1 | S2->S3 z=0       | C->D z=0         | C->D z=0
 3  1 | S3->S4 z=0       | D->B z=1         | D->A z=1
 4  0 | S4->S2 z=1       | B->C z=0         | A->A z=0
 5  1 | S2->S3 z=0       | C->D z=0         | A->B z=0
 6  1 | S3->S4 z=0       | D->B z=1         | B->B z=0
 7  0 | S4->S2 z=1       | B->C z=0         | B->C z=0
Moore            z = 00001001
Mealy            z = 00010010
Mealy-nonoverlap z = 00010000

তিনটি জিনিস লক্ষ করুন। এক: cycle ৩-এ চতুর্থ বিট (1) এসে “1011” পূর্ণ করে। Mealy সেই cycle-এই z = 1 দেয় (D->B z=1), কিন্তু Moore দেয় cycle ৪-এ (S4->S2 z=1) — এক cycle পরে। দুই: cycle ৬-এ আবার মিল — overlapping, কারণ cycle ৩-এর 1টি দ্বিতীয় “1011”-এরও প্রথম বিট। Mealy-র z = 00010010-এ দুটি 1, Moore-এর 00001001-এ একই দুটি 1, শুধু এক ঘর ডানে সরানো। তিন: non-overlapping নকশা মিলের পর A-তে ফিরে নতুন করে শোনে (D->A), তাই দ্বিতীয় মিলটি গোনে না: z = 00010000. নিজে চালিয়ে দেখুন: শেষ লাইনে input বদলে "1011011011" দিন, বা noOv-এর D সারিতে অন্য কিছু বসিয়ে দেখুন কোন মিল হারায়।

কেন Moore-এ state বেশি লাগে — একটি ছোট প্রমাণ

দাবি: একই input-output আচরণের জন্য (Moore-এর এক cycle দেরি মেনে নিয়ে) সবচেয়ে ছোট Mealy machine-এর state-সংখ্যা সবচেয়ে ছোট Moore machine-এর চেয়ে বেশি নয়।

  • Moore → Mealy, state একই: যেকোনো Moore machine নিন। প্রতিটি তীর s --x--> t-এর গায়ে output হিসেবে λ(t) লিখুন — অর্থাৎ গন্তব্য state-এর output. ফল একটি Mealy machine, state-সংখ্যা একই, আর Moore যে output পরের cycle-এ দিত, এটি সেটিই এই cycle-এ দেয়। তাই Mealy-র ন্যূনতম state-সংখ্যা ≤ Moore-এর।
  • Mealy → Moore, state বাড়তে পারে: একটি Mealy state-এ যদি ভিন্ন output-ওয়ালা তীর এসে পৌঁছায় (যেমন B-তে A --1/0--> B আর D --1/1--> B), Moore-এ সেই state-কে output অনুযায়ী ভাগ করতে হয় — B0 আর B1. সবচেয়ে খারাপ ক্ষেত্রে state-সংখ্যা |S| × |O| পর্যন্ত হয়। আমাদের detector-এ শুধু B ভাগ হয়েছে: B1 = S4, তাই ৪ থেকে ৫।
দিকMooreMealy
Output নির্ভর করেশুধু statestate + input
সাড়াএক cycle পরেএকই cycle-এ
“1011” detector-এ state / flip-flop (binary)৫ / ৩৪ / ২
Output-এর স্থিরতাপুরো cycle স্থির; input-এর glitch output-এ যায় নাinput cycle-এর মাঝে বদলালে output-ও বদলায়
TimingOutput-এর পথ ছোট: register → output logicInput → output সরাসরি combinational পথ; কয়েকটি Mealy পরপর জুড়লে পথ লম্বা হয়, এমনকি combinational loop-এর ঝুঁকি

বাস্তবে নকশাকারীরা প্রায়ই মাঝামাঝি পথ নেন: Mealy-তে হিসাব করে output-টিকে একটি flip-flop-এ ধরে রাখা (registered output). তখন আচরণ Moore-এর মতো এক cycle দেরিতে, কিন্তু state কম। Timing-এর এই হিসাব — setup, hold আর critical path — বিস্তারিত পর্ব ১৮-এ (Timing আর clock).

৫ · ধাপ ৩ · State minimisation — সমতুল্য state একত্র করা

প্রথমবার state diagram আঁকলে প্রায়ই অপ্রয়োজনীয় state থেকে যায় — বিশেষ করে বড় সমস্যায়, বা কেউ “প্রতিটি ঘটনার জন্য একটি নতুন state” নিয়ম মেনে আঁকলে। কম state মানে কম flip-flop (বা একই flip-flop-এ বেশি don't care) আর প্রায়ই ছোট logic. তাই ধাপ ৩: state minimisation.

সংজ্ঞা: দুটি state p আর q equivalent (p ≡ q), যদি যেকোনো input-ধারা p থেকে চালালে যে output-ধারা আসে, q থেকে চালালেও ঠিক সেটিই আসে। বাইরে থেকে এদের আলাদা করার কোনো পরীক্ষা নেই, তাই একটিকে মুছে তার দিকের সব তীর অন্যটিতে ঘুরিয়ে দেওয়া যায়। সরাসরি “সব input-ধারা” পরীক্ষা অসম্ভব (অসীম), তাই ধাপে ধাপে ভাবা হয়:

  • p আর q k-equivalent, যদি ১ থেকে k দৈর্ঘ্যের সব input-ধারায় output এক। ১-equivalent মানে প্রতিটি একক input-এ output এক — এটিই শুরুর ভাগ, যাকে এই পর্বে P0 বলা হয়েছে (কিছু বই একে P1 বলে)। Moore-এ শুরুর ভাগ হয় state-এর নিজের output দিয়ে।
  • মূল সূত্র: p আর q (k+1)-equivalent ⇔ এদের output প্রতিটি input-এ এক, আর প্রতিটি input x-এ δ(p, x) আর δ(q, x) k-equivalent.
  • প্রতিটি ধাপে দলগুলো শুধু ভাঙতে পারে, জোড়া লাগে না; আর n state-এর বেশি দল হতে পারে না। তাই সর্বোচ্চ n − ১ ধাপে এমন একটি ধাপ আসে যেখানে কিছু ভাঙে না। তখন থেকে আর কখনো ভাঙবে না (পরের ধাপ একই সূত্রে একই দল থেকে হিসাব হয়) — সেই দলগুলোই আসল equivalence-এর দল।

এই পদ্ধতির নাম partition refinement (বইভেদে partition method বা Moore-এর algorithm). একটি ৭-state Mealy machine নিন, যা কেউ বাড়তি state রেখে এঁকেছেন:

Statex = 0: পরের / zx = 1: পরের / z
A (শুরু)A / 0B / 0
BC / 0E / 0
CG / 0D / 0
DF / 0E / 1
EF / 0B / 0
FA / 0D / 0
GG / 0E / 0
প্রতিটি state: দল আর “স্বাক্ষর” (x = 0 আর x = 1-এ পরের state কোন দলে)
দলের ভাগ
A
B
C
D
E
F
G
  1. P0 — output দিয়ে প্রথম ভাগ। প্রতিটি state-এর output-সারি (x = 0, x = 1) দেখুন। শুধু D-এর সারি “0 1”, বাকি ছয়টির “0 0”. তাই P0 = {A,B,C,E,F,G} {D}. ভিন্ন দলের দুটি state কখনো equivalent নয় — একটি এক-বিটের input-ই তাদের আলাদা করে।
  2. স্বাক্ষর হিসাব। বড় দল I-এর প্রতিটি state-এর জন্য লিখুন, x = 0 আর x = 1-এ পরের state কোন দলে। C যায় (G, D) = (I, II), F যায় (A, D) = (I, II); বাকি চারটি (I, I). স্বাক্ষর আলাদা মানে আলাদা ভবিষ্যৎ: C বা F থেকে “1” দিলে D-তে পৌঁছায়, তারপর আরেকটি “1” দিলে z = 1 — অন্যদের থেকে তা হয় না।
  3. P1 = {A,B,E,G} {C,F} {D}. নতুন দল দিয়ে আবার স্বাক্ষর: B যায় (C, E) = (β, α), E যায় (F, B) = (β, α); কিন্তু A যায় (A, B) = (α, α), G যায় (G, E) = (α, α). তাই α দুই ভাগে ভাঙে। β-র C আর F দুজনেই (α, γ) — অটুট।
  4. P2 = {A,G} {B,E} {C,F} {D}. আবার পরীক্ষা: A (AG, BE) আর G (AG, BE) মেলে; B আর E দুজনেই (CF, BE); C আর F দুজনেই (AG, D). কোনো দল ভাঙল না, তাই P3 = P2 — থামুন। মোট তিনটি ধাপে স্থির।
  5. ছোট machine. প্রতিটি দল থেকে একটি নাম রাখুন: G → A, E → B, F → C. নতুন টেবিল: A: A/0, B/0 · B: C/0, B/0 · C: A/0, D/0 · D: C/0, B/1. চিনতে পারছেন? এটি অংশ ৩-এর “1011” overlapping Mealy detector-ই — বাড়তি তিনটি state শুধু নকল ছিল।

একই কাজ implication table দিয়ে

পরীক্ষায় অনেক সময় implication table চাওয়া হয়। প্রতিটি state-জোড়ার একটি ঘর (৭টি state-এ ৭ × ৬ / ২ = ২১টি)। ধাপ: (১) output ভিন্ন হলে ঘরে X. (২) নইলে ঘরে লিখুন, এই জোড়া equivalent হতে হলে কোন কোন জোড়াকে equivalent হতে হবে (পরের state-এর জোড়া)। (৩) বারবার পুরো টেবিল ঘুরে দেখুন: কোনো ঘরের শর্তে X-ওয়ালা জোড়া থাকলে সেই ঘরেও X. আমাদের machine-এ:

ধাপযে জোড়াগুলোয় X পড়লকারণ
শুরুAD, BD, CD, DE, DF, DGD-এর output (x = 1-এ 1) বাকিদের থেকে আলাদা
পাস ১AC, BC, CE, AF, BF, EF, CG, FGপ্রত্যেকের শর্তে একটি D-জোড়া আছে, যেমন AC চায় BD, CG চায় DE
পাস ২AB, AE, BG, EGAB চায় AC আর BE — AC এখন X; AE চায় AF — X
পাস ৩নতুন কিছু নয় — থামুনবাকি ঘর: AG (চায় BE), BE (চায় CF), CF (চায় AG)

যে তিনটি ঘর X-মুক্ত রইল — AG, BE, CF — সেগুলোই equivalent জোড়া, partition-এর ফলের সাথে হুবহু এক। লক্ষ করুন, বাকি তিনটি শর্ত একে অন্যের ওপর চক্রাকারে নির্ভর করে (AG চায় BE, BE চায় CF, CF চায় AG) — কোনো বিরোধ নেই বলে তিনটিই টিকে যায়। নিচের প্রোগ্রাম partition refinement চালিয়ে প্রতিটি ধাপ ছাপে, তারপর মূল আর ছোট machine-কে ৮ বিট পর্যন্ত দৈর্ঘ্যের সব input-ধারায় চালিয়ে মেলায়:

// State minimisation by partition refinement on a 7-state Mealy machine.
// M[s][x] = [next state, output]. Start state A.
const M = { A: [["A", 0], ["B", 0]], B: [["C", 0], ["E", 0]], C: [["G", 0], ["D", 0]],
            D: [["F", 0], ["E", 1]], E: [["F", 0], ["B", 0]], F: [["A", 0], ["D", 0]],
            G: [["G", 0], ["E", 0]] };
const S = Object.keys(M), show = P => P.map(g => "{" + g.join(",") + "}").join(" ");
function split(keyOf) {                       // group states that have the same key
  const g = {}; S.forEach(s => (g[keyOf(s)] ??= []).push(s)); return Object.values(g);
}
let P = split(s => "out" + M[s].map(c => c[1]).join("")), k = 0;  // P0: same output row
for (;;) {
  console.log(`P${k}: ${show(P)}`);
  const id = {}; P.forEach((g, i) => g.forEach(s => (id[s] = i)));
  const Q = split(s => id[s] + ":" + M[s].map(c => id[c[0]]).join(","));  // same block AND same next-blocks
  if (Q.length === P.length) { console.log(`P${k + 1} = P${k}: stable`); break; }
  P = Q; k++;
}
const rep = {}; P.forEach(g => g.forEach(s => (rep[s] = g[0])));   // name each block by its first state
const R = {}; P.forEach(g => (R[g[0]] = M[g[0]].map(([n, z]) => [rep[n], z])));
console.log("reduced table (state: x=0 next/z, x=1 next/z):");
for (const s in R) console.log(`  ${s}: ${R[s][0].join("/")}  ${R[s][1].join("/")}`);
function outputs(T, bits) {                   // output string of a machine on an input string
  let s = "A", z = "";
  for (const ch of bits) { z += T[s][+ch][1]; s = T[s][+ch][0]; }
  return z;
}
let tested = 0, bad = 0;
for (let len = 1; len <= 8; len++)
  for (let v = 0; v < 1 << len; v++) {
    const bits = v.toString(2).padStart(len, "0"); tested++;
    if (outputs(M, bits) !== outputs(R, bits)) bad++;
  }
console.log(`${S.length} states -> ${P.length} states; ${tested} input strings checked, ${bad} differ`);

আউটপুট:

P0: {A,B,C,E,F,G} {D}
P1: {A,B,E,G} {C,F} {D}
P2: {A,G} {B,E} {C,F} {D}
P3 = P2: stable
reduced table (state: x=0 next/z, x=1 next/z):
  A: A/0  B/0
  B: C/0  B/0
  C: A/0  D/0
  D: C/0  B/1
7 states -> 4 states; 510 input strings checked, 0 differ

প্রথম চার লাইন ঠিক stepper-এর চারটি ধাপ: P0-এ শুধু output দিয়ে ভাগ, P1-এ C আর F আলাদা হলো, P2-এ A-G আর B-E আলাদা হলো, আর P3 = P2 বলে থামা। কোডের মূল লাইনটি split(s => id[s] + ":" + …) — একটি state-এর “চাবি” হলো তার নিজের দল আর দুই পরের state-এর দল; একই চাবির state-গুলো এক দলে যায়। তারপর ছোট টেবিলটি হুবহু “1011” detector. শেষ লাইন 510 input strings checked, 0 differ: ১ থেকে ৮ দৈর্ঘ্যের মোট ২ + ৪ + … + ২৫৬ = ৫১০টি ধারায় দুই machine-এর output এক। এটি প্রমাণ নয়, যাচাই — প্রমাণটি ওপরের k-equivalence-এর যুক্তি; তবে টেবিলে একটি ভুল ঢুকিয়ে দেখুন (যেমন G-এর x = 1-এ ["D", 0]), সাথে সাথে partition বদলাবে।

সাধারণ ভুল: শুধু “একই output, একই পরের state” দেখে জোড়া মেলানো (row matching). এটি নিরাপদ কিন্তু অসম্পূর্ণ — B আর E-এর পরের state (C, E) আর (F, B) হুবহু এক নয়, তবু তারা equivalent. চক্রাকার নির্ভরতা ধরতে partition বা implication table লাগে। আরেকটি ভুল: Moore machine-এ শুরুর ভাগ করতে ভুলে Mealy-র মতো তীরের output দেখা — Moore-এ ভাগ হয় state-এর নিজের output দিয়ে।

৬ · ধাপ ৪–৭ · State assignment, K-map থেকে সমীকরণ আর যাচাই

ধাপ ৪ · কোন state পাবে কোন বিট

A, B, C, D নামগুলো hardware বোঝে না; প্রতিটিকে একটি বিট-নকশা দিতে হয়। এই সিদ্ধান্তকে বলে state assignment বা state encoding. n-টি state-এর জন্য প্রধান তিনটি পথ:

Encoding৪টি state-এ উদাহরণFlip-flopসুবিধাঅসুবিধা
Binary00, 01, 10, 11⌈log2 n⌉সবচেয়ে কম flip-flopNext-state logic অনেক বিটের ওপর নির্ভর করতে পারে
Gray00, 01, 11, 10⌈log2 n⌉ক্রমানুসারে চলা machine-এ প্রতি ধারে এক বিট বদলায় — কম toggle, কম শক্তিশাখা-প্রশাখার machine-এ সুবিধা কম, logic বড়ও হতে পারে
One-hot1000, 0100, 0010, 0001nপ্রতিটি next-state সমীকরণ ছোট আর অগভীর; দ্রুত; ডিবাগ সহজ (কোন বিট 1, সেটিই state)বেশি flip-flop; ২n − n টি অবৈধ নকশা — reset আর নিরাপত্তার যত্ন লাগে

One-hot-এর সমীকরণ লেখা প্রায় যান্ত্রিক: “এই state-এর flip-flop পরের ধারে 1 হবে, যদি এখন এমন কোনো state সক্রিয় থাকে যার তীর এখানে আসে, আর সেই তীরের input মেলে”। যেমন “1011” detector-এ C-তে আসে B --0--> আর D --0-->, তাই DC = QBx′ + QDx′. FPGA-তে প্রতিটি LUT-এর পাশে flip-flop প্রায় বিনামূল্যে থাকে, আর এমন ছোট সমীকরণ একটি LUT-এই ধরে যায় — তাই FPGA-র synthesis tool প্রায়ই নিজে থেকে FSM-কে one-hot-এ বদলে নেয় (tool আর সেটিংসভেদে)। ASIC-এ flip-flop তুলনায় দামি, তাই ছোট-মাঝারি FSM-এ binary বা নকশাকারীর বাছা encoding বেশি দেখা যায়।

Binary-র ভেতরেও কোন state কোন কোড পাবে, তাতে logic বদলায়। ৪টি state-এ ৪! = ২৪ রকম assignment, আর বড় machine-এ সংখ্যাটি বিশাল — তাই পুরোনো পাঠ্যবইয়ে হাতে-খাটানো নিয়ম আছে: যে দুটি state-এর একই পরের state, বা যারা একই state-এর পরের state, তাদের পাশাপাশি (এক বিট ভিন্ন) কোড দিন — এতে K-map-এ 1-গুলো পাশাপাশি পড়ে বড় দল হয়। আধুনিক tool এই খোঁজ heuristic দিয়ে করে।

ধাপ ৫–৭ · K-map থেকে সমীকরণ, circuit আর যাচাই

Binary assignment নিন: A = 00, B = 01, C = 10, D = 11 (বিট Q1Q0). প্রতিটি সারিতে বর্তমান Q1Q0 আর x থেকে পরের Q1+Q0+ আর z লিখুন। D flip-flop-এ Q+ = D, তাই পরের state-এর বিটই সরাসরি D ইনপুট — একে বলে transition table:

StateQ1 Q0 xপরের stateD1 D0z
A0 0 0A0 00
A0 0 1B0 10
B0 1 0C1 00
B0 1 1B0 10
C1 0 0A0 00
C1 0 1D1 10
D1 1 0C1 00
D1 1 1B0 11

এবার প্রতিটি কলাম আলাদা একটি ৩-চলকের Boolean function — পর্ব ০৯-এর K-map দিয়ে সরল করুন (এই পৃষ্ঠায় complement লেখা হয়েছে প্রাইম চিহ্নে: x′ মানে NOT x; কোডের আউটপুটে একই জিনিস ASCII ' দিয়ে):

  • D1 = Σm(2, 5, 6). ঘর ২ (010) আর ৬ (110) পাশাপাশি — দল Q0x′. ঘর ৫ (101) একা — Q1Q0′x. তাই D1 = Q0x′ + Q1Q0′x.
  • D0 = Σm(1, 3, 5, 7) — x = 1-এর চারটি ঘরই। এক দলে: D0 = x. অর্থ স্পষ্ট: শেষ বিট 1 হলেই পরের state B বা D (দুটিরই Q0 = 1).
  • z = Σm(7) = Q1Q0x — state D আর x = 1. Mealy বলে x আছে।

ধাপ ৬, circuit: দুটি D flip-flop (একই clock); D0-এ সরাসরি x-এর তার; D1-এ দুটি AND (২ আর ৩ ইনপুটের) আর একটি OR; z-এর জন্য একটি ৩-ইনপুট AND; আর x′ ও Q0′-এর জন্য দুটি inverter. সব মিলিয়ে কয়েকটি gate — ৪টি product term, ৯টি literal. Encoding বদলালে এই হিসাব কেমন বদলায়, আর সমীকরণগুলো আসলেই state table মেনে চলে কি না (ধাপ ৭), নিচের প্রোগ্রাম দেখায়। এটি ছোট একটি brute-force minimiser চালিয়ে binary আর Gray-তে ন্যূনতম SOP খোঁজে, one-hot-এ তীর গুনে সমীকরণ লেখে, তারপর তিনটি circuit-কে ২৫৬ cycle চালিয়ে টেবিলের সাথে মেলায়:

// Minimised "1011" Mealy detector -> D flip-flop and output equations under three encodings.
const T = { A: [["A", 0], ["B", 0]], B: [["C", 0], ["B", 0]], C: [["A", 0], ["D", 0]], D: [["C", 0], ["B", 1]] };
const S = Object.keys(T), lits = c => [...c].filter(ch => ch !== "-").length;
const has = (c, m, n) => [...c].every((ch, i) => ch === "-" || +ch === ((m >> (n - 1 - i)) & 1));
function minSOP(n, f) {                       // f(m) = 1 or 0; brute-force smallest SOP (n <= 3)
  const all = [...Array(1 << n).keys()], on = all.filter(m => f(m)), cubes = [];
  for (let v = 0; v < 3 ** n; v++) { let c = ""; for (let i = 0, w = v; i < n; i++, w = (w - w % 3) / 3) c += "01-"[w % 3]; cubes.push(c); }
  const imp = cubes.filter(c => all.every(m => !has(c, m, n) || f(m)) && on.some(m => has(c, m, n)));
  let best = [], cost = Infinity;                   // try every subset of implicants
  for (let mask = 0; mask < 2 ** imp.length; mask++) {   // cost = literals, then number of terms
    const pick = imp.filter((_, i) => Math.floor(mask / 2 ** i) % 2), c = pick.reduce((a, p) => a + lits(p), 0) * 100 + pick.length;
    if (c < cost && on.every(m => pick.some(p => has(p, m, n)))) { best = pick; cost = c; }
  }
  return best; }
function design(label, code, names, oneHot) { // code[state] = bits; one-hot = OR of the arcs entering each state
  const k = code.A.length, n = k + 1, dec = {}; S.forEach(s => (dec[code[s]] = s));
  const row = m => T[dec[(m >> 1).toString(2).padStart(k, "0")]][m & 1];
  const arcs = want => S.flatMap(s => [0, 1].filter(x => want(T[s][x])).map(x => code[s].replace(/0/g, "-") + x));
  const eqs = [...Array(k).keys()].map(i => oneHot ? arcs(([nx]) => code[nx][i] === "1") : minSOP(n, m => +code[row(m)[0]][i]));
  const zq = oneHot ? arcs(([, z]) => z === 1) : minSOP(n, m => row(m)[1]);
  const sop = e => e.map(c => [...c].map((ch, i) => ch === "-" ? "" : names[i] + (ch === "0" ? "'" : "")).join("")).join(" + ") || "0";
  const total = [...eqs, zq].flat(); console.log(`${label}: ${k} flip-flops, ${total.length} product terms, ${total.reduce((a, c) => a + lits(c), 0)} literals`);
  eqs.forEach((e, i) => console.log(`  D${names[i]} = ${sop(e)}`)); console.log(`  z = ${sop(zq)}`);
  let s = "A", q = code.A, ok = 0, x = 1, seen = new Set();   // verify: equations vs table, 256 clocks
  for (let t = 0; t < 256; t++, x = (x * 13 + 7) % 32) {
    const b = x >> 4, m = parseInt(q + b, 2), z = +zq.some(c => has(c, m, n));
    const nq = eqs.map(e => +e.some(c => has(c, m, n))).join("");
    if (z === T[s][b][1] && nq === code[T[s][b][0]]) ok++;
    seen.add(s + b); s = T[s][b][0]; q = nq;
  }
  console.log(`  check: ${ok}/256 cycles match the table, ${seen.size}/8 transitions exercised`);
}
design("binary  A=00 B=01 C=10 D=11", { A: "00", B: "01", C: "10", D: "11" }, ["Q1", "Q0", "x"]);
design("gray    A=00 B=01 C=11 D=10", { A: "00", B: "01", C: "11", D: "10" }, ["Q1", "Q0", "x"]);
design("one-hot A=1000 B=0100 C=0010 D=0001", { A: "1000", B: "0100", C: "0010", D: "0001" }, ["QA", "QB", "QC", "QD", "x"], true);

আউটপুট:

binary  A=00 B=01 C=10 D=11: 2 flip-flops, 4 product terms, 9 literals
  DQ1 = Q0x' + Q1Q0'x
  DQ0 = x
  z = Q1Q0x
  check: 256/256 cycles match the table, 8/8 transitions exercised
gray    A=00 B=01 C=11 D=10: 2 flip-flops, 7 product terms, 18 literals
  DQ1 = Q1Q0'x' + Q1'Q0x' + Q1Q0x
  DQ0 = Q0'x + Q1Q0' + Q1'Q0
  z = Q1Q0'x
  check: 256/256 cycles match the table, 8/8 transitions exercised
one-hot A=1000 B=0100 C=0010 D=0001: 4 flip-flops, 9 product terms, 18 literals
  DQA = QAx' + QCx'
  DQB = QAx + QBx + QDx
  DQC = QBx' + QDx'
  DQD = QCx
  z = QDx
  check: 256/256 cycles match the table, 8/8 transitions exercised

Binary-এ প্রোগ্রামের ফল হাতে করা K-map-এর সাথে মেলে: DQ1 = Q0x' + Q1Q0'x, DQ0 = x, z = Q1Q0x — ২টি flip-flop, ৯টি literal. Gray (A = 00, B = 01, C = 11, D = 10)-এ literal দ্বিগুণ, ১৮টি — কারণ এই detector ক্রমানুসারে চলে না, পেছনে লাফায় (C → A, D → B), তাই Gray-এর “এক বিট বদল” সুবিধা এখানে কাজে লাগে না। One-hot-এ ৪টি flip-flop আর ১৮টি literal, কিন্তু প্রতিটি term মাত্র দুই literal-এর — প্রতিটি সমীকরণ অগভীর, আর বড় machine-এ (ধরুন ২০টি state) binary-র সমীকরণ যেখানে ৫টি state-বিট আর input মিলিয়ে বড় হয়ে যায়, one-hot-এর প্রতিটি সমীকরণ তখনো শুধু আগত তীরের সংখ্যার সমান ছোট থাকে। তিন ক্ষেত্রেই 256/256 cycles match the table, 8/8 transitions exercised: সমীকরণ থেকে বানানো circuit প্রতি cycle-এ টেবিলের মতোই আচরণ করেছে, আর আটটি তীরের প্রতিটি অন্তত একবার চলেছে। শেষ সংখ্যাটি গুরুত্বপূর্ণ: এই প্রোগ্রামের প্রথম খসড়ায় একটি ছোট-চক্রের ছদ্ম-এলোমেলো input ব্যবহার করা হয়েছিল, যাতে 1010 কখনো আসত না — তখন D --0--> C তীরটি একবারও চলেনি (৭/৮), অথচ “256/256 match” ঠিকই দেখাত। এজন্যই অংশ ৮-এ coverage মাপার কথা আসবে।

একটি JK flip-flop উদাহরণ

পরীক্ষায় অনেক সময় JK বা T flip-flop দিয়ে নকশা চাওয়া হয়। তখন এক ধাপ বাড়ে: প্রতিটি সারিতে “Q থেকে Q+-এ যেতে J আর K-তে কী দিতে হবে” — এটি আসে excitation table থেকে (পর্ব ১৫-এ বিস্তারিত)। JK flip-flop-এর excitation: 0 → 0: J = 0, K = X; 0 → 1: J = 1, K = X; 1 → 0: J = X, K = 1; 1 → 1: J = X, K = 0. অনেক X (don't care) থাকায় K-map-এ দল বড় হয়। একই binary detector-এ:

Q1 Q0 xQ1+ Q0+J1 K1J0 K0
0 0 00 00 X0 X
0 0 10 10 X1 X
0 1 01 01 XX 1
0 1 10 10 XX 0
1 0 00 0X 10 X
1 0 11 1X 01 X
1 1 01 0X 0X 1
1 1 10 1X 1X 0

K-map থেকে (X-কে দরকারমতো 1 ধরে): J1 = Q0x′, K1 = Q0′x′ + Q0x (অর্থাৎ Q0 ⊙ x, XNOR), J0 = x, K0 = x′. যাচাই: JK-র সূত্র Q+ = JQ′ + K′Q-তে বসালে Q0+ = xQ0′ + xQ0 = x — D-নকশার D0 = x-এর সাথে মেলে। (এই সমীকরণগুলো একটি আলাদা scratch script-এ brute-force minimiser দিয়েও মিলিয়ে নেওয়া হয়েছে।)

Moore সংস্করণের হিসাব: ৫-state Moore detector-এ binary-তে ৩টি flip-flop লাগে (S0 = 000 … S4 = 100), আর 101, 110, 111 অব্যবহৃত — এগুলোকে don't care ধরলে D2 = Q1Q0x, D1 = Q0x′ + Q2x′ + Q1Q0′x, D0 = Q0′x + Q1′x, আর z = Q2 — output-এ কোনো gate-ই লাগে না, সরাসরি একটি flip-flop. Mealy-র চেয়ে একটি flip-flop বেশি, কিন্তু output পরিষ্কার। (একই scratch script-এ যাচাই করা।)

৭ · আরও দুটি উদাহরণ, অব্যবহৃত state আর reset

(ক) Serial even parity — একটি T flip-flop

একটি তারে বিট আসছে; এখন পর্যন্ত আসা 1-এর সংখ্যা জোড় হলে z = 1 (Moore). দুটি state যথেষ্ট — EVEN (z = 1) আর ODD (z = 0); 1 এলে state উল্টায়, 0 এলে থাকে। Q = 0 মানে EVEN ধরলে: D-তে D = Q ⊕ x, আর T flip-flop-এ আরও সহজ — T = x (1 এলে toggle), z = Q′. Network-এর parity বিট এভাবেই হিসাব হয় (Computer Networks কোর্সের error detection পর্ব)।

(খ) ৩ দিয়ে বিভাজ্য কি না — serial বিটে

একটি binary সংখ্যা MSB আগে করে একটি একটি বিট আসছে। প্রতি মুহূর্তে বলতে হবে, এখন পর্যন্ত আসা সংখ্যাটি ৩ দিয়ে বিভাজ্য কি না। পুরো সংখ্যা মনে রাখার দরকার নেই — শুধু ৩ দিয়ে ভাগশেষ r. যুক্তি: এখন পর্যন্ত সংখ্যা N হলে নতুন বিট x আসার পর সংখ্যা 2N + x; তাই নতুন ভাগশেষ r+ = (2r + x) mod 3, যা শুধু r আর x-এর ওপর নির্ভর করে। ৩টি state: R0, R1, R2; z = 1 শুধু R0-তে (Moore).

State (কোড Q1Q0)x = 0 (2r)x = 1 (2r + 1)z
R0 (00)R0R11
R1 (01)R2R00
R2 (10)R1R20
অব্যবহৃত (11)XXX

উদাহরণ: 110110 (= ৫৪)। ভাগশেষ ক্রমে 1, 0, 0, 1, 0, 0 (১, ৩, ৬, ১৩, ২৭, ৫৪-এর ভাগশেষ) — শেষে R0, অর্থাৎ ৫৪ ৩ দিয়ে বিভাজ্য। কোড 11-কে don't care ধরে K-map থেকে: D1 = Q0x′ + Q1x, D0 = Q1x′ + Q1′Q0′x, z = Q1′Q0′ — মোট ৯টি literal.

অব্যবহৃত state — চুপচাপ ফাঁদ

৩টি state-এর জন্য ২টি flip-flop, তাই কোড 11 কোনো state পায়নি — এটি unused state. স্বাভাবিক চলায় সেখানে যাওয়া যায় না, কিন্তু চালু হওয়ার মুহূর্তে flip-flop-এর মান এলোমেলো থাকতে পারে, বা বিদ্যুতের ঝাঁকুনি, তড়িৎ-চৌম্বক শব্দ বা মহাজাগতিক কণার আঘাতে একটি বিট উল্টে যেতে পারে। তখন প্রশ্ন: 11 থেকে machine কোথায় যায়? ওপরের সমীকরণে বসিয়ে দেখুন: x = 0 হলে D1 = 1·1 = 1, D0 = 1·1 = 1 — আবার 11! আর z = 0. অর্থাৎ যতক্ষণ 0 আসতে থাকে, machine 11-এ আটকে থাকে, ভুল output দেয় — একে বলে lock-up. x = 1 এলে 10 (R2)-তে বেরিয়ে আসে, কিন্তু ততক্ষণে হিসাব নষ্ট।

সমাধান তিনটি, খরচ অনুযায়ী:

  • স্পষ্ট নিয়ম দেওয়া: don't care না ধরে লিখুন 11 → R0 (দুই input-এই)। নতুন সমীকরণ D1 = Q1′Q0x′ + Q1Q0′x, D0 = Q1Q0′x′ + Q1′Q0′x — ১২টি literal (আগে ৯)। খরচ সামান্য বাড়ল, বদলে machine self-correcting: যেকোনো অবস্থা থেকে এক cycle-এ বৈধ state-এ ফেরে।
  • অন্তত যাচাই করা: don't care রেখে সমীকরণ বের করার পর প্রতিটি অব্যবহৃত কোড বসিয়ে দেখুন — কয়েক cycle-এ বৈধ state-এ ফিরলে যথেষ্ট কি না, নকশার প্রয়োজন অনুযায়ী ঠিক করুন। (অংশ ৬-এর ৫-state Moore detector-এ 101, 110, 111 সবই এক cycle-এ বৈধ state-এ যায়।)
  • Reset: চালু হওয়ার সময় একটি reset সংকেত সব flip-flop-কে শুরুর state-এ বসায়। এটি প্রায় প্রতিটি নকশায় লাগে — কিন্তু চলার মাঝে বিট উল্টালে reset সাহায্য করে না, তাই নিরাপত্তা-গুরুত্বপূর্ণ নকশায় প্রথম পথটিও লাগে।

Synchronous বনাম asynchronous reset

Synchronous reset

Reset শুধু clock-এর ধারে কাজ করে: always @(posedge clk) if (rst) state <= A; — reset আসলে D-পথে একটি mux. সুবিধা: সবকিছু একই clock-এর ছন্দে, timing হিসাব সহজ। অসুবিধা: clock না চললে reset হয় না, আর reset pulse অন্তত একটি ধার পর্যন্ত টিকতে হয়। একে বলে synchronous reset.

Asynchronous reset

Reset এলেই সঙ্গে সঙ্গে: always @(posedge clk or negedge rst_n) — flip-flop-এর বিশেষ clear pin ব্যবহার হয়। সুবিধা: clock ছাড়াই কাজ করে, চালু হওয়ার সময় নিরাপদ। ঝুঁকি: reset ছাড়ার মুহূর্ত clock ধারের খুব কাছে পড়লে কিছু flip-flop এই ধারে, কিছু পরের ধারে ছাড়া পায় — state ভেঙে যেতে পারে। একে বলে asynchronous reset.

শিল্পে প্রচলিত সমাধান দুটির মিশ্রণ: reset ধরা হয় asynchronously, ছাড়া হয় synchronously — দুই flip-flop-এর একটি ছোট “reset synchronizer” দিয়ে। কোনটি ভালো, তা নিয়ে কোম্পানি আর FPGA-নির্মাতাদের পরামর্শ ভিন্ন; নকশার নিয়মপুস্তক মেনে চলাই নিয়ম। কেন ধারের কাছে বদলানো সংকেত বিপজ্জনক (setup-hold আর metastability), তা পর্ব ১৮-এ; reset ছাড়ার ক্ষেত্রে একই ধরনের সময়সীমার নাম recovery আর removal time.

৮ · Verilog-এ FSM — তিন block-এর রীতি আর পরীক্ষা

পর্ব ১৪-এ দেখেছেন, combinational block-এ কোনো পথে output মান না পেলে latch তৈরি হয়। FSM লেখার প্রচলিত রীতি এই ফাঁদ এড়ায় নকশাটিকে ছবি ১৭.২-এর তিন টুকরোয় আলাদা রেখে: একটি clock-চালিত block (শুধু state register), একটি combinational block (next-state logic) আর output-এর জন্য আরেকটি (বা একটি assign). State-এর নাম দেওয়া হয় localparam দিয়ে:

module det1011 (
    input  wire clk,
    input  wire rst_n,          // active-low asynchronous reset
    input  wire x,              // one serial bit per clock
    output reg  z
);
    localparam [1:0] A = 2'd0,  // nothing useful seen
                     B = 2'd1,  // "1"
                     C = 2'd2,  // "10"
                     D = 2'd3;  // "101"
    reg [1:0] state, next;

    // (1) state register: the only flip-flops in the design
    always @(posedge clk or negedge rst_n)
        if (!rst_n) state <= A;
        else        state <= next;

    // (2) next-state logic: combinational, blocking "="
    always @(*) begin
        next = state;                   // default first: every path assigns next, so no latch
        case (state)
            A: if (x)  next = B;
            B: if (!x) next = C;
            C: next = x ? D : A;
            D: next = x ? B : C;        // overlapping: "1011" ends in "1" -> B
            default: next = A;          // unreachable here (all 4 codes used) - safe habit
        endcase
    end

    // (3) output logic: Mealy = state AND input
    always @(*) begin
        z = 1'b0;
        if (state == D && x) z = 1'b1;
    end
endmodule

কয়েকটি নিয়ম, যা এই ছোট module-এ লুকিয়ে আছে:

  • next = state; শুরুতেই: যে শাখায় next লেখা হয়নি (যেমন A-তে x = 0), সেখানে “একই state-এ থাকা” — latch নয়, কারণ register তো আছেই। এই এক লাইন বাদ দিলে A আর B শাখায় next কোনো মান পায় না, আর synthesis একটি latch বসায়।
  • Register block-এ <=, combinational block-এ = (non-blocking বনাম blocking) — পর্ব ১৪-এর নিয়ম।
  • Moore হলে output block শুধু state পড়বে: ৫-state নকশায় assign z = (state == S4);.
  • Synchronous reset চাইলে sensitivity list থেকে negedge rst_n সরিয়ে দিন — বাকি সব একই।

SystemVerilog-এ আরও পরিষ্কার: typedef enum logic [1:0] {A, B, C, D} state_t; দিয়ে state-এর নিজস্ব type (enum), আর always_ff / always_comb, যাতে tool নিজে মিলিয়ে দেখে block-টি সত্যিই flip-flop বা combinational. Simulator-এর waveform-এ তখন 2'd3-এর বদলে নাম “D” দেখায়। দুই-block রীতিও প্রচলিত — next-state আর output একই combinational block-এ — তবে output-কে register-এ রাখতে চাইলে (registered output) সেটি clock-চালিত block-এ যায়।

FSM পরীক্ষা — state আর transition coverage

একটি testbench যত cycle-ই চালাক, যদি কোনো তীর একবারও না চলে, সেই তীরের ভুল ধরা পড়বে না — অংশ ৬-এর প্রোগ্রামের প্রথম খসড়ার অভিজ্ঞতাই এর প্রমাণ। তাই FSM-এর পরীক্ষায় দুটি সংখ্যা মাপা হয়:

  • State coverage: মোট state-এর কয়টিতে অন্তত একবার পৌঁছানো গেছে। দুর্বল মাপ — “1011” detector-এর চারটি state ছোঁয়া যায় এমন input-এও D --0--> C তীর বাদ পড়তে পারে।
  • Transition coverage: state × input-এর কয়টি তীর চলেছে — এখানে ৮টির ৮টি চাই। আরও কড়া মাপ হলো তীরের জোড়া বা ক্রম (যেমন “মিলের ঠিক পরে আবার মিল” — overlapping পরীক্ষা)।

এর সাথে থাকে reset-এর পরের state, প্রতিটি অব্যবহৃত কোড থেকে কী হয়, আর একটি “সোনালি মডেল” (যেমন অংশ ৪-এর JS simulator) — RTL-এর output প্রতি cycle-এ মডেলের সাথে মেলানো। শিল্পে SystemVerilog-এর coverage tool এই গোনা স্বয়ংক্রিয়ভাবে করে, আর formal tool গাণিতিকভাবে প্রমাণ করতে পারে যে কোনো state থেকে ফেরার পথ আছে।

৯ · FSM সবখানে — protocol থেকে CPU, cache আর regex

একবার FSM চিনলে চারপাশে সবখানে দেখবেন। Hardware-এ:

  • Protocol controller: একটি UART receiver-এর state সাধারণত IDLE (তার উঁচু) → START (নিচু হলো — start বিট কি না, মাঝখানে আবার দেখা) → DATA (৮টি বিট, প্রতিটির মাঝখানে নমুনা; সময় মাপতে প্রায়ই baud rate-এর ১৬ গুণ গতির একটি counter) → STOP (তার উঁচু কি না; না হলে framing error). USB-এর specification-এ একটি device-এর অবস্থাগুলো (যেমন Default, Address, Configured, Suspended) state machine হিসেবেই বর্ণিত, আর TCP সংযোগের LISTEN, SYN-SENT, ESTABLISHED-এর মতো অবস্থাও একটি বিখ্যাত state diagram (Computer Networks কোর্সের TCP সংযোগ পর্ব)।
  • CPU-র control unit: একটি multi-cycle প্রসেসরে প্রতিটি instruction কয়েকটি ধাপে চলে — fetch, decode, execute, memory, write-back — আর কোন ধাপের পর কোন ধাপ, তা ঠিক করে একটি FSM; প্রতিটি state-এ কোন control সংকেত চালু থাকবে, তা Moore-ধাঁচের output. এই নকশা পর্ব ৩৩ (Control unit) আর পর্ব ৩৪ (Multi-cycle datapath আর microprogrammed control)-এ। Counter-ও আসলে একটি সরল FSM — যার input নেই, বা বড়জোর একটি enable; পর্ব ১৬-এ।
  • Cache controller: প্রতিটি cache line-এর অবস্থা (Modified, Exclusive, Shared, Invalid) আর অন্য core-এর অনুরোধে তার বদল — MESI protocol — একটি FSM; পর্ব ৫৩-এ।
  • Regex engine: তত্ত্বে output-হীন FSM-কে বলে DFA: কিছু state “গ্রহণযোগ্য”, শেষে সেখানে থাকলে লেখাটি নকশার সাথে মেলে। প্রতিটি regular expression-এর সমান একটি DFA আছে, আর “1011” detector আসলে regex (0|1)*1011-এর DFA. Programming-এ regex ব্যবহার দেখতে পারেন Python কোর্সের regex পর্বে।

Software-এও FSM একটি প্রিয় নকশা-পদ্ধতি: firmware, game-এর চরিত্র, UI-এর পর্দা বদল, network parser. সবচেয়ে পরিষ্কার রূপ টেবিল-চালিত — state × event-এর একটি টেবিল, আর একটি ছোট loop. অংশ ১-এর PIN-লকের নকশা C-তে:

#include <stdio.h>
/* PIN entry that locks after 3 wrong tries, written as a table-driven FSM (Moore style). */
typedef enum { WRONG0, WRONG1, WRONG2, UNLOCKED, LOCKED, NSTATES } State;
typedef enum { OK, BAD, LOGOUT, RESET, NEVENTS } Event;
static const char *sname[NSTATES] = { "WRONG0", "WRONG1", "WRONG2", "UNLOCKED", "LOCKED" };
static const char *ename[NEVENTS] = { "correct PIN", "wrong PIN", "logout", "admin reset" };
static const char *say[NSTATES]   = { "enter PIN (3 tries left)", "enter PIN (2 tries left)",
                                      "enter PIN (1 try left)", "welcome", "account locked" };
static const State next[NSTATES][NEVENTS] = {
    /*             OK        BAD       LOGOUT    RESET  */
    /* WRONG0 */ { UNLOCKED, WRONG1,   WRONG0,   WRONG0 },
    /* WRONG1 */ { UNLOCKED, WRONG2,   WRONG1,   WRONG0 },
    /* WRONG2 */ { UNLOCKED, LOCKED,   WRONG2,   WRONG0 },
    /* UNLOCK */ { UNLOCKED, UNLOCKED, WRONG0,   WRONG0 },
    /* LOCKED */ { LOCKED,   LOCKED,   LOCKED,   WRONG0 },
};
static State step(State s, Event e) {
    if ((unsigned)s >= (unsigned)NSTATES || (unsigned)e >= (unsigned)NEVENTS)
        return LOCKED;                      /* corrupted value: fall into the safe state */
    return next[s][e];
}
int main(void) {
    const Event input[] = { BAD, OK, LOGOUT, BAD, BAD, BAD, OK, RESET, OK };
    State s = WRONG0;                       /* reset state */
    printf("start    %-8s : %s\n", sname[s], say[s]);
    for (unsigned i = 0; i < sizeof input / sizeof input[0]; i++) {
        State n = step(s, input[i]);
        printf("%-11s %-8s -> %-8s : %s\n", ename[input[i]], sname[s], sname[n], say[n]);
        s = n;
    }
    printf("unknown state 7 -> %s\n", sname[step((State)7, OK)]);
    return 0;
}

আউটপুট:

start    WRONG0   : enter PIN (3 tries left)
wrong PIN   WRONG0   -> WRONG1   : enter PIN (2 tries left)
correct PIN WRONG1   -> UNLOCKED : welcome
logout      UNLOCKED -> WRONG0   : enter PIN (3 tries left)
wrong PIN   WRONG0   -> WRONG1   : enter PIN (2 tries left)
wrong PIN   WRONG1   -> WRONG2   : enter PIN (1 try left)
wrong PIN   WRONG2   -> LOCKED   : account locked
correct PIN LOCKED   -> LOCKED   : account locked
admin reset LOCKED   -> WRONG0   : enter PIN (3 tries left)
correct PIN WRONG0   -> UNLOCKED : welcome
unknown state 7 -> LOCKED

প্রথম ভুলে WRONG1 (“2 tries left”), তারপর সঠিক PIN-এ UNLOCKED. Logout-এর পর WRONG0 — ভুলের গোনা আবার শূন্য। তারপর পরপর তিনটি ভুল: WRONG1 → WRONG2 → LOCKED. লক্ষ করুন পরের লাইন: LOCKED অবস্থায় সঠিক PIN দিলেও LOCKED -> LOCKED — টেবিলে LOCKED সারির OK ঘরে LOCKED লেখা, তাই কোনো if-এর ফাঁক দিয়ে ঢোকার সুযোগ নেই। শুধু admin reset-এ WRONG0, তারপর সঠিক PIN-এ আবার UNLOCKED. শেষ লাইনটি অংশ ৭-এর অব্যবহৃত state-এর software সংস্করণ: কোনো কারণে state variable-এ অবৈধ মান 7 এলে step() সোজা নিরাপদ state LOCKED-এ পাঠায় — hardware-এর default: শাখার মতো। টেবিল-চালিত নকশার আরেকটি সুবিধা: পুরো আচরণ এক নজরে দেখা আর পরীক্ষা করা যায় — ৫ × ৪ = ২০টি ঘর, ২০টি transition.

আরও গভীরে: বড় নকশায় একটি বিশাল FSM না বানিয়ে কয়েকটি ছোট FSM একে অন্যকে সংকেত দেয় (communicating FSMs), আর ডেটা রাখা হয় আলাদা datapath-এ — এই জোড়াকে বলে FSMD (FSM + datapath), যা পর্ব ৩২–৩৪-এর প্রসেসর নকশার কাঠামো। মহাকাশ বা চিকিৎসা-যন্ত্রের মতো জায়গায় বিকিরণে বিট উল্টানোর ঝুঁকি বেশি, তাই সেখানে state-কে Hamming কোডে রাখা, তিন কপি রেখে ভোট নেওয়া (triple modular redundancy) বা synthesis tool-এর “safe FSM” বিকল্প ব্যবহারের কথা শোনা যায়। গবেষণায় FSM-এর state assignment আর decomposition বহু দশকের বিষয়, আর formal verification tool এখন নিয়মিতভাবে FSM-এর deadlock বা পৌঁছানো-যায়-না-এমন state খোঁজে।

পরীক্ষা ও ইন্টারভিউতে — কয়েকটি প্রচলিত ধরনের প্রশ্ন আর এক লাইনের উত্তর:

  • Moore আর Mealy-র পার্থক্য কী? কোনটিতে state কম লাগে? Moore-এর output শুধু state থেকে (এক cycle পরে, স্থির); Mealy-র state + input থেকে (একই cycle-এ) — Mealy-তে state সমান বা কম।
  • “1011” overlapping detector-এ কয়টি state আর flip-flop? Mealy: ৪টি state, ২টি flip-flop; Moore: ৫টি state, ৩টি flip-flop.
  • ২০টি state-এর FSM-এ binary আর one-hot-এ কয়টি flip-flop? ⌈log2 ২০⌉ = ৫ বনাম ২০.
  • দুটি state কখন equivalent? যেকোনো input-ধারায় দুটি থেকে একই output-ধারা আসলে; output-এ ভাগ করে তারপর পরের state-এর দল দিয়ে বারবার ভাগ করে (partition) বের হয়।
  • Verilog FSM-এ latch কেন আসে, কীভাবে এড়াবেন? Next-state-এর combinational block-এ কোনো শাখায় next মান না পেলে; শুরুতে next = state; আর case-এ default.

১০ · AI-এর যুগে — state diagram AI দিয়ে, যাচাই simulation দিয়ে

“1011 detector-এর Verilog লিখে দিন” বললে AI কয়েক সেকেন্ডে উত্তর দেয়, আর দেখতে প্রায়ই নিখুঁত। কিন্তু FSM-এর ভুল সূক্ষ্ম — একটি ভুল তীর শুধু বিশেষ input-ক্রমেই ধরা পড়ে। এই বিষয়ে AI-এর প্রচলিত ভুল:

  • ভুল তীর: B-তে 1 এলে A-তে ফেরানো, D-তে 0 এলে A-তে ফেরানো (C হওয়ার কথা) — overlapping আর non-overlapping গুলিয়ে ফেলা।
  • Moore আর Mealy মিশিয়ে ফেলা: “Moore” বলে output-এ input ঢুকিয়ে দেওয়া, বা Moore-এর এক cycle দেরি ভুলে testbench-এ ভুল cycle-এ output খোঁজা।
  • K-map আর minimisation-এ ভুল: ভুল দল, অব্যবহৃত কোডকে don't care ধরে lock-up তৈরি করা, বা equivalent নয় এমন state একত্র করা।
  • Non-synthesizable বা latch-ওয়ালা Verilog: default ছাড়া combinational block, একই block-এ = আর <= মেশানো, নকশার ভেতরে initial দিয়ে state বসানো।
  • বানানো তথ্য: কোনো chip বা protocol-এর state-এর নাম ও সংখ্যা, বা কোনো tool-এর encoding option ভুল বলা।

AI-কে নকশাকার নয়, সহকারী হিসেবে ব্যবহার করুন — সাথে প্রতিটি state-এর অর্থ আর পরীক্ষা চেয়ে নিন:

আমি digital logic শিখছি। নিচের সমস্যার জন্য একটি FSM নকশা করো, এই শর্তে: ১. প্রথমে বলো Moore না Mealy, আর overlapping না non-overlapping — কেন। ২. প্রতিটি state-এর অর্থ এক লাইনে লেখো (যেমন "C = শেষ দুই বিট 10"), তারপর পূর্ণ state table দাও — প্রতিটি state × প্রতিটি input-এর ঘর। ৩. binary encoding-এ D flip-flop-এর next-state আর output সমীকরণ দাও, K-map-এর দলগুলো উল্লেখ করে; অব্যবহৃত কোড থেকে machine কোথায় যায় তাও বলো। ৪. synthesizable Verilog-2001 দাও: state register, next-state আর output আলাদা block; শুরুতে next = state; case-এ default; asynchronous active-low reset. ৫. একটি testbench দাও যা প্রতিটি transition অন্তত একবার চালায় আর overlapping মিল পরীক্ষা করে; প্রত্যাশিত output-এর cycle নম্বর লিখে দাও। সমস্যা: [এখানে আপনার সমস্যা লিখুন]

AI-এর দেওয়া FSM যাচাইয়ের চেকলিস্ট

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

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

প্র ০১Mealy আর Moore — একই সময়ে দুটি মডেল কেন জন্মাল, আর আজও দুটিই কেন টিকে আছে?

১৯৫০-এর দশকের শুরুতে টেলিফোন এক্সচেঞ্জ আর প্রথম দিকের কম্পিউটারে relay আর vacuum tube দিয়ে বানানো sequential circuit-এর নকশা ছিল অনেকটাই শিল্পকর্ম — অভিজ্ঞ প্রকৌশলীর অনুমাননির্ভর। এটিকে একটি পদ্ধতিতে আনার চেষ্টা থেকেই তত্ত্বের জন্ম। ১৯৫৪ সালে David Huffman (যাঁর নাম Huffman coding-এর জন্যও পরিচিত) sequential switching circuit-এর নকশা নিয়ে একটি প্রভাবশালী প্রবন্ধ প্রকাশ করেন, যেখানে state table আর state কমানোর ধারণা গুরুত্ব পায়। ১৯৫৫ সালে Bell Labs-এর George H. Mealy Bell System Technical Journal-এ “A Method for Synthesizing Sequential Circuits” প্রকাশ করেন — সেখানে output transition-এর সাথে যুক্ত, যা relay circuit-এর বাস্তবতার কাছাকাছি, কারণ relay-এর output সরাসরি input-এর পরিবর্তনে সাড়া দিত।

১৯৫৬ সালে Edward F. Moore-এর “Gedanken-experiments on Sequential Machines” প্রকাশিত হয় Automata Studies নামের সংকলনে। তাঁর প্রশ্ন ছিল আরও দার্শনিক: একটি বন্ধ বাক্স, ভেতরে অজানা machine; বাইরে থেকে input দিয়ে output দেখে আমরা ভেতরের state সম্পর্কে কী জানতে পারি? এখান থেকেই “দুটি state বাইরে থেকে আলাদা করা যায় কি না” — equivalence আর minimisation-এর ধারণা স্পষ্ট রূপ পায়। Moore-এর মডেলে output state-এর গায়ে, যা গাণিতিকভাবে পরিষ্কার।

দুটি মডেল সমান শক্তিশালী — অংশ ৪-এর রূপান্তর দেখায়, একটিকে অন্যটিতে বদলানো যায়, শুধু এক cycle-এর দেরি আর state-সংখ্যার পার্থক্য। তবু দুটিই টিকে আছে, কারণ দুটি আলাদা প্রকৌশল-চাহিদা মেটায়। Mealy কম state আর তাৎক্ষণিক সাড়া দেয় — handshake protocol-এ “অনুরোধ এলেই একই cycle-এ ack” দরকার হলে কাজের। Moore স্থির, glitch-মুক্ত output দেয়, আর কয়েকটি FSM জোড়া লাগালে combinational loop তৈরি হয় না — বড় নকশায় timing নিশ্চিত করা সহজ। আধুনিক RTL নকশায় তাই প্রায়ই মিশ্র রূপ দেখা যায়: কিছু output Moore, কিছু Mealy, আর গুরুত্বপূর্ণ output-গুলো register-এ ধরে রাখা।

মূল উপলব্ধি: মডেলের পছন্দ গণিতের নয়, প্রকৌশলের প্রশ্ন — সাড়ার গতি, state-এর খরচ আর output-এর স্থিরতার মধ্যে দর-কষাকষি।

প্র ০২পূর্ণভাবে নির্দিষ্ট FSM-এর state কমানো সহজ, কিন্তু don't care থাকলে কেন হঠাৎ কঠিন হয়ে যায়?

এই পর্বের partition refinement কাজ করে কারণ “equivalence” একটি সত্যিকারের equivalence relation — p ≡ q আর q ≡ r হলে p ≡ r. তাই state-গুলোকে পরিষ্কার, পরস্পর-বিচ্ছিন্ন দলে ভাগ করা যায়, আর ভাগ শুধু সূক্ষ্ম হতে থাকে। প্রতিটি ধাপ বহুপদী (polynomial) সময়ের, ধাপ সর্বোচ্চ n − ১টি। ১৯৭১ সালে John Hopcroft এমন একটি চতুর algorithm দেন যা কাজটি প্রায় n log n সময়ে করে — আজও DFA minimisation-এর মানক পদ্ধতি। তত্ত্বের দিক থেকে Myhill–Nerode উপপাদ্য বলে, প্রতিটি regular language-এর জন্য একটি অনন্য (নামবদল ছাড়া) ন্যূনতম DFA আছে — অর্থাৎ উত্তর একটাই।

এখন ধরুন কিছু ঘর don't care — কোনো state-এ কোনো input কখনো আসে না, বা এলে output-এ কিছু যায় আসে না। একে বলে incompletely specified machine. তখন “equivalent”-এর বদলে আসে “compatible”: p আর q একসাথে রাখা যায়, যদি যেখানে দুজনেরই মান নির্দিষ্ট সেখানে মেলে। সমস্যা হলো compatibility transitive নয়: p-q compatible, q-r compatible, কিন্তু p-r নয় — কারণ q-এর don't care দুই দিকে দুইভাবে ব্যবহার হয়েছে। ফলে দলগুলো আর বিচ্ছিন্ন নয়, একে অন্যের ওপর পড়ে, আর “কোন দলগুলো বেছে নিলে সব state ঢাকা পড়ে, আর বেছে নেওয়া দলগুলোর পরের state-ও কোনো বেছে নেওয়া দলে থাকে” — এটি একটি জটিল আবরণ-সমস্যা। ১৯৫৯ সালে Paull আর Unger এই সমস্যার পদ্ধতিগত সমাধান (maximal compatible খুঁজে বাছাই) দেন, আর পরে দেখানো হয় যে সাধারণভাবে এটি NP-hard — বড় machine-এ সবচেয়ে ভালো উত্তর নিশ্চিতভাবে দ্রুত পাওয়ার কোনো পরিচিত উপায় নেই।

এটি পর্ব ১০-এর গল্পের পুনরাবৃত্তি: prime implicant বের করা সহজ, কিন্তু ন্যূনতম আবরণ বাছাই NP-hard; সেখানেও Espresso-র মতো heuristic tool এসেছিল। FSM synthesis tool-গুলোও তাই বাস্তবে heuristic আর সীমিত খোঁজ ব্যবহার করে, আর নকশাকারী নিজে বুঝে don't care দেন।

মূল উপলব্ধি: একটি ছোট সংজ্ঞাগত পার্থক্য — transitive হওয়া বা না হওয়া — একটি সমস্যাকে সহজ থেকে কঠিন শ্রেণিতে ঠেলে দিতে পারে; don't care স্বাধীনতা দেয়, কিন্তু খোঁজার জায়গাও বিশাল করে।

প্র ০৩Flip-flop কমানোই যদি লক্ষ্য হয়, তবু FPGA-তে one-hot কেন এত জনপ্রিয়? আর এর ঝুঁকি কোথায়?

Binary encoding শেখার সময় মনে হয় flip-flop কমানোই বুদ্ধিমানের কাজ। কিন্তু খরচের হিসাব নির্ভর করে hardware-এর গঠনের ওপর। ASIC-এ প্রতিটি flip-flop একটি standard cell, যা কয়েকটি NAND gate-এর সমান জায়গা নেয় আর clock-এ বিদ্যুৎ খরচ করে — সেখানে flip-flop কমানো সত্যিই লাভ। FPGA-তে ছবি উল্টো: প্রতিটি logic ব্লকে LUT-এর পাশে এক বা একাধিক flip-flop আগে থেকেই বসানো, ব্যবহার না করলে নষ্ট। সেখানে দামি জিনিস হলো LUT-এর ইনপুট আর logic-এর স্তর, কারণ প্রতিটি স্তর আর routing-এ delay যোগ হয়।

এই অবস্থায় one-hot-এর সুবিধা স্পষ্ট। প্রতিটি state-বিটের next-state সমীকরণ শুধু সেই state-এ আসা তীরের সংখ্যার সমান term — অংশ ৬-এর উদাহরণে সর্বোচ্চ ৩টি দুই-literal-এর term. এমন সমীকরণ প্রায়ই একটি LUT-এ ধরে, তাই এক স্তরের logic — দ্রুত clock. Binary-তে ২০টি state-এর machine-এ প্রতিটি next-state বিট ৫টি state-বিট আর input-এর জটিল function, যা কয়েক স্তরের LUT নেয়। এছাড়া one-hot-এ নতুন state যোগ করলে পুরোনো সমীকরণ প্রায় অপরিবর্তিত থাকে, আর waveform-এ কোন state সক্রিয় তা এক নজরে দেখা যায়। এজন্য প্রধান FPGA-নির্মাতাদের synthesis tool প্রায়ই FSM চিনে নিজে থেকে one-hot বা অন্য উপযুক্ত encoding বেছে নেয় — ঠিক কী করবে তা tool, সংস্করণ আর সেটিংসের ওপর নির্ভর করে।

ঝুঁকিটি অংশ ৭-এর অব্যবহৃত state-এর বড় সংস্করণ। n-বিট one-hot-এ বৈধ নকশা মাত্র nটি, অবৈধ ২n − nটি — যেমন দুটি বিট একসাথে 1, বা সব 0. “তীর গুনে” লেখা সমীকরণ ধরে নেয় ঠিক একটি বিট 1; একটি বিট উল্টে গেলে দুটি state একসাথে সক্রিয় হয়ে দুই দিকের output একসাথে চালু হতে পারে, বা সব 0 হয়ে machine চিরকাল থেমে যেতে পারে। তাই নিরাপত্তা-গুরুত্বপূর্ণ নকশায় অবৈধ নকশা ধরার logic, reset-এ ফেরা, বা tool-এর “safe” FSM বিকল্প ব্যবহার করা হয় — যা কিছু গতি আর জায়গা খরচ করে।

মূল উপলব্ধি: “সবচেয়ে ভালো encoding” বলে কিছু নেই — লক্ষ্য hardware-এর খরচের গঠন (flip-flop বনাম logic বনাম গতি) আর ভুলের ঝুঁকি মিলিয়ে বাছতে হয়।

প্র ০৪Regular expression, DFA আর “ধীর regex” — তত্ত্বের FSM কীভাবে প্রতিদিনের software-এর নিরাপত্তার প্রশ্ন হয়ে উঠল?

Regular expression-এর ধারণা এসেছে Stephen Kleene-এর ১৯৫০-এর দশকের কাজ থেকে, যেখানে তিনি স্নায়ুকোষের McCulloch–Pitts মডেল যে ধরনের “ঘটনা” চিনতে পারে, তা বর্ণনা করতে regular event-এর ভাষা দেন, আর দেখান এগুলো finite automaton দিয়ে চেনা যায়। ১৯৬৮ সালে Ken Thompson Communications of the ACM-এ একটি ছোট প্রবন্ধে দেখান কীভাবে একটি regex-কে সরাসরি machine code-এ রূপান্তর করে লেখার মধ্যে খোঁজা যায় — সব সম্ভাব্য state একসাথে অনুসরণ করে (NFA simulation). এই ধারণা পরে Unix-এর ed আর grep-এর মতো tool-এ আসে বলে জানা যায়।

তত্ত্ব বলে, যেকোনো regex-কে DFA-তে রূপান্তর করলে প্রতিটি অক্ষরে ঠিক একটি টেবিল-দেখা — লেখার দৈর্ঘ্যের সমানুপাতিক সময়, এই পর্বের “1011” detector-এর মতোই। সমস্যা হলো DFA-র state-সংখ্যা কখনো কখনো regex-এর দৈর্ঘ্যের তুলনায় সূচকীয়ভাবে বেড়ে যেতে পারে, তাই অনেক engine তৈরির সময় পুরো DFA বানায় না। আরও বড় কথা, অনেক জনপ্রিয় programming ভাষার regex engine backreference-এর মতো সুবিধা দিতে backtracking ব্যবহার করে — একটি পথ চেষ্টা, ব্যর্থ হলে ফিরে আরেকটি। কিছু নকশা, যেমন (a+)+b, মেলে না এমন লেখায় সূচকীয় সংখ্যক পথ চেষ্টা করে।

এখান থেকে একটি নিরাপত্তা-সমস্যা: কেউ ইচ্ছে করে এমন লেখা পাঠালে server-এর CPU আটকে যায় — একে বলে ReDoS (regular expression denial of service). প্রতিরক্ষার পথগুলো FSM তত্ত্ব থেকেই আসে: Google-এর RE2-এর মতো engine backreference বাদ দিয়ে automaton-ভিত্তিক পদ্ধতিতে রৈখিক সময়ের নিশ্চয়তা দেয়; অন্য engine-এ সময়সীমা বসানো, বিপজ্জনক নকশা এড়ানো, আর ব্যবহারকারীর দেওয়া regex গ্রহণ না করা। Network-এর intrusion detection-এ হাজারো নকশা একসাথে মেলাতে hardware বা FPGA-তে DFA-ভিত্তিক matcher-এর গবেষণাও হয়েছে।

মূল উপলব্ধি: FSM-এর state আর transition-এর সরল হিসাবই বলে দেয় কোন খোঁজ রৈখিক আর কোনটি বিস্ফোরক — তত্ত্ব জানা থাকলে নিরাপদ software লেখা সহজ হয়।

প্র ০৫একটি পুরো কম্পিউটারও কি একটি finite state machine? তাহলে CPU-কে একটি বিশাল FSM হিসেবে নকশা করা হয় না কেন?

কঠোর অর্থে হ্যাঁ। একটি কম্পিউটারের সব register, cache আর মেমরির বিট মিলিয়ে সসীমসংখ্যক বিট আছে; তাই সম্ভাব্য অবস্থার সংখ্যা সসীম — যদিও কল্পনাতীত বড়। ধরুন মাত্র ১ গিগাবাইট মেমরি: ২৩০ বাইট মানে প্রায় ৮৬০ কোটি বিট, আর অবস্থার সংখ্যা ২-এর সেই ঘাত — মহাবিশ্বের পরমাণুর আনুমানিক সংখ্যার চেয়েও বহু বহু গুণ বড়। তত্ত্বে তাই কম্পিউটারকে সাধারণত Turing machine দিয়ে ভাবা হয়, যার অসীম tape আছে, কারণ “মেমরি ফুরিয়ে গেলে আরেকটু যোগ করা যায়” — এই ধারণাই বাস্তবের কাছাকাছি।

নকশার দিক থেকে একটি বিশাল FSM অচল, কারণ state table লেখা, minimise করা বা যাচাই করা অসম্ভব। তাই প্রকৌশলীরা ভাগ করে কাজ করেন: যে তথ্য নিয়মিত আকারের (৩২-বিট সংখ্যা, মেমরির শব্দ), সেগুলো থাকে datapath-এ — register, ALU, multiplexer — যেখানে প্রতিটি বিট একই নিয়মে চলে, আলাদা state হিসেবে গোনার দরকার নেই। আর কখন কোন কাজ হবে, সেই ছোট সিদ্ধান্তগুলো নেয় একটি ছোট control FSM — পর্ব ৩৩–৩৪-এর control unit. Multi-cycle প্রসেসরের control unit-এ হয়তো দশ-বারোটি state, অথচ পুরো CPU-র অবস্থা অগণিত। এই “FSM + datapath” ভাগই আধুনিক digital নকশার মূল কাঠামো।

ইতিহাসেও এই ভাগের চিহ্ন আছে। ১৯৫১ সালে Maurice Wilkes প্রস্তাব করেন, control-এর FSM-কে gate দিয়ে না বানিয়ে একটি ছোট মেমরিতে “microprogram” হিসেবে রাখা যায় — প্রতিটি state একটি মেমরির শব্দ, আর পরের state-এর ঠিকানা সেই শব্দেই লেখা। IBM System/360 পরিবারের অনেক মডেলে এই microprogrammed control ব্যবহার হয়েছিল, আর আজও জটিল CISC instruction-এর জন্য x86 প্রসেসরে microcode আছে বলে জানা যায়। পর্ব ৩৪-এ এটি বিস্তারিত দেখবেন।

মূল উপলব্ধি: FSM শক্তিশালী ধারণা, কিন্তু বড় সিস্টেমে কাজে লাগে ছোট ছোট FSM হিসেবে — নিয়মিত ডেটা datapath-এ, আর সিদ্ধান্তের ছোট স্মৃতি control FSM-এ।

অনুশীলন

কাগজ-কলমে আগে নিজে করুন, তারপর পূর্ণ সমাধান মিলিয়ে নিন।

  1. Detector নকশা করুন: একটি Moore machine নকশা করুন, যা serial input x-এ 101 (overlapping) এলে z = 1 দেয়। (ক) state diagram ও state table, (খ) binary assignment-এ D flip-flop-এর সমীকরণ আর z, (গ) input 0101101-এ প্রতি cycle-এর z (শেষ input-এর পরের cycle-সহ)।

    (ক) S0 = কিছু না, S1 = “1”, S2 = “10”, S3 = “101” পূর্ণ (z = 1). Transition: S0: 0 → S0, 1 → S1 · S1: 0 → S2, 1 → S1 · S2: 0 → S0, 1 → S3 · S3: 0 → S2 (“1010”-এর শেষ “10”), 1 → S1 (“1011”-এর শেষ “1”). মাত্র ৪টি state, কারণ Moore-এ “পূর্ণ” state-টিই S3.

    (খ) S0 = 00, S1 = 01, S2 = 10, S3 = 11. Transition table থেকে D1 = Σm(2, 5, 6), D0 = Σm(1, 3, 5, 7). K-map: D1 = Q0x′ + Q1Q0′x, D0 = x, আর z = Q1Q0 (input নেই — Moore). মজার ব্যাপার: next-state সমীকরণ “1011” Mealy detector-এর হুবহু এক — কারণ দুই machine-এর state-এর অর্থ (কিছু না, 1, 10, 101) আর transition একই; শুধু output-এর নিয়ম আলাদা।

    (গ) State ক্রম: S0 →0→ S0 →1→ S1 →0→ S2 →1→ S3 →1→ S1 →0→ S2 →1→ S3. Cycle ০ থেকে ৭-এ z = 0 0 0 0 1 0 0 1 — “101” পূর্ণ হয় cycle ৩ আর ৬-এর input-এ, Moore-এর output আসে এক cycle পরে, cycle ৪ আর ৭-এ। (Scratch simulator-এ যাচাই করা।)

  2. State table ছোট করুন: নিচের Moore machine-এর state কমান (partition বা implication table — যেকোনো একটি), ছোট টেবিল লিখুন, আর বলুন machine-টি আসলে কী করে। শুরু A; প্রতিটি সারিতে x = 0-এ পরের state, x = 1-এ পরের state, আর z:
    Statex = 0x = 1z
    AAB1
    BCD0
    CEF0
    DAE1
    EFA0
    FBC0

    Partition: P0 (output দিয়ে) = {A, D} {B, C, E, F}. স্বাক্ষর (P0-এর দলে): A → (A, B) = (I, II), D → (A, E) = (I, II) — মেলে। B → (C, D) = (II, I), E → (F, A) = (II, I); C → (E, F) = (II, II), F → (B, C) = (II, II). তাই P1 = {A, D} {B, E} {C, F}. আবার: A (AD, BE), D (AD, BE); B (CF, AD), E (CF, AD); C (BE, CF), F (BE, CF) — কিছু ভাঙল না, থামুন।

    Implication table দিয়েও একই: output-এ X: AB, AC, AE, AF, BD, CD, DE, DF. বাকি ঘর: AD চায় BE; BC চায় CE, DF; BE চায় CF, AD; BF চায় BC, CD; CE চায় EF, AF; CF চায় BE; EF চায় BF, AC. পাস ১-এ X: BC (DF X), BF (CD X), CE (AF X), EF (AC X). পাস ২-এ নতুন কিছু নয়। টিকে থাকে AD, BE, CF.

    ছোট টেবিল: A: A, B, z = 1 · B: C, A, z = 0 · C: B, C, z = 0. এটি অংশ ৭-এর ৩ দিয়ে বিভাজ্যতার machine (A = R0, B = R1, C = R2) — MSB আগে আসা binary সংখ্যা ৩ দিয়ে বিভাজ্য হলে z = 1. যাচাই: মূল ৬-state machine-কে ০ থেকে ২৫৫ পর্যন্ত সব ৮-বিট সংখ্যায় চালিয়ে শেষ state-এর ভাগশেষ মেলানো হয়েছে — ২৫৬টিতেই ঠিক।

  3. আউটপুট অনুমান করুন: “1011” detector-এর তিনটি সংস্করণে input 1011011011 (বাঁ থেকে, cycle ০ থেকে ৯) দিলে কোন কোন cycle-এ z = 1 হবে? (ক) Mealy overlapping (খ) Mealy non-overlapping (গ) Moore overlapping (শেষ input-এর পরের cycle ১০-সহ)।

    (ক) z = 0001001001 — cycle ৩, ৬ আর ৯. State-এর ক্রম (প্রতি ধারের পর): B C D B C D B C D B — প্রতিটি মিলের শেষ “1” পরের মিলের শুরু।

    (খ) z = 0001000001 — cycle ৩ আর ৯. Cycle ৩-এর মিলের পর A-তে ফিরে নতুন করে শোনে: বাকি 011011-এ প্রথম “0”-তে A-তেই থাকে, তারপর “1”, “1” — B, B; তারপর 0 → C, 1 → D, আর শেষ 1-এ মিল (z = 1, আবার A); অর্থাৎ cycle ৪–৯-এর বিট দিয়ে একটি নতুন “1011” পূর্ণ হয় cycle ৯-এ। State ক্রম: B C D A A B B C D A.

    (গ) Moore-এর z আসে এক cycle পরে: cycle ৪, ৭ আর ১০ — state ক্রম S0 S1 S2 S3 S4 S2 S3 S4 S2 S3 S4. (তিনটিই অংশ ৪-এর simulator-এর মতো একটি scratch script-এ যাচাই করা।)

  4. সমীকরণ বের করুন: ৩ দিয়ে বিভাজ্যতার FSM (R0 = 00, R1 = 01, R2 = 10, কোড 11 don't care) JK flip-flop দিয়ে বানান: J1, K1, J0, K0 বের করুন। তারপর পরীক্ষা করুন, কোনোভাবে state 11-এ গেলে এই JK নকশা কোথায় যায় — D-নকশার মতো আটকে থাকে কি?

    Excitation: সারি (Q1Q0x → পরের): 000 → 00, 001 → 01, 010 → 10, 011 → 00, 100 → 01, 101 → 10, 11x → X. Q1-এর জন্য: Q1 = 0 সারিতে J1 = পরের Q1 (0, 0, 1, 0), K1 = X; Q1 = 1 সারিতে J1 = X, K1 = উল্টো (100 → 0 হয়, তাই 1; 101 → 1 থাকে, তাই 0). Q0-এর জন্য একইভাবে।

    ফল: J1 = Q0x′, K1 = x′, J0 = Q1x′ + Q1′x (= Q1 ⊕ x), K0 = 1 (Q0 = 1 হলে পরের ধারে সবসময় 0 — R1 থেকে R2 বা R0, দুটিরই Q0 = 0). z = Q1′Q0′.

    State 11 থেকে: x = 0 হলে J1 = 1, K1 = 1 → Q1 উল্টে 0; J0 = 1, K0 = 1 → Q0 উল্টে 0 — পরের state 00 (R0). x = 1 হলে J1 = 0, K1 = 0 → Q1 = 1 থাকে; J0 = 0, K0 = 1 → Q0 = 0 — পরের state 10 (R2). তাই JK নকশা এক cycle-এই বৈধ state-এ ফেরে, যেখানে D-নকশা (D1 = Q0x′ + Q1x, D0 = Q1x′ + Q1′Q0′x) x = 0-তে 11-এই আটকে থাকে। শিক্ষা: don't care কীভাবে ব্যবহার হলো তার ওপর অব্যবহৃত state-এর আচরণ নির্ভর করে, তাই প্রতিবার আলাদা করে যাচাই করতে হয়। (দুটি ফলই scratch script-এ যাচাই করা।)

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি FSM কথার সমস্যা থেকে যাচাই-করা circuit পর্যন্ত নকশার ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. প্রতিটি state-এর অর্থ ঠিক করে state diagram আঁকা
  2. State table লেখা
  3. সমতুল্য state একত্র করা (minimisation)
  4. প্রতিটি state-কে বিট-কোড দেওয়া (state assignment)
  5. K-map দিয়ে next-state আর output সমীকরণ বের করা
  6. Circuit বানিয়ে simulation-এ প্রতিটি transition যাচাই করা

একটি synchronous FSM-এর output z কেবল বর্তমান state-এর ওপর নির্ভর করে, input x-এর ওপর সরাসরি নয়। এটি কোন ধরনের machine, আর input বদলালে output কখন সাড়া দেয়?

  • Mealy; একই cycle-এ
  • Moore; পরের clock ধারে state বদলানোর পর
  • Asynchronous machine; সঙ্গে সঙ্গে
  • Moore; কখনোই নয়, কারণ output input দেখে না

একটি FSM-এ ১০টি state. Binary encoding আর one-hot encoding-এ যথাক্রমে কয়টি flip-flop লাগবে?

  • ৩ আর ১০
  • ৪ আর ৮
  • ৪ আর ১০
  • ১০ আর ৪

“1011” overlapping Mealy detector-এর state: A (কিছু না), B (“1”), C (“10”), D (“101”). State D-তে input 1 এলে output আর পরের state কী?

  • z = 1, পরের state B
  • z = 1, পরের state A
  • z = 0, পরের state C
  • z = 0, পরের state একটি নতুন state E

একটি Mealy machine-এর state P আর Q-এর output প্রতিটি input-এ এক। P-এর পরের state (x = 0, x = 1) = (R, S), আর Q-এর = (S, R). কোন শর্তে P আর Q equivalent?

  • যেহেতু output এক, তারা সবসময় equivalent
  • শুধু তখনই, যদি পরের state-গুলো হুবহু এক হয়
  • কখনোই নয়, কারণ পরের state উল্টো ক্রমে
  • যদি R আর S নিজেরা equivalent হয়

Verilog-এ FSM-এর combinational next-state block always @(*) begin case (state) A: if (x) next = B; … endcase end-এ কিছু শাখায় next মান পায় না। Latch এড়ানোর সবচেয়ে প্রচলিত উপায় কোনটি?

  • Sensitivity list-এ সব সংকেত হাতে লেখা
  • Block-এর শুরুতেই next = state; লেখা
  • সব =-কে <= করা
  • initial next = A; লেখা

৩টি state-এর একটি FSM ২টি flip-flop দিয়ে বানানো (কোড 00, 01, 10); কোড 11 অব্যবহৃত আর K-map-এ don't care ধরা হয়েছে। নিচের কোন কথাটি সঠিক?

  • Reset থাকলে 11 নিয়ে কখনো ভাবতে হয় না
  • Don't care ধরা থাকলে 11 সবসময় পরের ধারে 00-তে যায়
  • সমীকরণে 11 বসিয়ে দেখতে হয়; কোনো input-এ এটি 11-এই আটকে থাকতে পারে
  • Synthesis tool সবসময় 11-কে নিজে থেকে নিরাপদ state-এ পাঠায়

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. FSM = state + input + output + transition. State অতীতের সারাংশ — ভবিষ্যতের জন্য যতটুকু দরকার। Hardware-এ: state register (D flip-flop) + next-state logic + output logic.
  2. Moore: z = λ(state) — এক cycle পরে, স্থির; Mealy: z = λ(state, x) — একই cycle-এ, state সমান বা কম। “1011” detector: Moore ৫ state, Mealy ৪.
  3. Sequence detector-এর নিয়ম: প্রতিটি state = “লক্ষ্যের শুরুর কতটুকু মিলেছে”; ভুল বিটে শেষ অংশের সবচেয়ে লম্বা মিলে-যাওয়া শুরুতে ফেরা। Overlapping বনাম non-overlapping শুধু মিলের পরের তীরে আলাদা।
  4. Minimisation: output দিয়ে ভাগ, তারপর পরের state-এর দল দিয়ে বারবার ভাগ যতক্ষণ না স্থির (বা implication table-এ X ছড়ানো)। Assignment: binary = কম flip-flop, one-hot = ছোট-দ্রুত logic (FPGA-তে প্রিয়), Gray = ক্রমিক machine-এ কম toggle.
  5. বাস্তবের নিয়ম: অব্যবহৃত কোড বসিয়ে lock-up যাচাই; reset (ধরা async, ছাড়া sync); Verilog-এ register, next-state, output আলাদা block আর next = state; default; পরীক্ষায় পূর্ণ transition coverage.

পরের পর্বে: এতক্ষণ ধরে নিয়েছি clock ধারে সব flip-flop নিখুঁতভাবে নতুন মান নেয়। বাস্তবে প্রতিটি gate-এর delay আছে, flip-flop-এর setup আর hold time আছে — next-state logic কত দ্রুত হলে FSM কত দ্রুত clock-এ চলবে, আর অসমলয় (asynchronous) input FSM-এ ঢুকলে metastability কেন ভয়ের — পর্ব ১৮-এ।

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

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান