HW 02 - CMOS Full Adder - Learnings

Class: CSCE-312


Notes:

Build a Full Adder

For this assignment, you should build a full adder circuit using CMOS P and N transistors in a little C program I came up with. Currently the C program implements an OR gate with two inputs and one output. You should modify or replace the code to implement a full adder with three inputs and two outputs. The program will call your code to build the circuit, then print the circuit in a somewhat human-readable format, then exhaustively test the circuit with all possible combinations of three inputs. You're done when the output of the program shows the correct truth table for a full adder, i.e. something like this:

...
found 3 input nodes, 2 output nodes
 2  1  0  |  4  3 
----------------
 0  0  0     0 0
 0  0  1     0 1
 0  1  0     0 1
 0  1  1     1 0
 1  0  0     0 1
 1  0  1     1 0
 1  1  0     1 0
 1  1  1     1 1

The Full Adder Logic Diagram

One implementation of the full adder circuit looks as follow:

Pasted image 20250913203629.png|400

Strategy for Minimal node number design (Static-CMOS)

Basically use the diagram above as a blueprint of your circuit

Transmission Gates

1. What is a transmission gate (TG)?

A transmission gate is basically a “bidirectional switch” built from one NMOS and one PMOS in parallel, controlled by complementary signals.

A ----|| NMOS (gate=C) ||---- B            
	  || PMOS (gate=¬C) ||

When C=1:

When C=0:

So a transmission gate is just a controllable wire (closed switch when enabled, open when disabled).

Diagram Example:
Pasted image 20250913220520.png|200


2. Why use TGs?

3. Example: XOR with TGs

We can build X = A ⊕ B with just 8 transistors using TGs:

X=(¬BA)+(B¬A)

Circuit intuition:

That’s a 2:1 multiplexer:

X=(¬BA)+(B¬A)

A multiplexer is the perfect job for a transmission gate:

Total transistors:

Compare with static CMOS XOR (~12T). Much leaner.

1. Building a Transmission Gate (TG)

We want to achieve the following behavior

SEL NMOS gate PMOS gate NMOS PMOS TG
0 0 1 OFF OFF Open
1 1 0 ON ON Closed

Wired up in C framework:

void make_TGate (circuit *c, int input_wire, int select_wire, int output_wire) {
	// Define building blocks (PMOS, NMOS)
	int p, n;
	
	// get P and N transistors
	p = new_node (c, P);
	n = new_node (c, N);
	
	// Invert the selecter (to be used by PMOS)
	int not_sel_wire = new_wire(c);
	make_inverter (c, select_wire, not_sel_wire);
		// Now the not_sel_wire will give the opposite of what select_wire gives
	
	// Wire up PMOS (triggered when select = 0)
	attach_node_to_wire(c, p, not_sel_wire, CONTROL);	// not_select_wire to SELECT
	attach_node_to_wire(c, p, input_wire, INPUT);		// input_wire to INPUT
	attach_node_to_wire(c, p, output_wire, OUTPUT);		// output_wire to DRAIN
		// We want both ON at the same time when the switch/select is “ON” 
		// and both OFF together when it's “OFF”
		// Note: I could have inverted NMOS instead, will give the same.
		
	// Wire up NMOS (triggered when select = 1)
	attach_node_to_wire(c, n, select_wire, CONTROL);	// select_wire to SELECT
	attach_node_to_wire(c, n, input_wire, INPUT);		// input_wire to INPUT
	attach_node_to_wire(c, n, output_wire, OUTPUT);		// output_wire to DRAIN
}

2. Building a 2:1 MUX

A 2:1 multiplexer is a gate that chooses between two inputs D0,D1 and forwards one of them to the output, depending on a select input (SEL):

Y=(SELD0)+(SELD1)Y=(SELD0)+(SELD1)
SEL Y
0 D0
1 D1
So, the MUX is basically a controlled switch that says: “If SEL=0, connect D0 → Y; if SEL=1, connect D1 → Y.”

A MUX is just two TGs in parallel onto the same output, one passing D0 when SEL=0, the other passing D1 when SEL=1.

Pasted image 20250913225517.png

Why do we need it?

Because many complex functions can be rewritten as a MUX. For example:

So, using a MUX often reduces transistor count and node clutter.