You are on page 1of 16

Lab 8: Introduction to

Sequential Logic
Deanna Sessions
ECEN 248-511
TA: Priya Venkatas
Date: October 30, 2013

Objectives:
This lab is where we will learn about sequential logic circuits. This includes learning about
latches and flip-flops and adding the element of time delays into the circuit. This gets to a more
real-life application of the circuits because time delays end up being a large portion of intricate
circuits and it is important the proper information is at the right place at the right time. The
concept of a synchronous circuit has been talked about in previous labs, but we have not really
cared about time delay up until this point and now we will account for timing with a clock signal.
This lab also introduces our first technical usage of latches in which we include a clock and a
master-slave layout of the flip-flop circuit.

Design:
Below are all of the source codes from the lab with comments included:
//sr_latch.v
`timescale 1 ns/ 1 ps
`default_nettype none
module sr_latch( Q, notQ, En, S, R);

//defining inputs and outputs

output wire Q, notQ;


input wire En, S, R;

//outputs of Q and ~Q
//inputs of an enable bit, set, and reset

wire nandSEN, nandREN;

//internal wires

nand #2 nand0(Q, nandSEN, notQ); //NAND gates with time delays of 2 ns


nand #2 nand1(notQ, nandREN, Q);
nand #2 nand2(nandSEN, En, S);
nand #2 nand3(nandREN, En, R);
endmodule
//d_latch
//for the #4 just change #2 to #4
`timescale 1 ns/ 1 ps
`default_nettype none
module d_latch(Q, notQ, En, D);

//defining inputs and outputs

input wire D, En;


output wire Q, notQ;

//input of data and enable


//outputs Q and ~Q

wire nandDEN, nandNotDEN, notD;

//internal wires

not #2 not0(notD, D);


//NOT gate to have an inverse of the data
nand #2 nand0(Q, nandDEN, notQ); //NAND gates with time delay of 2 ns (or 4 ns for second test)
nand #2 nand1(notQ, nandNotDEN, Q);
nand #2 nand2(nandDEN, D, En);
nand #2 nand3(nandNotDEN, notD, En);
endmodule

//d_flip_flop.v
`timescale 1 ns/ 1 ps
`default_nettype none
module d_flip_flop(Q, notQ, Clk, D);

//defining inputs and outputs

output wire Q, notQ;


input wire Clk, D;

//outputs of Q and ~Q
//inputs of a clock and data

wire notClk, notNotClk;


wire Q_m;
wire notQ_m;

//internal wires

not #2 not0(notClk, Clk);


not #2 not1(notNotClk, notClk);

//NOT gate to have an inverse clock


//NOT gate to have an inverse inverse clock

d_latch master(Q_m, notQ_m, notClk, D); //Master D Latch


d_latch slave(Q, notQ, notNotClk, Q_m); //Slave D Latch that follows the Master
endmodule
//new d flip flop that works with my test bench
`timescale 1 ns/ 1 ps
`default_nettype none
module d_flip_flop(Q, notQ, Q_m, notQ_m, Clk, D);

//Defining inputs and outputs

output wire Q, notQ, Q_m, notQ_m;


input wire Clk, D;
wire notClk, notNotClk;

//Gives internal answers as outputs as well


//inputs of clock and data
//internal clock wires

not #2 not0(notClk, Clk);


not #2 not1(notNotClk, notClk);

//NOT to have different timed clock

d_latch master(Q_m, notQ_m, notClk, D);


d_latch slave(Q, notQ, notNotClk, Q_m);

//Master D Latch
//Slave D Latch

endmodule
//d_latch_behavioral
`timescale 1 ns/ 1 ps
`default_nettype none
module d_latch_behavioral(
output reg Q,
output wire notQ,
input wire D, En
);
always@(En or D)
if (En)
Q=D;
else
Q=Q;

//Defining inputs and outputs

//Called whenever the is an Enable or Data


//If Enable bit is high
//Then Q is equal to the data
//anything else (Enable is low)
//Q is equal to whatever Q was previously

assign notQ = ~Q;


endmodule

//d_flip_flop_behavioral
`timescale 1 ns/ 1 ps
`default_nettype none
module d_flip_flop_behavioral(
output reg Q,
output wire notQ,
input wire D,
input wire Clk
);
always@(posedge Clk)
Q<=D;

//defining inputs and outputs

//If the clock is on a positive edge it latches to data

assign notQ = ~Q;


endmodule
//adder_2bit
`timescale 1 ns/ 1 ps
`default_nettype none
module adder_2bit(Carry, Sum, A, B);
output wire Carry;
output wire [1:0] Sum;
input wire [1:0] A, B;

//defining inputs and outputs

wire Cin;

//internal wires

full_adder f0(Sum[0], Cin, A[0], B[0], 1'b0);


full_adder f1(Sum[1], Carry, A[1], B[1], Cin);

//calls the full adders from previous lab

endmodule
//Full adder from previous lab
`timescale 1 ns/ 1 ps
`default_nettype none
module full_adder(S, Cout, A, B, Cin);
input wire A, B, Cin;
output wire S, Cout;

//defines inputs and outputs


//declare output and input

wire andBCin, andACin, andAB;

//declaring 1-bit wires

assign #6 S = A ^ B ^ Cin;
assign #4 andAB = A & B;
assign #4 andBCin = B & Cin;
assign #4 andACin = A & Cin;
assign #6 Cout = andAB | andBCin | andACin;

//XORed
//ANDed
//AND for BCin
//AND for ACin
//ORed together

endmodule

//adder_synchronous
`timescale 1 ns/ 1 ps
`default_nettype none
module adder_synchronous(Carry_reg, Sum_reg, Clk, A, B);
output reg Carry_reg;
output reg [1:0] Sum_reg;

//Outputs

input wire Clk;


input wire [1:0] A, B;

//inputs of a Clk, A, and B

reg [1:0] A_reg, B_reg;


wire Carry;
wire [1:0] Sum;

//internal wires

adder_2bit Add1(Carry, Sum, A_reg, B_reg); //calling the 2-bit adder


always@(posedge Clk)
begin
A_reg <=A;
B_reg <=B;
end
always@(posedge Clk)
begin
Carry_reg <= Carry;
Sum_reg <= Sum;
end

//when its on the positive edge of the clock


//internal A wire is equal to A
//internal B wire is equal to B
//when its on a positive edge of the clock
//Carry wire is equal to the carry
//Sum wire is equal to the sum

endmodule

These are the test bench programs that I amended:


//D_Flip_Flop_tb
`timescale 1ns / 1ps
`define STRLEN 32
module d_flip_flop_tb;
/*A task is similar to a procedure in the traditional programming language*/
/*This particular task simply checks the output of our circuit against a
known answer and prints a message based on the outcome. Additionally,
this task increments the variable we are using to keep track of the
number of tests successfully passed.*/
task passTest;
input [1:0] actualOut, expectedOut;
input [`STRLEN*8:0] testType;
inout [7:0] passed;
if(actualOut === expectedOut) begin $display ("%s passed", testType); passed = passed + 1; end
else $display ("%s failed: %x should be %x", testType, actualOut, expectedOut);
endtask
/*this task simply informs the user of the final outcome of the test*/
task allPassed;
input [7:0] passed;

input [7:0] numTests;


if(passed == numTests) $display ("All tests passed");
else $display("Some tests failed");
endtask
// Inputs
reg D;
reg Clk;
// Outputs
wire Q;
wire notQ;
wire Q_m;
wire notQ_m;

//these wires had to be added to match my code

reg [7:0] passed;


// Instantiate the Unit Under Test (UUT)
d_flip_flop uut (
.Q(Q),
.notQ(notQ),
.Clk(Clk),
.D(D),
.Q_m(Q_m),
//I had to add these variables to match with my code
.notQ_m(notQ_m)
);
/*generate clock signal*/
always
#40 Clk <= ~Clk;
initial begin
passed = 0;
Clk = 0;//initialize clock
D = 0;
@(posedge Clk) #11; //allow for internal delay in flip-flop
passTest({Q, notQ}, 2'b01, "D flip-flop Store 0 Test", passed);
D = 1;
#5;
passTest({Q, notQ}, 2'b01, "D flip-flop Hold 0 Test", passed);
@(posedge Clk) #11; //allow for internal delay in flip-flop
passTest({Q, notQ}, 2'b10, "D flip-flop Store 1", passed);
D = 0;
#1;
passTest({Q, notQ}, 2'b10, "D flip-flop Hold 1 Test", passed);
#5
@(posedge Clk) #11; //allow for internal delay in flip-flop
passTest({Q, notQ}, 2'b01, "D flip-flop Store 0 Test Again...", passed);
allPassed(passed, 5);//did all the tests pass???
$stop;//that's all folks!
end
endmodule

//adder_2bit_tb
`timescale 1ns / 1ps
module add_2bit_tb;//a test bench does not have any ports of its own!
/* Input nets */
reg [1:0] A; //these are regs because they are modified in
reg [1:0] B; //a behavioral block
/* Output nets */
wire [1:0] Sum; //these are wires because they will be driven
wire Carry;//by the inantiated module
/* Instantiate the Unit Under Test (UUT) */
adder_2bit uut ( //this is a different way
.A(A),
//to instantiate a module.
.B(B),
//the nice thing about this style
.Sum(Sum), //is that the order does not matter!
.Carry(Carry)//notice the ports are in a different order!
);

/*-this is a behavioral block which is executed only once! *


*-the statements within this behavioral block are executed *
*-sequentially because we are using blocking statements *
*-an '=' sign within a behavioral construct is considered a*
* blocking statement. We will talk more about this later...*/
initial
begin
/* Initialize inputs*/
A = 0;
B = 0;
#25; //just delay 25 ns
{A,B} = 4'b0000; //stimulate the inputs
#25; //wait a bit for the result to propagate
//here is where we could put a check to see if the results
//are as expected!
if({Carry, Sum} != 3'b000)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
//let's do it again with a different input...
{A,B} = 4'b0001; //stimulate the inputs
#25; //wait a bit for the result to propagate
//check output
if({Carry, Sum} != 3'b001)
$display("Your own message here...");
else
$display("Test vector passed!!!");
{A,B} = 4'b0010; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b010) //One of these statements had to be made for each binary possibility
$display("Ah crap... something went wrong here...");
else

$display("Hey! The UUT passed this test vector...");


{A,B} = 4'b0010; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b010)
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b0011; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b011)
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b0100; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b001)
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b0101; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b010)
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b0110; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b011)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b0111; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b100)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b1000; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b010)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b1001; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b011)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b1010; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b100)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b1011; //stimulate the inputs

#25;
if({Carry, Sum} != 3'b101)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b1100; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b011)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b1101; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b100)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b1110; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b101)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
{A,B} = 4'b1111; //stimulate the inputs
#25;
if({Carry, Sum} != 3'b110)//you could put your own message here
$display("Ah crap... something went wrong here...");
else
$display("Hey! The UUT passed this test vector...");
$stop;
end
endmodule

Results:
The results below are the waveforms that were created by running the source code found in the
design section with the test benches that had been previously made (some of which had to be
modified.) The bottom of the screen in each waveform demonstrates that all of the tests were
passed and the waveform itself displays the time delay that was being demonstrated in many of
the circuits. Each of the waveforms turned out much like I had expected and the circuits that
were run multiple times with different time delays proved to show the time delay accurately.

Figure 8.1: SR Latch 2ns

Figure 8.2: SR Latch 4ns

10

Figure 8.3: D Latch

Figure 8.4: D Flip Flop

11

Figure 8.5: D Flip Flop with all 6 outputs

Figure 8.6: D Flip Flop Behavioral

12

Figure 8.7: D Latch Behavioral

Figure 8.8: 2-Bit Adder

13

Figure 8.9: 2-bit Adder with Amended Test Bench

Figure 8.10: Synchronous Adder

14

Figure 8.11: Synchronous Adder at 20 ns Timescale

Conclusion:
Questions:
1. Source code shown in design section
2. Waveform diagrams shown in results section.
3. Questions throughout lab:
a. Now, change the 2 unit delays in your code to 4 units and run the test bench
again. Explain the results of the simulation.
Using the 4 ns delay caused the Q and notQ results to be delayed by 4ns instead
of 2 ns and the R, S, and En bits stayed the same as they were from the 2 ns
simulation. This makes sense because the inputs do not have the time delay
applied to them, the time delay comes through the circuit and the outputs are the
ones affected.
b. Simulate your D ip-op using the d ip op tb.v le in the course directory.
Add the internal nets within your D ip-op to the waveform and examine the
waveform after restarting the simulation. Do the latches behave as expected?
Why or why not?
The latches behave as expected when the internal nets have been added.
c. Compare the waveforms you captured from the behavioral Verilog
(d_latch_behavioral.v and d_flip_flop_behavioral.v) to those captured from the
structural Verilog. Are they different? If so, how?
The main difference is the time it took to start receiving data for Q and notQ. It
15

was significantly faster in the behavioral Verilog than it was in the structural
Verilog. Also, the D Latch had no time delay in the behavioral, but a significant
delay in the structural.
4. Compare the behavioral description of the synchronous adder found in the test
bench code with the combination of structural and dataflow Verilog you used in the
lab assignment. What are the advantages and disadvantages of each? Which to you
prefer and why?
The advantage to using the behavioral description is that it is very concise and to the
point because it uses one statement that then decides what kind of output it is going to be
rather than having to go through each specific answer and check it. In structural and
dataflow Verilog it is precise, but efficiency is lost because it has to read for each specific
output rather than just paying attention to the output behavior as a whole. I prefer
behavioral Verilog when it comes to this because it makes for nicer looking code that
works efficiently.
5. Based on the clock period you measured for your synchronous adder, what would
be the theoretical maximum clock rate? What would be the effect of increasing the
width of the adder on the clock rate? How might you improve the clock rate of the
design?
The timescale that the circuit can be reduced to and still work is 20 ns which works at a
50MHz clock rate. Increasing the width of the adder would cause the clock rate to drop
because it has to work with more inputs than previously and this would result in more of
a time delay which causes a drop in clock rate. Improving the clock rate of the design
would be best executed by decreasing the time delay in the circuit by simplifying the
circuit to less gates or by using gates with less time delay.

Student Feedback:
1. I liked that this lab was clear and to the point while also having enough questions in it
allowing for me to actually learn what I was doing. I feel like I am learning Verilog in an
efficient way and using the knowledge that I already have in order to build upon. It was
nice to see the differences between structural and behavioral circuits again and write my
own test bench parts.
2. Nothing about the lab manual was unclear.
3. Keep it exactly as it is. This lab works so nicely with the preceding labs.

16