====== Sp20 - Seven Segment Decoder ====== In this lab you will learn what a seven segment display is and how it works. You will create a digital circuit that drives a seven segment display with hexadecimal characters. ===== Learning Outcomes ===== * Learn how a seven segment display works. * Create a seven segment decoder digital circuit. * Learn how to use SystemVerilog dataflow operators and ''always_comb'' blocks. * Learn how to validate your circuit with a testbench. ===== Preliminary ===== The NEXYS4 board contains an 8-digit, seven segment display as shown below. This display can be used to display any information you desire, such as a counter value, register values, a timer, etc. You will create a circuit to drive one digit of this display! Later in the semester we will provide you with a module that will use what you have built in this lab to drive each of the eight digits at once. {{ :labs:eight_digit_seven_segment_display.png?300&nolink |}} Before designing a seven-segment controller circuit, it is necessary to understand how the seven-segment display operates. As the name implies, a seven-segment display has seven discrete //segments// that can each be individually turned on to make a variety of different characters. Each of the seven segments are labeled with a letter as shown in the image below: {{ :labs:lab_5:seven-segments.png?nolink |}} For example, the character "0" can be displayed on the seven-segment display by turning on segments **a**, **b**, **c**, **d**, **e**, **f**, and turning off segment **g**. Each segment of the seven-segment display is driven by an individual **LED** (light-emitting diode). The schematic diagram below shows these LEDs used by a seven-segment display. In addition to the seven segments for displaying a character, many displays include an eighth LED for the **digit point** (the round circle to the bottom right of the seven-segments). This is commonly abbreviated to **DP** as seen below. In this configuration, all eight LEDs share a common **anode** which enables the display. Each segment has its own **cathode** signal labeled CX where **X** represents the segment letter. For example, signal **CA** corresponds to the cathode signal for segment **a**. To turn on an LED, there must be a sufficient voltage drop from anode to cathode. That is, the anode needs to have a high voltage ('1') and the cathode has to have a low voltage ('0'). To display the character **0**, the anode signal will have a high voltage, the cathode signals CA, CB, CC, CD, CE, and CF will have a low voltage, and the cathode signal CG will have a high voltage. {{ :tutorials:seven_segment_cathode.png?500&nolink |}} Although any arbitrary combination of segments can be turned on, digital circuits are often created to display the 16 different characters representing any 4-bit value in hexadecimal. These characters are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F. Each of these is shown in the image below. {{ :tutorials:seven_segment_font.png?nolink |}} Before you can create a circuit to display these hexadecimal characters, you need to determine the value each cathode signal needs for each character. Fill out the table below so that the segment outputs on each row will display the number given by that row's hexadecimal character. Also included in this table is the binary representation of each hexadecimal character in the **D** columns. For an example, the output for an input of **0** is already in the table. It was said already above but you probably missed it - you turn a segment ON by driving its cathode LOW. Carefully look at the top entry (for a '0') to make sure you understand this. ^ Hex ^ Input ^^^^ Outputs ^^^^^^^ ^ Character ^ Binary ^^^^ Segments ^^^^^^^ ^ ::: ^ D3 ^ D2 ^ D1 ^ D0 ^ A ^ B ^ C ^ D ^ E ^ F ^ G ^ ^ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | ^ 1 | 0 | 0 | 0 | 1 | | | | | | | | ^ 2 | 0 | 0 | 1 | 0 | | | | | | | | ^ 3 | 0 | 0 | 1 | 1 | | | | | | | | ^ 4 | 0 | 1 | 0 | 0 | | | | | | | | ^ 5 | 0 | 1 | 0 | 1 | | | | | | | | ^ 6 | 0 | 1 | 1 | 0 | | | | | | | | ^ 7 | 0 | 1 | 1 | 1 | | | | | | | | ^ 8 | 1 | 0 | 0 | 0 | | | | | | | | ^ 9 | 1 | 0 | 0 | 1 | | | | | | | | ^ A | 1 | 0 | 1 | 0 | | | | | | | | ^ b | 1 | 0 | 1 | 1 | | | | | | | | ^ C | 1 | 1 | 0 | 0 | | | | | | | | ^ d | 1 | 1 | 0 | 1 | | | | | | | | ^ E | 1 | 1 | 1 | 0 | | | | | | | | ^ F | 1 | 1 | 1 | 1 | | | | | | | | After filling out the table, provide a logic equation for segment A (CA). If you're confused about how to make an equation for a segment, remember that a whole column represents an individual output. Simply pick the column for the segment as labeled in the table. On Learning Suite, you will only fill in a few sections of this table. Make sure that your entire table is correct - it will make the rest of this lab much easier. === The Board's 7 Segments === The seven-segment display on the NEXYS 4 board has //eight// unique digits as shown below. {{ :labs:7seglab_0.png?600 |}} /*{{ :labs:seven_segment_schematic.png?350&nolink |}} */ Each digit of the eight digit display has its own anode input (A0-A7). NOTE, however, that there is a built-in inverter on each anode signal. Thus, to turn on any of the segments of a digit, its corresponding anode and cathode signals must both be //driven LOW//. The schematic of this eight-digit, seven-segment display is shown below. This eight-digit, seven-segment display configuration is known as a **common cathode** arrangement because the cathode signals are shared among all eight digits. If more than one anode signal is asserted low, the corresponding digits will have the same segments turn on because they are connected to the same cathode signals. While this significantly reduces the pin count, it makes it difficult to display different values simultaneously. (Different values can be displayed by quickly switching between the various anode and cathode signals --- the LED's will flash so quickly your eye will see them as all being "on". This is called "time-multiplexing" the digits. You will be given a time-multiplexing seven segment display controller to use in future laboratory assignments.) For example, to turn on only the right two digits of the eight digit display, AN1 and AN0 must have a logic value of **0** and the other anode signals must have a logic value of **1**. In the following example, two of the digits are turned on by setting their corresponding anode to zero. All of the other digits are off since their anode signals are set to one. In addition, the digit **3** is displayed based on which cathode signals have a logic **0**. The digit point is also on since the cathode signal, DP, associated with the digit point is set to **0**. ^ A7 ^ A6 ^ A5 ^ A4 ^ A3 ^ A2 ^ A1 ^ A0 ^ | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | ^ CG ^ CF ^ CE ^ CD ^ CC ^ CB ^ CA ^ DP ^ | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | {{ :tutorials:eight_digit_display_example.png?640&nolink |}} What would happen if all eight anode control signals were set to a logic value of **0** simultaneously in the example above? Determine what will be shown on the display with the following signal values. Fill in the segments in the diagram below that will be turned on by this set of input signals. (You might use Paint or another program. It doesn't have to look great, it just has to be clear which character it is and which digits are lit.) ^ A7 ^ A6 ^ A5 ^ A4 ^ A3 ^ A2 ^ A1 ^ A0 ^ | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | ^ CG ^ CF ^ CE ^ CD ^ CC ^ CB ^ CA ^ DP ^ | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | {{ :labs:8-segment-display.png?640&nolink |}} ===== Exercises ===== ==== Exercise #1 - Seven Segment SystemVerilog ==== In this exercise you will create a seven segment decoder in a SystemVerilog module. Begin by [[tutorials:vivado_project_setup|creating a new Vivado project]] like you did in the previous lab (you will create a new project for each laboratory assignment). Remember to always follow the instructions in red to properly configure the error messages. After creating this project, create a new SystemVerilog file with the following module name and ports: ^ **Module Name**: seven_segment ^^^^ ^ Port Name ^ Direction ^ Width ^ Function ^ | data | Input | 4 | Data input to display on the seven segment display | | segment | Output | 7 | Cathode signals for seven segment display (excluding digit point). segment[0] corresponds to CA and segment[6] corresponds to CG | Review the page on [[resources:combinational_logic_styles|Combinational Logic Styles]]. Create the logic necessary for your cathode segments (CA to CG) (For this circuit, you will not create logic for the digit point (segment[7])). You are required to use a mix of combinational logic styles. For your seven segments, you must have at least one segment that uses each of the following styles: * Structural SV, in non-minimized, sum-of-products. * Structural SV, optimized using the theorems in Table 4.1 of the textbook. * Dataflow SV, using an assign statement and the ?: (sometimes called the ternary) operator. * Dataflow SV, using an assign statement and dataflow operators of your choice (comparison, and, or, etc.) * Behavioral SV, using an ''always_comb'' block, and if/else statements. * Behavioral SV, using an ''always_comb'' block, and case statements. Once you have completed the logic for your seven segment decoder, proceed with the simulation of your module using a TCL script. Your TCL file should simulate all 16 possible digits to see if the output of your module matches that seven segment decoder table from the preliminary section. Include your TCL simulation file in your report. **Exercise 1 Pass-off:** Show a TA your SV code, tcl commands and simulation. \\ \\ ==== Exercise #2 - Verification with a Testbench ==== A testbench circuit has been created for you in this lab to test your seven segment decoder. Test your seven segment decoder circuit using the testbench by the following steps. - Download the {{:labs:tb_sevensegment.v|}} testbench file. - If needed, review the [[tutorials:testbench_tutorial]] tutorial. - Add the testbench to your project (as a simulation source file) - Start simulating the testbench and carefully view the messages. If you have errors, carefully debug these errors and simulate again until you have no errors. When you pass the testbench without any errors, you are ready to proceed to the next exercise. Copy and paste the testbench console output into your report (the console should report no errors). **Exercise 2 Pass-off:** Nothing to pass off, just be sure it is passing the testbench.\\ \\ ==== Exercise #3 - Top-Level Design ==== Begin this exercise by creating a second SystemVerilog file with the following module name and ports: ^ **Module Name**: seven_segment_top ^^^^ ^ Port Name ^ Direction ^ Width ^ Function ^ | sw | Input | 4 | Input from four switches to drive seven segment decoder. | | btnc | Input | 1 | Center button | /* | btnl | Input | 1 | Left button | | btnr | Input | 1 | Right button | */ | segment | Output | 8 | Cathode signals for seven segment display (including digit point). segment[0] corresponds to CA and segment[6] corresponds to CG, and segment[7] corresponds to DP. | | anode | Output | 8 | Anode signals for each of the eight digits. | The figure below demonstrates the structure of this top-level design. You will also create some additional logic in this top-level design. {{ :labs:seven_segment_top.png?nolink&500 |}} === Instance Seven Segment Decoder Module === Begin your top-level by instancing the seven segment display module you created in the previous exercise. Connect the four-bit switch input ports from your top-level design to the data inputs of your seven segment display. Connect the 7 segment bits (segment[6:0]) from your seven segment display outputs to bits [6:0] of the top-level segment output. /* You do not need to put any LUT4 modules or other logic that was in your seven segment decoder in this top-level module. */ === Digit Point === Your seven segment decoder module drives seven of the eight cathode segment signals (segment[6:0]). The eighth segment signal (segment[7]) is used for the "digit point". You need to create logic to //turn on// the digit point (DP or segment[7]). For this top-level design, we want to turn on the digit point when **btnc** is pressed. Create a logic circuit using structural SystemVerilog in your top-level module for the digit point based on the value of **btnc**. Remember that the cathode segment signals are turned on when the logic value of **0** is given. === Anode Signals === The last component of your top-level design is the logic to drive the anode signals. For this top-level design, you will need to create logic that turns on the right most digit (associated with anode[0]) and turn off all of the other seven digits (anode[7:1]). To turn on the right most digit, we simply need to assign the 'anode' output with a constant value. Add a dataflow assignment statement in your top-level SystemVerilog file to assign the anode signals such that only the right most digit is turned on. The following SystemVerilog statement can be added to set the anode signals (you will need to replace the "X" values with actual '1's or '0'): assign anode = 8'bXXXXXXXX; /* The last step of this top level verilog design is to create the logic for the eight anode signals. The logic for the anode signals should be designed to meet the following specifications: * When no buttons are pressed, turn on //only// the rightmost digit, digit 0 (corresponding to anode[0]). * When the left button is pressed, **btnl**, turn on all 8 digits (no matter what the value of btnr is). All 8 digits will display the same value as dictated by the switches and btnc for **DP**. * When the right button is pressed, **btnr**, turn off all 8 digits (including digit 0). Note that this condition has lower priority than the previous condition. If both the right and left buttons are pressed at the same time, all digits should be turned on as described in the previous condition. Note that your center button //does not// affect your anodes at all. It only affects segment[7]. Do not include the center button in your logic for the anodes. In your top level design, the logic for anode[0] signal (driving digit 0) will be different from the logic for the anode[7:1] signals (driving digits 1-7). Since the logic for the anode signals anode[7:1] is all the same, it is best to use one signal to drive all of them. Assuming you have a logic signal named **anode_1_7** you can drive anode outputs 1-7 with this signal using the **buf** primitive as shown in the following example. buf(anode[1],anode_1_7); buf(anode[2],anode_1_7); buf(anode[3],anode_1_7); buf(anode[4],anode_1_7); buf(anode[5],anode_1_7); buf(anode[6],anode_1_7); buf(anode[7],anode_1_7); */ /* Complete the [[tutorials:hierarchy_vivado_tutorial]] tutorial to learn about adding hierarchical modules in the Vivado design suite. Make sure your hierarchy is correct before proceeding to the next exercise. */ After completing your top-level design, simulate your top-level design to make sure your digit point (DP) logic and your anode logic is correct. Also, simulate all possible data inputs to verify your top-level circuit is working properly. Attach your top-level module to LearningSuite. Attach a screenshot of your working simulation to LearningSuite. **Exercise 3 Pass-off:** Nothing to pass off - just answer the questions above.\\ \\ ==== Exercise #4 - Implement and Download ==== /* do we want to have them look at the elaborated design pre-synthesis? */ /* [[tutorials:viewing_design_elaboration]] */ Begin this process by [[tutorials:making_an_xdc_file|creating]] and [[tutorials:adding_an_xdc_file|adding]] an XDC constraints file. Your XDC file should have entries for the four switches, the btnc button, eight cathode output signals and eight anode output signals. The easiest way to create this file is to start with the {{:resources:nexys4_220.xdc|master XDC}} file and modify it with the signals you will use by uncommenting the pins you use and insert top-level signal names. Once you have the XDC file added to your project, [[tutorials:synthesis|synthesize]] your project. Provide a summary of your synthesis warnings. [[tutorials:implementation|Implement]] your module. Indicate the number of LUTs and I/O pins your design uses. You can find this in the the **Utilization** box within the "Project Summary" window (use the "Post-Implementation" tab). [[tutorials:bitgen|Generate a bitfile]] for your design, download your circuit, and verify that it works as expected. ====Final Pass-Off:==== Attach a video (narrated) showing your circuit working correctly on the board. Show that it displays what it ought to as you manipulate the switches and btnc. Explain why we aren't able to display two different numbers on two different digits at the same time. How many hours did you work on the lab? Provide any suggestions for improving this lab in the future. Submit your SystemVerilog modules using the code submission on Learning Suite. (Make sure your SystemVerilog conforms to the lab SystemVerilog coding standards). ===== Personal Exploration ===== There is no personal exploration this week. /* Here are some ideas for personal exploration in this laboratory: * Create a different seven-segment decoder that implements a different font (upside down, letters in the alphabet, your own unique character set, etc.) * Change the behavior of the top-level design. Here are some ideas: * Turn on all of the segments or some sub-set of the segments * Add additional buttons and use the buttons to selectively turn on or off the segments * Use additional switches and multiplex the switches using a button * Experiment with the simulator and learn new features, tools, or TCL commands Describe your personal exploration activities */ /* Listing of errors helped with: - One student made his .tcl simulation file as a constraints file (had a .tcl extension but was in the Design Sources pane). Synthesis didn't like that... */ ---- [[labs:ta:seven_segment_decoder|TA Notes and Feedback]]