VERILOG HDL CODE AND TESTBENCHES FOR DIGITAL EXPERIMENTS
1. VERIFICATION OF LOGIC EXPRESSIONS USING LOGIC GATES
------------------------------------------------------
Design: logic_expr.v
module logic_expr (
input a, b, c,
output y1,
output y2
);
assign y1 = (a & b) | (~c);
assign y2 = (~a & c) | b;
endmodule
Testbench: tb_logic_expr.v
`timescale 1ns/1ps
module tb_logic_expr;
reg a, b, c;
wire y1, y2;
logic_expr DUT (a, b, c, y1, y2);
initial begin
$display("a b c | y1 y2");
$monitor("%b %b %b | %b %b", a, b, c, y1, y2);
a=0; b=0; c=0;
#10 a=0; b=0; c=1;
#10 a=0; b=1; c=0;
#10 a=1; b=0; c=0;
#10 a=1; b=1; c=1;
#10 $finish;
end
endmodule
2. IMPLEMENTATION OF LOGIC FUNCTIONS USING NAND–NOR GATES
---------------------------------------------------------
Design: nand_nor_logic.v
module nand_nor_logic(
input a, b, c,
output f1,
output f2,
output f3
);
// AND using NAND
wire t1;
nand (t1, a, b);
nand (f1, t1, t1);
// OR using NOR
wire t2;
nor (t2, a, b);
nor (f2, t2, t2);
// XOR using NAND
wire n1,n2,n3;
nand (n1, a, b);
nand (n2, a, n1);
nand (n3, b, n1);
nand (f3, n2, n3);
endmodule
Testbench: tb_nand_nor_logic.v
`timescale 1ns/1ps
module tb_nand_nor_logic;
reg a,b,c;
wire f1,f2,f3;
nand_nor_logic DUT(a,b,c,f1,f2,f3);
initial begin
$display("a b | AND OR XOR");
$monitor("%b %b | %b %b %b", a,b,f1,f2,f3);
a=0; b=0;
#10 a=0; b=1;
#10 a=1; b=0;
#10 a=1; b=1;
#10 $finish;
end
endmodule
3. DESIGN & VERIFICATION OF ADDERS / SUBTRACTOR
-----------------------------------------------
Half Adder: half_adder.v
module half_adder(a, b, sum, carry);
input a, b;
output sum, carry;
assign sum = a ^ b;
assign carry = a & b;
endmodule
Full Adder: full_adder.v
module full_adder(a, b, cin, sum, carry);
input a, b, cin;
output sum, carry;
assign sum = a ^ b ^ cin;
assign carry = (a & b) | (b & cin) | (a & cin);
endmodule
Subtractor: subtractor.v
module subtractor(a, b, diff, borrow);
input a, b;
output diff, borrow;
assign diff = a ^ b;
assign borrow = (~a) & b;
endmodule
Testbench: tb_add_sub.v
`timescale 1ns/1ps
module tb_add_sub;
reg a,b,cin;
wire sum,carry;
wire diff,borrow;
full_adder FA(a,b,cin,sum,carry);
subtractor SUB(a,b,diff,borrow);
initial begin
$display("a b cin | sum carry | diff borrow");
$monitor("%b %b %b | %b %b | %b %b",
a,b,cin,sum,carry,diff,borrow);
a=0; b=0; cin=0;
#10 a=0; b=1; cin=0;
#10 a=1; b=0; cin=1;
#10 a=1; b=1; cin=1;
#10 $finish;
end
endmodule
4. BCD ADDER + BCD → 7-SEGMENT DECODER
---------------------------------------
BCD Adder: bcd_adder.v
module bcd_adder(a, b, cin, sum, cout);
input [3:0] a, b;
input cin;
output reg [3:0] sum;
output reg cout;
reg [4:0] temp;
always @(*) begin
temp = a + b + cin;
if (temp > 9) begin
temp = temp + 6;
cout = 1;
end else begin
cout = 0;
end
sum = temp[3:0];
end
endmodule
BCD to 7-seg: bcd_to_7seg.v
module bcd_to_7seg(bcd, seg);
input [3:0] bcd;
output reg [6:0] seg;
always @(*) begin
case(bcd)
4'd0: seg = 7'b0000001;
4'd1: seg = 7'b1001111;
4'd2: seg = 7'b0010010;
4'd3: seg = 7'b0000110;
4'd4: seg = 7'b1001100;
4'd5: seg = 7'b0100100;
4'd6: seg = 7'b0100000;
4'd7: seg = 7'b0001111;
4'd8: seg = 7'b0000000;
4'd9: seg = 7'b0000100;
default: seg = 7'b1111111;
endcase
end
endmodule
Testbench: tb_bcd_add_7seg.v
`timescale 1ns/1ps
module tb_bcd_add_7seg;
reg [3:0] a,b;
reg cin;
wire [3:0] sum;
wire cout;
wire [6:0] seg;
bcd_adder BA(a,b,cin,sum,cout);
bcd_to_7seg DEC(sum, seg);
initial begin
$display("a b | sum cout | 7seg");
a=4; b=7; cin=0;
#10 a=6; b=8;
#10 a=9; b=9;
#10 $finish;
end
endmodule
5. MULTIPLEXER / DEMULTIPLEXER
------------------------------
4×1 MUX: mux4.v
module mux4 (input [3:0] d, input [1:0] s, output y);
assign y = s==2'b00 ? d[0] :
s==2'b01 ? d[1] :
s==2'b10 ? d[2] :
d[3];
endmodule
1×4 DEMUX: demux1_4.v
module demux1_4(input din, input [1:0] s, output reg [3:0] y);
always @(*) begin
y = 4'b0000;
y[s] = din;
end
endmodule
Testbench: tb_mux_demux.v
`timescale 1ns/1ps
module tb_mux_demux;
reg [3:0] d;
reg [1:0] s;
wire y;
wire [3:0] dm;
mux4 M1 (d, s, y);
demux1_4 D1 (y, s, dm);
initial begin
d = 4'b1010;
s = 2'b00; #10
s = 2'b01; #10
s = 2'b10; #10
s = 2'b11; #10
$finish;
end
endmodule
6. ENCODER / DECODER
--------------------
8-to-3 Encoder: encoder8_3.v
module encoder8_3(d, y);
input [7:0] d;
output reg [2:0] y;
always @(*) begin
case(d)
8'b00000001: y=3'b000;
8'b00000010: y=3'b001;
8'b00000100: y=3'b010;
8'b00001000: y=3'b011;
8'b00010000: y=3'b100;
8'b00100000: y=3'b101;
8'b01000000: y=3'b110;
8'b10000000: y=3'b111;
default: y=3'bxxx;
endcase
end
endmodule
3-to-8 Decoder: decoder3_8.v
module decoder3_8(a, y);
input [2:0] a;
output reg [7:0] y;
always @(*) begin
y = 8'b00000000;
y[a] = 1'b1;
end
endmodule
Testbench: tb_enc_dec.v
`timescale 1ns/1ps
module tb_enc_dec;
reg [7:0] d;
wire [2:0] y;
wire [7:0] dec;
encoder8_3 ENC(d, y);
decoder3_8 DEC(y, dec);
initial begin
d=8'b00000100; #10;
d=8'b01000000; #10;
d=8'b00010000; #10;
$finish;
end
endmodule
7. Design of 4-bit comparator
module comparator_4bit (
input [3:0] A, B,
output reg A_greater,
output reg A_equal
output reg A_less );
always @(A or B)
begin
if (A>B)
regA_greater =1
else if (A<B)
reg A_less =1
else
reg A_equal =1
end
endmodule
TESTBENCH – 4-bit Comparator
timescale 1ns/1ps
module tb_comparator_4bit;
reg [3:0] A, B;
wire A_greater, A_equal, A_less;
comparator_4bit dut (
.A(A),
.B(B),
.A_greater(A_greater),
.A_equal(A_equal),
.A_less(A_less)
);
initial begin
A = 4'd10; B = 4'd5; #10;
A = 4'd3; B = 4'd12; #10;
A = 4'd7; B = 4'd7; #10;
$stop;
end
initial begin
$monitor("Time=%0t | A=%d B=%d | > =%b, == =%b, < =%b",
$time, A, B, A_greater, A_equal, A_less);
end
endmodule
8. DESIGN OF CODE CONVERTOR – BINARY TO GRAY CODE
module binary_to_gray ( input [3:0] binary, output [3:0] gray );
assign gray[3] = binary[3];
assign gray[2] = binary[3] ^ binary[2];
assign gray[1] = binary[2] ^ binary[1];
assign gray[0] = binary[1] ^ binary[0];
endmodule
TEST BENCH – BINARY TO GRAY CODE
timescale 1ns/1ps
module tb_binary_to_gray;
reg [3:0] binary;
wire [3:0] gray;
binary_to_gray dut (
.binary(binary),
.gray(gray)
);
initial begin
binary = 4'b0000; #10;
binary = 4'b0001; #10;
binary = 4'b0010; #10;
binary = 4'b0100; #10;
binary = 4'b0111; #10;
$stop;
end
initial begin
$monitor("Time=%0t | Binary=%b | Gray=%b",
$time, binary, gray);
end
endmodule
9. DESIGN OF JK FLIPFLOP
module jk_ff (
input wire clk,
input wire rst
input wire J,
input wire K,
output reg Q
);
always @(posedge clk or posedge rst) begin
if (rst)
Q <= 0;
else begin
case ({J, K})
2'b00: Q <= Q;
2'b01: Q <= 0;
2'b10: Q <= 1;
2'b11: Q <= ~Q;
endcase
end
end
endmodule
TESTBENCH – JK FLIPFLOP
timescale 1ns/1ps
module tb_jk_ff;
reg clk, rst;
reg J, K;
wire Q;
jk_ff dut (
.clk(clk),
.rst(rst),
.J(J),
.K(K),
.Q(Q)
);
always #5 clk = ~clk;
initial begin
clk = 0;
rst = 1;
J = 0;
K = 0;
#10 rst = 0;
J = 0; K = 0; #10;
J= 0; K = 1; #10;
J = 1; K = 0; #10;
J = 1; K = 1; #10;
#20;
$stop;
end
initial begin
$monitor("Time=%0t | J=%b K=%b | Q=%b",
$time, J, K, Q);
end
endmodule
10 A. RING COUNTER
module ring_counter (
input wire clk,
input wire rst,
output reg [3:0] q
);
always @(posedge clk or posedge rst) begin
if (rst)
q <= 4'b0001;
else
q <= {q[2:0], q[3]};
end
endmodule
TESTBENCH –RING COUNTER
timescale 1ns/1ps
module tb_ring_counter;
reg clk, rst;
wire [3:0] q;
ring_counter dut (
.clk(clk),
.rst(rst),
.q(q) );
always #5 clk = ~clk;
initial begin
clk = 0;
rst = 1;
#10;
rst = 0;
#200;
$stop;
end
initial begin
$monitor("Time=%0t | q = %b", $time, q);
end
endmodule
10 B. MOD N COUNTER
module modN_counter #(parameter N = 10) (
input wire clk,
input wire rst,
output reg [$clog2(N)-1:0] count
);
always @(posedge clk or posedge rst) begin
if (rst)
count <= 0;
else if (count == N-1)
count <= 0;
else
count <= count + 1;
end
endmodule
TESTBENCH – MOD N COUNTER
timescale 1ns/1ps
module tb_modN;
parameter N = 10; // Change N to test different modulus
reg clk, rst;
wire [$clog2(N)-1:0] count;
modN_counter #(N) dut (
.clk(clk),
.rst(rst),
.count(count)
);
always #5 clk = ~clk;
initial begin
clk = 0;
rst = 1;
#10;
rst = 0;
#200;
$stop; end
initial begin
$monitor("Time = %0t | Count = %d", $time, count);
end
endmodule
10.C. 4-bit Ripple Counter
SUBPROGRAM –T Flip flop
module T_ff (
input clk,
input rst,
output reg q
);
always @(posedge clk or posedge rst) begin
if (rst)
q <= 0;
else
q <= ~q;
end
endmodule
MAIN PROGRAM
module ripple_counter_4bit (
input clk,
input rst,
output [3:0] q
);
T_ff t0 (.clk(clk), .rst(rst), .q(q[0]));
T_ff t1 (.clk(q[0]), .rst(rst), .q(q[1]));
T_ff t2 (.clk(q[1]), .rst(rst), .q(q[2]));
T_ff t3 (.clk(q[2]), .rst(rst), .q(q[3]));
endmodule
TESTBENCH
timescale 1ns/1ps
module tb_ripple_counter_4bit;
reg clk, rst;
wire [3:0] q;
ripple_counter_4bit dut (
.clk(clk),
.rst(rst),
.q(q));
always #5 clk = ~clk;
initial begin
clk = 0;
rst = 1;
#10 rst = 0;
#200;
$stop;
end
initial begin
$monitor("Time=%0t | Count = %b (%0d)", $time, q, q);
end
endmodule
11. UNIVERSAL SHIFT REGISTER
module universal_shift_register (
input [3:0] data_in,
input sl, sr,
input [1:0] sel,
input clk,
output reg [3:0] q
);
always @(posedge clk)
begin
case (sel)
2'b00: q <= q;
2'b01: q <= {sr, q[3:1]};
2'b10: q <= {q[2:0], sl};
2'b11: q <= data_in;
default: q <= q;
endcase
end
endmodule
TESTBENCH – UNIVERSAL SHIFT REGISTER
`timescale 1ns/1ps
module tb_universal_shift_register;
reg [3:0] data_in;
reg sl, sr;
reg [1:0] sel;
reg clk;
wire [3:0] q;
universal_shift_register dut (
.data_in(data_in),
.sl(sl),
.sr(sr),
.sel(sel),
.clk(clk),
.q(q) );
always #5 clk = ~clk;
initial begin
clk = 0;
sel = 2'b11;
data_in = 4'b1010;
sl = 0; sr = 0;
#10;
sel = 2'b00;
#20;
sel = 2'b01;
sr = 1;
#20;
sel = 2'b10;
sl = 1;
#20;
sl = 0;
#20;
$stop;
end
initial begin
$monitor("Time=%0t | sel=%b | sl=%b sr=%b | data_in=%b | q=%b",
$time, sel, sl, sr, data_in, q);
end
endmodule
12. A. 8-bit Serial-In Parallel-Out (SIPO) Register
module sipo_8bit (
input clk,
input rst,
input serial_in,
output reg [7:0] parallel_out
);
always @(posedge clk or posedge rst) begin
if (rst)
parallel_out <= 8'b00000000;
else
parallel_out <= {parallel_out[6:0], serial_in};
end
endmodule
TESTBENCH - 8-bit Serial-In Parallel-Out (SIPO) Register
timescale 1ns/1ps
module tb_sipo_8bit;
reg clk, rst;
reg serial_in;
wire [7:0] parallel_out;
sipo_8bit dut (
.clk(clk),
.rst(rst),
.serial_in(serial_in),
.parallel_out(parallel_out)
);
always #5 clk = ~clk;
initial begin
clk = 0;
rst = 1;
serial_in = 0;
#10 rst = 0;
serial_in = 1; #10;
serial_in = 1; #10;
serial_in = 0; #10;
serial_in = 1; #10;
serial_in = 0; #10;
serial_in = 0; #10;
serial_in = 1; #10;
serial_in = 1; #10;
$stop;
end
initial begin
$monitor("Time=%0t | Serial In=%b | Parallel Out=%b",
$time, serial_in, parallel_out);
end
endmodule
12.B 8-bit PISO Register
module piso_8bit (
input clk,
input rst,
input load,
input [7:0] parallel_in,
output serial_out
);
reg [7:0] shift_reg;
assign serial_out = shift_reg[7];
always @(posedge clk or posedge rst) begin
if (rst)
shift_reg <= 8'b0;
else if (load)
shift_reg <= parallel_in;
else
shift_reg <= {shift_reg[6:0], 1'b0};
end
endmodule
TESTBENCH - 8-bit PISO Register
timescale 1ns/1ps
module tb_piso_8bit;
reg clk, rst, load;
reg [7:0] parallel_in;
wire serial_out;
piso_8bit dut (
.clk(clk),
.rst(rst),
.load(load),
.parallel_in(parallel_in),
.serial_out(serial_out) );
always #5 clk = ~clk; // Clock
initial begin
clk = 0; rst = 1; load = 0;
parallel_in = 0;
#10 rst = 0;
load = 1;
parallel_in = 8'b10110011;
#10;
load = 0;
#100;
$stop;
end
initial begin
$monitor("Time=%0t | Serial Out = %b", $time, serial_out);
end
endmodule