Chapter 02: Combinational Logic

Building complex functions from simple gates

What is Combinational Logic?

Combinational logic means the output depends ONLY on the current inputs. No memory, no history, no state. Change the inputs, output changes instantly (within nanoseconds).

Examples: AND gates, OR gates, multiplexers, adders, comparators. Output = f(inputs) at any moment.

All Basic Logic Gates

GateOperatorFunctionExample
AND&Both inputs HIGHy = a & b;
OR|At least one HIGHy = a | b;
NOT~Invert signaly = ~a;
XOR^Inputs differenty = a ^ b;
NAND~(&)NOT ANDy = ~(a & b);
NOR~(|)NOT ORy = ~(a | b);

Building a 4-Input Logic Function

Let's build something useful: A 2-to-4 decoder. Takes 2 input bits, activates one of 4 outputs.

Truth Table

A  B  |  Y0  Y1  Y2  Y3
------+----------------
0  0  |   1   0   0   0
0  1  |   0   1   0   0
1  0  |   0   0   1   0
1  1  |   0   0   0   1

The Verilog

// 2-to-4 Decoder
// Only ONE output is HIGH based on input combination

module decoder_2to4 (
    input  a,
    input  b,
    output y0,
    output y1,
    output y2,
    output y3
);

    // Each output is HIGH for ONE specific input combination
    assign y0 = ~a & ~b;  // 00
    assign y1 = ~a &  b;  // 01
    assign y2 =  a & ~b;  // 10
    assign y3 =  a &  b;  // 11

endmodule

Multi-bit Signals (Buses)

Instead of declaring many single wires, use buses - multi-bit signals:

// Same decoder, cleaner code using buses

module decoder_2to4_bus (
    input  [1:0] sel,      // 2-bit input bus
    output [3:0] y         // 4-bit output bus
);

    // Use shift operator to activate the correct bit
    assign y = 4'b0001 << sel;

endmodule
Power Move: 4'b0001 << sel shifts a 1 left by sel positions. When sel=2, result is 0100 (bit 2 high). One line does everything!

Multiplexer (MUX): The Universal Selector

A multiplexer selects ONE input from many to pass to the output. It's like a railroad switch.

// 4-to-1 Multiplexer
// Select which of 4 inputs appears at output

module mux_4to1 (
    input  [3:0] data_in,     // 4 data inputs
    input  [1:0] sel,          // 2-bit selector
    output       data_out      // Selected output
);

    // Use selector to index into the data bus
    assign data_out = data_in[sel];

endmodule
How it works: data_in[sel] dynamically selects a bit. If sel=2, output = data_in[2]. Hardware builds this as actual MUX gates!

Real Example: 8-bit Adder

// Add two 8-bit numbers

module adder_8bit (
    input  [7:0] a,
    input  [7:0] b,
    output [7:0] sum,
    output       carry_out
);

    // Add with carry capture
    // {carry_out, sum} creates a 9-bit result
    assign {carry_out, sum} = a + b;

endmodule

Exercise: Build an ALU

Create an Arithmetic Logic Unit that can ADD, SUB, AND, OR based on operation select:

module alu_4bit (
    input  [3:0] a, b,
    input  [1:0] op,       // 00=ADD, 01=SUB, 10=AND, 11=OR
    output reg [3:0] result
);

    always @(*) begin
        case(op)
            2'b00: result = a + b;
            2'b01: result = a - b;
            2'b10: result = a & b;
            2'b11: result = a | b;
        endcase
    end

endmodule
New Concepts: always @(*) creates combinational logic with procedural statements. reg type allows assignment inside always blocks. case statement builds MUX-like logic.

Key Takeaways