Skip to content

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

Lab 1 is a warmup designed to give you experience designing, implementing, testing, and prototyping a simple Verilog hardware design. This lab will primarily leverage 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

    • 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

    • 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 Prototype

    • 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
    • Post-lab survey on Canvas is due at the same time as the report

This handout assumes that you have read and understand the course tutorials and that you have attended the discussion sections. This handout assumed you have successfully completed Part A. 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

where netid should be replaced with your NetID. Students must try to get Part B working before their lab section the week of 9/15. At a minimum, have at least three of the outputs fully optimized using your Karnaugh maps and the remaning four outputs can still be unoptimized. You will not have time at the beginning of your lab section to fix a bug. So it is better to have a partially optimized working binary-to-seven-segment converter than to not have anything working at all. You can then finish your optimizations before the Part B deadline on 9/18.

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 for Part B. 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 might not be terribly optimized; we want to explore implementing the same truth table with fewer combinational logic gates. In this part, you should use what you have learned in lecture on 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 to derive a minimal Boolean logic equation. Then transform this Boolean logic equation into a gate-level netlist which you can then implement in Verilog using gate-level modeling. 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.

It is ok if your "optimized" design actually ends up taking more logic gates than your "unoptimized" design. You should hopefully be able to figure out why this might happen. Focus on gaining experience using Karnaugh maps to simplifying Boolean logic equations as opposed to finding the absolutely most optimized implementation.

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. Students are responsible for going to the GitHub website for your repository, browsing the source code, and confirming the code on GitHub is the code they want to submit is on GitHub 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, then you should fix whatever is wrong. If your design is passing your tests but failing our tests you should browse the staff tests to see 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 submission, simply push any updates to your tests and/or your hardware designs to GiHub just like normal. You do not need to switch branches; just push your changes to the main branch like normal. Make sure your updates are passing all of your (potentially updated) tests on the main branch on GitHub Actions. After pushing your updated code, you must enter a comment on the grading pull request page that explains what was wrong and how you fixed it. The instructors will then take care of merging your changes into the grading pull request. You should not rely on the instructor merging your revision into the pull request to see if your code passes the staff tests; you should copy whatever staff tests are important into your own test benches. 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 grading pull request then you will not receive a revised score!

All Part A 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-partA
% make check-lab1-partB