Skip to content

Lab 1: Five-Bit Numeric Display
Part B: Optimized Code

Lab 1 is a warmup designed to give you experience designing, implementing, testing, and prototyping a simple Verilog hardware design. This lab will focus primarily leverage on concepts from Topic 2: Combinational Logic and Topic 3: Boolean Algebra.

You will be implementing a five-bit numeric display that takes as input a five-bit binary value and displays this value as a decimal number using two seven-segment displays. Your implementation will exclusively use combinational logic gates. This five-bit numeric display will be reused extensively across all of the remaining labs. The lab includes four parts:

  • Part A: Unoptimized Code and Testing

    • Must be completed individually
    • Due 9/11 @ 11:59pm via GitHub
    • Students should work on Part A before, during, and after your assigned lab section during the week of 9/8
  • Part B: Optimized Code and Testing

    • Must be completed individually
    • Due 9/18 @ 11:59pm via GitHub
    • Plan to start on Part B during the week of 9/8
    • Even though Part B is due on 9/18 you still need the code ready to go before your lab section the week of 9/15!
  • Part C: FPGA Analysis and Prototyping

    • Done with randomly assigned partner
    • Due week of 9/15 during assigned lab section
    • Even though completed with a partner, every student must turn in their own paper check-off sheet in their lab section!
  • Part D: Report

    • Done with same partner as in Part C
    • Due week of 9/15, three days after lab section @ 11:59pm via Canvas

This handout assumes that you have read and understand the course tutorials and that you have attended the discussion sections. You should have already cloned your individual remote repository, so use git pull to ensure you have any recent updates before working on your lab assignment.

% cd ${HOME}/ece2300/netid
% git pull
% tree

Students will must try to get Part B working before their lab section the week of 9/15. You might have a little time at the beginning of your lab section the week of 9/15 to fix a bug, but if your code is not almost finished you might not have enough time to finish Part C during your assigned lab section!

Your repo includes the following files in the lab1 subdirectory for Part B. These files are for modeling real hardware using the synthesizable subset of Verilog.

  • BinaryToSevenSegOpt_GL.v: Binary-to-seven-segment converter (optimized)
  • DisplayOpt_GL.v: Five-bit numeric display (optimized)

Your repo includes the following files in the lab1/test subdirectory. These files are for systematic and automatic testing of your hardware using the non-synthesizable subset of Verilog.

  • BinaryToSevenSegOpt_GL-test.v: Test bench for binary-to-seven-segment (optimized)
  • DisplayOpt_GL-test.v: Test bench for five-bit numeric display (optimized)

Part B is divided into two steps. Complete each step before moving on to the next step.

  • Step 1. Implement and test BinaryToSevenSegOpt_GL
  • Step 2. Implement and test DisplayOpt_GL

1. Unoptimized vs Optimized Implementations

Your design for the binary-to-seven-segment converter in Part A was not terribly optimized; we should be able to implement the same truth table with fewer combinational logic gates. In this part, you should use what you have learned in lecture on Boolean algebra (especially Karnaugh maps) to see if you can reduce the amount of logic required to implement the binary-to-seven-segment converter. You should use BinaryToSevenSegOpt_GL for your optimized implementation.

We strongly recommend taking a incremental design approach! Start by copying your unoptimized implementation into BinaryToSevenSegOpt_GL. Then pick a single output port to optimize. Work through the corresponding Karnaugh map and replace just the logic for that output port with the newly optimized version. Leave all of the logic for the other output ports unoptimized. Then use your tests to verify the converter is still working. If not, you know where to focus your debugging. If so, you can move on to the next output port.

Once you have implemented (and thoroughly tested!) your optimized binary-to-seven-segment converter, you can then instantiate this optimized unit within DisplayOpt_GL to create an optimized five-digit numeric display. Note that students do not need to optimize their binary-to-BCD converter.

2. Testing Strategy

You will use a similar strategy as in Part A to ensure all of your implementations are correct.

2.1. Linting

You can use the same linting strategy you used in Part A.

% cd ${HOME}/ece2300/netid
% verilator --Wall --lint-only lab1/BinaryToSevenSegOpt_GL.v
% verilator --Wall --lint-only lab1/DisplayOpt_GL.v

2.2. Systematic Unit Testing

There is no need to write any new test cases for Part B. You will just be reusing the test cases you wrote for Part A. To see how this works look in these test benches:

  • BinaryToSevenSegOpt_GL-test.v
  • DisplayOpt_GL-test.v

You can run your tests just like in Part A.

% cd ${HOME}/ece2300/netid
% iverilog -Wall -g2012 -o BinaryToSevenSegOpt_GL-test lab1/test/BinaryToSevenSegOpt_GL-test.v
% ./BinaryToSevenSegOpt_GL-test

% iverilog -Wall -g2012 -o DisplayOpt_GL-test lab1/test/DisplayOpt_GL-test.v
% ./DisplayOpt_GL-test

3. Automated Build System

Constantly entering commands on the command line to lint, compile, and run tests can quickly become tedious. In the third discussion section, students will learn about a build system we can use to automate this process. We will be pushing this build system into student's repos on Friday 9/12 so that students can use the build system to work on Part B and get ready for Part C.

The automated build system involves the following new files in your repo:

  • 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

It will also add a lab1.mk file to the lab1 subdirectory which is used to tell the build system about all of the files in Lab 1.

When using the automated build system we always work in a build directory. This simplifies keeping the generated files separate from the source files. You should be able to trash the build directory at any time for a "clean build". This is particularly useful if something seems to be going seriously wrong; a "clean build" is sometimes all you need to fix the issue.

3.1. Configuring the Automated Build System

Here is how to create the build directory and configure the automated build system.

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

3.2. Building Tests

Here is how to build and run the tests for the unoptimized binary-to-seven-segment converter.

% cd ${HOME}/ece2300/netid/build
% make BinaryToSevenSegUnopt_GL-test
% ./BinaryToSevenSegUnopt_GL-test
% ./BinaryToSevenSegUnopt_GL-test +test-case=1
% ./BinaryToSevenSegUnopt_GL-test +test-case=2
% ./BinaryToSevenSegUnopt_GL-test +test-case=2 +dump-vcd=waves.vcd

The build system takes care of using Verilator to lint your design, using our own custom linter to check rules specific to ECE 2300, and using Icarus Verilog to compile your design into a simulator. Here is how to build and run the remaining tests.

% cd ${HOME}/ece2300/netid/build

% make BinaryToBinCodedDec_GL-test
% make BinaryToSevenSegOpt_GL-test
% make DisplayUnopt_GL-test
% make DisplayOpt_GL-test

% ./BinaryToBinCodedDec_GL-test
% ./BinaryToSevenSegOpt_GL-test
% ./DisplayUnopt_GL-test
% ./DisplayOpt_GL-test

It can be convenient to build and run a test using a single command line like this so you can just use the up-arrow key to quickly rebuild and rerun a test.

% cd ${HOME}/ece2300/netid/build
% make BinaryToSevenSegUnopt_GL-test && ./BinaryToSevenSegUnopt_GL-test

You can build and run all of the test with the check target like this:

% cd ${HOME}/ece2300/netid/build
% make check

3.3. Building Interactive Simulators

You can build and run the interactive simulator like this:

% cd ${HOME}/ece2300/netid/build
% make display-sim && ./display-sim +switches=01111

4. Lab Code Submission

To submit your code you simply push your code to GitHub. You can push your code as many times as you like before the deadline. Be sure to verify your code is passing your tests both on ecelinux and on GitHub Actions. Your design code will be assessed both in terms of code quality, verification quality, and functionality.

4.1. Part A Revisions

If your design is failing some tests from Part A, we encourage you go ahead and fix whatever is wrong. If your design is passing your tests but failing our tests consider using the staff tests for inspiration on how to improve your own testing. Fixing whatever is wrong now can improve your code functionality score and also ensures that you can use your work from this lab in future labs.

To revise your Part A submission, simply push improvements on the regular main branch. After improving your code, you must enter a comment in the Part A grading pull request that explains what was wrong and how you fixed it. The only way we can increase your score after a revision is if you clearly explain what was wrong and how you fixed it. If you fix your code on the main branch and do not explain it in the pull request then you will not receive a revised score!

All revisions need to be finalized by the due date for Part B. No revisions are allowed for Part B code.

4.2. Code and Verification Quality

Code and verification quality will be assessed in the same way as for Part A.

4.3. Functionality

Your functionality score will be determined by running your code against a series of tests developed by the instructors to test its correctness. Note that we will be using the automated build system to test your final code submission as shown below.

% mkdir -p ${HOME}/ece2300
% cd ${HOME}/ece2300
% git clone git@github.com:cornell-ece2300/netid
% cd netid

% mkdir -p build
% cd build
% ../configure
% make check-lab1