0% found this document useful (0 votes)
3 views80 pages

VLSI Testing

Uploaded by

my1005tube
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views80 pages

VLSI Testing

Uploaded by

my1005tube
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

VLSI Testing

(ME02000181)

LABORATORY MANUAL

SEMESTER II

VLSI Design

[ DEPARTMENT OF

ELECTRONICS AND COMMUNICATION ]

L.D. COLLEGE OF ENGINEERING – AHMEDABAD


L.D. College of Engineering
Electronics and Communication Department

Certificate

This is to certify that Mr. Khichadiya Dip Rameshbhai of Electronics and


Communication Department with Enrolment Number 250280763009 has
satisfactorily completed his entire practical work in the subject of ME02000181:
VLSI Testing

Lab In-Charge
Prof. Dhaval Patel
INDEX
Sr. Title of Experiment Pg. No. Date Sign
No.
1. To develop an exhaustive testbench for 4
lower-level combinational designs:
(1) Adder
(2) Subtractor
(3) Multiplexer
(4) Demultiplexer

2. To develop testbench for various flip-flops. 24


3. To develop testbench for various counters: 35
Ring Counter and Johson Counter
4. Write a HDLcode and testbench to realize 39
functioning of Linear Feedback Shift
Register (LFSR).

5. Write a HDL code and testbench to implement 43


8 BIT ALU

6. Write a HDL code to realize functioning of 32- 47


bit RAM.
7. Write a HDL code to realize functioning of 52
Observation Point Insertion Technique.

8. Write a HDL code to realize functioning of 55


Control Point Insertion Technique

9. Write HDL code for MUX-D scan cell and 58


Level Sensitive/Edge Triggered MUXED-D
scan cell
10. Write a HDL code to realize functioning of 65
clocked scan cell and LSSD scan cell design

11. Write a HDL code to realize functioning of 72


LSSD double latch design

12. Write a HDL code to realize functioning of 76


fixing bus contention in scan design rules
250280763009 ME02000181

EXPERIMENT 1

To develop an exhaustive testbench for lower-level combinational designs: (1)


Adder (2)Subtractor(3) Multiplexer (4) Demultiplexer

 Half Adder:

Theory: A half-adder is a basic digital circuit used for adding two single-bit binary numbers. It
consists of two inputs, A and B, and two outputs, Sum and Carry.
 Sum: Represents the least significant bit of the addition result. It is obtained by performing an
XOR operation on the inputs A and B.

Figure 1 HALF_ADDER truth table & realization

 Carry: Represents the most significant bit, which indicates if there is an overflow from the
addition. It is obtained by performing an AND operation on the inputs A and B.

DESIGN CODE:

 Dataflow Modeling

module half_adder (
input a, b,
output sum, carry
);
assign sum = a ^ b;
assign carry = a & b;
endmodule

 Behavioral modeling

module half_adder ( input a, b,


output sum, carry
);
4
250280763009 ME02000181

always@(*) begin
sum = a ^ b; carry = a & b;
end
endmodule

 Structural Modeling

module half_adder ( input a, b,


output sum, carry
);
xor X1(sum, a, b); and A1(carry, a, b);
endmodule

TESTBENCH:

module tb_half_adder;
reg a, b;
wire sum, carry;
half_adder uut ( a, b, sum, carry);
initial begin
$dumpfile("half_adder.vcd");
$dumpvars(0, tb_half_adder);
$monitor("At time %t, a = %b, b = %b, sum = %b, carry = %b", $time, a, b, sum, carry);
// test cases
a = 0; b = 0; #10;
a = 0; b = 1; #10;
a = 1; b = 0; #10;
a = 1; b = 1; #10;
a = 0; b = 0; #10;
$finish;
end
endmodule

OUTPUT WAVEFORM:

5
250280763009 ME02000181

CODE COVERAGE:

 Full Adder:

Theory: A full-adder is a digital circuit used to add three single-bit binary numbers: two significant
bits (A and B) and a carry-in bit (Cin) from a previous addition. It has three inputs and two
outputs:
 Sum: The least significant bit of the addition result, calculated using the XOR operation on all
three inputs (A, B, and Cin).
 Carry-out (Cout): Indicates if there is a carry-over to the next higher bit position, determined by
the majority function of the inputs (A, B, and Cin). It is calculated using the OR operation on the
AND operations of the inputs.

DESIGN CODE:

 Dataflow Modeling

module full_adder ( input a, b, cin, output sum, carry


6
250280763009 ME02000181

);
assign sum = a ^ b ^ cin;
assign carry = (a & b) | (b & cin) | (cin & a);
endmodule

 Behavioral modeling

module full_adder ( input a, b, cin, output sum, carry


);
Always@(*) begin sum = a ^ b ^ cin;
carry = (a & b) | (b & cin) | (cin & a); end
endmodule

 Structural Modeling

module full_adder ( input a, b, cin, output sum, carry


);
Xor (w1, a, b);
xor (sum, w1, cin);
and (w2, a, b);
and (w3, b, cin);
and (w4, cin, a);
or(carry, w2, w3, w4); endmodule

TESTBENCH:

module tb_full_adder; reg a, b, cin;


wire sum, carry;
full_adder uut (a, b, cin, sum, carry); initial begin
$dumpfile("full_adder.vcd");
$dumpvars(0, tb_full_adder);
$monitor("At time %t, a = %b, b = %b, cin = %b, sum = %b, cout = %b", $time, a, b, cin, sum, carry);
// test cases
a = 0; b = 0; cin = 0; #10;
a = 0; b = 0; cin = 1; #10;
a = 0; b = 1; cin = 1; #10;
a = 0; b = 1; cin = 0; #10;
a = 1; b = 0; cin = 1; #10;
a = 1; b = 0; cin = 0; #10;
a = 1; b = 1; cin = 1; #10;
a = 1; b = 1; cin = 0; #10;
$finish; end
Endmodule

7
250280763009 ME02000181

OUTPUT WAVEFORM:

CODE COVERAGE:

 Half Subtractor:
Theory: A half-subtractor is a basic digital circuit used for subtracting two single-bit binary
numbers. It consists of two inputs, A and B, and two outputs, Difference and Borrow.
 Difference: Represents the least significant bit of the addition result. It is obtained by
performing an XOR operation on the inputs A and B.
 Borrow: Represents the most significant bit, which indicates if there is an overflow from the
addition. It is obtained by performing an AND operation on the inputs ~A and B.

8
250280763009 ME02000181

DESIGN CODE:

 Dataflow Modeling

module half_subtractor ( input a, b,


output diff, borrow
);
assign diff = a ^ b;
assign borrow = ~a & b;
endmodule

 Behavioral modeling

module half_subtractor ( input a, b,


output diff, borrow
);
Alwaya@(*) begin diff = a ^ b;
borrow = ~a & b;
end endmodule

 Structural Modeling

module half_subtractor ( input a, b,


output diff, borrow
);
wire x;
xor (diff , a, b);
not (x, a);
and (borrow, x, b);
endmodule

TESTBENCH:

module tb_half_subtractor;
reg a, b;
wire diff, borrow;
half_subtractor uut ( a, b, diff, bout);
initial begin
$dumpfile("half_subtractor.vcd");
$dumpvars(0, tb_half_subtractor);
$monitor("At time %t, a = %b, b = %b, diff = %b, = %b", $time, a, b, diff, borrow);
// test cases
a = 0; b = 1; #10;
a = 1; b = 1; #10;

9
250280763009 ME02000181

a = 0; b = 0; #10;
a = 1; b = 0; #10;
a = 0; b = 1; #10;
$finish;
end
Endmodule

OUTPUT WAVEFORM:

CODE COVERAGE:

 FULL SUBTRACTOR
Theory: A full subtractor is a digital circuit used to subtract three single-bit binary numbers: two
significant bits (A and B) and a borrow-in bit (Bin) from a previous subtraction. It has three inputs
and two outputs:
 Difference: The result of subtracting B and Bin from A, calculated using the XOR operation on all
three inputs (A, B, and Bin).
 Borrow-out (Bout): Indicates if a borrow is needed for the next higher bit position, determined
by checking if A is less than the combination of B and Bin. It is calculated using the OR and
AND operations on the inputs.

10
250280763009 ME02000181

DESIGN CODE:

 Dataflow Modeling

module full_subtractor ( input a, b, bin,


output diff, borrow
);
assign diff = a ^ b ^ bin;
assign borrow = (~a & b) | (~(a ^ b) & bin);
endmodule

 Behavioral modeling

module full_subtractor ( input a, b, bin,


output diff, borrow
);
Always@(*) begin
diff = a ^ b ^ bin;
borrow = (~a & b) | (~(a ^ b) & bin);
end
endmodule

 Structural Modeling

module full_subtractor ( input a, b, bin,


output diff, borrow
);
wire w1, w2, w3, w4; xor G1(w1, a, b);
xor G2(diff, w1, bin); and G3(w2, ~a, b); and G4(w3, ~a, bin); and G5(w4, b, bin);
or G6(bout, w2, w3, w4);
endmodule

11
250280763009 ME02000181

TESTBENCH:

module tb_full_subtractor; reg a, b, bin;


wire diff, bout;
full_subtractor uut (a, b, bin, diff, bout); initial begin
$dumpfile("full_subtractor.vcd");
$dumpvars(0, tb_full_subtractor);
$monitor("At time %t, a = %b, b = %b, bin = %b, diff = %b, bout = %b", $time, a, b, bin, diff, bout);
//test cases
a = 0; b = 0; bin = 0; #10;
a = 0; b = 0; bin = 1; #10;
a = 0; b = 1; bin = 0; #10;
a = 0; b = 1; bin = 1; #10;
a = 1; b = 0; bin = 0; #10;
a = 1; b = 0; bin = 1; #10;
a = 1; b = 1; bin = 0; #10;
a = 1; b = 1; bin = 1; #10;
$finish; end
Endmodule

OUTPUT WAVEFORM:

CODE COVERAGE:

12
250280763009 ME02000181

 Multiplexer
Theory: Multiplexer is a digital logic device which is used to perform multiplexing of data. Where,
multiplexing simply means sharing of data. Technically, when a particular data is selected from
multiple input data sources and transmitted the selected data to a single output channel, it is called
multiplexing.
There are two types of multiplexing namely, frequency multiplexing and time multiplexing. When
multiple devices are connected to a single transmission line in a system. At any point of time, only one
device is using the line to transmit data, then this is called time multiplexing.
On the other hand, when multiple devices share a common line to transmit data but at different
frequencies, it is called frequency multiplexing.

4*1 MULTIPLEXER

4×1 Multiplexer has four data inputs I3, I2, I1 & I0, two selection lines s1 & s0 and one output Y. One of
these 4 inputs will be connected to the output based on the combination of inputs present at these two
selection lines. Truth table of 4×1 Multiplexer is shown below

DESIGN CODE:

 Dataflow Modeling

module mux4to1 ( input wire [3:0] I, input wire [1:0] sel, output wire y
);
assign y = (I[0] & ~sel[1] & ~sel[0]) | (I[1] & ~sel[1] & sel[0]) | (I[2] & sel[1] & ~sel[0]) | (I[3] &
sel[1] & sel[0]);
endmodule

 Behavioral modeling

module mux4to1 ( input wire [3:0] I, input wire [1:0] sel, output reg y
);
always @(*) begin
13
250280763009 ME02000181

case (sel)
2'b00: y = I[0];
2'b01: y = I[1];
2'b10: y = I[2];
2'b11: y = I[3];
default: y = I[0];
endcase
end
endmodule

 Structural Modeling

module mux4to1 ( input wire [3:0] I,


input wire [1:0] sel,
output wire y
);
wire nsel0, nsel1;
wire and0, and1, and2, and3;
not (nsel0, sel[0]);
not (nsel1, sel[1]);
and (and0, I[0], nsel1, nsel0);
and (and1, I[1], nsel1, sel[0]);
and (and2, I[2], sel[1], nsel0);
and (and3, I[3], sel[1], sel[0]);
or (y, and0, and1, and2, and3);
endmodule

TESTBENCH:

module tb_mux4to1;
reg [3:0] I;
reg [1:0] sel;
wire y;
mux4to1 uut (.I(I), .sel(sel),.y(y));
initial begin
$dumpfile("[Link]");
$dumpvars(0, tb_mux4to1);
// TEST CONDITIONS
I = 4'b1111; sel = 2'bxx; #10;
I = 4'b1010; sel = 2'b00; #10;
I = 4'b0101; sel = 2'b00; #10;

I = 4'b0101; sel = 2'b01; #10;


I = 4'b1010; sel = 2'b01; #10;

I = 4'b1010; sel = 2'b10; #10;


14
250280763009 ME02000181

I = 4'b0101; sel = 2'b10; #10;

I = 4'b0101; sel = 2'b11; #10;


I = 4'b1010; sel = 2'b11; #10;

I = 4'b1111; sel = 2'b00; #10;


$finish;
end
endmodule

OUTPUT WAVEFORM:

CODE COVERAGE:

4x1 MUX using 2x1 MUX

Three 2: 1 MUX are required to implement 4 : 1 MUX.


In a hierarchical design, all we need is to design a small block and construct a big block using these small
blocks. Now we have constructed our 2×1 mux we can easily construct 4×1 mux using three of these 2×1
muxes.
15
250280763009 ME02000181

When S1 is set to HIGH it will select i1 and i3 now if s0 is LOW output will have i1 otherwise i3 and
similar for i0 and i2.

DESIGN CODE:

module mux2to1 ( input wire a, input wire b, input wire sel, output wire y
);
assign y = sel ? b : a;
endmodule module mux4to1 (
input wire [3:0] I, input wire [1:0] sel, output wire y
);
wire mux1_out, mux2_out;
mux2to1 mux1 (.a(I[0]), .b(I[1]), .sel(sel[0]), .y(mux1_out));
mux2to1 mux2 (.a(I[2]), .b(I[3]), .sel(sel[0]), .y(mux2_out));
mux2to1 mux3 (.a(mux1_out), .b(mux2_out), .sel(sel[1]), .y(y));
endmodule

TESTBENCH:

module tb_mux4to1; reg [3:0] I;


reg [1:0] sel; wire y; mux4to1 uut (
.I(I),
.sel(sel),
.y(y)
);
initial begin
$dumpfile("mux4to1_using_2to1.vcd");
$dumpvars(0, tb_mux4to1);
//TEST CONDITIONS
I = 4'b0001; sel = 2'b00; #10;
I = 4'b0010; sel = 2'b01; #10; I = 4'b0100; sel = 2'b10; #10; I = 4'b1000; sel = 2'b11; #10; I = 4'b1110; sel =
2'b00; #10; I = 4'b1110; sel = 2'b01; #10; I = 4'b1110; sel = 2'b10; #10; I = 4'b1110; sel = 2'b11; #10;
16
250280763009 ME02000181

$display("Time: %0t | I = %b | sel = %b | y = %b", $time, I, sel, y);


$finish; end
endmodule

OUTPUT WAVEFORM:

CODE COVERAGE:

DEMULTIPLEXER

Theory: A demultiplexer (DEMUX) is a digital logic device used to route a single input data source
to one of multiple output channels based on select signals. Essentially, it performs the reverse
function of a multiplexer, allowing data from one source to be distributed to various destinations.
There are two types of Demultiplexing namely, frequency Demultiplexing and time Demultiplexing. when
a single data source transmits data to multiple devices at different time intervals At any given moment,
only one device receives the data while others remain inactive. This method optimizes the use of
communication channels.
On the other hand, a single source transmits multiple signals over a common channel at different
frequencies. The demultiplexer separates these frequencies, directing the appropriate signal to its
corresponding output.

17
250280763009 ME02000181

1X4 DEMULTIPLEXER:

A 1×4 Demultiplexer has one data input I, two selection lines s1 & s0, and four outputs Y3, Y2, Y1, and
Y0. The single input will be routed to one of these 4 outputs based on the combination of inputs present at
the two selection lines. The truth table of the 1×4 Demultiplexer is shown below:

DESIGN CODE:

 Dataflow Modeling

module demux1to4 ( input wire I,


input wire [1:0] sel, output wire [3:0] Y
);
assign Y[0] = I & ~sel[1] & ~sel[0];
assign Y[1] = I & ~sel[1] & sel[0];
assign Y[2] = I & sel[1] & ~sel[0];
assign Y[3] = I & sel[1] & sel[0];
endmodule

 Behavioral modeling

module demux1to4 ( input wire I,


input wire [1:0] sel, output reg [3:0] Y
);
always @(*)
begin Y = 4'b0000;
case (sel)
2'b00: Y[0] = I;
2'b01: Y[1] = I;
2'b10: Y[2] = I;
2'b11: Y[3] = I;
default: Y[0] = I;
endcase
end
18
250280763009 ME02000181

endmodule

 Structural Modeling

module demux1to4 ( input wire I,


input wire [1:0] sel, output wire [3:0] Y
);
wire nsel0, nsel1;
not (nsel0, sel[0]);
not (nsel1, sel[1]);
and (Y[0], I, nsel1, nsel0);
and (Y[1], I, nsel1, sel[0]);
and (Y[2], I, sel[1], nsel0);
and (Y[3], I, sel[1], sel[0]);
endmodule

TESTBENCH:

module tb_demux1to4; reg I;


reg [1:0] sel;
wire [3:0] Y; demux1to4 uut (
.I(I),
.sel(sel),
.Y(Y)
);
initial begin
$dumpfile("[Link]");
$dumpvars(0, tb_demux1to4);
//TEST CONDITIONS
I = 1'b1; sel = 2'b00; #10;
I = 1'b0; sel = 2'b01; #10;
I = 1'b1; sel = 2'b01; #10;
I = 1'b0; sel = 2'b10; #10;
I = 1'b1; sel = 2'b11; #10;
I = 1'b1; sel = 2'b00; #10;
I = 1'b0; sel = 2'bxx; #10;
I = 1'b0; sel = 2'b01; #10;
I = 1'b1; sel = 2'b10; #10;
I = 1'b0; sel = 2'b11; #10;
$finish;
end
endmodule

19
250280763009 ME02000181

OUTPUT WAVEFORM:

CODE COVERAGE:

1x4 DEMUX using 2x1 DEMUX

Three 1:2 DEMUXs are required to implement a 1:4 DEMUX.


In a hierarchical design approach, we first design a smaller block and then use these small blocks to
construct a larger block. Once we have designed our 1:2 demux, we can easily construct a 1:4 demux
using three of these 1:2 demux’s.
When S1 is set to HIGH, the 1:4 DEMUX will select the lower two outputs (y2 and y3). If S0 is LOW, y2
will be active, otherwise y3 will be active. Similarly, when S1 is set to LOW, it will select the upper two
outputs (y0 and y1). If S0 is LOW, y0 will be active, otherwise y1 will be active.

20
250280763009 ME02000181

DESIGN CODE:

 Dataflow Modeling

module demux1to2 ( input wire sel, input wire din, output wire y0, output wire y1
);
assign y0 = (~sel) ? din : 0; assign y1 = sel ? din : 0;
endmodule

module demux1to4 ( input wire din, input wire [1:0] sel, output wire [3:0] y
);
wire demux1_out1, demux1_out2;
demux1to2 demux1 (.sel(sel[1]), .din(din), .y0(demux1_out1), .y1(demux1_out2));
demux1to2 demux2 (.sel(sel[0]), .din(demux1_out1), .y0(y[0]), .y1(y[1]));
demux1to2 demux3 (.sel(sel[0]), .din(demux1_out2), .y0(y[2]), .y1(y[3]));
endmodule

TESTBENCH:

module tb_demux1to4;
reg din;
reg [1:0] sel;
wire [3:0] y;

demux1to4 uut (
.din(din),
.sel(sel),
.y(y)
);

initial begin
$dumpfile("demux1to4_using_1to2.vcd");
$dumpvars(0, tb_demux1to4);
21
250280763009 ME02000181

//TEST CONDITIONS
din = 0; sel = 2'b00; #10;
din = 1; sel = 2'b01; #10;
din = 1; sel = 2'b10; #10;
din = 1; sel = 2'b11; #10;
din = 0; sel = 2'b00; #10;
din = 0; sel = 2'b01; #10;
din = 0; sel = 2'b10; #10;
din = 0; sel = 2'b11; #10;
$display("Time: %0t | din = %b | sel = %b | y = %b", $time, din, sel, y);
$finish;
end
endmodule

OUTPUT WAVEFORM:

CODE COVERAGE:

22
250280763009 ME02000181

EXPERIMENT 2

To develop testbench for various flip-flops.

Flip-Flop
A flip-flop is a type of sequential logic circuit that stores a single bit of data (0 or 1). Unlike latches, flip-
flops are edge-triggered devices, meaning they change state only at specific moments (on the rising or
falling edge of a clock signal). Flip-flops are widely used in digital electronics for data storage,
synchronization, and sequential logic operations.
Applications of Flip-Flops:

 Data Storage: Registers and memory elements in processors and other digital systems.
 Synchronization: Flip-flops are used in synchronous circuits where all operations are synchronized
to a clock.
 Counters and Dividers: Used in building counters, frequency dividers, and state machines.
 Control Systems: Flip-flops help in holding states and ensuring data is only latched on specific
clock edges.

 D Flip Flop
A D flip- flop stands for data or delay flip-flop. The outputs of this flip-flop are equal to the inputs.

DESIGN CODE:

 Behavioral Code:

module d_flip_flop (
input wire D, // Data input
input wire CLK, // Clock input
output reg Q, // Output
output reg Qn // Inverted output
); always @(posedge CLK) begin
Q <= D; // Capture the data on the clock edge end
always @(*) begin
23
250280763009 ME02000181

Qn = ~Q; // Inverted output end


Endmodule
TESTBENCH:
//test bench for d flip flop
module tb_d_flip_flop;
// Testbench signals
reg D; // Data input
reg CLK; // Clock
wire Q; // Output
wire Qn; // Inverted output
// Instantiate the D flip-flop
d_flip_flop uut (
.D(D),
.CLK(CLK),
.Q(Q),
.Qn(Qn)
);
// Clock generation
initial begin
CLK = 0;
forever #5 CLK = ~CLK; // Generate a clock with a period of 10 units
end
initial begin
// Display the outputs
$monitor("Time: %0t | D: %b | CLK: %b | Q: %b | Qn: %b", $time, D, CLK, Q, Qn);
// Test case 1: D = 0
D = 1'b0; #5; // Q should become 0 on the next clock edge
// Test case 2: D = 1
D = 1'b1; #5; // Q should become 1 on the next clock edge
// Test case 3: D = 0
D = 1'b1; #5; // Q should become 0 on the next clock edge
// Test case 4: D = 1
D = 1'b0; #5; // Q should become 1 on the next clock edge
D = 1'b0; #5; // Q should become 0 on the next clock edge
// Test case 2: D = 1
D = 1'b1; #5; // Q should become 1 on the next clock edge
$finish; // Finish the simulation
end
endmodule

24
250280763009 ME02000181

OUTPUT WAVEFORM:

CODE COVERAGE:

 SR Flip Flop

DESIGN CODE:

 Dataflow Modeling:

module sr_ff_dataflow( input S,


input R, input clk, output Q, output Q_bar
);
wire SR, RQ;
25
250280763009 ME02000181

assign SR = ~(S & clk); assign RQ = ~(R & clk); assign Q = ~(SR & Q_bar); assign Q_bar = ~(RQ & Q);
endmodule

 Behavioral Code:

module sr_ff_behavioral( input wire S,


input wire R,
input wire clk, output reg Q,
output reg Q_bar
);
always @(posedge clk) begin
if (S == 1'b0 && R == 1'b0) begin
Q <= Q; // No change Q_bar <= Q_bar;
end
else if (S == 1'b0 && R == 1'b1) begin
Q <= 1'b0; // Reset
Q_bar <= 1'b1;
end
else if (S == 1'b1 && R == 1'b0) begin
Q <= 1'b1; // Set
Q_bar <= 1'b0;
end
else begin
Q <= 1'bx; // Invalid Q_bar <= 1'bx;
end
end
endmodule

 Structural Modeling:

module sr_ff_gatelevel( input S,


input R, input clk, output Q, output Q_bar
);
wire SR_n, RQ_n; nand(SR_n, S, clk); nand(RQ_n, R, clk); nand(Q, SR_n, Q_bar); nand(Q_bar,
RQ_n, Q);
endmodule

TESTBENCH:

module tb_sr_ff;
reg S, R, clk;
wire Q, Q_bar;

sr_ff_behavioral uut (.S(S),


.R(R),
.clk(clk),

26
250280763009 ME02000181

.Q(Q),
.Q_bar(Q_bar));

always #5 clk = ~clk;


initial begin
// Initialize the inputs
S = 0; R = 0; clk = 0;

// Test case 3: Reset (S=0, R=1)


#10 S = 0; R = 1;

// Test case 4: Invalid (S=1, R=1)


#10 S = 1; R = 1;

// Test case 1: No change (S=0, R=0)


#10 S = 0; R = 0;

// Test case 3: Reset (S=0, R=1)


#10 S = 0; R = 1;

// Test case 2: Set (S=1, R=0)


#10 S = 1; R = 0;

// Test case 3: Reset (S=0, R=1)


#10 S = 0; R = 1;

// End the simulation


#10 $finish;
end

initial begin
$monitor("Time = %0d: S = %b, R = %b, clk = %b, Q = %b, Q_bar = %b",
$time, S, R, clk, Q, Q_bar);
end
endmodule

OUTPUT WAVEFORM:

27
250280763009 ME02000181

CODE COVERAGE:

 JK Flip Flop

DESIGN CODE:

 Dataflow Modeling:

module jk_flipflop_dataflow( input wire clk,


input wire j, input wire k, input wire rst, output wire q
);
reg q_int; assign q = q_int;
always @(posedge clk or posedge rst) begin if (rst)
q_int <= 1'b0; else
q_int <= (j & ~q_int) | (~k & q_int);
end endmodule

 Behavioral Code:

module jk_flipflop_behavioral( input wire clk,


input wire j,
input wire k, input wire rst, output reg q
);
always @(posedge clk or posedge rst) begin if (rst)
q <= 1'b0;
else begin case ({j, k})
2'b00: q <= q; // No change 2'b01: q <= 1'b0; // Reset 2'b10: q <= 1'b1; // Set 2'b11: q <= ~q;
28
250280763009 ME02000181

// Toggle
endcase end
end
endmodule

 Structural Modeling:

module jk_flipflop_structural( input wire clk,


input wire j, input wire k, input wire rst, output wire q
);
wire d;
assign d = (j & ~q) | (~k & q);
d_ff dff(.clk(clk), .rst(rst), .d(d), .q(q));
endmodule
// D Flip-Flop module used in the structural model module d_ff(
input wire clk, input wire rst, input wire d, output reg q
);
always @(posedge clk or posedge rst) begin
if (rst)
q <= 1'b0;
else
q <= d;
end endmodule

TESTBENCH:

module jk_flipflop_tb;
reg clk, j, k, rst;
wire q_behavioral;

// Instantiate behavioral model


jk_flipflop_behavioral jk_behavioral (
.clk(clk),
.j(j),
.k(k),
.rst(rst),
.q(q_behavioral)
);

// Clock generation
always #5 clk = ~clk;

// Test sequence
initial begin
// Initialize signals
clk = 0;
rst = 0;
29
250280763009 ME02000181

j = 0;
k = 0;

// Reset the flip-flops


#10 rst = 1;
#10 rst = 0;

// Test cases
#10 j = 1; k = 0; // Set
#10 j = 1'bx; k = 1'bx;
#10 j = 0; k = 1; // Reset
#10 j = 1; k = 1; // Toggle
#10 j = 0; k = 0; // No change
#10 j = 1; k = 0; // Set
#10 j = 0; k = 1; // Reset
#10 j = 1; k = 1; // Toggle
#10 $finish;
end

// Monitor the outputs


initial begin
$monitor("Time=%0d : rst=%b, j=%b, k=%b, q_behavioral=%b", $time, rst, j, k, q_behavioral);
end
endmodule

OUTPUT WAVEFORM:

30
250280763009 ME02000181

CODE COVERAGE:

 T Flip Flop

DESIGN CODE:

 Behavioral Code:

module t_flip_flop (
input wire clk, // Clock signal
input wire rst, // Reset signal (active high) input wire T, // Toggle control inputoutput reg
Q // Output
);

always @(posedge clk or posedge rst) begin if (rst) begin


Q <= 1'b0; // Reset output to 0 end else if (T) begin
Q <= ~Q; // Toggle the output end
// Else, Q remains the same (no toggle) end
Endmodule

31
250280763009 ME02000181

TESTBENCH:

module tb_t_flip_flop;
// Inputs
reg clk;
reg rst;
reg T;
// Output
wire Q;
// Instantiate the T flip-flop
t_flip_flop uut (
.clk(clk),
.rst(rst),
.T(T),
.Q(Q)
);
// Clock generation
initial begin
clk = 0;
forever #5 clk = ~clk; // Clock period is 10 time units
end

// Test sequence
initial begin
// Initialize inputs
rst = 1; T = 0;
#10 rst = 0; // Release reset

// Test Case 1: T = 0, output should remain the same


T = 0; #20;
// Test Case 2: T = 1, output should toggle on clock edges
T = 1; #20;
// Test Case 3: T = 0 again, output should remain the same
T = 0; #20;
// Test Case 4: Toggle reset to see if it works
rst = 1; #10;
rst = 0; #10;

// Finish simulation
$finish;
end
// Monitor changes
initial begin
$monitor("Time=%0t | clk=%b | rst=%b | T=%b | Q=%b", $time, clk, rst, T, Q);
end
endmodule

32
250280763009 ME02000181

OUTPUT WAVEFORM:

CODE COVERAGE:

33
250280763009 ME02000181

EXPERIMENT 3

To develop testbench for various counters.

Counters:
A counter is a sequential circuit that counts the number of clock pulses. Counters are widely used in digital
electronics for counting events, generating time delays, or dividing the frequency of a signal. They can
be designed to count up, count down, or perform both functions, depending on the design.

Counters are classified based on:

 Type of counting: Up counter, down counter, or up/down counter.


 Mode of operation: Synchronous or asynchronous.
 Modulus (MOD): The number of states the counter goes through before it resets.

 Ring Counter

DESIGN CODE:

 Behavioral Code:

module ring_ctr #(parameter WIDTH = 4) (


input clk,
input rstn,
output reg [WIDTH-1:0] out
);

always @(posedge clk or negedge rstn) begin


if (!rstn)
out <= 1; // Reset, initializing the first bit to 1 else
out <= {out[0], out[WIDTH-1:1]}; // Shift bits, wrapping around
end
endmodule

34
250280763009 ME02000181

TESTBENCH:

module ring_counter_tb;
parameter WIDTH = 4;

reg clk;
reg rstn;
wire [WIDTH-1:0] out;

ring_counter u0 (.clk (clk), .rstn (rstn), .out (out));

always #10 clk = ~clk;

initial begin
{clk, rstn} <= 0;

$monitor ("T=%0t out=%b", $time, out);


repeat (2) @(posedge clk);
rstn <= 1;
repeat (15) @(posedge clk);
rstn <= 0;
repeat (4) @(posedge clk);
$finish;
end
endmodule

OUTPUT WAVEFORM:

35
250280763009 ME02000181

CODE COVERAGE:

 Johnson Counter

DESIGN CODE:

 Behavioral Code:

module johnson_ctr #(parameter WIDTH = 4) (


input clk, input rstn,
output reg [WIDTH-1:0] out
);

always @(posedge clk) begin if (!rstn) begin


out <= 1; end else begin
out[WIDTH-1] <= ~out[0]; // Feedback for Johnson Counter out[WIDTH-2:0] <= out[WIDTH-1:1];
// Shift the bits
end end
endmodule

TESTBENCH:

module johnson_counter_tb;
parameter WIDTH = 4;

36
250280763009 ME02000181

reg clk;
reg rstn;
wire [WIDTH-1:0] out;

johnson_counter u0 (.clk (clk), .rstn (rstn), .out (out));

always #10 clk = ~clk;

initial begin
{clk,rstn} <= 0;

$monitor ("T=%0t out=%b", $time, rstn, out);


repeat (2) @(posedge clk);
#2 rstn <= 1;
repeat (15) @(posedge clk);
#2 rstn <= 0;
repeat (7) @(posedge clk);
$finish;
end
endmodule

OUTPUT WAVEFORM:

CODE COVERAGE:

37
250280763009 ME02000181

EXPERIMENT 4

Write a HDLcode and testbench to realize functioning of Linear Feedback Shift Register
(LFSR).

A Linear-feedback shift register (LFSR) is another variation of shift register whose input bit is a
linear function (typically XOR operation) of its previous state. It is generally used as a pseudo-
random number generator, whitening sequence, pseudo-noise sequence, etc.
The bit positions that act as an input to a linear function to affect the next state are known as taps.

4-bit pseudo-random sequence generator

At every step,
1. Q[3] xor Q[2]
2. Q = Q << 1
3. The result of the XOR operation is fed to the LSB (0th bit) In the above pseudo-random sequence
generator, taps are 4 and 3.

Working Of LFSR:

 Initial State (Seed): The LFSR starts with an initial state, often referred to as the seed. This state is
typically a non-zero value, as an all-zero state can lead the LFSR to remain stuck at zero in many
configurations.
 Shifting: On each clock cycle, all the bits in the LFSR shift to the right (or left, depending on
design). The bit in the least significant position (LSB) is discarded, and a new bit is introduced
into the most significant position (MSB) through the feedback mechanism.
 Feedback Mechanism: The feedback bit is generated by XOR-ing the bits from specific
positions in the register. These positions are referred to as taps. The output of the XOR operation
is used as the new input bit at the MSB position.

For example, in a 4-bit LFSR with taps at positions 4 and 3, the feedback bit is calculated as:
feedback= bit3 ⊕ bit2

This feedback value is then shifted into the MSB of the LFSR.
 Repeat: This process of shifting and applying feedback continues on each clock cycle, and the
register evolves into different states over time. The sequence of states produced is determined by
the positions of the taps.
 Periodicity: If the taps are chosen correctly (following the characteristic polynomial), the LFSR

38
250280763009 ME02000181

can produce a maximal-length sequence. In a maximal-length LFSR, the register goes through
all possible non-zero states (for an n-bit LFSR, there are 2n−12^n - 12n−1 states) before
repeating itself. This makes the sequence appear "random," but it is entirely deterministic.

Advantages:

1. Simplicity: LFSRs are simple to implement in both hardware and software, requiring minimal
resources.
2. Fast Operation: They can generate pseudorandom sequences quickly due to their simple shifting
and feedback operations.
3. Deterministic Output: LFSRs produce predictable output sequences from a given initial state,
making them useful for applications requiring repeatability.
4. Good Statistical Properties: LFSRs can produce long sequences with good statistical properties,
making them suitable for cryptography and error detection.
5. Efficient Memory Usage: They use very little memory, as they only need to store the current state
and feedback polynomial coefficients.

Disadvantages:
1. Linear Nature: The linear feedback mechanism can make LFSRs vulnerable to certain types of
attacks in cryptographic applications, particularly if the polynomial is not chosen carefully.
2. Limited Period: The maximum length of the sequence generated is limited by the number of
flip-flops and the feedback polynomial, which can lead to periodicity.
3. Sensitivity to Initial State: The output is highly sensitive to the initial state; poor choice can result in
predictable sequences.
4. Not Truly Random: While they can approximate randomness, the sequences produced are
deterministic and not truly random, which can be a limitation in some applications.
5. Complexity in Polynomial Selection: Selecting the correct feedback polynomial to achieve maximum
length and desired properties can be complex and requires expertise.

DESIGN CODE:

 Behavioral Modeling:

module lfsr (
input clk,
(* dont_touch = "true" *) input rst, // FORCES VIVADO TO TRACK THIS PORT
output reg [3:0] op
);

reg feedback;

always @(*) begin


feedback = op[3] ^ op[2];
end

always @(posedge clk) begin


if (rst) begin
op <= 4'b0001;
end else begin
op <= {op[2:0], feedback};
39
250280763009 ME02000181

end
end

endmodule

TESTBENCH:

module lfsr_tb;
reg clk = 0;
reg rst = 0;
wire [3:0] op;

lfsr uut (.clk(clk), .rst(rst), .op(op));

always #5 clk = ~clk;

initial begin
// 1. Establish the baseline
clk = 0;
rst = 0;
#25;

// 2. Normal Reset Sequence


rst = 1;
#25;
rst = 0;

// 3. Let LFSR complete its 15-state sequence


#350;

// 4. THE FIX: The Coverage Hammer


// Rapidly toggle the reset signal at the end of the simulation
// independent of the clock to force the engine to log it as data.
#13 rst = 1;
#13 rst = 0;
#13 rst = 1;
#13 rst = 0;

#20 $finish;
end
endmodule

OUTPUT WAVEFORM:

40
250280763009 ME02000181

CODE COVERAGE:

41
250280763009 ME02000181

EXPERIMENT 5

Write a HDL code and testbench to implement 8 BIT ALU.

ALU is the fundamental building block of the processor, which is responsible for
carrying out the arithmetic and logic functions. ALU comprises of combinatorial logic that
implements arithmetic operations such as Addition, Subtraction and Multiplication, and logic
operations such as AND, OR, NOT. The ALU gets operands from the register file or memory. The
block diagram of a typical ALU is shown in Figure 1.

The ALU reads two input operands In A and In B. The operation to perform on these input operands is
selected using the control input OpDESIGN CODE. The ALU performs the selected operation on
the input operands In A and In B and produces the output, Out. The ALU also updates different flag
signals after performing the selected function. Note that the ALU is purely combinatorial logic and
contains no registers or latches.

The ALU is divided into an arithmetic section and a logical section.

The Arithmetic Unit compromises of three functions.


They are:
 Addition
 Subtraction
 Multiplication

The Logical Unit compromises of five functions.


They are:
 Bitwise AND
 Bitwise OR
 Bitwise NAND
 Bitwise NOR
 Bitwise XOR

Flags: ALU updates the conditional flags, which are used by the processor to perform other
operations like condition checking and branching. In this example two flags are implemented. They
are:
Flags:
 Zero Flag (Z): Since the result is not zero, this flag is cleared (set to 0).
 Carry Flag (C): No carry occurs as the sum fits within 8 bits, so the carry flag is cleared.
 Overflow Flag (V): In unsigned arithmetic, no overflow occurs.
42
250280763009 ME02000181

 Negative Flag (N): In signed arithmetic, the result is negative because the most significant
bit (MSB) is 1.

How an 8-bit ALU Works:

Example: Addition of Two Numbers (A = 10101010₂, B = 00111001₂)

1. Inputs:
oOperand A: 10101010₂ (170 in decimal)
oOperand B: 00111001₂ (57 in decimal)
oOpcode: Suppose the opcode 0001 is used to represent addition.
2. Operation:
o The ALU receives the opcode 0001 indicating it should perform addition.
o The binary addition of A and B is performed.

The result of the operation is `11100011₂` (227 in decimal).

DESIGN CODE:

 Behavioral Modeling:

module alu(
input [7:0] A, // input A
input [7:0] B, // input ,B
input [3:0] select, // input select
output reg [7:0] result, // output result
output reg carry_flag, // output carry_flag
output reg overflow_flag, // output overflow_flag
output reg zero_flag, // output zero_flag
output reg negative_flag // output negative_flag
);
always@(*)begin
carry_flag = 0;
overflow_flag = 0;
zero_flag = 0;
negative_flag = 0;

case(select)
4'b0000:begin
{carry_flag,result} = A+B;
overflow_flag =(A[7] == B[7])&&(A[7]!=result[7]);
end

4'b0001:begin
{carry_flag,result} = A-B;
overflow_flag = (A[7] != B[7])&&(A[7]!=result[7]);
end

4'b0010:result = A*B;

43
250280763009 ME02000181

4'b0011:begin
if(B!=0)begin
result = A/B;
end
else begin
result = 8'b00000000;
end
end
// conditon
4'b0100:result = A&B;
4'b0101:result = A|B;
4'b0110:result = ~(A&B);
4'b0111:result = ~(A|B);
4'b1000:result = A^B;
4'b1001:result = A~^B;
4'b1010:result = ~A;
default:result = 8'b00000000; endcase
if(result == 8'b00000000) zero_flag = 1;
else zero_flag = 0;
if(result[7] == 1) negative_flag = 1;
else negative_flag = 0;

end
endmodule

TESTBENCH:

module alu_tb();
reg [7:0] A,B; // input A,B
reg [3:0] select; // input select
wire [7:0] result; // output result
wire carry_flag; // output carry_flag
wire overflow_flag; // output overflow_flag
wire zero_flag; // output zero_flag
wire negative_flag; // output negative_flag
integer i;
alu uut(A,B,select,result,carry_flag,overflow_flag,zero_flag,negative_flag);

initial begin
A = 0; B = 0; select = 0; // Initialize everything
#10;
// dumpfile for OUTPUT WAVEFORM form
$dumpfile("alu_tb.vcd");
$dumpvars(0,alu_tb);

// conditon
for(i=0;i<12;i=i+1) begin
44
250280763009 ME02000181

select = i;
A = i;B = i+1; #10;
end

#10; select = 1; A = 8'b10000000; B = 8'b01010101;


#10; select = 1; A = 8'hFF; B = 8'h01;
#10; select = 0; A = 8'b00000000; B = 8'b01010101;
#10; select = 0; A = 8'b10000000; B = 8'b01010101;
#10; select = 0; A = 8'b11000000; B = 8'b01010101;
#10; select = 3; A = 1; B = 0;
#10; select = 8'bx; A = 8'hFF; B = 8'hFF;
#10; select = 1; A = 8'h00; B = 8'h00;
#10; select = 0; A = 8'h70; B = 8'h70;
#10; select = 1; A = 8'h70; B = 8'hFF;
#10; select = 1; A = 8'h05; B = 8'h03;
$finish;
end
endmodule

OUTPUT WAVEFORM:

CODE COVERAGE:

45
250280763009 ME02000181

EXPERIMENT 6

Write a HDL code to realize functioning of 32-bit RAM.

RAM (Random Access Memory) is a type of volatile memory used to store data temporarily in digital
systems like microprocessors, microcontrollers, and FPGAs/ASICs. It allows both read and write operations.

Structure of 32-bit RAM


 A 32-bit RAM means each memory location can store a 32-bit word (i.e., 4 bytes).
 If the RAM has 256 locations, it requires an 8-bit address ( 2^8 = 256).
 The memory is organized as an array:
reg [31:0] mem [0:255];

Functional Blocks

1. Address Bus: Used to specify the memory location to be accessed.


→ 8 bits required for 256 locations.
2. Data Bus:
o Input (data_in) – data to be written into RAM
o Output (data_out) – data read from RAM
→ Both are 32 bits wide.
3. Control Signals:
o clk: Synchronizes the operation (read/write on clock edge)
o we(Write Enable):
 If high, RAM writes data_ininto the given address.
 If low, RAM reads and gives data_out.

Operation
 Write Operation (we = 1):
On rising edge of clk, data_inis stored at addr.
 Read Operation (we = 0):
On rising edge of clk, the content of addris placed on data_out.

Applications

 Temporary data storage in processors


 Buffering data between modules
 Implementing register files, lookup tables, and caches

DESIGN CODE:

module ram_32bit # (
parameter DATA_WIDTH = 32, // Width of each data word (32-bit)
parameter ADDR_WIDTH = 6, // 6 bits allows 64 memory locations (2^6)
parameter DEPTH = 64 // Total number of memory slots
)(
input clk, // System clock
input write_enable, // 1 = Write mode, 0 = Read mode

46
250280763009 ME02000181

input [ADDR_WIDTH-1:0] address, // Target address pointer


input [DATA_WIDTH-1:0] data_in, // Data to write into RAM
output reg [DATA_WIDTH-1:0] data_out // Data read out from RAM
);

// Declare the memory array structure: 64 words, each 32 bits wide


reg [DATA_WIDTH-1:0] memory_array [0:DEPTH-1];

// Synchronous Read and Write block


always @(posedge clk) begin
if (write_enable) begin
memory_array[address] <= data_in;
data_out <= data_in; // Directly bypass to data_out to avoid reading 'X'
end else begin
data_out <= memory_array[address];
end
end

endmodule

TESTBENCH:

module ram_32bit_tb;

parameter DATA_WIDTH = 32;


parameter ADDR_WIDTH = 6;
parameter DEPTH = 64;

reg clk;
reg write_enable;
reg [ADDR_WIDTH-1:0] address;
reg [DATA_WIDTH-1:0] data_in;
wire [DATA_WIDTH-1:0] data_out;

integer i;

// Instantiate the design module under test


ram_32bit #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.DEPTH(DEPTH)
) uut (
.clk(clk),
.write_enable(write_enable),
.address(address),
.data_in(data_in),
.data_out(data_out)
);
47
250280763009 ME02000181

// Free-running Clock Generator (20ns period)


always #10 clk = ~clk;

initial begin
// --- STEP 1: INITIAL STATE SETTING ---
clk = 0;
write_enable = 0;
address = 0;
data_in = 0;

// Wait 5ns to move completely away from the posedge clk boundaries
#5;

// --- STEP 2: CLEAR ALL 'X' BY FILLING ENTIRE ARRAY WITH 0s ---
// Every input change happens cleanly on the NEGEDGE of the clock
for (i = 0; i < DEPTH; i = i + 1) begin
@(negedge clk);
write_enable = 1;
address = i;
data_in = {DATA_WIDTH{1'b0}};
end

// --- STEP 3: TOGGLE WRITE_ENABLE FOR COVERAGE ---


@(negedge clk);
write_enable = 0;
@(negedge clk);
write_enable = 1;

#40;
// --- STEP 4: TOGGLE ALL INDIVIDUAL ADDRESS BITS ---
@(negedge clk);
write_enable = 0; // Keep in read mode to test clean address changes
for (i = 0; i < ADDR_WIDTH; i = i + 1) begin
address = (1 << i);
@(negedge clk);
address = 0;
end

#40;
// --- STEP 5: WRITE ALL 1s TO ALL SLOTS (0 -> 1 Toggle) ---
for (i = 0; i < DEPTH; i = i + 1) begin
@(negedge clk);
write_enable = 1;
address = i;
data_in = {DATA_WIDTH{1'b1}};
end

48
250280763009 ME02000181

#40;
// --- STEP 6: READ ALL 1s (Forces data_out 0 -> 1 Toggle) ---
for (i = 0; i < DEPTH; i = i + 1) begin
@(negedge clk);
write_enable = 0;
address = i;
end

#40;
// --- STEP 7: WRITE ALL 0s TO ALL SLOTS (1 -> 0 Toggle) ---
for (i = 0; i < DEPTH; i = i + 1) begin
@(negedge clk);
write_enable = 1;
address = i;
data_in = {DATA_WIDTH{1'b0}};
end

#40;
// --- STEP 8: READ ALL 0s (Forces data_out 1 -> 0 Toggle) ---
for (i = 0; i < DEPTH; i = i + 1) begin
@(negedge clk);
write_enable = 0;
address = i;
end

// --- STEP 9: WRAP UP AND EXIT ---


@(negedge clk);
#20;
$display("Done! 100%% Toggle coverage reached without any X states.");
$finish;
end

endmodule

OUTPUT WAVEFORM:

49
250280763009 ME02000181

CODE COVERAGE
:

50
250280763009 ME02000181

EXPERIMENT 7

Write a HDL code to realize functioning of Observation Point Insertion Technique.

Observation Point Insertion (OPI) is a crucial technique in digital design that allows for easier debugging
and testing by adding specific points in the circuit where internal signals can be monitored. This
technique can be especially useful during simulation and on-chip debugging processes. Below, I present
a detailed theory and a practical Verilog HDL code example to illustrate the functioning of the
Observation Point Insertion Technique.

Application:
 Debugging: To facilitate the debugging process by providing visibility into the internal signals of a
digital circuit.
 Testing: To enhance the testing capabilities by
allowing specific points in the circuit to be observed during various test scenarios.
 Simulation: During the simulation phase, observation points help in monitoring and verifying the
internal signal states without affecting the circuit's functionality.
 Hardware Debugging: On-chip observation points can be routed to debug interfaces to observe real-
time signal states during hardware testing.

DESIGN CODE:

module ObservationPointCircuit (
input wire a, // Input signal a
input wire b, // Input signal b
output wire y, // Output signal y
output wire obs // Observation point output
);
// Step 1: G1 - OR gate operation
wire g1_out;
assign g1_out = a | b;
// Step 2: Observation point assignment
assign obs = g1_out;
// Step 3: G2 - AND gate operation
assign y = g1_out & a;
endmodule

51
250280763009 ME02000181

TESTBENCH:

module Testbench;
reg a, b;
wire y, obs;
ObservationPointCircuit uut (
.a(a),

.b(b),
.y(y),
.obs(obs)
);
initial begin
a = 0; b = 0;
#10 a = 1; b = 0;
#10 a = 1; b = 1;
#10 a = 0; b = 1;
#10 a = 1; b = 1;
#10 a = 0; b = 0;
#10 $finish;
end
initial begin
$monitor("At time %t: a = %b, b = %b, obs = %b, y = %b",
$time, a, b, obs, y);
end
endmodule

OUTPUT WAVEFORM:

52
250280763009 ME02000181

CODE COVERAGE:

53
250280763009 ME02000181

EXPERIMENT 8

Write a HDL code to realize functioning of Control Point Insertion Technique.

In digital circuit design, particularly for Design for Testability (DFT), Control Point Insertion (CPI) is a
technique where additional logic is inserted into a circuit to improve its controllability during testing.
The goal is to make internal nodes easily set to a known value (0 or 1) during scan testing without affecting
the normal functional behavior.

In CPI:

 Normal Mode: The circuit behaves as originally designed.


 Test Mode: Specific internal nodes can be forced to a given value (control value) to improve
fault coverage.

Typically, this is implemented using a 2:1 multiplexer that selects between normal output and a forced value
based on a test_mode signal.

Advantages:
 Increases fault coverage.
 Reduces test pattern generation complexity.
 Enhances circuit testability without significantly affecting performance.

DESIGN CODE:

module control_point_insertion (
input wire a,
input wire b,
input wire test_mode, // 1 for test mode, 0 for normal operation
input wire control_value, // Forced value in test mode
output wire y
);
wire normal_output;
// Original functional logic
assign normal_output = a & b;
// Control point logic
assign y = (test_mode) ? control_value : normal_output;

54
250280763009 ME02000181

endmodule

TESTBENCH:

module control_point_insertion_tb;
// Testbench signals
reg a, b;
reg test_mode;
reg control_value;
wire y;

// Instantiate the design under test (DUT)


control_point_insertion dut (
.a(a),
.b(b),
.test_mode(test_mode),
.control_value(control_value),
.y(y)
);
// Test sequence
initial begin
$display("Time\t a b test_mode control_value | y");
$monitor("%0t\t %b %b %b %b | %b", $time, a, b, test_mode, control_value, y);
// Test 1: Normal mode, a=0, b=0
a = 0; b = 0; test_mode = 0; control_value = 0;
#10;
// Test 2: Normal mode, a=1, b=0
a = 1; b = 0;
#10;
// Test 3: Normal mode, a=1, b=1
a = 1; b = 1;
#10;

// Test 4: Test mode, force output to 0


test_mode = 1; control_value = 0;
#10;
// Test 5: Test mode, force output to 1
control_value = 1;
#10;
// Test 6: Normal mode, a=0, b=0
a = 0; b = 0; test_mode = 0; control_value = 0;
#10;
// Finish simulation
$finish;
end
endmodule

55
250280763009 ME02000181

OUTPUT WAVEFORM:

CODE COVERAGE:

56
250280763009 ME02000181

EXPERIMENT 9

Write HDL code for MUX-D scan cell and Level Sensitive/Edge Triggered MUXED-D scan cell.

MUX-D Scan Cell Overview:

A MUX-D Scan Cell is a type of flip-flop used in scan chains during digital circuit testing, particularly in
the context of scan-based testing and design-for-testability (DFT). This flip-flop combines both normal
data storage (as in a standard flip-flop) and the ability to participate in scan chains used for easier testing
and debugging of digital circuits.

Key Concepts:

1. Multiplexer (MUX): A multiplexer is a combinational circuit that selects one of many inputs
based on control signals and outputs it. In the case of a scan cell, a multiplexer is used to select
between the normal data input (d) and the scan input (scan_in). This allows the flip-flop to
behave as a regular flip-flop when the scan mode is not enabled, but when the scan mode is
enabled, the scan input can be passed through to the output.
2. Scan Mode: In scan-based testing, the normal behavior of a flip-flop is overridden by the scan
chain, which is used to shift in test vectors and shift out captured data. When the scan_enable
signal is activated, the scan input (scan_in) takes precedence over the normal data input (d). This
enables the testing of the circuit by manipulating the flip-flops in a controlled sequence.
3. Flip-Flop: A flip-flop is a fundamental memory element that stores a single bit of data. It
typically has two stable states: 0 and 1. A flip-flop is triggered on a specific edge of a clock signal
(positive or negative) and can have an asynchronous reset that forces the output to a known value
(e.g., 0) when the reset signal is asserted.

DESIGN CODE:

module MUX_D_Scan_Cell (
input wire clk, // Clock signal
input wire rst_n, // Active-low reset signal
input wire scan_in, // Scan input for testing
input wire scan_enable, // Control signal to enable scan mode
input wire d, // Normal data input
output reg q // Output of the scan cell (change to reg)
);

57
250280763009 ME02000181

wire mux_out;

// Multiplexer that selects between normal data (D) and scan data (scan_in)
assign mux_out = scan_enable ? scan_in : d;

// Flip-flop with asynchronous reset


always @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 0; // Reset output to 0
else
q <= mux_out; // Output the selected data
end

endmodule

TESTBENCH:

module tb_MUX_D_Scan_Cell;

// Testbench signals
reg clk;
reg rst_n;
reg scan_in;
reg scan_enable;
reg d;
wire q;

// Instantiate the MUX-D Scan Cell


MUX_D_Scan_Cell uut (
.clk(clk),
.rst_n(rst_n),
.scan_in(scan_in),
.scan_enable(scan_enable),
.d(d),
.q(q)
);

// Clock generation (10ns period)


always begin
#5 clk = ~clk;
end

// Test sequence
initial begin
$dumpfile("[Link]");
$dumpvars(0, tb_MUX_D_Scan_Cell);

58
250280763009 ME02000181

// 1. Initialize all signals to 0 (Registers the initial state)


clk = 0;
rst_n = 0;
scan_in = 0;
scan_enable = 0;
d = 0;

// 2. Release Reset (rst_n toggles 0 -> 1)


#12 rst_n = 1;

// 3. Test Normal Mode (scan_enable = 0)


// Toggle d; q will follow on the next posedge clk
#10 d = 1; // d and mux_out toggle 0 -> 1
#10; // Wait for clk edge to toggle q to 1
#10 d = 0; // d and mux_out toggle 1 -> 0
#10; // Wait for clk edge to toggle q to 0

// 4. Enable Scan Mode (scan_enable toggles 0 -> 1)


#10 scan_enable = 1;

// 5. Test Scan Mode (scan_enable = 1)


// Toggle scan_in; q will follow on the next posedge clk
#10 scan_in = 1; // scan_in and mux_out toggle 0 -> 1
#10; // Wait for clk edge to toggle q to 1
#10 scan_in = 0; // scan_in and mux_out toggle 1 -> 0
#10; // Wait for clk edge to toggle q to 0

// 6. FIX FOR COVERAGE: Explicitly toggle scan_enable back (1 -> 0)


#10 scan_enable = 0;

// 7. FIX FOR COVERAGE: Explicitly toggle rst_n back (1 -> 0)


#10 rst_n = 0;
#10 rst_n = 1;

// 8. Final Wait: Ensures the tool captures the last transitions


#20 $finish;
end

initial begin
$monitor("Time = %0t, rst_n = %b, scan_in = %b, scan_enable = %b, d = %b, q = %b",
$time, rst_n, scan_in, scan_enable, d, q);
end
endmodule

59
250280763009 ME02000181

OUTPUT WAVEFORM:

CODE COVERAGE:

Level Sensitive/Edge Triggered MUXED-D Scan Cell

This version of the scan cell can work in two modes:

 Level-sensitive mode: The data is latched when scan_enable is active.


 Edge-triggered mode: The data is latched on the rising edge of the clock (clk).

60
250280763009 ME02000181

DESIGN CODE:

module level_edge_Scan_Cell (
input wire clk, // Clock signal
input wire rst_n, // Active-low reset signal
input wire scan_in, // Scan input for testing
input wire scan_enable, // Control signal to enable scan mode
input wire d, // Normal data input
output reg q // Output of the scan cell
);

wire mux_out;

// Multiplexer to select between normal data (D) and scan data (scan_in)
assign mux_out = scan_enable ? scan_in : d;

// Level-sensitive or edge-triggered flip-flop


always @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 0; // Reset output to 0
else
q <= mux_out; // Output the selected data
end

endmodule

TESTBENCH:

module tb_level_edge_Scan_Cell;

// Testbench signals
reg clk;
reg rst_n;
reg scan_in;
reg scan_enable;
reg d;
wire q;

// Instantiate the MUXED-D Scan Cell


MUXED_D_Scan_Cell uut (
.clk(clk),
.rst_n(rst_n),
.scan_in(scan_in),
.scan_enable(scan_enable),
.d(d),
.q(q)
);
61
250280763009 ME02000181

// Clock generation
always begin
#5 clk = ~clk; // Generate clock with a period of 10 time units
end

// Test sequence
initial begin
// Initialize signals
clk = 0;
rst_n = 0;
scan_in = 0;
scan_enable = 0;
d = 0;

// Apply reset
#10 rst_n = 1;

// Test Normal Data Input (D)


#10 d = 1;
#10 d = 0;

// Test Scan Data Input (Scan_in)


#10 scan_enable = 1; // Enable scan mode
scan_in = 1;
#10 scan_in = 0;
scan_enable = 0; // Disable scan mode

// Test edge-triggered behavior


#10 d = 1;
#10 d = 0;

// Test reset functionality


#10 rst_n = 0;
#10 rst_n = 1;

// End simulation
#10 $finish;
end

// Display output
initial begin
$monitor("Time = %0t, rst_n = %b, scan_in = %b, scan_enable = %b, d = %b, q = %b",
$time, rst_n, scan_in, scan_enable, d, q);
end

endmodule

62
250280763009 ME02000181

OUTPUT WAVEFORM:

CODE COVERAGE:

63
250280763009 ME02000181

EXPERIMENT 10
Write a HDL code to realize functioning of clocked scan cell and LSSD scan cell design.

Clocked Scan

A Clocked Scan Cell (CSC) is a specialized type of flip-flop used primarily in scan-based testing for
digital circuits. In this context, it allows for efficient testing of a circuit's internal nodes by enabling easier
control and observation of flip-flops during the testing phase.

Key Features:
1. Scan Input and Normal Input: The CSC can capture data either from a normal input (D) or a scan
input (Scan) depending on a control signal. The control signal, typically referred to as
scan_enable, dictates whether the CSC is functioning in normal mode or scan mode.
2. Scan Mode: In scan mode (when scan_enable is active), the CSC connects its scan input to its
data input, enabling the insertion of test vectors into the flip-flop chain, which is crucial for
functional and structural testing.
3. Normal Mode: When scan_enable is inactive, the CSC operates as a standard flip-flop, capturing
data from the normal data input.
4. Shift and Capture Operations: The CSC is often part of a shift-register chain that allows for serial
shifting of test data (in scan mode) and capturing of output data during the testing process.

Applications:
 Scan-Based Testing: Essential for Design for Testability (DFT), where multiple CSCs are
connected to form a scan chain. This allows for easier test pattern application and fault detection
in the circuit's sequential logic.
 Improved Fault Coverage: By using scan chains and CSCs, complex logic circuits can be
tested more effectively, improving fault detection capabilities.

DESIGN CODE:

module CSC_Scan_Cell (
input wire clk, // Clock signal
input wire rst_n, // Active-low reset signal
input wire scan_in, // Scan input for testing
input wire scan_enable, // Control signal to enable scan mode
input wire d, // Normal data input
output reg q // Output of the scan cell
);

64
250280763009 ME02000181

wire mux_out;

// Multiplexer that selects between normal data (D) and scan data (scan_in)
assign mux_out = scan_enable ? scan_in : d;

// Flip-flop with clocked operation and asynchronous reset


always @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 0; // Reset output to 0 when rst_n is low
else
q <= mux_out; // Output the selected data (D or scan_in)
end
endmodule

TESTBENCH:

module tb_CSC_Scan_Cell;
// Testbench signals
reg clk;
reg rst_n;
reg scan_in;
reg scan_enable;
reg d;
wire q;

// Instantiate the Clocked Scan Cell


CSC_Scan_Cell uut (
.clk(clk),
.rst_n(rst_n),
.scan_in(scan_in),
.scan_enable(scan_enable),
.d(d),
.q(q)
);

// Clock generation
always begin
#5 clk = ~clk; // Generate a clock with a period of 10 time units
end

// Test sequence
initial begin

$dumpfile("[Link]"); $dumpvars;
// Initialize signals
clk = 0;
rst_n = 0;
scan_in = 0;
65
250280763009 ME02000181

scan_enable = 0;
d = 0;

// Apply reset
#10 rst_n = 1;

// Test Normal Data Input (D)


#10 d = 1;
#10 d = 0;

// Test Scan Data Input (scan_in)


#10 scan_enable = 1; // Enable scan mode
scan_in = 1;
#10 scan_in = 0;
scan_enable = 0; // Disable scan mode

// Test reset functionality


#10 rst_n = 0;
#10 rst_n = 1;

// End simulation
#10 $finish;
end

// Display output
initial begin
$monitor("Time = %0t, rst_n = %b, scan_in = %b, scan_enable = %b, d = %b, q = %b",
$time, rst_n, scan_in, scan_enable, d, q);
end

endmodule

OUTPUT WAVEFORM:

66
250280763009 ME02000181

CODE COVERAGE:

LSSD Scan Cell:

The LSSD Scan Cell (Level-Sensitive Scan Design) is a type of flip-flop used in scan-based testing and is
commonly employed in Design for Testability (DFT). It allows for controlled access to the internal flip-
flop states during testing, making it easier to test sequential logic in digital circuits. The LSSD Scan Cell
can operate in two modes:

1. Scan Mode: When the scan_enable signal is active, the cell bypasses the normal data input (D)
and instead accepts the data from the scan_in input. This allows test patterns to be shifted into the
circuit, enabling fault detection and easier debugging.
2. Normal Mode: When scan_enable is inactive, the LSSD Scan.

Cell behaves like a regular flip-flop, capturing the data from the normal input (D).

The LSSD Scan Cell has a level-sensitive latch mechanism that responds to the clock (clk) and active-low
reset (rst_n) signals. It latches data based on the control signal, scan_enable, and stores the output in the q
register.

 Clock: The latch captures the data on the rising edge of the clock.
 Reset (rst_n): When the reset is active-low, the output q is reset to 0.
 Scan Input (scan_in): Used for testing purposes, when scan_enable is high.
 Data Input (d): Used in normal operation, when scan_enable is low.

67
250280763009 ME02000181

DESIGN CODE:

module LSSD_Scan_Cell (
input wire clk, // Clock signal
input wire rst_n, // Active-low reset signal
input wire scan_in, // Scan input for testing
input wire scan_enable, // Control signal to enable scan mode
input wire d, // Normal data input
output reg q // Output of the scan cell

);

// Multiplexer that selects between normal data (D) and scan data (scan_in)
wire mux_out;
assign mux_out = scan_enable ? scan_in : d;

// Level-sensitive latch (LSSD behavior)


always @(clk or negedge rst_n) begin
if (!rst_n)
q <= 0; // Reset output to 0 when rst_n is low
else if (clk) // When clock is high, latch data
q <= mux_out; // Output the selected data (D or scan_in)
end

endmodule

TESTBENCH:

module tb_LSSD_Scan_Cell;

// Testbench signals
reg clk;
reg rst_n;
reg scan_in;
reg scan_enable;
reg d;
wire q;

// Instantiate the LSSD Scan Cell


LSSD_Scan_Cell uut (
.clk(clk),
.rst_n(rst_n),
.scan_in(scan_in),
.scan_enable(scan_enable),
.d(d),
.q(q)
);

68
250280763009 ME02000181

// Clock generation
always begin
#5 clk = ~clk; // 10ns period
end

// Test sequence
initial begin
$dumpfile("[Link]");
$dumpvars(0, tb_LSSD_Scan_Cell);

// 1. Initialize signals (Registers the '0' state)


clk = 0;
rst_n = 0;
scan_in = 0;
scan_enable = 0;
d = 0;

// 2. Release reset (rst_n toggles 0 -> 1)


#12 rst_n = 1;

// 3. Test Normal Mode (scan_enable = 0)


// Ensure d toggles while clk is high to test transparency
#10 d = 1; // d toggles 0 -> 1
#10 d = 0; // d toggles 1 -> 0

// 4. Switch to Scan Mode (scan_enable toggles 0 -> 1)


#10 scan_enable = 1;

// 5. Test Scan Mode


#10 scan_in = 1; // scan_in toggles 0 -> 1
#10 scan_in = 0; // scan_in toggles 1 -> 0

// 6. FIX: Explicitly toggle scan_enable back (1 -> 0)


#10 scan_enable = 0;

// 7. FIX: Explicitly toggle reset to capture the 1 -> 0 transition


#10 rst_n = 0; // rst_n toggles 1 -> 0
#10 rst_n = 1; // rst_n toggles 0 -> 1

// 8. End simulation with a final delay to ensure all toggles are recorded
#20 $finish;
end

// Display output
initial begin
$monitor("Time = %0t, rst_n = %b, scan_in = %b, scan_enable = %b, d = %b, q = %b",
$time, rst_n, scan_in, scan_enable, d, q);
end
69
250280763009 ME02000181

endmodule
OUTPUT WAVEFORM:

CODE COVERAGE:

70
250280763009 ME02000181

EXPERIMENT 11
Write a HDL code to realize functioning of LSSD double latch design.

Level Sensitive Scan Design (LSSD) is a testing technique used in digital circuits to facilitate easy testing
and diagnosis of faults. It uses a combination of scan chains and special latch structures to allow test
signals to be inserted into the circuit and test results to be observed.

The LSSD Double Latch design is part of this testing framework, and it specifically involves two latches
that are used together to enhance testability. The primary goal is to create a mechanism that supports both
normal functional operation of the circuit and its scan-based operation for testing

Key Features:
1. Two Latches:
o Latch1 captures input data, while Latch2 holds and propagates it, forming a pipeline for
data flow.
2. Scan Mode vs Normal Mode:
o Scan Mode: Captures test vectors for boundary scan testing.
o Normal Mode: Holds functional data in the latches for regular operation.
3. Testability:
o Part of a scan chain, allowing external test equipment to control and observe internal
states, improving fault detection.
4. Operation:
o In Normal Mode, data flows from Latch1 to Latch2. In Scan Mode, scan inputs are used to
load and shift test data.
5. Advantages:
o Fault Isolation and Test Efficiency: Enables better control and faster testing by utilizing
scan chains and latches.

DESIGN CODE:

module lssd_double_latch (
input wire clk, // Clock signal
input wire rst_n, // Active-low reset signal
input wire data_in, // Input data to be latched
input wire scan_in, // Scan input for test purposes
input wire scan_mode, // Scan mode control (1 for scan mode, 0 for normal operation)
output reg data_out // Output data from the latch
);

// Declare internal signals for the two latches


reg latch1, latch2;
// Always block to describe the behavior of the double latch
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// Reset condition (both latches are cleared)
latch1 <= 1'b0;
latch2 <= 1'b0;

71
250280763009 ME02000181

data_out <= 1'b0;


end else if (scan_mode) begin
// Scan mode: Load scan_in into latch1
latch1 <= scan_in;
// Propagate latch1's value to latch2
latch2 <= latch1;
data_out <= latch2;
end else begin
// Normal operation: Load data_in into latch1
latch1 <= data_in;
// Propagate latch1's value to latch2
latch2 <= latch1;
data_out <= latch2;
end
end
endmodule

TESTBENCH:

module tb_lssd_double_latch;
// Declare inputs and outputs for the testbench
reg clk;
reg rst_n;
reg data_in;
reg scan_in;
reg scan_mode;
wire data_out;

// Instantiate the LSSD Double Latch module


lssd_double_latch uut (
.clk(clk),
.rst_n(rst_n),
.data_in(data_in),
.scan_in(scan_in),
.scan_mode(scan_mode),
.data_out(data_out)
);

// Clock generation (50 MHz clock)


always begin
#10 clk = ~clk; // Toggle clock every 10ns (50 MHz)
end

// Test sequence
initial begin
$dumpfile("[Link]"); $dumpvars;

// --- STEP 1: INITIALIZATION & RESET TOGGLE ---


72
250280763009 ME02000181

// Initialize all inputs to 0


clk = 0;
rst_n = 0; // rst_n starts at 0
data_in = 0;
scan_in = 0;
scan_mode = 0;

#15 rst_n = 1; // rst_n toggles: 0 -> 1


#20 rst_n = 0; // rst_n toggles: 1 -> 0 (Verifies reset can pull active low again)
#20 rst_n = 1; // rst_n toggles: 0 -> 1 (Leaves it high for normal operation)

// Synchronize with the clock edge to avoid setup/hold race conditions in simulation
@(posedge clk);
#2; // Small delay after clock edge to mimic physical signal settling

// --- STEP 2: NORMAL OPERATION TOGGLES (scan_mode = 0) ---


scan_mode = 0;
data_in = 1; // data_in toggles: 0 -> 1

// We need multiple clock cycles to push the '1' through latch1, then latch2, then data_out
@(posedge clk); #2; // latch1 becomes 1
@(posedge clk); #2; // latch2 and data_out become 1

data_in = 0; // data_in toggles: 1 -> 0


@(posedge clk); #2; // latch1 becomes 0
@(posedge clk); #2; // latch2 and data_out become 0

// --- STEP 3: SCAN OPERATION TOGGLES (scan_mode = 1) ---


scan_mode = 1; // scan_mode toggles: 0 -> 1
scan_in = 1; // scan_in toggles: 0 -> 1
@(posedge clk); #2; // latch1 becomes 1 (via scan path)
@(posedge clk); #2; // latch2 and data_out become 1

scan_in = 0; // scan_in toggles: 1 -> 0


@(posedge clk); #2; // latch1 becomes 0
@(posedge clk); #2; // latch2 and data_out become 0

// --- STEP 4: CLOSING THE TOGGLE LOOPS ---


// Currently, scan_mode went from 0 -> 1, but never back to 0 at a stable sample point.
// We must toggle it back to 0 to complete its 1 -> 0 toggle requirement.
scan_mode = 0; // scan_mode toggles: 1 -> 0

// Run for two more clock cycles to make sure XSIM processes the final evaluation
@(posedge clk);
@(posedge clk);

// Finish the simulation


$finish;
73
250280763009 ME02000181

end

// Display output
initial begin
$monitor("Time = %0t, rst_n = %b, data_in = %b, scan_in = %b, scan_mode = %b, data_out = %b",
$time, rst_n, data_in, scan_in, scan_mode, data_out);
end
endmodule

OUTPUT WAVEFORM:

CODE COVERAGE:

74
250280763009 ME02000181

EXPERIMENT 12

Write a HDL code to realize functioning of fixing bus contention in scan design rules.

Bus Arbitration: Basic Theory

Bus Arbitration is a mechanism used in digital systems to ensure that multiple devices (or drivers) do not
attempt to drive the same bus at the same time, which would lead to bus contention and potentially cause
data corruption or hardware damage.

Why Bus Arbitration is Needed:


In systems where multiple components (such as processors, memory units, or I/O devices) share a
common data bus, it's crucial to control access to the bus. Without proper arbitration, two or more devices
might try to write data to the bus simultaneously, causing:
 Data corruption: Multiple drivers sending conflicting data.
 Hardware damage: Driving different voltage levels onto the same bus can cause permanent damage
to components.
 Logical errors: Incorrect data might be read by the receiving component.

Types of Bus Arbitration:


1. Centralized Arbitration:
o A single arbitrator (usually a controller) decides which device can use the bus at any given
time.
o The arbitrator controls access to the bus and ensures that only one device drives the bus at
a time.
o Example: A "Bus Request" signal is sent from devices to the arbitrator. The arbitrator then
grants access to one device at a time.
2. Distributed Arbitration:
o In this approach, each device has its own control logic to decide if it can access the bus.
o There is no central arbitrator, but the devices communicate with each other to negotiate bus
access.
o Example: A "priority" scheme is used where devices with higher priority can access the bus
over others.

Arbitration Methods:
 Priority-based Arbitration: Devices are assigned priorities, and the device with the highest
priority gains access to the bus first. This can be implemented using a simple priority encoder.
 Round-Robin Arbitration: Each device gets a fair chance to access the bus in a cyclic order,
preventing starvation of lower-priority devices.
 First-Come-First-Served (FCFS): The first device requesting access to the bus is granted
permission to drive the bus, and the order is maintained.

Simple Arbitration Example:


In the case of scan-based testing or devices such as processors trying to access a bus, an arbitration
circuit ensures only one device can write to the bus at a time. The arbitration circuit typically includes:
 A request signal from each device.
 A grant signal that informs the requesting device whether it can access the bus.
 Logic to handle multiple devices requesting access simultaneously (using priority or round-robin).

75
250280763009 ME02000181

In a scan-based design, this arbitration prevents issues like bus contention, ensuring that scan chains (used
for testing) are properly driven during testing phases.

DESIGN CODE:

module bus_arbitration ( input wire clk,


input wire reset,
input wire scan_mode,// Scan mode signal
input wire driver_a_valid, // Driver A is trying to drive the bus input wire driver_b_valid, // Driver B
is trying to drive the bus input wire driver_c_valid, // Driver C is trying to drive the bus input wire
[7:0] driver_a_data, // Data from Driver A
input wire [7:0] driver_b_data, // Data from Driver B input wire [7:0] driver_c_data, // Data from
Driver C output reg [7:0] bus_data // The output bus data
);
// Internal signal to select the bus driver reg [7:0] selected_data;
always @(posedge clk or posedge reset) begin if (reset) begin
bus_data <= 8'b0; // Reset bus data selected_data <= 8'b0;
end else if (scan_mode) begin
// Bus arbitration logic during scan mode if (driver_a_valid) begin
selected_data <= driver_a_data; end else if (driver_b_valid) begin
selected_data <= driver_b_data; end else if (driver_c_valid) begin
selected_data <= driver_c_data; end else begin
selected_data <= 8'b0; // No valid driver end
bus_data <= selected_data; end
end
endmodule

TESTBENCH:

module tb_bus_arbitration;
// Declare testbench signals
reg clk;
reg reset;
reg scan_mode; reg driver_a_valid; reg driver_b_valid; reg driver_c_valid;
reg [7:0] driver_a_data;
reg [7:0] driver_b_data;
reg [7:0] driver_c_data;
wire [7:0] bus_data;
// Instantiate the bus_arbitration module
bus_arbitration uut (
.clk(clk),
.reset(reset),
.scan_mode(scan_mode),
.driver_a_valid(driver_a_valid),
.driver_b_valid(driver_b_valid),
.driver_c_valid(driver_c_valid),
.driver_a_data(driver_a_data),

76
250280763009 ME02000181

.driver_b_data(driver_b_data),
.driver_c_data(driver_c_data),
.bus_data(bus_data)
);
// Clock generation
always begin
#5 clk = ~clk; // 100MHz clock (period = 10ns)
end

// Initial block to apply test vectors


initial begin
$dumpfile("[Link]"); $dumpvars;
// Initialize signals
clk = 0;
reset = 0;
scan_mode = 0;
driver_a_valid = 0;
driver_b_valid = 0;
driver_c_valid = 0; driver_a_data = 8'b0; driver_b_data = 8'b0; driver_c_data = 8'b0;

// Apply reset
#10 reset = 0;
#10 reset = 1;
#10 reset = 0;
// Start scan mode
#10 scan_mode = 0;
#10 scan_mode = 1;

// Test case 1: Only Driver A is valid


driver_a_valid = 1;
driver_a_data = 8'b10101010; // Driver A sends data
driver_b_valid = 0;
driver_c_valid = 0;
#10; // Wait for 1 clock cycle
$display("Bus Data: %b (Expected: 10101010)", bus_data);

// Test case 2: Only Driver B is valid


driver_a_valid = 0;
driver_b_valid = 1;
driver_b_data = 8'b11001100; // Driver B sends data
driver_c_valid = 0;
#10;
$display("Bus Data: %b (Expected: 11001100)", bus_data);

// Test case 3: Only Driver B is valid


driver_a_valid = 0;
driver_b_valid = 1;
driver_b_data = 8'b00110011; // Driver B sends data
77
250280763009 ME02000181

#10;
$display("Bus Data: %b (Expected: 00110011)", bus_data);

// Test case 4: Only Driver B is valid


driver_a_valid = 0;
driver_b_valid = 1;
driver_b_data = 8'b11001100; // Driver B sends data
driver_c_valid = 0;
#10;
$display("Bus Data: %b (Expected: 11001100)", bus_data);

// Test case 5: Driver A and Driver B are both valid, but A has priority
driver_a_valid = 1;
driver_b_valid = 1;
driver_a_data = 8'b01010101;
driver_b_data = 8'b00001111;
driver_c_valid = 0;
#10;
$display("Bus Data: %b (Expected: 01010101)", bus_data); // A has priority over B

// Test case 6: Only Driver C is valid


driver_a_valid = 0;
driver_b_valid = 0;
driver_c_valid = 1;
driver_c_data = 8'b00110011; // Driver C sends data
#10;
$display("Bus Data: %b (Expected: 00110011)", bus_data);

// Test case 7: Only Driver C is valid


driver_a_valid = 0;
driver_b_valid = 0;
driver_c_valid = 1;
driver_c_data = 8'b11001100; // Driver C sends data
#10;
$display("Bus Data: %b (Expected: 11001100)", bus_data);

// Test case 8: Only Driver C is valid


driver_a_valid = 0;
driver_b_valid = 0;
driver_c_valid = 1;
driver_c_data = 8'b00110011; // Driver C sends data
#10;
$display("Bus Data: %b (Expected: 00110011)", bus_data);

// Test case 9: All drivers are valid (only A should drive the bus)
driver_a_valid = 1;
driver_b_valid = 1;
78
250280763009 ME02000181

driver_c_valid = 1;
driver_a_data = 8'b10101010;
driver_b_data = 8'b00000000;
driver_c_data = 8'b10101010;
#10;
$display("Bus Data: %b (Expected: 10101010)", bus_data); // A has priority over others

// Test case 10: No driver is valid (bus should be zero)


driver_a_valid = 0;
driver_b_valid = 0;
driver_c_valid = 0;

#10 scan_mode = 0;
#10;
$display("Bus Data: %b (Expected: 00000000)", bus_data);

// End simulation
$finish; // Ensure this is inside the initial block
end
endmodule

OUTPUT WAVEFORM:

79
250280763009 ME02000181

CODE COVERAGE:

80

You might also like