Example: FPGA-Based Digital System Design
Course: Advanced FPGA-based System Design (ECE-863)
Instructor: Dr. Zahid Ullah
Student Name: Rehan Uz Zaman
Roll Number: M25S0020ESI002
Date: March 2025
Task 1: 8-bit Less Than Detector
Verilog Code:
module less_than_detector (
input [7:0] A,
input [7:0] B,
output LT
);
assign LT = (A < B) ? 1'b1 : 1'b0;
endmodule
Testbench:
module tb_less_than_detector;
reg [7:0] A, B;
wire LT;
less_than_detector uut (A, B, LT);
initial begin
A = 8'd10; B = 8'd20; #10;
A = 8'd30; B = 8'd15; #10;
A = 8'd50; B = 8'd50; #10;
$stop;
end
endmodule
Explanation:
This module takes two 8-bit numbers as input and compares them using a continuous
assignment. The output LT is high when A is less than B. The testbench verifies the
behavior with different values.
Task 2: 8-bit Wide AND Operation
Verilog Code:
module and_8bit (
input [7:0] A,
input [7:0] B,
output [7:0] Y
);
assign Y = A & B;
endmodule
Testbench:
module tb_and_8bit;
reg [7:0] A, B;
wire [7:0] Y;
and_8bit uut (A, B, Y);
initial begin
A = 8'b10101010; B = 8'b11001100; #10;
A = 8'b11110000; B = 8'b00001111; #10;
$stop;
end
endmodule
Explanation:
This module performs a bitwise AND operation between two 8-bit inputs. The
testbench checks its correctness by applying different binary patterns.
Task 3: Full Adder (Gate-Level Model)
Verilog Code:
module full_adder (
input A, B, Cin,
output Sum, Cout
);
assign Sum = A ^ B ^ Cin;
assign Cout = (A & B) | (Cin & (A ^ B));
endmodule
Testbench:
module tb_full_adder;
reg A, B, Cin;
wire Sum, Cout;
full_adder uut (A, B, Cin, Sum, Cout);
initial begin
A = 0; B = 0; Cin = 0; #10;
A = 0; B = 1; Cin = 0; #10;
A = 1; B = 1; Cin = 1; #10;
$stop;
end
endmodule
Explanation:
This module implements a single-bit full adder using basic logic operations. The
testbench verifies its correctness by testing all possible input combinations.
Task 4: 4-bit Ripple Carry Adder
Verilog Code:
module ripple_carry_adder (
input [3:0] A, B,
input Cin,
output [3:0] Sum,
output Cout
);
wire [3:0] Carry;
full_adder fa0 (A[0], B[0], Cin, Sum[0], Carry[0]);
full_adder fa1 (A[1], B[1], Carry[0], Sum[1], Carry[1]);
full_adder fa2 (A[2], B[2], Carry[1], Sum[2], Carry[2]);
full_adder fa3 (A[3], B[3], Carry[2], Sum[3], Cout);
endmodule
Testbench:
module tb_ripple_carry_adder;
reg [3:0] A, B;
reg Cin;
wire [3:0] Sum;
wire Cout;
ripple_carry_adder uut (A, B, Cin, Sum, Cout);
initial begin
A = 4'b0011; B = 4'b0101; Cin = 0; #10;
A = 4'b1111; B = 4'b0001; Cin = 1; #10;
$stop;
end
endmodule
Explanation:
This module constructs a 4-bit ripple carry adder using four instances of a full adder.
The carry-out of each stage is fed into the next stage. The testbench verifies correct
summation and carry propagation.
Task 5: Logical Gates
Verilog Code:
module logic_gates (
input A, B,
output AND_out, OR_out, XOR_out, NOT_A
);
assign AND_out = A & B;
assign OR_out = A | B;
assign XOR_out = A ^ B;
assign NOT_A = ~A;
endmodule
Testbench:
module tb_logic_gates;
reg A, B;
wire AND_out, OR_out, XOR_out, NOT_A;
logic_gates uut (A, B, AND_out, OR_out, XOR_out, NOT_A);
initial begin
A = 0; B = 0; #10;
A = 0; B = 1; #10;
A = 1; B = 0; #10;
A = 1; B = 1; #10;
$stop;
end
endmodule
Explanation:
This module implements basic logic gates (AND, OR, XOR, and NOT). The
testbench verifies the correct functionality of each gate using different input
combinations.
Task 6: Half Adder and Full Adder (Gate-Level and
RTL Modeling)
Verilog Code:
module half_adder (
input A, B,
output Sum, Carry
);
assign Sum = A ^ B;
assign Carry = A & B;
endmodule
module full_adder (
input A, B, Cin,
output Sum, Cout
);
assign Sum = A ^ B ^ Cin;
assign Cout = (A & B) | (Cin & (A ^ B));
endmodule
Testbench:
module tb_half_full_adder;
reg A, B, Cin;
wire Sum_HA, Carry_HA;
wire Sum_FA, Cout_FA;
half_adder ha (A, B, Sum_HA, Carry_HA);
full_adder fa (A, B, Cin, Sum_FA, Cout_FA);
initial begin
A = 0; B = 0; Cin = 0; #10;
A = 0; B = 1; Cin = 0; #10;
A = 1; B = 1; Cin = 1; #10;
$stop;
end
endmodule
Explanation:
The half adder adds two bits and produces a sum and carry. The full adder extends
this by adding a carry-in bit. The testbench verifies different input combinations.
Task 7: 2-bit Binary Comparator
Verilog Code:
module comparator_2bit (
input [1:0] A, B,
output LT, EQ, GT
);
assign LT = (A < B);
assign EQ = (A == B);
assign GT = (A > B);
endmodule
Testbench:
module tb_comparator_2bit;
reg [1:0] A, B;
wire LT, EQ, GT;
comparator_2bit uut (A, B, LT, EQ, GT);
initial begin
A = 2'b00; B = 2'b01; #10;
A = 2'b10; B = 2'b10; #10;
A = 2'b11; B = 2'b01; #10;
$stop;
end
endmodule
Explanation:
This module compares two 2-bit numbers and outputs signals for less than, equal, or
greater conditions. The testbench verifies its functionality.
Task 8: 128-bit Binary Comparator (RTL Modeling)
Verilog Code:
module comparator_128bit (
input [127:0] A, B,
output LT, EQ, GT
);
assign LT = (A < B);
assign EQ = (A == B);
assign GT = (A > B);
endmodule
Testbench:
module tb_comparator_128bit;
reg [127:0] A, B;
wire LT, EQ, GT;
comparator_128bit uut (A, B, LT, EQ, GT);
initial begin
A = 128'h00000000000000000000000000000001;
B = 128'h00000000000000000000000000000002; #10;
A = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
B = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE; #10;
$stop;
end
endmodule
Explanation:
This module extends the functionality of a binary comparator to 128 bits, allowing
large numbers to be compared efficiently. The testbench checks various edge cases.
Task 9: 128-bit Adder
Verilog Code:
module adder_128bit (
input [127:0] A, B,
output [127:0] Sum
);
assign Sum = A + B;
endmodule
Testbench:
module tb_adder_128bit;
reg [127:0] A, B;
wire [127:0] Sum;
adder_128bit uut (A, B, Sum);
initial begin
A = 128'h00000000000000000000000000000001;
B = 128'h00000000000000000000000000000001; #10;
A = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
B = 128'h00000000000000000000000000000001; #10;
$stop;
end
endmodule
Explanation:
This module performs a 128-bit addition using a simple arithmetic operation. The
testbench tests normal and edge-case additions.
Task 10: Car Park Slot Counter
Verilog Code:
module car_park_counter (
input [2:0] slot_sensors,
output [2:0] occupied_count
);
assign occupied_count = slot_sensors[0] + slot_sensors[1] +
slot_sensors[2];
endmodule
Testbench:
module tb_car_park_counter;
reg [2:0] slot_sensors;
wire [2:0] occupied_count;
car_park_counter uut (slot_sensors, occupied_count);
initial begin
slot_sensors = 3'b000; #10;
slot_sensors = 3'b101; #10;
slot_sensors = 3'b111; #10;
$stop;
end
endmodule
Explanation:
This module counts the number of occupied slots in a 3-slot car park using sensor
inputs. The testbench verifies different occupancy scenarios.
Task 11: 128-bit Adder (RTL Modeling)
Verilog Code:
module adder_128bit (
input [127:0] A, B,
output [127:0] Sum
);
assign Sum = A + B;
endmodule
Testbench:
module tb_adder_128bit;
reg [127:0] A, B;
wire [127:0] Sum;
adder_128bit uut (A, B, Sum);
initial begin
A = 128'h00000000000000000000000000000001;
B = 128'h00000000000000000000000000000001; #10;
A = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
B = 128'h00000000000000000000000000000001; #10;
$stop;
end
endmodule
Explanation:
This module performs a 128-bit addition operation, using a simple arithmetic sum.
The testbench checks both normal and edge-case additions.
Task 12: Car Park Slot Counter with Artix-7 FPGA
Verilog Code:
module car_park_system (
input clk,
input rst,
input [2:0] slot_sensors,
output reg [2:0] occupied_count
);
always @(posedge clk or posedge rst) begin
if (rst)
occupied_count <= 3'b000;
else
occupied_count <= slot_sensors[0] + slot_sensors[1] +
slot_sensors[2];
end
endmodule
Testbench:
module tb_car_park_system;
reg clk, rst;
reg [2:0] slot_sensors;
wire [2:0] occupied_count;
car_park_system uut (clk, rst, slot_sensors, occupied_count);
always #5 clk = ~clk;
initial begin
clk = 0; rst = 1; slot_sensors = 3'b000; #10;
rst = 0; slot_sensors = 3'b010; #10;
slot_sensors = 3'b101; #10;
slot_sensors = 3'b111; #10;
$stop;
end
endmodule
Explanation:
Clock (clk) and reset (rst) inputs to work in an FPGA environment.
The occupied slot count updates on the positive edge of clk.
If rst is triggered, the counter resets to 0.
The testbench introduces a clock signal that toggles every 5 time units and
simulates different parking slot occupancy scenarios.
Task 13: Input-Output Manipulation System
Verilog Code:
module io_manipulation (
input [2:0] bin_input,
output reg [2:0] bin_output
);
always @(*) begin
if (bin_input <= 4)
bin_output = bin_input + 1;
else
bin_output = bin_input - 1;
end
endmodule
Testbench:
module tb_io_manipulation;
reg [2:0] bin_input;
wire [2:0] bin_output;
io_manipulation uut (bin_input, bin_output);
initial begin
bin_input = 3'b000; #10;
bin_input = 3'b011; #10;
bin_input = 3'b101; #10;
bin_input = 3'b111; #10;
$stop;
end
endmodule
Explanation:
This module manipulates input values based on their range. If the input is 0-4, the
output is incremented by 1, otherwise, it's decremented by 1. The testbench verifies
both conditions.
Task 14: Digital Circuit Representation in Verilog
Verilog Code:
module digital_circuit (
input A, B, C,
output X, Y, Z
);
assign X = (A & B) | C;
assign Y = (A ^ B) & C;
assign Z = ~(A | B);
endmodule
Testbench:
module tb_digital_circuit;
reg A, B, C;
wire X, Y, Z;
digital_circuit uut (A, B, C, X, Y, Z);
initial begin
A = 0; B = 0; C = 0; #10;
A = 0; B = 1; C = 1; #10;
A = 1; B = 1; C = 0; #10;
$stop;
end
endmodule
Explanation:
This module describes a digital circuit that performs AND, OR, and NOT operations
on inputs. The testbench verifies its logical correctness.
Task 15: Temperature Monitoring System
Verilog Code:
module temp_monitor (
input power_switch,
input [3:0] temp_sensor,
output reg alert
);
always @(*) begin
if (power_switch && temp_sensor > 4'b1010)
alert = 1'b1;
else
alert = 1'b0;
end
endmodule
Testbench:
module tb_temp_monitor;
reg power_switch;
reg [3:0] temp_sensor;
wire alert;
temp_monitor uut (power_switch, temp_sensor, alert);
initial begin
power_switch = 0; temp_sensor = 4'b1000; #10;
power_switch = 1; temp_sensor = 4'b1011; #10;
power_switch = 1; temp_sensor = 4'b0100; #10;
$stop;
end
endmodule
Explanation:
This module simulates a temperature monitoring system that triggers an alert if the
temperature exceeds a threshold (10 in binary). The testbench verifies the
functionality for different sensor readings.