Practice exercises
Solve real digital design problems against hidden test cases. Three modalities, three difficulties, one waveform that has to match.
Build from zero
Read the spec, draft the entity body, prove it against the test cases.
AND gate
Two-input AND gate.
4-bit equality comparator
Output high when a equals b.
2-to-4 decoder
One-hot output for 2-bit input.
Half-adder
Two inputs, two outputs — write the sum and carry-out from scratch.
Half-subtractor
Compute a − b on single bits — output diff and borrow.
3-input majority voter
Output the majority of three single-bit inputs.
2-to-1 multiplexer
Pick a or b based on sel.
4-to-1 multiplexer
Select one of four inputs by 2-bit sel.
NAND gate
Two-input NAND.
NOR gate
Two-input NOR.
NOT gate
Single-input inverter.
OR gate
Two-input OR gate.
Even parity generator
4-bit input — output 1 if odd number of 1s (so total becomes even).
XNOR gate
Two-input exclusive-NOR.
XOR gate
Two-input exclusive-OR.
4-to-2 priority encoder
Encode highest active bit (one-hot in) into 2-bit y.
4-bit adder
4-bit a + b + cin → sum (4) and cout.
Divide-by-4 clock
Generate a clock at clk/4.
Greater/equal/less comparator
4-bit unsigned a vs b — three flag outputs.
4-bit synchronous counter
Increments q each rising edge; async reset.
Rising-edge detector
Outputs a 1-clock pulse on every 0→1 transition of d.
Full-adder
a + b + cin → sum, cout.
3-bit Gray code
Convert 3-bit binary to Gray code.
Load register (4-bit)
Loads d into q when load=1 on rising edge.
4-to-1 mux with enable
Output 0 when en=0; otherwise route input by sel.
One-hot to binary
Convert a 4-bit one-hot input to 2-bit binary.
8-bit left shift register
Shift left on each rising clock edge; serial input din.
T flip-flop
Toggles q when t=1 on a rising edge.
Toggle register with enable
Toggle q each cycle when en=1.
4-bit up/down counter
+1 when dir=1, −1 when dir=0; async reset.
8-bit ALU
4-op ALU: add / sub / and / or selected by 2-bit op.
Round-robin arbiter (4)
Grant one of four requests in rotating priority.
CORDIC iteration step
Single CORDIC step: x' = x ± y, y' = y ∓ x, signed by dir.
CRC-8 serial accumulator
Update an 8-bit CRC by feeding one bit per clock; reset to 0.
Button debouncer
Output flips only after the input has been stable for N cycles.
FIFO empty/full flags
Track count of pushes vs pops for a depth-4 queue; output flags only.
Hamming(7,4) encoder
Append three parity bits to a 4-bit data word.
8-bit LFSR
Maximal-length LFSR with taps at 8,6,5,4. Reset to 0xFF.
Manchester encoder
For each bit period emit two half-bits — '01' or '10'.
4-bit unsigned multiplier
a × b → 8-bit product. Combinational.
PWM generator (4-bit duty)
Output high while a 4-bit free-running counter is below duty.
SPI master shift
Generate sclk and shift the MSB of a register on mosi.
4-word stack flags
Track push/pop on a depth-4 stack; expose full/empty.
Traffic-light FSM
3-state traffic light: red → green → yellow → red.
UART receiver FSM
Idle → start → data → stop, controlled by rx serial input.
Find and fix the bug
A working-ish design with a planted defect — find it and patch the architecture.
2-bit add — no carry chain
The carry between bits is dropped.
3-input AND — input dropped
Output ignores c.
AND that's an OR
Author wrote `or` instead of `and`.
Comparator missing a bit
Compares only 3 of 4 bits.
Decoder — missing line
One output line never asserts.
Encoder — wrong priority
Lower bit takes precedence over higher.
Equality with xor
`eq` is high when bits differ — should use xnor.
Full-adder — fix the carry
Sum is right, carry-out is wrong. Patch the architecture.
Mux — default '1' instead of input
Returns '1' for sel=1 instead of b.
Mux — wrong default
sel=0 returns b instead of a.
Mux 2:1 — sel inverted
sel chooses the wrong input. Fix it.
NOR via AND
Author DeMorganized incorrectly.
Inverter that's a buffer
`y <= a` should be `not a`.
Parity using nand
Author used nand instead of xor.
Half-adder — sum & cout swapped
sum is on cout and vice-versa.
Adder — sign extension
Padding with zeros where signed extension was needed.
ALU — op missing
`xor` op decodes to zeros — fix the case.
Async reset wired sync
Process sensitivity list excludes reset.
BCD decoder — digit dropped
Digit 7 produces zeros.
Comparator — bad equal
`eq` is always 0.
Counter — reset ignored
Reset never zeroes the counter.
Divider by 8 — meant 4
Counter compare uses wrong constant.
Edge detector — falls instead of rises
Pulses on 1→0 transitions, not 0→1.
FSM — unreachable state
One transition guard never fires.
Gray code — two bits flip
Two bits flip on adjacent transitions.
Load register — wrong edge
Loads on falling edge instead of rising.
4:1 mux — sel only 1 bit
Top half of inputs is unreachable.
Shift register — wrong direction
Should shift left, shifts right.
T-FF ignores enable
Toggles every cycle regardless of t.
Up/down — dir ignored
Always counts up.
ALU — wrong overflow flag
Reads bit 6 instead of bit 7.
Arbiter — starves req3
Priority never rotates to req3.
Booth — wrong shift
Logical instead of arithmetic shift.
CORDIC — rotation reversed
Rotates clockwise instead of CCW.
CRC — wrong polynomial
Author used 0x07 instead of the spec 0x1D.
FIFO pointer — wrap off
Wrap drops one slot.
Hamming(7,4) — parity swap
Two parity bits are swapped.
Handshake — race condition
ack rises before req is stable.
LFSR — wrong taps
Sequence stays short — fix tap polynomial.
Manchester — half-bit swap
Encoder emits '10' for 0 and '01' for 1 (inverted).
Multiplier — wrong extension
Sign-extends an unsigned operand.
PWM — off-by-one
Duty cycle is 1 too short.
SPI — wrong sample edge
Samples on rising instead of falling.
Stack — pop off-by-one
Empty asserts one cycle late.
UART — start-bit miss
FSM samples start bit at wrong time.
Fill in the missing piece
The skeleton is wired; one block is missing. Implement it.
AND body — fill
Implement the single output assignment.
Tri-state buffer — fill
Output a when en=1, otherwise 'Z'.
Comparator (eq) — fill
Implement the equality comparison line.
4-bit counter — fill the gap
Skeleton is wired; write the single increment line.
Decoder Y0 — fill
Compute the y(0) line.
Half-adder — write cout only
sum is given; you write cout.
Half-adder — write sum only
cout is given; you write sum.
2:1 mux output — fill
Implement the y assignment.
NAND body — fill
Single output assignment.
NOR body — fill
Single output assignment.
NOT body — fill
Implement the inverter.
OR body — fill
Single output assignment.
Parity body — fill
Implement the parity expression.
XNOR body — fill
Single output assignment.
XOR body — fill
Single output assignment.
Adder carry — fill
Connect c1 between bit-0 and bit-1 adders.
BCD digit 5 — fill
Provide the 7-segment pattern for the digit 5.
Divider — toggle line
Toggle clk_out on counter overflow.
Comparator gt — fill
Implement the greater-than line.
Counter wrap — fill
Implement the wrap-around case.
Edge pulse — fill
Compute pulse from d_curr and d_prev.
FSM transition — fill
Pick the next state from current + input.
Gray-code next — fill
Compute next Gray value.
Load register — branch
Implement the load=1 branch.
4:1 mux block — fill
Implement the 4:1 mux selection.
Priority encoder default
Cover the all-zero input case.
Shift register — fill bit
Choose the bit shifted in (din vs '0').
T-FF toggle — fill
Compute next q given t and current q.
Toggle reg feedback — fill
Compute next q from current q when en=1.
Up/down — direction logic
Choose ±1 based on dir.
ALU shift unit — fill
Implement left shift by sh bits.
Arbiter grant rotation
Pick next grant in round-robin order.
Booth step — fill
Conditional add/sub based on Booth bits.
CORDIC step (x)
Implement x' = x + dir*y.
CRC register update
Implement the CRC step (xor + shift).
FIFO read pointer
Increment the read pointer when pop && !empty.
Hamming syndrome
Compute the 3-bit syndrome of a code word.
LFSR feedback tap
Compute the feedback bit.
Manchester transition
Emit half-bit pair for the input bit.
PWM comparator — fill
Compare counter against duty.
Round-robin token
Rotate the token left each cycle.
SPI edge select — fill
Sample on falling sclk only.
Stack pop — fill
Decrement sp on pop && !empty.
Traffic FSM table — fill
Implement the next-state table.
UART sample point
Pulse sample_now when bit-counter mid-bit.