04 Combinational-Circuit Building Blocks

This chapter presents the standard combinational building blocks used everywhere in digital design. Multiplexers are covered in depth, including their use for implementing arbitrary logic functions via Shannon's expansion theorem. Decoders (including demultiplexers) and encoders (binary and priority) are discussed as fundamental address-translation and selection circuits. Code converters (e.g., BCD to 7-segment display) and arithmetic comparison circuits (magnitude comparators) are also presented. The major Verilog section introduces the conditional operator (?:), if-else statements, the case statement, for loops, the full set of Verilog operators, the generate construct, and tasks/functions — essentially all the Verilog constructs needed for combinational circuit description.

Multiplexers Shannon's Expansion Decoders / Demux Encoders / Priority Code Converters Comparators Verilog if-else / case Verilog for / generate
Decoder vs demultiplexer — interactive demo

A decoder takes an $n$-bit input and asserts exactly one of its $2^n$ outputs. A demultiplexer (demux) takes one data line plus an $n$-bit select and routes the data to one of $2^n$ outputs (the others stay at 0). The two circuits share an internal structure — a demux is just a decoder whose data-line gates each output.

2-to-4 Decoder

Input $w_1 w_0$:
y₀ = 1 when 00 y₁ = 1 when 01 y₂ = 1 when 10 y₃ = 1 when 11

The output corresponding to the binary value of the input is high; all others are low. Equivalently $y_i = m_i$ (minterm $i$).

1-to-4 Demultiplexer

A demux equals a decoder whose output is gated by a data input: $y_i = D \cdot \text{(decode of select)}_i$.

Data $D$: D = on
Select $s_1 s_0$:
y₀ ← D when 00 y₁ ← D when 01 y₂ ← D when 10 y₃ ← D when 11

Toggle D to off and watch the selected output drop to 0 — the demux only routes the data bit, it doesn't generate one. With $D=1$ the demux behaves identically to the decoder above.

4-to-1 Multiplexer (the inverse of a demux)

A multiplexer reverses the demux: it has $2^n$ data inputs $D_0, D_1, D_2, D_3$, an $n$-bit select, and a single output $y$ which equals whichever data line the select points to. $y = D_{(\text{select})}$.

Data inputs (toggle each):
Select $s_1 s_0$:
D₀ D₁ D₂ D₃
y = D(sel)

Gold cells = data inputs currently 1. The cell with the green outline is the one currently routed through. The output $y$ takes that cell's value: if the outlined cell is gold (1) the output is 1; if dim (0) the output is 0.

Three-way comparison (decoder, demultiplexer, multiplexer):

DecoderDemultiplexerMultiplexer
Direction$n$ → $2^n$$1 + n$ → $2^n$ (fan-out)$2^n + n$ → 1 (fan-in)
Inputs$n$ select bits1 data + $n$ select$2^n$ data + $n$ select
Outputs$2^n$ minterm signals$2^n$ (one carries data, rest 0)1 (carries selected input)
Behavior$y_i = 1$ iff input $= i$$y_i = D$ iff sel $= i$, else 0$y = D_{\text{sel}}$
Boolean form$y_i = m_i(s)$$y_i = D \cdot m_i(s)$$y = \sum_i D_i \cdot m_i(s)$
Use caseaddress decode, minterm generation, ROM rowsrouting one signal to many destinations (clock distribution, write-enable)selecting one of many sources (bus arbitration, ALU operand pick, function realization via Shannon expansion)

Duality. A demux and a MUX are inverse circuits — connect them back-to-back with the same select, and the data on $D_i$ at the demux input reappears unchanged at the MUX output. This is the basis of time-division multiplexing: many channels share one wire by alternating selects.

Decoder vs MUX. A decoder generates all $2^n$ minterms; a MUX uses minterms internally to select among inputs. Equivalently: a MUX is built from a decoder + AND gates + a big OR. So decoders are the building block; MUXes and demuxes are decoder-based variants — read-direction (MUX, $2^n$→1) vs. write-direction (demux, 1→$2^n$).

Shannon's Expansion — cheat sheet

Shannon's expansion theorem decomposes any Boolean function on a chosen variable into two simpler "cofactor" pieces. It's the algebraic foundation of MUX-based logic synthesis, BDDs, and recursive function analysis.

Theorem (SOP form):

$f(x_1, x_2, \ldots, x_n) \;=\; \overline{x_1}\cdot f(0, x_2, \ldots, x_n) \;+\; x_1 \cdot f(1, x_2, \ldots, x_n)$

Theorem (POS / dual form):

$f(x_1, x_2, \ldots, x_n) \;=\; \bigl(x_1 + f(0, x_2, \ldots, x_n)\bigr) \cdot \bigl(\overline{x_1} + f(1, x_2, \ldots, x_n)\bigr)$

The two pieces are called the cofactors of $f$ with respect to $x_1$:

NotationMeaning
$f_{x_1=0}$,   $f|_{x_1=0}$,   $f_0$substitute $x_1=0$ everywhere in $f$ → 0-cofactor
$f_{x_1=1}$,   $f|_{x_1=1}$,   $f_1$substitute $x_1=1$ everywhere in $f$ → 1-cofactor

$\boxed{\,f \;=\; \overline{x_1}\,f_0 \;+\; x_1\,f_1\,}$

Connection to a 2-to-1 MUX — that's literally MUX2 with select $= x_1$, data inputs $f_0$ and $f_1$:

f₀ f₁ x₁ MUX2 0 1 f

Recursive application — break a function down to a tree of MUXes:

$f \;=\; \overline{x_1}\bigl[\overline{x_2} f_{00} + x_2 f_{01}\bigr] + x_1\bigl[\overline{x_2} f_{10} + x_2 f_{11}\bigr]$

Each cofactor is itself expanded on the next variable, producing a binary tree with $2^n$ leaves (constants 0 or 1, equal to the truth-table values). This is a binary decision diagram (BDD) before any reduction.

Worked example. $f(w_1, w_2, w_3) = w_1 w_2 + \overline{w_1} w_3$. Expand on $w_1$:

  • $f_0 = f|_{w_1 = 0} = (0)\cdot w_2 + (1)\cdot w_3 = w_3$
  • $f_1 = f|_{w_1 = 1} = (1)\cdot w_2 + (0)\cdot w_3 = w_2$
  • So $f = \overline{w_1}\,w_3 + w_1\,w_2$ — implementable with a 2-to-1 MUX: select $= w_1$, $D_0 = w_3$, $D_1 = w_2$. The original function vanishes into a single MUX with two raw-literal data inputs.

Useful identities & properties:

IdentityNote
$f = \overline{x}\,f_0 + x\,f_1$canonical SOP form
$f = (x + f_0)(\overline{x} + f_1)$canonical POS form (the dual)
$f_0 \cdot f_1 \neq 0 \Rightarrow$ Boolean diff$\partial f / \partial x = f_0 \oplus f_1$ (XOR of cofactors)
$f_0 = f_1 \iff f$ is independent of $x$used to detect "vacuous" variables
$(f \cdot g)_{x=v} = f_{x=v} \cdot g_{x=v}$cofactoring distributes over AND, OR, NOT, XOR

Where it shows up:

  • MUX-based synthesis — implement any Boolean function with a tree of 2-to-1 MUXes by recursive Shannon expansion.
  • BDDs / ROBDDs — every node of a BDD is a Shannon-expansion split on one variable. Variable ordering choice = which variable to expand at each level.
  • Functional decomposition — to factor $f(x, y, \ldots) = g(h(x, \ldots), y, \ldots)$, examine cofactors and look for repeated patterns.
  • Boolean differentiation — $\partial f / \partial x = f_0 \oplus f_1$. A variable is sensitized iff this is true; the basis of test-pattern generation in DFT.
  • SAT solvers — DPLL search algorithm performs Shannon expansion on each chosen literal, branching the search tree.

Quick recipe: to express $f$ with a 2-to-1 MUX selected by $x_i$ — compute $f_0$ and $f_1$ by substitution, wire them as the two data inputs, wire $x_i$ as select. To go further (tree of MUXes), expand each cofactor on the next variable. The recursion bottoms out at the constants 0 and 1.

Encoder ↔ Decoder — the inverse pair (back-to-back co-working)

An encoder turns a one-of-$2^n$ one-hot signal into an $n$-bit binary index. A decoder does the reverse: it turns an $n$-bit binary index back into a one-hot signal. Connected back-to-back with the same width, they form an identity on valid one-hot inputs — exactly like a demux/MUX pair, but in the opposite direction.

$\text{one-hot}\;\xrightarrow{\;\text{encoder}\;}\;\text{binary index}\;\xrightarrow{\;\text{decoder}\;}\;\text{one-hot}$

Side-by-side block diagram (4-to-2 encoder → 2-to-4 decoder):

W₃ W₂ W₁ W₀ 4-to-2 Encoder y₁ y₀ 2-bit binary 2-to-4 Decoder Y₃ Y₂ Y₁ Y₀ one-hot in (compress) one-hot out (expand) narrow link

Truth-table round-trip — encoder squeezes 4 wires into 2; decoder expands them back. On valid one-hot inputs the round-trip is identity:

W₃W₂W₁W₀ (one-hot) y₁y₀ (encoded) Y₃Y₂Y₁Y₀ (decoded) match?
0001000001
0010010010
0100100100
1000111000
0000 (invalid)000001 (wrong!)×

Back-to-back chain with a valid gate — the row in red shows why a plain encoder output is ambiguous: input 0001 and input 0000 both produce y = 00. To distinguish them, the encoder asserts an extra valid bit (= OR of all one-hot inputs), and the decoder uses it as enable so its outputs stay 0000 when no input was asserted:

Encoder 4→2 W[3:0] /4 y[1:0] /2 valid Decoder 2→4 W En Y[3:0] /4 narrow link: 2 + 1 wires instead of 4

Where this pair shows up:

  • Address compression on a bus. A wide one-hot signal (say 16 device-request lines) is encoded to 4 bits, transmitted across a backplane, then decoded back at the destination. Saves wires and routing area.
  • Interrupt vector. Many interrupt-request lines (one-hot) are encoded into a numeric vector index by a priority encoder; the CPU later decodes that index to look up the service routine — same encoder/decoder pair, with priority resolution added.
  • Memory-mapped I/O. Address bits travel as a binary index; a chip-select decoder turns them back into one-hot enables for individual peripherals or memory banks.
  • Bus arbitration. A priority encoder picks the winning request; a decoder re-asserts the matching grant line back to the requester.

Verilog — minimal back-to-back pair:

module binary_encoder_4to2(input [3:0] W, output reg [1:0] y, output valid);
  assign valid = |W;            // 1 if any input is asserted
  always @(*) case (W)
    4'b0001: y = 2'b00;
    4'b0010: y = 2'b01;
    4'b0100: y = 2'b10;
    4'b1000: y = 2'b11;
    default: y = 2'b00;         // ambiguous without 'valid'
  endcase
endmodule

module dec2to4(input [1:0] W, input En, output reg [3:0] Y);
  always @(*) case ({En, W})
    3'b100: Y = 4'b0001;
    3'b101: Y = 4'b0010;
    3'b110: Y = 4'b0100;
    3'b111: Y = 4'b1000;
    default: Y = 4'b0000;
  endcase
endmodule

module enc_dec_link(input [3:0] W, output [3:0] Y);
  wire [1:0] y;
  wire       valid;
  binary_encoder_4to2 enc(.W(W), .y(y), .valid(valid));
  dec2to4             dec(.W(y), .En(valid), .Y(Y));
endmodule

Footnote on the valid output. A plain (non-priority) encoder cannot tell "no input asserted" from "input 0 asserted" — both produce y = 00. The valid = OR-of-all-inputs bit fixes this: it gates the downstream decoder so the round-trip is correct even when no source line is active. For a priority encoder, valid doubles as the "any request pending" signal feeding the arbiter.

Multiplexer ↔ Demultiplexer — the inverse pair (time-division multiplexing)

A multiplexer (MUX) picks one of $2^n$ data sources and routes it to a single output. A demultiplexer (DEMUX) does the reverse: it takes one data input and steers it to one of $2^n$ outputs (the rest stay at 0). Connected back-to-back with a shared select, MUX→DEMUX makes a perfect time-division multiplexed (TDM) link: many channels share one wire, alternating in time.

$D_0 \ldots D_{2^n-1}\;\xrightarrow{\;\text{MUX}\;}\;\text{1 wire}\;\xrightarrow{\;\text{DEMUX}\;}\;Y_0 \ldots Y_{2^n-1}$

Side-by-side block diagram (4-to-1 MUX → 1-to-4 DEMUX):

D₃ D₂ D₁ D₀ MUX 4→1 shared 1-bit wire DEMUX 1→4 Y₃ Y₂ Y₁ Y₀ shared sel[1:0]

Round-trip table — with the same select on both sides, $Y_i = D_i$ for the selected slot, all other $Y_j = 0$ (the demux floor):

sel MUX out (= shared wire) DEMUX outputs Y₃Y₂Y₁Y₀ live channel
00D₀000 D₀channel 0
01D₁00 D₁ 0channel 1
10D₂0 D₂ 00channel 2
11D₃D₃ 000channel 3

TDM timing — rotate sel through 00 → 01 → 10 → 11 in successive time slots; each source $D_i$ owns the wire for one slot, and the demux drops it onto the matching $Y_i$:

time → sel 00 01 10 11 wire D₀ D₁ D₂ D₃ Y₀ D₀ Y₁ D₁ Y₂ D₂ Y₃ D₃

Where this pair shows up:

  • Time-division multiplexing (TDM). Multiple low-rate channels share one high-rate wire. The transmitter MUXes; the receiver DEMUXes with the same rotating select. Used in T1/E1 telephony, serial UART framing, I²S audio.
  • ADC channel sharing. One physical ADC samples many sensor lines via an analog MUX; the digital side DEMUXes the samples into per-channel buffers.
  • Memory bus arbitration. Several masters share one memory data bus through a MUX; the destination registers behave as a DEMUX, capturing the word into the correct latch on the matching cycle.
  • Pipeline operand routing. ALUs use a MUX to pick the operand source (register file, immediate, forwarded value); a DEMUX-shaped write-enable network steers the result back to the right register.

Verilog — minimal back-to-back pair:

module mux4to1(input [3:0] D, input [1:0] sel, output reg out);
  always @(*) case (sel)
    2'b00: out = D[0];
    2'b01: out = D[1];
    2'b10: out = D[2];
    2'b11: out = D[3];
  endcase
endmodule

module demux1to4(input in, input [1:0] sel, output reg [3:0] Y);
  always @(*) begin
    Y = 4'b0000;
    case (sel)
      2'b00: Y[0] = in;
      2'b01: Y[1] = in;
      2'b10: Y[2] = in;
      2'b11: Y[3] = in;
    endcase
  end
endmodule

module tdm_link(input [3:0] D, input [1:0] sel, output [3:0] Y);
  wire bus;                              // the shared 1-bit wire
  mux4to1   tx(.D(D),  .sel(sel), .out(bus));
  demux1to4 rx(.in(bus), .sel(sel), .Y(Y));
endmodule

Note. The MUX/DEMUX pair carries data (one wire, value-bearing); the encoder/decoder pair carries an index (binary number, position-bearing). Both pairs are inverse circuits, but they operate on different abstractions: data routing vs. address translation.

4.1EasyTier 1?R
Show how $f(w_1,w_2,w_3) = \sum m(0,2,3,4,5,7)$ can be implemented using a 3-to-8 decoder and a single OR gate.
4.2MediumTier 1?R
Use Shannon's expansion with respect to variable $w_1$ to implement $f(w_1,w_2,w_3) = \sum m(0,2,3,6)$ using a 2-to-1 multiplexer and any necessary gates.
Background — Shannon's expansion: full SOP and POS walk-through

Here's a concrete walk-through using a 3-variable function.

Setup

Take $F(A, B, C) = A + BC$ with 3 variables ($n = 3$), so there are $2^3 = 8$ minterms ($m_0$ through $m_7$). [cs.ucr]

Truth Table

Evaluate $F$ for every input combination: [cs.ucr]

$i$ABCMinterm $m_i$$F(A,B,C)$
0000$A'B'C'$0
1001$A'B'C$0
2010$A'BC'$0
3011$A'BC$1
4100$AB'C'$1
5101$AB'C$1
6110$ABC'$1
7111$ABC$1

Applying the Formula

$$F = \sum_{i=0}^{7} m_i \cdot F(\text{inputs for } m_i)$$

Only minterms where $F = 1$ survive (multiplying by 0 eliminates the rest): [caslab.ee.ncku.edu]

$$F(A,B,C) = m_3 \cdot 1 + m_4 \cdot 1 + m_5 \cdot 1 + m_6 \cdot 1 + m_7 \cdot 1$$

Substituting the actual minterm products: [cs.ucr]

$$F(A,B,C) = A'BC + AB'C' + AB'C + ABC' + ABC$$

Written in shorthand notation: [jazapka.people.ysu]

$$F(A,B,C) = \Sigma\, m(3, 4, 5, 6, 7)$$

What This Means

The formula is simply saying: OR together every minterm for which the function outputs 1. Each minterm $m_i$ is exactly 1 for one and only one input combination, so the sum "selects" the rows in the truth table where $F = 1$. This canonical SOP is the fully expanded Shannon decomposition over all variables simultaneously. [cs.ucr]


Here is a full worked example using the dual POS form of Shannon's expansion.

Setup

Let $F(A, B, C) = A + BC$, and expand on $X_1 = A$: [en.wikipedia]

$$F = (A + F(0, B, C)) \cdot (A' + F(1, B, C))$$

Step 1 — Compute the Two Cofactors

Negative cofactor — set $A = 0$: [en.wikipedia]

$$F(0, B, C) = 0 + BC = BC$$

Positive cofactor — set $A = 1$: [en.wikipedia]

$$F(1, B, C) = 1 + BC = 1$$

Step 2 — Plug into the POS Formula

$$F(A, B, C) = (A + BC) \cdot (A' + 1)$$

Since $A' + 1 = 1$ (anything OR'd with 1 is 1):

$$F(A, B, C) = (A + BC) \cdot 1 = A + BC$$

The function is confirmed correctly $\checkmark$

Step 3 — Expand Further to Canonical POS

To reach the fully canonical POS (maxterm form), apply the theorem recursively to each remaining sub-function. Expand $BC$ on variable $B$: [eplauchu.files.wordpress]

$$BC = (B + C \cdot 0)(B' + C \cdot 1) = (B + 0)(B' + C) = B(B' + C)$$

Wait — in POS, the canonical expansion over all variables yields maxterms where $F = 0$. From the earlier truth table, $F = 0$ only at rows $i = 0, 1, 2$ (i.e., $A=0, BC=0$):

$i$ABCMaxterm $M_i$$F$
0000$A+B+C$0
1001$A+B+C'$0
2010$A+B'+C$0
3–71

So the canonical POS is: [eplauchu.files.wordpress]

$$F(A,B,C) = \Pi\, M(0, 1, 2) = (A+B+C)(A+B+C')(A+B'+C)$$

Key Insight: SOP vs POS Duality

SOP (Shannon direct)POS (Shannon dual)
Operator$x \cdot F_x + x' \cdot F_{x'}$$(x + F_{x=0})(x' + F_{x=1})$
Canonical formSum of minterms where $F = 1$Product of maxterms where $F = 0$
Building blocksMinterms $m_i$Maxterms $M_i$

The dual POS form is particularly useful when a function has fewer 0s than 1s in the truth table — the POS expression will then be more compact. [eplauchu.files.wordpress]

4.3EasyTier 1?R
Draw the circuit diagram for a 4-to-1 multiplexer using AND, OR, and NOT gates.
4.4MediumTier 1?R
Design a 4-to-2 priority encoder where input 3 has the highest priority. Give the truth table and logic equations for the two outputs and a valid-output signal.
Why does input 3 have the highest priority?

By convention the highest-indexed asserted input wins: I₃ > I₂ > I₁ > I₀. The encoder reports the index of that winning input on (Y₁, Y₀), and V=1 whenever any input is active.

In an if / else if chain this is the input checked first:

if      (in[3]) out = 2'd3;   // highest priority
else if (in[2]) out = 2'd2;
else if (in[1]) out = 2'd1;
else if (in[0]) out = 2'd0;   // lowest priority

To make input 0 the highest priority instead, just reverse the order of the chain.

What if input 0 has the highest priority?

Then I₀ > I₁ > I₂ > I₃. The output (Y₁,Y₀) still reports the index of the winning input, but every term must gate on the complements of the higher-priority inputs.

I₃I₂I₁I₀Y₁Y₀V
0000xx0
xxx1001
xx10011
x100101
1000111

$Y_0 = I_1\overline{I_0} + I_3\overline{I_2}\,\overline{I_1}\,\overline{I_0}$

$Y_1 = \overline{I_0}\,\overline{I_1}(I_2 + I_3)$

$V = I_0 + I_1 + I_2 + I_3$

Compared to the I₃-highest case ($Y_1 = I_3 + I_2$, $Y_0 = I_3 + I_1\overline{I_2}$), flipping the priority to I₀ makes the equations longer because the higher-priority inputs now need to be explicitly suppressed.

What if input 1 has the highest priority?

Naming only I₁ as highest doesn't fully specify the order of the other three. The usual reading is a cyclic shift (round-robin style): I₁ > I₂ > I₃ > I₀.

I₃I₂I₁I₀Y₁Y₀V
0000xx0
xx1x011
x10x101
100x111
0001001

$Y_0 = I_1 + I_3\overline{I_2}\,\overline{I_1}$

$Y_1 = \overline{I_1}(I_2 + I_3)$

$V = I_0 + I_1 + I_2 + I_3$

Because I₀ is now the lowest priority and its index is 00, no I₀ term appears in either output — it's "selected" only when all higher-priority inputs are 0, and that selection is encoded by Y₁Y₀ = 00.

4.5MediumTier 1?R
Implement a 2-to-4 decoder with an enable input. Write the truth table and the Verilog code using a case statement.
4.6MediumTier 1?R
Derive minimum SOP expressions for outputs a, b, and c of a BCD-to-7-segment display decoder.
完整 0–9 真值表 (a–g, common cathode)

段位示意:a = 上橫,b = 右上,c = 右下,d = 下橫,e = 左下,f = 左上,g = 中橫。BCD 用 ABCD = wxyz。

十進位BCD (wxyz)abcdefg
000001111110
100010110000
200101101101
300111111001
401000110011
501011011011
601101011111
701111110000
810001111111
910011111011

特殊規律:

  • 數字 8:七段全亮 (1111111),是最完整的圖形。
  • 數字 1:只有 b、c 亮 (右側兩段)。
  • 數字 7:比 1 多一條上橫 (a 段)。
  • g 段 (中橫):只有 0、1、7 不亮,其餘皆亮。
  • BCD 1010–1111 (10–15) 為無效輸入,列為 Don't Care (X),可在 K-map 化簡時自由利用。
4.7MediumTier 1?R
Design a 2-bit magnitude comparator that produces three outputs: AgtB, AeqB, AltB. Give the truth table and simplified equations. See Compound Gates for XNOR (≡) used in equality detection.
4.8MediumTier 1?R
Use two 2-to-4 decoders and additional gates to build a 3-to-8 decoder. Draw the block diagram.
4.9MediumTier 1?R
Write Verilog code for a priority encoder with 8 inputs using an if-else chain inside an always block.
4.10EasyTier 1?R
What happens if a case statement in Verilog doesn't cover all possible input combinations and no default is provided? What type of hardware is inferred?
4.11MediumTier 1?R
Design a 4-bit binary-to-Gray code converter. Give the truth table and Verilog implementation.
What is Gray code?

Gray code (reflected binary code) is a binary numbering system where two consecutive values differ in exactly one bit.

DecBinaryGrayDecBinaryGray
000000000810001100
100010001910011101
2001000111010101111
3001100101110111110
4010001101211001010
5010101111311011011
6011001011411101001
7011101001511111000

Each row changes only one bit from the row above. Compare with binary: 0011 → 0100 changes 3 bits at once.

Why it matters:

  • Mechanical / optical encoders (rotary position): sensors at bit boundaries can't all switch simultaneously. With binary, mid-transition you might briefly read a wildly wrong value (e.g. 011 → 100 might glitch through 000 or 111). Gray guarantees only one sensor changes, so the worst-case mis-read is off by one.
  • K-maps: rows/columns are in Gray order so physical adjacency = logical adjacency for grouping minterms.
  • Asynchronous FIFOs / clock-domain crossing: counters use Gray code so a sampled value is always either "this count" or "next count", never garbage in-between.
  • Power / EMI: fewer bit transitions per increment → less switching noise.

Conversion formulas:

  • Binary → Gray: $G_i = B_i \oplus B_{i+1}$, with $G_{MSB} = B_{MSB}$. Equivalently $G = B \oplus (B \gg 1)$.
  • Gray → Binary: $B_{MSB} = G_{MSB}$, then $B_i = G_i \oplus B_{i+1}$ (cumulative XOR from MSB down).
4.12HardTier 1?R
Prove Shannon's expansion theorem: $f(x_1,\ldots,x_n) = x_1 \cdot f(1,x_2,\ldots,x_n) + \overline{x_1} \cdot f(0,x_2,\ldots,x_n)$.
4.13MediumTier 1E?R
Design a $2\times 2$ crossbar switch using 2-to-1 multiplexers. The circuit has inputs $x_1,x_2$, outputs $y_1,y_2$, and a control signal $s$ such that $s=0$ connects $x_1\to y_1$, $x_2\to y_2$ and $s=1$ swaps the connections.
Context: what is a 2×2 crossbar switch?

A crossbar switch is a network element that lets any input be routed to any output, like a digital "patch panel". The simplest non-trivial case is the 2×2 crossbar: two inputs ($x_1, x_2$), two outputs ($y_1, y_2$), and one control bit $s$ that picks between two connection patterns:

$s$routing$y_1$$y_2$
0straight (pass-through)$x_1$$x_2$
1crossed (swap)$x_2$$x_1$

Schematic of the two routing patterns:

s = 0 (pass-through)x₁x₂y₁ = x₁y₂ = x₂s = 1 (swap / crossed)x₁x₂y₁ = x₂y₂ = x₁

Boolean expressions:

$y_1 = \overline{s}\,x_1 + s\,x_2 \;=\; \mathrm{MUX2}(s; x_1, x_2)$

$y_2 = \overline{s}\,x_2 + s\,x_1 \;=\; \mathrm{MUX2}(s; x_2, x_1)$

Each output is a 2-to-1 MUX: when $s=0$ pick the "straight" input, when $s=1$ pick the "crossed" input. Two MUXes total.

Block diagram:

x₁ s x₂ MUX2 y₁ MUX2 y₂

Each MUX has its top data line wired straight from $x_i$ and its bottom data line wired across from $x_j$. The single control $s$ flips both MUXes simultaneously.

Verilog:

module crossbar_2x2 (
  input  x1, x2, s,
  output y1, y2
);
  assign y1 = s ? x2 : x1;
  assign y2 = s ? x1 : x2;
endmodule

Why it matters. Crossbar switches scale up to $n \times n$ networks (used in CPU register files, multiprocessor memory networks, network-on-chip routers). An $n \times n$ crossbar takes $n$ parallel $n$-to-1 MUXes — non-blocking but $O(n^2)$ in size, hence the use of multistage networks (Clos, Beneš) for larger $n$.

4.14EasyTier 1E?R
Implement the three-input majority function using a single 4-to-1 multiplexer. Choose $w_1$ and $w_2$ as the select inputs and determine the data inputs as functions of $w_3$.
Context: what is the three-input majority function?

The three-input majority function $M(w_1, w_2, w_3)$ outputs 1 when at least two of the three inputs are 1, and 0 otherwise. It's the Boolean version of "majority vote": each input is a yes/no vote, the output is the winning side.

Truth table:

$w_1$$w_2$$w_3$$M$comment
0000no votes for 1
0010only one vote
0100only one vote
0111two votes
1000only one vote
1011two votes
1101two votes
1111all three

Boolean expression (minimum SOP):

$M = w_1 w_2 + w_1 w_3 + w_2 w_3$   必背

(any pair of 1s makes $M=1$ — three 2-input AND terms ORed together).

4-to-1 MUX implementation strategy. Use $w_1, w_2$ as select inputs ($s_1 s_0 = w_1 w_2$). The MUX output for each select pattern is whatever the truth table dictates, parameterized by $w_3$:

$w_1 w_2$MUX line$M$ when $w_3{=}0$$M$ when $w_3{=}1$data input
00$I_0$000
01$I_1$01$w_3$
10$I_2$01$w_3$
11$I_3$111

Result: connect $I_0 = 0$, $I_1 = I_2 = w_3$, $I_3 = 1$. The 4-to-1 MUX automatically produces the majority output for whatever $(w_1, w_2, w_3)$ comes in.

Why majority is interesting: it's the canonical example of a "voting" / "fault-masking" function — used in triple-modular redundancy (TMR), where three copies of a signal are voted on to mask a single fault. Also a classic K-map example because its prime-implicant SOP form has no static hazards.

4.15MediumTier 1E?R
Implement the three-input XOR function $f = w_1 \oplus w_2 \oplus w_3$ using only 2-to-1 multiplexers, exploiting that $w_2 \oplus w_3$ can be selected by $w_1$. the concept is very important
4.16MediumTier 1E?R
For $f = \overline{w_1}\overline{w_3}+w_2 w_3$, perform Shannon's expansion with respect to each of $w_1$, $w_2$, and $w_3$ in turn, and identify which expansion variable produces the lowest-cost circuit.
4.17MediumTier 1E?R
Implement $f = \overline{w_1}\overline{w_3} + w_1 w_2 + w_1 w_3$ using (a) a single 2-to-1 multiplexer plus other gates and (b) a single 4-to-1 multiplexer. Use Shannon's expansion to derive both circuits.
4.18MediumTier 1E?R
Implement the three-input majority function using only 2-to-1 multiplexers by applying Shannon's expansion twice (first on $w_1$, then on $w_2$ within each cofactor).
4.19MediumTier 1E?R
Show how a 4-to-1 multiplexer can be built from a 2-to-4 decoder (with enable held high) plus a single OR gate combining the AND of each decoder output with the corresponding data input.
4.20EasyTier 1E?R
Write a Verilog module mux2to1 with inputs w0, w1, s and output f, using a continuous assign with the conditional operator ?:.
4.21EasyTier 1E?R
Write a Verilog module for a 2-to-1 multiplexer using an if-else statement inside an always block.
4.22MediumTier 1E?R
Write hierarchical Verilog code for a 16-to-1 multiplexer that instantiates five 4-to-1 multiplexer modules. Use a 16-bit data vector $W$ and a 4-bit select vector $S$.
4.23EasyTier 1E?R
Write Verilog code for a 4-to-1 multiplexer using a case statement inside an always block, with a 2-bit select vector $S$.
4.24MediumTier 1E?R
Write Verilog code for a 2-to-4 binary decoder with an enable input En, using a case statement on the concatenation {En, W}.
4.25MediumTier 1E?R
Write Verilog code for a 2-to-4 binary decoder using a combination of if-else (for the enable) and a case statement (for the input pattern).
4.26MediumTier 1E?R
Write hierarchical Verilog code for a 4-to-16 decoder built as a tree of five 2-to-4 decoders. important trick
4.27MediumTier 1E?R
Write a Verilog module seg7 that implements a hexadecimal-to-7-segment display decoder. The 4-bit input is hex and the 7-bit output is leds; use a case statement listing all 16 patterns.
4.28HardTier 1E?R
Write Verilog code for a 4-bit ALU modeled on the 74381 chip, with 3-bit select $S$, 4-bit operands $A$ and $B$, and a 4-bit output $F$. Implement clear, $B-A$, $A-B$, $A+B$, $A\oplus B$, $A|B$, $A\&B$, and preset-to-1111.
4.29MediumTier 1E?R
Write Verilog code for a 4-input priority encoder using a casex statement that treats lower-priority bits as don't-cares. Provide a valid output flag $z$.
4.30MediumTier 1E?R
Write Verilog code for a 2-to-4 decoder using a for loop that iterates over the four output positions, asserting $Y[k]=1$ when $W=k$ and $\text{En}=1$.
4.31MediumTier 1E?R
Write Verilog code for a 4-input priority encoder using a for loop. Exploit the fact that, in an always block, multiple assignments to the same variable retain the last assignment, so the highest priority input wins.
4.32MediumTier 1E?R
Write Verilog code for a 4-bit magnitude comparator that uses the relational operators (==, >, <) inside an if-else chain to drive outputs AeqB, AgtB, AltB.
4.33HardTier 1E?R
Use the Verilog generate construct with a for loop and gate-level primitives to specify an $n$-bit ripple-carry adder. Use a genvar index and parameterize $n$.
4.34MediumTier 1E?R
Re-implement the hierarchical 16-to-1 multiplexer of Example 4.10 using a Verilog task for the inner 4-to-1 multiplexer, called from a case statement inside an always block.— example 4.10
4.35MediumTier 1E?R
Re-implement the 16-to-1 multiplexer using a Verilog function rather than a task. Explain the syntactic and semantic differences from the task-based version.
4.36MediumTier 1E?R
Implement $f(w_1,w_2,w_3) = \sum m(0,1,3,4,6,7)$ using a 3-to-8 binary decoder and a single OR gate.
4.37MediumTier 1E?R
Design an 8-to-3 binary encoder. Assume only one input is asserted at a time and write the truth table along with minimum SOP expressions for $y_2$, $y_1$, $y_0$.
4.38HardTier 1E?R
Implement $f(w_1,\ldots,w_5) = \overline{w_1}\,\overline{w_2}\,w_4 w_5 + w_1\overline{w_2} + w_1 w_3 + w_1 w_4 + w_3 w_4 w_5$ using a single 4-to-1 multiplexer (selects $w_1, w_4$) and as few additional gates as possible. Assume only uncomplemented inputs are available.
4.39MediumTier 1E?R
Design a 3-bit binary-to-Gray code converter according to the table $b_2 b_1 b_0 \to g_2 g_1 g_0$. Show that $g_2 = b_2$, $g_1 = b_1 \oplus b_2$, $g_0 = b_0 \oplus b_1$.
4.40MediumTier 1E?R
A 4-input function $f$ has been Shannon-expanded with respect to $w_1$, giving cofactors $f_{w_1}$ and $f_{\overline{w_1}}$. Show that the multiplexer in the Shannon-expansion circuit can be replaced by a single logic gate (a) when $f_{\overline{w_1}}=0$ and (b) when $f_{\overline{w_1}}=1$.
4.41HardTier 1E?R
A commercial FPGA uses 4-input lookup tables (4-LUTs). Determine the minimum number of 4-LUTs needed to construct a 4-to-1 multiplexer with select inputs $s_1, s_0$ and data inputs $w_3, w_2, w_1, w_0$. Show both a straightforward 3-LUT solution and an optimized 2-LUT solution.
4.42MediumTier 1E?R
Design a 4-bit right-shift circuit using five 2-to-1 multiplexers. The control signal Shift selects between (a) pass-through $Y=W$, $k=0$ and (b) right-shift by one with $y_3=0$, $y_2=w_3$, $y_1=w_2$, $y_0=w_1$, $k=w_0$.
4.43HardTier 1E?R
Design a 4-bit barrel shifter that rotates the input vector $W$ by 0, 1, 2, or 3 positions according to a 2-bit control $S$. Implement the circuit using four 4-to-1 multiplexers.
Context: what is a barrel shifter?

A barrel shifter is a combinational circuit that shifts (or rotates) an $n$-bit vector by any amount in one clock cycle, regardless of how many bits the shift is. Unlike a sequential shift register, which moves one position per clock, a barrel shifter performs the entire shift through pure combinational logic — exploiting parallel multiplexers.

Two flavors:

  • Rotating barrel shifter — bits that fall off one end re-enter the other. Output bits are a cyclic permutation of input bits.
  • Logical/Arithmetic shift barrel shifter — bits that fall off are discarded; vacated positions get 0 (logical) or sign-extension (arithmetic).

Problem 4.43 asks for a rotating 4-bit shifter ($n=4$) with shift amounts $\{0,1,2,3\}$ selected by a 2-bit control $S = s_1 s_0$.

Functional table (input $W = w_3 w_2 w_1 w_0$, output $Y = y_3 y_2 y_1 y_0$):

$S$shift$y_3$$y_2$$y_1$$y_0$
000$w_3$$w_2$$w_1$$w_0$
011 right$w_0$$w_3$$w_2$$w_1$
102 right$w_1$$w_0$$w_3$$w_2$
113 right$w_2$$w_1$$w_0$$w_3$

Each output bit needs a 4-to-1 MUX whose data inputs are the four candidate source bits and whose select is $S$. From the table, reading down each $y_i$ column tells you the data inputs to MUX$_i$:

  • MUX for $y_3$: data lines $(w_3, w_0, w_1, w_2)$ for $S = (00, 01, 10, 11)$
  • MUX for $y_2$: data lines $(w_2, w_3, w_0, w_1)$
  • MUX for $y_1$: data lines $(w_1, w_2, w_3, w_0)$
  • MUX for $y_0$: data lines $(w_0, w_1, w_2, w_3)$

Pattern: each MUX$_i$ has data inputs $(w_i, w_{(i-1)\bmod 4}, w_{(i-2)\bmod 4}, w_{(i-3)\bmod 4})$ — exactly the cyclic shift of $W$ starting at position $i$.

Schematic (four parallel 4-to-1 MUXes sharing the same $S$):

w₃ w₂ w₁ w₀w₃w₂w₁w₀MUX₃y₃w₃,w₀,w₁,w₂MUX₂y₂w₂,w₃,w₀,w₁MUX₁y₁w₁,w₂,w₃,w₀MUX₀y₀w₀,w₁,w₂,w₃S = s₁s₀

Verilog (parameterized for any $n$ that is a power of 2):

module barrel_rot4 (
  input  [3:0] W,
  input  [1:0] S,
  output [3:0] Y
);
  // each output is the input rotated right by S
  assign Y = (W >> S) | (W << (4 - S));
endmodule

The expression `(W >> S) | (W << (4-S))` is the canonical right-rotate idiom: bits shifted off the bottom re-enter at the top via the inverted shift. The synthesis tool will turn this into the four 4-to-1 MUXes shown above.

Cost & depth. An $n$-bit barrel rotator built from $n$ parallel $n$-to-1 MUXes uses $O(n^2)$ gates and one MUX-delay. For larger $n$, a logarithmic multi-stage barrel shifter ($\log_2 n$ stages of 2-to-1 MUXes per bit) cuts cost to $O(n \log n)$ at the price of $\log_2 n$ MUX delays — the standard ALU shifter design in modern CPUs.

4.44MediumTier 1E?R
Write Verilog code that builds a 4-to-1 multiplexer from a 2-to-4 decoder (instantiated as a dec2to4 module) and a single reduction-OR over the AND of decoder outputs with the data vector.
4.45EasyTier 1E?R
Write Verilog code for the 4-bit right-shifter of Example 4.30 in two styles: one using an if-else with explicit bit assignments, and another using the Verilog shift operator >>.
Why use >> instead of explicit bit assignments?

Style 1 — explicit bit assignments:

module shifter_if (input [3:0] R, input shift, output reg [3:0] Q);
    always @* begin
        if (shift) begin
            Q[3] = 1'b0;       // fill MSB with 0
            Q[2] = R[3];
            Q[1] = R[2];
            Q[0] = R[1];       // R[0] discarded
        end else
            Q = R;
    end
endmodule

Style 2 — using >>:

module shifter_op (input [3:0] R, input shift, output [3:0] Q);
    assign Q = shift ? (R >> 1) : R;
endmodule

Why prefer >>?

AspectExplicit if-else>> operator
Lines of code~101
Bug surfaceEasy to swap two bit indices and miss itCompiler enforces the relation
Scales to wider wordsOne extra line per bitSame line works for any width
ParameterizableNeed to template every assignmentassign Q = R >> 1; works for any [N-1:0]
Variable shift amountNeed a large case / mux networkR >> n — synthesizer builds the barrel shifter
Synthesized hardwareIdentical wire-renameIdentical wire-rename

Bottom line: the two are electrically identical for a fixed 1-bit shift (both synthesize to a trivial wire-rename — no flip-flops). But >> is the right level of abstraction: it states the operation rather than its implementation. For parameterized widths or variable shift amounts, >> saves you from writing a barrel multiplexer by hand. The textbook asks for both styles to make clear that HDL operators are not magic — they're shorthand for what you could otherwise write structurally.

— example 4.30
4.46HardTier 1E?R
Write Verilog code that defines a 4-bit barrel shifter by concatenating two copies of the input vector $W$ and shifting the resulting 8-bit value right by $S$ bits, then taking the four least-significant bits as the output.
4.47MediumTier 1E?R
Write Verilog code for an even-parity generator that takes a 7-bit ASCII character on input bits $b_6\ldots b_0$ and produces an 8-bit output where $b_7$ is the even-parity bit and $b_6\ldots b_0$ pass through unchanged.