Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 23

Lab Experiment-7

Title of the Experiment: To design Latches (D-Latch) and Flip-Flops (D, T, JK, SR-FF’s) using Verilog
code and compare them with their respective truth tables.
Objective/Motivation: In this lab, Latches (D-Latch) and Flip-Flops (D, T, JK, SR-FF’s) are designed. The
objective will be to test these designs on the Xilinx simulation tool. The tests will be performed for all the
possible combinations of inputs to verify their functionality. Moreover, the knowledge gained will be used to
design much larger and complex logic designs.
Equipment required:
S No Name of The Components/Tool Version Quantity
1. Xilinx Vivado Design Suite / EDA play Ground software V23.1 1
Zynq
2. Zybo board 1
XC7Z010
3. Personal Computer - 1
Logic diagram(s) and Truth tables:
Logic Circuit
Logic Diagram Logical Expression Truth Table
name
Input Output
Clk S R Q Q’
0 0 0 Q Q’
SR FF
0 0 1 0 1
0 1 0 1 0
0 1 1 x x
Input Output
Clk D Q Q’
D-FF 0 0 0 0
1 0 0 1
Q(next) = D 1 1 1 0
Input Output
Clk J K Q Q’
0 0 0 Q=0 1
JK-FF 0 0 1 0 1
0 1 0 1 0

0 1 1 1 0
Q(n+1) = JQ’ + K’Q

Input Output
rstn Clk T Q Q’
0 0 0 0 1
T-FF
0 1 0 0 1

1 0 1 0 1
Q(next) = TQ’ + T’Q
1 1 1 1 0
Logic CKT
Logic Diagram Logical Expression Truth Table
name
Input Output
En D Q Q’
D-Latch 0 0 0 0
1 0 0 1
Q(n+1) = EN.D + EN'.Q(n) 1 1 1 0
Verilog Source Code for All gates in various Models or various Level of Abstrction:
Gate name Source Code Test Bench
// D Latch Source code // D Latch Test bench code
module dl_d(d,e,q,q1); module dl_d_tb();
input d,c; reg d,e;
output q,q1;
wire q,q1;
assign w1=~(d&e); dl_d uut(d,e,q,q1);
assign w2=~((~d)&e);
assign q=~(w1&&q1); initial begin
assign q1=~(w2&q); d=0;e=0;
D-latch endmodule #100
d=1;e=1;
#100
d=0;e=1;
#100
$stop;
end
endmodule
// SRFF Source code // SRFF Testbench code
module srff_d_tb();
module srff_d(s,r,clk,q,qb);
reg s,r,clk;
input s,r,clk; wire q,qb;
output q,qb; srff_d uut(s,r,clk,q,qb);
wire a,b; initial begin
assign a=~(clk&s); s=0;r=0;clk=0;
assign b=~(clk&r); #100
SRFF assign qb=~(b&q); s=0;r=1;
assign q=~(a&qb); #100
endmodule s=1;r=0;
#100
s=1;r=1;
#100
$stop;
end
always #50 clk=~clk;
endmodule
module dff_d(d,c,q,q1); module dff_d_tb();
input d,c; reg d,c;
output q,q1;
wire q,q1;
assign w1=~(d&c); dff_d uut(d,c,q,q1);
assign w2=~((~d)&c);
assign q=~(w1|q1); initial begin
D-FF assign q1=~(w2|q); d=0;c=0; #100
endmodule d=1;c=1; #100
d=0;c=1; #100
$stop;
end
endmodule
Verilog Source Code for All gates in various Models or various Level of Abstrction:

Gate name Source Code Test Bench


// JKFF Source code // JKFF Testbench code
module jkfff_d_tb();
module jkff_d(j,k,clk,q,qb);
input j,k,clk; reg j,k,clk;
output q,qb; wire q,qb;
reg q; jkff_d uut(j,k,clk,q,qb);
initial initial begin
q=0;
j=0;k=0;clk=0;
always@(negedge clk) #100
assign q=(j&~q)|(~k&q); j=0;k=1;
JK-FF assign qb=~q; #100
endmodule
j=1;k=0;
#100
j=1;k=1;
#100
$stop();
end
always #50 clk=~clk;
endmodule
// TFF Source code // TFF Tesetbench code
module tff_d(q,qbar,clk,rst,t);
input clk,rst,t; module tff_d_tb();
output q,qbar; reg clk,rst,t;
reg q,qbar;
wire qq=t^q; wire q,qbar;
always @ (posedge clk,negedge tff_d uut(q,qbar,clk,rst,t);
rst) initial begin
begin rst = 1'b0;
if(rst==1'b0)
T-FF begin clk = 1'b0;
q=1'b0; t = 1'b0;
qbar=1'b1; end
end always #100 clk=~clk;
else always #200 t=~t;
begin
q=qq; always #200 rst=~rst;
qbar=~q; endmodule
end
end
endmodule

Operation Procedure:
 A flip-flop is a digital memory circuit that stores one bit of data. They are the primary blocks of the most
sequential circuits. It is also called one-bit memory, binary, or a bistable multivibrator. Flip-flops act as
memory elements in a sequential circuit. You can obtain the output in the sequential circuits using a flip-flop,
a combinational circuit, or both.
 Flip-flop state repeatedly changes at an active state of the clock pulses. They remain unaffected even when
the clock pulse does not stay active. The clocked flip-flops particularly act as the memory elements of the
synchronous sequential circuit- while the un-clocked ones (latches) function as the memory elements of
asynchronous sequential circuits.
 There are mainly four types of flip-flops:
 JK Flip-Flop
 SR (Set-Reset) Flip-Flop
 Data or Delay (D) Flip-Flop
 Toggle (T) Flip-Flop
 A latch is an electronic device that changes its output immediately on the basis of the applied input. One can
use it to store either 0 or 1 at a specified time. A latch contains two inputs- SET and RESET, and it also has
two outputs. They complement each other. One can use a latch for storing one bit of data. It is a memory
device- just like the flip-flop. But it is not synchronous, and it does not work on the edges of the clock like
the flip-flop.
 The major difference between flip-flop and latch is that the flip-flop is an edge-triggered type of memory
circuit while the latch is a level-triggered type. It means that the output of a latch changes whenever the input
changes. On the other hand, the latch only changes its state whenever the control signal goes from low to
high and high to low.
8. Design and verification of 4-bit shift registers SISO, SIPO, PISO and PIPO
Objective: Design and verification of SISO,SIPO,PISO,PIPO.

Serial In Serial Out Shift register(SISO)


Theory:
The SISO shift register is one of the simplest of the four configurations as it has only three connections, the serial
input (SI) which determines what enters the left hand flip-flop, the serial output (SO) which is taken from the
output of the right hand flip-flop and the sequencing clock signal (Clk). The logic circuit diagram below shows a
generalized serial-in serial-out shift register.
Block Diagram

Truth table

Source code:
module D_FF(clk,din,q);
input clk,din; // Define input ports clk and din
output reg q; // Define output port q as a registered output
always @(posedge clk) // Always block triggered on positive edge of clk
q<=din; // Assign din to q on positive edge of clk
endmodule

module SISO_4bit(CLK,A,B0,B1,B2,B3);
input CLK, A; // Define input ports CLK and A
output B0,B1,B2,B3; // Define output ports B0, B1, B2, B3
D_FF D0(CLK, A, B0); // Instantiate D_FF module with inputs CLK, A, and output B0
D_FF D1(CLK, B0, B1); // Instantiate D_FF module with inputs CLK, B0, and output B1
D_FF D2(CLK, B1, B2); // Instantiate D_FF module with inputs CLK, B1, and output B2
D_FF D3(CLK, B2, B3); // Instantiate D_FF module with inputs CLK, B2, and output B3
endmodule

Testbench code:
module testbench;
reg clk, a; // Declare reg type variables clk and a
wire b0,b1,b2,b3; // Declare wire type variables b0, b1, b2, b3
SISO_4bit s1(clk,a,b0,b1,b2,b3); // Instantiate SISO_4bit module with inputs clk, a, and outputs b0, b1, b2, b3
initial
begin
$monitor("clk=%b, a=%b, b0=%b, b1=%b, b2=%b, b3=%b", clk, a, b0,b1,b2,b3); // Display values of clk, a,
b0, b1, b2, b3 using $monitor
clk=0; // Initialize clk to 0
a=0; // Initialize a to 0
#2 // Wait for 2 time units
a=1; // Assign 1 to a
#2 // Wait for 2 time units
a=0; // Assign 0 to a
#2 // Wait for 2 time units
a=1; // Assign 1 to a
#4 // Wait for 4 time units
a=0; // Assign 0 to a
#2 // Wait for 2 time units
a=1; // Assign 1 to a
end
initial
repeat(35) // Repeat block 35 times
#1 clk=~clk; // Toggle clk every 1 time unit
initial begin
$dumpfile("dump.vcd"); // Create a VCD dump file named "dump.vcd"
$dumpvars; // Dump all variables for waveform viewing
end
endmodule

Parallel In Serial Out (PISO)


The Parallel-in to Serial-out shift register acts in the opposite way to the serial-in to parallelout one above. The
data is loaded into the register in a parallel format in which all the data bits enter their inputs simultaneously, to
the parallel input pins PA to PD of the register. The data is then read out sequentially in the normal shift-right
mode from the register
at Q representing the data present at PA to PD.
This data is outputted one bit at a time on each clock cycle in a serial format.
Block diagram

Source code:
module piso(din,clk,rst,dout);
input [3:0]din; // Input data of 4 bits
input clk, rst; // Clock and reset inputs
output reg dout; // Output register

always@(posedge clk) // Always block triggered on positive edge of clk


begin
if(rst) // Reset condition
dout=0; // Output is set to 0 when reset is active
else
begin
dout=din[3]; // Output is set to the most significant bit of din
$display("Time=%0t rst=%b din=%b dout=%b", $time, rst, din, dout); // Display simulation time, reset,
input, and output values

dout=din[2]; // Output is set to the second most significant bit of din


$display("Time=%0t rst=%b din=%b dout=%b", $time, rst, din, dout); // Display simulation time, reset,
input, and output values

dout=din[1]; // Output is set to the third most significant bit of din


$display("Time=%0t rst=%b din=%b dout=%b", $time, rst, din, dout); // Display simulation time, reset,
input, and output values

dout=din[0]; // Output is set to the least significant bit of din


$display("Time=%0t rst=%b din=%b dout=%b", $time, rst, din, dout); // Display simulation time, reset,
input, and output values
end
end
endmodule

Testbench code:
module tb();
reg clk,rst; // Register for clock and reset
reg [3:0]din; // Register for 4-bit input data
wire dout; // Output wire
piso p1(din,clk,rst,dout); // Instance of piso module

initial begin
clk=0; // Initialize clock to 0
forever #1clk=~clk; // Toggle clock every 1 time unit
end

initial begin
rst=1; // Set reset to 1
#5 rst=0; // Remove the reset after 5 time units
repeat(10) // Repeat loop 10 times
#1 din=$random; // Assign random values to din every time unit
$finish; // Finish simulation
end

initial begin
$dumpfile("dump.vcd"); // Dump waveform data to dump.vcd file
$dumpvars(); // Dump variables for waveform tracing
end
endmodule

Parallel In parallel Out (PIPO)


module pipo(din, clk, rst, dout);
input [3:0] din; // 4-bit input data
input rst, clk; // Reset and clock inputs
output reg [3:0] dout; // 4-bit output register

always@(posedge clk) // Triggered on positive edge of clk


begin
if(rst)
dout = 0; // Reset output to 0 when rst is active
else
begin
dout = din; // Set output to input data when rst is not active
$display("Time=%0t rst=%b din=%b dout=%b", $time, rst, din, dout); // Display simulation time, rst, input
data, and output data
end
end
endmodule

Testbench Code

module tb();
reg clk, rst; // Clock and reset registers
reg [3:0] din; // 4-bit data input register
wire [3:0] dout; // 4-bit data output wire
pipo p1(din, clk, rst, dout); // Instance of pipo module

initial begin
clk = 0; // Initialize clock to 0
forever #1clk =~clk; // Toggle clock every 1 time unit
end

initial begin
rst = 1; // Set reset to 1
#5 rst = 0; // Deassert reset after 5 time units
repeat(40) // Repeat loop 40 times
#1 din = $random; // Assign random values to din every time unit
#40 $finish; // Finish simulation after 50 time units
end

initial begin
$dumpfile("dump.vcd"); // Dump waveform data to dump.vcd file
$dumpvars(); // Dump variables for waveform tracing
end
endmodule
Asynchronous Counter
In asynchronous counter, within the counter output of one flip flop stage, is driven to the clock
pin of the next flip flop stage. Thus, the transition of the first stage ripples till the last flip-flop stage.
Hence, it is also known as the “Ripple Counter” or “Serial Counter”. In the asynchronous counter,
individual flip-flop stages are triggered with the different clocks. Due to this, it is slower when
compared with a synchronous counter. It is easy to design with less hardware requirement.
Disadvantages
1. Slow operation when compared with a synchronous counter.
2. High propagation delay

module JK_flipflop (
input clk, rst_n,
input j,k,
output reg q, q_bar
);

always@(posedge clk or negedge rst_n) begin // for asynchronous reset


if(!rst_n) q <= 0;
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; // Toggle
endcase
end
end
assign q_bar = ~q;
endmodule

module updown_selector(input q, q_bar, bit up, output nclk);


assign nclk = up?q_bar:q;
endmodule
module asynchronous_counter #(parameter SIZE=4)(
input clk, rst_n,
input j, k,
input up,
output [3:0] q, q_bar
);
wire [3:0] nclk;
genvar g;
/*
// Up Counter (at output q)
JK_flipflop jk1(clk, rst_n, j, k, q[0], q_bar[0]);
JK_flipflop jk2(q_bar[0], rst_n, j, k, q[1], q_bar[1]);
JK_flipflop jk3(q_bar[1], rst_n, j, k, q[2], q_bar[2]);
JK_flipflop jk4(q_bar[2], rst_n, j, k, q[3], q_bar[3]);

// Down Counter (at output q)


JK_flipflop jk1(clk, rst_n, j, k, q[0], q_bar[0]);
JK_flipflop jk2(q[0], rst_n, j, k, q[1], q_bar[1]);
JK_flipflop jk3(q[1], rst_n, j, k, q[2], q_bar[2]);
JK_flipflop jk4(q[2], rst_n, j, k, q[3], q_bar[3]);

// Up and Down Counter (at output q)


JK_flipflop jk1(clk, rst_n, j, k, q[0], q_bar[0]);
updown_selector ud1(q[0], q_bar[0], up, nclk[0]);

JK_flipflop jk2(nclk[0], rst_n, j, k, q[1], q_bar[1]);


updown_selector ud2(q[1], q_bar[1], up, nclk[1]);

JK_flipflop jk3(nclk[1], rst_n, j, k, q[2], q_bar[2]);


updown_selector ud3(q[2], q_bar[2], up, nclk[2]);

JK_flipflop jk4(nclk[2], rst_n, j, k, q[3], q_bar[3]);


*/

// Using generate block


JK_flipflop jk0(clk, rst_n, j, k, q[0], q_bar[0]);
generate
for(g = 1; g<SIZE; g++) begin
updown_selector ud1(q[g-1], q_bar[g-1], up, nclk[g-1]);
JK_flipflop jk1(nclk[g-1], rst_n, j, k, q[g], q_bar[g]);
end
endgenerate
endmodule

module tb;
reg clk, rst_n;
reg j, k;
reg up;
wire [3:0] q, q_bar;
asynchronous_counter uut(clk, rst_n, j, k, up, q, q_bar);

initial begin
clk = 0; rst_n = 0;
up = 1;
#4; rst_n = 1;
j = 1; k = 1;
#80;
rst_n = 0;
#4; rst_n = 1; up = 0;
#50;
$finish;
end
always #2 clk = ~clk;

initial begin
$dumpfile("dump.vcd"); $dumpvars;
end
endmodule

Synchronous Counter
As we have discussed the asynchronous counter, output of one flip-flop stage is connected to
the input clock pin of the next stage that introduces propagation delay. In a synchronous counter, all
flip-flops within the counter are clocked together by the same clock which makes it faster when
compared with an asynchronous counter. It is known as a parallel counter.

module synchronous_counter #(parameter SIZE=4)(


input clk, rst_n,
input up,
output reg [3:0] cnt
);

always@(posedge clk) begin


if(!rst_n) begin
cnt <= 4'h0;
end
else begin
if(up) cnt <= cnt + 1'b1;
else cnt <= cnt - 1'b1;
end
end
endmodule

module tb;
reg clk, rst_n;
reg up;
wire [3:0] cnt;
synchronous_counter(clk, rst_n, up, cnt);

initial begin
clk = 0; rst_n = 0;
up = 1;
#4; rst_n = 1;
#80;
rst_n = 0;
#4; rst_n = 1; up = 0;
#50;
$finish;
end
always #2 clk = ~clk;

initial begin
$dumpfile("dump.vcd"); $dumpvars;
end
endmodule

Difference between synchronous and asynchronous counter

Asynchronous Counter Synchronous Counter

In asynchronous counter, the output of one


In the synchronous counter, the same
flip flop stage is driven to the clock input of
clock is driven to all flip-flop stages
the next stage.

Slower as compared to the synchronous Faster as compared to the asynchronous


counter counter.

It is also known as serial counter It is also known as parallel counter

Propagation delay is less compared to the


High propagation delay
asynchronous counter.
Universal Shift Register
A universal shift register is a sequential logic that can store data within and on every clock pulse it
transfers data to the output port.
The universal shift register can be used as
1. Parallel In Parallel Out shift register
2. Parallel In Serial Out shift register
3. Serial In Parallel Out shift register
4. Serial In Serial Out shift register

Operation

Mode control
Operation
(select)

0 0 No change

0 1 Shift right

1 0 Shift left

1 1 Parallel load

module universal_shift_reg(
input clk, rst_n,
input [1:0] select, // select operation
input [3:0] p_din, // parallel data in
input s_left_din, // serial left data in
input s_right_din, // serial right data in
output reg [3:0] p_dout, //parallel data out
output s_left_dout, // serial left data out
output s_right_dout // serial right data out
);
always@(posedge clk) begin
if(!rst_n) p_dout <= 0;
else begin
case(select)
2'h1: p_dout <= {s_right_din,p_dout[3:1]}; // Right Shift
2'h2: p_dout <= {p_dout[2:0],s_left_din}; // Left Shift
2'h3: p_dout <= p_din; // Parallel in - Parallel out
default: p_dout <= p_dout; // Do nothing
endcase
end
end
assign s_left_dout = p_dout[0];
assign s_right_dout = p_dout[3];
endmodule

module TB;
reg clk, rst_n;
reg [1:0] select;
reg [3:0] p_din;
reg s_left_din, s_right_din;
wire [3:0] p_dout; //parallel data out
wire s_left_dout, s_right_dout;

universal_shift_reg usr(clk, rst_n, select, p_din, s_left_din, s_right_din, p_dout,


s_left_dout, s_right_dout);

always #2 clk = ~clk;


initial begin
$monitor("select=%b, p_din=%b, s_left_din=%b, s_right_din=%b --> p_dout = %b,
s_left_dout = %b, s_right_dout = %b",select, p_din, s_left_din, s_right_din, p_dout,
s_left_dout, s_right_dout);
clk = 0; rst_n = 0;
#3 rst_n = 1;

p_din = 4'b1101;
s_left_din = 1'b1;
s_right_din = 1'b0;

select = 2'h3; #10;


select = 2'h1; #20;
p_din = 4'b1101;
select = 2'h3; #10;
select = 2'h2; #20;
select = 2'h0; #20;

$finish;
end
// To enable waveform
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end

endmodule
EXP 11
Ring Counter and Johnson Counter
// Code your design here
module ringcounter(clk, rst, count);
input clk, rst;
output [5:0] count;
wire clk, rst;
reg [5:0] count = 8'b1;
// Respond to the positive-going pulse edge
always @ ( posedge clk, posedge rst )
begin
if ( ~rst )
begin
count <= count << 1;
count[0] <= count[5];
end
else
count <= 8'b1;
end

endmodule

// Code your testbench here


// or browse Examples
module top();
reg clk = 0, rst = 0;
wire [5:0] count;
always #1 clk = ~clk; // Create a clock pulse

initial begin
$monitor("At time %4t, count = %b", $time, count );
#5 rst = 1;
#5 rst = 0;
#200 $finish;
end

ringcounter cntr01 ( .clk(clk), .rst(rst), .count(count) );

initial
begin
$dumpvars(0,top);
$dumpfile("my.vcd");
end
endmodule

Johnson Counter Code:

module johnson_ctr #(parameter WIDTH=4)


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

always @ (posedge clk) begin


if (!rstn)
out <= 1;
else begin
out[WIDTH-1] <= ~out[0];
for (int i = 0; i < WIDTH-1; i=i+1) begin
out[i] <= out[i+1];
end
end
end
endmodule

module tb;
parameter WIDTH = 4;

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

johnson_ctr 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);
$finish;
end

initial begin
$dumpvars;
$dumpfile("dump.vcd");
end
endmodule
Result: The simulation waveforms are obtained with various input combination of binary data and verified with
the truth table data.

You might also like