Section 6: Lab 3 Head Start
In this discussion section you will use what you have learned in the previous discussion sections to get started on Lab 3. By the end of this discussion sectino, you will have implemented a D latch, D flip-flop, D flip-flop with reset, and D flip-flop with reset and enable. You will implement all of these (except the D latch) two ways: first using gate-level modeling and then using register-transfer-level modeling. Feel free to copy any code you would like from your work in this discussion section into your lab group repo.
In the past discussion sections, we have focused on how to use Verilog to model combinational logic at both the gate-level and register-transfer-level (RTL). In this discussion section, we will learn how to use Verilog to model sequential logic. Gate-level modeling of sequential logic largely uses similar syntax and semantics to modeling combinational logic at the gate level, but RTL modeling of sequential logic will require new syntax and semantics which we will need to understand and use carefully. Remember from last discussion section that it is critical that students always know what is the hardware they are modeling whether they are working at the gate- or register-transfer level.
1. Logging Into ecelinux
with VS Code
Follow the same process as previous discussion sections. Find a free workstation and log into the workstation using your NetID and standard NetID password. Then complete the following steps (described in more detail in the last discussion section):
- Start VS Code
- Install the Remote-SSH, Verilog, and Surfer extensions
- Use View > Command Palette to execute Remote-SSH: Connect Current Window to Host...
- Enter
netid@ecelinux-XX.ece.cornell.edu
where XX is anecelinux
server number - Install the Verilog extension on the server
- Use View > Explorer to open your home directory on
ecelinux
- Use View > Terminal to open a terminal on
ecelinux
There is no need to fork the repo for today's discussion section. Simple clone the repo as follows.
% source setup-ece2300.sh
% mkdir -p ${HOME}/ece2300
% cd ${HOME}/ece2300
% git clone git@github.com:cornell-ece2300/ece2300-sec06-lab3-head-start sec06
% cd sec06
% tree
The repo includes the following files:
Makefile.in
: Makefile for the build systemconfigure
: Configure script for the build systemconfigure.ac
: Used to generate the configure scriptscripts
: Scripts used by the build systemece2300
: ECE 2300 unit testing library and miscellaneous macroslab2/lab2.mk
: Tells build system about files in this subprojectlab2/Mux2_1b_GL.v
: 8-bit RTL adder (copy from lab 2)lab2/test
: Directory with unit tests for each hardware modulelab3/DLatch_GL.v
: 1-bit D latch at gate-levellab3/DFF_GL.v
: 1-bit D flip-flop at gate-levellab3/DFF_RTL.v
: 1-bit D flip-flop at RTLlab3/DFFR_GL.v
: 1-bit D flip-flop with reset at gate-levellab3/DFFR_RTL.v
: 1-bit D flip-flop with reset at RTLlab3/DFFRE_GL.v
: 1-bit D flip-flop with reset and enable at gate-levellab3/DFFRE_RTL.v
: 1-bit D flip-flop with reset and enable at RTLlab3/test
: Directory with unit tests for each hardware module
Go ahead and create a build directory and run configure to generate a Makefile.
To make it easier to cut-and-paste commands from this handout onto the
command line, you can tell Bash to ignore the %
character using the
following command:
Now you can cut-and-paste a sequence of commands from this tutorial
document and Bash will not get confused by the %
character which begins
each line.
2. Mux from Lab 2
Copy your 1-bit 2-to-1 multiplexor Lab 2 into the lab2
directory for
this discussion section. We give you our tests. Verify that these
hardware modules are working.
3. Implementing and Testing D Latch
We will start by exploring how to implement a D latch which has a data
input (d
) and a clock input (clk
) and one output (q
). A D latch is
transparent when the clock is one (i.e., the input passes directly to the
output) and is opaque with the clock is zero (i.e., the latch "remembers"
the value right before the clock transitioned to zero and holds this
value while the latch is opaque).
We have provided you the interface a D latch in DLatch_GL.v
and a test
bench in DLatch_GL-test.v
. For the test bench, we have provided you a
template for an exhaustive test case; all you need to do is fill in the
correct output values for each provided check. Notice that our checks
look exactly like an explicit-clock simulation table we discussed
lecture. You can test the D latch as follows.
Once your design is passing all your tests generate waveforms and take a look using Surfer.
% cd ${HOME}/ece2300/sec06/build
% ./DLatch_GL-test +test-case=2 +dump-vcd=waves.vcd
% surfer waves.vcd
4. Implementing and Testing Various D Flip-Flops
We will not implement three different kinds of flip-flops: a D flip-flop, a D flip-flop with reset, and a D flip-flop with reset and enable. Each will be implemented in two ways: first using gate-level modeling and then using register-transfer-level modeling.
4.1 D Flip-Flop
A D flip-flop has a data input (d
) and a clock input (clk
) and one
output (q
). Unlike a D latch, a D flip-flop is never transparent. A D
flip-flop samples its input right before the positive edge of the clock
and then holds this value for the entire clock period until the next
rising edge. We can implement a D flip-flop with two latches: a leader
latch and a follower latch. The leader latch uses the complement of the
clock so that only one latch is ever transparent on either phase of the
clock.
We have provided you the interface a D flip-flop in DFF_GL.v
, a test
bench in DFF_GL-test.v
, and test cases in DFF-test-cases.v
. Go ahead
and implement this module. For the test cases, we have provided you a
template for directed test cases; all you need to do is fill in the
correct output values for each provided check. You can test the D
flip-flop as follows.
We can also use RTL modeling to implement a D flip-flop. We will need to
use an always_ff
block, a new Verilog construct specifically design for
RTL modeling of sequential logic. Here is an example of how to use such
an always_ff
block.
module DFF_RTL
(
input logic clk,
input logic d,
output logic q
);
always_ff @( posedge clk ) begin
q <= d;
end
endmodule
An always_comb
block executes whenever any of the inputs to that block
change. An always_ff @(posedge clk)
block only executes on the rising
edge of the clock. Notice how we are using a non-block assignment (<=
)
instead of a blocking assignment (=
). A non-block assignment has very
different semantics to a blocking assignment. In a non-blocking
assignment, the right-hand side (i.e., d
) is evaluated and saved
before the rising clock edge and the left-hand side (i.e., q
) is only
updated after the rising clock edge. Critically, the right-hand side is
evaluated and saved in every always_ff
across the entire hardware
design before updating any left-hand side. This effectively models all
of these assignments happening concurrently on the rising edge of the
clock which is exactly what happens in hardware. We should only use
non-blocking assignments in always_ff
blocks, and we should only use
blocking assignments in always_comb
blocks. We should never mix these
up!
We have provided you the interface a D flip-flop in DFF_RTL.v
and a
test bench in DFF_RTL-test.v
. Go ahead and implement this module. The
test bench includes the same test cases you developed for the gate-level
implementation, so you should be able to go ahead and test the D
flip-flop as follows.
4.2 D Flip-Flop with Reset
We can add a reset (rst
) to our D flip-flop. The reset signal is used
to reset the D flip-flop to a known value. In our case we will reset the
flip-flop to zero. To implement a D flip-flop with reset, you will need
to instantiate a DFF_GL
and then add an AND gate and NOT gate as shown
in lecture.
We have provided you the interface a D flip-flop with reset in
DFFR_GL.v
, a test bench in DFFR_GL-test.v
, and test cases in
DFFR-test-cases.v
. Go ahead and implement this module. For the test
cases, we have provided you a template for directed test cases; all you
need to do is fill in the correct output values for each provided check.
You can test the D flip-flop with reset as follows.
To implement a D flip-flop with reset using RTL modeling, we will need to
use an if
statement to set the output to zero if the reset input is
one. We have provided you the interface a D flip-flop with reset in
DFFR_RTL.v
and a test bench in DFFR_RTL-test.v
. Go ahead and
implement this module. The test bench includes the same test cases you
developed for the gate-level implementation, so you should be able to go
ahead and test the D flip-flop as follows.
4.3 D Flip-Flop with Reset and Enable
Finally, we add an enable (en
) to our D flip-flop. The enable signal is
used to decided whether or not the flip-flop is "enabled": if the
flip-flop is enabled (i.e., en
is one) then the flip-flop will sample a
new value on the rising edge of the clock; but if the flip-flop is
disabled then the flip-flop will hold the old value and not sample a new
value on the rising edge of the clock. We can implement a D flip-flop with
reset and enable by adding a multiplexor, AND gate, and NOT gate to our D
flip-flop.
We have provided you the interface a D flip-flop with reset and enable in
DFFRE_GL.v
, a test bench in DFFRE_GL-test.v
, and test cases in
DFFRE-test-cases.v
. Go ahead and implement this module. For the test
cases, we have provided you a template for directed test cases; all you
need to do is fill in the correct output values for each provided check.
You can test the D flip-flop with reset and enable as follows.
To implement a D flip-flop with reset and enable using RTL modeling, we
will need to use a slightly more complicated if
statement. We have
provided you the interface a D flip-flop with reset and enable in
DFFRE_RTL.v
and a test bench in DFFRE_RTL-test.v
. Go ahead and
implement this module. The test bench includes the same test cases you
developed for the gate-level implementation, so you should be able to go
ahead and test the D flip-flop as follows.
5. Clean Build
As a final step, do a clean build to verify everything is working correctly.