RTL Coding

Designing Half Adder and Full Adder Using Verilog

HARI PREETH D M
5 min readJun 22, 2024

--

In digital electronics, adders are crucial components used in arithmetic operations, particularly in CPUs and other processing units. This blog post will guide you through designing two fundamental types of adders: the half adder and the full adder, using Verilog, a popular hardware description language.

Prerequisites to Install Icarus Verilog and GTKWave

Before diving into Verilog simulations with Icarus Verilog and visualizing waveforms using GTKWave, it’s important to ensure your system meets the necessary prerequisites for installation. This section Installation process outlines the requirements and steps to prepare your environment for setting up these tools.

Understanding Adders

Half Adder

A half adder is a simple combinational circuit that adds two single-bit binary numbers (A and B). It produces two outputs: the sum (S) and the carry (Cy). The truth table for a half adder is as follows:

Half_adder_Truthtable

Full Adder

A full adder extends the functionality of a half adder by including a carry-in (Cin) input, allowing for the addition of three bits. It produces a sum (S) and a carry-out (Cout). The truth table for a full adder is:

Full_adder_Truthtable

Designing the Half Adder in Verilog

Let’s start by designing the half adder. Below is the Verilog code for the half adder module and its testbench.

Half Adder Module

// Half Adder Module
module half_adder (
input wire a, // Input bit a
input wire b, // Input bit b
output wire sum, // Sum output
output wire carry // Carry output
);

// Sum is the XOR of a and b
assign sum = a ^ b;

// Carry is the AND of a and b
assign carry = a & b;

endmodule

Testbench for Half Adder

// Testbench for Half Adder
module tb_half_adder;

// Inputs
reg a;
reg b;

// Outputs
wire sum;
wire carry;

// Instantiate the Half Adder
half_adder uut (
.a(a),
.b(b),
.sum(sum),
.carry(carry)
);

// Test Vector
initial begin
// Initialize inputs
a = 0;
b = 0;

// Generate waveform file
$dumpfile("half_adder.vcd");
$dumpvars(0, tb_half_adder);

// Display header
$display("a b | sum carry");
$display("-------------");

// Test cases
a = 0; b = 0; #10;
$display("%b %b | %b %b", a, b, sum, carry);

a = 0; b = 1; #10;
$display("%b %b | %b %b", a, b, sum, carry);

a = 1; b = 0; #10;
$display("%b %b | %b %b", a, b, sum, carry);

a = 1; b = 1; #10;
$display("%b %b | %b %b", a, b, sum, carry);

// Finish simulation
$finish;
end

endmodule

Designing the Full Adder in Verilog

Next, let’s design the full adder. Below is the Verilog code for the full adder module and its testbench.

Full Adder Module

// Full Adder Module
module full_adder (
input wire a, // Input bit a
input wire b, // Input bit b
input wire cin, // Carry-in bit
output wire sum, // Sum output
output wire cout // Carry-out output
);

// Internal signals
wire sum1, c1, c2;

// Half Adder for a and b
assign sum1 = a ^ b;
assign c1 = a & b;

// Half Adder for sum1 and cin
assign sum = sum1 ^ cin;
assign c2 = sum1 & cin;

// Carry-out
assign cout = c1 | c2;

endmodule

Testbench for Full Adder

// Testbench for Full Adder
module tb_full_adder;

// Inputs
reg a;
reg b;
reg cin;

// Outputs
wire sum;
wire cout;

// Instantiate the Full Adder
full_adder uut (
.a(a),
.b(b),
.cin(cin),
.sum(sum),
.cout(cout)
);

// Test Vector
initial begin
// Initialize inputs
a = 0;
b = 0;
cin = 0;

// Generate waveform file
$dumpfile("full_adder.vcd");
$dumpvars(0, tb_full_adder);

// Display header
$display("a b cin | sum cout");
$display("------------------");

// Test cases
a = 0; b = 0; cin = 0; #10;
$display("%b %b %b | %b %b", a, b, cin, sum, cout);

a = 0; b = 0; cin = 1; #10;
$display("%b %b %b | %b %b", a, b, cin, sum, cout);

a = 0; b = 1; cin = 0; #10;
$display("%b %b %b | %b %b", a, b, cin, sum, cout);

a = 0; b = 1; cin = 1; #10;
$display("%b %b %b | %b %b", a, b, cin, sum, cout);

a = 1; b = 0; cin = 0; #10;
$display("%b %b %b | %b %b", a, b, cin, sum, cout);

a = 1; b = 0; cin = 1; #10;
$display("%b %b %b | %b %b", a, b, cin, sum, cout);

a = 1; b = 1; cin = 0; #10;
$display("%b %b %b | %b %b", a, b, cin, sum, cout);

a = 1; b = 1; cin = 1; #10;
$display("%b %b %b | %b %b", a, b, cin, sum, cout);

// Finish simulation
$finish;
end

endmodule

Running the Simulations

To simulate the designs, use the following commands:

  1. For the Half Adder:
iverilog -o half_adder.vvp half_adder.v tb_half_adder.v
vvp half_adder.vvp

2. For the Full Adder:

iverilog -o full_adder.vvp full_adder.v tb_full_adder.v
vvp full_adder.vvp

After running the simulations, you’ll get VCD (Value Change Dump) files named half_adder.vcd and full_adder.vcd, respectively. These files can be viewed using GTKWave to analyze the waveforms.

3. Viewing the Waveforms:

gtkwave half_adder.vcd
gtkwave full_adder.vcd

Conclusion

In this blog post, we covered the basics of designing half adders and full adders using Verilog. These simple yet fundamental components are essential in the design of more complex arithmetic units used in digital systems. By simulating these designs, you can visualize how binary addition works at the hardware level, which is a crucial step in learning digital design and Verilog.

--

--