CSA222: Modern Computer Architecture
Ekdam Zero se Complete Notes — Labs + Lectures + Assignments + Quizzes
🔮 Lab 1–7 (Full Detail) 📖 L01–L07 Lectures ✏️ Q1–Q26 Assignments ❓ Q1–Q35 Quizzes 💡 Verilog HDL
L01 Boolean Algebra & Logic Gates — Ekdam Zero Se Shuru

🔮 Pehle Samjho: Computer ke andar kya hota hai?

Tu jab Python mein a + b likhta hai, tab actually lakhon transistors ek saath switch karte hain. Har transistor ek chota switch hai — ya to band hai (0) ya khula hai (1). Bas itna. Aur in switches ko combine karke bante hain logic gates, gates se bante hain adders, adders se bante hain ALU, aur ALU se banta hai pura CPU.

Abstraction Stack — Upar se Neeche:
AI/ML Models (PyTorch, neural nets)
Application Software (Python, your code)
Operating System (Linux, Windows — manages hardware)
ISA (Instruction Set Architecture) — CPU ki vocabulary: ADD, SUB, LOAD, STORE
Datapath & Control (registers, ALU, FSMs — ye course yahan focus karta hai!)
Logic Gates (AND, OR, NOT — aaj yahan se shuru)
Transistors (silicon switches, physical world)

Ye course gates se datapath tak ka safar karaata hai. Tujhe A[i]=B[i]+C[i] ko Python se leke transistors tak trace karna aana chahiye. Aaj ka kaam: gates aur Boolean algebra.

🔮 Architecture vs Organisation — Difference Kya Hai?

🅾 Architecture — "KYA" hai
Programmer ko jo dikhta hai. Kaunse instructions available hain (ADD, SUB, JUMP). Kitne registers hain. ISA = contract between hardware and software.

Example: "Is CPU mein ADD instruction hai" — ye architecture hai.

Same architecture, alag hardware chal sakta hai. ARM ka koi bhi CPU same code chalata hai, chahe Apple M4 ho ya Qualcomm Snapdragon.
🔢 Organisation — "KAISE" hai
Implementation detail. ADD kaise physically banta hai. Pipeline kitne stages ka hai. Cache kitna bada. Ye programmer ko nahi dikhta.

Example: "ADD operation 1 clock cycle mein hota hai aur carry-lookahead adder use karta hai" — ye organisation hai.

Apple M4 aur Qualcomm dono ARM ISA pe chal sakte hain but andar se bilkul alag hain.

🔮 Boolean Algebra Kya Hai? (George Boole, 1847)

Boolean algebra ek aisa math hai jahan sirf do values hote hain: 0 aur 1. George Boole ne 1847 mein ye system banaya tha for logical reasoning. Phir 1937 mein Claude Shannon ne prove kiya ki ye EXACTLY electronic circuits describe karta hai!

SymbolHardware MeaningSoftware MeaningPhysical Meaning
1HIGH voltage (~3.3V)TRUESwitch ON
0LOW voltage (~0V)FALSESwitch OFF
Kyun sirf 0 aur 1? Reliability ke liye! Agar tu "2.7V aur 3.1V alag hain" detect karne ki koshish kare, noise mein problem hogi. But "volts hai ya nahi" = easy! Threshold ke upar = 1, neeche = 0. Simple aur noise-resistant.

🔮 Logic Gates — Har Gate Ka DNA

Gate ek electrical circuit hai jo Boolean operation karta hai. Aaj 7 gates padho — yahi teri poori digital duniya hai.

🔌 AND Gate — "Dono chahiye"

Series mein do switches ki tarah. Dono ON hone chahiye tab hi output ON. Real example: "Alarm tab baje jab door bhi khuli HO aur motion bhi detect hua HO."

Y = A · B      (Matlab: "A AND B")
ABY = A·BExplanation
000Dono switch band → current nahi
010Pehla band → current nahi
100Doosra band → current nahi
111Dono ON → current jaata hai!
💡 Memory trick: "AND = Stingy gate" — output 1 tab hi deta hai jab DONO 1 hon. Sirf ek 1 mein satisfy nahi hota!

🔌 OR Gate — "Koi bhi ek chalega"

Parallel mein do switches ki tarah. Koi bhi ek ON ho tab output ON. Real example: "Light on karo jab presence sensor OR motion sensor trigger ho."

Y = A + B      (Matlab: "A OR B", '+' ka matlab yahan OR hai, add nahi!)
ABY = A+BExplanation
000Dono band → current nahi (SIRF yahi case 0 hai!)
011B ON hai kafi hai
101A ON hai kafi hai
111Dono ON, definitely 1
💡 Memory trick: "OR = Generous gate" — kisi bhi ek 1 se kush ho jaata hai. Sirf tabhi 0 deta hai jab dono 0 hon.

🔌 NOT Gate — "Ulta kar do"

Simplest gate. Ek input, ek output — bas flip karo. Real example: "Active-LOW LED: logic 0 pe jalti hai, 1 pe bujhti hai." Uses: complement banane ke liye, active-low signals ke liye.

Y = A'      (also written À, or ~A in Verilog)
AY = A'
01
10

🔌 XOR Gate — "Ek ya doosra, dono nahi"

Exclusive OR. Output 1 tab jab inputs alag hain. Output 0 tab jab inputs same hain. Real uses: adder ka SUM bit, parity checker, cryptography.

Y = A ⊕ B      (A XOR B, caret ^ in Verilog)
ABY = A⊕BWhy?
000Same (both 0) → 0
011Different → 1
101Different → 1
110Same (both 1) → 0 (yahi "exclusive" hai!)
XOR ek aur important property: agar A XOR B = C, to A XOR C = B. Iska matlab: XOR apni khud ki inverse operation hai! Isliye encryption mein use hota hai — same key se encrypt aur decrypt dono!

🔌 NAND, NOR, XNOR — Inverted versions

GateFormulaMeaning00011011
NAND~(A·B)NOT AND — AND ka ulta1110
NOR~(A+B)NOT OR — OR ka ulta1000
XNOR~(A⊕B)Same = 1, Different = 01001
NAND aur NOR — Universal Gates!
Sirf NAND gates use karke NOT, AND, OR — aur therefore koi bhi logic — bana sakte hain!
NOT(A) = NAND(A,A) → inputs tie karo, NAND becomes NOT!
AND(A,B) = NOT(NAND(A,B)) = 2 NANDs
OR(A,B) = NAND(NOT A, NOT B) = 3 NANDs
Real chip factories isliye NAND optimize karte hain — ek gate type bahut acchhi tarah manufacture ho sakti hai!

🔮 Boolean Laws — Simplification ke Rules

In laws se hum complex expressions simplify karte hain → kam gates = chhota chip, kam power, tez circuit.

Law NameAND FormOR FormIntuition
IdentityA · 1 = AA + 0 = A1 se AND ya 0 se OR → kuch nahi badla
Null/DominanceA · 0 = 0A + 1 = 10 se AND = always 0. 1 se OR = always 1
IdempotentA · A = AA + A = AKhud se operate = no change
ComplementA · A' = 0A + A' = 1Opposite combine = extreme result
Double Negation(A')' = ADo baar NOT = original
CommutativeAB = BAA+B = B+AOrder doesn't matter (addition ki tarah)
Associative(AB)C = A(BC)(A+B)+C = A+(B+C)Grouping doesn't matter
DistributiveA(B+C) = AB+ACA+(BC) = (A+B)(A+C)AND distributes over OR, and vice versa!
AbsorptionA(A+B) = AA+AB = A"A already included in AB" — redundant term drops!
ConsensusAB + A'C + BC = AB + A'CBC is consensus term — always redundant!

De Morgan's Laws — SABSE IMPORTANT!

(A · B)' = A' + B'       (A + B)' = A' · B'
Plain English mein:
"NAND(A,B) = OR with inverted inputs" — (AB)' = A'+B'
"NOR(A,B) = AND with inverted inputs" — (A+B)' = A'B'

Trick to apply: "Break the bar, flip the sign"
1. Complement whole expression: change sign
2. Swap AND ↔ OR everywhere
3. Invert each individual variable

3-variable: (ABC)' = A' + B' + C'   |   (A+B+C)' = A'B'C'
Works for ANY number of variables!

Worked Example: AB + AB' ko simplify karo

  • 1Start: Y = AB + AB'
  • 2Factor out A: Y = A(B + B')   [Distributive Law]
  • 3B + B' = 1: Y = A(1)   [Complement Law]
  • 4A·1 = A: Y = A   [Identity Law]
Result: 4 gates (2 AND, 1 OR, 1 NOT) → 1 wire! Yahi Boolean algebra ki power hai. Real chips mein ye savings multiply hoke crores of gates tak jaate hain!

🔮 SOP, POS, Minterms aur Maxterms

SOP (Sum of Products) — F=1 rows se banao

  • 1Truth table mein jahan F=1 hai, un rows ko dekho
  • 2Har row ke liye ek AND term banao: variable=1 → as-is, variable=0 → complement
  • 3Sab AND terms ko OR karo
Example: F(A,B,C) = Σm(1,3,5,7)
m1 = A=0,B=0,C=1 → A'B'C    m3 = A=0,B=1,C=1 → A'BC
m5 = A=1,B=0,C=1 → AB'C    m7 = A=1,B=1,C=1 → ABC
F = A'B'C + A'BC + AB'C + ABC
Simplify: C(A'B'+A'B+AB'+AB) = C(A'+A) = C·1 = C (C sirf ek hai!)

POS (Product of Sums) — F=0 rows se banao

F=0 wali rows mein MAXTERMS hote hain. Har maxterm mein: variable=1 → complement, variable=0 → as-is. Phir AND karo sab maxterms ko.

Minterm vs Maxterm:
Minterm m5: A=1,B=0,C=1 → Binary 101 = 5 → AB'C (SOP term, AND of all vars)
Maxterm M5: same row but POS → (A'+B+C') (OR of all vars, with flip!)
L02 Logic Minimisation — K-Maps, NAND/NOR Universal Gates

🔮 Kyun Minimise Karte Hain?

Har extra gate = extra silicon area, extra power, extra heat, aur extra delay. Ek mobile phone mein 10 billion transistors hain. Agar har function 2x zyada gates use kare → phone ka battery 2x tez khatam ho, aur chip 2x costly ho. Boolean minimization directly money aur performance se linked hai!

🔮 Karnaugh Map (K-Map) — Visual Minimization Tool

K-map ek grid hai jo truth table ka visual version hai. Adjacent cells mein single bit change hoti hai (Gray code!). Adjacent 1s ko group karke, combined Boolean term result mein kam variables hote hain.

⚠️ GRAY CODE ORDER = NON-NEGOTIABLE!
Rows/columns: 00, 01, 11, 10 — NOT 00, 01, 10, 11!
Reason: 01 ke baad 11 aata hai (1-bit change). Agar 10 aata to 2-bit change hoti → adjacent nahi!
Adjacent grouping valid hai SIRF jab 1 bit change ho. Yahi combining theorem ka base hai!

K-Map Rules — Sab Yaad Karo

  • Group sizes sirf powers of 2: 1, 2, 4, 8, 16. 3 cells = ILLEGAL!
  • Groups rectangular hone chahiye (square ya rectangle only)
  • Wrap-around valid hai! Left edge + right edge = neighbors. Top + bottom = neighbors. Four corners bhi ek group!
  • Overlapping groups allowed aur zaroorat bhi padti hai
  • Har 1 cover hona chahiye kam se kam ek group mein
  • Don't-cares (X): Group bada karne ke liye 1 maano, baaki ignore karo
  • Variable elimination: Agar group mein variable 0 bhi ata hai aur 1 bhi → eliminate karo. Agar constant hai → rakho term mein

3-Variable K-Map Layout

AB\CC=0C=1
AB=00m0 (ABC=000)m1 (ABC=001)
AB=01m2 (ABC=010)m3 (ABC=011)
AB=11m6 (ABC=110)m7 (ABC=111)
AB=10m4 (ABC=100)m5 (ABC=101)
💡 Gray code order: 00, 01, 11, 10. Note 11 comes BEFORE 10! That's the trick — 01→11 = 1 bit change (B), 11→10 = 1 bit change (A). If it were 00,01,10,11: 01→10 = 2 bits change = NOT adjacent logically!

Step-by-Step: 4-Variable K-Map Example

F(A,B,C,D) = Σm(0,2,5,7,8,10,13,15)

  • 1Draw 4x4 grid. Rows = AB (00,01,11,10), Cols = CD (00,01,11,10)
  • 2Fill 1s at minterms: 0,2,5,7,8,10,13,15
  • 3Find FOUR CORNERS: m0(0000), m2(0010), m8(1000), m10(1010). B=0,D=0 throughout. A and C change → eliminate A,C. Group = B'D'
  • 4Find quad: m5(0101),m7(0111),m13(1101),m15(1111). B=1,D=1 throughout. A and C change → eliminate A,C. Group = BD
  • 5Final: F = B'D' + BD

Prime Implicants (PI) aur Essential PI (EPI)

Prime Implicant (PI)
Ek aisa group jo aur bada nahi ho sakta (grow nahi ho sakta while remaining rectangular and power-of-2). Ye sab groups hain jo aap khich sakte ho agar sirf maximally large groups lo.
Essential Prime Implicant (EPI)
Ek PI jo kam se kam ek aisa "1" cover karta hai jo koi aur PI cover nahi karta. EPI MUST be in every minimal SOP. EPIs pehle identify karo, phir baaki uncovered 1s ke liye cheapest PI chuno.
Minimal Cover
All EPIs + minimum additional PIs to cover ALL 1s.

🔮 NAND aur NOR Universal Gates — Deep Dive

NAND se NOT, AND, OR banana

NOT A = NAND(A, A) // Both inputs tied = A NAND A = ~(A&A) = ~A ✓ AND(A,B) = NOT(NAND(A,B)) // 2 NANDs: one NAND then one NOT (= NAND with tied inputs) OR(A,B) = NAND(NOT A, NOT B) // 3 NANDs: invert both, then NAND // Why? NAND(A', B') = ~(A'·B') = A+B by DeMorgan! (A+B)=~(~(A+B))=~(A'B')
NAND-NAND = 2-level SOP implementation!
F = AB + CD (standard SOP)
F = NAND(NAND(A,B), NAND(C,D))
Proof: NAND(NAND(A,B), NAND(C,D)) = ~(~(AB) · ~(CD)) = AB + CD ✓
This is the most common real-chip implementation. Two levels of NAND = any SOP. Fast!

NOR se NOT, OR, AND banana

NOT A = NOR(A, A) // A NOR A = ~(A|A) = ~A ✓ OR(A,B) = NOT(NOR(A,B)) // 2 NORs AND(A,B) = NOR(NOT A, NOT B) // 3 NORs: invert both, then NOR // Why? NOR(A', B') = ~(A'+B') = A·B by DeMorgan!

🔮 Bubble Pushing — Gate Conversion Without Algebra

Bubble pushing = DeMorgan ka visual version. Gate ke output pe bubble lagaao → gate type flip karo aur sab inputs pe bubble lagaao.

Rules:
1. NAND = AND gate with bubble on output = OR gate with bubbles on all inputs
2. NOR = OR gate with bubble on output = AND gate with bubbles on all inputs
3. Two bubbles in series CANCEL each other (double NOT = original)
Use this to: Convert SOP NAND-NAND to bubble-pushed form visually. Much easier than algebra!
L03 Combinational Building Blocks — MUX, Decoder, Adder

🔮 Kyun "Reusable Blocks"?

Koi bhi CPU ek gate at a time design nahi karta. Verified blocks banao — MUX, decoder, adder — aur phir in blocks ko compose karo. Ek verified MUX = infinite trusted copies. Jaise LEGO bricks: individual bricks simple, but mila ke complex cheez banti hai.

🔮 Multiplexer (MUX) — Data Selector

MUX = "N inputs mein se exactly 1 choose karke output pe daal do." Select lines decide karti hain kaunsa. Real-world analogy: railway switch — do tracks mein se ek choose karta hai.

2:1 MUX — Ek Select Line, Do Inputs

Y = S'·A + S·B
Kaise kaam karta hai yeh equation?
S=0: S'=1. Y = 1·A + 0·B = A. (A pass hua, B block hua)
S=1: S'=0. Y = 0·A + 1·B = B. (B pass hua, A block hua)
Exactly like a train switch selecting one track.

MUX as Universal Logic Function

2n:1 MUX = ANY n-variable Boolean function! Feed variables into SELECT lines, feed truth table values as DATA inputs.

XOR(A,B) using 4:1 MUX:
S1=A, S0=B (address lines)
I0 (A=0,B=0) = 0 (XOR is 0)
I1 (A=0,B=1) = 1 (XOR is 1)
I2 (A=1,B=0) = 1 (XOR is 1)
I3 (A=1,B=1) = 0 (XOR is 0)
This is EXACTLY how FPGA LUTs work! 4-input LUT = 16:1 MUX = any 4-variable function. You "program" an FPGA by choosing what values go in the LUT data inputs.

🔮 Decoder — Binary Code to One-Hot

n-bit input → 2n outputs. Exactly ONE output HIGH at any time (one-hot output). Input = which output goes HIGH.

2:4 Decoder example:
Input 00 → Y0=1, Y1=Y2=Y3=0
Input 01 → Y1=1, rest=0
Input 10 → Y2=1, rest=0
Input 11 → Y3=1, rest=0

Real use: Register file write! 5-bit write address → 5:32 decoder → exactly one of 32 register's WE (write enable) goes HIGH → only that register captures data on clock edge.

🔮 Adders — Already covered in detail in Lab 4!

Half Adder, Full Adder, 4-bit RCA, Overflow detection — sab Lab 4 mein with full Verilog code & truth tables. Lab 4 section dekho!
L04 Number Systems & Two's Complement — Negatives Kaise Represent Karte Hain

🔮 Number Systems

Binary to Decimal

Har bit ki value = 2position. MSB se shuru:

Bit2726252423222120
Weight1286432168421
Example: 10110101₂ = ?
1×128 + 0×64 + 1×32 + 1×16 + 0×8 + 1×4 + 0×2 + 1×1 = 128+32+16+4+1 = 181

Decimal to Binary — Divide-by-2 Method

42 ko binary mein convert karo:

  • 142 ÷ 2 = 21 remainder 0
  • 221 ÷ 2 = 10 remainder 1
  • 310 ÷ 2 = 5 remainder 0
  • 45 ÷ 2 = 2 remainder 1
  • 52 ÷ 2 = 1 remainder 0
  • 61 ÷ 2 = 0 remainder 1
  • 7Remainders neeche se upar padho: 101010₂ = 42 ✓

Hex (Base-16) Shortcuts

Hex digits: 0-9, A=10, B=11, C=12, D=13, E=14, F=15
Hex to Binary: Har hex digit = exactly 4 bits. 0xB5 = 1011 0101
B=1011, 5=0101 → 10110101 → same as 181 above!
Binary to Hex: 4 bits mein group karo right se. 11011001 → 1101=D, 1001=9 → 0xD9
Why hex? 8-bit binary (10110101) hard to read. 0xB5 much more compact!

🔮 Signed Numbers — Negative Kaise Represent Karen?

Problem: bits sirf 0 ya 1 hoti hain. Negative numbers kaise?

Representation+5 (8-bit)−5 (8-bit)Range (8-bit)Problem
Sign-Magnitude0000 01011000 0101−127 to +127Two zeros! (+0 and −0). Complex adder needed.
One's Complement0000 01011111 1010−127 to +127Two zeros again! End-around carry in addition.
Two's Complement ✔0000 01011111 1011−128 to +127ONE zero. Regular binary adder works. WINNER!

Two's Complement — Ekdam Deep Dive

Negate karo = Flip all bits (one's complement), then add 1
  • 1+5 = 00000101
  • 2Flip all bits: 11111010 (one's complement)
  • 3Add 1: 11111011
  • 411111011 = −5 in two's complement ✓
Verify: 11111011 = −5?
MSB has NEGATIVE weight in two's complement!
11111011 = −128 + 64 + 32 + 16 + 8 + 2 + 1 = −128 + 123 = −5

4-bit ranges:
0000 = 0
0001 to 0111 = +1 to +7
1000 = −8 (MSB weight is −8, others positive)
1001 = −8+1 = −7
1111 = −8+4+2+1 = −1
Range: −8 to +7 (n-bit: −2n-1 to +2n-1−1)
⚠️ Exam Traps:
1. 1000 (4-bit) = NOT −0! It's −8 (the most negative value).
2. −8 ka two's complement kya hai? ~(1000)+1 = 0111+1 = 1000. −8 apna khud ka complement hai! No positive +8 in 4-bit.
3. Sign extension: 4-bit → 8-bit? MSB copy karo upar: +3 (0011) → 00000011. −3 (1101) → 11111101. Formula: {4{a[3]}, a}

🔮 Two's Complement Addition — Regular Binary Adder!

Yahi two's complement ka magic hai: same hardware for positive AND negative numbers.

+7 + (−3) = ?
+7 = 0111, −3 = 1101
0111 + 1101 = 10100. Drop the carry-out → 0100 = 4 ✓

+7 + (−7) = ?
0111 + 1001 = 10000. Drop carry → 0000 = 0 ✓

Regular binary adder kaam karta hai signed numbers ke liye bhi! No special logic needed.
L05 Sequential Circuits — Memory, Clock, Latches & Flip-Flops

🔮 Combinational vs Sequential — The Great Divide

Combinational — No Memory
Output = f(current inputs ONLY). Past kuch matter nahi. Same inputs = always same output. Examples: AND gate, adder, MUX, decoder.

Test: Agar input change karo aur output change hoti hai "turant" without needing a clock → combinational!
Sequential — Has Memory (state)
Output = f(inputs + PAST STATE). History matters! Same inputs can give different outputs depending on what happened before. Examples: counter, register, UART, CPU itself.

Test: Agar circuit ko "remember" karna hai → sequential!

🔮 Feedback = Memory Ka Secret

Circuit mein memory kaise aati hai? Output ko input mein wapas connect karo = FEEDBACK LOOP.

Do stable states possible hain: "Q=0, Q'=1 stable" aur "Q=1, Q'=0 stable". Yahi memory hai!

🔮 SR Latch — Pehli Memory Cell

Do NOR gates, cross-coupled. Har gate ka output doosre gate ka input feed karta hai.

SRQ (next)ActionWhy?
00Q (hold)HOLDDono NOR inputs same, output maintains. Perfect memory!
101SETS=1 forces Q=1. Even after S goes back to 0, Q stays 1 (memory!)
010RESETR=1 forces Q=0. Memory again.
11???FORBIDDENBoth outputs go to 0. Q = Q' = 0 → breaks Q ≠ Q' invariant!
Forbidden State (S=R=1) Physics — Step by Step:
Step 1: S=1, R=1. Both NOR gates: ~(1|anything) = 0. So Q=0, Q'=0.
Step 2: Now Q=Q'=0 simultaneously — this violates the fundamental rule that they must be complements!
Step 3: Now release S=R=0. Both NOR gates see: ~(0|0) = 1. Both want to output 1 simultaneously!
Step 4: They race! Whichever NOR gate is even a picosecond faster wins. The other loses. Result is completely non-deterministic.
Step 5: In simulator: iverilog shows 'X' (unknown) — this is CORRECT and EXPECTED behavior. Not a bug!

🔮 D Latch — Forbidden State Ko Fix Karo

D latch = SR latch + enable gate + clever internal wiring: S = D·E and R = D'·E. Since D and D' are always opposite, S and R can NEVER both be 1. Forbidden state = impossible!

Transparency Problem (D latch ka main flaw):
E=1 ke dauran, koi bhi noise ya glitch jo D pe aata hai, turant Q tak pahunch jaata hai!
Example: E=HIGH, D wiggles 0→1→0→1 (noise). Q bhi usi tarah wiggle karta hai.
CPU pipelines mein ye disastrous hai. Ek 1ns glitch D pe = permanent wrong value stored!
Fix: Edge-triggered flip-flop which samples D at EXACTLY ONE INSTANT (clock edge).
FeatureD LatchD Flip-Flop
Control signalEnable (level)Clock (edge)
When output updatesEntire HIGH window of EnableExactly ONE rising edge instant
Transparent?YES — D wiggles = Q wigglesNO — Q frozen between edges
Glitch propagation?YESNO
Used in modern CPUs?Rarely (SRAM cells, time borrowing)EVERYWHERE — all registers!

🔮 D Flip-Flop — The CPU's Memory Cell

At rising clock edge: Q ← D (sampled once). Between edges: Q is frozen, regardless of what D does.

Master-Slave DFF — Two-Phase Airlock

  • 1CLK=HIGH: Master latch is transparent (captures D). Slave latch is locked (holds Q).
  • 2CLK=LOW: Master locks (holds its captured value). Slave becomes transparent (passes master's value to Q).
  • 3Never both transparent! Data can only advance one stage per half-cycle. Race impossible!
  • 4Result: Q changes when CLK falls (falling-edge triggered master-slave DFF)
Two latches in series = "two-stage airlock". Data enters master. Data exits from slave. No way to skip from D to Q in one shot. This is why we can pipeline!

🔮 All 4 Flip-Flop Types

TypeInputsChar. EquationPrimary UseSpecial
SRS, RQ+ = S + R'Q  (if SR'=invalid)Basic memory, latchesS=R=1 = forbidden!
DDQ+ = DRegisters, pipelines, state FFs. THE DEFAULT.Simplest, no forbidden state
JKJ, KQ+ = JQ' + K'QUniversal — can do SR, D, TJ=K=1 → TOGGLE! No forbidden.
TTQ+ = T ⊕ QCounters (T=1 toggles every clock)Built from JK (J=K=T) or D (D=T⊕Q)
JK FF — Forbidden State Fix:
J=K=1 mein SR latch k S=R=1 (forbidden) tha. JK ne ise TOGGLE mein convert kiya!
When J=K=1: Q+ = Q' (flip). No more forbidden state.
Har aur behavior same: J=1,K=0 → SET. J=0,K=1 → RESET. J=K=0 → HOLD.
D from JK: J=D, K=D'. T from JK: J=K=T.

🔮 Setup Time, Hold Time, Metastability

Flip-flop ek snapshot leta hai clock edge pe. Usi snapshot ke around D stable honi chahiye, warna blurry photo!

t_su (Setup Time)
D must be stable at LEAST t_su BEFORE the clock edge. Like stopping motion BEFORE the shutter clicks. Violate → FF captures wrong value or goes metastable.
t_h (Hold Time)
D must be stable for at LEAST t_h AFTER the clock edge. Like holding still AFTER the shutter. Violate → same problem.
t_cq (Clock-to-Q)
Time from clock edge to Q being valid. After clock edge, Q takes t_cq time to settle. Max frequency limited by: f_max = 1/(t_cq + t_logic + t_su)
Metastability
If D changes in the setup/hold window, FF enters an undefined state — output somewhere between 0 and 1, like a coin balanced on its edge. It WILL resolve eventually (to 0 or 1) but WHEN and to WHAT is unpredictable. This is why CDC synchronizers are needed!
Clock Domain Crossing (CDC):
Signal from 100MHz clock domain → sampled by 133MHz domain FF.
No guaranteed phase relationship → D might change exactly AT the clock edge → metastability!
Fix: 2-stage synchronizer — two DFFs in series on the destination clock. After 2 stages, probability of unresolved metastability in 1 clock cycle = astronomically small. MTBF = millions of years!
L06 Registers, Shift Registers, Counters & FSM Intro

🔮 Register — N Flip-Flops in Parallel

N D flip-flops, sab ek hi clock share karte hain. N bits store karta hai. All N bits update SIMULTANEOUSLY on same clock edge = atomic update.

CPU register kya hai?
RISC-V x0–x31: 32 registers, each 32-bit = 32 × 32 = 1024 DFFs sharing one clock!
Fastest memory (register > cache > RAM > disk).
Right next to the ALU — zero latency for computations.
PC (Program Counter) = 1 register that holds current instruction address.
IR (Instruction Register) = holds currently executing instruction.

Load Enable — Why Registers Need It

Plain DFF grabs D on EVERY clock edge. But register should hold value for many cycles, update only when told. Solution: 2:1 MUX per bit at D input.

LOAD=1: new_data → MUX output → D → FF captures new value
LOAD=0: Q_current → MUX output → D → FF re-captures same value (HOLD)

🔮 Shift Registers — Bit Conveyor Belt

FFs chain karo: one FF's Q = next FF's D. Clock edge pe, har bit ek position aage shift hoti hai.

TypeInput ModeOutput ModeKey ApplicationDirection
SISOSerial (1 bit)Serial (1 bit)Delay line, pipeline bufferData waits N clocks
SIPOSerial (1 bit)Parallel (all)UART Receiver, SPIBuild up parallel word
PISOParallel (all)Serial (1 bit)UART Transmitter, SPIBreak down parallel word
PIPOParallel (all)Parallel (all)Normal register!Load all, read all
UART (Serial Communication) deep dive:
UART = Universal Asynchronous Receiver/Transmitter. Baud rate = bits per second.
Transmitter (PISO): CPU gives 8-bit byte (parallel). PISO loads all 8 bits, then shifts out 1 bit per clock = serial data on TX wire.
Receiver (SIPO): Incoming serial bits arrive at RX wire. SIPO shifts in 1 bit per clock. After 8 clocks, all 8 bits assembled → CPU reads 8-bit parallel output.
Same for SPI (3 wires: MOSI, MISO, CLK) and I2C. Shift registers everywhere!
Shift = Multiply/Divide:
Binary number left shift by 1 = multiply by 2! 0011(3) → 0110(6)
Binary right shift by 1 = divide by 2! 1100(12) → 0110(6)
This is how CPUs do fast multiply/divide by powers of 2 with no adder — just shift!

🔮 Counters

Ripple Counter (Asynchronous) — DON'T USE

Bit-0 FF toggling every clock. Bit-1 FF clocked by Bit-0's output. Bit-2 clocked by Bit-1. Etc.

Problems with Ripple:
1. Delay = N × t_FF. 12-bit ripple @0.6ns/FF = 7.2ns delay → only 139MHz max!
2. GLITCHY! 3-bit going 011(3) → 100(4): bit-0 flips first(0), then bit-1(0), then bit-2(1). Briefly: 011→010→000→100. Temporary 0 appears! Any decoder watching sees false 0 output!

Synchronous Counter — ALWAYS USE THIS

All FFs share same clock. Next-state logic computed in PARALLEL. All FFs update simultaneously.

Synchronous counter advantages:
1. No glitches — all bits change together
2. Constant delay regardless of N (no ripple!)
3. Clean transitions for decoders, comparators
4. TC (Terminal Count) = &q (reduction AND). Pulses once when counter reaches max value. Use to cascade counters!

🔮 LFSR — Linear Feedback Shift Register

Shift register + XOR feedback from specific taps → generates pseudo-random bit stream.

  • Maximal length: n-bit LFSR visits 2n−1 unique non-zero states before repeating
  • All-zeros stuck forever: XOR of zeros = 0. Initial state must NOT be 0!
  • Applications: CRC (error detection), pseudo-random number generation, test pattern generation, spread-spectrum comms

🔮 FSM Introduction

FSM = Finite State Machine. Any circuit ki general blueprint. States + transitions + outputs.

5-Tuple Definition: (S, I, O, δ, λ)
S = set of states (finite!)
I = input alphabet
O = output alphabet
δ = state transition function: δ(state, input) → next_state
λ = output function: Moore → λ(state), Mealy → λ(state, input)

Registers = special FSM with trivial state (just stored value)
Counters = special FSM that loops through a sequence
CPU itself = FSM (instruction cycle: fetch, decode, execute, writeback)
L07 Register Files & Complete FSM Design

🔮 Register File — CPU ka "Workspace"

Register file = CPU ke andar multiple registers ka collection with efficient read/write mechanism.

RISC-V Register File:
32 registers (x0 to x31), each 32-bit wide
= 32 × 32 = 1024 DFFs sharing one clock
2 READ ports (DUAL read — both async!)
1 WRITE port (synchronous)
x0 = hardwired zero (writes ignored, reads always 0)

READ Operation — Asynchronous (NO CLOCK!)

Why async? Speed! In one clock cycle, CPU needs to: read 2 operands → ALU computes → write result. Reads must be instant (combinational) or there won't be time for ALU.

MOST ASKED EXAM QUESTION: Register file reads are ASYNCHRONOUS!
Read address (5-bit) → 32:1 MUX (with all 32 register outputs as data inputs) → output
Two independent MUXes = two simultaneous reads in same cycle
Output appears INSTANTLY when address changes (combinational)
No clock edge needed for reads — this is fundamental!

WRITE Operation — Synchronous (NEEDS CLOCK)

  • 1Write address (5-bit) → 5-to-32 decoder
  • 2Decoder output: one of 32 WE (write enable) lines goes HIGH
  • 3On posedge clk: only that register (with WE=1) captures write_data
  • 4All other 31 registers: WE=0 → HOLD their values

x0 Hardwired Zero — Why?

RISC-V mein x0 hamesha 0 kyu rahta hai?
1. No-op (NOP) easy: ADD x0, x0, x0 = literally does nothing!
2. Comparison: BEQ x1, x0, label → branch if x1==0. Constant 0 always needed for comparison.
3. Move: ADD x2, x1, x0 → x2 = x1 + 0 = x1. Register copy!
4. Load immediate: ADDI x1, x0, 5 → x1 = 0 + 5 = 5. Load constant!
Writes to x0: hardware SILENTLY IGNORES them. Reads from x0: always return 0.

🔮 Moore vs Mealy FSM — Full Comparison

FeatureMoore MachineMealy Machine
Output depends onCurrent STATE onlyState + Current INPUT
Where output writtenINSIDE the state circleON the transition arrow
Output changes whenState changes (clock edge)Input changes (immediate!)
Glitchy?NO — output stable between edgesYES — can glitch when input glitches
Number of statesMore (separate state for each output)Fewer (output on edges)
Response speed1 cycle delay (output after state)Same cycle (combinational)
Design preferenceSafer, easier to verifyFaster response, fewer states

🔮 1011 Sequence Detector — Full Moore FSM Design

Problem: Detect "1011" in a serial bit stream. Output 1 when detected. Handle overlaps!

  • 1Understand: Serial input 'x'. Output 'z'. Detect pattern "1011". Overlapping allowed (e.g., "10110 11" — the second "11" might start at overlap).
  • 2Identify States: How much of the pattern have we matched so far?
    S0=nothing matched, S1=matched "1", S2=matched "10", S3=matched "101", S4=matched "1011" (OUTPUT!)
  • 3Draw Transitions: For each state, what happens when x=0 and when x=1?
StateMeaningx=0 → Nextx=1 → NextOutput ZWhy the transition?
S0Idle/ResetS0S10x=1 starts our pattern; x=0 can't start 1011
S1Got "1"S2S10x=0 → "10" so far; x=1 → "11" = still have 1 (last 1 valid)
S2Got "10"S0S30x=1 → "101"; x=0 → "100" = no prefix of 1011 → back to S0
S3Got "101"S2S40x=1 → "1011" done!; x=0 → "1010" = "10" is prefix → S2
S4Got "1011" ✓S2S11x=0 → "10110" = "10" so far; x=1 → "10111" = last "1" could start new
TRICKY S4 Transitions — EXAM FAVOURITE!
S4 + x=1 → S1 (NOT S0!):
After "1011" (matched!), if next bit is 1, we now have "10111". The LAST '1' of this could be the START of a new "1011". So we go to S1 (seen one '1' so far). If we went to S0, we'd miss overlapping patterns!

S4 + x=0 → S2 (NOT S0!):
After "1011", if x=0, we have "10110". Now look at the TAIL: "10" — this IS a prefix of "1011"! So we go to S2 (seen "10"). Going to S0 would waste the match we've already made!

Test: Input "101110110 11" → should detect TWO "1011" patterns. Wrong S4 transitions = misses second match!

State Encoding — Kaunsa Best?

Binary Encoding
5 states → ⌈log₂5⌉ = 3 FFs. S0=000, S1=001, S2=010, S3=011, S4=100. Compact but decode logic complex. Unused states (101,110,111) need safe handling (go to reset state).
One-Hot Encoding
5 states → 5 FFs. S0=10000, S1=01000, S2=00100, S3=00010, S4=00001. Exactly ONE FF=1. Next state logic very simple (each state = just check current FF). FPGAs prefer this (FFs are abundant).
Gray Encoding
Adjacent states differ by 1 bit. Fewer power-hungry transitions. Used in counters to minimize switching power.
LAB 1 Verilog Setup & Basic Gates — Where It All Begins

🔮 Verilog Kya Hai? (Basics from Scratch)

Verilog = Hardware Description Language (HDL). Ye ek programming language nahi hai — ye ek wiring diagram ka textual representation hai. Jab tu Verilog likhta hai, tu CPU ke andar wires aur gates describe kar raha hota hai, not steps.

Software (C/Python) — Sequential
Instructions ek-ek karke execute hoti hain. Line 2 execute hone ke liye Line 1 khatam honi chahiye. CPU ek kaam ek time pe karta hai.
Hardware (Verilog) — Concurrent
Saare gates SIMULTANEOUSLY switch karte hain. 10 billion transistors AAEK SAATH switch karte hain. No queues, no waiting!
Simulation vs. Synthesis:
Simulation (iverilog/ModelSim): Tumhara Verilog ek normal CPU pe run hota hai aur circuit behavior model karta hai. Waveform (.vcd) generate hoti hai. Kuch physical nahi banta — ye sab Lab 1-7 yahi karta hai.
Synthesis (Synopsys/Cadence): Same Verilog padh ke real gate-level netlist generate karta hai jo silicon pe fabricate hoti hai. Real chips aise bante hain!
⚠️ Sabse Important Mental Shift: Verilog ko C ki tarah mat padho! assign y = a & b; ye ek line nahi hai jo "execute" hoti hai — ye ek WIRE hai jo a aur b ke beech ek AND gate se permanently connected hai. Jab a ya b change hote hain, y TURANT change hoti hai — koi delay nahi, koi sequence nahi.

🔮 Verilog Language Fundamentals

Module — Hardware ka Building Block

Verilog mein har circuit ek module hai. Module = black box with inputs and outputs. Andar wires aur logic. Bahar sirf ports.

module module_name ( input wire single_bit_in, // 1-bit input input wire [7:0] eight_bit_bus, // 8-bit input bus [MSB:LSB] output wire comb_output, // Use WIRE for assign outputs output reg seq_output // Use REG for always outputs ); // Internal signals (wires between submodules) wire internal_signal; // Continuous assignment (combinational logic) assign comb_output = single_bit_in & eight_bit_bus[0]; // Procedural block (sequential logic) always @(posedge clk) seq_output <= single_bit_in; endmodule

wire vs reg — Most Confused Concept!

wire — A Physical Wire
Net hai — gate output ko input se connect karta hai. Hamesha driven hona chahiye (by assign or module output). Use wire for: module outputs connected via assign, module instance connections. Kabhi bhi inside always block assign mat karo wire ko!
reg — A Variable (NOT a register!)
Procedural variable — sirf always blocks ke andar assign hoti hai. Naam misleading hai — ye real register nahi banta unless posedge clk block mein ho. Use reg for: always block outputs.
Rule: always @(*) mein output → reg. assign mein output → wire. Simple!
Violation pe synthesis tool error dega (ya worse, wrong circuit silently banayega).

assign vs always — Two Worlds

assign (Continuous Assignment)
Ye ek wire hai, statement nahi! Jab bhi RHS change ho, LHS turant update. No clock needed. For combinational logic only. LHS must be wire.
Example: assign y = a ^ b;
always @(*) (Combinational Block)
Jab bhi koi bhi signal inside change ho, re-evaluate. (*) means "auto-detect all inputs." Complex combinational logic ke liye (case statements etc). LHS must be reg.
Example: always @(*) begin y = sel ? b : a; end
// always @(posedge clk) — Sequential (flip-flop) // Sirf rising clock edge pe evaluate. Register/FF banana ho to ye use karo. always @(posedge clk) q <= d; // <= = nonblocking assignment // always @(*) — Combinational // Koi bhi input change ho — re-run. assign ki tarah. always @(*) y = a & b; // = blocking assignment ok here

Blocking (=) vs Nonblocking (<=)

🎓 EXAM FAVOURITE:
= (Blocking): Execute NOW. Next statement waits. Use in combinational always @(*).
<= (Nonblocking): Schedule update end of time step. All RHS evaluated first THEN all LHS update. Use ALWAYS in posedge always blocks!

Why <= in sequential? Agar posedge mein = use karo aur do flops ek dusre ko chain karo, data ek cycle mein skip ho sakta hai (race condition). <= ensures all flops capture same-cycle values correctly.

Verilog Operators Quick Reference

OpSymbolExampleUseResult
AND&a & bAND gate1 if both 1
OR|a | bOR gate1 if any 1
NOT~~aInverterFlip
XOR^a ^ bXOR gateDifferent=1
XNOR~^a ~^ bXNOR gateSame=1
NAND~( & )~(a&b)NAND gateNOT AND
NOR~( | )~(a|b)NOR gateNOT OR
Ternary?:s?b:a2:1 MUXs=1→b, s=0→a
Concat{}{a,b,c}Bit joinMSB first
Replicate{n{x}}{4{a[3]}}Sign extend4 copies
Red-AND&x&qAll bits 1?1 if all bits=1
Red-OR|x|qAny bit 1?1 if any bit=1

🔮 All 7 Gates in Verilog

// AND Gate module and_gate(input wire a,b, output wire y); assign y = a & b; // 0,0,0,1 endmodule // OR Gate module or_gate(input wire a,b, output wire y); assign y = a | b; // 0,1,1,1 endmodule // NOT Gate module not_gate(input wire a, output wire y); assign y = ~a; // 1,0 endmodule // XOR Gate module xor_gate(input wire a,b, output wire y); assign y = a ^ b; // 0,1,1,0 (different=1) endmodule // NAND Gate module nand_gate(input wire a,b, output wire y); assign y = ~(a & b); // 1,1,1,0 endmodule // NOR Gate module nor_gate(input wire a,b, output wire y); assign y = ~(a | b); // 1,0,0,0 endmodule // XNOR Gate module xnor_gate(input wire a,b, output wire y); assign y = ~(a ^ b); // 1,0,0,1 (same=1) endmodule

Testbench Template (Self-Checking)

Testbench ek special module hai jiska koi port nahi hota — ye sirf simulation ke liye hai. Andar DUT (Design Under Test) instantiate hoti hai aur stimulus diya jaata hai.

module and_gate_tb; // No ports! reg a, b; // reg = we drive these wire y; // wire = DUT drives this // Instantiate DUT and_gate dut(.a(a), .b(b), .y(y)); initial begin $dumpfile("and_tb.vcd"); $dumpvars(0, and_gate_tb); // Apply all 4 input combinations a=0; b=0; #10; $display("%s a=%b b=%b y=%b", (y===0)?"PASS":"FAIL", a,b,y); a=0; b=1; #10; $display("%s a=%b b=%b y=%b", (y===0)?"PASS":"FAIL", a,b,y); a=1; b=0; #10; $display("%s a=%b b=%b y=%b", (y===0)?"PASS":"FAIL", a,b,y); a=1; b=1; #10; $display("%s a=%b b=%b y=%b", (y===1)?"PASS":"FAIL", a,b,y); $finish; end endmodule
Run Commands:
iverilog -o sim.vvp and_gate.v and_gate_tb.v — Compile
vvp sim.vvp — Run simulation
gtkwave and_tb.vcd — View waveforms
Common Errors & Fixes (Lab 1):
✕ Forgot $dumpfile + $dumpvars → Empty VCD file
✕ wire where reg needed (in always) → Compile error
✕ No #delay between stimuli → All happen at t=0, waveform useless
✕ Wrong port connection order → Use named ports .portname(wire) always!
LAB 2 Logic Minimisation & Universal Gates — 35 Worked Questions

🔮 Section A: Warm-up & Fundamentals (Q1–Q7)

Strategy — Canonical Forms:
• SOP: F=1 wali rows → 1=as-is, 0=complemented variable
• POS: F=0 wali rows → 1=complemented, 0=as-is variable
• Minterm number = binary value of input combo (MSB left)
• Maxterm = same index as minterm at same row
Q1 — Evaluate F = AB + AB' + A'B for A=1, B=0
✔️ F = 1
Step 1: A=1,B=0 → B'=1
Step 2: AB = 1·0 = 0  |  AB' = 1·1 = 1  |  A'B = 0·0 = 0
F = 0+1+0 = 1
Q2 — Canonical SOP from truth table: F(A,B,C) = Σm(1,2,4,7)
✔️ F = A'B'C + A'BC' + AB'C' + ABC
Rows where F=1: (0,0,1)=m1, (0,1,0)=m2, (1,0,0)=m4, (1,1,1)=m7
m1: A=0→A', B=0→B', C=1→C → A'B'C
m2: A=0→A', B=1→B, C=0→C' → A'BC'
m4: A=1→A, B=0→B', C=0→C' → AB'C'
m7: A=1→A, B=1→B, C=1→C → ABC
Q3 — Same truth table, canonical POS
✔️ F = (A+B+C)(A+B'+C')(A'+B+C')(A'+B'+C) = ΠM(0,3,5,6)
F=0 rows: (0,0,0)=M0, (0,1,1)=M3, (1,0,1)=M5, (1,1,0)=M6
POS rule: 1→complement, 0→as-is in maxterm
M0=(A+B+C), M3=(A+B'+C'), M5=(A'+B+C'), M6=(A'+B'+C)
Q4 — Convert F = Σm(0,3,5,6) to Π notation
✔️ F = ΠM(1,2,4,7)
Missing minterms (where F=0) = 1,2,4,7 → these are the maxterms
Q5 — Minterm for A=1, B=0, C=1, D=0
✔️ m10 = AB'CD'
Binary 1010₂ = 10₁₀ → A=1→A, B=0→B', C=1→C, D=0→D'
Q6 — Maxterm for A=0, B=1, C=1
✔️ M₃ = (A + B' + C')
011₂ = 3₁₀. Maxterm rule: 1→complement, 0→as-is in OR terms.
A=0→A (0 stays), B=1→B' (1 complements), C=1→C'
Q7 — F = Σm(1,2,4,7): SOP + equivalent POS
✔️ SOP = A'B'C + A'BC' + AB'C' + ABC  |  POS = ΠM(0,3,5,6)
Missing minterms = 0,3,5,6 → these are maxterms for POS

🔮 Section B: Boolean Algebra & Simplification (Q8–Q13)

Laws to Know: Identity(A+0=A, A·1=A), Null(A+1=1, A·0=0), Complement(A+A'=1, A·A'=0), Idempotent(A+A=A), Absorption(A+AB=A), Consensus(AB+A'C+BC = AB+A'C)
Q8 — Which law: X + X·Y = X?
✔️ Absorption Law
X + XY = X(1+Y) = X·1 = X   (1+Y = 1 by Null law)
Q9 — Simplify A + A'B
✔️ F = A + B
A + A'B = (A+A')(A+B) = 1·(A+B) = A+B  [Distributive: A+BC = (A+B)(A+C)]
Q10 — Simplify F = XY + X'Z + YZ. Is YZ necessary?
✔️ F = XY + X'Z  (YZ is redundant — Consensus Theorem)
Consensus Theorem: AB + A'C + BC = AB + A'C (BC is consensus term — ALWAYS redundant)
Here: XY + X'Z + YZ → YZ is the consensus of XY(X) and X'Z(X'). Drop it!
Q11 — Prove/disprove: (A+B)(A'+C) = AC + A'B
✔️ True! F = AC + A'B
Expand LHS: AA' + AC + A'B + BC = 0 + AC + A'B + BC
BC is consensus of AC and A'B → drop it. F = AC + A'B ✓
Q12 — Remove redundancy: F = A'B'C + A'BC + AB'C + ABC + A'B
✔️ F = C + A'B
A'B'C + A'BC = A'C(B'+B) = A'C  |  AB'C + ABC = AC(B'+B) = AC
A'C + AC = C(A'+A) = C  |  Remaining A'B  |  F = C + A'B
Q13 — Complement of F = (A+B)(A'+C)
✔️ F' = A'B' + AC'
F' = [(A+B)(A'+C)]' = (A+B)' + (A'+C)'  [DeMorgan on whole]
= A'B' + AC'  [DeMorgan on each factor]

🔮 Section C & D: K-Maps (Q14–Q26)

K-Map Rules — MUST MEMORIZE:
1. Gray code order: 00, 01, 11, 10 (NOT 00,01,10,11!)
2. Group sizes: powers of 2 only (1,2,4,8,16)
3. Groups must be rectangular
4. Wrap-around valid! (Top-bottom, left-right, corners)
5. Overlapping groups allowed and often needed
6. Every 1 must be covered
7. Don't-cares (X): treat as 1 when grouping, ignore otherwise
8. Variable CHANGES inside group → ELIMINATED from term
9. Variable CONSTANT in group → SURVIVES in term
Q14 — Why Gray code order (00-01-11-10) not binary (00-01-10-11)?
✔️ Gray code ensures adjacent cells differ by EXACTLY 1 bit
Binary order: 01 next to 10 = 2-bit difference → NOT adjacent logically!
Gray code: 01 next to 11 = 1-bit difference ✓, 11 next to 10 = 1-bit difference ✓
Adjacent grouping only valid when single bit changes → allows combining theorem: AB + AB' = A
Q15 — 2-var K-map for F(A,B) = Σm(0,2)
✔️ F = B'
m0=(A=0,B=0), m2=(A=1,B=0). Both have B=0, A changes → eliminate A → F = B'
Group of 2 (vertical column where B=0) → B stays 0 → term = B'
Q16 — 3-var K-map F(A,B,C) = Σm(0,2,3,5)
✔️ F = A'B + A'C' + AB'C
m2(010)+m3(011): A=0, B=1, C changes → A'B (group of 2)
m0(000)+m2(010): A changes, B changes? No — wrap! m0+m2 with B fixed? Let me check:
m0(000),m2(010): B changes(0,1) A same(0), C same(0) → A'C' (group of 2)
m5(101): AB'C (lone cell, must cover)
F = A'B + A'C' + AB'C
Q17 — Legal groups on 3-var K-map (select all)
✔️ A (four corners) and B (2x2 block)
A: Four corners = valid group of 4 (wrap-around on both axes) ✓
B: 2x2 block = rectangular, power-of-2 size ✓
C: Three adjacent = size 3, NOT power of 2 ✗
D: Two cells differing in 2 variables = NOT adjacent (must differ by 1 bit only) ✗
Q18 — Group of 4 covering m0,m2,m4,m6 on 3-var K-map
✔️ F = C'
m0=000, m2=010, m4=100, m6=110. C is ALWAYS 0! A and B both change → both eliminated. Only C survives as C'
Q19 — All 8 minterms = 1. Minimal expression?
✔️ F = 1
Entire 3-var K-map is one group of 8. All 3 variables change → all eliminated. F = 1 (tautology)
Q20 — F = A'C + AB: place on K-map, list minterms
✔️ Σm(1,3,6,7)
A'C: A=0,C=1 → m1(001), m3(011)
AB: A=1,B=1 → m6(110), m7(111)
Q21 — 4-var: F(A,B,C,D) = Σm(0,2,5,7,8,10,13,15). Watch corners!
✔️ F = B'D' + BD
Four corners: m0(0000), m2(0010), m8(1000), m10(1010) → B=0,D=0 always → B'D'
Quad: m5(0101), m7(0111), m13(1101), m15(1111) → B=1,D=1 always → BD
F = B'D' + BD  [XOR of B and D... actually XNOR pattern!]
Q22 — Cells m0,m2,m8,m10 on 4-var K-map: one product term
✔️ B'D'
These are the four corners. B=0, D=0 throughout. A,C change → eliminated. Term = B'D'
Q23 — F(A,B,C) = Σm(0,1,2,5,6,7): All PIs, EPIs, minimal cover
✔️ F = A'B' + BC' + AC
PIs: A'B'(m0,m1), A'C'(m0,m2), B'C(m1,m5), BC'(m2,m6), AC(m5,m7), AB(m6,m7)
EPI check: m1 uniquely in A'B' and B'C... Find EPIs by cells covered by only 1 PI
One minimal cover: A'B' + BC' + AC ✓
Q24 — 5 PIs, 3 are essential. Minimum product terms?
✔️ At least 3 (exactly 3 if EPIs cover all 1s)
All EPIs MUST be in minimal cover. If 3 EPIs cover everything, answer = 3
Q25 — True/False: Overlapping groups always illegal?
✔️ FALSE! Overlapping is LEGAL and often required for minimal cover
A single 1 can belong to multiple groups. Overlapping lets each group be larger → simpler terms
Q26 — F has PIs P1=A'B, P2=BC', P3=AC, P4=A'C'. m0 unique in P4, m7 unique in P3
✔️ EPIs = P4 + P3. Minimal cover: A'C' + AC + BC'
P4(A'C') and P3(AC) are EPIs (must include). Remaining 1s: use P1 or P2 to cover.
One answer: A'C' + AC + BC'

🔮 Section E: DeMorgan & Bubble Pushing (Q27–Q30)

DeMorgan Rules (MOST IMPORTANT in this course!):
(AB)' = A' + B'     (A+B)' = A'·B'
Trick: Complement the whole, then change AND↔OR
Bubble Pushing: Bubble on output = bubbles on all inputs + change gate type
Q27 — Simplify F = ((A+B)'·C)' + (A·B)'
✔️ F = 1
(A+B)' = A'B' (DeMorgan)
(A'B'·C)' = (A'B')' + C' = (A+B) + C' = A+B+C' (DeMorgan again)
(AB)' = A'+B'
F = (A+B+C') + (A'+B') = (has A+A') = 1 (since A+A'=1 always)
Q28 — (A·B)' + C into simplest form
✔️ F = A' + B' + C
(AB)' = A'+B' by DeMorgan. F = A'+B'+C. Done!
Q29 — (A·B·C)' into OR form
✔️ A' + B' + C'
DeMorgan on 3 inputs: (ABC)' = A'+B'+C'. Complement + AND→OR
Q30 — Simplify F = ((A'+B)' + (A·C)')'
✔️ F = ABC
(A'+B)' = AB' (DeMorgan: complement, OR→AND)
(AC)' = A'+C' (DeMorgan)
Inner: AB' + A' + C'  [two terms inside outer complement]
F = (AB' + A' + C')' = (AB')'·(A')'·(C')' = (A'+B)·A·C = (A+AA') wait...
F = A·(A'+B)·C... wait: A·A'=0, so F = A·B·C = ABC

🔮 Section F&G: Universal Gates + GATE-style (Q31–Q35)

Q31 — NAND realizations of NOT, AND, OR. Gate counts?
✔️ NOT=1, AND=2, OR=3
NOT(A) = NAND(A,A) = ~(A·A) = ~A → 1 NAND
AND(A,B) = NOT(NAND(A,B)) = 2 NANDs (NAND then NAND as inverter)
OR(A,B) = NAND(NOT A, NOT B) = NAND(NAND(A,A), NAND(B,B)) = 3 NANDs
Because: NAND(A',B') = ~(A'·B') = A+B by DeMorgan ✓
Q32 — NOR realizations. Gate counts?
✔️ NOT=1, OR=2, AND=3
NOT(A) = NOR(A,A) = 1 NOR
OR(A,B) = NOT(NOR(A,B)) = 2 NORs
AND(A,B) = NOR(NOT A, NOT B) = NOR(NOR(A,A), NOR(B,B)) = 3 NORs
Q33 — F = AB + C using only 2-input NANDs. Minimum gates?
✔️ 3 NAND gates
F = AB + C = ((AB)'·C')' (DeMorgan)
G1: NAND(A,B) = (AB)'
G2: NAND(C,C) = C'  (inverter)
G3: NAND((AB)', C') = ~((AB)'·C') = AB+C ✓
3 gates total!
Q34 — GATE-Style: Min 2-input NANDs for F=(A+B)(C+D)?
✔️ D. 6 NAND gates
A+B needs 3 NANDs. C+D needs 3 NANDs. Then AND them? No, use NAND-NAND...
(A+B) = NAND(A',B') = 3 NANDs | (C+D) = 3 NANDs | AND final = 2 more → Total 6+overlap = 6 classic count
Q35 — Which statements true about PIs, EPIs, don't-cares?
✔️ B and C are true
A. FALSE — #PIs ≠ #EPIs always (can have non-essential PIs)
B. TRUE — Every EPI MUST appear in minimal SOP (by definition!)
C. TRUE — Don't-care minterms CAN be part of a PI (we include them to make bigger groups)
D. FALSE — Under classic definition, two minimal covers have same number of terms
LAB 3 Combinational Circuits — MUX, DEMUX & Verilog Constructs

🔮 Why Data Selector Circuits?

CPU ke andar har jagah MUX aur DEMUX hain:

  • ALU operand select: Register value ya immediate constant? → 2:1 MUX
  • PC update: PC+4, branch target, ya jump target? → 3:1 MUX
  • Write address: Kaunse register mein data likhe? → Decoder (= DEMUX)
  • FPGA LUT: 16 inputs = 4-var truth table → 16:1 MUX!

🔮 Verilog New Constructs

Ternary Operator (?:) — 2:1 MUX in 8 characters

assign y = condition ? value_if_1 : value_if_0; // sel=0 → y=a, sel=1 → y=b assign y = sel ? b : a; // Perfect 2:1 MUX!

case Statement — 4:1 MUX (No latch inference if default!)

always @(*) begin case (sel) 2'b00: y = i0; 2'b01: y = i1; 2'b10: y = i2; default: y = i3; // MUST HAVE! Covers 2'b11 + catches X/Z endcase end
⚠️ Missing default = LATCH inferred! Agar case sab values cover nahi karta, tool sochta hai "undefined case mein purani value rakh" = latch. Always add default!

for Loop in Testbench

integer k; initial begin for (k=0; k<4; k=k+1) begin {s1, s0} = k; // k=0→00, k=1→01, k=2→10, k=3→11 #10; end end

🔮 2:1 MUX — Gate-Level + Behavioral

Y = S'·I0 + S·I1
SYMeaning
0I0 (=A)A selected
1I1 (=B)B selected
// Gate-Level (structural) — shows actual transistors module mux2x1_gate(input wire a,b,sel, output wire y); wire sel_n, t0, t1; not u0(sel_n, sel); // S' and u1(t0, a, sel_n); // S'·A and u2(t1, b, sel); // S·B or u3(y, t0, t1); // Y = S'A + SB endmodule // Behavioral (ternary) — what you'll actually use module mux2x1(input wire a,b,sel, output wire y); assign y = sel ? b : a; endmodule

🔮 4:1 MUX

Y = S1'S0'·I0 + S1'S0·I1 + S1S0'·I2 + S1S0·I3
S1S0Y
00I0
01I1
10I2
11I3
// Behavioral with case (preferred) module mux4x1(input wire i0,i1,i2,i3, input wire [1:0] sel, output reg y); always @(*) begin case (sel) 2'b00: y = i0; 2'b01: y = i1; 2'b10: y = i2; default: y = i3; endcase end endmodule // Testbench — for-loop sweeps all select combos module mux4x1_tb; reg i0,i1,i2,i3; reg[1:0] sel; wire y; integer k; mux4x1 dut(.i0(i0),.i1(i1),.i2(i2),.i3(i3),.sel(sel),.y(y)); initial begin i0=0; i1=1; i2=0; i3=1; for(k=0;k<4;k=k+1) begin {sel}=k; #10; end $finish; end endmodule

🔮 1:2 DEMUX — Mirror of MUX

DEMUX = Data Distributor. 1 input, routed to one of many outputs. Unselected outputs = 0.

Y0 = S'·D      Y1 = S·D
SY0Y1
0D0
10D
module demux1x2(input wire d,sel, output wire y0,y1); assign y0 = ~sel & d; assign y1 = sel & d; endmodule

🔮 1:4 DEMUX

S1S0Y0Y1Y2Y3
00D000
010D00
1000D0
11000D
module demux1x4(input wire d, input wire[1:0] sel, output reg[3:0] y); always @(*) begin y = 4'b0000; // Clear all first! case(sel) 2'b00: y[0] = d; 2'b01: y[1] = d; 2'b10: y[2] = d; default: y[3] = d; endcase end endmodule
Common Errors (Lab 3):
✕ Missing default in case → Latch inferred!
✕ y declared wire but assigned in always → Compile error!
✕ {s1,s0} vs {s0,s1} wrong order → Wrong input selected!
✕ Overlapping case items → Silent misbehaviour!
LAB 4 Adders, Two's Complement & Overflow Detection

🔮 Why Adders Matter

  • Subtraction: A−B = A+(~B)+1 — same adder with XOR gates!
  • Multiplication: Array of adders (shift + add)
  • PC update: PC ← PC+4 every single clock cycle
  • Address calculation: Base + offset, always an adder

🔮 Half Adder (HA) — 2 inputs, no carry-in

Sum = A ⊕ B      Cout = A · B
ABSumCoutBinary
00000+0=00
01100+1=01
10101+0=01
11011+1=10 ⚠
Why "HALF" adder? It has NO carry-in. So it can only add bit-0 (LSB). For any other bit position, carry from previous stage must be accepted → need Full Adder!
module half_adder(input wire a,b, output wire sum,cout); assign sum = a ^ b; // XOR assign cout = a & b; // AND endmodule

🔮 Full Adder (FA) — 3 inputs, has carry-in

Sum = A ⊕ B ⊕ Cin      Cout = AB + Cin(A⊕B)
KEY INSIGHT — Full Adder = 2 Half Adders + OR:
HA1: a,b → s1,c1  |  HA2: s1,cin → sum,c2  |  cout = c1 | c2
Why OR works: c1 = AB, c2 = (A⊕B)·Cin. If A=B=1 then A⊕B=0, so c2=0. They can NEVER both be 1 → OR is correct!
ABCinSumCoutRule
000000
001101
010101
011012
100101
101012
110012
111113

Sum=1 when odd number of inputs are 1 (parity). Cout=1 when 2+ inputs are 1 (majority).

// Structural: 2 HAs + OR (hierarchical design!) module full_adder(input wire a,b,cin, output wire sum,cout); wire s1,c1,c2; half_adder ha1(.a(a), .b(b), .sum(s1), .cout(c1)); half_adder ha2(.a(s1), .b(cin),.sum(sum),.cout(c2)); assign cout = c1 | c2; endmodule // Behavioral (shorter, same circuit after synthesis) module full_adder_beh(input wire a,b,cin, output wire sum,cout); assign sum = a ^ b ^ cin; assign cout = (a&b) | (cin&(a^b)); endmodule

🔮 4-bit Ripple Carry Adder (RCA)

Idea: Chain 4 FAs. Bit-0 FA cout goes to bit-1 FA cin. Carry "ripples" stage by stage.

⚠️ Ripple = SLOW! Worst case (1111+0001): carry must ripple through ALL 4 stages before last sum is correct. N-bit RCA delay = N × t_FA. For 64-bit: 64 × 2 = 128 gate delays! Modern CPUs use Carry Lookahead Adder (CLA) instead (parallel carry computation).
module rca_4bit( input [3:0] a,b, input cin, output [3:0] s, output cout); wire c1,c2,c3; // internal carry chain full_adder fa0(.a(a[0]),.b(b[0]),.cin(cin),.sum(s[0]),.cout(c1)); full_adder fa1(.a(a[1]),.b(b[1]),.cin(c1), .sum(s[1]),.cout(c2)); full_adder fa2(.a(a[2]),.b(b[2]),.cin(c2), .sum(s[2]),.cout(c3)); full_adder fa3(.a(a[3]),.b(b[3]),.cin(c3), .sum(s[3]),.cout(cout)); endmodule
Test Cases (must know!):
0001+0001 = 00010 (CF=0) — Simple, carry only bit0→bit1
0111+0001 = 01000 (CF=0) — Carry ripples bits 0,1,2
1111+0001 = 10000 (CF=1) — Full ripple! sum=0000, cout=1 = overflow!
1000+1000 = 10000 (CF=1) — Immediate overflow from bit-3

🔮 Unsigned vs Signed — Same Bits, Two Meanings

Unsigned (U): 0 to 2ⁿ−1
All bits = magnitude only. 4-bit: 0000=0 to 1111=15. Overflow = Cout!
CF = Cout
Signed 2s Comp (S): −2ⁿ⁻¹ to +2ⁿ⁻¹−1
MSB = sign bit. 4-bit: 0000=0 to 0111=+7, 1000=−8 to 1111=−1. Cout meaningless!
OF = C3 ⊕ C4
Overflow Flag (OF) = C3 ⊕ C4
C3 = carry INTO MSB position  |  C4 (=cout) = carry OUT of MSB
Why XOR? Signed overflow happens when sign bit gets flipped by carry incorrectly.
Same-sign inputs → different-sign output = overflow (e.g., +7+1=−8 in 4-bit!)
0111+0001: MSB cin=1, cout=0 → OF = 1⊕0 = 1 (overflow!) ⚠️
1111+0001: MSB cin=1, cout=1 → OF = 1⊕1 = 0 (no signed overflow — −1+1=0 ok)
CaseInputsSumCFOFNote
10001+00010010001+1=2, all fine
21111+0001000010Unsigned wrap, signed −1+1=0 ok
30111+0001100001+7+1 should be +8 but got −8!
41000+1000000011Both CF and OF! Unsigned 8+8=16, Signed −8+−8=−16 both wrong
// Adder-Subtractor: m=0 add, m=1 subtract module adder_subtractor(input[3:0] a,b, input m, output[3:0] s, output cout); wire[3:0] bx = b ^ {4{m}}; // m=1: ~b (flip), m=0: b unchanged rca_4bit rca(.a(a),.b(bx),.cin(m),.s(s),.cout(cout)); // m=1: cin=1, b=~b → a + ~b + 1 = a - b (two's complement!) endmodule
🏭 Common Lab 4 Errors:
✕ cout always 0 even for 1+1+1: wrote c1 & c2 instead of c1 | c2! AND requires BOTH carries=1 which never happens
✕ sum bits reversed: a[0] is LSB! fa0 should connect to a[0],s[0] not a[3]
✕ Last sum always X: fa3 missing c3 connection → unconnected Cin = X
✕ No delay in testbench: all at t=0, waveform useless
LAB 5 Latches & Flip-Flops — The Day Your Circuit Learns to Remember

🔮 Why Memory? Combinational vs Sequential

Combinational — No Memory
Output = f(current inputs only). Same inputs → always same output. Outputs update instantly when inputs change. Examples: adders, MUXes, decoders.
Sequential — Has Memory
Output = f(inputs + past state). Same inputs can give different outputs depending on history! A clock decides WHEN state updates. Examples: registers, counters, FSMs.
Try writing a counter with only AND/OR/XOR. You can't! There's no way to ask "what was Q a moment ago?" without something that remembers. That something = FEEDBACK LOOP.

Feedback = wire an output back into an input. With the right topology, two stable states exist → the circuit can hold either → memory!

🔮 SR Latch — Sabse Pehli Memory Cell

Made of 2 cross-coupled NOR gates. Each gate's output feeds the other's input. This mutual reference = storage.

Equations: Q = ~(R|Q')    Q' = ~(S|Q)    When S=R=0: Q=~Q', Q'=~Q (consistent → stable!)

SRQ(next)ActionNotes
00Q_prevHOLDBoth NORs in hold. Q keeps its value!
101SETS=1 forces Q=1
010RESETR=1 forces Q=0
11??FORBIDDEN!Both outputs driven to 0. Q=Q'=0 breaks invariant. On release: race!
Forbidden State Deep-Dive (S=R=1):
Step 1: S=R=1 → both NOR gates output 0. So Q=0, Q'=0 (violates Q≠Q' rule!)
Step 2: Now release S=R=0. Both NOR inputs are 0 → both outputs try to go to 1 simultaneously
Step 3: They RACE! Whichever gate is even slightly faster wins → non-deterministic result
In simulator: iverilog shows X (unknown) after S=R=1 then 0. That is CORRECT behavior!
// NOR-based SR Latch (cross-coupled assigns) module sr_latch(input wire s,r, output wire q,qbar); assign q = ~(r | qbar); // q depends on qbar assign qbar = ~(s | q); // qbar depends on q // Mutual reference = the memory loop! endmodule // Testbench: walk through all cases module sr_tb; reg s,r; wire q,qbar; sr_latch dut(.s(s),.r(r),.q(q),.qbar(qbar)); initial begin $dumpfile("sr.vcd"); $dumpvars(0,sr_tb); s=0; r=0; #5; // HOLD (unknown initial) s=1; r=0; #5; // SET: q=1 s=0; r=0; #5; // HOLD: q stays 1 s=0; r=1; #5; // RESET: q=0 s=0; r=0; #5; // HOLD: q stays 0 s=1; r=1; #5; // FORBIDDEN: q=qbar=0! s=0; r=0; #5; // After forbidden: X (metastable) $finish; end endmodule

🔮 SR Latch Problems → D Latch Fixes Them

  • Problem 1: Two control lines (S and R) = user can accidentally assert both → forbidden!
  • Problem 2: Any glitch on S/R propagates instantly → unsafe
  • Problem 3: No concept of "time" → asynchronous, can't pipeline

🔮 D Latch — Forbidden State Impossible

D latch = SR latch + enable gate. Internally: S = D·E, R = D'·E. Since S=D·E and R=D'·E, they can never BOTH be 1 at same time (D and D' are always different).

EDQAction
0XQ_prevHOLD — D can change freely, Q frozen
100TRANSPARENT: Q=D=0
111TRANSPARENT: Q=D=1
⚠️ TRANSPARENT means D wiggles pass through! During E=1, any noise on D appears on Q. CPU pipelines can't use latches in critical paths because glitches propagate! A 1ns spike on D during E=1 changes Q permanently.
// D Latch: using if in always @(*) module d_latch(input wire d,en, output reg q,q_n); always @(*) begin if(en) begin q <= d; q_n <= ~d; end // en=0: no assignment → Verilog infers HOLD (latch!) end endmodule // Structural: using SR latch as submodule module d_latch_struct(input wire d,e, output wire q,qbar); wire s_int, r_int; assign s_int = d & e; // S = D·E assign r_int = ~d & e; // R = D'·E (never both 1!) sr_latch core(.s(s_int),.r(r_int),.q(q),.qbar(qbar)); endmodule

🔮 Level-Triggered vs Edge-Triggered

FeatureD Latch (Level)D Flip-Flop (Edge)
TriggerEntire LEVEL (E=HIGH window)Single EDGE (0→1 instant)
Transparent?Yes during E=1No — opaque between edges
Glitches propagate?YesNo
Verilogalways @(*) if(en)always @(posedge clk)
Output typereg (or wire via assign)reg (always)
Used in CPU?Rarely (SRAM, time-borrow)Everywhere!

🔮 D Flip-Flop — The CPU Workhorse

Samples D at exactly ONE instant (rising clock edge). Between edges: Q frozen no matter what D does.

Q(next) = D   —   sampled at posedge clk
// Positive-edge triggered D Flip-Flop module d_ff(input wire clk,d, output reg q); always @(posedge clk) begin q <= d; // Nonblocking! Captures D at rising edge end endmodule // With sync reset and enable module dff_en_rst(input wire clk,rst,en,d, output reg q); always @(posedge clk) begin if (rst) q <= 1'b0; // Sync reset: highest priority else if(en) q <= d; // Load when enabled // else: hold (en=0, rst=0) end endmodule

🔮 Master-Slave DFF — Two-Phase Airlock

  • 1Master latch (E=CLK): When CLK=HIGH → master transparent, captures D. Slave locked.
  • 2Slave latch (E=~CLK): When CLK=LOW → slave transparent, passes master output to Q. Master locked.
  • 3Never both transparent! Data can only advance one stage per half-cycle → Q changes on FALLING EDGE.
Why master-slave solves transparency: Data enters master on rising edge. Data leaves to Q on falling edge. At no point can data race from D all the way to Q in one shot — the two-latch airlock prevents it!
module master_slave_dff(input wire clk,d, output wire q); wire qm, qm_n; d_latch master(.d(d), .en(clk), .q(qm), .q_n(qm_n)); d_latch slave (.d(qm), .en(~clk),.q(q), .q_n()); endmodule

🔮 Setup Time, Hold Time & Metastability

Setup Time (t_su)
D must be stable BEFORE clock edge by at least t_su. Like holding still before a photo is taken. Violation → wrong data captured.
Hold Time (t_h)
D must be stable AFTER clock edge for at least t_h. Like holding still AFTER shutter clicks. Violation → corrupt capture.
Clock-to-Q (t_cq)
Time from clock edge to Q being valid. f_max = 1/(t_cq + t_logic + t_su)
Metastability
If D changes inside setup/hold window → FF enters unstable equilibrium. Output stuck between 0 and 1 for UNPREDICTABLE duration. Eventually resolves but WHEN and to WHAT value are non-deterministic!
CDC (Clock Domain Crossing)
Signal from 100MHz domain sampled by 133MHz FF → no guaranteed phase relationship → metastability risk! Fix: 2-stage synchronizer (2 FFs in series on target clock). MTBF increases exponentially with each added stage.
Common Lab 5 Errors:
✕ q declared wire in FF → always block needs reg
✕ Used = instead of <= in posedge block → Correct most times but race in cascaded FFs
✕ Missing begin/end on multi-line always → Only first statement in posedge!
✕ S=R=1 shows X: NOT a bug! That IS the forbidden state response
✕ Called your DFF a latch: if posedge clk, it is a FF. If always @(*), it is a latch
LAB 6 Registers, Shift Registers & Counters

🔮 Registers

Register = N D flip-flops sharing same clock. Stores N bits of state.

// 8-bit register with load enable module reg8(input clk,ld, input[7:0] d, output reg[7:0] q); always @(posedge clk) if(ld) q <= d; // ld=0: q holds. ld=1: q captures d. Synthesis infers 8 DFFs. endmodule // 8-bit register with sync reset + load enable module reg8_rst(input clk,rst,ld, input[7:0] d, output reg[7:0] q); always @(posedge clk) if (rst) q <= 8'b0; // Sync reset: priority 1 else if(ld) q <= d; // Load: priority 2 endmodule

🔮 Shift Registers — All 4 Types

TypeInputOutputUse CaseKey Operation
SISOSerialSerialDelay lineq <= {q[N-2:0], d_in}
SIPOSerialParallelUART receiver, data collectionShift in, read all bits
PISOParallelSerialUART transmitter, data sendLoad all, shift out one bit
PIPOParallelParallelNormal registerDirect load
UART uses BOTH: Transmitter = PISO (CPU gives parallel byte, shifts out serially). Receiver = SIPO (receives serial bits, assembles parallel byte). Baud rate = shift clock frequency.
// SIPO (Serial In, Parallel Out) — 4-bit module sipo(input clk,rst,d_in, output reg[3:0] q); always @(posedge clk) if(rst) q <= 4'b0; else q <= {q[2:0], d_in}; // Shift left: q3←q2, q2←q1, q1←q0, q0←d_in endmodule // PISO (Parallel In, Serial Out) — sh_ld=0: load, sh_ld=1: shift module piso(input clk,rst,sh_ld, input[3:0] d, output reg[3:0] q, output wire d_out); assign d_out = q[0]; // LSB always output always @(posedge clk) if (rst) q <= 4'b0; else if(!sh_ld) q <= d; // Parallel load else q <= {1'b0, q[3:1]}; // Shift right, MSB=0 endmodule

🔮 Counters — Ripple vs Synchronous

Ripple Counter (Async) ❌
Each FF's Q clocks next FF. Delay = N × t_FF. Shows glitchy intermediate states during ripple. Example: 4-bit going 0111→1000 briefly shows 0110, 0100, 0000. BAD for decoders!
Synchronous Counter ✔️
ALL FFs share same clock. T input computed in parallel. Delay = t_logic + t_FF (constant regardless of N!). Clean, glitch-free transitions. Always use this!
// 4-bit Synchronous Up Counter with Terminal Count (TC) module sync_counter(input clk,rst,en, output reg[3:0] q, output wire tc); assign tc = &q; // Reduction AND: 1 only when ALL bits=1 (q=1111=15) always @(posedge clk) if (rst) q <= 4'b0; else if(en) q <= q + 1; // 1111+1 = 10000, drops MSB → 0000 (wrap!) endmodule
12-bit ripple counter @ 0.6ns/FF: Max freq = 1/(12×0.6ns) = 138.9 MHz. Synchronous counter: freq = 1/(0.6ns + logic_delay). Far faster and cleaner!
LAB 7 Register Files & Finite State Machines (FSM)

🔮 Register File Architecture

RISC-V Standard register file:
32 registers × 32 bits = 1024 FFs total
2 READ ports (ASYNCHRONOUS — combinational, instant, no clock!)
1 WRITE port (SYNCHRONOUS — posedge clk)
x0 (R0) hardwired to 0: writes silently ignored, reads always return 0

How READ works (Combinational)

  • 1Read address (5-bit for 32 regs) → 32:1 MUX
  • 2All register outputs connected to MUX inputs
  • 3Address = select signal → output appears instantly (no clock!)
  • 4Two independent MUXes → two simultaneous reads in one cycle!

How WRITE works (Synchronous)

  • 1Write address → 5-to-32 Decoder → one enable line goes HIGH
  • 2Only that register's WE (write enable) = 1
  • 3On posedge clk: only that register captures write data
MOST TESTED FACT: Register file reads are ASYNCHRONOUS (combinational)! A student claiming "reads wait for clock" is WRONG. Only writes are synchronous. This enables: read operands → ALU computes → write result, all in 1 cycle!
// 4-register 32-bit file with dual read, single write, sync reset module regfile( input clk, rst, we, input[1:0] wr_addr, ra1, ra2, input[31:0] wr_data, output[31:0] rd1, rd2); reg[31:0] regs[0:3]; integer i; initial for(i=0;i<4;i=i+1) regs[i]=32'b0; always @(posedge clk) begin if(rst) for(i=0;i<4;i=i+1) regs[i] <= 32'b0; else if(we && wr_addr != 2'b00) regs[wr_addr] <= wr_data; // R0 write ignored (addr=00 check) end // Async reads (combinational!) assign rd1 = (ra1==2'b00) ? 32'b0 : regs[ra1]; assign rd2 = (ra2==2'b00) ? 32'b0 : regs[ra2]; endmodule

🔮 Moore FSM — 1011 Sequence Detector

FSM Formal Definition: (S, I, O, δ, λ)
S = States  |  I = Inputs  |  O = Outputs
δ = Next-state function: δ(state, input) → next_state
λ = Output function: Moore → λ(state), Mealy → λ(state, input)
Moore Machine
Output = f(state only). Output written INSIDE the state circle. Glitch-free (output stable between edges). May need more states. "Output IN the circle"
Mealy Machine
Output = f(state + input). Output written ON the transition arrow. Faster response (same cycle as input). Fewer states. Can glitch. "Output ON the arrow"

1011 Detector State Table (5 States, Moore)

StateMeaningInput=0 → NextInput=1 → NextOutput
S0IdleS0S10
S1Got "1"S2S10
S2Got "10"S0S30
S3Got "101"S2S40
S4Got "1011" !S2S11
⚠️ Tricky transitions at S4 (MATCH!) — most common exam trap:
S4 + input=1 → S1 (NOT S0!): That trailing '1' could start a NEW "1011". Going to S1 means "I've seen one '1' so far" = correct overlap handling!
S4 + input=0 → S2 (NOT S0!): After "1011" + 0 we have "10110". Last two chars "10" = prefix of 1011! So S2 (got "10") is correct.
Going to S0 on either → MISSES overlapping patterns! Wrong answer!

State Encoding

Binary Encoding
5 states → ⌈log₂5⌉ = 3 FFs (2³=8≥5). Compact but complex decode logic. Unused states (5,6,7) need handling.
One-Hot Encoding
5 states → 5 FFs. Only ONE FF=1 at a time. Simple next-state logic. FPGAs PREFER this (LUTs handle it efficiently). S0=10000, S1=01000, S2=00100, S3=00010, S4=00001
Gray Encoding
Adjacent states differ by 1 bit. S0=000, S1=001, S2=011, S3=010, S4=110. Minimizes transitions → less power, fewer glitches.
// 1011 Moore FSM — Binary encoded (3 FFs) module fsm_1011(input clk,rst,x, output reg z); reg[2:0] state, next; parameter S0=0,S1=1,S2=2,S3=3,S4=4; // State register (sequential) always @(posedge clk) if(rst) state <= S0; else state <= next; // Next-state logic (combinational) always @(*) begin case(state) S0: next = x ? S1 : S0; S1: next = x ? S1 : S2; S2: next = x ? S3 : S0; S3: next = x ? S4 : S2; S4: next = x ? S1 : S2; // Overlap handling! default: next = S0; endcase end // Output logic (Moore: only depends on state) always @(*) z = (state == S4) ? 1'b1 : 1'b0; endmodule
FSM Design 6-Step Flow:
1. Understand: states, inputs, outputs
2. List all (state, input) → (next, output) transitions
3. Draw state diagram
4. Create state table
5. Choose encoding (binary/one-hot/gray)
6. Implement: FFs for state + combinational next-state + output logic
ASSIGN All 26 Assignment Solutions (Complete Verilog)

Q1: NOR Gate

2-input NOR: output HIGH only when BOTH inputs LOW. Truth: 00→1, 01→0, 10→0, 11→0
Solution:
module nor_gate(input wire a,b, output wire y); assign y = ~(a | b); endmodule

Q2: NAND Gate

Output LOW only when BOTH inputs HIGH. Truth: 00→1, 01→1, 10→1, 11→0
Solution:
module nand_gate(input wire a,b, output wire y); assign y = ~(a & b); endmodule

Q3: NOT Gate

Solution:
module not_gate(input wire a, output wire y); assign y = ~a; endmodule

Q4: XOR Gate

Output HIGH when inputs DIFFERENT. Parity detector.
Solution:
module xor_gate(input wire a,b, output wire y); assign y = a ^ b; endmodule

Q5: OR Gate

Solution:
module or_gate(input wire a,b, output wire y); assign y = a | b; endmodule

Q6: AND Gate

Solution:
module and_gate(input wire a,b, output wire y); assign y = a & b; endmodule

Q7: 2:1 MUX using Logic Gates

sel=0→y=a, sel=1→y=b. Y = S'A+SB using AND/OR/NOT.
Solution:
module mux2x1(input wire a,b,sel, output wire y); assign y = (~sel & a) | (sel & b); // Y = S'A + SB endmodule

Q8: 4:1 MUX

sel[1:0]: 00→i0, 01→i1, 10→i2, 11→i3.
Solution:
module mux4x1(input wire i0,i1,i2,i3, input[1:0] sel, output wire y); assign y = (~sel[1]&~sel[0]&i0) | (~sel[1]&sel[0]&i1) | (sel[1]&~sel[0]&i2) | (sel[1]&sel[0]&i3); endmodule

Q9: 1:2 DEMUX

Solution:
module demux1x2(input wire i,sel, output wire y0,y1); assign y0=i&~sel; assign y1=i&sel; endmodule

Q10: 1:4 DEMUX

Solution:
module demux1x4(input wire i, input[1:0] sel, output wire y0,y1,y2,y3); assign y0=i&~sel[1]&~sel[0]; assign y1=i&~sel[1]&sel[0]; assign y2=i& sel[1]&~sel[0]; assign y3=i& sel[1]&sel[0]; endmodule

Q11: Half Adder

Solution:
module half_adder(input wire a,b, output wire sum,cout); assign sum=a^b; assign cout=a&b; endmodule

Q12: Full Adder

Solution:
module full_adder(input wire a,b,cin, output wire sum,cout); assign sum=a^b^cin; assign cout=(a&b)|(cin&(a^b)); endmodule

Q13: 4-bit Ripple Carry Adder

Solution:
module rca_4bit(input[3:0] a,b, input cin, output[3:0] s, output cout); wire c1,c2,c3; full_adder fa0(.a(a[0]),.b(b[0]),.cin(cin),.sum(s[0]),.cout(c1)); full_adder fa1(.a(a[1]),.b(b[1]),.cin(c1),.sum(s[1]),.cout(c2)); full_adder fa2(.a(a[2]),.b(b[2]),.cin(c2),.sum(s[2]),.cout(c3)); full_adder fa3(.a(a[3]),.b(b[3]),.cin(c3),.sum(s[3]),.cout(cout)); endmodule

Q14: Sign Extender 4-bit → 8-bit

Preserve signed value when widening. MSB copies fill upper bits.
Solution:
module sign_ext(input[3:0] a, output[7:0] y); assign y = {{4{a[3]}}, a}; // a[3]=0 (positive): 0000xxxx. a[3]=1 (negative): 1111xxxx endmodule

Q15: Adder-Subtractor

Solution:
module adder_sub(input[3:0] a,b, input m, output[3:0] s, output cout); wire[3:0] bx=b^{4{m}}; rca_4bit rca(.a(a),.b(bx),.cin(m),.s(s),.cout(cout)); endmodule

Q16: Two's Complement Negator

Solution:
module twos_comp(input[7:0] a, output[7:0] y); assign y = ~a + 8'd1; // Flip all bits, add 1 endmodule

Q17: D Latch

Solution:
module d_latch(input wire d,en, output reg q,q_n); always @(*) if(en) begin q<=d; q_n<=~d; end endmodule

Q18: D Flip-Flop with Enable & Reset

Solution:
module dff_en(input wire clk,rst,en,d, output reg q); always @(posedge clk) if (rst) q<=1'b0; else if(en) q<=d; endmodule

Q19: Master-Slave DFF

Q changes on FALLING edge. Built from 2 d_latch instances.
Solution:
module ms_dff(input wire clk,d, output wire q); wire qm,qmn; d_latch master(.d(d), .en(clk), .q(qm), .q_n(qmn)); d_latch slave (.d(qm), .en(~clk),.q(q), .q_n()); endmodule

Q20: 8-bit Register with Load Enable

Solution:
module reg8(input clk,ld, input[7:0] d, output reg[7:0] q); always @(posedge clk) if(ld) q<=d; endmodule

Q21: 8-bit Register with Sync Reset

Solution:
module reg8_rst(input clk,rst,ld, input[7:0] d, output reg[7:0] q); always @(posedge clk) if(rst) q<=8'b0; else if(ld) q<=d; endmodule

Q22: 4-bit Sync Up Counter

Solution:
module counter4(input clk,rst,en, output reg[3:0] q, output wire tc); assign tc=(&q); always @(posedge clk) if(rst) q<=0; else if(en) q<=q+1; endmodule

Q23: SIPO Shift Register

Solution:
module sipo(input clk,rst,d_in, output reg[3:0] q); always @(posedge clk) if(rst) q<=0; else q<={q[2:0],d_in}; endmodule

Q24: PISO Shift Register

Solution:
module piso(input clk,rst,sh_ld, input[3:0] d, output reg[3:0] q, output wire d_out); assign d_out=q[0]; always @(posedge clk) if(rst) q<=0; else if(!sh_ld) q<=d; else q<={1'b0,q[3:1]}; endmodule

Q25: 4-Register File (Dual Read)

Solution:
module regfile(input clk,we, input[1:0] wa,ra1,ra2, input[31:0] wd, output[31:0] rd1,rd2); reg[31:0] r[0:3]; integer i; initial for(i=0;i<4;i=i+1) r[i]=0; always @(posedge clk) if(we) r[wa]<=wd; assign rd1=r[ra1]; assign rd2=r[ra2]; endmodule

Q26: Register File + Sync Reset + Hardwired R0=0

R0 writes silently ignored. Reads from R0 always return 0 (RISC-V x0 behavior).
Solution:
module regfile_x0(input clk,rst,we, input[1:0] wa,ra1,ra2, input[31:0] wd, output[31:0] rd1,rd2); reg[31:0] r[0:3]; integer k; initial for(k=0;k<4;k=k+1) r[k]=0; always @(posedge clk) begin if(rst) for(k=0;k<4;k=k+1) r[k]<=0; else if(we && wa!=2'b00) r[wa]<=wd; // R0 write ignored! end assign rd1=(ra1==2'b00)?32'b0:r[ra1]; // R0 read = always 0 assign rd2=(ra2==2'b00)?32'b0:r[ra2]; endmodule
QUIZ All 35 Quiz Questions & Complete Answers

❓ All 35 Quiz Questions with Answers

Q1 — What is the output of a 2-input AND gate when A=1, B=0?
✔️ 0  (AND is 1 ONLY when BOTH inputs are 1)
Q2 — What is the output of a 2-input OR gate when A=0, B=0?
✔️ 0  (OR is 0 ONLY when BOTH inputs are 0)
Q3 — What is the output of a NOT gate when A=1?
✔️ 0
Q4 — Which gate is called the Universal Gate? Why?
✔️ NAND (and NOR). Any Boolean function can be built using only NAND (or only NOR) gates.
NOT=NAND(A,A). AND=NOT(NAND(A,B)). OR=NAND(NOT A, NOT B). All 3 primitives built → universal!
Q5 — DeMorgan's First Theorem: (A·B)' = ?
✔️ A' + B'  (NAND = OR with inverted inputs)
Q6 — DeMorgan's Second Theorem: (A+B)' = ?
✔️ A' · B'  (NOR = AND with inverted inputs)
Q7 — What does SOP stand for? Give example.
✔️ Sum Of Products. F = AB + A'C + BC (OR of AND terms)
Q8 — What is a minterm?
✔️ AND term containing every variable (complemented if 0, as-is if 1) for a row where F=1.
A=1,B=0,C=1: minterm m5 = AB'C  (binary 101 = 5)
Q9 — Why must K-map use Gray code order?
✔️ Adjacent cells must differ by exactly 1 bit for the combining theorem to work.
Natural binary: 01 next to 10 = 2-bit difference, NOT adjacent logically. Gray code: 01,11,10 each differ by 1 bit.
Q10 — What is the maximum group size in a 3-variable K-map?
✔️ 8 (= 2^3). A group of 8 covers ALL cells → F = 1
Q11 — What is a Prime Implicant (PI)?
✔️ A PI is the LARGEST possible group of 1s that cannot be enlarged further (while staying a power-of-2 rectangle).
Q12 — What is an Essential Prime Implicant (EPI)?
✔️ A PI that covers at least one "1" that no other PI covers. MUST be in every minimal cover.
Q13 — Can groups overlap in a K-map?
✔️ YES! Overlapping is allowed and often necessary to make each group as large as possible.
Q14 — What is the difference between wire and reg in Verilog?
✔️ wire: net/connection, driven by assign or module output, for combinational logic.
reg: procedural variable, used inside always blocks. Despite name, NOT necessarily a hardware register!
Q15 — What operator is used for 2:1 MUX behavior in one line?
✔️ Ternary operator: assign y = sel ? b : a;
Q16 — What happens if you forget "default" in a case statement?
✔️ Latch is inferred! Verilog assumes "hold previous value" for unspecified cases = storage element = latch!
Q17 — What is the Full Adder equation for Cout?
✔️ Cout = AB + Cin(A⊕B) = AB + ACin + BCin
Q18 — Why is Ripple Carry Adder slow?
✔️ Carry must propagate serially through every FA stage. N-bit RCA delay = N × t_FA. For 64-bit: 128 gate delays!
Q19 — Overflow flag (OF) formula for signed addition?
✔️ OF = C_in_MSB ⊕ C_out_MSB = C(n-1) ⊕ Cout
XOR of carry INTO MSB and carry OUT of MSB. If they disagree, sign bit was corrupted by carry = overflow!
Q20 — What is the forbidden state of SR latch? What happens?
✔️ S=R=1. Both outputs Q and Q' are forced to 0 (violating Q≠Q'). On release (S=R=0): race condition → non-deterministic output!
Q21 — What is the difference between a latch and a flip-flop?
✔️ Latch: level-triggered. Transparent while enable=HIGH. Output follows input during window.
Flip-flop: edge-triggered. Samples input at ONE instant (clock edge). Output frozen between edges.
Q22 — What does <= (nonblocking) do in Verilog?
✔️ Schedules assignment at END of time step. All RHS evaluated first, then all LHS updated. Used in posedge always blocks to prevent race conditions in cascaded flip-flops.
Q23 — What is setup time violation?
✔️ D changes LESS than t_su before clock edge → flip-flop may capture wrong value or go metastable.
Q24 — What is metastability?
✔️ FF enters undefined state between 0 and 1 when D changes inside setup/hold window. Output takes unpredictable extra time to resolve. In CDC: synchronizer adds latency but reduces metastability probability exponentially.
Q25 — What does SIPO stand for? Name one application.
✔️ Serial-In Parallel-Out. Application: UART receiver — collects serial bits one at a time, outputs all 8 bits in parallel to the CPU.
Q26 — Difference between Synchronous and Ripple counter?
✔️ Ripple: each FF clocks the next → glitchy, delay=N×t_FF.
Synchronous: all FFs share one clock → clean, delay=t_logic+t_FF (constant for any N).
Q27 — What does "terminal count (TC)" in a counter mean?
✔️ TC=1 when counter reaches maximum value (1111 for 4-bit = 15). Can cascade: TC of stage-1 = EN of stage-2 to build larger counter.
Q28 — In register file, are reads synchronous or asynchronous?
✔️ ASYNCHRONOUS (combinational). Reads are just MUX operations — no clock needed. Outputs appear instantly when address changes. Only WRITES are synchronous (posedge clk).
Q29 — Why is RISC-V register x0 (R0) hardwired to zero?
✔️ Constant 0 is needed very frequently (initialize, compare, NOP via ADD x0,x0,x0). Hardwiring saves one read port to a constant-0 generator. Writes to x0 are silently ignored.
Q30 — Moore vs Mealy: where is output written?
✔️ Moore: output written INSIDE state circle (f(state) only). Output changes only on state transition.
Mealy: output written ON transition ARROW (f(state + input)). Output can change mid-cycle when input changes!
Q31 — What is the FSM for a 1011 sequence detector: how many states?
✔️ 5 states (Moore): S0=idle, S1=got1, S2=got10, S3=got101, S4=got1011(output=1)
Q32 — 1011 detector: After detecting "1011", input is 1. Next state?
✔️ S1 (NOT S0!). That trailing "1" could be the start of a new "1011". Overlap must be handled!
Q33 — What is one-hot encoding? Advantage?
✔️ N states → N FFs, only ONE is 1 at a time. Advantage: simple next-state logic (each state transition is just an OR), preferred by FPGAs which have abundant flip-flops.
Q34 — What is two's complement of 8-bit 0 (00000000)?
✔️ 00000000 → ~(00000000) = 11111111, +1 = 100000000. Drop carry → 00000000. Zero is its own two's complement!
Q35 — For 4-bit two's complement: range is −8 to +7. What is the two's complement representation of −8?
✔️ 1000. MSB=1 (negative), value = −8 (only +8 doesn't fit in positive range since max=+7). ~(1000)=0111, +1=1000 → still 1000! −8 is its own two's complement (no positive counterpart in 4-bit)!