Skip to content

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 an ecelinux 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 system
  • configure: Configure script for the build system
  • configure.ac: Used to generate the configure script
  • scripts: Scripts used by the build system
  • ece2300: ECE 2300 unit testing library and miscellaneous macros
  • lab2/lab2.mk: Tells build system about files in this subproject
  • lab2/Mux2_1b_GL.v: 8-bit RTL adder (copy from lab 2)
  • lab2/test: Directory with unit tests for each hardware module
  • lab3/DLatch_GL.v: 1-bit D latch at gate-level
  • lab3/DFF_GL.v: 1-bit D flip-flop at gate-level
  • lab3/DFF_RTL.v: 1-bit D flip-flop at RTL
  • lab3/DFFR_GL.v: 1-bit D flip-flop with reset at gate-level
  • lab3/DFFR_RTL.v: 1-bit D flip-flop with reset at RTL
  • lab3/DFFRE_GL.v: 1-bit D flip-flop with reset and enable at gate-level
  • lab3/DFFRE_RTL.v: 1-bit D flip-flop with reset and enable at RTL
  • lab3/test: Directory with unit tests for each hardware module

Go ahead and create a build directory and run configure to generate a Makefile.

% cd ${HOME}/ece2300/sec06
% mkdir -p build
% cd build
% ../configure

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:

% alias %=""

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.

% cd ${HOME}/ece2300/sec06/build
% make check-lab2

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.

% cd ${HOME}/ece2300/sec06/build
% make DLatch_GL-test
% ./DLatch_GL-test

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.

% cd ${HOME}/ece2300/sec06/build
% make DFF_GL-test
% ./DFF_GL-test

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.

% cd ${HOME}/ece2300/sec06/build
% make DFF_RTL-test
% ./DFF_RTL-test

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.

% cd ${HOME}/ece2300/sec06/build
% make DFFR_GL-test
% ./DFFR_GL-test

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.

% cd ${HOME}/ece2300/sec06/build
% make DFFR_RTL-test
% ./DFFR_RTL-test

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.

% cd ${HOME}/ece2300/sec06/build
% make DFFRE_GL-test
% ./DFFRE_GL-test

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.

% cd ${HOME}/ece2300/sec06/build
% make DFFRE_RTL-test
% ./DFFRE_RTL-test

5. Clean Build

As a final step, do a clean build to verify everything is working correctly.

% cd ${HOME}/ece2300/sec06
% trash build
% mkdir -p build
% cd build
% ../configure
% make check